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/async_pixel_transfer_delegate.h"
33 #include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
34 #include "gpu/command_buffer/service/buffer_manager.h"
35 #include "gpu/command_buffer/service/context_group.h"
36 #include "gpu/command_buffer/service/context_state.h"
37 #include "gpu/command_buffer/service/error_state.h"
38 #include "gpu/command_buffer/service/feature_info.h"
39 #include "gpu/command_buffer/service/framebuffer_manager.h"
40 #include "gpu/command_buffer/service/gl_utils.h"
41 #include "gpu/command_buffer/service/gles2_cmd_clear_framebuffer.h"
42 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
43 #include "gpu/command_buffer/service/gles2_cmd_validation.h"
44 #include "gpu/command_buffer/service/gpu_state_tracer.h"
45 #include "gpu/command_buffer/service/gpu_switches.h"
46 #include "gpu/command_buffer/service/gpu_tracer.h"
47 #include "gpu/command_buffer/service/image_manager.h"
48 #include "gpu/command_buffer/service/logger.h"
49 #include "gpu/command_buffer/service/mailbox_manager.h"
50 #include "gpu/command_buffer/service/memory_tracking.h"
51 #include "gpu/command_buffer/service/path_manager.h"
52 #include "gpu/command_buffer/service/program_manager.h"
53 #include "gpu/command_buffer/service/query_manager.h"
54 #include "gpu/command_buffer/service/renderbuffer_manager.h"
55 #include "gpu/command_buffer/service/shader_manager.h"
56 #include "gpu/command_buffer/service/shader_translator.h"
57 #include "gpu/command_buffer/service/texture_manager.h"
58 #include "gpu/command_buffer/service/valuebuffer_manager.h"
59 #include "gpu/command_buffer/service/vertex_array_manager.h"
60 #include "gpu/command_buffer/service/vertex_attrib_manager.h"
61 #include "third_party/smhasher/src/City.h"
62 #include "ui/gfx/geometry/point.h"
63 #include "ui/gfx/geometry/rect.h"
64 #include "ui/gfx/geometry/size.h"
65 #include "ui/gfx/overlay_transform.h"
66 #include "ui/gl/gl_bindings.h"
67 #include "ui/gl/gl_context.h"
68 #include "ui/gl/gl_fence.h"
69 #include "ui/gl/gl_image.h"
70 #include "ui/gl/gl_implementation.h"
71 #include "ui/gl/gl_surface.h"
72 #include "ui/gl/gl_version_info.h"
73 #include "ui/gl/gpu_timing.h"
75 #if defined(OS_MACOSX)
76 #include <IOSurface/IOSurface.h>
77 // Note that this must be included after gl_bindings.h to avoid conflicts.
78 #include <OpenGL/CGLIOSurface.h>
86 const char kOESDerivativeExtension
[] = "GL_OES_standard_derivatives";
87 const char kEXTFragDepthExtension
[] = "GL_EXT_frag_depth";
88 const char kEXTDrawBuffersExtension
[] = "GL_EXT_draw_buffers";
89 const char kEXTShaderTextureLodExtension
[] = "GL_EXT_shader_texture_lod";
91 const GLfloat kIdentityMatrix
[16] = {1.0f
, 0.0f
, 0.0f
, 0.0f
,
92 0.0f
, 1.0f
, 0.0f
, 0.0f
,
93 0.0f
, 0.0f
, 1.0f
, 0.0f
,
94 0.0f
, 0.0f
, 0.0f
, 1.0f
};
96 bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin
,
99 return (rangeMin
>= 62) && (rangeMax
>= 62) && (precision
>= 16);
102 void GetShaderPrecisionFormatImpl(GLenum shader_type
,
103 GLenum precision_type
,
104 GLint
* range
, GLint
* precision
) {
105 switch (precision_type
) {
109 // These values are for a 32-bit twos-complement integer format.
115 case GL_MEDIUM_FLOAT
:
117 // These values are for an IEEE single-precision floating-point format.
127 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
&&
128 gfx::g_driver_gl
.fn
.glGetShaderPrecisionFormatFn
) {
129 // This function is sometimes defined even though it's really just
130 // a stub, so we need to set range and precision as if it weren't
131 // defined before calling it.
132 // On Mac OS with some GPUs, calling this generates a
133 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
135 glGetShaderPrecisionFormat(shader_type
, precision_type
,
138 // TODO(brianderson): Make the following official workarounds.
140 // Some drivers have bugs where they report the ranges as a negative number.
141 // Taking the absolute value here shouldn't hurt because negative numbers
142 // aren't expected anyway.
143 range
[0] = abs(range
[0]);
144 range
[1] = abs(range
[1]);
146 // If the driver reports a precision for highp float that isn't actually
147 // highp, don't pretend like it's supported because shader compilation will
149 if (precision_type
== GL_HIGH_FLOAT
&&
150 !PrecisionMeetsSpecForHighpFloat(range
[0], range
[1], *precision
)) {
158 gfx::OverlayTransform
GetGFXOverlayTransform(GLenum plane_transform
) {
159 switch (plane_transform
) {
160 case GL_OVERLAY_TRANSFORM_NONE_CHROMIUM
:
161 return gfx::OVERLAY_TRANSFORM_NONE
;
162 case GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM
:
163 return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL
;
164 case GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM
:
165 return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL
;
166 case GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM
:
167 return gfx::OVERLAY_TRANSFORM_ROTATE_90
;
168 case GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM
:
169 return gfx::OVERLAY_TRANSFORM_ROTATE_180
;
170 case GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM
:
171 return gfx::OVERLAY_TRANSFORM_ROTATE_270
;
173 return gfx::OVERLAY_TRANSFORM_INVALID
;
177 template <typename MANAGER_TYPE
, typename OBJECT_TYPE
>
178 GLuint
GetClientId(const MANAGER_TYPE
* manager
, const OBJECT_TYPE
* object
) {
180 GLuint client_id
= 0;
182 manager
->GetClientId(object
->service_id(), &client_id
);
188 explicit Vec4f(const Vec4
& data
) {
195 // Returns the union of |rect1| and |rect2| if one of the rectangles is empty,
196 // contains the other rectangle or shares an edge with the other rectangle.
197 bool CombineAdjacentRects(const gfx::Rect
& rect1
,
198 const gfx::Rect
& rect2
,
200 // Return |rect2| if |rect1| is empty or |rect2| contains |rect1|.
201 if (rect1
.IsEmpty() || rect2
.Contains(rect1
)) {
206 // Return |rect1| if |rect2| is empty or |rect1| contains |rect2|.
207 if (rect2
.IsEmpty() || rect1
.Contains(rect2
)) {
212 // Return the union of |rect1| and |rect2| if they share an edge.
213 if (rect1
.SharesEdgeWith(rect2
)) {
214 *result
= gfx::UnionRects(rect1
, rect2
);
218 // Return false if it's not possible to combine |rect1| and |rect2|.
224 class GLES2DecoderImpl
;
226 // Local versions of the SET_GL_ERROR macros
227 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
228 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
229 #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
230 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
231 function_name, value, label)
232 #define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
233 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
234 function_name, pname)
235 #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
236 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
238 #define LOCAL_PEEK_GL_ERROR(function_name) \
239 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
240 #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
241 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
242 #define LOCAL_PERFORMANCE_WARNING(msg) \
243 PerformanceWarning(__FILE__, __LINE__, msg)
244 #define LOCAL_RENDER_WARNING(msg) \
245 RenderWarning(__FILE__, __LINE__, msg)
247 // Check that certain assumptions the code makes are true. There are places in
248 // the code where shared memory is passed direclty to GL. Example, glUniformiv,
249 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
250 // a few others) are 32bits. If they are not 32bits the code will have to change
251 // to call those GL functions with service side memory and then copy the results
252 // to shared memory, converting the sizes.
253 static_assert(sizeof(GLint
) == sizeof(uint32
), // NOLINT
254 "GLint should be the same size as uint32");
255 static_assert(sizeof(GLsizei
) == sizeof(uint32
), // NOLINT
256 "GLsizei should be the same size as uint32");
257 static_assert(sizeof(GLfloat
) == sizeof(float), // NOLINT
258 "GLfloat should be the same size as float");
260 // TODO(kbr): the use of this anonymous namespace core dumps the
261 // linker on Mac OS X 10.6 when the symbol ordering file is used
264 // Returns the address of the first byte after a struct.
265 template <typename T
>
266 const void* AddressAfterStruct(const T
& pod
) {
267 return reinterpret_cast<const uint8
*>(&pod
) + sizeof(pod
);
270 // Returns the address of the frst byte after the struct or NULL if size >
271 // immediate_data_size.
272 template <typename RETURN_TYPE
, typename COMMAND_TYPE
>
273 RETURN_TYPE
GetImmediateDataAs(const COMMAND_TYPE
& pod
,
275 uint32 immediate_data_size
) {
276 return (size
<= immediate_data_size
) ?
277 static_cast<RETURN_TYPE
>(const_cast<void*>(AddressAfterStruct(pod
))) :
281 // Computes the data size for certain gl commands like glUniform.
282 bool ComputeDataSize(
285 unsigned int elements_per_unit
,
288 if (!SafeMultiplyUint32(count
, size
, &value
)) {
291 if (!SafeMultiplyUint32(value
, elements_per_unit
, &value
)) {
298 // Return true if a character belongs to the ASCII subset as defined in
299 // GLSL ES 1.0 spec section 3.1.
300 static bool CharacterIsValidForGLES(unsigned char c
) {
301 // Printing characters are valid except " $ ` @ \ ' DEL.
302 if (c
>= 32 && c
<= 126 &&
311 // Horizontal tab, line feed, vertical tab, form feed, carriage return
313 if (c
>= 9 && c
<= 13) {
320 static bool StringIsValidForGLES(const char* str
) {
321 for (; *str
; ++str
) {
322 if (!CharacterIsValidForGLES(*str
)) {
329 // This class prevents any GL errors that occur when it is in scope from
330 // being reported to the client.
331 class ScopedGLErrorSuppressor
{
333 explicit ScopedGLErrorSuppressor(
334 const char* function_name
, ErrorState
* error_state
);
335 ~ScopedGLErrorSuppressor();
337 const char* function_name_
;
338 ErrorState
* error_state_
;
339 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor
);
342 // Temporarily changes a decoder's bound texture and restore it when this
343 // object goes out of scope. Also temporarily switches to using active texture
344 // unit zero in case the client has changed that to something invalid.
345 class ScopedTextureBinder
{
347 explicit ScopedTextureBinder(ContextState
* state
, GLuint id
, GLenum target
);
348 ~ScopedTextureBinder();
351 ContextState
* state_
;
353 DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder
);
356 // Temporarily changes a decoder's bound render buffer and restore it when this
357 // object goes out of scope.
358 class ScopedRenderBufferBinder
{
360 explicit ScopedRenderBufferBinder(ContextState
* state
, GLuint id
);
361 ~ScopedRenderBufferBinder();
364 ContextState
* state_
;
365 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder
);
368 // Temporarily changes a decoder's bound frame buffer and restore it when this
369 // object goes out of scope.
370 class ScopedFrameBufferBinder
{
372 explicit ScopedFrameBufferBinder(GLES2DecoderImpl
* decoder
, GLuint id
);
373 ~ScopedFrameBufferBinder();
376 GLES2DecoderImpl
* decoder_
;
377 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder
);
380 // Temporarily changes a decoder's bound frame buffer to a resolved version of
381 // the multisampled offscreen render buffer if that buffer is multisampled, and,
382 // if it is bound or enforce_internal_framebuffer is true. If internal is
383 // true, the resolved framebuffer is not visible to the parent.
384 class ScopedResolvedFrameBufferBinder
{
386 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl
* decoder
,
387 bool enforce_internal_framebuffer
,
389 ~ScopedResolvedFrameBufferBinder();
392 GLES2DecoderImpl
* decoder_
;
393 bool resolve_and_bind_
;
394 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder
);
397 class ScopedModifyPixels
{
399 explicit ScopedModifyPixels(TextureRef
* ref
);
400 ~ScopedModifyPixels();
406 ScopedModifyPixels::ScopedModifyPixels(TextureRef
* ref
) : ref_(ref
) {
408 ref_
->texture()->OnWillModifyPixels();
411 ScopedModifyPixels::~ScopedModifyPixels() {
413 ref_
->texture()->OnDidModifyPixels();
416 class ScopedRenderTo
{
418 explicit ScopedRenderTo(Framebuffer
* framebuffer
);
422 const Framebuffer
* framebuffer_
;
425 ScopedRenderTo::ScopedRenderTo(Framebuffer
* framebuffer
)
426 : framebuffer_(framebuffer
) {
428 framebuffer_
->OnWillRenderTo();
431 ScopedRenderTo::~ScopedRenderTo() {
433 framebuffer_
->OnDidRenderTo();
436 // Encapsulates an OpenGL texture.
439 explicit BackTexture(MemoryTracker
* memory_tracker
, ContextState
* state
);
442 // Create a new render texture.
445 // Set the initial size and format of a render texture or resize it.
446 bool AllocateStorage(const gfx::Size
& size
, GLenum format
, bool zero
);
448 // Copy the contents of the currently bound frame buffer.
449 void Copy(const gfx::Size
& size
, GLenum format
);
451 // Destroy the render texture. This must be explicitly called before
452 // destroying this object.
455 // Invalidate the texture. This can be used when a context is lost and it is
456 // not possible to make it current in order to free the resource.
463 gfx::Size
size() const {
468 MemoryTypeTracker memory_tracker_
;
469 ContextState
* state_
;
470 size_t bytes_allocated_
;
473 DISALLOW_COPY_AND_ASSIGN(BackTexture
);
476 // Encapsulates an OpenGL render buffer of any format.
477 class BackRenderbuffer
{
479 explicit BackRenderbuffer(
480 RenderbufferManager
* renderbuffer_manager
,
481 MemoryTracker
* memory_tracker
,
482 ContextState
* state
);
485 // Create a new render buffer.
488 // Set the initial size and format of a render buffer or resize it.
489 bool AllocateStorage(const FeatureInfo
* feature_info
,
490 const gfx::Size
& size
,
494 // Destroy the render buffer. This must be explicitly called before destroying
498 // Invalidate the render buffer. This can be used when a context is lost and
499 // it is not possible to make it current in order to free the resource.
507 RenderbufferManager
* renderbuffer_manager_
;
508 MemoryTypeTracker memory_tracker_
;
509 ContextState
* state_
;
510 size_t bytes_allocated_
;
512 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer
);
515 // Encapsulates an OpenGL frame buffer.
516 class BackFramebuffer
{
518 explicit BackFramebuffer(GLES2DecoderImpl
* decoder
);
521 // Create a new frame buffer.
524 // Attach a color render buffer to a frame buffer.
525 void AttachRenderTexture(BackTexture
* texture
);
527 // Attach a render buffer to a frame buffer. Note that this unbinds any
528 // currently bound frame buffer.
529 void AttachRenderBuffer(GLenum target
, BackRenderbuffer
* render_buffer
);
531 // Destroy the frame buffer. This must be explicitly called before destroying
535 // Invalidate the frame buffer. This can be used when a context is lost and it
536 // is not possible to make it current in order to free the resource.
539 // See glCheckFramebufferStatusEXT.
540 GLenum
CheckStatus();
547 GLES2DecoderImpl
* decoder_
;
549 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer
);
552 struct FenceCallback
{
554 : fence(gfx::GLFence::Create()) {
557 std::vector
<base::Closure
> callbacks
;
558 scoped_ptr
<gfx::GLFence
> fence
;
561 class AsyncUploadTokenCompletionObserver
562 : public AsyncPixelTransferCompletionObserver
{
564 explicit AsyncUploadTokenCompletionObserver(uint32 async_upload_token
)
565 : async_upload_token_(async_upload_token
) {
568 void DidComplete(const AsyncMemoryParams
& mem_params
) override
{
569 DCHECK(mem_params
.buffer().get());
570 void* data
= mem_params
.GetDataAddress();
571 AsyncUploadSync
* sync
= static_cast<AsyncUploadSync
*>(data
);
572 sync
->SetAsyncUploadToken(async_upload_token_
);
576 ~AsyncUploadTokenCompletionObserver() override
{}
578 uint32 async_upload_token_
;
580 DISALLOW_COPY_AND_ASSIGN(AsyncUploadTokenCompletionObserver
);
583 // } // anonymous namespace.
586 const unsigned int GLES2Decoder::kDefaultStencilMask
=
587 static_cast<unsigned int>(-1);
589 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id
,
590 uint32
* service_texture_id
) {
594 GLES2Decoder::GLES2Decoder()
595 : initialized_(false),
597 log_commands_(false),
598 unsafe_es3_apis_enabled_(false) {
601 GLES2Decoder::~GLES2Decoder() {
604 void GLES2Decoder::BeginDecoding() {}
606 void GLES2Decoder::EndDecoding() {}
608 // This class implements GLES2Decoder so we don't have to expose all the GLES2
609 // cmd stuff to outside this class.
610 class GLES2DecoderImpl
: public GLES2Decoder
,
611 public FramebufferManager::TextureDetachObserver
,
612 public ErrorStateClient
{
614 explicit GLES2DecoderImpl(ContextGroup
* group
);
615 ~GLES2DecoderImpl() override
;
617 // Overridden from AsyncAPIInterface.
618 Error
DoCommand(unsigned int command
,
619 unsigned int arg_count
,
620 const void* args
) override
;
622 error::Error
DoCommands(unsigned int num_commands
,
625 int* entries_processed
) override
;
627 template <bool DebugImpl
>
628 error::Error
DoCommandsImpl(unsigned int num_commands
,
631 int* entries_processed
);
633 // Overridden from AsyncAPIInterface.
634 const char* GetCommandName(unsigned int command_id
) const override
;
636 // Overridden from GLES2Decoder.
637 bool Initialize(const scoped_refptr
<gfx::GLSurface
>& surface
,
638 const scoped_refptr
<gfx::GLContext
>& context
,
640 const gfx::Size
& offscreen_size
,
641 const DisallowedFeatures
& disallowed_features
,
642 const std::vector
<int32
>& attribs
) override
;
643 void Destroy(bool have_context
) override
;
644 void SetSurface(const scoped_refptr
<gfx::GLSurface
>& surface
) override
;
645 void ProduceFrontBuffer(const Mailbox
& mailbox
) override
;
646 bool ResizeOffscreenFrameBuffer(const gfx::Size
& size
) override
;
647 void UpdateParentTextureInfo();
648 bool MakeCurrent() override
;
649 GLES2Util
* GetGLES2Util() override
{ return &util_
; }
650 gfx::GLContext
* GetGLContext() override
{ return context_
.get(); }
651 ContextGroup
* GetContextGroup() override
{ return group_
.get(); }
652 Capabilities
GetCapabilities() override
;
653 void RestoreState(const ContextState
* prev_state
) override
;
655 void RestoreActiveTexture() const override
{ state_
.RestoreActiveTexture(); }
656 void RestoreAllTextureUnitBindings(
657 const ContextState
* prev_state
) const override
{
658 state_
.RestoreAllTextureUnitBindings(prev_state
);
660 void RestoreActiveTextureUnitBinding(unsigned int target
) const override
{
661 state_
.RestoreActiveTextureUnitBinding(target
);
663 void RestoreBufferBindings() const override
{
664 state_
.RestoreBufferBindings();
666 void RestoreGlobalState() const override
{ state_
.RestoreGlobalState(NULL
); }
667 void RestoreProgramBindings() const override
{
668 state_
.RestoreProgramBindings();
670 void RestoreTextureUnitBindings(unsigned unit
) const override
{
671 state_
.RestoreTextureUnitBindings(unit
, NULL
);
673 void RestoreFramebufferBindings() const override
;
674 void RestoreRenderbufferBindings() override
;
675 void RestoreTextureState(unsigned service_id
) const override
;
677 void ClearAllAttributes() const override
;
678 void RestoreAllAttributes() const override
;
680 QueryManager
* GetQueryManager() override
{ return query_manager_
.get(); }
681 VertexArrayManager
* GetVertexArrayManager() override
{
682 return vertex_array_manager_
.get();
684 ImageManager
* GetImageManager() override
{ return image_manager_
.get(); }
686 ValuebufferManager
* GetValuebufferManager() override
{
687 return valuebuffer_manager();
690 bool ProcessPendingQueries(bool did_finish
) override
;
692 bool HasMoreIdleWork() override
;
693 void PerformIdleWork() override
;
695 void WaitForReadPixels(base::Closure callback
) override
;
697 void SetResizeCallback(
698 const base::Callback
<void(gfx::Size
, float)>& callback
) override
;
700 Logger
* GetLogger() override
;
702 void BeginDecoding() override
;
703 void EndDecoding() override
;
705 ErrorState
* GetErrorState() override
;
706 const ContextState
* GetContextState() override
{ return &state_
; }
708 void SetShaderCacheCallback(const ShaderCacheCallback
& callback
) override
;
709 void SetWaitSyncPointCallback(const WaitSyncPointCallback
& callback
) override
;
711 AsyncPixelTransferManager
* GetAsyncPixelTransferManager() override
;
712 void ResetAsyncPixelTransferManagerForTest() override
;
713 void SetAsyncPixelTransferManagerForTest(
714 AsyncPixelTransferManager
* manager
) override
;
715 void SetIgnoreCachedStateForTest(bool ignore
) override
;
716 void ProcessFinishedAsyncTransfers();
718 bool GetServiceTextureId(uint32 client_texture_id
,
719 uint32
* service_texture_id
) override
;
721 uint32
GetTextureUploadCount() override
;
722 base::TimeDelta
GetTotalTextureUploadTime() override
;
723 base::TimeDelta
GetTotalProcessingCommandsTime() override
;
724 void AddProcessingCommandsTime(base::TimeDelta
) override
;
726 // Restores the current state to the user's settings.
727 void RestoreCurrentFramebufferBindings();
729 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
730 void ApplyDirtyState();
732 // These check the state of the currently bound framebuffer or the
733 // backbuffer if no framebuffer is bound.
734 // Check with all attached and enabled color attachments.
735 bool BoundFramebufferHasColorAttachmentWithAlpha();
736 bool BoundFramebufferHasDepthAttachment();
737 bool BoundFramebufferHasStencilAttachment();
739 error::ContextLostReason
GetContextLostReason() override
;
741 // Overridden from FramebufferManager::TextureDetachObserver:
742 void OnTextureRefDetachedFromFramebuffer(TextureRef
* texture
) override
;
744 // Overriden from ErrorStateClient.
745 void OnContextLostError() override
;
746 void OnOutOfMemoryError() override
;
748 // Ensure Renderbuffer corresponding to last DoBindRenderbuffer() is bound.
749 void EnsureRenderbufferBound();
751 // Helpers to facilitate calling into compatible extensions.
752 static void RenderbufferStorageMultisampleHelper(
753 const FeatureInfo
* feature_info
,
756 GLenum internal_format
,
760 void BlitFramebufferHelper(GLint srcX0
,
772 friend class ScopedFrameBufferBinder
;
773 friend class ScopedResolvedFrameBufferBinder
;
774 friend class BackFramebuffer
;
776 // Initialize or re-initialize the shader translator.
777 bool InitializeShaderTranslator();
779 void UpdateCapabilities();
781 // Helpers for the glGen and glDelete functions.
782 bool GenTexturesHelper(GLsizei n
, const GLuint
* client_ids
);
783 void DeleteTexturesHelper(GLsizei n
, const GLuint
* client_ids
);
784 bool GenBuffersHelper(GLsizei n
, const GLuint
* client_ids
);
785 void DeleteBuffersHelper(GLsizei n
, const GLuint
* client_ids
);
786 bool GenFramebuffersHelper(GLsizei n
, const GLuint
* client_ids
);
787 void DeleteFramebuffersHelper(GLsizei n
, const GLuint
* client_ids
);
788 bool GenRenderbuffersHelper(GLsizei n
, const GLuint
* client_ids
);
789 void DeleteRenderbuffersHelper(GLsizei n
, const GLuint
* client_ids
);
790 bool GenValuebuffersCHROMIUMHelper(GLsizei n
, const GLuint
* client_ids
);
791 void DeleteValuebuffersCHROMIUMHelper(GLsizei n
, const GLuint
* client_ids
);
792 bool GenQueriesEXTHelper(GLsizei n
, const GLuint
* client_ids
);
793 void DeleteQueriesEXTHelper(GLsizei n
, const GLuint
* client_ids
);
794 bool GenVertexArraysOESHelper(GLsizei n
, const GLuint
* client_ids
);
795 void DeleteVertexArraysOESHelper(GLsizei n
, const GLuint
* client_ids
);
796 bool GenPathsCHROMIUMHelper(GLuint first_client_id
, GLsizei range
);
797 bool DeletePathsCHROMIUMHelper(GLuint first_client_id
, GLsizei range
);
799 // Helper for async upload token completion notification callback.
800 base::Closure
AsyncUploadTokenCompletionClosure(uint32 async_upload_token
,
801 uint32 sync_data_shm_id
,
802 uint32 sync_data_shm_offset
);
807 void OnFboChanged() const;
808 void OnUseFramebuffer() const;
810 error::ContextLostReason
GetContextLostReasonFromResetStatus(
811 GLenum reset_status
) const;
813 // TODO(gman): Cache these pointers?
814 BufferManager
* buffer_manager() {
815 return group_
->buffer_manager();
818 RenderbufferManager
* renderbuffer_manager() {
819 return group_
->renderbuffer_manager();
822 FramebufferManager
* framebuffer_manager() {
823 return group_
->framebuffer_manager();
826 ValuebufferManager
* valuebuffer_manager() {
827 return group_
->valuebuffer_manager();
830 PathManager
* path_manager() { return group_
->path_manager(); }
832 ProgramManager
* program_manager() {
833 return group_
->program_manager();
836 ShaderManager
* shader_manager() {
837 return group_
->shader_manager();
840 ShaderTranslatorCache
* shader_translator_cache() {
841 return group_
->shader_translator_cache();
844 const TextureManager
* texture_manager() const {
845 return group_
->texture_manager();
848 TextureManager
* texture_manager() {
849 return group_
->texture_manager();
852 MailboxManager
* mailbox_manager() {
853 return group_
->mailbox_manager();
856 ImageManager
* image_manager() { return image_manager_
.get(); }
858 VertexArrayManager
* vertex_array_manager() {
859 return vertex_array_manager_
.get();
862 MemoryTracker
* memory_tracker() {
863 return group_
->memory_tracker();
866 bool EnsureGPUMemoryAvailable(size_t estimated_size
) {
867 MemoryTracker
* tracker
= memory_tracker();
869 return tracker
->EnsureGPUMemoryAvailable(estimated_size
);
874 bool IsWebGLContext() const {
875 return webgl_version_
== 1 || webgl_version_
== 2;
878 bool IsOffscreenBufferMultisampled() const {
879 return offscreen_target_samples_
> 1;
882 // Creates a Texture for the given texture.
883 TextureRef
* CreateTexture(
884 GLuint client_id
, GLuint service_id
) {
885 return texture_manager()->CreateTexture(client_id
, service_id
);
888 // Gets the texture info for the given texture. Returns NULL if none exists.
889 TextureRef
* GetTexture(GLuint client_id
) const {
890 return texture_manager()->GetTexture(client_id
);
893 // Deletes the texture info for the given texture.
894 void RemoveTexture(GLuint client_id
) {
895 texture_manager()->RemoveTexture(client_id
);
898 // Get the size (in pixels) of the currently bound frame buffer (either FBO
899 // or regular back buffer).
900 gfx::Size
GetBoundReadFrameBufferSize();
902 // Get the format/type of the currently bound frame buffer (either FBO or
903 // regular back buffer).
904 // If the color image is a renderbuffer, returns 0 for type.
905 GLenum
GetBoundReadFrameBufferTextureType();
906 GLenum
GetBoundReadFrameBufferInternalFormat();
908 // Wrapper for CompressedTexImage2D commands.
909 error::Error
DoCompressedTexImage2D(
912 GLenum internal_format
,
919 // Wrapper for CompressedTexImage3D commands.
920 error::Error
DoCompressedTexImage3D(
923 GLenum internal_format
,
931 // Wrapper for CompressedTexSubImage2D.
932 void DoCompressedTexSubImage2D(
943 // Wrapper for CompressedTexSubImage3D.
944 void DoCompressedTexSubImage3D(
957 // Wrapper for CopyTexImage2D.
958 void DoCopyTexImage2D(
961 GLenum internal_format
,
968 // Wrapper for SwapBuffers.
969 void DoSwapBuffers();
971 // Wrapper for SwapInterval.
972 void DoSwapInterval(int interval
);
974 // Wrapper for CopyTexSubImage2D.
975 void DoCopyTexSubImage2D(
985 // Validation for TexSubImage2D.
986 bool ValidateTexSubImage2D(
988 const char* function_name
,
999 // Wrapper for TexSubImage2D.
1000 error::Error
DoTexSubImage2D(
1011 // Wrapper for TexSubImage3D.
1012 error::Error
DoTexSubImage3D(
1025 // Extra validation for async tex(Sub)Image2D.
1026 bool ValidateAsyncTransfer(
1027 const char* function_name
,
1028 TextureRef
* texture_ref
,
1033 // Wrapper for TexImageIOSurface2DCHROMIUM.
1034 void DoTexImageIOSurface2DCHROMIUM(
1038 GLuint io_surface_id
,
1041 void DoCopyTextureCHROMIUM(GLenum target
,
1044 GLenum internal_format
,
1046 GLboolean unpack_flip_y
,
1047 GLboolean unpack_premultiply_alpha
,
1048 GLboolean unpack_unmultiply_alpha
);
1050 void DoCopySubTextureCHROMIUM(GLenum target
,
1059 GLboolean unpack_flip_y
,
1060 GLboolean unpack_premultiply_alpha
,
1061 GLboolean unpack_unmultiply_alpha
);
1063 void DoCompressedCopyTextureCHROMIUM(GLenum target
,
1067 void DoCompressedCopySubTextureCHROMIUM(GLenum target
,
1077 // Wrapper for TexStorage2DEXT.
1078 void DoTexStorage2DEXT(
1081 GLenum internal_format
,
1085 void DoProduceTextureCHROMIUM(GLenum target
, const GLbyte
* key
);
1086 void DoProduceTextureDirectCHROMIUM(GLuint texture
, GLenum target
,
1088 void ProduceTextureRef(std::string func_name
, TextureRef
* texture_ref
,
1089 GLenum target
, const GLbyte
* data
);
1091 void EnsureTextureForClientId(GLenum target
, GLuint client_id
);
1092 void DoConsumeTextureCHROMIUM(GLenum target
, const GLbyte
* key
);
1093 void DoCreateAndConsumeTextureCHROMIUM(GLenum target
, const GLbyte
* key
,
1096 bool DoIsValuebufferCHROMIUM(GLuint client_id
);
1097 void DoBindValueBufferCHROMIUM(GLenum target
, GLuint valuebuffer
);
1098 void DoSubscribeValueCHROMIUM(GLenum target
, GLenum subscription
);
1099 void DoPopulateSubscribedValuesCHROMIUM(GLenum target
);
1100 void DoUniformValueBufferCHROMIUM(GLint location
,
1102 GLenum subscription
);
1104 void DoBindTexImage2DCHROMIUM(
1107 void DoReleaseTexImage2DCHROMIUM(
1111 void DoTraceEndCHROMIUM(void);
1113 void DoDrawBuffersEXT(GLsizei count
, const GLenum
* bufs
);
1115 void DoLoseContextCHROMIUM(GLenum current
, GLenum other
);
1117 void DoFlushDriverCachesCHROMIUM(void);
1119 void DoMatrixLoadfCHROMIUM(GLenum matrix_mode
, const GLfloat
* matrix
);
1120 void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode
);
1122 // Creates a Program for the given program.
1123 Program
* CreateProgram(
1124 GLuint client_id
, GLuint service_id
) {
1125 return program_manager()->CreateProgram(client_id
, service_id
);
1128 // Gets the program info for the given program. Returns NULL if none exists.
1129 Program
* GetProgram(GLuint client_id
) {
1130 return program_manager()->GetProgram(client_id
);
1134 void LogClientServiceMapping(
1135 const char* /* function_name */,
1136 GLuint
/* client_id */,
1137 GLuint
/* service_id */) {
1139 template<typename T
>
1140 void LogClientServiceForInfo(
1141 T
* /* info */, GLuint
/* client_id */, const char* /* function_name */) {
1144 void LogClientServiceMapping(
1145 const char* function_name
, GLuint client_id
, GLuint service_id
) {
1146 if (service_logging_
) {
1147 VLOG(1) << "[" << logger_
.GetLogPrefix() << "] " << function_name
1148 << ": client_id = " << client_id
1149 << ", service_id = " << service_id
;
1152 template<typename T
>
1153 void LogClientServiceForInfo(
1154 T
* info
, GLuint client_id
, const char* function_name
) {
1156 LogClientServiceMapping(function_name
, client_id
, info
->service_id());
1161 // Gets the program info for the given program. If it's not a program
1162 // generates a GL error. Returns NULL if not program.
1163 Program
* GetProgramInfoNotShader(
1164 GLuint client_id
, const char* function_name
) {
1165 Program
* program
= GetProgram(client_id
);
1167 if (GetShader(client_id
)) {
1169 GL_INVALID_OPERATION
, function_name
, "shader passed for program");
1171 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown program");
1174 LogClientServiceForInfo(program
, client_id
, function_name
);
1179 // Creates a Shader for the given shader.
1180 Shader
* CreateShader(
1183 GLenum shader_type
) {
1184 return shader_manager()->CreateShader(
1185 client_id
, service_id
, shader_type
);
1188 // Gets the shader info for the given shader. Returns NULL if none exists.
1189 Shader
* GetShader(GLuint client_id
) {
1190 return shader_manager()->GetShader(client_id
);
1193 // Gets the shader info for the given shader. If it's not a shader generates a
1194 // GL error. Returns NULL if not shader.
1195 Shader
* GetShaderInfoNotProgram(
1196 GLuint client_id
, const char* function_name
) {
1197 Shader
* shader
= GetShader(client_id
);
1199 if (GetProgram(client_id
)) {
1201 GL_INVALID_OPERATION
, function_name
, "program passed for shader");
1204 GL_INVALID_VALUE
, function_name
, "unknown shader");
1207 LogClientServiceForInfo(shader
, client_id
, function_name
);
1211 // Creates a buffer info for the given buffer.
1212 void CreateBuffer(GLuint client_id
, GLuint service_id
) {
1213 return buffer_manager()->CreateBuffer(client_id
, service_id
);
1216 // Gets the buffer info for the given buffer.
1217 Buffer
* GetBuffer(GLuint client_id
) {
1218 Buffer
* buffer
= buffer_manager()->GetBuffer(client_id
);
1222 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1223 // on glDeleteBuffers so we can make sure the user does not try to render
1224 // with deleted buffers.
1225 void RemoveBuffer(GLuint client_id
);
1227 // Creates a framebuffer info for the given framebuffer.
1228 void CreateFramebuffer(GLuint client_id
, GLuint service_id
) {
1229 return framebuffer_manager()->CreateFramebuffer(client_id
, service_id
);
1232 // Gets the framebuffer info for the given framebuffer.
1233 Framebuffer
* GetFramebuffer(GLuint client_id
) {
1234 return framebuffer_manager()->GetFramebuffer(client_id
);
1237 // Removes the framebuffer info for the given framebuffer.
1238 void RemoveFramebuffer(GLuint client_id
) {
1239 framebuffer_manager()->RemoveFramebuffer(client_id
);
1242 // Creates a renderbuffer info for the given renderbuffer.
1243 void CreateRenderbuffer(GLuint client_id
, GLuint service_id
) {
1244 return renderbuffer_manager()->CreateRenderbuffer(
1245 client_id
, service_id
);
1248 // Gets the renderbuffer info for the given renderbuffer.
1249 Renderbuffer
* GetRenderbuffer(GLuint client_id
) {
1250 return renderbuffer_manager()->GetRenderbuffer(client_id
);
1253 // Removes the renderbuffer info for the given renderbuffer.
1254 void RemoveRenderbuffer(GLuint client_id
) {
1255 renderbuffer_manager()->RemoveRenderbuffer(client_id
);
1258 // Creates a valuebuffer info for the given valuebuffer.
1259 void CreateValuebuffer(GLuint client_id
) {
1260 return valuebuffer_manager()->CreateValuebuffer(client_id
);
1263 // Gets the valuebuffer info for a given valuebuffer.
1264 Valuebuffer
* GetValuebuffer(GLuint client_id
) {
1265 return valuebuffer_manager()->GetValuebuffer(client_id
);
1268 // Removes the valuebuffer info for the given valuebuffer.
1269 void RemoveValuebuffer(GLuint client_id
) {
1270 valuebuffer_manager()->RemoveValuebuffer(client_id
);
1273 // Gets the vertex attrib manager for the given vertex array.
1274 VertexAttribManager
* GetVertexAttribManager(GLuint client_id
) {
1275 VertexAttribManager
* info
=
1276 vertex_array_manager()->GetVertexAttribManager(client_id
);
1280 // Removes the vertex attrib manager for the given vertex array.
1281 void RemoveVertexAttribManager(GLuint client_id
) {
1282 vertex_array_manager()->RemoveVertexAttribManager(client_id
);
1285 // Creates a vertex attrib manager for the given vertex array.
1286 scoped_refptr
<VertexAttribManager
> CreateVertexAttribManager(
1289 bool client_visible
) {
1290 return vertex_array_manager()->CreateVertexAttribManager(
1291 client_id
, service_id
, group_
->max_vertex_attribs(), client_visible
);
1294 void DoBindAttribLocation(GLuint client_id
, GLuint index
, const char* name
);
1295 void DoBindUniformLocationCHROMIUM(
1296 GLuint client_id
, GLint location
, const char* name
);
1298 error::Error
GetAttribLocationHelper(
1299 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1300 const std::string
& name_str
);
1302 error::Error
GetUniformLocationHelper(
1303 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1304 const std::string
& name_str
);
1306 error::Error
GetFragDataLocationHelper(
1307 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1308 const std::string
& name_str
);
1310 // Wrapper for glShaderSource.
1311 void DoShaderSource(
1312 GLuint client_id
, GLsizei count
, const char** data
, const GLint
* length
);
1314 // Wrapper for glTransformFeedbackVaryings.
1315 void DoTransformFeedbackVaryings(
1316 GLuint client_program_id
, GLsizei count
, const char* const* varyings
,
1317 GLenum buffer_mode
);
1319 // Clear any textures used by the current program.
1320 bool ClearUnclearedTextures();
1322 // Clears any uncleared attachments attached to the given frame buffer.
1323 // Returns false if there was a generated GL error.
1324 void ClearUnclearedAttachments(GLenum target
, Framebuffer
* framebuffer
);
1326 // overridden from GLES2Decoder
1327 bool ClearLevel(Texture
* texture
,
1335 int height
) override
;
1337 // Restore all GL state that affects clearing.
1338 void RestoreClearState();
1340 // Remembers the state of some capabilities.
1341 // Returns: true if glEnable/glDisable should actually be called.
1342 bool SetCapabilityState(GLenum cap
, bool enabled
);
1344 // Check that the currently bound framebuffers are valid.
1345 // Generates GL error if not.
1346 bool CheckBoundFramebuffersValid(const char* func_name
);
1348 // Check that the currently bound read framebuffer has a color image
1349 // attached. Generates GL error if not.
1350 bool CheckBoundReadFramebufferColorAttachment(const char* func_name
);
1352 // Check that the currently bound read framebuffer's color image
1353 // isn't the target texture of the glCopyTex{Sub}Image2D.
1354 bool FormsTextureCopyingFeedbackLoop(TextureRef
* texture
, GLint level
);
1356 // Check if a framebuffer meets our requirements.
1357 bool CheckFramebufferValid(
1358 Framebuffer
* framebuffer
,
1360 const char* func_name
);
1362 // Check if the current valuebuffer exists and is valid. If not generates
1363 // the appropriate GL error. Returns true if the current valuebuffer is in
1365 bool CheckCurrentValuebuffer(const char* function_name
);
1367 // Check if the current valuebuffer exists and is valiud and that the
1368 // value buffer is actually subscribed to the given subscription
1369 bool CheckCurrentValuebufferForSubscription(GLenum subscription
,
1370 const char* function_name
);
1372 // Check if the location can be used for the given subscription target. If not
1373 // generates the appropriate GL error. Returns true if the location is usable
1374 bool CheckSubscriptionTarget(GLint location
,
1375 GLenum subscription
,
1376 const char* function_name
);
1378 // Checks if the current program exists and is valid. If not generates the
1379 // appropriate GL error. Returns true if the current program is in a usable
1381 bool CheckCurrentProgram(const char* function_name
);
1383 // Checks if the current program exists and is valid and that location is not
1384 // -1. If the current program is not valid generates the appropriate GL
1385 // error. Returns true if the current program is in a usable state and
1386 // location is not -1.
1387 bool CheckCurrentProgramForUniform(GLint location
, const char* function_name
);
1389 // Checks if the current program samples a texture that is also the color
1390 // image of the current bound framebuffer, i.e., the source and destination
1391 // of the draw operation are the same.
1392 bool CheckDrawingFeedbackLoops();
1394 // Checks if |api_type| is valid for the given uniform
1395 // If the api type is not valid generates the appropriate GL
1396 // error. Returns true if |api_type| is valid for the uniform
1397 bool CheckUniformForApiType(const Program::UniformInfo
* info
,
1398 const char* function_name
,
1399 Program::UniformApiType api_type
);
1401 // Gets the type of a uniform for a location in the current program. Sets GL
1402 // errors if the current program is not valid. Returns true if the current
1403 // program is valid and the location exists. Adjusts count so it
1404 // does not overflow the uniform.
1405 bool PrepForSetUniformByLocation(GLint fake_location
,
1406 const char* function_name
,
1407 Program::UniformApiType api_type
,
1408 GLint
* real_location
,
1412 // Gets the service id for any simulated backbuffer fbo.
1413 GLuint
GetBackbufferServiceId() const;
1415 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1416 bool GetHelper(GLenum pname
, GLint
* params
, GLsizei
* num_written
);
1418 // Helper for glGetVertexAttrib
1419 void GetVertexAttribHelper(
1420 const VertexAttrib
* attrib
, GLenum pname
, GLint
* param
);
1422 // Wrapper for glActiveTexture
1423 void DoActiveTexture(GLenum texture_unit
);
1425 // Wrapper for glAttachShader
1426 void DoAttachShader(GLuint client_program_id
, GLint client_shader_id
);
1428 // Wrapper for glBindBuffer since we need to track the current targets.
1429 void DoBindBuffer(GLenum target
, GLuint buffer
);
1431 // Wrapper for glBindFramebuffer since we need to track the current targets.
1432 void DoBindFramebuffer(GLenum target
, GLuint framebuffer
);
1434 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1435 void DoBindRenderbuffer(GLenum target
, GLuint renderbuffer
);
1437 // Wrapper for glBindTexture since we need to track the current targets.
1438 void DoBindTexture(GLenum target
, GLuint texture
);
1440 // Wrapper for glBindVertexArrayOES
1441 void DoBindVertexArrayOES(GLuint array
);
1442 void EmulateVertexArrayState();
1444 // Wrapper for glBlitFramebufferCHROMIUM.
1445 void DoBlitFramebufferCHROMIUM(
1446 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
1447 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
1448 GLbitfield mask
, GLenum filter
);
1450 // Wrapper for glBufferSubData.
1451 void DoBufferSubData(
1452 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
);
1454 // Wrapper for glCheckFramebufferStatus
1455 GLenum
DoCheckFramebufferStatus(GLenum target
);
1457 // Wrapper for glClear
1458 error::Error
DoClear(GLbitfield mask
);
1460 // Wrappers for various state.
1461 void DoDepthRangef(GLclampf znear
, GLclampf zfar
);
1462 void DoSampleCoverage(GLclampf value
, GLboolean invert
);
1464 // Wrapper for glCompileShader.
1465 void DoCompileShader(GLuint shader
);
1467 // Wrapper for glDetachShader
1468 void DoDetachShader(GLuint client_program_id
, GLint client_shader_id
);
1470 // Wrapper for glDisable
1471 void DoDisable(GLenum cap
);
1473 // Wrapper for glDisableVertexAttribArray.
1474 void DoDisableVertexAttribArray(GLuint index
);
1476 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1478 void DoDiscardFramebufferEXT(GLenum target
,
1479 GLsizei numAttachments
,
1480 const GLenum
* attachments
);
1482 // Wrapper for glEnable
1483 void DoEnable(GLenum cap
);
1485 // Wrapper for glEnableVertexAttribArray.
1486 void DoEnableVertexAttribArray(GLuint index
);
1488 // Wrapper for glFinish.
1491 // Wrapper for glFlush.
1494 // Wrapper for glFramebufferRenderbufffer.
1495 void DoFramebufferRenderbuffer(
1496 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
1497 GLuint renderbuffer
);
1499 // Wrapper for glFramebufferTexture2D.
1500 void DoFramebufferTexture2D(
1501 GLenum target
, GLenum attachment
, GLenum textarget
, GLuint texture
,
1504 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1505 void DoFramebufferTexture2DMultisample(
1506 GLenum target
, GLenum attachment
, GLenum textarget
,
1507 GLuint texture
, GLint level
, GLsizei samples
);
1509 // Common implementation for both DoFramebufferTexture2D wrappers.
1510 void DoFramebufferTexture2DCommon(const char* name
,
1511 GLenum target
, GLenum attachment
, GLenum textarget
,
1512 GLuint texture
, GLint level
, GLsizei samples
);
1514 // Wrapper for glFramebufferTextureLayer.
1515 void DoFramebufferTextureLayer(
1516 GLenum target
, GLenum attachment
, GLuint texture
, GLint level
,
1519 // Wrapper for glGenerateMipmap
1520 void DoGenerateMipmap(GLenum target
);
1522 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1523 // to account for different pname values defined in different extension
1525 GLenum
AdjustGetPname(GLenum pname
);
1527 // Wrapper for DoGetBooleanv.
1528 void DoGetBooleanv(GLenum pname
, GLboolean
* params
);
1530 // Wrapper for DoGetFloatv.
1531 void DoGetFloatv(GLenum pname
, GLfloat
* params
);
1533 // Wrapper for glGetFramebufferAttachmentParameteriv.
1534 void DoGetFramebufferAttachmentParameteriv(
1535 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
);
1537 // Wrapper for glGetInteger64v.
1538 void DoGetInteger64v(GLenum pname
, GLint64
* params
);
1540 // Wrapper for glGetIntegerv.
1541 void DoGetIntegerv(GLenum pname
, GLint
* params
);
1543 // Gets the max value in a range in a buffer.
1544 GLuint
DoGetMaxValueInBufferCHROMIUM(
1545 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
);
1547 // Wrapper for glGetBufferParameteri64v.
1548 void DoGetBufferParameteri64v(
1549 GLenum target
, GLenum pname
, GLint64
* params
);
1551 // Wrapper for glGetBufferParameteriv.
1552 void DoGetBufferParameteriv(
1553 GLenum target
, GLenum pname
, GLint
* params
);
1555 // Wrapper for glGetProgramiv.
1556 void DoGetProgramiv(
1557 GLuint program_id
, GLenum pname
, GLint
* params
);
1559 // Wrapper for glRenderbufferParameteriv.
1560 void DoGetRenderbufferParameteriv(
1561 GLenum target
, GLenum pname
, GLint
* params
);
1563 // Wrapper for glGetShaderiv
1564 void DoGetShaderiv(GLuint shader
, GLenum pname
, GLint
* params
);
1566 // Wrappers for glGetTexParameter.
1567 void DoGetTexParameterfv(GLenum target
, GLenum pname
, GLfloat
* params
);
1568 void DoGetTexParameteriv(GLenum target
, GLenum pname
, GLint
* params
);
1569 void InitTextureMaxAnisotropyIfNeeded(GLenum target
, GLenum pname
);
1571 // Wrappers for glGetVertexAttrib.
1572 template <typename T
>
1573 void DoGetVertexAttribImpl(GLuint index
, GLenum pname
, T
* params
);
1574 void DoGetVertexAttribfv(GLuint index
, GLenum pname
, GLfloat
* params
);
1575 void DoGetVertexAttribiv(GLuint index
, GLenum pname
, GLint
* params
);
1576 void DoGetVertexAttribIiv(GLuint index
, GLenum pname
, GLint
* params
);
1577 void DoGetVertexAttribIuiv(GLuint index
, GLenum pname
, GLuint
* params
);
1579 // Wrappers for glIsXXX functions.
1580 bool DoIsEnabled(GLenum cap
);
1581 bool DoIsBuffer(GLuint client_id
);
1582 bool DoIsFramebuffer(GLuint client_id
);
1583 bool DoIsProgram(GLuint client_id
);
1584 bool DoIsRenderbuffer(GLuint client_id
);
1585 bool DoIsShader(GLuint client_id
);
1586 bool DoIsTexture(GLuint client_id
);
1587 bool DoIsVertexArrayOES(GLuint client_id
);
1588 bool DoIsPathCHROMIUM(GLuint client_id
);
1590 // Wrapper for glLinkProgram
1591 void DoLinkProgram(GLuint program
);
1593 // Wrapper for glReadBuffer
1594 void DoReadBuffer(GLenum src
);
1596 // Wrapper for glRenderbufferStorage.
1597 void DoRenderbufferStorage(
1598 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
);
1600 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1601 void DoRenderbufferStorageMultisampleCHROMIUM(
1602 GLenum target
, GLsizei samples
, GLenum internalformat
,
1603 GLsizei width
, GLsizei height
);
1605 // Handler for glRenderbufferStorageMultisampleEXT
1606 // (multisampled_render_to_texture).
1607 void DoRenderbufferStorageMultisampleEXT(
1608 GLenum target
, GLsizei samples
, GLenum internalformat
,
1609 GLsizei width
, GLsizei height
);
1611 // Common validation for multisample extensions.
1612 bool ValidateRenderbufferStorageMultisample(GLsizei samples
,
1613 GLenum internalformat
,
1617 // Verifies that the currently bound multisample renderbuffer is valid
1618 // Very slow! Only done on platforms with driver bugs that return invalid
1619 // buffers under memory pressure
1620 bool VerifyMultisampleRenderbufferIntegrity(
1621 GLuint renderbuffer
, GLenum format
);
1623 // Wrapper for glReleaseShaderCompiler.
1624 void DoReleaseShaderCompiler() { }
1626 // Wrappers for glSamplerParameter*v functions.
1627 void DoSamplerParameterfv(
1628 GLuint sampler
, GLenum pname
, const GLfloat
* params
);
1629 void DoSamplerParameteriv(GLuint sampler
, GLenum pname
, const GLint
* params
);
1631 // Wrappers for glTexParameter functions.
1632 void DoTexParameterf(GLenum target
, GLenum pname
, GLfloat param
);
1633 void DoTexParameteri(GLenum target
, GLenum pname
, GLint param
);
1634 void DoTexParameterfv(GLenum target
, GLenum pname
, const GLfloat
* params
);
1635 void DoTexParameteriv(GLenum target
, GLenum pname
, const GLint
* params
);
1637 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1638 // spec only these 2 functions can be used to set sampler uniforms.
1639 void DoUniform1i(GLint fake_location
, GLint v0
);
1640 void DoUniform1iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1641 void DoUniform2iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1642 void DoUniform3iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1643 void DoUniform4iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1645 // Wrappers for glUniformfv because some drivers don't correctly accept
1647 void DoUniform1fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1648 void DoUniform2fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1649 void DoUniform3fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1650 void DoUniform4fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1652 void DoUniformMatrix2fv(
1653 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1654 const GLfloat
* value
);
1655 void DoUniformMatrix3fv(
1656 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1657 const GLfloat
* value
);
1658 void DoUniformMatrix4fv(
1659 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1660 const GLfloat
* value
);
1662 template <typename T
>
1663 bool SetVertexAttribValue(
1664 const char* function_name
, GLuint index
, const T
* value
);
1666 // Wrappers for glVertexAttrib??
1667 void DoVertexAttrib1f(GLuint index
, GLfloat v0
);
1668 void DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
);
1669 void DoVertexAttrib3f(GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
);
1670 void DoVertexAttrib4f(
1671 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
);
1672 void DoVertexAttrib1fv(GLuint index
, const GLfloat
* v
);
1673 void DoVertexAttrib2fv(GLuint index
, const GLfloat
* v
);
1674 void DoVertexAttrib3fv(GLuint index
, const GLfloat
* v
);
1675 void DoVertexAttrib4fv(GLuint index
, const GLfloat
* v
);
1676 void DoVertexAttribI4i(GLuint index
, GLint v0
, GLint v1
, GLint v2
, GLint v3
);
1677 void DoVertexAttribI4iv(GLuint index
, const GLint
* v
);
1678 void DoVertexAttribI4ui(
1679 GLuint index
, GLuint v0
, GLuint v1
, GLuint v2
, GLuint v3
);
1680 void DoVertexAttribI4uiv(GLuint index
, const GLuint
* v
);
1682 // Wrapper for glViewport
1683 void DoViewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
1685 // Wrapper for glUseProgram
1686 void DoUseProgram(GLuint program
);
1688 // Wrapper for glValidateProgram.
1689 void DoValidateProgram(GLuint program_client_id
);
1691 void DoInsertEventMarkerEXT(GLsizei length
, const GLchar
* marker
);
1692 void DoPushGroupMarkerEXT(GLsizei length
, const GLchar
* group
);
1693 void DoPopGroupMarkerEXT(void);
1695 // Gets the number of values that will be returned by glGetXXX. Returns
1696 // false if pname is unknown.
1697 bool GetNumValuesReturnedForGLGet(GLenum pname
, GLsizei
* num_values
);
1699 // Checks if the current program and vertex attributes are valid for drawing.
1701 const char* function_name
, GLuint max_vertex_accessed
, bool instanced
,
1704 // Returns true if successful, simulated will be true if attrib0 was
1706 bool SimulateAttrib0(
1707 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
);
1708 void RestoreStateForAttrib(GLuint attrib
, bool restore_array_binding
);
1710 // If an image is bound to texture, this will call Will/DidUseTexImage
1712 void DoWillUseTexImageIfNeeded(Texture
* texture
, GLenum textarget
);
1713 void DoDidUseTexImageIfNeeded(Texture
* texture
, GLenum textarget
);
1715 // Returns false if textures were replaced.
1716 bool PrepareTexturesForRender();
1717 void RestoreStateForTextures();
1719 // Returns true if GL_FIXED attribs were simulated.
1720 bool SimulateFixedAttribs(
1721 const char* function_name
,
1722 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
);
1723 void RestoreStateForSimulatedFixedAttribs();
1725 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1726 // cases (primcount is always 1 for non-instanced).
1727 error::Error
DoDrawArrays(
1728 const char* function_name
,
1729 bool instanced
, GLenum mode
, GLint first
, GLsizei count
,
1731 error::Error
DoDrawElements(
1732 const char* function_name
,
1733 bool instanced
, GLenum mode
, GLsizei count
, GLenum type
,
1734 int32 offset
, GLsizei primcount
);
1736 GLenum
GetBindTargetForSamplerType(GLenum type
) {
1737 DCHECK(type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_CUBE
||
1738 type
== GL_SAMPLER_EXTERNAL_OES
|| type
== GL_SAMPLER_2D_RECT_ARB
);
1741 return GL_TEXTURE_2D
;
1742 case GL_SAMPLER_CUBE
:
1743 return GL_TEXTURE_CUBE_MAP
;
1744 case GL_SAMPLER_EXTERNAL_OES
:
1745 return GL_TEXTURE_EXTERNAL_OES
;
1746 case GL_SAMPLER_2D_RECT_ARB
:
1747 return GL_TEXTURE_RECTANGLE_ARB
;
1754 // Gets the framebuffer info for a particular target.
1755 Framebuffer
* GetFramebufferInfoForTarget(GLenum target
) {
1756 Framebuffer
* framebuffer
= NULL
;
1758 case GL_FRAMEBUFFER
:
1759 case GL_DRAW_FRAMEBUFFER_EXT
:
1760 framebuffer
= framebuffer_state_
.bound_draw_framebuffer
.get();
1762 case GL_READ_FRAMEBUFFER_EXT
:
1763 framebuffer
= framebuffer_state_
.bound_read_framebuffer
.get();
1772 Renderbuffer
* GetRenderbufferInfoForTarget(
1774 Renderbuffer
* renderbuffer
= NULL
;
1776 case GL_RENDERBUFFER
:
1777 renderbuffer
= state_
.bound_renderbuffer
.get();
1783 return renderbuffer
;
1786 // Validates the program and location for a glGetUniform call and returns
1787 // a SizeResult setup to receive the result. Returns true if glGetUniform
1788 // should be called.
1790 bool GetUniformSetup(GLuint program
,
1791 GLint fake_location
,
1794 error::Error
* error
,
1795 GLint
* real_location
,
1797 SizedResult
<T
>** result
,
1798 GLenum
* result_type
,
1799 GLsizei
* result_size
);
1801 bool WasContextLost() const override
;
1802 bool WasContextLostByRobustnessExtension() const override
;
1803 void MarkContextLost(error::ContextLostReason reason
) override
;
1804 bool CheckResetStatus();
1806 #if defined(OS_MACOSX)
1807 void ReleaseIOSurfaceForTexture(GLuint texture_id
);
1810 bool GetCompressedTexSizeInBytes(
1811 const char* function_name
, GLsizei width
, GLsizei height
, GLsizei depth
,
1812 GLenum format
, GLsizei
* size_in_bytes
);
1814 bool ValidateCompressedTexDimensions(
1815 const char* function_name
, GLenum target
, GLint level
,
1816 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
);
1817 bool ValidateCompressedTexFuncData(
1818 const char* function_name
, GLsizei width
, GLsizei height
, GLsizei depth
,
1819 GLenum format
, GLsizei size
);
1820 bool ValidateCompressedTexSubDimensions(
1821 const char* function_name
,
1822 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
1823 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
,
1825 bool ValidateCopyTextureCHROMIUM(const char* function_name
,
1827 TextureRef
* source_texture_ref
,
1828 TextureRef
* dest_texture_ref
,
1829 GLenum dest_internal_format
);
1830 bool ValidateCompressedCopyTextureCHROMIUM(const char* function_name
,
1832 TextureRef
* source_texture_ref
,
1833 TextureRef
* dest_texture_ref
);
1835 void RenderWarning(const char* filename
, int line
, const std::string
& msg
);
1836 void PerformanceWarning(
1837 const char* filename
, int line
, const std::string
& msg
);
1839 const FeatureInfo::FeatureFlags
& features() const {
1840 return feature_info_
->feature_flags();
1843 const FeatureInfo::Workarounds
& workarounds() const {
1844 return feature_info_
->workarounds();
1847 bool ShouldDeferDraws() {
1848 return !offscreen_target_frame_buffer_
.get() &&
1849 framebuffer_state_
.bound_draw_framebuffer
.get() == NULL
&&
1850 surface_
->DeferDraws();
1853 bool ShouldDeferReads() {
1854 return !offscreen_target_frame_buffer_
.get() &&
1855 framebuffer_state_
.bound_read_framebuffer
.get() == NULL
&&
1856 surface_
->DeferDraws();
1859 bool IsRobustnessSupported() {
1860 return has_robustness_extension_
&&
1861 context_
->WasAllocatedUsingRobustnessExtension();
1864 error::Error
WillAccessBoundFramebufferForDraw() {
1865 if (ShouldDeferDraws())
1866 return error::kDeferCommandUntilLater
;
1867 if (!offscreen_target_frame_buffer_
.get() &&
1868 !framebuffer_state_
.bound_draw_framebuffer
.get() &&
1869 !surface_
->SetBackbufferAllocation(true))
1870 return error::kLostContext
;
1871 return error::kNoError
;
1874 error::Error
WillAccessBoundFramebufferForRead() {
1875 if (ShouldDeferReads())
1876 return error::kDeferCommandUntilLater
;
1877 if (!offscreen_target_frame_buffer_
.get() &&
1878 !framebuffer_state_
.bound_read_framebuffer
.get() &&
1879 !surface_
->SetBackbufferAllocation(true))
1880 return error::kLostContext
;
1881 return error::kNoError
;
1884 bool BackBufferHasAlpha() const {
1885 if (back_buffer_draw_buffer_
== GL_NONE
)
1887 if (offscreen_target_frame_buffer_
.get()) {
1888 return (offscreen_target_color_format_
== GL_RGBA
||
1889 offscreen_target_color_format_
== GL_RGBA8
);
1891 return (back_buffer_color_format_
== GL_RGBA
||
1892 back_buffer_color_format_
== GL_RGBA8
);
1895 // Set remaining commands to process to 0 to force DoCommands to return
1896 // and allow context preemption and GPU watchdog checks in GpuScheduler().
1897 void ExitCommandProcessingEarly() { commands_to_process_
= 0; }
1899 void ProcessPendingReadPixels(bool did_finish
);
1900 void FinishReadPixels(const cmds::ReadPixels
& c
, GLuint buffer
);
1902 // Generate a member function prototype for each command in an automated and
1904 #define GLES2_CMD_OP(name) \
1905 Error Handle##name(uint32 immediate_data_size, const void* data);
1907 GLES2_COMMAND_LIST(GLES2_CMD_OP
)
1911 // The GL context this decoder renders to on behalf of the client.
1912 scoped_refptr
<gfx::GLSurface
> surface_
;
1913 scoped_refptr
<gfx::GLContext
> context_
;
1915 // The ContextGroup for this decoder uses to track resources.
1916 scoped_refptr
<ContextGroup
> group_
;
1918 DebugMarkerManager debug_marker_manager_
;
1921 // All the state for this context.
1922 ContextState state_
;
1924 // Current width and height of the offscreen frame buffer.
1925 gfx::Size offscreen_size_
;
1927 // Util to help with GL.
1930 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1931 GLuint attrib_0_buffer_id_
;
1933 // The value currently in attrib_0.
1934 Vec4 attrib_0_value_
;
1936 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1937 bool attrib_0_buffer_matches_value_
;
1939 // The size of attrib 0.
1940 GLsizei attrib_0_size_
;
1942 // The buffer used to simulate GL_FIXED attribs.
1943 GLuint fixed_attrib_buffer_id_
;
1945 // The size of fiixed attrib buffer.
1946 GLsizei fixed_attrib_buffer_size_
;
1948 // The offscreen frame buffer that the client renders to. With EGL, the
1949 // depth and stencil buffers are separate. With regular GL there is a single
1950 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1951 // offscreen_target_stencil_render_buffer_ is unused.
1952 scoped_ptr
<BackFramebuffer
> offscreen_target_frame_buffer_
;
1953 scoped_ptr
<BackTexture
> offscreen_target_color_texture_
;
1954 scoped_ptr
<BackRenderbuffer
> offscreen_target_color_render_buffer_
;
1955 scoped_ptr
<BackRenderbuffer
> offscreen_target_depth_render_buffer_
;
1956 scoped_ptr
<BackRenderbuffer
> offscreen_target_stencil_render_buffer_
;
1957 GLenum offscreen_target_color_format_
;
1958 GLenum offscreen_target_depth_format_
;
1959 GLenum offscreen_target_stencil_format_
;
1960 GLsizei offscreen_target_samples_
;
1961 GLboolean offscreen_target_buffer_preserved_
;
1963 // The copy that is saved when SwapBuffers is called.
1964 scoped_ptr
<BackFramebuffer
> offscreen_saved_frame_buffer_
;
1965 scoped_ptr
<BackTexture
> offscreen_saved_color_texture_
;
1966 scoped_refptr
<TextureRef
>
1967 offscreen_saved_color_texture_info_
;
1969 // The copy that is used as the destination for multi-sample resolves.
1970 scoped_ptr
<BackFramebuffer
> offscreen_resolved_frame_buffer_
;
1971 scoped_ptr
<BackTexture
> offscreen_resolved_color_texture_
;
1972 GLenum offscreen_saved_color_format_
;
1974 scoped_ptr
<QueryManager
> query_manager_
;
1976 scoped_ptr
<VertexArrayManager
> vertex_array_manager_
;
1978 scoped_ptr
<ImageManager
> image_manager_
;
1980 base::Callback
<void(gfx::Size
, float)> resize_callback_
;
1982 WaitSyncPointCallback wait_sync_point_callback_
;
1984 ShaderCacheCallback shader_cache_callback_
;
1986 scoped_ptr
<AsyncPixelTransferManager
> async_pixel_transfer_manager_
;
1988 // The format of the back buffer_
1989 GLenum back_buffer_color_format_
;
1990 bool back_buffer_has_depth_
;
1991 bool back_buffer_has_stencil_
;
1993 // Tracks read buffer and draw buffer for backbuffer, whether it's onscreen
1995 // TODO(zmo): when ES3 APIs are exposed to Nacl, make sure read_buffer_
1996 // setting is set correctly when SwapBuffers().
1997 GLenum back_buffer_read_buffer_
;
1998 GLenum back_buffer_draw_buffer_
;
2002 // Backbuffer attachments that are currently undefined.
2003 uint32 backbuffer_needs_clear_bits_
;
2005 // The current decoder error communicates the decoder error through command
2006 // processing functions that do not return the error value. Should be set only
2007 // if not returning an error.
2008 error::Error current_decoder_error_
;
2010 bool use_shader_translator_
;
2011 scoped_refptr
<ShaderTranslatorInterface
> vertex_translator_
;
2012 scoped_refptr
<ShaderTranslatorInterface
> fragment_translator_
;
2014 DisallowedFeatures disallowed_features_
;
2016 // Cached from ContextGroup
2017 const Validators
* validators_
;
2018 scoped_refptr
<FeatureInfo
> feature_info_
;
2022 // Number of commands remaining to be processed in DoCommands().
2023 int commands_to_process_
;
2025 bool has_robustness_extension_
;
2026 error::ContextLostReason context_lost_reason_
;
2027 bool context_was_lost_
;
2028 bool reset_by_robustness_extension_
;
2029 bool supports_post_sub_buffer_
;
2031 // Indicates whether this is a context for WebGL1, WebGL2, or others.
2035 unsigned webgl_version_
;
2037 // These flags are used to override the state of the shared feature_info_
2038 // member. Because the same FeatureInfo instance may be shared among many
2039 // contexts, the assumptions on the availablity of extensions in WebGL
2040 // contexts may be broken. These flags override the shared state to preserve
2042 bool derivatives_explicitly_enabled_
;
2043 bool frag_depth_explicitly_enabled_
;
2044 bool draw_buffers_explicitly_enabled_
;
2045 bool shader_texture_lod_explicitly_enabled_
;
2047 bool compile_shader_always_succeeds_
;
2049 // An optional behaviour to lose the context and group when OOM.
2050 bool lose_context_when_out_of_memory_
;
2053 bool service_logging_
;
2055 #if defined(OS_MACOSX)
2056 typedef std::map
<GLuint
, IOSurfaceRef
> TextureToIOSurfaceMap
;
2057 TextureToIOSurfaceMap texture_to_io_surface_map_
;
2060 scoped_ptr
<CopyTextureCHROMIUMResourceManager
> copy_texture_CHROMIUM_
;
2061 scoped_ptr
<ClearFramebufferResourceManager
> clear_framebuffer_blit_
;
2063 // Cached values of the currently assigned viewport dimensions.
2064 GLsizei viewport_max_width_
;
2065 GLsizei viewport_max_height_
;
2067 // Command buffer stats.
2068 base::TimeDelta total_processing_commands_time_
;
2070 // States related to each manager.
2071 DecoderTextureState texture_state_
;
2072 DecoderFramebufferState framebuffer_state_
;
2074 scoped_ptr
<GPUTracer
> gpu_tracer_
;
2075 scoped_ptr
<GPUStateTracer
> gpu_state_tracer_
;
2076 const unsigned char* cb_command_trace_category_
;
2077 const unsigned char* gpu_decoder_category_
;
2078 int gpu_trace_level_
;
2079 bool gpu_trace_commands_
;
2080 bool gpu_debug_commands_
;
2082 std::queue
<linked_ptr
<FenceCallback
> > pending_readpixel_fences_
;
2084 // Used to validate multisample renderbuffers if needed
2085 GLuint validation_texture_
;
2086 GLuint validation_fbo_multisample_
;
2087 GLuint validation_fbo_
;
2089 typedef gpu::gles2::GLES2Decoder::Error (GLES2DecoderImpl::*CmdHandler
)(
2090 uint32 immediate_data_size
,
2093 // A struct to hold info about each command.
2094 struct CommandInfo
{
2095 CmdHandler cmd_handler
;
2096 uint8 arg_flags
; // How to handle the arguments for this command
2097 uint8 cmd_flags
; // How to handle this command
2098 uint16 arg_count
; // How many arguments are expected for this command.
2101 // A table of CommandInfo for all the commands.
2102 static const CommandInfo command_info
[kNumCommands
- kStartPoint
];
2104 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl
);
2107 const GLES2DecoderImpl::CommandInfo
GLES2DecoderImpl::command_info
[] = {
2108 #define GLES2_CMD_OP(name) \
2110 &GLES2DecoderImpl::Handle##name, cmds::name::kArgFlags, \
2111 cmds::name::cmd_flags, \
2112 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, \
2115 GLES2_COMMAND_LIST(GLES2_CMD_OP
)
2119 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
2120 const char* function_name
, ErrorState
* error_state
)
2121 : function_name_(function_name
),
2122 error_state_(error_state
) {
2123 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_
, function_name_
);
2126 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
2127 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_
, function_name_
);
2130 static void RestoreCurrentTextureBindings(ContextState
* state
, GLenum target
) {
2131 TextureUnit
& info
= state
->texture_units
[0];
2133 scoped_refptr
<TextureRef
> texture_ref
;
2136 texture_ref
= info
.bound_texture_2d
;
2138 case GL_TEXTURE_CUBE_MAP
:
2139 texture_ref
= info
.bound_texture_cube_map
;
2141 case GL_TEXTURE_EXTERNAL_OES
:
2142 texture_ref
= info
.bound_texture_external_oes
;
2144 case GL_TEXTURE_RECTANGLE_ARB
:
2145 texture_ref
= info
.bound_texture_rectangle_arb
;
2151 if (texture_ref
.get()) {
2152 last_id
= texture_ref
->service_id();
2157 glBindTexture(target
, last_id
);
2158 glActiveTexture(GL_TEXTURE0
+ state
->active_texture_unit
);
2161 ScopedTextureBinder::ScopedTextureBinder(ContextState
* state
,
2166 ScopedGLErrorSuppressor
suppressor(
2167 "ScopedTextureBinder::ctor", state_
->GetErrorState());
2169 // TODO(apatrick): Check if there are any other states that need to be reset
2170 // before binding a new texture.
2171 glActiveTexture(GL_TEXTURE0
);
2172 glBindTexture(target
, id
);
2175 ScopedTextureBinder::~ScopedTextureBinder() {
2176 ScopedGLErrorSuppressor
suppressor(
2177 "ScopedTextureBinder::dtor", state_
->GetErrorState());
2178 RestoreCurrentTextureBindings(state_
, target_
);
2181 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState
* state
,
2184 ScopedGLErrorSuppressor
suppressor(
2185 "ScopedRenderBufferBinder::ctor", state_
->GetErrorState());
2186 glBindRenderbufferEXT(GL_RENDERBUFFER
, id
);
2189 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
2190 ScopedGLErrorSuppressor
suppressor(
2191 "ScopedRenderBufferBinder::dtor", state_
->GetErrorState());
2192 state_
->RestoreRenderbufferBindings();
2195 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl
* decoder
,
2197 : decoder_(decoder
) {
2198 ScopedGLErrorSuppressor
suppressor(
2199 "ScopedFrameBufferBinder::ctor", decoder_
->GetErrorState());
2200 glBindFramebufferEXT(GL_FRAMEBUFFER
, id
);
2201 decoder
->OnFboChanged();
2204 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
2205 ScopedGLErrorSuppressor
suppressor(
2206 "ScopedFrameBufferBinder::dtor", decoder_
->GetErrorState());
2207 decoder_
->RestoreCurrentFramebufferBindings();
2210 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
2211 GLES2DecoderImpl
* decoder
, bool enforce_internal_framebuffer
, bool internal
)
2212 : decoder_(decoder
) {
2213 resolve_and_bind_
= (
2214 decoder_
->offscreen_target_frame_buffer_
.get() &&
2215 decoder_
->IsOffscreenBufferMultisampled() &&
2216 (!decoder_
->framebuffer_state_
.bound_read_framebuffer
.get() ||
2217 enforce_internal_framebuffer
));
2218 if (!resolve_and_bind_
)
2221 ScopedGLErrorSuppressor
suppressor(
2222 "ScopedResolvedFrameBufferBinder::ctor", decoder_
->GetErrorState());
2223 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
,
2224 decoder_
->offscreen_target_frame_buffer_
->id());
2227 if (!decoder_
->offscreen_resolved_frame_buffer_
.get()) {
2228 decoder_
->offscreen_resolved_frame_buffer_
.reset(
2229 new BackFramebuffer(decoder_
));
2230 decoder_
->offscreen_resolved_frame_buffer_
->Create();
2231 decoder_
->offscreen_resolved_color_texture_
.reset(
2232 new BackTexture(decoder
->memory_tracker(), &decoder
->state_
));
2233 decoder_
->offscreen_resolved_color_texture_
->Create();
2235 DCHECK(decoder_
->offscreen_saved_color_format_
);
2236 decoder_
->offscreen_resolved_color_texture_
->AllocateStorage(
2237 decoder_
->offscreen_size_
, decoder_
->offscreen_saved_color_format_
,
2239 decoder_
->offscreen_resolved_frame_buffer_
->AttachRenderTexture(
2240 decoder_
->offscreen_resolved_color_texture_
.get());
2241 if (decoder_
->offscreen_resolved_frame_buffer_
->CheckStatus() !=
2242 GL_FRAMEBUFFER_COMPLETE
) {
2243 LOG(ERROR
) << "ScopedResolvedFrameBufferBinder failed "
2244 << "because offscreen resolved FBO was incomplete.";
2248 targetid
= decoder_
->offscreen_resolved_frame_buffer_
->id();
2250 targetid
= decoder_
->offscreen_saved_frame_buffer_
->id();
2252 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, targetid
);
2253 const int width
= decoder_
->offscreen_size_
.width();
2254 const int height
= decoder_
->offscreen_size_
.height();
2255 decoder
->state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
2256 decoder
->BlitFramebufferHelper(0,
2264 GL_COLOR_BUFFER_BIT
,
2266 glBindFramebufferEXT(GL_FRAMEBUFFER
, targetid
);
2269 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
2270 if (!resolve_and_bind_
)
2273 ScopedGLErrorSuppressor
suppressor(
2274 "ScopedResolvedFrameBufferBinder::dtor", decoder_
->GetErrorState());
2275 decoder_
->RestoreCurrentFramebufferBindings();
2276 if (decoder_
->state_
.enable_flags
.scissor_test
) {
2277 decoder_
->state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
2281 BackTexture::BackTexture(
2282 MemoryTracker
* memory_tracker
,
2283 ContextState
* state
)
2284 : memory_tracker_(memory_tracker
, MemoryTracker::kUnmanaged
),
2286 bytes_allocated_(0),
2290 BackTexture::~BackTexture() {
2291 // This does not destroy the render texture because that would require that
2292 // the associated GL context was current. Just check that it was explicitly
2297 void BackTexture::Create() {
2298 ScopedGLErrorSuppressor
suppressor("BackTexture::Create",
2299 state_
->GetErrorState());
2301 glGenTextures(1, &id_
);
2302 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2303 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
2304 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
2305 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
2306 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
2308 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
2309 // never called on an offscreen context, no data will ever be uploaded to the
2310 // saved offscreen color texture (it is deferred until to when SwapBuffers
2311 // is called). My idea is that some nvidia drivers might have a bug where
2312 // deleting a texture that has never been populated might cause a
2315 GL_TEXTURE_2D
, 0, GL_RGBA
, 16, 16, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, NULL
);
2317 bytes_allocated_
= 16u * 16u * 4u;
2318 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2321 bool BackTexture::AllocateStorage(
2322 const gfx::Size
& size
, GLenum format
, bool zero
) {
2324 ScopedGLErrorSuppressor
suppressor("BackTexture::AllocateStorage",
2325 state_
->GetErrorState());
2326 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2327 uint32 image_size
= 0;
2328 GLES2Util::ComputeImageDataSizes(
2329 size
.width(), size
.height(), 1, format
, GL_UNSIGNED_BYTE
, 8, &image_size
,
2332 if (!memory_tracker_
.EnsureGPUMemoryAvailable(image_size
)) {
2336 scoped_ptr
<char[]> zero_data
;
2338 zero_data
.reset(new char[image_size
]);
2339 memset(zero_data
.get(), 0, image_size
);
2342 glTexImage2D(GL_TEXTURE_2D
,
2354 bool success
= glGetError() == GL_NO_ERROR
;
2356 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2357 bytes_allocated_
= image_size
;
2358 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2363 void BackTexture::Copy(const gfx::Size
& size
, GLenum format
) {
2365 ScopedGLErrorSuppressor
suppressor("BackTexture::Copy",
2366 state_
->GetErrorState());
2367 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2368 glCopyTexImage2D(GL_TEXTURE_2D
,
2377 void BackTexture::Destroy() {
2379 ScopedGLErrorSuppressor
suppressor("BackTexture::Destroy",
2380 state_
->GetErrorState());
2381 glDeleteTextures(1, &id_
);
2384 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2385 bytes_allocated_
= 0;
2388 void BackTexture::Invalidate() {
2392 BackRenderbuffer::BackRenderbuffer(
2393 RenderbufferManager
* renderbuffer_manager
,
2394 MemoryTracker
* memory_tracker
,
2395 ContextState
* state
)
2396 : renderbuffer_manager_(renderbuffer_manager
),
2397 memory_tracker_(memory_tracker
, MemoryTracker::kUnmanaged
),
2399 bytes_allocated_(0),
2403 BackRenderbuffer::~BackRenderbuffer() {
2404 // This does not destroy the render buffer because that would require that
2405 // the associated GL context was current. Just check that it was explicitly
2410 void BackRenderbuffer::Create() {
2411 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Create",
2412 state_
->GetErrorState());
2414 glGenRenderbuffersEXT(1, &id_
);
2417 bool BackRenderbuffer::AllocateStorage(const FeatureInfo
* feature_info
,
2418 const gfx::Size
& size
,
2421 ScopedGLErrorSuppressor
suppressor(
2422 "BackRenderbuffer::AllocateStorage", state_
->GetErrorState());
2423 ScopedRenderBufferBinder
binder(state_
, id_
);
2425 uint32 estimated_size
= 0;
2426 if (!renderbuffer_manager_
->ComputeEstimatedRenderbufferSize(
2427 size
.width(), size
.height(), samples
, format
, &estimated_size
)) {
2431 if (!memory_tracker_
.EnsureGPUMemoryAvailable(estimated_size
)) {
2436 glRenderbufferStorageEXT(GL_RENDERBUFFER
,
2441 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info
,
2448 bool success
= glGetError() == GL_NO_ERROR
;
2450 // Mark the previously allocated bytes as free.
2451 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2452 bytes_allocated_
= estimated_size
;
2453 // Track the newly allocated bytes.
2454 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2459 void BackRenderbuffer::Destroy() {
2461 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Destroy",
2462 state_
->GetErrorState());
2463 glDeleteRenderbuffersEXT(1, &id_
);
2466 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2467 bytes_allocated_
= 0;
2470 void BackRenderbuffer::Invalidate() {
2474 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl
* decoder
)
2475 : decoder_(decoder
),
2479 BackFramebuffer::~BackFramebuffer() {
2480 // This does not destroy the frame buffer because that would require that
2481 // the associated GL context was current. Just check that it was explicitly
2486 void BackFramebuffer::Create() {
2487 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Create",
2488 decoder_
->GetErrorState());
2490 glGenFramebuffersEXT(1, &id_
);
2493 void BackFramebuffer::AttachRenderTexture(BackTexture
* texture
) {
2495 ScopedGLErrorSuppressor
suppressor(
2496 "BackFramebuffer::AttachRenderTexture", decoder_
->GetErrorState());
2497 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2498 GLuint attach_id
= texture
? texture
->id() : 0;
2499 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
,
2500 GL_COLOR_ATTACHMENT0
,
2506 void BackFramebuffer::AttachRenderBuffer(GLenum target
,
2507 BackRenderbuffer
* render_buffer
) {
2509 ScopedGLErrorSuppressor
suppressor(
2510 "BackFramebuffer::AttachRenderBuffer", decoder_
->GetErrorState());
2511 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2512 GLuint attach_id
= render_buffer
? render_buffer
->id() : 0;
2513 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
,
2519 void BackFramebuffer::Destroy() {
2521 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Destroy",
2522 decoder_
->GetErrorState());
2523 glDeleteFramebuffersEXT(1, &id_
);
2528 void BackFramebuffer::Invalidate() {
2532 GLenum
BackFramebuffer::CheckStatus() {
2534 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::CheckStatus",
2535 decoder_
->GetErrorState());
2536 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2537 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER
);
2540 GLES2Decoder
* GLES2Decoder::Create(ContextGroup
* group
) {
2541 return new GLES2DecoderImpl(group
);
2544 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup
* group
)
2547 logger_(&debug_marker_manager_
),
2548 state_(group_
->feature_info(), this, &logger_
),
2549 attrib_0_buffer_id_(0),
2550 attrib_0_buffer_matches_value_(true),
2552 fixed_attrib_buffer_id_(0),
2553 fixed_attrib_buffer_size_(0),
2554 offscreen_target_color_format_(0),
2555 offscreen_target_depth_format_(0),
2556 offscreen_target_stencil_format_(0),
2557 offscreen_target_samples_(0),
2558 offscreen_target_buffer_preserved_(true),
2559 offscreen_saved_color_format_(0),
2560 back_buffer_color_format_(0),
2561 back_buffer_has_depth_(false),
2562 back_buffer_has_stencil_(false),
2563 back_buffer_read_buffer_(GL_BACK
),
2564 back_buffer_draw_buffer_(GL_BACK
),
2565 surfaceless_(false),
2566 backbuffer_needs_clear_bits_(0),
2567 current_decoder_error_(error::kNoError
),
2568 use_shader_translator_(true),
2569 validators_(group_
->feature_info()->validators()),
2570 feature_info_(group_
->feature_info()),
2572 has_robustness_extension_(false),
2573 context_lost_reason_(error::kUnknown
),
2574 context_was_lost_(false),
2575 reset_by_robustness_extension_(false),
2576 supports_post_sub_buffer_(false),
2578 derivatives_explicitly_enabled_(false),
2579 frag_depth_explicitly_enabled_(false),
2580 draw_buffers_explicitly_enabled_(false),
2581 shader_texture_lod_explicitly_enabled_(false),
2582 compile_shader_always_succeeds_(false),
2583 lose_context_when_out_of_memory_(false),
2584 service_logging_(base::CommandLine::InitializedForCurrentProcess()
2585 ? base::CommandLine::ForCurrentProcess()->HasSwitch(
2586 switches::kEnableGPUServiceLoggingGPU
)
2588 viewport_max_width_(0),
2589 viewport_max_height_(0),
2590 texture_state_(group_
->feature_info()
2592 .texsubimage_faster_than_teximage
),
2593 cb_command_trace_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2594 TRACE_DISABLED_BY_DEFAULT("cb_command"))),
2595 gpu_decoder_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2596 TRACE_DISABLED_BY_DEFAULT("gpu_decoder"))),
2597 gpu_trace_level_(2),
2598 gpu_trace_commands_(false),
2599 gpu_debug_commands_(false),
2600 validation_texture_(0),
2601 validation_fbo_multisample_(0),
2602 validation_fbo_(0) {
2605 // The shader translator is used for WebGL even when running on EGL
2606 // because additional restrictions are needed (like only enabling
2607 // GL_OES_standard_derivatives on demand). It is used for the unit
2608 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2609 // the empty string to CompileShader and this is not a valid shader.
2610 bool disable_translator
=
2611 base::CommandLine::InitializedForCurrentProcess()
2612 ? base::CommandLine::ForCurrentProcess()->HasSwitch(
2613 switches::kDisableGLSLTranslator
)
2615 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL
||
2616 disable_translator
) {
2617 use_shader_translator_
= false;
2621 GLES2DecoderImpl::~GLES2DecoderImpl() {
2624 bool GLES2DecoderImpl::Initialize(
2625 const scoped_refptr
<gfx::GLSurface
>& surface
,
2626 const scoped_refptr
<gfx::GLContext
>& context
,
2628 const gfx::Size
& offscreen_size
,
2629 const DisallowedFeatures
& disallowed_features
,
2630 const std::vector
<int32
>& attribs
) {
2631 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2632 DCHECK(context
->IsCurrent(surface
.get()));
2633 DCHECK(!context_
.get());
2634 DCHECK(!offscreen
|| !offscreen_size
.IsEmpty());
2636 ContextCreationAttribHelper attrib_parser
;
2637 if (!attrib_parser
.Parse(attribs
))
2639 webgl_version_
= attrib_parser
.webgl_version
;
2641 surfaceless_
= surface
->IsSurfaceless() && !offscreen
;
2644 gpu_state_tracer_
= GPUStateTracer::Create(&state_
);
2646 if (base::CommandLine::InitializedForCurrentProcess()) {
2647 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2648 switches::kEnableGPUDebugging
)) {
2652 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2653 switches::kEnableGPUCommandLogging
)) {
2654 set_log_commands(true);
2657 compile_shader_always_succeeds_
=
2658 base::CommandLine::ForCurrentProcess()->HasSwitch(
2659 switches::kCompileShaderAlwaysSucceeds
);
2662 // Take ownership of the context and surface. The surface can be replaced with
2667 // Create GPU Tracer for timing values.
2668 gpu_tracer_
.reset(new GPUTracer(this));
2670 if (feature_info_
->workarounds().disable_timestamp_queries
) {
2671 // Forcing time elapsed query for any GPU Timing Client forces it for all
2672 // clients in the context.
2673 GetGLContext()->CreateGPUTimingClient()->ForceTimeElapsedQuery();
2676 // Save the loseContextWhenOutOfMemory context creation attribute.
2677 lose_context_when_out_of_memory_
=
2678 attrib_parser
.lose_context_when_out_of_memory
;
2680 // If the failIfMajorPerformanceCaveat context creation attribute was true
2681 // and we are using a software renderer, fail.
2682 if (attrib_parser
.fail_if_major_perf_caveat
&&
2683 feature_info_
->feature_flags().is_swiftshader
) {
2684 group_
= NULL
; // Must not destroy ContextGroup if it is not initialized.
2689 disallowed_features_
= disallowed_features
;
2690 if (webgl_version_
== 1) {
2691 disallowed_features_
.npot_support
= true;
2694 if (!group_
->Initialize(this,
2695 ContextGroup::GetContextType(webgl_version_
),
2696 disallowed_features_
)) {
2697 group_
= NULL
; // Must not destroy ContextGroup if it is not initialized.
2703 if (webgl_version_
== 2) {
2704 if (!feature_info_
->IsES3Capable()) {
2705 LOG(ERROR
) << "Underlying driver does not support ES3.";
2709 feature_info_
->EnableES3Validators();
2710 set_unsafe_es3_apis_enabled(true);
2713 state_
.attrib_values
.resize(group_
->max_vertex_attribs());
2714 vertex_array_manager_
.reset(new VertexArrayManager());
2716 GLuint default_vertex_attrib_service_id
= 0;
2717 if (features().native_vertex_array_object
) {
2718 glGenVertexArraysOES(1, &default_vertex_attrib_service_id
);
2719 glBindVertexArrayOES(default_vertex_attrib_service_id
);
2722 state_
.default_vertex_attrib_manager
=
2723 CreateVertexAttribManager(0, default_vertex_attrib_service_id
, false);
2725 state_
.default_vertex_attrib_manager
->Initialize(
2726 group_
->max_vertex_attribs(),
2727 feature_info_
->workarounds().init_vertex_attributes
);
2729 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2730 DoBindVertexArrayOES(0);
2732 query_manager_
.reset(new QueryManager(this, feature_info_
.get()));
2734 image_manager_
.reset(new ImageManager
);
2736 util_
.set_num_compressed_texture_formats(
2737 validators_
->compressed_texture_format
.GetValues().size());
2739 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
2740 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2741 // OpenGL ES 2.0 does not have this issue.
2742 glEnableVertexAttribArray(0);
2744 glGenBuffersARB(1, &attrib_0_buffer_id_
);
2745 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
2746 glVertexAttribPointer(0, 1, GL_FLOAT
, GL_FALSE
, 0, NULL
);
2747 glBindBuffer(GL_ARRAY_BUFFER
, 0);
2748 glGenBuffersARB(1, &fixed_attrib_buffer_id_
);
2750 state_
.texture_units
.resize(group_
->max_texture_units());
2751 for (uint32 tt
= 0; tt
< state_
.texture_units
.size(); ++tt
) {
2752 glActiveTexture(GL_TEXTURE0
+ tt
);
2753 // We want the last bind to be 2D.
2755 if (features().oes_egl_image_external
) {
2756 ref
= texture_manager()->GetDefaultTextureInfo(
2757 GL_TEXTURE_EXTERNAL_OES
);
2758 state_
.texture_units
[tt
].bound_texture_external_oes
= ref
;
2759 glBindTexture(GL_TEXTURE_EXTERNAL_OES
, ref
? ref
->service_id() : 0);
2761 if (features().arb_texture_rectangle
) {
2762 ref
= texture_manager()->GetDefaultTextureInfo(
2763 GL_TEXTURE_RECTANGLE_ARB
);
2764 state_
.texture_units
[tt
].bound_texture_rectangle_arb
= ref
;
2765 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, ref
? ref
->service_id() : 0);
2767 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP
);
2768 state_
.texture_units
[tt
].bound_texture_cube_map
= ref
;
2769 glBindTexture(GL_TEXTURE_CUBE_MAP
, ref
? ref
->service_id() : 0);
2770 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D
);
2771 state_
.texture_units
[tt
].bound_texture_2d
= ref
;
2772 glBindTexture(GL_TEXTURE_2D
, ref
? ref
->service_id() : 0);
2774 glActiveTexture(GL_TEXTURE0
);
2777 // cache ALPHA_BITS result for re-use with clear behaviour
2778 GLint alpha_bits
= 0;
2781 if (attrib_parser
.samples
> 0 && attrib_parser
.sample_buffers
> 0 &&
2782 features().chromium_framebuffer_multisample
) {
2783 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2784 // max_sample_count must be initialized to a sane value. If
2785 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2786 GLint max_sample_count
= 1;
2787 glGetIntegerv(GL_MAX_SAMPLES_EXT
, &max_sample_count
);
2788 offscreen_target_samples_
= std::min(attrib_parser
.samples
,
2791 offscreen_target_samples_
= 1;
2793 offscreen_target_buffer_preserved_
= attrib_parser
.buffer_preserved
;
2795 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
2796 const bool rgb8_supported
=
2797 context_
->HasExtension("GL_OES_rgb8_rgba8");
2798 // The only available default render buffer formats in GLES2 have very
2799 // little precision. Don't enable multisampling unless 8-bit render
2800 // buffer formats are available--instead fall back to 8-bit textures.
2801 if (rgb8_supported
&& offscreen_target_samples_
> 1) {
2802 offscreen_target_color_format_
= attrib_parser
.alpha_size
> 0 ?
2805 offscreen_target_samples_
= 1;
2806 offscreen_target_color_format_
=
2807 attrib_parser
.alpha_size
> 0 || workarounds().disable_gl_rgb_format
2812 // ANGLE only supports packed depth/stencil formats, so use it if it is
2814 const bool depth24_stencil8_supported
=
2815 feature_info_
->feature_flags().packed_depth24_stencil8
;
2816 VLOG(1) << "GL_OES_packed_depth_stencil "
2817 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2818 if ((attrib_parser
.depth_size
> 0 || attrib_parser
.stencil_size
> 0) &&
2819 depth24_stencil8_supported
) {
2820 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2821 offscreen_target_stencil_format_
= 0;
2823 // It may be the case that this depth/stencil combination is not
2824 // supported, but this will be checked later by CheckFramebufferStatus.
2825 offscreen_target_depth_format_
= attrib_parser
.depth_size
> 0 ?
2826 GL_DEPTH_COMPONENT16
: 0;
2827 offscreen_target_stencil_format_
= attrib_parser
.stencil_size
> 0 ?
2828 GL_STENCIL_INDEX8
: 0;
2831 offscreen_target_color_format_
=
2832 attrib_parser
.alpha_size
> 0 || workarounds().disable_gl_rgb_format
2836 // If depth is requested at all, use the packed depth stencil format if
2837 // it's available, as some desktop GL drivers don't support any non-packed
2838 // formats for depth attachments.
2839 const bool depth24_stencil8_supported
=
2840 feature_info_
->feature_flags().packed_depth24_stencil8
;
2841 VLOG(1) << "GL_EXT_packed_depth_stencil "
2842 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2844 if ((attrib_parser
.depth_size
> 0 || attrib_parser
.stencil_size
> 0) &&
2845 depth24_stencil8_supported
) {
2846 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2847 offscreen_target_stencil_format_
= 0;
2849 offscreen_target_depth_format_
= attrib_parser
.depth_size
> 0 ?
2850 GL_DEPTH_COMPONENT
: 0;
2851 offscreen_target_stencil_format_
= attrib_parser
.stencil_size
> 0 ?
2852 GL_STENCIL_INDEX
: 0;
2856 offscreen_saved_color_format_
=
2857 attrib_parser
.alpha_size
> 0 || workarounds().disable_gl_rgb_format
2861 // Create the target frame buffer. This is the one that the client renders
2863 offscreen_target_frame_buffer_
.reset(new BackFramebuffer(this));
2864 offscreen_target_frame_buffer_
->Create();
2865 // Due to GLES2 format limitations, either the color texture (for
2866 // non-multisampling) or the color render buffer (for multisampling) will be
2867 // attached to the offscreen frame buffer. The render buffer has more
2868 // limited formats available to it, but the texture can't do multisampling.
2869 if (IsOffscreenBufferMultisampled()) {
2870 offscreen_target_color_render_buffer_
.reset(new BackRenderbuffer(
2871 renderbuffer_manager(), memory_tracker(), &state_
));
2872 offscreen_target_color_render_buffer_
->Create();
2874 offscreen_target_color_texture_
.reset(new BackTexture(
2875 memory_tracker(), &state_
));
2876 offscreen_target_color_texture_
->Create();
2878 offscreen_target_depth_render_buffer_
.reset(new BackRenderbuffer(
2879 renderbuffer_manager(), memory_tracker(), &state_
));
2880 offscreen_target_depth_render_buffer_
->Create();
2881 offscreen_target_stencil_render_buffer_
.reset(new BackRenderbuffer(
2882 renderbuffer_manager(), memory_tracker(), &state_
));
2883 offscreen_target_stencil_render_buffer_
->Create();
2885 // Create the saved offscreen texture. The target frame buffer is copied
2886 // here when SwapBuffers is called.
2887 offscreen_saved_frame_buffer_
.reset(new BackFramebuffer(this));
2888 offscreen_saved_frame_buffer_
->Create();
2890 offscreen_saved_color_texture_
.reset(new BackTexture(
2891 memory_tracker(), &state_
));
2892 offscreen_saved_color_texture_
->Create();
2894 // Allocate the render buffers at their initial size and check the status
2895 // of the frame buffers is okay.
2896 if (!ResizeOffscreenFrameBuffer(offscreen_size
)) {
2897 LOG(ERROR
) << "Could not allocate offscreen buffer storage.";
2902 state_
.viewport_width
= offscreen_size
.width();
2903 state_
.viewport_height
= offscreen_size
.height();
2905 // Allocate the offscreen saved color texture.
2906 DCHECK(offscreen_saved_color_format_
);
2907 offscreen_saved_color_texture_
->AllocateStorage(
2908 gfx::Size(1, 1), offscreen_saved_color_format_
, true);
2910 offscreen_saved_frame_buffer_
->AttachRenderTexture(
2911 offscreen_saved_color_texture_
.get());
2912 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
2913 GL_FRAMEBUFFER_COMPLETE
) {
2914 LOG(ERROR
) << "Offscreen saved FBO was incomplete.";
2919 // Bind to the new default frame buffer (the offscreen target frame buffer).
2920 // This should now be associated with ID zero.
2921 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
2923 glBindFramebufferEXT(GL_FRAMEBUFFER
, GetBackbufferServiceId());
2924 // These are NOT if the back buffer has these proprorties. They are
2925 // if we want the command buffer to enforce them regardless of what
2926 // the real backbuffer is assuming the real back buffer gives us more than
2927 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2928 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2929 // can't do anything about that.
2931 if (!surfaceless_
) {
2932 GLint depth_bits
= 0;
2933 GLint stencil_bits
= 0;
2935 bool default_fb
= (GetBackbufferServiceId() == 0);
2937 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
2938 glGetFramebufferAttachmentParameterivEXT(
2940 default_fb
? GL_BACK_LEFT
: GL_COLOR_ATTACHMENT0
,
2941 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE
, &alpha_bits
);
2942 glGetFramebufferAttachmentParameterivEXT(
2944 default_fb
? GL_DEPTH
: GL_DEPTH_ATTACHMENT
,
2945 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE
, &depth_bits
);
2946 glGetFramebufferAttachmentParameterivEXT(
2948 default_fb
? GL_STENCIL
: GL_STENCIL_ATTACHMENT
,
2949 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE
, &stencil_bits
);
2951 glGetIntegerv(GL_ALPHA_BITS
, &alpha_bits
);
2952 glGetIntegerv(GL_DEPTH_BITS
, &depth_bits
);
2953 glGetIntegerv(GL_STENCIL_BITS
, &stencil_bits
);
2956 // This checks if the user requested RGBA and we have RGBA then RGBA. If
2957 // the user requested RGB then RGB. If the user did not specify a
2958 // preference than use whatever we were given. Same for DEPTH and STENCIL.
2959 back_buffer_color_format_
=
2960 (attrib_parser
.alpha_size
!= 0 && alpha_bits
> 0) ? GL_RGBA
: GL_RGB
;
2961 back_buffer_has_depth_
= attrib_parser
.depth_size
!= 0 && depth_bits
> 0;
2962 back_buffer_has_stencil_
=
2963 attrib_parser
.stencil_size
!= 0 && stencil_bits
> 0;
2966 state_
.viewport_width
= surface
->GetSize().width();
2967 state_
.viewport_height
= surface
->GetSize().height();
2970 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2971 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2972 // isn't well documented; it was discovered in the Khronos OpenGL ES
2973 // mailing list archives. It also implicitly enables the desktop GL
2974 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2975 // variable in fragment shaders.
2976 if (!feature_info_
->gl_version_info().BehavesLikeGLES()) {
2977 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE
);
2978 glEnable(GL_POINT_SPRITE
);
2981 has_robustness_extension_
=
2982 context
->HasExtension("GL_ARB_robustness") ||
2983 context
->HasExtension("GL_KHR_robustness") ||
2984 context
->HasExtension("GL_EXT_robustness");
2986 if (!InitializeShaderTranslator()) {
2990 GLint viewport_params
[4] = { 0 };
2991 glGetIntegerv(GL_MAX_VIEWPORT_DIMS
, viewport_params
);
2992 viewport_max_width_
= viewport_params
[0];
2993 viewport_max_height_
= viewport_params
[1];
2995 state_
.scissor_width
= state_
.viewport_width
;
2996 state_
.scissor_height
= state_
.viewport_height
;
2998 // Set all the default state because some GL drivers get it wrong.
2999 state_
.InitCapabilities(NULL
);
3000 state_
.InitState(NULL
);
3001 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
3003 DoBindBuffer(GL_ARRAY_BUFFER
, 0);
3004 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
3005 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
3006 DoBindRenderbuffer(GL_RENDERBUFFER
, 0);
3007 DoBindValueBufferCHROMIUM(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM
, 0);
3009 bool call_gl_clear
= !surfaceless_
;
3010 #if defined(OS_ANDROID)
3011 // Temporary workaround for Android WebView because this clear ignores the
3012 // clip and corrupts that external UI of the App. Not calling glClear is ok
3013 // because the system already clears the buffer before each draw. Proper
3014 // fix might be setting the scissor clip properly before initialize. See
3015 // crbug.com/259023 for details.
3016 call_gl_clear
= surface_
->GetHandle();
3018 if (call_gl_clear
) {
3019 // On configs where we report no alpha, if the underlying surface has
3020 // alpha, clear the surface alpha to 1.0 to be correct on ReadPixels/etc.
3021 bool clear_alpha
= back_buffer_color_format_
== GL_RGB
&& alpha_bits
> 0;
3023 glClearColor(0.0f
, 0.0f
, 0.0f
, 1.0f
);
3026 // Clear the backbuffer.
3027 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
3029 // Restore alpha clear value if we changed it.
3031 glClearColor(0.0f
, 0.0f
, 0.0f
, 0.0f
);
3035 supports_post_sub_buffer_
= surface
->SupportsPostSubBuffer();
3036 if (feature_info_
->workarounds()
3037 .disable_post_sub_buffers_for_onscreen_surfaces
&&
3038 !surface
->IsOffscreen())
3039 supports_post_sub_buffer_
= false;
3041 if (feature_info_
->workarounds().reverse_point_sprite_coord_origin
) {
3042 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN
, GL_LOWER_LEFT
);
3045 if (feature_info_
->workarounds().unbind_fbo_on_context_switch
) {
3046 context_
->SetUnbindFboOnMakeCurrent();
3049 // Only compositor contexts are known to use only the subset of GL
3050 // that can be safely migrated between the iGPU and the dGPU. Mark
3051 // those contexts as safe to forcibly transition between the GPUs.
3052 // http://crbug.com/180876, http://crbug.com/227228
3054 context_
->SetSafeToForceGpuSwitch();
3056 async_pixel_transfer_manager_
.reset(
3057 AsyncPixelTransferManager::Create(context
.get()));
3058 async_pixel_transfer_manager_
->Initialize(texture_manager());
3060 if (workarounds().gl_clear_broken
) {
3061 DCHECK(!clear_framebuffer_blit_
.get());
3062 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glClearWorkaroundInit");
3063 clear_framebuffer_blit_
.reset(new ClearFramebufferResourceManager(this));
3064 if (LOCAL_PEEK_GL_ERROR("glClearWorkaroundInit") != GL_NO_ERROR
)
3068 framebuffer_manager()->AddObserver(this);
3073 Capabilities
GLES2DecoderImpl::GetCapabilities() {
3074 DCHECK(initialized());
3076 caps
.VisitPrecisions([](GLenum shader
, GLenum type
,
3077 Capabilities::ShaderPrecision
* shader_precision
) {
3078 GLint range
[2] = {0, 0};
3079 GLint precision
= 0;
3080 GetShaderPrecisionFormatImpl(shader
, type
, range
, &precision
);
3081 shader_precision
->min_range
= range
[0];
3082 shader_precision
->max_range
= range
[1];
3083 shader_precision
->precision
= precision
;
3085 DoGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
,
3086 &caps
.max_combined_texture_image_units
);
3087 DoGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE
, &caps
.max_cube_map_texture_size
);
3088 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS
,
3089 &caps
.max_fragment_uniform_vectors
);
3090 DoGetIntegerv(GL_MAX_RENDERBUFFER_SIZE
, &caps
.max_renderbuffer_size
);
3091 DoGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS
, &caps
.max_texture_image_units
);
3092 DoGetIntegerv(GL_MAX_TEXTURE_SIZE
, &caps
.max_texture_size
);
3093 DoGetIntegerv(GL_MAX_VARYING_VECTORS
, &caps
.max_varying_vectors
);
3094 DoGetIntegerv(GL_MAX_VERTEX_ATTRIBS
, &caps
.max_vertex_attribs
);
3095 DoGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS
,
3096 &caps
.max_vertex_texture_image_units
);
3097 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS
,
3098 &caps
.max_vertex_uniform_vectors
);
3099 DoGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS
,
3100 &caps
.num_compressed_texture_formats
);
3101 DoGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS
, &caps
.num_shader_binary_formats
);
3102 DoGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM
,
3103 &caps
.bind_generates_resource_chromium
);
3104 if (unsafe_es3_apis_enabled()) {
3105 // TODO(zmo): Note that some parameter values could be more than 32-bit,
3106 // but for now we clamp them to 32-bit max.
3107 DoGetIntegerv(GL_MAX_3D_TEXTURE_SIZE
, &caps
.max_3d_texture_size
);
3108 DoGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS
, &caps
.max_array_texture_layers
);
3109 DoGetIntegerv(GL_MAX_COLOR_ATTACHMENTS
, &caps
.max_color_attachments
);
3110 DoGetInteger64v(GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS
,
3111 &caps
.max_combined_fragment_uniform_components
);
3112 DoGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS
,
3113 &caps
.max_combined_uniform_blocks
);
3114 DoGetInteger64v(GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS
,
3115 &caps
.max_combined_vertex_uniform_components
);
3116 DoGetIntegerv(GL_MAX_DRAW_BUFFERS
, &caps
.max_draw_buffers
);
3117 DoGetInteger64v(GL_MAX_ELEMENT_INDEX
, &caps
.max_element_index
);
3118 DoGetIntegerv(GL_MAX_ELEMENTS_INDICES
, &caps
.max_elements_indices
);
3119 DoGetIntegerv(GL_MAX_ELEMENTS_VERTICES
, &caps
.max_elements_vertices
);
3120 DoGetIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS
,
3121 &caps
.max_fragment_input_components
);
3122 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS
,
3123 &caps
.max_fragment_uniform_blocks
);
3124 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS
,
3125 &caps
.max_fragment_uniform_components
);
3126 DoGetIntegerv(GL_MAX_PROGRAM_TEXEL_OFFSET
,
3127 &caps
.max_program_texel_offset
);
3128 DoGetInteger64v(GL_MAX_SERVER_WAIT_TIMEOUT
, &caps
.max_server_wait_timeout
);
3129 // Work around Linux NVIDIA driver bug where GL_TIMEOUT_IGNORED is
3131 if (caps
.max_server_wait_timeout
< 0)
3132 caps
.max_server_wait_timeout
= 0;
3133 DoGetFloatv(GL_MAX_TEXTURE_LOD_BIAS
, &caps
.max_texture_lod_bias
);
3134 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS
,
3135 &caps
.max_transform_feedback_interleaved_components
);
3136 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS
,
3137 &caps
.max_transform_feedback_separate_attribs
);
3138 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS
,
3139 &caps
.max_transform_feedback_separate_components
);
3140 DoGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE
, &caps
.max_uniform_block_size
);
3141 DoGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS
,
3142 &caps
.max_uniform_buffer_bindings
);
3143 DoGetIntegerv(GL_MAX_VARYING_COMPONENTS
, &caps
.max_varying_components
);
3144 DoGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS
,
3145 &caps
.max_vertex_output_components
);
3146 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS
,
3147 &caps
.max_vertex_uniform_blocks
);
3148 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS
,
3149 &caps
.max_vertex_uniform_components
);
3150 DoGetIntegerv(GL_MIN_PROGRAM_TEXEL_OFFSET
, &caps
.min_program_texel_offset
);
3151 DoGetIntegerv(GL_NUM_EXTENSIONS
, &caps
.num_extensions
);
3152 DoGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS
,
3153 &caps
.num_program_binary_formats
);
3154 DoGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
,
3155 &caps
.uniform_buffer_offset_alignment
);
3156 // TODO(zmo): once we switch to MANGLE, we should query version numbers.
3157 caps
.major_version
= 3;
3158 caps
.minor_version
= 0;
3160 if (feature_info_
->feature_flags().multisampled_render_to_texture
||
3161 feature_info_
->feature_flags().chromium_framebuffer_multisample
||
3162 unsafe_es3_apis_enabled()) {
3163 DoGetIntegerv(GL_MAX_SAMPLES
, &caps
.max_samples
);
3166 caps
.egl_image_external
=
3167 feature_info_
->feature_flags().oes_egl_image_external
;
3168 caps
.texture_format_atc
=
3169 feature_info_
->feature_flags().ext_texture_format_atc
;
3170 caps
.texture_format_bgra8888
=
3171 feature_info_
->feature_flags().ext_texture_format_bgra8888
;
3172 caps
.texture_format_dxt1
=
3173 feature_info_
->feature_flags().ext_texture_format_dxt1
;
3174 caps
.texture_format_dxt5
=
3175 feature_info_
->feature_flags().ext_texture_format_dxt5
;
3176 caps
.texture_format_etc1
=
3177 feature_info_
->feature_flags().oes_compressed_etc1_rgb8_texture
;
3178 caps
.texture_format_etc1_npot
=
3179 caps
.texture_format_etc1
&& !workarounds().etc1_power_of_two_only
;
3180 caps
.texture_rectangle
= feature_info_
->feature_flags().arb_texture_rectangle
;
3181 caps
.texture_usage
= feature_info_
->feature_flags().angle_texture_usage
;
3182 caps
.texture_storage
= feature_info_
->feature_flags().ext_texture_storage
;
3183 caps
.discard_framebuffer
=
3184 feature_info_
->feature_flags().ext_discard_framebuffer
;
3185 caps
.sync_query
= feature_info_
->feature_flags().chromium_sync_query
;
3187 #if defined(OS_MACOSX)
3188 // This is unconditionally true on mac, no need to test for it at runtime.
3189 caps
.iosurface
= true;
3192 caps
.post_sub_buffer
= supports_post_sub_buffer_
;
3194 caps
.surfaceless
= surfaceless_
;
3196 caps
.blend_equation_advanced
=
3197 feature_info_
->feature_flags().blend_equation_advanced
;
3198 caps
.blend_equation_advanced_coherent
=
3199 feature_info_
->feature_flags().blend_equation_advanced_coherent
;
3200 caps
.texture_rg
= feature_info_
->feature_flags().ext_texture_rg
;
3201 caps
.image_ycbcr_422
=
3202 feature_info_
->feature_flags().chromium_image_ycbcr_422
;
3203 caps
.max_copy_texture_chromium_size
=
3204 feature_info_
->workarounds().max_copy_texture_chromium_size
;
3205 caps
.render_buffer_format_bgra8888
=
3206 feature_info_
->feature_flags().ext_render_buffer_format_bgra8888
;
3207 caps
.occlusion_query_boolean
=
3208 feature_info_
->feature_flags().occlusion_query_boolean
;
3209 caps
.timer_queries
=
3210 query_manager_
->GPUTimingAvailable();
3214 void GLES2DecoderImpl::UpdateCapabilities() {
3215 util_
.set_num_compressed_texture_formats(
3216 validators_
->compressed_texture_format
.GetValues().size());
3217 util_
.set_num_shader_binary_formats(
3218 validators_
->shader_binary_format
.GetValues().size());
3221 bool GLES2DecoderImpl::InitializeShaderTranslator() {
3222 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
3224 if (!use_shader_translator_
) {
3227 ShBuiltInResources resources
;
3228 ShInitBuiltInResources(&resources
);
3229 resources
.MaxVertexAttribs
= group_
->max_vertex_attribs();
3230 resources
.MaxVertexUniformVectors
=
3231 group_
->max_vertex_uniform_vectors();
3232 resources
.MaxVaryingVectors
= group_
->max_varying_vectors();
3233 resources
.MaxVertexTextureImageUnits
=
3234 group_
->max_vertex_texture_image_units();
3235 resources
.MaxCombinedTextureImageUnits
= group_
->max_texture_units();
3236 resources
.MaxTextureImageUnits
= group_
->max_texture_image_units();
3237 resources
.MaxFragmentUniformVectors
=
3238 group_
->max_fragment_uniform_vectors();
3239 resources
.MaxDrawBuffers
= group_
->max_draw_buffers();
3240 resources
.MaxExpressionComplexity
= 256;
3241 resources
.MaxCallStackDepth
= 256;
3243 GLint range
[2] = { 0, 0 };
3244 GLint precision
= 0;
3245 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER
, GL_HIGH_FLOAT
,
3247 resources
.FragmentPrecisionHigh
=
3248 PrecisionMeetsSpecForHighpFloat(range
[0], range
[1], precision
);
3250 if (IsWebGLContext()) {
3251 resources
.OES_standard_derivatives
= derivatives_explicitly_enabled_
;
3252 resources
.EXT_frag_depth
= frag_depth_explicitly_enabled_
;
3253 resources
.EXT_draw_buffers
= draw_buffers_explicitly_enabled_
;
3254 if (!draw_buffers_explicitly_enabled_
)
3255 resources
.MaxDrawBuffers
= 1;
3256 resources
.EXT_shader_texture_lod
= shader_texture_lod_explicitly_enabled_
;
3257 resources
.NV_draw_buffers
=
3258 draw_buffers_explicitly_enabled_
&& features().nv_draw_buffers
;
3260 resources
.OES_standard_derivatives
=
3261 features().oes_standard_derivatives
? 1 : 0;
3262 resources
.ARB_texture_rectangle
=
3263 features().arb_texture_rectangle
? 1 : 0;
3264 resources
.OES_EGL_image_external
=
3265 features().oes_egl_image_external
? 1 : 0;
3266 resources
.EXT_draw_buffers
=
3267 features().ext_draw_buffers
? 1 : 0;
3268 resources
.EXT_frag_depth
=
3269 features().ext_frag_depth
? 1 : 0;
3270 resources
.EXT_shader_texture_lod
=
3271 features().ext_shader_texture_lod
? 1 : 0;
3272 resources
.NV_draw_buffers
=
3273 features().nv_draw_buffers
? 1 : 0;
3276 ShShaderSpec shader_spec
;
3277 if (IsWebGLContext()) {
3278 shader_spec
= webgl_version_
== 2 ? SH_WEBGL2_SPEC
: SH_WEBGL_SPEC
;
3280 shader_spec
= unsafe_es3_apis_enabled() ? SH_GLES3_SPEC
: SH_GLES2_SPEC
;
3283 if ((shader_spec
== SH_WEBGL_SPEC
|| shader_spec
== SH_WEBGL2_SPEC
) &&
3284 features().enable_shader_name_hashing
)
3285 resources
.HashFunction
= &CityHash64
;
3287 resources
.HashFunction
= NULL
;
3289 int driver_bug_workarounds
= 0;
3290 if (workarounds().needs_glsl_built_in_function_emulation
)
3291 driver_bug_workarounds
|= SH_EMULATE_BUILT_IN_FUNCTIONS
;
3292 if (workarounds().init_gl_position_in_vertex_shader
)
3293 driver_bug_workarounds
|= SH_INIT_GL_POSITION
;
3294 if (workarounds().unfold_short_circuit_as_ternary_operation
)
3295 driver_bug_workarounds
|= SH_UNFOLD_SHORT_CIRCUIT
;
3296 if (workarounds().init_varyings_without_static_use
)
3297 driver_bug_workarounds
|= SH_INIT_VARYINGS_WITHOUT_STATIC_USE
;
3298 if (workarounds().unroll_for_loop_with_sampler_array_index
)
3299 driver_bug_workarounds
|= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX
;
3300 if (workarounds().scalarize_vec_and_mat_constructor_args
)
3301 driver_bug_workarounds
|= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS
;
3302 if (workarounds().regenerate_struct_names
)
3303 driver_bug_workarounds
|= SH_REGENERATE_STRUCT_NAMES
;
3304 if (workarounds().remove_pow_with_constant_exponent
)
3305 driver_bug_workarounds
|= SH_REMOVE_POW_WITH_CONSTANT_EXPONENT
;
3307 if (base::CommandLine::InitializedForCurrentProcess() &&
3308 base::CommandLine::ForCurrentProcess()->HasSwitch(
3309 switches::kEmulateShaderPrecision
))
3310 resources
.WEBGL_debug_shader_precision
= true;
3312 ShShaderOutput shader_output_language
=
3313 ShaderTranslator::GetShaderOutputLanguageForContext(
3314 feature_info_
->gl_version_info());
3316 vertex_translator_
= shader_translator_cache()->GetTranslator(
3317 GL_VERTEX_SHADER
, shader_spec
, &resources
, shader_output_language
,
3318 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
3319 if (!vertex_translator_
.get()) {
3320 LOG(ERROR
) << "Could not initialize vertex shader translator.";
3325 fragment_translator_
= shader_translator_cache()->GetTranslator(
3326 GL_FRAGMENT_SHADER
, shader_spec
, &resources
, shader_output_language
,
3327 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
3328 if (!fragment_translator_
.get()) {
3329 LOG(ERROR
) << "Could not initialize fragment shader translator.";
3336 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n
, const GLuint
* client_ids
) {
3337 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3338 if (GetBuffer(client_ids
[ii
])) {
3342 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3343 glGenBuffersARB(n
, service_ids
.get());
3344 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3345 CreateBuffer(client_ids
[ii
], service_ids
[ii
]);
3350 bool GLES2DecoderImpl::GenFramebuffersHelper(
3351 GLsizei n
, const GLuint
* client_ids
) {
3352 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3353 if (GetFramebuffer(client_ids
[ii
])) {
3357 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3358 glGenFramebuffersEXT(n
, service_ids
.get());
3359 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3360 CreateFramebuffer(client_ids
[ii
], service_ids
[ii
]);
3365 bool GLES2DecoderImpl::GenRenderbuffersHelper(
3366 GLsizei n
, const GLuint
* client_ids
) {
3367 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3368 if (GetRenderbuffer(client_ids
[ii
])) {
3372 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3373 glGenRenderbuffersEXT(n
, service_ids
.get());
3374 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3375 CreateRenderbuffer(client_ids
[ii
], service_ids
[ii
]);
3380 bool GLES2DecoderImpl::GenValuebuffersCHROMIUMHelper(GLsizei n
,
3381 const GLuint
* client_ids
) {
3382 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3383 if (GetValuebuffer(client_ids
[ii
])) {
3387 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3388 CreateValuebuffer(client_ids
[ii
]);
3393 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n
, const GLuint
* client_ids
) {
3394 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3395 if (GetTexture(client_ids
[ii
])) {
3399 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3400 glGenTextures(n
, service_ids
.get());
3401 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3402 CreateTexture(client_ids
[ii
], service_ids
[ii
]);
3407 bool GLES2DecoderImpl::GenPathsCHROMIUMHelper(GLuint first_client_id
,
3409 GLuint last_client_id
;
3410 if (!SafeAddUint32(first_client_id
, range
- 1, &last_client_id
))
3413 if (path_manager()->HasPathsInRange(first_client_id
, last_client_id
))
3416 GLuint first_service_id
= glGenPathsNV(range
);
3417 if (first_service_id
== 0) {
3418 // We have to fail the connection here, because client has already
3419 // succeeded in allocating the ids. This happens if we allocate
3420 // the whole path id space (two allocations of 0x7FFFFFFF paths, for
3424 // GenPathsNV does not wrap.
3425 DCHECK(first_service_id
+ range
- 1 >= first_service_id
);
3427 path_manager()->CreatePathRange(first_client_id
, last_client_id
,
3433 bool GLES2DecoderImpl::DeletePathsCHROMIUMHelper(GLuint first_client_id
,
3435 GLuint last_client_id
;
3436 if (!SafeAddUint32(first_client_id
, range
- 1, &last_client_id
))
3439 path_manager()->RemovePaths(first_client_id
, last_client_id
);
3443 void GLES2DecoderImpl::DeleteBuffersHelper(
3444 GLsizei n
, const GLuint
* client_ids
) {
3445 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3446 Buffer
* buffer
= GetBuffer(client_ids
[ii
]);
3447 if (buffer
&& !buffer
->IsDeleted()) {
3448 buffer
->RemoveMappedRange();
3449 state_
.RemoveBoundBuffer(buffer
);
3450 RemoveBuffer(client_ids
[ii
]);
3455 void GLES2DecoderImpl::DeleteFramebuffersHelper(
3456 GLsizei n
, const GLuint
* client_ids
) {
3457 bool supports_separate_framebuffer_binds
=
3458 features().chromium_framebuffer_multisample
;
3460 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3461 Framebuffer
* framebuffer
=
3462 GetFramebuffer(client_ids
[ii
]);
3463 if (framebuffer
&& !framebuffer
->IsDeleted()) {
3464 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
3465 GLenum target
= supports_separate_framebuffer_binds
?
3466 GL_DRAW_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
3468 // Unbind attachments on FBO before deletion.
3469 if (workarounds().unbind_attachments_on_bound_render_fbo_delete
)
3470 framebuffer
->DoUnbindGLAttachmentsForWorkaround(target
);
3472 glBindFramebufferEXT(target
, GetBackbufferServiceId());
3473 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
3474 framebuffer_state_
.clear_state_dirty
= true;
3476 if (framebuffer
== framebuffer_state_
.bound_read_framebuffer
.get()) {
3477 framebuffer_state_
.bound_read_framebuffer
= NULL
;
3478 GLenum target
= supports_separate_framebuffer_binds
?
3479 GL_READ_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
3480 glBindFramebufferEXT(target
, GetBackbufferServiceId());
3483 RemoveFramebuffer(client_ids
[ii
]);
3488 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
3489 GLsizei n
, const GLuint
* client_ids
) {
3490 bool supports_separate_framebuffer_binds
=
3491 features().chromium_framebuffer_multisample
;
3492 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3493 Renderbuffer
* renderbuffer
=
3494 GetRenderbuffer(client_ids
[ii
]);
3495 if (renderbuffer
&& !renderbuffer
->IsDeleted()) {
3496 if (state_
.bound_renderbuffer
.get() == renderbuffer
) {
3497 state_
.bound_renderbuffer
= NULL
;
3499 // Unbind from current framebuffers.
3500 if (supports_separate_framebuffer_binds
) {
3501 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
3502 framebuffer_state_
.bound_read_framebuffer
3503 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT
, renderbuffer
);
3505 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3506 framebuffer_state_
.bound_draw_framebuffer
3507 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT
, renderbuffer
);
3510 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3511 framebuffer_state_
.bound_draw_framebuffer
3512 ->UnbindRenderbuffer(GL_FRAMEBUFFER
, renderbuffer
);
3515 framebuffer_state_
.clear_state_dirty
= true;
3516 RemoveRenderbuffer(client_ids
[ii
]);
3521 void GLES2DecoderImpl::DeleteValuebuffersCHROMIUMHelper(
3523 const GLuint
* client_ids
) {
3524 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3525 Valuebuffer
* valuebuffer
= GetValuebuffer(client_ids
[ii
]);
3527 if (state_
.bound_valuebuffer
.get() == valuebuffer
) {
3528 state_
.bound_valuebuffer
= NULL
;
3530 RemoveValuebuffer(client_ids
[ii
]);
3535 void GLES2DecoderImpl::DeleteTexturesHelper(
3536 GLsizei n
, const GLuint
* client_ids
) {
3537 bool supports_separate_framebuffer_binds
=
3538 features().chromium_framebuffer_multisample
;
3539 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3540 TextureRef
* texture_ref
= GetTexture(client_ids
[ii
]);
3542 Texture
* texture
= texture_ref
->texture();
3543 if (texture
->IsAttachedToFramebuffer()) {
3544 framebuffer_state_
.clear_state_dirty
= true;
3546 // Unbind texture_ref from texture_ref units.
3547 for (size_t jj
= 0; jj
< state_
.texture_units
.size(); ++jj
) {
3548 state_
.texture_units
[jj
].Unbind(texture_ref
);
3550 // Unbind from current framebuffers.
3551 if (supports_separate_framebuffer_binds
) {
3552 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
3553 framebuffer_state_
.bound_read_framebuffer
3554 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT
, texture_ref
);
3556 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3557 framebuffer_state_
.bound_draw_framebuffer
3558 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT
, texture_ref
);
3561 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3562 framebuffer_state_
.bound_draw_framebuffer
3563 ->UnbindTexture(GL_FRAMEBUFFER
, texture_ref
);
3566 #if defined(OS_MACOSX)
3567 GLuint service_id
= texture
->service_id();
3568 if (texture
->target() == GL_TEXTURE_RECTANGLE_ARB
) {
3569 ReleaseIOSurfaceForTexture(service_id
);
3572 RemoveTexture(client_ids
[ii
]);
3577 // } // anonymous namespace
3579 bool GLES2DecoderImpl::MakeCurrent() {
3580 if (!context_
.get())
3583 if (WasContextLost()) {
3584 LOG(ERROR
) << " GLES2DecoderImpl: Trying to make lost context current.";
3588 if (!context_
->MakeCurrent(surface_
.get())) {
3589 LOG(ERROR
) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3590 MarkContextLost(error::kMakeCurrentFailed
);
3591 group_
->LoseContexts(error::kUnknown
);
3595 if (CheckResetStatus()) {
3597 << " GLES2DecoderImpl: Context reset detected after MakeCurrent.";
3598 group_
->LoseContexts(error::kUnknown
);
3602 ProcessFinishedAsyncTransfers();
3604 // Rebind the FBO if it was unbound by the context.
3605 if (workarounds().unbind_fbo_on_context_switch
)
3606 RestoreFramebufferBindings();
3608 framebuffer_state_
.clear_state_dirty
= true;
3613 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3614 ProcessPendingReadPixels(false);
3615 if (engine() && query_manager_
.get())
3616 query_manager_
->ProcessPendingTransferQueries();
3618 // TODO(epenner): Is there a better place to do this?
3619 // This needs to occur before we execute any batch of commands
3620 // from the client, as the client may have recieved an async
3621 // completion while issuing those commands.
3622 // "DidFlushStart" would be ideal if we had such a callback.
3623 async_pixel_transfer_manager_
->BindCompletedAsyncTransfers();
3626 static void RebindCurrentFramebuffer(
3628 Framebuffer
* framebuffer
,
3629 GLuint back_buffer_service_id
) {
3630 GLuint framebuffer_id
= framebuffer
? framebuffer
->service_id() : 0;
3632 if (framebuffer_id
== 0) {
3633 framebuffer_id
= back_buffer_service_id
;
3636 glBindFramebufferEXT(target
, framebuffer_id
);
3639 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3640 framebuffer_state_
.clear_state_dirty
= true;
3642 if (!features().chromium_framebuffer_multisample
) {
3643 RebindCurrentFramebuffer(
3645 framebuffer_state_
.bound_draw_framebuffer
.get(),
3646 GetBackbufferServiceId());
3648 RebindCurrentFramebuffer(
3649 GL_READ_FRAMEBUFFER_EXT
,
3650 framebuffer_state_
.bound_read_framebuffer
.get(),
3651 GetBackbufferServiceId());
3652 RebindCurrentFramebuffer(
3653 GL_DRAW_FRAMEBUFFER_EXT
,
3654 framebuffer_state_
.bound_draw_framebuffer
.get(),
3655 GetBackbufferServiceId());
3660 bool GLES2DecoderImpl::CheckFramebufferValid(
3661 Framebuffer
* framebuffer
,
3662 GLenum target
, const char* func_name
) {
3666 if (backbuffer_needs_clear_bits_
) {
3667 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3668 offscreen_target_color_format_
) & 0x0008) != 0 ? 0 : 1.f
);
3669 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
3671 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
3672 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
3674 state_
.SetDeviceDepthMask(GL_TRUE
);
3675 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
3676 bool reset_draw_buffer
= false;
3677 if ((backbuffer_needs_clear_bits_
& GL_COLOR_BUFFER_BIT
) != 0 &&
3678 back_buffer_draw_buffer_
== GL_NONE
) {
3679 reset_draw_buffer
= true;
3680 GLenum buf
= GL_BACK
;
3681 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3682 buf
= GL_COLOR_ATTACHMENT0
;
3683 glDrawBuffersARB(1, &buf
);
3685 glClear(backbuffer_needs_clear_bits_
);
3686 if (reset_draw_buffer
) {
3687 GLenum buf
= GL_NONE
;
3688 glDrawBuffersARB(1, &buf
);
3690 backbuffer_needs_clear_bits_
= 0;
3691 RestoreClearState();
3696 if (framebuffer_manager()->IsComplete(framebuffer
)) {
3700 GLenum completeness
= framebuffer
->IsPossiblyComplete();
3701 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
3703 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
, "framebuffer incomplete");
3707 // Are all the attachments cleared?
3708 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3709 texture_manager()->HaveUnclearedMips()) {
3710 if (!framebuffer
->IsCleared()) {
3711 // Can we clear them?
3712 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3713 GL_FRAMEBUFFER_COMPLETE
) {
3715 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3716 "framebuffer incomplete (clear)");
3719 ClearUnclearedAttachments(target
, framebuffer
);
3723 if (!framebuffer_manager()->IsComplete(framebuffer
)) {
3724 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3725 GL_FRAMEBUFFER_COMPLETE
) {
3727 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3728 "framebuffer incomplete (check)");
3731 framebuffer_manager()->MarkAsComplete(framebuffer
);
3734 // NOTE: At this point we don't know if the framebuffer is complete but
3735 // we DO know that everything that needs to be cleared has been cleared.
3739 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name
) {
3740 if (!features().chromium_framebuffer_multisample
) {
3741 bool valid
= CheckFramebufferValid(
3742 framebuffer_state_
.bound_draw_framebuffer
.get(), GL_FRAMEBUFFER_EXT
,
3750 return CheckFramebufferValid(framebuffer_state_
.bound_draw_framebuffer
.get(),
3751 GL_DRAW_FRAMEBUFFER_EXT
,
3753 CheckFramebufferValid(framebuffer_state_
.bound_read_framebuffer
.get(),
3754 GL_READ_FRAMEBUFFER_EXT
,
3758 bool GLES2DecoderImpl::CheckBoundReadFramebufferColorAttachment(
3759 const char* func_name
) {
3760 Framebuffer
* framebuffer
= features().chromium_framebuffer_multisample
?
3761 framebuffer_state_
.bound_read_framebuffer
.get() :
3762 framebuffer_state_
.bound_draw_framebuffer
.get();
3765 if (framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
) == NULL
) {
3767 GL_INVALID_OPERATION
, func_name
, "no color image attached");
3773 bool GLES2DecoderImpl::FormsTextureCopyingFeedbackLoop(
3774 TextureRef
* texture
, GLint level
) {
3775 Framebuffer
* framebuffer
= features().chromium_framebuffer_multisample
?
3776 framebuffer_state_
.bound_read_framebuffer
.get() :
3777 framebuffer_state_
.bound_draw_framebuffer
.get();
3780 const Framebuffer::Attachment
* attachment
= framebuffer
->GetAttachment(
3781 GL_COLOR_ATTACHMENT0
);
3784 return attachment
->FormsFeedbackLoop(texture
, level
);
3787 gfx::Size
GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3788 Framebuffer
* framebuffer
=
3789 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3790 if (framebuffer
!= NULL
) {
3791 const Framebuffer::Attachment
* attachment
=
3792 framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
);
3794 return gfx::Size(attachment
->width(), attachment
->height());
3796 return gfx::Size(0, 0);
3797 } else if (offscreen_target_frame_buffer_
.get()) {
3798 return offscreen_size_
;
3800 return surface_
->GetSize();
3804 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3805 Framebuffer
* framebuffer
=
3806 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3808 return framebuffer
->GetReadBufferTextureType();
3809 } else { // Back buffer.
3810 if (back_buffer_read_buffer_
== GL_NONE
)
3812 return GL_UNSIGNED_BYTE
;
3816 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3817 Framebuffer
* framebuffer
=
3818 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3820 return framebuffer
->GetReadBufferInternalFormat();
3821 } else { // Back buffer.
3822 if (back_buffer_read_buffer_
== GL_NONE
)
3824 if (offscreen_target_frame_buffer_
.get()) {
3825 return offscreen_target_color_format_
;
3827 return back_buffer_color_format_
;
3831 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3832 if (!offscreen_saved_color_texture_info_
.get())
3834 GLenum target
= offscreen_saved_color_texture_info_
->texture()->target();
3835 glBindTexture(target
, offscreen_saved_color_texture_info_
->service_id());
3836 texture_manager()->SetLevelInfo(
3837 offscreen_saved_color_texture_info_
.get(), GL_TEXTURE_2D
,
3839 GL_RGBA
, offscreen_size_
.width(), offscreen_size_
.height(),
3842 GL_RGBA
, GL_UNSIGNED_BYTE
, gfx::Rect(offscreen_size_
));
3843 texture_manager()->SetParameteri(
3844 "UpdateParentTextureInfo",
3846 offscreen_saved_color_texture_info_
.get(),
3847 GL_TEXTURE_MAG_FILTER
,
3849 texture_manager()->SetParameteri(
3850 "UpdateParentTextureInfo",
3852 offscreen_saved_color_texture_info_
.get(),
3853 GL_TEXTURE_MIN_FILTER
,
3855 texture_manager()->SetParameteri(
3856 "UpdateParentTextureInfo",
3858 offscreen_saved_color_texture_info_
.get(),
3861 texture_manager()->SetParameteri(
3862 "UpdateParentTextureInfo",
3864 offscreen_saved_color_texture_info_
.get(),
3867 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
3869 glBindTexture(target
, texture_ref
? texture_ref
->service_id() : 0);
3872 void GLES2DecoderImpl::SetResizeCallback(
3873 const base::Callback
<void(gfx::Size
, float)>& callback
) {
3874 resize_callback_
= callback
;
3877 Logger
* GLES2DecoderImpl::GetLogger() {
3881 void GLES2DecoderImpl::BeginDecoding() {
3882 gpu_tracer_
->BeginDecoding();
3883 gpu_trace_commands_
= gpu_tracer_
->IsTracing() && *gpu_decoder_category_
;
3884 gpu_debug_commands_
= log_commands() || debug() || gpu_trace_commands_
||
3885 (*cb_command_trace_category_
!= 0);
3886 query_manager_
->ProcessFrameBeginUpdates();
3889 void GLES2DecoderImpl::EndDecoding() {
3890 gpu_tracer_
->EndDecoding();
3893 ErrorState
* GLES2DecoderImpl::GetErrorState() {
3894 return state_
.GetErrorState();
3897 void GLES2DecoderImpl::SetShaderCacheCallback(
3898 const ShaderCacheCallback
& callback
) {
3899 shader_cache_callback_
= callback
;
3902 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3903 const WaitSyncPointCallback
& callback
) {
3904 wait_sync_point_callback_
= callback
;
3907 AsyncPixelTransferManager
*
3908 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3909 return async_pixel_transfer_manager_
.get();
3912 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3913 async_pixel_transfer_manager_
.reset();
3916 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3917 AsyncPixelTransferManager
* manager
) {
3918 async_pixel_transfer_manager_
= make_scoped_ptr(manager
);
3921 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id
,
3922 uint32
* service_texture_id
) {
3923 TextureRef
* texture_ref
= texture_manager()->GetTexture(client_texture_id
);
3925 *service_texture_id
= texture_ref
->service_id();
3931 uint32
GLES2DecoderImpl::GetTextureUploadCount() {
3932 return texture_state_
.texture_upload_count
+
3933 async_pixel_transfer_manager_
->GetTextureUploadCount();
3936 base::TimeDelta
GLES2DecoderImpl::GetTotalTextureUploadTime() {
3937 return texture_state_
.total_texture_upload_time
+
3938 async_pixel_transfer_manager_
->GetTotalTextureUploadTime();
3941 base::TimeDelta
GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3942 return total_processing_commands_time_
;
3945 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time
) {
3946 total_processing_commands_time_
+= time
;
3949 void GLES2DecoderImpl::Destroy(bool have_context
) {
3953 DCHECK(!have_context
|| context_
->IsCurrent(NULL
));
3955 // Unbind everything.
3956 state_
.vertex_attrib_manager
= NULL
;
3957 state_
.default_vertex_attrib_manager
= NULL
;
3958 state_
.texture_units
.clear();
3959 state_
.bound_array_buffer
= NULL
;
3960 state_
.bound_copy_read_buffer
= NULL
;
3961 state_
.bound_copy_write_buffer
= NULL
;
3962 state_
.bound_pixel_pack_buffer
= NULL
;
3963 state_
.bound_pixel_unpack_buffer
= NULL
;
3964 state_
.bound_transform_feedback_buffer
= NULL
;
3965 state_
.bound_uniform_buffer
= NULL
;
3966 framebuffer_state_
.bound_read_framebuffer
= NULL
;
3967 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
3968 state_
.bound_renderbuffer
= NULL
;
3969 state_
.bound_valuebuffer
= NULL
;
3971 if (offscreen_saved_color_texture_info_
.get()) {
3972 DCHECK(offscreen_target_color_texture_
);
3973 DCHECK_EQ(offscreen_saved_color_texture_info_
->service_id(),
3974 offscreen_saved_color_texture_
->id());
3975 offscreen_saved_color_texture_
->Invalidate();
3976 offscreen_saved_color_texture_info_
= NULL
;
3979 if (copy_texture_CHROMIUM_
.get()) {
3980 copy_texture_CHROMIUM_
->Destroy();
3981 copy_texture_CHROMIUM_
.reset();
3984 clear_framebuffer_blit_
.reset();
3986 if (state_
.current_program
.get()) {
3987 program_manager()->UnuseProgram(shader_manager(),
3988 state_
.current_program
.get());
3991 if (attrib_0_buffer_id_
) {
3992 glDeleteBuffersARB(1, &attrib_0_buffer_id_
);
3994 if (fixed_attrib_buffer_id_
) {
3995 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_
);
3998 if (validation_texture_
) {
3999 glDeleteTextures(1, &validation_texture_
);
4000 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_
);
4001 glDeleteFramebuffersEXT(1, &validation_fbo_
);
4004 if (offscreen_target_frame_buffer_
.get())
4005 offscreen_target_frame_buffer_
->Destroy();
4006 if (offscreen_target_color_texture_
.get())
4007 offscreen_target_color_texture_
->Destroy();
4008 if (offscreen_target_color_render_buffer_
.get())
4009 offscreen_target_color_render_buffer_
->Destroy();
4010 if (offscreen_target_depth_render_buffer_
.get())
4011 offscreen_target_depth_render_buffer_
->Destroy();
4012 if (offscreen_target_stencil_render_buffer_
.get())
4013 offscreen_target_stencil_render_buffer_
->Destroy();
4014 if (offscreen_saved_frame_buffer_
.get())
4015 offscreen_saved_frame_buffer_
->Destroy();
4016 if (offscreen_saved_color_texture_
.get())
4017 offscreen_saved_color_texture_
->Destroy();
4018 if (offscreen_resolved_frame_buffer_
.get())
4019 offscreen_resolved_frame_buffer_
->Destroy();
4020 if (offscreen_resolved_color_texture_
.get())
4021 offscreen_resolved_color_texture_
->Destroy();
4023 if (offscreen_target_frame_buffer_
.get())
4024 offscreen_target_frame_buffer_
->Invalidate();
4025 if (offscreen_target_color_texture_
.get())
4026 offscreen_target_color_texture_
->Invalidate();
4027 if (offscreen_target_color_render_buffer_
.get())
4028 offscreen_target_color_render_buffer_
->Invalidate();
4029 if (offscreen_target_depth_render_buffer_
.get())
4030 offscreen_target_depth_render_buffer_
->Invalidate();
4031 if (offscreen_target_stencil_render_buffer_
.get())
4032 offscreen_target_stencil_render_buffer_
->Invalidate();
4033 if (offscreen_saved_frame_buffer_
.get())
4034 offscreen_saved_frame_buffer_
->Invalidate();
4035 if (offscreen_saved_color_texture_
.get())
4036 offscreen_saved_color_texture_
->Invalidate();
4037 if (offscreen_resolved_frame_buffer_
.get())
4038 offscreen_resolved_frame_buffer_
->Invalidate();
4039 if (offscreen_resolved_color_texture_
.get())
4040 offscreen_resolved_color_texture_
->Invalidate();
4043 // Current program must be cleared after calling ProgramManager::UnuseProgram.
4044 // Otherwise, we can leak objects. http://crbug.com/258772.
4045 // state_.current_program must be reset before group_ is reset because
4046 // the later deletes the ProgramManager object that referred by
4047 // state_.current_program object.
4048 state_
.current_program
= NULL
;
4050 copy_texture_CHROMIUM_
.reset();
4051 clear_framebuffer_blit_
.reset();
4053 if (query_manager_
.get()) {
4054 query_manager_
->Destroy(have_context
);
4055 query_manager_
.reset();
4058 if (vertex_array_manager_
.get()) {
4059 vertex_array_manager_
->Destroy(have_context
);
4060 vertex_array_manager_
.reset();
4063 if (image_manager_
.get()) {
4064 image_manager_
->Destroy(have_context
);
4065 image_manager_
.reset();
4068 offscreen_target_frame_buffer_
.reset();
4069 offscreen_target_color_texture_
.reset();
4070 offscreen_target_color_render_buffer_
.reset();
4071 offscreen_target_depth_render_buffer_
.reset();
4072 offscreen_target_stencil_render_buffer_
.reset();
4073 offscreen_saved_frame_buffer_
.reset();
4074 offscreen_saved_color_texture_
.reset();
4075 offscreen_resolved_frame_buffer_
.reset();
4076 offscreen_resolved_color_texture_
.reset();
4078 // Need to release these before releasing |group_| which may own the
4079 // ShaderTranslatorCache.
4080 fragment_translator_
= NULL
;
4081 vertex_translator_
= NULL
;
4083 // Should destroy the transfer manager before the texture manager held
4084 // by the context group.
4085 async_pixel_transfer_manager_
.reset();
4087 // Destroy the GPU Tracer which may own some in process GPU Timings.
4089 gpu_tracer_
->Destroy(have_context
);
4090 gpu_tracer_
.reset();
4094 framebuffer_manager()->RemoveObserver(this);
4095 group_
->Destroy(this, have_context
);
4099 if (context_
.get()) {
4100 context_
->ReleaseCurrent(NULL
);
4104 #if defined(OS_MACOSX)
4105 for (TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.begin();
4106 it
!= texture_to_io_surface_map_
.end(); ++it
) {
4107 CFRelease(it
->second
);
4109 texture_to_io_surface_map_
.clear();
4113 void GLES2DecoderImpl::SetSurface(
4114 const scoped_refptr
<gfx::GLSurface
>& surface
) {
4115 DCHECK(context_
->IsCurrent(NULL
));
4116 DCHECK(surface_
.get());
4118 RestoreCurrentFramebufferBindings();
4121 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox
& mailbox
) {
4122 if (!offscreen_saved_color_texture_
.get()) {
4123 LOG(ERROR
) << "Called ProduceFrontBuffer on a non-offscreen context";
4126 if (!offscreen_saved_color_texture_info_
.get()) {
4127 GLuint service_id
= offscreen_saved_color_texture_
->id();
4128 offscreen_saved_color_texture_info_
= TextureRef::Create(
4129 texture_manager(), 0, service_id
);
4130 texture_manager()->SetTarget(offscreen_saved_color_texture_info_
.get(),
4132 UpdateParentTextureInfo();
4134 mailbox_manager()->ProduceTexture(
4135 mailbox
, offscreen_saved_color_texture_info_
->texture());
4138 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size
& size
) {
4139 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
4140 if (!is_offscreen
) {
4141 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
4142 << " with an onscreen framebuffer.";
4146 if (offscreen_size_
== size
)
4149 offscreen_size_
= size
;
4150 int w
= offscreen_size_
.width();
4151 int h
= offscreen_size_
.height();
4152 if (w
< 0 || h
< 0 || h
>= (INT_MAX
/ 4) / (w
? w
: 1)) {
4153 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4154 << "to allocate storage due to excessive dimensions.";
4158 // Reallocate the offscreen target buffers.
4159 DCHECK(offscreen_target_color_format_
);
4160 if (IsOffscreenBufferMultisampled()) {
4161 if (!offscreen_target_color_render_buffer_
->AllocateStorage(
4162 feature_info_
.get(),
4164 offscreen_target_color_format_
,
4165 offscreen_target_samples_
)) {
4166 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4167 << "to allocate storage for offscreen target color buffer.";
4171 if (!offscreen_target_color_texture_
->AllocateStorage(
4172 offscreen_size_
, offscreen_target_color_format_
, false)) {
4173 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4174 << "to allocate storage for offscreen target color texture.";
4178 if (offscreen_target_depth_format_
&&
4179 !offscreen_target_depth_render_buffer_
->AllocateStorage(
4180 feature_info_
.get(),
4182 offscreen_target_depth_format_
,
4183 offscreen_target_samples_
)) {
4184 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4185 << "to allocate storage for offscreen target depth buffer.";
4188 if (offscreen_target_stencil_format_
&&
4189 !offscreen_target_stencil_render_buffer_
->AllocateStorage(
4190 feature_info_
.get(),
4192 offscreen_target_stencil_format_
,
4193 offscreen_target_samples_
)) {
4194 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4195 << "to allocate storage for offscreen target stencil buffer.";
4199 // Attach the offscreen target buffers to the target frame buffer.
4200 if (IsOffscreenBufferMultisampled()) {
4201 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4202 GL_COLOR_ATTACHMENT0
,
4203 offscreen_target_color_render_buffer_
.get());
4205 offscreen_target_frame_buffer_
->AttachRenderTexture(
4206 offscreen_target_color_texture_
.get());
4208 if (offscreen_target_depth_format_
) {
4209 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4210 GL_DEPTH_ATTACHMENT
,
4211 offscreen_target_depth_render_buffer_
.get());
4213 const bool packed_depth_stencil
=
4214 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
4215 if (packed_depth_stencil
) {
4216 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4217 GL_STENCIL_ATTACHMENT
,
4218 offscreen_target_depth_render_buffer_
.get());
4219 } else if (offscreen_target_stencil_format_
) {
4220 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4221 GL_STENCIL_ATTACHMENT
,
4222 offscreen_target_stencil_render_buffer_
.get());
4225 if (offscreen_target_frame_buffer_
->CheckStatus() !=
4226 GL_FRAMEBUFFER_COMPLETE
) {
4227 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4228 << "because offscreen FBO was incomplete.";
4232 // Clear the target frame buffer.
4234 ScopedFrameBufferBinder
binder(this, offscreen_target_frame_buffer_
->id());
4235 glClearColor(0, 0, 0, BackBufferHasAlpha() ? 0 : 1.f
);
4236 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
4238 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
4239 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
4241 state_
.SetDeviceDepthMask(GL_TRUE
);
4242 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
4243 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
4244 RestoreClearState();
4247 // Destroy the offscreen resolved framebuffers.
4248 if (offscreen_resolved_frame_buffer_
.get())
4249 offscreen_resolved_frame_buffer_
->Destroy();
4250 if (offscreen_resolved_color_texture_
.get())
4251 offscreen_resolved_color_texture_
->Destroy();
4252 offscreen_resolved_color_texture_
.reset();
4253 offscreen_resolved_frame_buffer_
.reset();
4258 error::Error
GLES2DecoderImpl::HandleResizeCHROMIUM(uint32 immediate_data_size
,
4259 const void* cmd_data
) {
4260 const gles2::cmds::ResizeCHROMIUM
& c
=
4261 *static_cast<const gles2::cmds::ResizeCHROMIUM
*>(cmd_data
);
4262 if (!offscreen_target_frame_buffer_
.get() && surface_
->DeferDraws())
4263 return error::kDeferCommandUntilLater
;
4265 GLuint width
= static_cast<GLuint
>(c
.width
);
4266 GLuint height
= static_cast<GLuint
>(c
.height
);
4267 GLfloat scale_factor
= c
.scale_factor
;
4268 TRACE_EVENT2("gpu", "glResizeChromium", "width", width
, "height", height
);
4270 width
= std::max(1U, width
);
4271 height
= std::max(1U, height
);
4273 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
4274 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
4275 // Make sure that we are done drawing to the back buffer before resizing.
4278 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
4280 if (!ResizeOffscreenFrameBuffer(gfx::Size(width
, height
))) {
4281 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because "
4282 << "ResizeOffscreenFrameBuffer failed.";
4283 return error::kLostContext
;
4287 if (!resize_callback_
.is_null()) {
4288 resize_callback_
.Run(gfx::Size(width
, height
), scale_factor
);
4289 DCHECK(context_
->IsCurrent(surface_
.get()));
4290 if (!context_
->IsCurrent(surface_
.get())) {
4291 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because context no longer "
4292 << "current after resize callback.";
4293 return error::kLostContext
;
4297 return error::kNoError
;
4300 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id
) const {
4301 if (command_id
> kStartPoint
&& command_id
< kNumCommands
) {
4302 return gles2::GetCommandName(static_cast<CommandId
>(command_id
));
4304 return GetCommonCommandName(static_cast<cmd::CommandId
>(command_id
));
4307 // Decode a command, and call the corresponding GL functions.
4308 // NOTE: DoCommand() is slower than calling DoCommands() on larger batches
4309 // of commands at once, and is now only used for tests that need to track
4310 // individual commands.
4311 error::Error
GLES2DecoderImpl::DoCommand(unsigned int command
,
4312 unsigned int arg_count
,
4313 const void* cmd_data
) {
4314 return DoCommands(1, cmd_data
, arg_count
+ 1, 0);
4317 // Decode multiple commands, and call the corresponding GL functions.
4318 // NOTE: 'buffer' is a pointer to the command buffer. As such, it could be
4319 // changed by a (malicious) client at any time, so if validation has to happen,
4320 // it should operate on a copy of them.
4321 // NOTE: This is duplicating code from AsyncAPIInterface::DoCommands() in the
4322 // interest of performance in this critical execution loop.
4323 template <bool DebugImpl
>
4324 error::Error
GLES2DecoderImpl::DoCommandsImpl(unsigned int num_commands
,
4327 int* entries_processed
) {
4328 commands_to_process_
= num_commands
;
4329 error::Error result
= error::kNoError
;
4330 const CommandBufferEntry
* cmd_data
=
4331 static_cast<const CommandBufferEntry
*>(buffer
);
4332 int process_pos
= 0;
4333 unsigned int command
= 0;
4335 while (process_pos
< num_entries
&& result
== error::kNoError
&&
4336 commands_to_process_
--) {
4337 const unsigned int size
= cmd_data
->value_header
.size
;
4338 command
= cmd_data
->value_header
.command
;
4341 result
= error::kInvalidSize
;
4345 if (static_cast<int>(size
) + process_pos
> num_entries
) {
4346 result
= error::kOutOfBounds
;
4351 TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4352 GetCommandName(command
));
4354 if (log_commands()) {
4355 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "]"
4356 << "cmd: " << GetCommandName(command
);
4360 const unsigned int arg_count
= size
- 1;
4361 unsigned int command_index
= command
- kStartPoint
- 1;
4362 if (command_index
< arraysize(command_info
)) {
4363 const CommandInfo
& info
= command_info
[command_index
];
4364 unsigned int info_arg_count
= static_cast<unsigned int>(info
.arg_count
);
4365 if ((info
.arg_flags
== cmd::kFixed
&& arg_count
== info_arg_count
) ||
4366 (info
.arg_flags
== cmd::kAtLeastN
&& arg_count
>= info_arg_count
)) {
4367 bool doing_gpu_trace
= false;
4368 if (DebugImpl
&& gpu_trace_commands_
) {
4369 if (CMD_FLAG_GET_TRACE_LEVEL(info
.cmd_flags
) <= gpu_trace_level_
) {
4370 doing_gpu_trace
= true;
4371 gpu_tracer_
->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_decoder"),
4372 GetCommandName(command
),
4377 uint32 immediate_data_size
= (arg_count
- info_arg_count
) *
4378 sizeof(CommandBufferEntry
); // NOLINT
4380 result
= (this->*info
.cmd_handler
)(immediate_data_size
, cmd_data
);
4382 if (DebugImpl
&& doing_gpu_trace
)
4383 gpu_tracer_
->End(kTraceDecoder
);
4385 if (DebugImpl
&& debug()) {
4387 while ((error
= glGetError()) != GL_NO_ERROR
) {
4388 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "] "
4389 << "GL ERROR: " << GLES2Util::GetStringEnum(error
)
4390 << " : " << GetCommandName(command
);
4391 LOCAL_SET_GL_ERROR(error
, "DoCommand", "GL error from driver");
4395 result
= error::kInvalidArguments
;
4398 result
= DoCommonCommand(command
, arg_count
, cmd_data
);
4402 TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4403 GetCommandName(command
));
4406 if (result
== error::kNoError
&&
4407 current_decoder_error_
!= error::kNoError
) {
4408 result
= current_decoder_error_
;
4409 current_decoder_error_
= error::kNoError
;
4412 if (result
!= error::kDeferCommandUntilLater
) {
4413 process_pos
+= size
;
4418 if (entries_processed
)
4419 *entries_processed
= process_pos
;
4421 if (error::IsError(result
)) {
4422 LOG(ERROR
) << "Error: " << result
<< " for Command "
4423 << GetCommandName(command
);
4429 error::Error
GLES2DecoderImpl::DoCommands(unsigned int num_commands
,
4432 int* entries_processed
) {
4433 if (gpu_debug_commands_
) {
4434 return DoCommandsImpl
<true>(
4435 num_commands
, buffer
, num_entries
, entries_processed
);
4437 return DoCommandsImpl
<false>(
4438 num_commands
, buffer
, num_entries
, entries_processed
);
4442 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id
) {
4443 buffer_manager()->RemoveBuffer(client_id
);
4446 void GLES2DecoderImpl::DoFinish() {
4448 ProcessPendingReadPixels(true);
4449 ProcessPendingQueries(true);
4452 void GLES2DecoderImpl::DoFlush() {
4454 ProcessPendingQueries(false);
4457 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit
) {
4458 GLuint texture_index
= texture_unit
- GL_TEXTURE0
;
4459 if (texture_index
>= state_
.texture_units
.size()) {
4460 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4461 "glActiveTexture", texture_unit
, "texture_unit");
4464 state_
.active_texture_unit
= texture_index
;
4465 glActiveTexture(texture_unit
);
4468 void GLES2DecoderImpl::DoBindBuffer(GLenum target
, GLuint client_id
) {
4469 Buffer
* buffer
= NULL
;
4470 GLuint service_id
= 0;
4471 if (client_id
!= 0) {
4472 buffer
= GetBuffer(client_id
);
4474 if (!group_
->bind_generates_resource()) {
4475 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4477 "id not generated by glGenBuffers");
4481 // It's a new id so make a buffer buffer for it.
4482 glGenBuffersARB(1, &service_id
);
4483 CreateBuffer(client_id
, service_id
);
4484 buffer
= GetBuffer(client_id
);
4487 LogClientServiceForInfo(buffer
, client_id
, "glBindBuffer");
4489 if (!buffer_manager()->SetTarget(buffer
, target
)) {
4491 GL_INVALID_OPERATION
,
4492 "glBindBuffer", "buffer bound to more than 1 target");
4495 service_id
= buffer
->service_id();
4497 state_
.SetBoundBuffer(target
, buffer
);
4498 glBindBuffer(target
, service_id
);
4501 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha() {
4502 Framebuffer
* framebuffer
=
4503 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4505 return framebuffer
->HasAlphaMRT();
4506 return BackBufferHasAlpha();
4509 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
4510 Framebuffer
* framebuffer
=
4511 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4513 return framebuffer
->HasDepthAttachment();
4515 if (offscreen_target_frame_buffer_
.get()) {
4516 return offscreen_target_depth_format_
!= 0;
4518 return back_buffer_has_depth_
;
4521 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
4522 Framebuffer
* framebuffer
=
4523 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4525 return framebuffer
->HasStencilAttachment();
4527 if (offscreen_target_frame_buffer_
.get()) {
4528 return offscreen_target_stencil_format_
!= 0 ||
4529 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
4531 return back_buffer_has_stencil_
;
4534 void GLES2DecoderImpl::ApplyDirtyState() {
4535 if (framebuffer_state_
.clear_state_dirty
) {
4536 bool have_alpha
= BoundFramebufferHasColorAttachmentWithAlpha();
4537 state_
.SetDeviceColorMask(state_
.color_mask_red
,
4538 state_
.color_mask_green
,
4539 state_
.color_mask_blue
,
4540 state_
.color_mask_alpha
&& have_alpha
);
4542 bool have_depth
= BoundFramebufferHasDepthAttachment();
4543 state_
.SetDeviceDepthMask(state_
.depth_mask
&& have_depth
);
4545 bool have_stencil
= BoundFramebufferHasStencilAttachment();
4546 state_
.SetDeviceStencilMaskSeparate(
4547 GL_FRONT
, have_stencil
? state_
.stencil_front_writemask
: 0);
4548 state_
.SetDeviceStencilMaskSeparate(
4549 GL_BACK
, have_stencil
? state_
.stencil_back_writemask
: 0);
4551 state_
.SetDeviceCapabilityState(
4552 GL_DEPTH_TEST
, state_
.enable_flags
.depth_test
&& have_depth
);
4553 state_
.SetDeviceCapabilityState(
4554 GL_STENCIL_TEST
, state_
.enable_flags
.stencil_test
&& have_stencil
);
4555 framebuffer_state_
.clear_state_dirty
= false;
4559 GLuint
GLES2DecoderImpl::GetBackbufferServiceId() const {
4560 return (offscreen_target_frame_buffer_
.get())
4561 ? offscreen_target_frame_buffer_
->id()
4562 : (surface_
.get() ? surface_
->GetBackingFrameBufferObject() : 0);
4565 void GLES2DecoderImpl::RestoreState(const ContextState
* prev_state
) {
4566 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
4567 "context", logger_
.GetLogPrefix());
4568 // Restore the Framebuffer first because of bugs in Intel drivers.
4569 // Intel drivers incorrectly clip the viewport settings to
4570 // the size of the current framebuffer object.
4571 RestoreFramebufferBindings();
4572 state_
.RestoreState(prev_state
);
4575 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
4577 framebuffer_state_
.bound_draw_framebuffer
.get()
4578 ? framebuffer_state_
.bound_draw_framebuffer
->service_id()
4579 : GetBackbufferServiceId();
4580 if (!features().chromium_framebuffer_multisample
) {
4581 glBindFramebufferEXT(GL_FRAMEBUFFER
, service_id
);
4583 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, service_id
);
4584 service_id
= framebuffer_state_
.bound_read_framebuffer
.get()
4585 ? framebuffer_state_
.bound_read_framebuffer
->service_id()
4586 : GetBackbufferServiceId();
4587 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, service_id
);
4592 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
4593 state_
.RestoreRenderbufferBindings();
4596 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id
) const {
4597 Texture
* texture
= texture_manager()->GetTextureForServiceId(service_id
);
4599 GLenum target
= texture
->target();
4600 glBindTexture(target
, service_id
);
4602 target
, GL_TEXTURE_WRAP_S
, texture
->wrap_s());
4604 target
, GL_TEXTURE_WRAP_T
, texture
->wrap_t());
4606 target
, GL_TEXTURE_MIN_FILTER
, texture
->min_filter());
4608 target
, GL_TEXTURE_MAG_FILTER
, texture
->mag_filter());
4609 RestoreTextureUnitBindings(state_
.active_texture_unit
);
4613 void GLES2DecoderImpl::ClearAllAttributes() const {
4614 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
4616 if (feature_info_
->feature_flags().native_vertex_array_object
)
4617 glBindVertexArrayOES(0);
4619 for (uint32 i
= 0; i
< group_
->max_vertex_attribs(); ++i
) {
4620 if (i
!= 0) // Never disable attribute 0
4621 glDisableVertexAttribArray(i
);
4622 if (features().angle_instanced_arrays
)
4623 glVertexAttribDivisorANGLE(i
, 0);
4627 void GLES2DecoderImpl::RestoreAllAttributes() const {
4628 state_
.RestoreVertexAttribs();
4631 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore
) {
4632 state_
.SetIgnoreCachedStateForTest(ignore
);
4635 void GLES2DecoderImpl::OnFboChanged() const {
4636 if (workarounds().restore_scissor_on_fbo_change
)
4637 state_
.fbo_binding_for_scissor_workaround_dirty
= true;
4639 if (workarounds().gl_begin_gl_end_on_fbo_change_to_backbuffer
) {
4640 GLint bound_fbo_unsigned
= -1;
4641 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT
, &bound_fbo_unsigned
);
4642 GLuint bound_fbo
= static_cast<GLuint
>(bound_fbo_unsigned
);
4643 if (surface_
&& surface_
->GetBackingFrameBufferObject() == bound_fbo
)
4644 surface_
->NotifyWasBound();
4648 // Called after the FBO is checked for completeness.
4649 void GLES2DecoderImpl::OnUseFramebuffer() const {
4650 if (state_
.fbo_binding_for_scissor_workaround_dirty
) {
4651 state_
.fbo_binding_for_scissor_workaround_dirty
= false;
4652 // The driver forgets the correct scissor when modifying the FBO binding.
4653 glScissor(state_
.scissor_x
,
4655 state_
.scissor_width
,
4656 state_
.scissor_height
);
4658 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
4659 // it's unclear how this bug works.
4664 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target
, GLuint client_id
) {
4665 Framebuffer
* framebuffer
= NULL
;
4666 GLuint service_id
= 0;
4667 if (client_id
!= 0) {
4668 framebuffer
= GetFramebuffer(client_id
);
4670 if (!group_
->bind_generates_resource()) {
4671 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4672 "glBindFramebuffer",
4673 "id not generated by glGenFramebuffers");
4677 // It's a new id so make a framebuffer framebuffer for it.
4678 glGenFramebuffersEXT(1, &service_id
);
4679 CreateFramebuffer(client_id
, service_id
);
4680 framebuffer
= GetFramebuffer(client_id
);
4682 service_id
= framebuffer
->service_id();
4684 framebuffer
->MarkAsValid();
4686 LogClientServiceForInfo(framebuffer
, client_id
, "glBindFramebuffer");
4688 if (target
== GL_FRAMEBUFFER
|| target
== GL_DRAW_FRAMEBUFFER_EXT
) {
4689 framebuffer_state_
.bound_draw_framebuffer
= framebuffer
;
4692 // vmiura: This looks like dup code
4693 if (target
== GL_FRAMEBUFFER
|| target
== GL_READ_FRAMEBUFFER_EXT
) {
4694 framebuffer_state_
.bound_read_framebuffer
= framebuffer
;
4697 framebuffer_state_
.clear_state_dirty
= true;
4699 // If we are rendering to the backbuffer get the FBO id for any simulated
4701 if (framebuffer
== NULL
) {
4702 service_id
= GetBackbufferServiceId();
4705 glBindFramebufferEXT(target
, service_id
);
4709 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target
, GLuint client_id
) {
4710 Renderbuffer
* renderbuffer
= NULL
;
4711 GLuint service_id
= 0;
4712 if (client_id
!= 0) {
4713 renderbuffer
= GetRenderbuffer(client_id
);
4714 if (!renderbuffer
) {
4715 if (!group_
->bind_generates_resource()) {
4716 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4717 "glBindRenderbuffer",
4718 "id not generated by glGenRenderbuffers");
4722 // It's a new id so make a renderbuffer for it.
4723 glGenRenderbuffersEXT(1, &service_id
);
4724 CreateRenderbuffer(client_id
, service_id
);
4725 renderbuffer
= GetRenderbuffer(client_id
);
4727 service_id
= renderbuffer
->service_id();
4729 renderbuffer
->MarkAsValid();
4731 LogClientServiceForInfo(renderbuffer
, client_id
, "glBindRenderbuffer");
4732 state_
.bound_renderbuffer
= renderbuffer
;
4733 state_
.bound_renderbuffer_valid
= true;
4734 glBindRenderbufferEXT(GL_RENDERBUFFER
, service_id
);
4737 void GLES2DecoderImpl::DoBindTexture(GLenum target
, GLuint client_id
) {
4738 TextureRef
* texture_ref
= NULL
;
4739 GLuint service_id
= 0;
4740 if (client_id
!= 0) {
4741 texture_ref
= GetTexture(client_id
);
4743 if (!group_
->bind_generates_resource()) {
4744 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4746 "id not generated by glGenTextures");
4750 // It's a new id so make a texture texture for it.
4751 glGenTextures(1, &service_id
);
4752 DCHECK_NE(0u, service_id
);
4753 CreateTexture(client_id
, service_id
);
4754 texture_ref
= GetTexture(client_id
);
4757 texture_ref
= texture_manager()->GetDefaultTextureInfo(target
);
4760 // Check the texture exists
4762 Texture
* texture
= texture_ref
->texture();
4763 // Check that we are not trying to bind it to a different target.
4764 if (texture
->target() != 0 && texture
->target() != target
) {
4765 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4767 "texture bound to more than 1 target.");
4770 LogClientServiceForInfo(texture
, client_id
, "glBindTexture");
4771 if (texture
->target() == 0) {
4772 texture_manager()->SetTarget(texture_ref
, target
);
4774 glBindTexture(target
, texture
->service_id());
4776 glBindTexture(target
, 0);
4779 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4780 unit
.bind_target
= target
;
4783 unit
.bound_texture_2d
= texture_ref
;
4785 case GL_TEXTURE_CUBE_MAP
:
4786 unit
.bound_texture_cube_map
= texture_ref
;
4788 case GL_TEXTURE_EXTERNAL_OES
:
4789 unit
.bound_texture_external_oes
= texture_ref
;
4791 case GL_TEXTURE_RECTANGLE_ARB
:
4792 unit
.bound_texture_rectangle_arb
= texture_ref
;
4795 unit
.bound_texture_3d
= texture_ref
;
4797 case GL_TEXTURE_2D_ARRAY
:
4798 unit
.bound_texture_2d_array
= texture_ref
;
4801 NOTREACHED(); // Validation should prevent us getting here.
4806 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index
) {
4807 if (state_
.vertex_attrib_manager
->Enable(index
, false)) {
4809 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
4810 glDisableVertexAttribArray(index
);
4815 "glDisableVertexAttribArray", "index out of range");
4819 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target
,
4820 GLsizei numAttachments
,
4821 const GLenum
* attachments
) {
4822 if (workarounds().disable_discard_framebuffer
)
4825 Framebuffer
* framebuffer
=
4826 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
4828 // Validates the attachments. If one of them fails
4829 // the whole command fails.
4830 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4832 !validators_
->attachment
.IsValid(attachments
[i
])) ||
4834 !validators_
->backbuffer_attachment
.IsValid(attachments
[i
]))) {
4835 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4836 "glDiscardFramebufferEXT", attachments
[i
], "attachments");
4841 // Marks each one of them as not cleared
4842 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4844 framebuffer
->MarkAttachmentAsCleared(renderbuffer_manager(),
4849 switch (attachments
[i
]) {
4851 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
4854 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
4855 case GL_STENCIL_EXT
:
4856 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
4865 // If the default framebuffer is bound but we are still rendering to an
4866 // FBO, translate attachment names that refer to default framebuffer
4867 // channels to corresponding framebuffer attachments.
4868 scoped_ptr
<GLenum
[]> translated_attachments(new GLenum
[numAttachments
]);
4869 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4870 GLenum attachment
= attachments
[i
];
4871 if (!framebuffer
&& GetBackbufferServiceId()) {
4872 switch (attachment
) {
4874 attachment
= GL_COLOR_ATTACHMENT0
;
4877 attachment
= GL_DEPTH_ATTACHMENT
;
4879 case GL_STENCIL_EXT
:
4880 attachment
= GL_STENCIL_ATTACHMENT
;
4887 translated_attachments
[i
] = attachment
;
4890 ScopedRenderTo
do_render(framebuffer
);
4891 if (feature_info_
->gl_version_info().is_es3
) {
4892 glInvalidateFramebuffer(
4893 target
, numAttachments
, translated_attachments
.get());
4895 glDiscardFramebufferEXT(
4896 target
, numAttachments
, translated_attachments
.get());
4900 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index
) {
4901 if (state_
.vertex_attrib_manager
->Enable(index
, true)) {
4902 glEnableVertexAttribArray(index
);
4905 GL_INVALID_VALUE
, "glEnableVertexAttribArray", "index out of range");
4909 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target
) {
4910 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
4913 !texture_manager()->CanGenerateMipmaps(texture_ref
)) {
4915 GL_INVALID_OPERATION
, "glGenerateMipmap", "Can not generate mips");
4919 if (target
== GL_TEXTURE_CUBE_MAP
) {
4920 for (int i
= 0; i
< 6; ++i
) {
4921 GLenum face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ i
;
4922 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, face
, 0)) {
4924 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
4929 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
, 0)) {
4931 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
4936 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4937 // Workaround for Mac driver bug. In the large scheme of things setting
4938 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4939 // hit so there's probably no need to make this conditional. The bug appears
4940 // to be that if the filtering mode is set to something that doesn't require
4941 // mipmaps for rendering, or is never set to something other than the default,
4942 // then glGenerateMipmap misbehaves.
4943 if (workarounds().set_texture_filter_before_generating_mipmap
) {
4944 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST_MIPMAP_NEAREST
);
4946 glGenerateMipmapEXT(target
);
4947 if (workarounds().set_texture_filter_before_generating_mipmap
) {
4948 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
,
4949 texture_ref
->texture()->min_filter());
4951 GLenum error
= LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4952 if (error
== GL_NO_ERROR
) {
4953 texture_manager()->MarkMipmapsGenerated(texture_ref
);
4957 bool GLES2DecoderImpl::GetHelper(
4958 GLenum pname
, GLint
* params
, GLsizei
* num_written
) {
4959 DCHECK(num_written
);
4960 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
4962 case GL_IMPLEMENTATION_COLOR_READ_FORMAT
:
4964 // Return the GL implementation's preferred format and (see below type)
4965 // if we have the GL extension that exposes this. This allows the GPU
4966 // client to use the implementation's preferred format for glReadPixels
4967 // for optimisation.
4969 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4970 // case when requested on integer/floating point buffers but which is
4971 // acceptable on GLES2 and with the GL_OES_read_format extension.
4973 // Therefore if an error occurs we swallow the error and use the
4974 // internal implementation.
4976 if (context_
->HasExtension("GL_OES_read_format")) {
4977 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
4979 glGetIntegerv(pname
, params
);
4980 if (glGetError() == GL_NO_ERROR
)
4983 *params
= GLES2Util::GetPreferredGLReadPixelsFormat(
4984 GetBoundReadFrameBufferInternalFormat());
4987 case GL_IMPLEMENTATION_COLOR_READ_TYPE
:
4990 if (context_
->HasExtension("GL_OES_read_format")) {
4991 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
4993 glGetIntegerv(pname
, params
);
4994 if (glGetError() == GL_NO_ERROR
)
4997 *params
= GLES2Util::GetPreferredGLReadPixelsType(
4998 GetBoundReadFrameBufferInternalFormat(),
4999 GetBoundReadFrameBufferTextureType());
5002 case GL_MAX_FRAGMENT_UNIFORM_VECTORS
:
5005 *params
= group_
->max_fragment_uniform_vectors();
5008 case GL_MAX_VARYING_VECTORS
:
5011 *params
= group_
->max_varying_vectors();
5014 case GL_MAX_VERTEX_UNIFORM_VECTORS
:
5017 *params
= group_
->max_vertex_uniform_vectors();
5022 if (unsafe_es3_apis_enabled()) {
5024 case GL_MAX_VARYING_COMPONENTS
: {
5025 if (feature_info_
->gl_version_info().is_es
) {
5026 // We can just delegate this query to the driver.
5030 // GL_MAX_VARYING_COMPONENTS is deprecated in the desktop
5031 // OpenGL core profile, so for simplicity, just compute it
5032 // from GL_MAX_VARYING_VECTORS on non-OpenGL ES
5034 GLint max_varying_vectors
= 0;
5035 glGetIntegerv(GL_MAX_VARYING_VECTORS
, &max_varying_vectors
);
5038 *params
= max_varying_vectors
* 4;
5042 case GL_READ_BUFFER
:
5045 Framebuffer
* framebuffer
=
5046 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER
);
5049 read_buffer
= framebuffer
->read_buffer();
5051 read_buffer
= back_buffer_read_buffer_
;
5053 *params
= static_cast<GLint
>(read_buffer
);
5059 case GL_MAX_VIEWPORT_DIMS
:
5060 if (offscreen_target_frame_buffer_
.get()) {
5063 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
5064 params
[1] = renderbuffer_manager()->max_renderbuffer_size();
5069 case GL_MAX_SAMPLES
:
5072 params
[0] = renderbuffer_manager()->max_samples();
5075 case GL_MAX_RENDERBUFFER_SIZE
:
5078 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
5081 case GL_MAX_TEXTURE_SIZE
:
5084 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D
);
5087 case GL_MAX_CUBE_MAP_TEXTURE_SIZE
:
5090 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP
);
5093 case GL_MAX_COLOR_ATTACHMENTS_EXT
:
5096 params
[0] = group_
->max_color_attachments();
5099 case GL_MAX_DRAW_BUFFERS_ARB
:
5102 params
[0] = group_
->max_draw_buffers();
5109 Framebuffer
* framebuffer
=
5110 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5112 if (framebuffer
->HasAlphaMRT() &&
5113 framebuffer
->HasSameInternalFormatsMRT()) {
5114 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
5115 glGetFramebufferAttachmentParameterivEXT(
5116 GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
5117 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE
, &v
);
5119 glGetIntegerv(GL_ALPHA_BITS
, &v
);
5123 v
= (BackBufferHasAlpha() ? 8 : 0);
5132 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
5133 Framebuffer
* framebuffer
=
5134 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5136 glGetFramebufferAttachmentParameterivEXT(
5137 GL_FRAMEBUFFER
, GL_DEPTH_ATTACHMENT
,
5138 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE
, &v
);
5140 v
= (back_buffer_has_depth_
? 24 : 0);
5143 glGetIntegerv(GL_DEPTH_BITS
, &v
);
5145 params
[0] = BoundFramebufferHasDepthAttachment() ? v
: 0;
5154 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
5155 Framebuffer
* framebuffer
=
5156 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5158 GLenum framebuffer_enum
= 0;
5161 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE
;
5164 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE
;
5167 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE
;
5170 glGetFramebufferAttachmentParameterivEXT(
5171 GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
, framebuffer_enum
, &v
);
5176 glGetIntegerv(pname
, &v
);
5181 case GL_STENCIL_BITS
:
5185 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
5186 Framebuffer
* framebuffer
=
5187 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5189 glGetFramebufferAttachmentParameterivEXT(
5190 GL_FRAMEBUFFER
, GL_STENCIL_ATTACHMENT
,
5191 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE
, &v
);
5193 v
= (back_buffer_has_stencil_
? 8 : 0);
5196 glGetIntegerv(GL_STENCIL_BITS
, &v
);
5198 params
[0] = BoundFramebufferHasStencilAttachment() ? v
: 0;
5201 case GL_COMPRESSED_TEXTURE_FORMATS
:
5202 *num_written
= validators_
->compressed_texture_format
.GetValues().size();
5204 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
5205 params
[ii
] = validators_
->compressed_texture_format
.GetValues()[ii
];
5209 case GL_NUM_COMPRESSED_TEXTURE_FORMATS
:
5212 *params
= validators_
->compressed_texture_format
.GetValues().size();
5215 case GL_NUM_SHADER_BINARY_FORMATS
:
5218 *params
= validators_
->shader_binary_format
.GetValues().size();
5221 case GL_SHADER_BINARY_FORMATS
:
5222 *num_written
= validators_
->shader_binary_format
.GetValues().size();
5224 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
5225 params
[ii
] = validators_
->shader_binary_format
.GetValues()[ii
];
5229 case GL_SHADER_COMPILER
:
5235 case GL_ARRAY_BUFFER_BINDING
:
5238 *params
= GetClientId(
5239 buffer_manager(), state_
.bound_array_buffer
.get());
5242 case GL_ELEMENT_ARRAY_BUFFER_BINDING
:
5245 *params
= GetClientId(
5247 state_
.vertex_attrib_manager
->element_array_buffer());
5250 case GL_COPY_READ_BUFFER_BINDING
:
5253 *params
= GetClientId(
5254 buffer_manager(), state_
.bound_copy_read_buffer
.get());
5257 case GL_COPY_WRITE_BUFFER_BINDING
:
5260 *params
= GetClientId(
5261 buffer_manager(), state_
.bound_copy_write_buffer
.get());
5264 case GL_PIXEL_PACK_BUFFER_BINDING
:
5267 *params
= GetClientId(
5268 buffer_manager(), state_
.bound_pixel_pack_buffer
.get());
5271 case GL_PIXEL_UNPACK_BUFFER_BINDING
:
5274 *params
= GetClientId(
5275 buffer_manager(), state_
.bound_pixel_unpack_buffer
.get());
5278 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING
:
5281 *params
= GetClientId(
5282 buffer_manager(), state_
.bound_transform_feedback_buffer
.get());
5285 case GL_UNIFORM_BUFFER_BINDING
:
5288 *params
= GetClientId(
5289 buffer_manager(), state_
.bound_uniform_buffer
.get());
5292 case GL_FRAMEBUFFER_BINDING
:
5293 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
5296 *params
= GetClientId(
5297 framebuffer_manager(),
5298 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
));
5301 case GL_READ_FRAMEBUFFER_BINDING_EXT
:
5304 *params
= GetClientId(
5305 framebuffer_manager(),
5306 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
));
5309 case GL_RENDERBUFFER_BINDING
:
5312 Renderbuffer
* renderbuffer
=
5313 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5315 *params
= renderbuffer
->client_id();
5321 case GL_CURRENT_PROGRAM
:
5324 *params
= GetClientId(program_manager(), state_
.current_program
.get());
5327 case GL_VERTEX_ARRAY_BINDING_OES
:
5330 if (state_
.vertex_attrib_manager
.get() !=
5331 state_
.default_vertex_attrib_manager
.get()) {
5332 GLuint client_id
= 0;
5333 vertex_array_manager_
->GetClientId(
5334 state_
.vertex_attrib_manager
->service_id(), &client_id
);
5335 *params
= client_id
;
5341 case GL_TEXTURE_BINDING_2D
:
5344 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5345 if (unit
.bound_texture_2d
.get()) {
5346 *params
= unit
.bound_texture_2d
->client_id();
5352 case GL_TEXTURE_BINDING_CUBE_MAP
:
5355 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5356 if (unit
.bound_texture_cube_map
.get()) {
5357 *params
= unit
.bound_texture_cube_map
->client_id();
5363 case GL_TEXTURE_BINDING_EXTERNAL_OES
:
5366 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5367 if (unit
.bound_texture_external_oes
.get()) {
5368 *params
= unit
.bound_texture_external_oes
->client_id();
5374 case GL_TEXTURE_BINDING_RECTANGLE_ARB
:
5377 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5378 if (unit
.bound_texture_rectangle_arb
.get()) {
5379 *params
= unit
.bound_texture_rectangle_arb
->client_id();
5385 case GL_BIND_GENERATES_RESOURCE_CHROMIUM
:
5388 params
[0] = group_
->bind_generates_resource() ? 1 : 0;
5392 if (pname
>= GL_DRAW_BUFFER0_ARB
&&
5393 pname
< GL_DRAW_BUFFER0_ARB
+ group_
->max_draw_buffers()) {
5396 Framebuffer
* framebuffer
=
5397 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
5399 params
[0] = framebuffer
->GetDrawBuffer(pname
);
5400 } else { // backbuffer
5401 if (pname
== GL_DRAW_BUFFER0_ARB
)
5402 params
[0] = back_buffer_draw_buffer_
;
5404 params
[0] = GL_NONE
;
5409 *num_written
= util_
.GLGetNumValuesReturned(pname
);
5414 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
5415 GLenum pname
, GLsizei
* num_values
) {
5416 if (state_
.GetStateAsGLint(pname
, NULL
, num_values
)) {
5419 return GetHelper(pname
, NULL
, num_values
);
5422 GLenum
GLES2DecoderImpl::AdjustGetPname(GLenum pname
) {
5423 if (GL_MAX_SAMPLES
== pname
&&
5424 features().use_img_for_multisampled_render_to_texture
) {
5425 return GL_MAX_SAMPLES_IMG
;
5430 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname
, GLboolean
* params
) {
5432 GLsizei num_written
= 0;
5433 if (GetNumValuesReturnedForGLGet(pname
, &num_written
)) {
5434 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
5435 if (!state_
.GetStateAsGLint(pname
, values
.get(), &num_written
)) {
5436 GetHelper(pname
, values
.get(), &num_written
);
5438 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
5439 params
[ii
] = static_cast<GLboolean
>(values
[ii
]);
5442 pname
= AdjustGetPname(pname
);
5443 glGetBooleanv(pname
, params
);
5447 void GLES2DecoderImpl::DoGetFloatv(GLenum pname
, GLfloat
* params
) {
5449 GLsizei num_written
= 0;
5450 if (!state_
.GetStateAsGLfloat(pname
, params
, &num_written
)) {
5451 if (GetHelper(pname
, NULL
, &num_written
)) {
5452 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
5453 GetHelper(pname
, values
.get(), &num_written
);
5454 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
5455 params
[ii
] = static_cast<GLfloat
>(values
[ii
]);
5458 pname
= AdjustGetPname(pname
);
5459 glGetFloatv(pname
, params
);
5464 void GLES2DecoderImpl::DoGetInteger64v(GLenum pname
, GLint64
* params
) {
5466 if (unsafe_es3_apis_enabled()) {
5468 case GL_MAX_ELEMENT_INDEX
: {
5469 if (feature_info_
->gl_version_info().IsAtLeastGLES(3, 0) ||
5470 feature_info_
->gl_version_info().IsAtLeastGL(4, 3)) {
5471 glGetInteger64v(GL_MAX_ELEMENT_INDEX
, params
);
5473 // Assume that desktop GL implementations can generally support
5476 *params
= std::numeric_limits
<unsigned int>::max();
5483 pname
= AdjustGetPname(pname
);
5484 glGetInteger64v(pname
, params
);
5487 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname
, GLint
* params
) {
5489 GLsizei num_written
;
5490 if (!state_
.GetStateAsGLint(pname
, params
, &num_written
) &&
5491 !GetHelper(pname
, params
, &num_written
)) {
5492 pname
= AdjustGetPname(pname
);
5493 glGetIntegerv(pname
, params
);
5497 void GLES2DecoderImpl::DoGetProgramiv(
5498 GLuint program_id
, GLenum pname
, GLint
* params
) {
5499 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetProgramiv");
5503 program
->GetProgramiv(pname
, params
);
5506 void GLES2DecoderImpl::DoGetBufferParameteri64v(
5507 GLenum target
, GLenum pname
, GLint64
* params
) {
5508 // Just delegate it. Some validation is actually done before this.
5509 buffer_manager()->ValidateAndDoGetBufferParameteri64v(
5510 &state_
, target
, pname
, params
);
5513 void GLES2DecoderImpl::DoGetBufferParameteriv(
5514 GLenum target
, GLenum pname
, GLint
* params
) {
5515 // Just delegate it. Some validation is actually done before this.
5516 buffer_manager()->ValidateAndDoGetBufferParameteriv(
5517 &state_
, target
, pname
, params
);
5520 void GLES2DecoderImpl::DoBindAttribLocation(
5521 GLuint program_id
, GLuint index
, const char* name
) {
5522 if (!StringIsValidForGLES(name
)) {
5524 GL_INVALID_VALUE
, "glBindAttribLocation", "Invalid character");
5527 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
5529 GL_INVALID_OPERATION
, "glBindAttribLocation", "reserved prefix");
5532 if (index
>= group_
->max_vertex_attribs()) {
5534 GL_INVALID_VALUE
, "glBindAttribLocation", "index out of range");
5537 Program
* program
= GetProgramInfoNotShader(
5538 program_id
, "glBindAttribLocation");
5542 // At this point, the program's shaders may not be translated yet,
5543 // therefore, we may not find the hashed attribute name.
5544 // glBindAttribLocation call with original name is useless.
5545 // So instead, we should simply cache the binding, and then call
5546 // Program::ExecuteBindAttribLocationCalls() right before link.
5547 program
->SetAttribLocationBinding(name
, static_cast<GLint
>(index
));
5548 // TODO(zmo): Get rid of the following glBindAttribLocation call.
5549 glBindAttribLocation(program
->service_id(), index
, name
);
5552 error::Error
GLES2DecoderImpl::HandleBindAttribLocationBucket(
5553 uint32 immediate_data_size
,
5554 const void* cmd_data
) {
5555 const gles2::cmds::BindAttribLocationBucket
& c
=
5556 *static_cast<const gles2::cmds::BindAttribLocationBucket
*>(cmd_data
);
5557 GLuint program
= static_cast<GLuint
>(c
.program
);
5558 GLuint index
= static_cast<GLuint
>(c
.index
);
5559 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
5560 if (!bucket
|| bucket
->size() == 0) {
5561 return error::kInvalidArguments
;
5563 std::string name_str
;
5564 if (!bucket
->GetAsString(&name_str
)) {
5565 return error::kInvalidArguments
;
5567 DoBindAttribLocation(program
, index
, name_str
.c_str());
5568 return error::kNoError
;
5571 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
5572 GLuint program_id
, GLint location
, const char* name
) {
5573 if (!StringIsValidForGLES(name
)) {
5576 "glBindUniformLocationCHROMIUM", "Invalid character");
5579 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
5581 GL_INVALID_OPERATION
,
5582 "glBindUniformLocationCHROMIUM", "reserved prefix");
5585 if (location
< 0 || static_cast<uint32
>(location
) >=
5586 (group_
->max_fragment_uniform_vectors() +
5587 group_
->max_vertex_uniform_vectors()) * 4) {
5590 "glBindUniformLocationCHROMIUM", "location out of range");
5593 Program
* program
= GetProgramInfoNotShader(
5594 program_id
, "glBindUniformLocationCHROMIUM");
5598 if (!program
->SetUniformLocationBinding(name
, location
)) {
5601 "glBindUniformLocationCHROMIUM", "location out of range");
5605 error::Error
GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
5606 uint32 immediate_data_size
,
5607 const void* cmd_data
) {
5608 const gles2::cmds::BindUniformLocationCHROMIUMBucket
& c
=
5609 *static_cast<const gles2::cmds::BindUniformLocationCHROMIUMBucket
*>(
5611 GLuint program
= static_cast<GLuint
>(c
.program
);
5612 GLint location
= static_cast<GLint
>(c
.location
);
5613 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
5614 if (!bucket
|| bucket
->size() == 0) {
5615 return error::kInvalidArguments
;
5617 std::string name_str
;
5618 if (!bucket
->GetAsString(&name_str
)) {
5619 return error::kInvalidArguments
;
5621 DoBindUniformLocationCHROMIUM(program
, location
, name_str
.c_str());
5622 return error::kNoError
;
5625 error::Error
GLES2DecoderImpl::HandleDeleteShader(uint32 immediate_data_size
,
5626 const void* cmd_data
) {
5627 const gles2::cmds::DeleteShader
& c
=
5628 *static_cast<const gles2::cmds::DeleteShader
*>(cmd_data
);
5629 GLuint client_id
= c
.shader
;
5631 Shader
* shader
= GetShader(client_id
);
5633 if (!shader
->IsDeleted()) {
5634 shader_manager()->Delete(shader
);
5637 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glDeleteShader", "unknown shader");
5640 return error::kNoError
;
5643 error::Error
GLES2DecoderImpl::HandleDeleteProgram(uint32 immediate_data_size
,
5644 const void* cmd_data
) {
5645 const gles2::cmds::DeleteProgram
& c
=
5646 *static_cast<const gles2::cmds::DeleteProgram
*>(cmd_data
);
5647 GLuint client_id
= c
.program
;
5649 Program
* program
= GetProgram(client_id
);
5651 if (!program
->IsDeleted()) {
5652 program_manager()->MarkAsDeleted(shader_manager(), program
);
5656 GL_INVALID_VALUE
, "glDeleteProgram", "unknown program");
5659 return error::kNoError
;
5662 error::Error
GLES2DecoderImpl::DoClear(GLbitfield mask
) {
5663 DCHECK(!ShouldDeferDraws());
5664 if (CheckBoundFramebuffersValid("glClear")) {
5666 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
5667 if (workarounds().gl_clear_broken
) {
5668 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::ClearWorkaround",
5670 if (!BoundFramebufferHasDepthAttachment())
5671 mask
&= ~GL_DEPTH_BUFFER_BIT
;
5672 if (!BoundFramebufferHasStencilAttachment())
5673 mask
&= ~GL_STENCIL_BUFFER_BIT
;
5674 clear_framebuffer_blit_
->ClearFramebuffer(
5675 this, GetBoundReadFrameBufferSize(), mask
, state_
.color_clear_red
,
5676 state_
.color_clear_green
, state_
.color_clear_blue
,
5677 state_
.color_clear_alpha
, state_
.depth_clear
, state_
.stencil_clear
);
5678 return error::kNoError
;
5682 return error::kNoError
;
5685 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
5686 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
5687 GLuint client_renderbuffer_id
) {
5688 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5691 GL_INVALID_OPERATION
,
5692 "glFramebufferRenderbuffer", "no framebuffer bound");
5695 GLuint service_id
= 0;
5696 Renderbuffer
* renderbuffer
= NULL
;
5697 if (client_renderbuffer_id
) {
5698 renderbuffer
= GetRenderbuffer(client_renderbuffer_id
);
5699 if (!renderbuffer
) {
5701 GL_INVALID_OPERATION
,
5702 "glFramebufferRenderbuffer", "unknown renderbuffer");
5705 service_id
= renderbuffer
->service_id();
5707 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
5708 glFramebufferRenderbufferEXT(
5709 target
, attachment
, renderbuffertarget
, service_id
);
5710 GLenum error
= LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
5711 if (error
== GL_NO_ERROR
) {
5712 framebuffer
->AttachRenderbuffer(attachment
, renderbuffer
);
5714 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
5715 framebuffer_state_
.clear_state_dirty
= true;
5720 void GLES2DecoderImpl::DoDisable(GLenum cap
) {
5721 if (SetCapabilityState(cap
, false)) {
5726 void GLES2DecoderImpl::DoEnable(GLenum cap
) {
5727 if (SetCapabilityState(cap
, true)) {
5732 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear
, GLclampf zfar
) {
5733 state_
.z_near
= std::min(1.0f
, std::max(0.0f
, znear
));
5734 state_
.z_far
= std::min(1.0f
, std::max(0.0f
, zfar
));
5735 glDepthRange(znear
, zfar
);
5738 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value
, GLboolean invert
) {
5739 state_
.sample_coverage_value
= std::min(1.0f
, std::max(0.0f
, value
));
5740 state_
.sample_coverage_invert
= (invert
!= 0);
5741 glSampleCoverage(state_
.sample_coverage_value
, invert
);
5744 // Assumes framebuffer is complete.
5745 void GLES2DecoderImpl::ClearUnclearedAttachments(
5746 GLenum target
, Framebuffer
* framebuffer
) {
5747 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
5748 // bind this to the DRAW point, clear then bind back to READ
5749 // TODO(gman): I don't think there is any guarantee that an FBO that
5750 // is complete on the READ attachment will be complete as a DRAW
5752 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, 0);
5753 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, framebuffer
->service_id());
5755 GLbitfield clear_bits
= 0;
5756 if (framebuffer
->HasUnclearedColorAttachments()) {
5757 // We should always use alpha == 0 here, because 1) some draw buffers may
5758 // have alpha and some may not; 2) we won't have the same situation as the
5759 // back buffer where alpha channel exists but is not requested.
5760 glClearColor(0.0f
, 0.0f
, 0.0f
, 0.0f
);
5761 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
5762 clear_bits
|= GL_COLOR_BUFFER_BIT
;
5763 if (feature_info_
->feature_flags().ext_draw_buffers
)
5764 framebuffer
->PrepareDrawBuffersForClear();
5767 if (framebuffer
->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT
) ||
5768 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
5770 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
5771 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
5772 clear_bits
|= GL_STENCIL_BUFFER_BIT
;
5775 if (framebuffer
->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT
) ||
5776 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
5778 state_
.SetDeviceDepthMask(GL_TRUE
);
5779 clear_bits
|= GL_DEPTH_BUFFER_BIT
;
5782 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5783 glClear(clear_bits
);
5785 if ((clear_bits
& GL_COLOR_BUFFER_BIT
) != 0 &&
5786 feature_info_
->feature_flags().ext_draw_buffers
)
5787 framebuffer
->RestoreDrawBuffersAfterClear();
5789 framebuffer_manager()->MarkAttachmentsAsCleared(
5790 framebuffer
, renderbuffer_manager(), texture_manager());
5792 RestoreClearState();
5794 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
5795 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, framebuffer
->service_id());
5796 Framebuffer
* draw_framebuffer
=
5797 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5798 GLuint service_id
= draw_framebuffer
? draw_framebuffer
->service_id() :
5799 GetBackbufferServiceId();
5800 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, service_id
);
5804 void GLES2DecoderImpl::RestoreClearState() {
5805 framebuffer_state_
.clear_state_dirty
= true;
5807 state_
.color_clear_red
, state_
.color_clear_green
, state_
.color_clear_blue
,
5808 state_
.color_clear_alpha
);
5809 glClearStencil(state_
.stencil_clear
);
5810 glClearDepth(state_
.depth_clear
);
5811 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
,
5812 state_
.enable_flags
.scissor_test
);
5813 glScissor(state_
.scissor_x
, state_
.scissor_y
, state_
.scissor_width
,
5814 state_
.scissor_height
);
5817 GLenum
GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target
) {
5818 Framebuffer
* framebuffer
=
5819 GetFramebufferInfoForTarget(target
);
5821 return GL_FRAMEBUFFER_COMPLETE
;
5823 GLenum completeness
= framebuffer
->IsPossiblyComplete();
5824 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
5825 return completeness
;
5827 return framebuffer
->GetStatus(texture_manager(), target
);
5830 void GLES2DecoderImpl::DoFramebufferTexture2D(
5831 GLenum target
, GLenum attachment
, GLenum textarget
,
5832 GLuint client_texture_id
, GLint level
) {
5833 DoFramebufferTexture2DCommon(
5834 "glFramebufferTexture2D", target
, attachment
,
5835 textarget
, client_texture_id
, level
, 0);
5838 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5839 GLenum target
, GLenum attachment
, GLenum textarget
,
5840 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
5841 DoFramebufferTexture2DCommon(
5842 "glFramebufferTexture2DMultisample", target
, attachment
,
5843 textarget
, client_texture_id
, level
, samples
);
5846 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5847 const char* name
, GLenum target
, GLenum attachment
, GLenum textarget
,
5848 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
5849 if (samples
> renderbuffer_manager()->max_samples()) {
5852 "glFramebufferTexture2DMultisample", "samples too large");
5855 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5858 GL_INVALID_OPERATION
,
5859 name
, "no framebuffer bound.");
5862 GLuint service_id
= 0;
5863 TextureRef
* texture_ref
= NULL
;
5864 if (client_texture_id
) {
5865 texture_ref
= GetTexture(client_texture_id
);
5868 GL_INVALID_OPERATION
,
5869 name
, "unknown texture_ref");
5872 service_id
= texture_ref
->service_id();
5875 if (!texture_manager()->ValidForTarget(textarget
, level
, 0, 0, 1)) {
5878 name
, "level out of range");
5883 DoWillUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
5885 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name
);
5887 glFramebufferTexture2DEXT(target
, attachment
, textarget
, service_id
, level
);
5889 if (features().use_img_for_multisampled_render_to_texture
) {
5890 glFramebufferTexture2DMultisampleIMG(target
, attachment
, textarget
,
5891 service_id
, level
, samples
);
5893 glFramebufferTexture2DMultisampleEXT(target
, attachment
, textarget
,
5894 service_id
, level
, samples
);
5897 GLenum error
= LOCAL_PEEK_GL_ERROR(name
);
5898 if (error
== GL_NO_ERROR
) {
5899 framebuffer
->AttachTexture(attachment
, texture_ref
, textarget
, level
,
5902 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
5903 framebuffer_state_
.clear_state_dirty
= true;
5907 DoDidUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
5912 void GLES2DecoderImpl::DoFramebufferTextureLayer(
5913 GLenum target
, GLenum attachment
, GLuint client_texture_id
,
5914 GLint level
, GLint layer
) {
5915 // TODO(zmo): Unsafe ES3 API, missing states update.
5916 GLuint service_id
= 0;
5917 TextureRef
* texture_ref
= NULL
;
5918 if (client_texture_id
) {
5919 texture_ref
= GetTexture(client_texture_id
);
5922 GL_INVALID_OPERATION
,
5923 "glFramebufferTextureLayer", "unknown texture_ref");
5926 service_id
= texture_ref
->service_id();
5928 glFramebufferTextureLayer(target
, attachment
, service_id
, level
, layer
);
5931 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5932 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
) {
5933 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5936 GL_INVALID_OPERATION
,
5937 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5940 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME
) {
5941 const Framebuffer::Attachment
* attachment_object
=
5942 framebuffer
->GetAttachment(attachment
);
5943 *params
= attachment_object
? attachment_object
->object_name() : 0;
5945 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT
&&
5946 features().use_img_for_multisampled_render_to_texture
) {
5947 pname
= GL_TEXTURE_SAMPLES_IMG
;
5949 glGetFramebufferAttachmentParameterivEXT(target
, attachment
, pname
, params
);
5953 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5954 GLenum target
, GLenum pname
, GLint
* params
) {
5955 Renderbuffer
* renderbuffer
=
5956 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5957 if (!renderbuffer
) {
5959 GL_INVALID_OPERATION
,
5960 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5964 EnsureRenderbufferBound();
5966 case GL_RENDERBUFFER_INTERNAL_FORMAT
:
5967 *params
= renderbuffer
->internal_format();
5969 case GL_RENDERBUFFER_WIDTH
:
5970 *params
= renderbuffer
->width();
5972 case GL_RENDERBUFFER_HEIGHT
:
5973 *params
= renderbuffer
->height();
5975 case GL_RENDERBUFFER_SAMPLES_EXT
:
5976 if (features().use_img_for_multisampled_render_to_texture
) {
5977 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_IMG
,
5980 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_EXT
,
5984 glGetRenderbufferParameterivEXT(target
, pname
, params
);
5989 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5990 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
5991 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
5992 GLbitfield mask
, GLenum filter
) {
5993 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5995 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5999 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
6000 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
6001 BlitFramebufferHelper(
6002 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
6003 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
,
6004 state_
.enable_flags
.scissor_test
);
6007 void GLES2DecoderImpl::EnsureRenderbufferBound() {
6008 if (!state_
.bound_renderbuffer_valid
) {
6009 state_
.bound_renderbuffer_valid
= true;
6010 glBindRenderbufferEXT(GL_RENDERBUFFER
,
6011 state_
.bound_renderbuffer
.get()
6012 ? state_
.bound_renderbuffer
->service_id()
6017 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
6018 const FeatureInfo
* feature_info
,
6021 GLenum internal_format
,
6024 // TODO(sievers): This could be resolved at the GL binding level, but the
6025 // binding process is currently a bit too 'brute force'.
6026 if (feature_info
->gl_version_info().is_angle
) {
6027 glRenderbufferStorageMultisampleANGLE(
6028 target
, samples
, internal_format
, width
, height
);
6029 } else if (feature_info
->feature_flags().use_core_framebuffer_multisample
) {
6030 glRenderbufferStorageMultisample(
6031 target
, samples
, internal_format
, width
, height
);
6033 glRenderbufferStorageMultisampleEXT(
6034 target
, samples
, internal_format
, width
, height
);
6038 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0
,
6048 // TODO(sievers): This could be resolved at the GL binding level, but the
6049 // binding process is currently a bit too 'brute force'.
6050 if (feature_info_
->gl_version_info().is_angle
) {
6051 glBlitFramebufferANGLE(
6052 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
6053 } else if (feature_info_
->feature_flags().use_core_framebuffer_multisample
) {
6055 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
6057 glBlitFramebufferEXT(
6058 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
6062 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
6064 GLenum internalformat
,
6067 if (samples
> renderbuffer_manager()->max_samples()) {
6070 "glRenderbufferStorageMultisample", "samples too large");
6074 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
6075 height
> renderbuffer_manager()->max_renderbuffer_size()) {
6078 "glRenderbufferStorageMultisample", "dimensions too large");
6082 uint32 estimated_size
= 0;
6083 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6084 width
, height
, samples
, internalformat
, &estimated_size
)) {
6087 "glRenderbufferStorageMultisample", "dimensions too large");
6091 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
6094 "glRenderbufferStorageMultisample", "out of memory");
6101 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
6102 GLenum target
, GLsizei samples
, GLenum internalformat
,
6103 GLsizei width
, GLsizei height
) {
6104 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
6105 if (!renderbuffer
) {
6106 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
6107 "glRenderbufferStorageMultisampleCHROMIUM",
6108 "no renderbuffer bound");
6112 if (!ValidateRenderbufferStorageMultisample(
6113 samples
, internalformat
, width
, height
)) {
6117 EnsureRenderbufferBound();
6118 GLenum impl_format
=
6119 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6121 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
6122 "glRenderbufferStorageMultisampleCHROMIUM");
6123 RenderbufferStorageMultisampleHelper(
6124 feature_info_
.get(), target
, samples
, impl_format
, width
, height
);
6126 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
6127 if (error
== GL_NO_ERROR
) {
6128 if (workarounds().validate_multisample_buffer_allocation
) {
6129 if (!VerifyMultisampleRenderbufferIntegrity(
6130 renderbuffer
->service_id(), impl_format
)) {
6133 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
6138 // TODO(gman): If renderbuffers tracked which framebuffers they were
6139 // attached to we could just mark those framebuffers as not complete.
6140 framebuffer_manager()->IncFramebufferStateChangeCount();
6141 renderbuffer_manager()->SetInfo(
6142 renderbuffer
, samples
, internalformat
, width
, height
);
6146 // This is the handler for multisampled_render_to_texture extensions.
6147 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
6148 GLenum target
, GLsizei samples
, GLenum internalformat
,
6149 GLsizei width
, GLsizei height
) {
6150 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
6151 if (!renderbuffer
) {
6152 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
6153 "glRenderbufferStorageMultisampleEXT",
6154 "no renderbuffer bound");
6158 if (!ValidateRenderbufferStorageMultisample(
6159 samples
, internalformat
, width
, height
)) {
6163 EnsureRenderbufferBound();
6164 GLenum impl_format
=
6165 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6167 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
6168 if (features().use_img_for_multisampled_render_to_texture
) {
6169 glRenderbufferStorageMultisampleIMG(
6170 target
, samples
, impl_format
, width
, height
);
6172 glRenderbufferStorageMultisampleEXT(
6173 target
, samples
, impl_format
, width
, height
);
6175 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
6176 if (error
== GL_NO_ERROR
) {
6177 // TODO(gman): If renderbuffers tracked which framebuffers they were
6178 // attached to we could just mark those framebuffers as not complete.
6179 framebuffer_manager()->IncFramebufferStateChangeCount();
6180 renderbuffer_manager()->SetInfo(
6181 renderbuffer
, samples
, internalformat
, width
, height
);
6185 // This function validates the allocation of a multisampled renderbuffer
6186 // by clearing it to a key color, blitting the contents to a texture, and
6187 // reading back the color to ensure it matches the key.
6188 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
6189 GLuint renderbuffer
, GLenum format
) {
6191 // Only validate color buffers.
6192 // These formats have been selected because they are very common or are known
6193 // to be used by the WebGL backbuffer. If problems are observed with other
6194 // color formats they can be added here.
6205 GLint draw_framebuffer
, read_framebuffer
;
6207 // Cache framebuffer and texture bindings.
6208 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING
, &draw_framebuffer
);
6209 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING
, &read_framebuffer
);
6211 if (!validation_texture_
) {
6212 GLint bound_texture
;
6213 glGetIntegerv(GL_TEXTURE_BINDING_2D
, &bound_texture
);
6215 // Create additional resources needed for the verification.
6216 glGenTextures(1, &validation_texture_
);
6217 glGenFramebuffersEXT(1, &validation_fbo_multisample_
);
6218 glGenFramebuffersEXT(1, &validation_fbo_
);
6220 // Texture only needs to be 1x1.
6221 glBindTexture(GL_TEXTURE_2D
, validation_texture_
);
6222 // TODO(erikchen): When Chrome on Mac is linked against an OSX 10.9+ SDK, a
6223 // multisample will fail if the color format of the source and destination
6224 // do not match. Here, we assume that the source is GL_RGBA, and make the
6225 // destination GL_RGBA. http://crbug.com/484203
6226 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, 1, 1, 0, GL_RGBA
,
6227 GL_UNSIGNED_BYTE
, NULL
);
6229 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
6230 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
6231 GL_TEXTURE_2D
, validation_texture_
, 0);
6233 glBindTexture(GL_TEXTURE_2D
, bound_texture
);
6236 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
6237 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
6238 GL_RENDERBUFFER
, renderbuffer
);
6240 // Cache current state and reset it to the values we require.
6241 GLboolean scissor_enabled
= false;
6242 glGetBooleanv(GL_SCISSOR_TEST
, &scissor_enabled
);
6243 if (scissor_enabled
)
6244 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
6246 GLboolean color_mask
[4] = {GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
};
6247 glGetBooleanv(GL_COLOR_WRITEMASK
, color_mask
);
6248 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
6250 GLfloat clear_color
[4] = {0.0f
, 0.0f
, 0.0f
, 0.0f
};
6251 glGetFloatv(GL_COLOR_CLEAR_VALUE
, clear_color
);
6252 glClearColor(1.0f
, 0.0f
, 1.0f
, 1.0f
);
6254 // Clear the buffer to the desired key color.
6255 glClear(GL_COLOR_BUFFER_BIT
);
6257 // Blit from the multisample buffer to a standard texture.
6258 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, validation_fbo_multisample_
);
6259 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, validation_fbo_
);
6261 BlitFramebufferHelper(
6262 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
6264 // Read a pixel from the buffer.
6265 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
6267 unsigned char pixel
[3] = {0, 0, 0};
6268 glReadPixels(0, 0, 1, 1, GL_RGB
, GL_UNSIGNED_BYTE
, &pixel
);
6270 // Detach the renderbuffer.
6271 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
6272 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
6273 GL_RENDERBUFFER
, 0);
6275 // Restore cached state.
6276 if (scissor_enabled
)
6277 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
6279 state_
.SetDeviceColorMask(
6280 color_mask
[0], color_mask
[1], color_mask
[2], color_mask
[3]);
6281 glClearColor(clear_color
[0], clear_color
[1], clear_color
[2], clear_color
[3]);
6282 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, draw_framebuffer
);
6283 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, read_framebuffer
);
6285 // Return true if the pixel matched the desired key color.
6286 return (pixel
[0] == 0xFF &&
6291 void GLES2DecoderImpl::DoRenderbufferStorage(
6292 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
) {
6293 Renderbuffer
* renderbuffer
=
6294 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
6295 if (!renderbuffer
) {
6297 GL_INVALID_OPERATION
,
6298 "glRenderbufferStorage", "no renderbuffer bound");
6302 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
6303 height
> renderbuffer_manager()->max_renderbuffer_size()) {
6305 GL_INVALID_VALUE
, "glRenderbufferStorage", "dimensions too large");
6309 uint32 estimated_size
= 0;
6310 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6311 width
, height
, 1, internalformat
, &estimated_size
)) {
6313 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "dimensions too large");
6317 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
6319 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "out of memory");
6323 EnsureRenderbufferBound();
6324 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
6325 glRenderbufferStorageEXT(
6327 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6331 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
6332 if (error
== GL_NO_ERROR
) {
6333 // TODO(gman): If tetxures tracked which framebuffers they were attached to
6334 // we could just mark those framebuffers as not complete.
6335 framebuffer_manager()->IncFramebufferStateChangeCount();
6336 renderbuffer_manager()->SetInfo(
6337 renderbuffer
, 1, internalformat
, width
, height
);
6341 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id
) {
6342 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
6343 SCOPED_UMA_HISTOGRAM_TIMER("GPU.DoLinkProgramTime");
6344 Program
* program
= GetProgramInfoNotShader(
6345 program_id
, "glLinkProgram");
6350 LogClientServiceForInfo(program
, program_id
, "glLinkProgram");
6351 if (program
->Link(shader_manager(),
6352 workarounds().count_all_in_varyings_packing
?
6353 Program::kCountAll
: Program::kCountOnlyStaticallyUsed
,
6354 shader_cache_callback_
)) {
6355 if (program
== state_
.current_program
.get()) {
6356 if (workarounds().use_current_program_after_successful_link
)
6357 glUseProgram(program
->service_id());
6358 if (workarounds().clear_uniforms_before_first_program_use
)
6359 program_manager()->ClearUniforms(program
);
6363 // LinkProgram can be very slow. Exit command processing to allow for
6364 // context preemption and GPU watchdog checks.
6365 ExitCommandProcessingEarly();
6368 void GLES2DecoderImpl::DoReadBuffer(GLenum src
) {
6375 GLenum upper_limit
= static_cast<GLenum
>(
6376 group_
->max_color_attachments() + GL_COLOR_ATTACHMENT0
);
6377 if (src
< GL_COLOR_ATTACHMENT0
|| src
>= upper_limit
) {
6379 GL_INVALID_ENUM
, "glReadBuffer", "invalid enum for src");
6386 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER
);
6388 if (src
== GL_BACK
) {
6390 GL_INVALID_ENUM
, "glReadBuffer",
6391 "invalid src for a named framebuffer");
6394 framebuffer
->set_read_buffer(src
);
6396 if (src
!= GL_NONE
&& src
!= GL_BACK
) {
6398 GL_INVALID_ENUM
, "glReadBuffer",
6399 "invalid src for the default framebuffer");
6402 back_buffer_read_buffer_
= src
;
6403 if (GetBackbufferServiceId() && src
== GL_BACK
)
6404 src
= GL_COLOR_ATTACHMENT0
;
6409 void GLES2DecoderImpl::DoSamplerParameterfv(
6410 GLuint sampler
, GLenum pname
, const GLfloat
* params
) {
6412 glSamplerParameterf(sampler
, pname
, params
[0]);
6415 void GLES2DecoderImpl::DoSamplerParameteriv(
6416 GLuint sampler
, GLenum pname
, const GLint
* params
) {
6418 glSamplerParameteri(sampler
, pname
, params
[0]);
6421 void GLES2DecoderImpl::DoTexParameterf(
6422 GLenum target
, GLenum pname
, GLfloat param
) {
6423 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6426 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterf", "unknown texture");
6430 texture_manager()->SetParameterf(
6431 "glTexParameterf", GetErrorState(), texture
, pname
, param
);
6434 void GLES2DecoderImpl::DoTexParameteri(
6435 GLenum target
, GLenum pname
, GLint param
) {
6436 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6439 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameteri", "unknown texture");
6443 texture_manager()->SetParameteri(
6444 "glTexParameteri", GetErrorState(), texture
, pname
, param
);
6447 void GLES2DecoderImpl::DoTexParameterfv(
6448 GLenum target
, GLenum pname
, const GLfloat
* params
) {
6449 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6452 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterfv", "unknown texture");
6456 texture_manager()->SetParameterf(
6457 "glTexParameterfv", GetErrorState(), texture
, pname
, *params
);
6460 void GLES2DecoderImpl::DoTexParameteriv(
6461 GLenum target
, GLenum pname
, const GLint
* params
) {
6462 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6466 GL_INVALID_VALUE
, "glTexParameteriv", "unknown texture");
6470 texture_manager()->SetParameteri(
6471 "glTexParameteriv", GetErrorState(), texture
, pname
, *params
);
6474 bool GLES2DecoderImpl::CheckCurrentValuebuffer(const char* function_name
) {
6475 if (!state_
.bound_valuebuffer
.get()) {
6476 // There is no valuebuffer bound
6477 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6478 "no valuebuffer in use");
6484 bool GLES2DecoderImpl::CheckCurrentValuebufferForSubscription(
6485 GLenum subscription
,
6486 const char* function_name
) {
6487 if (!CheckCurrentValuebuffer(function_name
)) {
6490 if (!state_
.bound_valuebuffer
.get()->IsSubscribed(subscription
)) {
6491 // The valuebuffer is not subscribed to the target
6492 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6493 "valuebuffer is not subscribed");
6499 bool GLES2DecoderImpl::CheckSubscriptionTarget(GLint location
,
6500 GLenum subscription
,
6501 const char* function_name
) {
6502 if (!CheckCurrentProgramForUniform(location
, function_name
)) {
6505 GLint real_location
= -1;
6506 GLint array_index
= -1;
6507 const Program::UniformInfo
* info
=
6508 state_
.current_program
->GetUniformInfoByFakeLocation(
6509 location
, &real_location
, &array_index
);
6511 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
, "unknown location");
6514 if ((ValuebufferManager::ApiTypeForSubscriptionTarget(subscription
) &
6515 info
->accepts_api_type
) == 0) {
6516 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6517 "wrong type for subscription");
6523 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name
) {
6524 if (!state_
.current_program
.get()) {
6525 // The program does not exist.
6527 GL_INVALID_OPERATION
, function_name
, "no program in use");
6530 if (!state_
.current_program
->InUse()) {
6532 GL_INVALID_OPERATION
, function_name
, "program not linked");
6538 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
6539 GLint location
, const char* function_name
) {
6540 if (!CheckCurrentProgram(function_name
)) {
6543 return location
!= -1;
6546 bool GLES2DecoderImpl::CheckDrawingFeedbackLoops() {
6547 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
6550 const Framebuffer::Attachment
* attachment
=
6551 framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
);
6555 DCHECK(state_
.current_program
.get());
6556 const Program::SamplerIndices
& sampler_indices
=
6557 state_
.current_program
->sampler_indices();
6558 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6559 const Program::UniformInfo
* uniform_info
=
6560 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6561 DCHECK(uniform_info
);
6562 if (uniform_info
->type
!= GL_SAMPLER_2D
)
6564 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6565 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6566 if (texture_unit_index
>= state_
.texture_units
.size())
6568 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6569 TextureRef
* texture_ref
=
6570 texture_unit
.GetInfoForSamplerType(GL_SAMPLER_2D
).get();
6571 if (attachment
->IsTexture(texture_ref
))
6578 bool GLES2DecoderImpl::CheckUniformForApiType(
6579 const Program::UniformInfo
* info
,
6580 const char* function_name
,
6581 Program::UniformApiType api_type
) {
6583 if ((api_type
& info
->accepts_api_type
) == 0) {
6584 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6585 "wrong uniform function for type");
6591 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
6592 GLint fake_location
,
6593 const char* function_name
,
6594 Program::UniformApiType api_type
,
6595 GLint
* real_location
,
6600 DCHECK(real_location
);
6602 if (!CheckCurrentProgramForUniform(fake_location
, function_name
)) {
6605 GLint array_index
= -1;
6606 const Program::UniformInfo
* info
=
6607 state_
.current_program
->GetUniformInfoByFakeLocation(
6608 fake_location
, real_location
, &array_index
);
6611 GL_INVALID_OPERATION
, function_name
, "unknown location");
6614 if (!CheckUniformForApiType(info
, function_name
, api_type
)) {
6617 if (*count
> 1 && !info
->is_array
) {
6619 GL_INVALID_OPERATION
, function_name
, "count > 1 for non-array");
6622 *count
= std::min(info
->size
- array_index
, *count
);
6630 void GLES2DecoderImpl::DoUniform1i(GLint fake_location
, GLint v0
) {
6633 GLint real_location
= -1;
6634 if (!PrepForSetUniformByLocation(fake_location
,
6636 Program::kUniform1i
,
6642 if (!state_
.current_program
->SetSamplers(
6643 state_
.texture_units
.size(), fake_location
, 1, &v0
)) {
6645 GL_INVALID_VALUE
, "glUniform1i", "texture unit out of range");
6648 glUniform1i(real_location
, v0
);
6651 void GLES2DecoderImpl::DoUniform1iv(
6652 GLint fake_location
, GLsizei count
, const GLint
*value
) {
6654 GLint real_location
= -1;
6655 if (!PrepForSetUniformByLocation(fake_location
,
6657 Program::kUniform1i
,
6663 if (type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_2D_RECT_ARB
||
6664 type
== GL_SAMPLER_CUBE
|| type
== GL_SAMPLER_EXTERNAL_OES
) {
6665 if (!state_
.current_program
->SetSamplers(
6666 state_
.texture_units
.size(), fake_location
, count
, value
)) {
6668 GL_INVALID_VALUE
, "glUniform1iv", "texture unit out of range");
6672 glUniform1iv(real_location
, count
, value
);
6675 void GLES2DecoderImpl::DoUniform1fv(
6676 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6678 GLint real_location
= -1;
6679 if (!PrepForSetUniformByLocation(fake_location
,
6681 Program::kUniform1f
,
6687 if (type
== GL_BOOL
) {
6688 scoped_ptr
<GLint
[]> temp(new GLint
[count
]);
6689 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
6690 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6692 DoUniform1iv(real_location
, count
, temp
.get());
6694 glUniform1fv(real_location
, count
, value
);
6698 void GLES2DecoderImpl::DoUniform2fv(
6699 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6701 GLint real_location
= -1;
6702 if (!PrepForSetUniformByLocation(fake_location
,
6704 Program::kUniform2f
,
6710 if (type
== GL_BOOL_VEC2
) {
6711 GLsizei num_values
= count
* 2;
6712 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6713 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6714 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6716 glUniform2iv(real_location
, count
, temp
.get());
6718 glUniform2fv(real_location
, count
, value
);
6722 void GLES2DecoderImpl::DoUniform3fv(
6723 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6725 GLint real_location
= -1;
6726 if (!PrepForSetUniformByLocation(fake_location
,
6728 Program::kUniform3f
,
6734 if (type
== GL_BOOL_VEC3
) {
6735 GLsizei num_values
= count
* 3;
6736 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6737 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6738 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6740 glUniform3iv(real_location
, count
, temp
.get());
6742 glUniform3fv(real_location
, count
, value
);
6746 void GLES2DecoderImpl::DoUniform4fv(
6747 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6749 GLint real_location
= -1;
6750 if (!PrepForSetUniformByLocation(fake_location
,
6752 Program::kUniform4f
,
6758 if (type
== GL_BOOL_VEC4
) {
6759 GLsizei num_values
= count
* 4;
6760 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6761 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6762 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6764 glUniform4iv(real_location
, count
, temp
.get());
6766 glUniform4fv(real_location
, count
, value
);
6770 void GLES2DecoderImpl::DoUniform2iv(
6771 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6773 GLint real_location
= -1;
6774 if (!PrepForSetUniformByLocation(fake_location
,
6776 Program::kUniform2i
,
6782 glUniform2iv(real_location
, count
, value
);
6785 void GLES2DecoderImpl::DoUniform3iv(
6786 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6788 GLint real_location
= -1;
6789 if (!PrepForSetUniformByLocation(fake_location
,
6791 Program::kUniform3i
,
6797 glUniform3iv(real_location
, count
, value
);
6800 void GLES2DecoderImpl::DoUniform4iv(
6801 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6803 GLint real_location
= -1;
6804 if (!PrepForSetUniformByLocation(fake_location
,
6806 Program::kUniform4i
,
6812 glUniform4iv(real_location
, count
, value
);
6815 void GLES2DecoderImpl::DoUniformMatrix2fv(
6816 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6817 const GLfloat
* value
) {
6819 GLint real_location
= -1;
6820 if (!PrepForSetUniformByLocation(fake_location
,
6821 "glUniformMatrix2fv",
6822 Program::kUniformMatrix2f
,
6828 glUniformMatrix2fv(real_location
, count
, transpose
, value
);
6831 void GLES2DecoderImpl::DoUniformMatrix3fv(
6832 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6833 const GLfloat
* value
) {
6835 GLint real_location
= -1;
6836 if (!PrepForSetUniformByLocation(fake_location
,
6837 "glUniformMatrix3fv",
6838 Program::kUniformMatrix3f
,
6844 glUniformMatrix3fv(real_location
, count
, transpose
, value
);
6847 void GLES2DecoderImpl::DoUniformMatrix4fv(
6848 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6849 const GLfloat
* value
) {
6851 GLint real_location
= -1;
6852 if (!PrepForSetUniformByLocation(fake_location
,
6853 "glUniformMatrix4fv",
6854 Program::kUniformMatrix4f
,
6860 glUniformMatrix4fv(real_location
, count
, transpose
, value
);
6863 void GLES2DecoderImpl::DoUseProgram(GLuint program_id
) {
6864 GLuint service_id
= 0;
6865 Program
* program
= NULL
;
6867 program
= GetProgramInfoNotShader(program_id
, "glUseProgram");
6871 if (!program
->IsValid()) {
6872 // Program was not linked successfully. (ie, glLinkProgram)
6874 GL_INVALID_OPERATION
, "glUseProgram", "program not linked");
6877 service_id
= program
->service_id();
6879 if (state_
.current_program
.get()) {
6880 program_manager()->UnuseProgram(shader_manager(),
6881 state_
.current_program
.get());
6883 state_
.current_program
= program
;
6884 LogClientServiceMapping("glUseProgram", program_id
, service_id
);
6885 glUseProgram(service_id
);
6886 if (state_
.current_program
.get()) {
6887 program_manager()->UseProgram(state_
.current_program
.get());
6888 if (workarounds().clear_uniforms_before_first_program_use
)
6889 program_manager()->ClearUniforms(program
);
6893 void GLES2DecoderImpl::RenderWarning(
6894 const char* filename
, int line
, const std::string
& msg
) {
6895 logger_
.LogMessage(filename
, line
, std::string("RENDER WARNING: ") + msg
);
6898 void GLES2DecoderImpl::PerformanceWarning(
6899 const char* filename
, int line
, const std::string
& msg
) {
6900 logger_
.LogMessage(filename
, line
,
6901 std::string("PERFORMANCE WARNING: ") + msg
);
6904 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
6905 Texture
* texture
, GLenum textarget
) {
6906 // Image is already in use if texture is attached to a framebuffer.
6907 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
6908 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6910 ScopedGLErrorSuppressor
suppressor(
6911 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
6913 glBindTexture(textarget
, texture
->service_id());
6914 image
->WillUseTexImage();
6915 RestoreCurrentTextureBindings(&state_
, textarget
);
6920 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6921 Texture
* texture
, GLenum textarget
) {
6922 // Image is still in use if texture is attached to a framebuffer.
6923 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
6924 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6926 ScopedGLErrorSuppressor
suppressor(
6927 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6929 glBindTexture(textarget
, texture
->service_id());
6930 image
->DidUseTexImage();
6931 RestoreCurrentTextureBindings(&state_
, textarget
);
6936 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6937 DCHECK(state_
.current_program
.get());
6938 if (!texture_manager()->HaveUnrenderableTextures() &&
6939 !texture_manager()->HaveImages()) {
6943 bool textures_set
= false;
6944 const Program::SamplerIndices
& sampler_indices
=
6945 state_
.current_program
->sampler_indices();
6946 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6947 const Program::UniformInfo
* uniform_info
=
6948 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6949 DCHECK(uniform_info
);
6950 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6951 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6952 if (texture_unit_index
< state_
.texture_units
.size()) {
6953 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6954 TextureRef
* texture_ref
=
6955 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6956 GLenum textarget
= GetBindTargetForSamplerType(uniform_info
->type
);
6957 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
6958 textures_set
= true;
6959 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6962 texture_manager()->black_texture_id(uniform_info
->type
));
6964 LOCAL_RENDER_WARNING(
6965 std::string("there is no texture bound to the unit ") +
6966 base::IntToString(texture_unit_index
));
6968 LOCAL_RENDER_WARNING(
6969 std::string("texture bound to texture unit ") +
6970 base::IntToString(texture_unit_index
) +
6971 " is not renderable. It maybe non-power-of-2 and have"
6972 " incompatible texture filtering.");
6977 if (textarget
!= GL_TEXTURE_CUBE_MAP
) {
6978 Texture
* texture
= texture_ref
->texture();
6979 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6980 if (image
&& !texture
->IsAttachedToFramebuffer()) {
6981 ScopedGLErrorSuppressor
suppressor(
6982 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6983 textures_set
= true;
6984 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6985 image
->WillUseTexImage();
6990 // else: should this be an error?
6993 return !textures_set
;
6996 void GLES2DecoderImpl::RestoreStateForTextures() {
6997 DCHECK(state_
.current_program
.get());
6998 const Program::SamplerIndices
& sampler_indices
=
6999 state_
.current_program
->sampler_indices();
7000 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
7001 const Program::UniformInfo
* uniform_info
=
7002 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
7003 DCHECK(uniform_info
);
7004 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
7005 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
7006 if (texture_unit_index
< state_
.texture_units
.size()) {
7007 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
7008 TextureRef
* texture_ref
=
7009 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
7010 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
7011 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
7012 // Get the texture_ref info that was previously bound here.
7013 texture_ref
= texture_unit
.bind_target
== GL_TEXTURE_2D
7014 ? texture_unit
.bound_texture_2d
.get()
7015 : texture_unit
.bound_texture_cube_map
.get();
7016 glBindTexture(texture_unit
.bind_target
,
7017 texture_ref
? texture_ref
->service_id() : 0);
7021 if (texture_unit
.bind_target
!= GL_TEXTURE_CUBE_MAP
) {
7022 Texture
* texture
= texture_ref
->texture();
7023 gfx::GLImage
* image
=
7024 texture
->GetLevelImage(texture_unit
.bind_target
, 0);
7025 if (image
&& !texture
->IsAttachedToFramebuffer()) {
7026 ScopedGLErrorSuppressor
suppressor(
7027 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
7028 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
7029 image
->DidUseTexImage();
7036 // Set the active texture back to whatever the user had it as.
7037 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
7040 bool GLES2DecoderImpl::ClearUnclearedTextures() {
7041 // Only check if there are some uncleared textures.
7042 if (!texture_manager()->HaveUnsafeTextures()) {
7046 // 1: Check all textures we are about to render with.
7047 if (state_
.current_program
.get()) {
7048 const Program::SamplerIndices
& sampler_indices
=
7049 state_
.current_program
->sampler_indices();
7050 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
7051 const Program::UniformInfo
* uniform_info
=
7052 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
7053 DCHECK(uniform_info
);
7054 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
7055 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
7056 if (texture_unit_index
< state_
.texture_units
.size()) {
7057 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
7058 TextureRef
* texture_ref
=
7059 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
7060 if (texture_ref
&& !texture_ref
->texture()->SafeToRenderFrom()) {
7061 if (!texture_manager()->ClearRenderableLevels(this, texture_ref
)) {
7072 bool GLES2DecoderImpl::IsDrawValid(
7073 const char* function_name
, GLuint max_vertex_accessed
, bool instanced
,
7074 GLsizei primcount
) {
7075 DCHECK(instanced
|| primcount
== 1);
7077 // NOTE: We specifically do not check current_program->IsValid() because
7078 // it could never be invalid since glUseProgram would have failed. While
7079 // glLinkProgram could later mark the program as invalid the previous
7080 // valid program will still function if it is still the current program.
7081 if (!state_
.current_program
.get()) {
7082 // The program does not exist.
7083 // But GL says no ERROR.
7084 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
7088 if (CheckDrawingFeedbackLoops()) {
7090 GL_INVALID_OPERATION
, function_name
,
7091 "Source and destination textures of the draw are the same.");
7095 return state_
.vertex_attrib_manager
7096 ->ValidateBindings(function_name
,
7098 feature_info_
.get(),
7099 state_
.current_program
.get(),
7100 max_vertex_accessed
,
7105 bool GLES2DecoderImpl::SimulateAttrib0(
7106 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
) {
7110 if (feature_info_
->gl_version_info().BehavesLikeGLES())
7113 const VertexAttrib
* attrib
=
7114 state_
.vertex_attrib_manager
->GetVertexAttrib(0);
7115 // If it's enabled or it's not used then we don't need to do anything.
7116 bool attrib_0_used
=
7117 state_
.current_program
->GetAttribInfoByLocation(0) != NULL
;
7118 if (attrib
->enabled() && attrib_0_used
) {
7122 // Make a buffer with a single repeated vec4 value enough to
7123 // simulate the constant value that is supposed to be here.
7124 // This is required to emulate GLES2 on GL.
7125 GLuint num_vertices
= max_vertex_accessed
+ 1;
7126 uint32 size_needed
= 0;
7128 if (num_vertices
== 0 ||
7129 !SafeMultiplyUint32(num_vertices
, sizeof(Vec4f
), &size_needed
) ||
7130 size_needed
> 0x7FFFFFFFU
) {
7131 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
7135 LOCAL_PERFORMANCE_WARNING(
7136 "Attribute 0 is disabled. This has signficant performance penalty");
7138 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
7139 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
7141 bool new_buffer
= static_cast<GLsizei
>(size_needed
) > attrib_0_size_
;
7143 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
7144 GLenum error
= glGetError();
7145 if (error
!= GL_NO_ERROR
) {
7147 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
7152 const Vec4
& value
= state_
.attrib_values
[0];
7155 (!attrib_0_buffer_matches_value_
|| !value
.Equal(attrib_0_value_
)))){
7156 // TODO(zmo): This is not 100% correct because we might lose data when
7157 // casting to float type, but it is a corner case and once we migrate to
7158 // core profiles on desktop GL, it is no longer relevant.
7159 Vec4f
fvalue(value
);
7160 std::vector
<Vec4f
> temp(num_vertices
, fvalue
);
7161 glBufferSubData(GL_ARRAY_BUFFER
, 0, size_needed
, &temp
[0].v
[0]);
7162 attrib_0_buffer_matches_value_
= true;
7163 attrib_0_value_
= value
;
7164 attrib_0_size_
= size_needed
;
7167 glVertexAttribPointer(0, 4, GL_FLOAT
, GL_FALSE
, 0, NULL
);
7169 if (attrib
->divisor())
7170 glVertexAttribDivisorANGLE(0, 0);
7176 void GLES2DecoderImpl::RestoreStateForAttrib(
7177 GLuint attrib_index
, bool restore_array_binding
) {
7178 const VertexAttrib
* attrib
=
7179 state_
.vertex_attrib_manager
->GetVertexAttrib(attrib_index
);
7180 if (restore_array_binding
) {
7181 const void* ptr
= reinterpret_cast<const void*>(attrib
->offset());
7182 Buffer
* buffer
= attrib
->buffer();
7183 glBindBuffer(GL_ARRAY_BUFFER
, buffer
? buffer
->service_id() : 0);
7184 glVertexAttribPointer(
7185 attrib_index
, attrib
->size(), attrib
->type(), attrib
->normalized(),
7186 attrib
->gl_stride(), ptr
);
7188 if (attrib
->divisor())
7189 glVertexAttribDivisorANGLE(attrib_index
, attrib
->divisor());
7191 GL_ARRAY_BUFFER
, state_
.bound_array_buffer
.get() ?
7192 state_
.bound_array_buffer
->service_id() : 0);
7194 // Never touch vertex attribute 0's state (in particular, never
7195 // disable it) when running on desktop GL because it will never be
7197 if (attrib_index
!= 0 ||
7198 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
7199 if (attrib
->enabled()) {
7200 glEnableVertexAttribArray(attrib_index
);
7202 glDisableVertexAttribArray(attrib_index
);
7207 bool GLES2DecoderImpl::SimulateFixedAttribs(
7208 const char* function_name
,
7209 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
) {
7212 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
)
7215 if (!state_
.vertex_attrib_manager
->HaveFixedAttribs()) {
7219 LOCAL_PERFORMANCE_WARNING(
7220 "GL_FIXED attributes have a signficant performance penalty");
7222 // NOTE: we could be smart and try to check if a buffer is used
7223 // twice in 2 different attribs, find the overlapping parts and therefore
7224 // duplicate the minimum amount of data but this whole code path is not meant
7225 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
7226 // tests so we just add to the buffer attrib used.
7228 GLuint elements_needed
= 0;
7229 const VertexAttribManager::VertexAttribList
& enabled_attribs
=
7230 state_
.vertex_attrib_manager
->GetEnabledVertexAttribs();
7231 for (VertexAttribManager::VertexAttribList::const_iterator it
=
7232 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
7233 const VertexAttrib
* attrib
= *it
;
7234 const Program::VertexAttrib
* attrib_info
=
7235 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
7236 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
7237 max_vertex_accessed
);
7238 GLuint num_vertices
= max_accessed
+ 1;
7239 if (num_vertices
== 0) {
7241 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
7245 attrib
->CanAccess(max_accessed
) &&
7246 attrib
->type() == GL_FIXED
) {
7247 uint32 elements_used
= 0;
7248 if (!SafeMultiplyUint32(num_vertices
, attrib
->size(), &elements_used
) ||
7249 !SafeAddUint32(elements_needed
, elements_used
, &elements_needed
)) {
7251 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
7257 const uint32 kSizeOfFloat
= sizeof(float); // NOLINT
7258 uint32 size_needed
= 0;
7259 if (!SafeMultiplyUint32(elements_needed
, kSizeOfFloat
, &size_needed
) ||
7260 size_needed
> 0x7FFFFFFFU
) {
7262 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
7266 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
7268 glBindBuffer(GL_ARRAY_BUFFER
, fixed_attrib_buffer_id_
);
7269 if (static_cast<GLsizei
>(size_needed
) > fixed_attrib_buffer_size_
) {
7270 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
7271 GLenum error
= glGetError();
7272 if (error
!= GL_NO_ERROR
) {
7274 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
7279 // Copy the elements and convert to float
7280 GLintptr offset
= 0;
7281 for (VertexAttribManager::VertexAttribList::const_iterator it
=
7282 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
7283 const VertexAttrib
* attrib
= *it
;
7284 const Program::VertexAttrib
* attrib_info
=
7285 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
7286 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
7287 max_vertex_accessed
);
7288 GLuint num_vertices
= max_accessed
+ 1;
7289 if (num_vertices
== 0) {
7291 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
7295 attrib
->CanAccess(max_accessed
) &&
7296 attrib
->type() == GL_FIXED
) {
7297 int num_elements
= attrib
->size() * num_vertices
;
7298 const int src_size
= num_elements
* sizeof(int32
);
7299 const int dst_size
= num_elements
* sizeof(float);
7300 scoped_ptr
<float[]> data(new float[num_elements
]);
7301 const int32
* src
= reinterpret_cast<const int32
*>(
7302 attrib
->buffer()->GetRange(attrib
->offset(), src_size
));
7303 const int32
* end
= src
+ num_elements
;
7304 float* dst
= data
.get();
7305 while (src
!= end
) {
7306 *dst
++ = static_cast<float>(*src
++) / 65536.0f
;
7308 glBufferSubData(GL_ARRAY_BUFFER
, offset
, dst_size
, data
.get());
7309 glVertexAttribPointer(
7310 attrib
->index(), attrib
->size(), GL_FLOAT
, false, 0,
7311 reinterpret_cast<GLvoid
*>(offset
));
7319 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
7320 // There's no need to call glVertexAttribPointer because we shadow all the
7321 // settings and passing GL_FIXED to it will not work.
7324 state_
.bound_array_buffer
.get() ? state_
.bound_array_buffer
->service_id()
7328 error::Error
GLES2DecoderImpl::DoDrawArrays(
7329 const char* function_name
,
7334 GLsizei primcount
) {
7335 error::Error error
= WillAccessBoundFramebufferForDraw();
7336 if (error
!= error::kNoError
)
7338 if (!validators_
->draw_mode
.IsValid(mode
)) {
7339 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
7340 return error::kNoError
;
7343 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
7344 return error::kNoError
;
7346 if (primcount
< 0) {
7347 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
7348 return error::kNoError
;
7350 if (!CheckBoundFramebuffersValid(function_name
)) {
7351 return error::kNoError
;
7353 // We have to check this here because the prototype for glDrawArrays
7354 // is GLint not GLsizei.
7356 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "first < 0");
7357 return error::kNoError
;
7360 if (count
== 0 || primcount
== 0) {
7361 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
7362 return error::kNoError
;
7365 GLuint max_vertex_accessed
= first
+ count
- 1;
7366 if (IsDrawValid(function_name
, max_vertex_accessed
, instanced
, primcount
)) {
7367 if (!ClearUnclearedTextures()) {
7368 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
7369 return error::kNoError
;
7371 bool simulated_attrib_0
= false;
7372 if (!SimulateAttrib0(
7373 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
7374 return error::kNoError
;
7376 bool simulated_fixed_attribs
= false;
7377 if (SimulateFixedAttribs(
7378 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
7380 bool textures_set
= !PrepareTexturesForRender();
7382 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
7384 glDrawArrays(mode
, first
, count
);
7386 glDrawArraysInstancedANGLE(mode
, first
, count
, primcount
);
7389 RestoreStateForTextures();
7391 if (simulated_fixed_attribs
) {
7392 RestoreStateForSimulatedFixedAttribs();
7395 if (simulated_attrib_0
) {
7396 // We don't have to restore attrib 0 generic data at the end of this
7397 // function even if it is simulated. This is because we will simulate
7398 // it in each draw call, and attrib 0 generic data queries use cached
7399 // values instead of passing down to the underlying driver.
7400 RestoreStateForAttrib(0, false);
7403 return error::kNoError
;
7406 error::Error
GLES2DecoderImpl::HandleDrawArrays(uint32 immediate_data_size
,
7407 const void* cmd_data
) {
7408 // TODO(zmo): crbug.com/481184
7409 // On Desktop GL with versions lower than 4.3, we need to emulate
7410 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7411 const cmds::DrawArrays
& c
= *static_cast<const cmds::DrawArrays
*>(cmd_data
);
7412 return DoDrawArrays("glDrawArrays",
7414 static_cast<GLenum
>(c
.mode
),
7415 static_cast<GLint
>(c
.first
),
7416 static_cast<GLsizei
>(c
.count
),
7420 error::Error
GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
7421 uint32 immediate_data_size
,
7422 const void* cmd_data
) {
7423 const gles2::cmds::DrawArraysInstancedANGLE
& c
=
7424 *static_cast<const gles2::cmds::DrawArraysInstancedANGLE
*>(cmd_data
);
7425 if (!features().angle_instanced_arrays
) {
7427 GL_INVALID_OPERATION
,
7428 "glDrawArraysInstancedANGLE", "function not available");
7429 return error::kNoError
;
7431 return DoDrawArrays("glDrawArraysIntancedANGLE",
7433 static_cast<GLenum
>(c
.mode
),
7434 static_cast<GLint
>(c
.first
),
7435 static_cast<GLsizei
>(c
.count
),
7436 static_cast<GLsizei
>(c
.primcount
));
7439 error::Error
GLES2DecoderImpl::DoDrawElements(
7440 const char* function_name
,
7446 GLsizei primcount
) {
7447 error::Error error
= WillAccessBoundFramebufferForDraw();
7448 if (error
!= error::kNoError
)
7450 if (!state_
.vertex_attrib_manager
->element_array_buffer()) {
7452 GL_INVALID_OPERATION
, function_name
, "No element array buffer bound");
7453 return error::kNoError
;
7457 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
7458 return error::kNoError
;
7461 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "offset < 0");
7462 return error::kNoError
;
7464 if (!validators_
->draw_mode
.IsValid(mode
)) {
7465 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
7466 return error::kNoError
;
7468 if (!validators_
->index_type
.IsValid(type
)) {
7469 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, type
, "type");
7470 return error::kNoError
;
7472 if (primcount
< 0) {
7473 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
7474 return error::kNoError
;
7477 if (!CheckBoundFramebuffersValid(function_name
)) {
7478 return error::kNoError
;
7481 if (count
== 0 || primcount
== 0) {
7482 return error::kNoError
;
7485 GLuint max_vertex_accessed
;
7486 Buffer
* element_array_buffer
=
7487 state_
.vertex_attrib_manager
->element_array_buffer();
7489 if (!element_array_buffer
->GetMaxValueForRange(
7490 offset
, count
, type
, &max_vertex_accessed
)) {
7492 GL_INVALID_OPERATION
, function_name
, "range out of bounds for buffer");
7493 return error::kNoError
;
7496 if (IsDrawValid(function_name
, max_vertex_accessed
, instanced
, primcount
)) {
7497 if (!ClearUnclearedTextures()) {
7498 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
7499 return error::kNoError
;
7501 bool simulated_attrib_0
= false;
7502 if (!SimulateAttrib0(
7503 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
7504 return error::kNoError
;
7506 bool simulated_fixed_attribs
= false;
7507 if (SimulateFixedAttribs(
7508 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
7510 bool textures_set
= !PrepareTexturesForRender();
7512 // TODO(gman): Refactor to hide these details in BufferManager or
7513 // VertexAttribManager.
7514 const GLvoid
* indices
= reinterpret_cast<const GLvoid
*>(offset
);
7515 bool used_client_side_array
= false;
7516 if (element_array_buffer
->IsClientSideArray()) {
7517 used_client_side_array
= true;
7518 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
7519 indices
= element_array_buffer
->GetRange(offset
, 0);
7522 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
7524 glDrawElements(mode
, count
, type
, indices
);
7526 glDrawElementsInstancedANGLE(mode
, count
, type
, indices
, primcount
);
7529 if (used_client_side_array
) {
7530 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
7531 element_array_buffer
->service_id());
7535 RestoreStateForTextures();
7537 if (simulated_fixed_attribs
) {
7538 RestoreStateForSimulatedFixedAttribs();
7541 if (simulated_attrib_0
) {
7542 // We don't have to restore attrib 0 generic data at the end of this
7543 // function even if it is simulated. This is because we will simulate
7544 // it in each draw call, and attrib 0 generic data queries use cached
7545 // values instead of passing down to the underlying driver.
7546 RestoreStateForAttrib(0, false);
7549 return error::kNoError
;
7552 error::Error
GLES2DecoderImpl::HandleDrawElements(uint32 immediate_data_size
,
7553 const void* cmd_data
) {
7554 // TODO(zmo): crbug.com/481184
7555 // On Desktop GL with versions lower than 4.3, we need to emulate
7556 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7557 const gles2::cmds::DrawElements
& c
=
7558 *static_cast<const gles2::cmds::DrawElements
*>(cmd_data
);
7559 return DoDrawElements("glDrawElements",
7561 static_cast<GLenum
>(c
.mode
),
7562 static_cast<GLsizei
>(c
.count
),
7563 static_cast<GLenum
>(c
.type
),
7564 static_cast<int32
>(c
.index_offset
),
7568 error::Error
GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
7569 uint32 immediate_data_size
,
7570 const void* cmd_data
) {
7571 const gles2::cmds::DrawElementsInstancedANGLE
& c
=
7572 *static_cast<const gles2::cmds::DrawElementsInstancedANGLE
*>(cmd_data
);
7573 if (!features().angle_instanced_arrays
) {
7575 GL_INVALID_OPERATION
,
7576 "glDrawElementsInstancedANGLE", "function not available");
7577 return error::kNoError
;
7579 return DoDrawElements("glDrawElementsInstancedANGLE",
7581 static_cast<GLenum
>(c
.mode
),
7582 static_cast<GLsizei
>(c
.count
),
7583 static_cast<GLenum
>(c
.type
),
7584 static_cast<int32
>(c
.index_offset
),
7585 static_cast<GLsizei
>(c
.primcount
));
7588 GLuint
GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
7589 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
7590 GLuint max_vertex_accessed
= 0;
7591 Buffer
* buffer
= GetBuffer(buffer_id
);
7593 // TODO(gman): Should this be a GL error or a command buffer error?
7595 GL_INVALID_VALUE
, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
7597 if (!buffer
->GetMaxValueForRange(
7598 offset
, count
, type
, &max_vertex_accessed
)) {
7599 // TODO(gman): Should this be a GL error or a command buffer error?
7601 GL_INVALID_OPERATION
,
7602 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
7605 return max_vertex_accessed
;
7608 void GLES2DecoderImpl::DoShaderSource(
7609 GLuint client_id
, GLsizei count
, const char** data
, const GLint
* length
) {
7611 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
7612 if (length
&& length
[ii
] > 0)
7613 str
.append(data
[ii
], length
[ii
]);
7615 str
.append(data
[ii
]);
7617 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glShaderSource");
7621 // Note: We don't actually call glShaderSource here. We wait until
7622 // we actually compile the shader.
7623 shader
->set_source(str
);
7626 void GLES2DecoderImpl::DoTransformFeedbackVaryings(
7627 GLuint client_program_id
, GLsizei count
, const char* const* varyings
,
7628 GLenum buffer_mode
) {
7629 Program
* program
= GetProgramInfoNotShader(
7630 client_program_id
, "glTransformFeedbackVaryings");
7634 program
->TransformFeedbackVaryings(count
, varyings
, buffer_mode
);
7635 glTransformFeedbackVaryings(
7636 program
->service_id(), count
, varyings
, buffer_mode
);
7639 void GLES2DecoderImpl::DoCompileShader(GLuint client_id
) {
7640 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
7641 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glCompileShader");
7646 scoped_refptr
<ShaderTranslatorInterface
> translator
;
7647 if (use_shader_translator_
) {
7648 translator
= shader
->shader_type() == GL_VERTEX_SHADER
?
7649 vertex_translator_
: fragment_translator_
;
7652 const Shader::TranslatedShaderSourceType source_type
=
7653 feature_info_
->feature_flags().angle_translated_shader_source
?
7654 Shader::kANGLE
: Shader::kGL
;
7655 shader
->RequestCompile(translator
, source_type
);
7658 void GLES2DecoderImpl::DoGetShaderiv(
7659 GLuint shader_id
, GLenum pname
, GLint
* params
) {
7660 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderiv");
7665 // Compile now for statuses that require it.
7667 case GL_COMPILE_STATUS
:
7668 case GL_INFO_LOG_LENGTH
:
7669 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE
:
7670 shader
->DoCompile();
7678 case GL_SHADER_SOURCE_LENGTH
:
7679 *params
= shader
->source().size();
7683 case GL_COMPILE_STATUS
:
7684 *params
= compile_shader_always_succeeds_
? true : shader
->valid();
7686 case GL_INFO_LOG_LENGTH
:
7687 *params
= shader
->log_info().size();
7691 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE
:
7692 *params
= shader
->translated_source().size();
7699 glGetShaderiv(shader
->service_id(), pname
, params
);
7702 error::Error
GLES2DecoderImpl::HandleGetShaderSource(uint32 immediate_data_size
,
7703 const void* cmd_data
) {
7704 const gles2::cmds::GetShaderSource
& c
=
7705 *static_cast<const gles2::cmds::GetShaderSource
*>(cmd_data
);
7706 GLuint shader_id
= c
.shader
;
7707 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7708 Bucket
* bucket
= CreateBucket(bucket_id
);
7709 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderSource");
7710 if (!shader
|| shader
->source().empty()) {
7712 return error::kNoError
;
7714 bucket
->SetFromString(shader
->source().c_str());
7715 return error::kNoError
;
7718 error::Error
GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
7719 uint32 immediate_data_size
,
7720 const void* cmd_data
) {
7721 const gles2::cmds::GetTranslatedShaderSourceANGLE
& c
=
7722 *static_cast<const gles2::cmds::GetTranslatedShaderSourceANGLE
*>(
7724 GLuint shader_id
= c
.shader
;
7725 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7726 Bucket
* bucket
= CreateBucket(bucket_id
);
7727 Shader
* shader
= GetShaderInfoNotProgram(
7728 shader_id
, "glGetTranslatedShaderSourceANGLE");
7731 return error::kNoError
;
7734 // Make sure translator has been utilized in compile.
7735 shader
->DoCompile();
7737 bucket
->SetFromString(shader
->translated_source().c_str());
7738 return error::kNoError
;
7741 error::Error
GLES2DecoderImpl::HandleGetProgramInfoLog(
7742 uint32 immediate_data_size
,
7743 const void* cmd_data
) {
7744 const gles2::cmds::GetProgramInfoLog
& c
=
7745 *static_cast<const gles2::cmds::GetProgramInfoLog
*>(cmd_data
);
7746 GLuint program_id
= c
.program
;
7747 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7748 Bucket
* bucket
= CreateBucket(bucket_id
);
7749 Program
* program
= GetProgramInfoNotShader(
7750 program_id
, "glGetProgramInfoLog");
7751 if (!program
|| !program
->log_info()) {
7752 bucket
->SetFromString("");
7753 return error::kNoError
;
7755 bucket
->SetFromString(program
->log_info()->c_str());
7756 return error::kNoError
;
7759 error::Error
GLES2DecoderImpl::HandleGetShaderInfoLog(
7760 uint32 immediate_data_size
,
7761 const void* cmd_data
) {
7762 const gles2::cmds::GetShaderInfoLog
& c
=
7763 *static_cast<const gles2::cmds::GetShaderInfoLog
*>(cmd_data
);
7764 GLuint shader_id
= c
.shader
;
7765 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7766 Bucket
* bucket
= CreateBucket(bucket_id
);
7767 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderInfoLog");
7769 bucket
->SetFromString("");
7770 return error::kNoError
;
7773 // Shader must be compiled in order to get the info log.
7774 shader
->DoCompile();
7776 bucket
->SetFromString(shader
->log_info().c_str());
7777 return error::kNoError
;
7780 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap
) {
7781 return state_
.GetEnabled(cap
);
7784 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id
) {
7785 const Buffer
* buffer
= GetBuffer(client_id
);
7786 return buffer
&& buffer
->IsValid() && !buffer
->IsDeleted();
7789 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id
) {
7790 const Framebuffer
* framebuffer
=
7791 GetFramebuffer(client_id
);
7792 return framebuffer
&& framebuffer
->IsValid() && !framebuffer
->IsDeleted();
7795 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id
) {
7796 // IsProgram is true for programs as soon as they are created, until they are
7797 // deleted and no longer in use.
7798 const Program
* program
= GetProgram(client_id
);
7799 return program
!= NULL
&& !program
->IsDeleted();
7802 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id
) {
7803 const Renderbuffer
* renderbuffer
=
7804 GetRenderbuffer(client_id
);
7805 return renderbuffer
&& renderbuffer
->IsValid() && !renderbuffer
->IsDeleted();
7808 bool GLES2DecoderImpl::DoIsShader(GLuint client_id
) {
7809 // IsShader is true for shaders as soon as they are created, until they
7810 // are deleted and not attached to any programs.
7811 const Shader
* shader
= GetShader(client_id
);
7812 return shader
!= NULL
&& !shader
->IsDeleted();
7815 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id
) {
7816 const TextureRef
* texture_ref
= GetTexture(client_id
);
7817 return texture_ref
&& texture_ref
->texture()->IsValid();
7820 void GLES2DecoderImpl::DoAttachShader(
7821 GLuint program_client_id
, GLint shader_client_id
) {
7822 Program
* program
= GetProgramInfoNotShader(
7823 program_client_id
, "glAttachShader");
7827 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glAttachShader");
7831 if (!program
->AttachShader(shader_manager(), shader
)) {
7833 GL_INVALID_OPERATION
,
7835 "can not attach more than one shader of the same type.");
7838 glAttachShader(program
->service_id(), shader
->service_id());
7841 void GLES2DecoderImpl::DoDetachShader(
7842 GLuint program_client_id
, GLint shader_client_id
) {
7843 Program
* program
= GetProgramInfoNotShader(
7844 program_client_id
, "glDetachShader");
7848 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glDetachShader");
7852 if (!program
->DetachShader(shader_manager(), shader
)) {
7854 GL_INVALID_OPERATION
,
7855 "glDetachShader", "shader not attached to program");
7858 glDetachShader(program
->service_id(), shader
->service_id());
7861 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id
) {
7862 Program
* program
= GetProgramInfoNotShader(
7863 program_client_id
, "glValidateProgram");
7867 program
->Validate();
7870 void GLES2DecoderImpl::GetVertexAttribHelper(
7871 const VertexAttrib
* attrib
, GLenum pname
, GLint
* params
) {
7873 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
:
7875 Buffer
* buffer
= attrib
->buffer();
7876 if (buffer
&& !buffer
->IsDeleted()) {
7878 buffer_manager()->GetClientId(buffer
->service_id(), &client_id
);
7879 *params
= client_id
;
7883 case GL_VERTEX_ATTRIB_ARRAY_ENABLED
:
7884 *params
= attrib
->enabled();
7886 case GL_VERTEX_ATTRIB_ARRAY_SIZE
:
7887 *params
= attrib
->size();
7889 case GL_VERTEX_ATTRIB_ARRAY_STRIDE
:
7890 *params
= attrib
->gl_stride();
7892 case GL_VERTEX_ATTRIB_ARRAY_TYPE
:
7893 *params
= attrib
->type();
7895 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED
:
7896 *params
= attrib
->normalized();
7898 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR
:
7899 *params
= attrib
->divisor();
7901 case GL_VERTEX_ATTRIB_ARRAY_INTEGER
:
7902 *params
= attrib
->integer();
7910 void GLES2DecoderImpl::DoGetTexParameterfv(
7911 GLenum target
, GLenum pname
, GLfloat
* params
) {
7912 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
7913 glGetTexParameterfv(target
, pname
, params
);
7916 void GLES2DecoderImpl::DoGetTexParameteriv(
7917 GLenum target
, GLenum pname
, GLint
* params
) {
7918 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
7919 glGetTexParameteriv(target
, pname
, params
);
7922 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
7923 GLenum target
, GLenum pname
) {
7924 if (!workarounds().init_texture_max_anisotropy
)
7926 if (pname
!= GL_TEXTURE_MAX_ANISOTROPY_EXT
||
7927 !validators_
->texture_parameter
.IsValid(pname
)) {
7931 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
7935 GL_INVALID_OPERATION
,
7936 "glGetTexParamter{fi}v", "unknown texture for target");
7939 Texture
* texture
= texture_ref
->texture();
7940 texture
->InitTextureMaxAnisotropyIfNeeded(target
);
7943 template <typename T
>
7944 void GLES2DecoderImpl::DoGetVertexAttribImpl(
7945 GLuint index
, GLenum pname
, T
* params
) {
7946 VertexAttrib
* attrib
= state_
.vertex_attrib_manager
->GetVertexAttrib(index
);
7949 GL_INVALID_VALUE
, "glGetVertexAttrib", "index out of range");
7953 case GL_CURRENT_VERTEX_ATTRIB
:
7954 state_
.attrib_values
[index
].GetValues(params
);
7958 GetVertexAttribHelper(attrib
, pname
, &value
);
7959 *params
= static_cast<T
>(value
);
7965 void GLES2DecoderImpl::DoGetVertexAttribfv(
7966 GLuint index
, GLenum pname
, GLfloat
* params
) {
7967 DoGetVertexAttribImpl
<GLfloat
>(index
, pname
, params
);
7970 void GLES2DecoderImpl::DoGetVertexAttribiv(
7971 GLuint index
, GLenum pname
, GLint
* params
) {
7972 DoGetVertexAttribImpl
<GLint
>(index
, pname
, params
);
7975 void GLES2DecoderImpl::DoGetVertexAttribIiv(
7976 GLuint index
, GLenum pname
, GLint
* params
) {
7977 DoGetVertexAttribImpl
<GLint
>(index
, pname
, params
);
7980 void GLES2DecoderImpl::DoGetVertexAttribIuiv(
7981 GLuint index
, GLenum pname
, GLuint
* params
) {
7982 DoGetVertexAttribImpl
<GLuint
>(index
, pname
, params
);
7985 template <typename T
>
7986 bool GLES2DecoderImpl::SetVertexAttribValue(
7987 const char* function_name
, GLuint index
, const T
* value
) {
7988 if (index
>= state_
.attrib_values
.size()) {
7989 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "index out of range");
7992 state_
.attrib_values
[index
].SetValues(value
);
7996 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index
, GLfloat v0
) {
7997 GLfloat v
[4] = { v0
, 0.0f
, 0.0f
, 1.0f
, };
7998 if (SetVertexAttribValue("glVertexAttrib1f", index
, v
)) {
7999 glVertexAttrib1f(index
, v0
);
8003 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
) {
8004 GLfloat v
[4] = { v0
, v1
, 0.0f
, 1.0f
, };
8005 if (SetVertexAttribValue("glVertexAttrib2f", index
, v
)) {
8006 glVertexAttrib2f(index
, v0
, v1
);
8010 void GLES2DecoderImpl::DoVertexAttrib3f(
8011 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
) {
8012 GLfloat v
[4] = { v0
, v1
, v2
, 1.0f
, };
8013 if (SetVertexAttribValue("glVertexAttrib3f", index
, v
)) {
8014 glVertexAttrib3f(index
, v0
, v1
, v2
);
8018 void GLES2DecoderImpl::DoVertexAttrib4f(
8019 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
) {
8020 GLfloat v
[4] = { v0
, v1
, v2
, v3
, };
8021 if (SetVertexAttribValue("glVertexAttrib4f", index
, v
)) {
8022 glVertexAttrib4f(index
, v0
, v1
, v2
, v3
);
8026 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index
, const GLfloat
* v
) {
8027 GLfloat t
[4] = { v
[0], 0.0f
, 0.0f
, 1.0f
, };
8028 if (SetVertexAttribValue("glVertexAttrib1fv", index
, t
)) {
8029 glVertexAttrib1fv(index
, v
);
8033 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index
, const GLfloat
* v
) {
8034 GLfloat t
[4] = { v
[0], v
[1], 0.0f
, 1.0f
, };
8035 if (SetVertexAttribValue("glVertexAttrib2fv", index
, t
)) {
8036 glVertexAttrib2fv(index
, v
);
8040 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index
, const GLfloat
* v
) {
8041 GLfloat t
[4] = { v
[0], v
[1], v
[2], 1.0f
, };
8042 if (SetVertexAttribValue("glVertexAttrib3fv", index
, t
)) {
8043 glVertexAttrib3fv(index
, v
);
8047 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index
, const GLfloat
* v
) {
8048 if (SetVertexAttribValue("glVertexAttrib4fv", index
, v
)) {
8049 glVertexAttrib4fv(index
, v
);
8053 void GLES2DecoderImpl::DoVertexAttribI4i(
8054 GLuint index
, GLint v0
, GLint v1
, GLint v2
, GLint v3
) {
8055 GLint v
[4] = { v0
, v1
, v2
, v3
};
8056 if (SetVertexAttribValue("glVertexAttribI4i", index
, v
)) {
8057 glVertexAttribI4i(index
, v0
, v1
, v2
, v3
);
8061 void GLES2DecoderImpl::DoVertexAttribI4iv(GLuint index
, const GLint
* v
) {
8062 if (SetVertexAttribValue("glVertexAttribI4iv", index
, v
)) {
8063 glVertexAttribI4iv(index
, v
);
8067 void GLES2DecoderImpl::DoVertexAttribI4ui(
8068 GLuint index
, GLuint v0
, GLuint v1
, GLuint v2
, GLuint v3
) {
8069 GLuint v
[4] = { v0
, v1
, v2
, v3
};
8070 if (SetVertexAttribValue("glVertexAttribI4ui", index
, v
)) {
8071 glVertexAttribI4ui(index
, v0
, v1
, v2
, v3
);
8075 void GLES2DecoderImpl::DoVertexAttribI4uiv(GLuint index
, const GLuint
* v
) {
8076 if (SetVertexAttribValue("glVertexAttribI4uiv", index
, v
)) {
8077 glVertexAttribI4uiv(index
, v
);
8081 error::Error
GLES2DecoderImpl::HandleVertexAttribIPointer(
8082 uint32 immediate_data_size
,
8083 const void* cmd_data
) {
8084 if (!unsafe_es3_apis_enabled())
8085 return error::kUnknownCommand
;
8086 const gles2::cmds::VertexAttribIPointer
& c
=
8087 *static_cast<const gles2::cmds::VertexAttribIPointer
*>(cmd_data
);
8089 if (!state_
.bound_array_buffer
.get() ||
8090 state_
.bound_array_buffer
->IsDeleted()) {
8091 if (state_
.vertex_attrib_manager
.get() ==
8092 state_
.default_vertex_attrib_manager
.get()) {
8094 GL_INVALID_VALUE
, "glVertexAttribIPointer", "no array buffer bound");
8095 return error::kNoError
;
8096 } else if (c
.offset
!= 0) {
8099 "glVertexAttribIPointer", "client side arrays are not allowed");
8100 return error::kNoError
;
8104 GLuint indx
= c
.indx
;
8105 GLint size
= c
.size
;
8106 GLenum type
= c
.type
;
8107 GLsizei stride
= c
.stride
;
8108 GLsizei offset
= c
.offset
;
8109 const void* ptr
= reinterpret_cast<const void*>(offset
);
8110 if (!validators_
->vertex_attrib_i_type
.IsValid(type
)) {
8111 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribIPointer", type
, "type");
8112 return error::kNoError
;
8114 if (!validators_
->vertex_attrib_size
.IsValid(size
)) {
8116 GL_INVALID_VALUE
, "glVertexAttribIPointer", "size GL_INVALID_VALUE");
8117 return error::kNoError
;
8119 if (indx
>= group_
->max_vertex_attribs()) {
8121 GL_INVALID_VALUE
, "glVertexAttribIPointer", "index out of range");
8122 return error::kNoError
;
8126 GL_INVALID_VALUE
, "glVertexAttribIPointer", "stride < 0");
8127 return error::kNoError
;
8131 GL_INVALID_VALUE
, "glVertexAttribIPointer", "stride > 255");
8132 return error::kNoError
;
8136 GL_INVALID_VALUE
, "glVertexAttribIPointer", "offset < 0");
8137 return error::kNoError
;
8139 GLsizei component_size
=
8140 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type
);
8141 // component_size must be a power of two to use & as optimized modulo.
8142 DCHECK(GLES2Util::IsPOT(component_size
));
8143 if (offset
& (component_size
- 1)) {
8145 GL_INVALID_OPERATION
,
8146 "glVertexAttribIPointer", "offset not valid for type");
8147 return error::kNoError
;
8149 if (stride
& (component_size
- 1)) {
8151 GL_INVALID_OPERATION
,
8152 "glVertexAttribIPointer", "stride not valid for type");
8153 return error::kNoError
;
8155 state_
.vertex_attrib_manager
8156 ->SetAttribInfo(indx
,
8157 state_
.bound_array_buffer
.get(),
8162 stride
!= 0 ? stride
: component_size
* size
,
8165 glVertexAttribIPointer(indx
, size
, type
, stride
, ptr
);
8166 return error::kNoError
;
8169 error::Error
GLES2DecoderImpl::HandleVertexAttribPointer(
8170 uint32 immediate_data_size
,
8171 const void* cmd_data
) {
8172 const gles2::cmds::VertexAttribPointer
& c
=
8173 *static_cast<const gles2::cmds::VertexAttribPointer
*>(cmd_data
);
8175 if (!state_
.bound_array_buffer
.get() ||
8176 state_
.bound_array_buffer
->IsDeleted()) {
8177 if (state_
.vertex_attrib_manager
.get() ==
8178 state_
.default_vertex_attrib_manager
.get()) {
8180 GL_INVALID_VALUE
, "glVertexAttribPointer", "no array buffer bound");
8181 return error::kNoError
;
8182 } else if (c
.offset
!= 0) {
8185 "glVertexAttribPointer", "client side arrays are not allowed");
8186 return error::kNoError
;
8190 GLuint indx
= c
.indx
;
8191 GLint size
= c
.size
;
8192 GLenum type
= c
.type
;
8193 GLboolean normalized
= static_cast<GLboolean
>(c
.normalized
);
8194 GLsizei stride
= c
.stride
;
8195 GLsizei offset
= c
.offset
;
8196 const void* ptr
= reinterpret_cast<const void*>(offset
);
8197 if (!validators_
->vertex_attrib_type
.IsValid(type
)) {
8198 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type
, "type");
8199 return error::kNoError
;
8201 if (!validators_
->vertex_attrib_size
.IsValid(size
)) {
8203 GL_INVALID_VALUE
, "glVertexAttribPointer", "size GL_INVALID_VALUE");
8204 return error::kNoError
;
8206 if (indx
>= group_
->max_vertex_attribs()) {
8208 GL_INVALID_VALUE
, "glVertexAttribPointer", "index out of range");
8209 return error::kNoError
;
8213 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride < 0");
8214 return error::kNoError
;
8218 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride > 255");
8219 return error::kNoError
;
8223 GL_INVALID_VALUE
, "glVertexAttribPointer", "offset < 0");
8224 return error::kNoError
;
8226 GLsizei component_size
=
8227 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type
);
8228 // component_size must be a power of two to use & as optimized modulo.
8229 DCHECK(GLES2Util::IsPOT(component_size
));
8230 if (offset
& (component_size
- 1)) {
8232 GL_INVALID_OPERATION
,
8233 "glVertexAttribPointer", "offset not valid for type");
8234 return error::kNoError
;
8236 if (stride
& (component_size
- 1)) {
8238 GL_INVALID_OPERATION
,
8239 "glVertexAttribPointer", "stride not valid for type");
8240 return error::kNoError
;
8242 state_
.vertex_attrib_manager
8243 ->SetAttribInfo(indx
,
8244 state_
.bound_array_buffer
.get(),
8249 stride
!= 0 ? stride
: component_size
* size
,
8252 // We support GL_FIXED natively on EGL/GLES2 implementations
8253 if (type
!= GL_FIXED
|| feature_info_
->gl_version_info().is_es
) {
8254 glVertexAttribPointer(indx
, size
, type
, normalized
, stride
, ptr
);
8256 return error::kNoError
;
8259 void GLES2DecoderImpl::DoViewport(GLint x
, GLint y
, GLsizei width
,
8261 state_
.viewport_x
= x
;
8262 state_
.viewport_y
= y
;
8263 state_
.viewport_width
= std::min(width
, viewport_max_width_
);
8264 state_
.viewport_height
= std::min(height
, viewport_max_height_
);
8265 glViewport(x
, y
, width
, height
);
8268 error::Error
GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
8269 uint32 immediate_data_size
,
8270 const void* cmd_data
) {
8271 const gles2::cmds::VertexAttribDivisorANGLE
& c
=
8272 *static_cast<const gles2::cmds::VertexAttribDivisorANGLE
*>(cmd_data
);
8273 if (!features().angle_instanced_arrays
) {
8275 GL_INVALID_OPERATION
,
8276 "glVertexAttribDivisorANGLE", "function not available");
8277 return error::kNoError
;
8279 GLuint index
= c
.index
;
8280 GLuint divisor
= c
.divisor
;
8281 if (index
>= group_
->max_vertex_attribs()) {
8284 "glVertexAttribDivisorANGLE", "index out of range");
8285 return error::kNoError
;
8288 state_
.vertex_attrib_manager
->SetDivisor(
8291 glVertexAttribDivisorANGLE(index
, divisor
);
8292 return error::kNoError
;
8295 template <typename pixel_data_type
>
8296 static void WriteAlphaData(
8297 void* pixels
, uint32 row_count
, uint32 channel_count
,
8298 uint32 alpha_channel_index
, uint32 unpadded_row_size
,
8299 uint32 padded_row_size
, pixel_data_type alpha_value
) {
8300 DCHECK_GT(channel_count
, 0U);
8301 DCHECK_EQ(unpadded_row_size
% sizeof(pixel_data_type
), 0U);
8302 uint32 unpadded_row_size_in_elements
=
8303 unpadded_row_size
/ sizeof(pixel_data_type
);
8304 DCHECK_EQ(padded_row_size
% sizeof(pixel_data_type
), 0U);
8305 uint32 padded_row_size_in_elements
=
8306 padded_row_size
/ sizeof(pixel_data_type
);
8307 pixel_data_type
* dst
=
8308 static_cast<pixel_data_type
*>(pixels
) + alpha_channel_index
;
8309 for (uint32 yy
= 0; yy
< row_count
; ++yy
) {
8310 pixel_data_type
* end
= dst
+ unpadded_row_size_in_elements
;
8311 for (pixel_data_type
* d
= dst
; d
< end
; d
+= channel_count
) {
8314 dst
+= padded_row_size_in_elements
;
8318 void GLES2DecoderImpl::FinishReadPixels(
8319 const cmds::ReadPixels
& c
,
8321 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
8322 GLsizei width
= c
.width
;
8323 GLsizei height
= c
.height
;
8324 GLenum format
= c
.format
;
8325 GLenum type
= c
.type
;
8326 typedef cmds::ReadPixels::Result Result
;
8328 Result
* result
= NULL
;
8329 if (c
.result_shm_id
!= 0) {
8330 result
= GetSharedMemoryAs
<Result
*>(
8331 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
8334 glDeleteBuffersARB(1, &buffer
);
8339 GLES2Util::ComputeImageDataSizes(
8340 width
, height
, 1, format
, type
, state_
.pack_alignment
, &pixels_size
,
8342 void* pixels
= GetSharedMemoryAs
<void*>(
8343 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
8346 glDeleteBuffersARB(1, &buffer
);
8352 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
8354 if (features().map_buffer_range
) {
8355 data
= glMapBufferRange(
8356 GL_PIXEL_PACK_BUFFER_ARB
, 0, pixels_size
, GL_MAP_READ_BIT
);
8358 data
= glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB
, GL_READ_ONLY
);
8361 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glMapBuffer",
8362 "Unable to map memory for readback.");
8365 memcpy(pixels
, data
, pixels_size
);
8366 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
8367 // have to restore the state.
8368 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB
);
8369 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
8370 glDeleteBuffersARB(1, &buffer
);
8373 if (result
!= NULL
) {
8377 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
8378 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
8379 if ((channels_exist
& 0x0008) == 0 &&
8380 workarounds().clear_alpha_in_readpixels
) {
8381 // Set the alpha to 255 because some drivers are buggy in this regard.
8384 uint32 unpadded_row_size
;
8385 uint32 padded_row_size
;
8386 if (!GLES2Util::ComputeImageDataSizes(
8387 width
, 2, 1, format
, type
, state_
.pack_alignment
, &temp_size
,
8388 &unpadded_row_size
, &padded_row_size
)) {
8392 uint32 channel_count
= 0;
8393 uint32 alpha_channel
= 0;
8406 if (channel_count
> 0) {
8408 case GL_UNSIGNED_BYTE
:
8409 WriteAlphaData
<uint8
>(
8410 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
8411 padded_row_size
, 0xFF);
8414 WriteAlphaData
<float>(
8415 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
8416 padded_row_size
, 1.0f
);
8419 WriteAlphaData
<uint16
>(
8420 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
8421 padded_row_size
, 0x3C00);
8428 error::Error
GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size
,
8429 const void* cmd_data
) {
8430 const gles2::cmds::ReadPixels
& c
=
8431 *static_cast<const gles2::cmds::ReadPixels
*>(cmd_data
);
8432 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
8433 error::Error fbo_error
= WillAccessBoundFramebufferForRead();
8434 if (fbo_error
!= error::kNoError
)
8438 GLsizei width
= c
.width
;
8439 GLsizei height
= c
.height
;
8440 GLenum format
= c
.format
;
8441 GLenum type
= c
.type
;
8442 GLboolean async
= static_cast<GLboolean
>(c
.async
);
8443 if (width
< 0 || height
< 0) {
8444 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glReadPixels", "dimensions < 0");
8445 return error::kNoError
;
8447 typedef cmds::ReadPixels::Result Result
;
8449 if (!GLES2Util::ComputeImageDataSizes(
8450 width
, height
, 1, format
, type
, state_
.pack_alignment
, &pixels_size
,
8452 return error::kOutOfBounds
;
8454 void* pixels
= GetSharedMemoryAs
<void*>(
8455 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
8457 return error::kOutOfBounds
;
8459 Result
* result
= NULL
;
8460 if (c
.result_shm_id
!= 0) {
8461 result
= GetSharedMemoryAs
<Result
*>(
8462 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
8464 return error::kOutOfBounds
;
8468 if (!validators_
->read_pixel_format
.IsValid(format
)) {
8469 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format
, "format");
8470 return error::kNoError
;
8472 if (!validators_
->read_pixel_type
.IsValid(type
)) {
8473 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type
, "type");
8474 return error::kNoError
;
8477 GLenum src_internal_format
= GetBoundReadFrameBufferInternalFormat();
8478 if (src_internal_format
== 0) {
8479 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glReadPixels",
8480 "no valid read buffer source");
8481 return error::kNoError
;
8483 std::vector
<GLenum
> accepted_formats
;
8484 std::vector
<GLenum
> accepted_types
;
8485 switch (src_internal_format
) {
8487 accepted_formats
.push_back(GL_RGBA
);
8488 accepted_types
.push_back(GL_UNSIGNED_INT_2_10_10_10_REV
);
8495 // All the RGB_INTEGER formats are not renderable.
8499 accepted_formats
.push_back(GL_RGBA_INTEGER
);
8500 accepted_types
.push_back(GL_UNSIGNED_INT
);
8511 accepted_formats
.push_back(GL_RGBA_INTEGER
);
8512 accepted_types
.push_back(GL_INT
);
8515 accepted_formats
.push_back(GL_RGBA
);
8517 GLenum src_type
= GetBoundReadFrameBufferTextureType();
8520 case GL_HALF_FLOAT_OES
:
8522 case GL_UNSIGNED_INT_10F_11F_11F_REV
:
8523 accepted_types
.push_back(GL_FLOAT
);
8526 accepted_types
.push_back(GL_UNSIGNED_BYTE
);
8532 if (!IsWebGLContext()) {
8533 accepted_formats
.push_back(GL_BGRA_EXT
);
8534 accepted_types
.push_back(GL_UNSIGNED_BYTE
);
8536 DCHECK_EQ(accepted_formats
.size(), accepted_types
.size());
8537 bool format_type_acceptable
= false;
8538 for (size_t ii
= 0; ii
< accepted_formats
.size(); ++ii
) {
8539 if (format
== accepted_formats
[ii
] && type
== accepted_types
[ii
]) {
8540 format_type_acceptable
= true;
8544 if (!format_type_acceptable
) {
8545 // format and type are acceptable enums but not guaranteed to be supported
8546 // for this framebuffer. Have to ask gl if they are valid.
8547 GLint preferred_format
= 0;
8548 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT
, &preferred_format
);
8549 GLint preferred_type
= 0;
8550 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE
, &preferred_type
);
8551 if (format
== static_cast<GLenum
>(preferred_format
) &&
8552 type
== static_cast<GLenum
>(preferred_type
)) {
8553 format_type_acceptable
= true;
8556 if (!format_type_acceptable
) {
8557 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glReadPixels",
8558 "format and type incompatible with the current read framebuffer");
8559 return error::kNoError
;
8561 if (width
== 0 || height
== 0) {
8562 return error::kNoError
;
8565 // Get the size of the current fbo or backbuffer.
8566 gfx::Size max_size
= GetBoundReadFrameBufferSize();
8570 if (!SafeAddInt32(x
, width
, &max_x
) || !SafeAddInt32(y
, height
, &max_y
)) {
8572 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
8573 return error::kNoError
;
8576 if (!CheckBoundFramebuffersValid("glReadPixels")) {
8577 return error::kNoError
;
8580 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
8582 ScopedResolvedFrameBufferBinder
binder(this, false, true);
8584 if (x
< 0 || y
< 0 || max_x
> max_size
.width() || max_y
> max_size
.height()) {
8585 // The user requested an out of range area. Get the results 1 line
8588 uint32 unpadded_row_size
;
8589 uint32 padded_row_size
;
8590 if (!GLES2Util::ComputeImageDataSizes(
8591 width
, 2, 1, format
, type
, state_
.pack_alignment
, &temp_size
,
8592 &unpadded_row_size
, &padded_row_size
)) {
8594 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
8595 return error::kNoError
;
8598 GLint dest_x_offset
= std::max(-x
, 0);
8599 uint32 dest_row_offset
;
8600 if (!GLES2Util::ComputeImageDataSizes(
8601 dest_x_offset
, 1, 1, format
, type
, state_
.pack_alignment
,
8602 &dest_row_offset
, NULL
, NULL
)) {
8604 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
8605 return error::kNoError
;
8608 // Copy each row into the larger dest rect.
8609 int8
* dst
= static_cast<int8
*>(pixels
);
8610 GLint read_x
= std::max(0, x
);
8611 GLint read_end_x
= std::max(0, std::min(max_size
.width(), max_x
));
8612 GLint read_width
= read_end_x
- read_x
;
8613 for (GLint yy
= 0; yy
< height
; ++yy
) {
8617 memset(dst
, 0, unpadded_row_size
);
8619 // If the row is in range, copy it.
8620 if (ry
>= 0 && ry
< max_size
.height() && read_width
> 0) {
8622 read_x
, ry
, read_width
, 1, format
, type
, dst
+ dest_row_offset
);
8624 dst
+= padded_row_size
;
8627 if (async
&& features().use_async_readpixels
) {
8629 glGenBuffersARB(1, &buffer
);
8630 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
8631 // For ANGLE client version 2, GL_STREAM_READ is not available.
8632 const GLenum usage_hint
= feature_info_
->gl_version_info().is_angle
?
8633 GL_STATIC_DRAW
: GL_STREAM_READ
;
8634 glBufferData(GL_PIXEL_PACK_BUFFER_ARB
, pixels_size
, NULL
, usage_hint
);
8635 GLenum error
= glGetError();
8636 if (error
== GL_NO_ERROR
) {
8637 glReadPixels(x
, y
, width
, height
, format
, type
, 0);
8638 pending_readpixel_fences_
.push(linked_ptr
<FenceCallback
>(
8639 new FenceCallback()));
8640 WaitForReadPixels(base::Bind(
8641 &GLES2DecoderImpl::FinishReadPixels
,
8642 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
8643 <GLES2DecoderImpl
>(this),
8645 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
8646 return error::kNoError
;
8648 // On error, unbind pack buffer and fall through to sync readpixels
8649 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
8650 glDeleteBuffersARB(1, &buffer
);
8653 glReadPixels(x
, y
, width
, height
, format
, type
, pixels
);
8655 GLenum error
= LOCAL_PEEK_GL_ERROR("glReadPixels");
8656 if (error
== GL_NO_ERROR
) {
8657 if (result
!= NULL
) {
8660 FinishReadPixels(c
, 0);
8663 return error::kNoError
;
8666 error::Error
GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size
,
8667 const void* cmd_data
) {
8668 const gles2::cmds::PixelStorei
& c
=
8669 *static_cast<const gles2::cmds::PixelStorei
*>(cmd_data
);
8670 GLenum pname
= c
.pname
;
8671 GLenum param
= c
.param
;
8672 if (!validators_
->pixel_store
.IsValid(pname
)) {
8673 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname
, "pname");
8674 return error::kNoError
;
8677 case GL_PACK_ALIGNMENT
:
8678 case GL_UNPACK_ALIGNMENT
:
8679 if (!validators_
->pixel_store_alignment
.IsValid(param
)) {
8681 GL_INVALID_VALUE
, "glPixelStorei", "param GL_INVALID_VALUE");
8682 return error::kNoError
;
8688 glPixelStorei(pname
, param
);
8690 case GL_PACK_ALIGNMENT
:
8691 state_
.pack_alignment
= param
;
8693 case GL_PACK_REVERSE_ROW_ORDER_ANGLE
:
8694 state_
.pack_reverse_row_order
= (param
!= 0);
8696 case GL_UNPACK_ALIGNMENT
:
8697 state_
.unpack_alignment
= param
;
8700 // Validation should have prevented us from getting here.
8704 return error::kNoError
;
8707 error::Error
GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
8708 uint32 immediate_data_size
,
8709 const void* cmd_data
) {
8710 const gles2::cmds::PostSubBufferCHROMIUM
& c
=
8711 *static_cast<const gles2::cmds::PostSubBufferCHROMIUM
*>(cmd_data
);
8712 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
8714 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
8716 if (!supports_post_sub_buffer_
) {
8718 GL_INVALID_OPERATION
,
8719 "glPostSubBufferCHROMIUM", "command not supported by surface");
8720 return error::kNoError
;
8723 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
8726 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
8727 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
8728 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
8729 is_offscreen
? offscreen_size_
: surface_
->GetSize());
8731 if (surface_
->PostSubBuffer(c
.x
, c
.y
, c
.width
, c
.height
) !=
8732 gfx::SwapResult::SWAP_FAILED
) {
8733 return error::kNoError
;
8735 LOG(ERROR
) << "Context lost because PostSubBuffer failed.";
8736 return error::kLostContext
;
8740 error::Error
GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
8741 uint32 immediate_data_size
,
8742 const void* cmd_data
) {
8743 const gles2::cmds::ScheduleOverlayPlaneCHROMIUM
& c
=
8744 *static_cast<const gles2::cmds::ScheduleOverlayPlaneCHROMIUM
*>(cmd_data
);
8745 TextureRef
* ref
= texture_manager()->GetTexture(c
.overlay_texture_id
);
8747 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
8748 "glScheduleOverlayPlaneCHROMIUM",
8750 return error::kNoError
;
8752 gfx::GLImage
* image
=
8753 ref
->texture()->GetLevelImage(ref
->texture()->target(), 0);
8755 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
8756 "glScheduleOverlayPlaneCHROMIUM",
8757 "unsupported texture format");
8758 return error::kNoError
;
8760 gfx::OverlayTransform transform
= GetGFXOverlayTransform(c
.plane_transform
);
8761 if (transform
== gfx::OVERLAY_TRANSFORM_INVALID
) {
8762 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM
,
8763 "glScheduleOverlayPlaneCHROMIUM",
8764 "invalid transform enum");
8765 return error::kNoError
;
8767 if (!surface_
->ScheduleOverlayPlane(
8771 gfx::Rect(c
.bounds_x
, c
.bounds_y
, c
.bounds_width
, c
.bounds_height
),
8772 gfx::RectF(c
.uv_x
, c
.uv_y
, c
.uv_width
, c
.uv_height
))) {
8773 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
8774 "glScheduleOverlayPlaneCHROMIUM",
8775 "failed to schedule overlay");
8777 return error::kNoError
;
8780 error::Error
GLES2DecoderImpl::GetAttribLocationHelper(
8781 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8782 const std::string
& name_str
) {
8783 if (!StringIsValidForGLES(name_str
.c_str())) {
8785 GL_INVALID_VALUE
, "glGetAttribLocation", "Invalid character");
8786 return error::kNoError
;
8788 Program
* program
= GetProgramInfoNotShader(
8789 client_id
, "glGetAttribLocation");
8791 return error::kNoError
;
8793 if (!program
->IsValid()) {
8795 GL_INVALID_OPERATION
, "glGetAttribLocation", "program not linked");
8796 return error::kNoError
;
8798 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8799 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8801 return error::kOutOfBounds
;
8803 // Require the client to init this incase the context is lost and we are no
8804 // longer executing commands.
8805 if (*location
!= -1) {
8806 return error::kGenericError
;
8808 *location
= program
->GetAttribLocation(name_str
);
8809 return error::kNoError
;
8812 error::Error
GLES2DecoderImpl::HandleGetAttribLocation(
8813 uint32 immediate_data_size
,
8814 const void* cmd_data
) {
8815 const gles2::cmds::GetAttribLocation
& c
=
8816 *static_cast<const gles2::cmds::GetAttribLocation
*>(cmd_data
);
8817 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8819 return error::kInvalidArguments
;
8821 std::string name_str
;
8822 if (!bucket
->GetAsString(&name_str
)) {
8823 return error::kInvalidArguments
;
8825 return GetAttribLocationHelper(
8826 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8829 error::Error
GLES2DecoderImpl::GetUniformLocationHelper(
8830 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8831 const std::string
& name_str
) {
8832 if (!StringIsValidForGLES(name_str
.c_str())) {
8834 GL_INVALID_VALUE
, "glGetUniformLocation", "Invalid character");
8835 return error::kNoError
;
8837 Program
* program
= GetProgramInfoNotShader(
8838 client_id
, "glGetUniformLocation");
8840 return error::kNoError
;
8842 if (!program
->IsValid()) {
8844 GL_INVALID_OPERATION
, "glGetUniformLocation", "program not linked");
8845 return error::kNoError
;
8847 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8848 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8850 return error::kOutOfBounds
;
8852 // Require the client to init this incase the context is lost an we are no
8853 // longer executing commands.
8854 if (*location
!= -1) {
8855 return error::kGenericError
;
8857 *location
= program
->GetUniformFakeLocation(name_str
);
8858 return error::kNoError
;
8861 error::Error
GLES2DecoderImpl::HandleGetUniformLocation(
8862 uint32 immediate_data_size
,
8863 const void* cmd_data
) {
8864 const gles2::cmds::GetUniformLocation
& c
=
8865 *static_cast<const gles2::cmds::GetUniformLocation
*>(cmd_data
);
8866 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8868 return error::kInvalidArguments
;
8870 std::string name_str
;
8871 if (!bucket
->GetAsString(&name_str
)) {
8872 return error::kInvalidArguments
;
8874 return GetUniformLocationHelper(
8875 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8878 error::Error
GLES2DecoderImpl::HandleGetUniformIndices(
8879 uint32 immediate_data_size
,
8880 const void* cmd_data
) {
8881 if (!unsafe_es3_apis_enabled())
8882 return error::kUnknownCommand
;
8883 const gles2::cmds::GetUniformIndices
& c
=
8884 *static_cast<const gles2::cmds::GetUniformIndices
*>(cmd_data
);
8885 Bucket
* bucket
= GetBucket(c
.names_bucket_id
);
8887 return error::kInvalidArguments
;
8890 std::vector
<char*> names
;
8891 std::vector
<GLint
> len
;
8892 if (!bucket
->GetAsStrings(&count
, &names
, &len
) || count
<= 0) {
8893 return error::kInvalidArguments
;
8895 typedef cmds::GetUniformIndices::Result Result
;
8896 Result
* result
= GetSharedMemoryAs
<Result
*>(
8897 c
.indices_shm_id
, c
.indices_shm_offset
,
8898 Result::ComputeSize(static_cast<size_t>(count
)));
8899 GLuint
* indices
= result
? result
->GetData() : NULL
;
8900 if (indices
== NULL
) {
8901 return error::kOutOfBounds
;
8903 // Check that the client initialized the result.
8904 if (result
->size
!= 0) {
8905 return error::kInvalidArguments
;
8907 Program
* program
= GetProgramInfoNotShader(c
.program
, "glGetUniformIndices");
8909 return error::kNoError
;
8911 GLuint service_id
= program
->service_id();
8912 GLint link_status
= GL_FALSE
;
8913 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
8914 if (link_status
!= GL_TRUE
) {
8915 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
8916 "glGetUniformIndices", "program not linked");
8917 return error::kNoError
;
8919 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetUniformIndices");
8920 glGetUniformIndices(service_id
, count
, &names
[0], indices
);
8921 GLenum error
= glGetError();
8922 if (error
== GL_NO_ERROR
) {
8923 result
->SetNumResults(count
);
8925 LOCAL_SET_GL_ERROR(error
, "GetUniformIndices", "");
8927 return error::kNoError
;
8930 error::Error
GLES2DecoderImpl::GetFragDataLocationHelper(
8931 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8932 const std::string
& name_str
) {
8933 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8934 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8936 return error::kOutOfBounds
;
8938 // Require the client to init this incase the context is lost and we are no
8939 // longer executing commands.
8940 if (*location
!= -1) {
8941 return error::kGenericError
;
8943 Program
* program
= GetProgramInfoNotShader(
8944 client_id
, "glGetFragDataLocation");
8946 return error::kNoError
;
8948 *location
= glGetFragDataLocation(program
->service_id(), name_str
.c_str());
8949 return error::kNoError
;
8952 error::Error
GLES2DecoderImpl::HandleGetFragDataLocation(
8953 uint32 immediate_data_size
,
8954 const void* cmd_data
) {
8955 if (!unsafe_es3_apis_enabled())
8956 return error::kUnknownCommand
;
8957 const gles2::cmds::GetFragDataLocation
& c
=
8958 *static_cast<const gles2::cmds::GetFragDataLocation
*>(cmd_data
);
8959 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8961 return error::kInvalidArguments
;
8963 std::string name_str
;
8964 if (!bucket
->GetAsString(&name_str
)) {
8965 return error::kInvalidArguments
;
8967 return GetFragDataLocationHelper(
8968 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8971 error::Error
GLES2DecoderImpl::HandleGetUniformBlockIndex(
8972 uint32 immediate_data_size
, const void* cmd_data
) {
8973 if (!unsafe_es3_apis_enabled())
8974 return error::kUnknownCommand
;
8975 const gles2::cmds::GetUniformBlockIndex
& c
=
8976 *static_cast<const gles2::cmds::GetUniformBlockIndex
*>(cmd_data
);
8977 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8979 return error::kInvalidArguments
;
8981 std::string name_str
;
8982 if (!bucket
->GetAsString(&name_str
)) {
8983 return error::kInvalidArguments
;
8985 GLuint
* index
= GetSharedMemoryAs
<GLuint
*>(
8986 c
.index_shm_id
, c
.index_shm_offset
, sizeof(GLuint
));
8988 return error::kOutOfBounds
;
8990 // Require the client to init this in case the context is lost and we are no
8991 // longer executing commands.
8992 if (*index
!= GL_INVALID_INDEX
) {
8993 return error::kGenericError
;
8995 Program
* program
= GetProgramInfoNotShader(
8996 c
.program
, "glGetUniformBlockIndex");
8998 return error::kNoError
;
9000 *index
= glGetUniformBlockIndex(program
->service_id(), name_str
.c_str());
9001 return error::kNoError
;
9004 error::Error
GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size
,
9005 const void* cmd_data
) {
9006 const gles2::cmds::GetString
& c
=
9007 *static_cast<const gles2::cmds::GetString
*>(cmd_data
);
9008 GLenum name
= static_cast<GLenum
>(c
.name
);
9009 if (!validators_
->string_type
.IsValid(name
)) {
9010 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name
, "name");
9011 return error::kNoError
;
9014 const char* str
= nullptr;
9015 std::string extensions
;
9018 if (unsafe_es3_apis_enabled())
9019 str
= "OpenGL ES 3.0 Chromium";
9021 str
= "OpenGL ES 2.0 Chromium";
9023 case GL_SHADING_LANGUAGE_VERSION
:
9024 if (unsafe_es3_apis_enabled())
9025 str
= "OpenGL ES GLSL ES 3.0 Chromium";
9027 str
= "OpenGL ES GLSL ES 1.0 Chromium";
9031 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
9032 // They are used by WEBGL_debug_renderer_info.
9033 if (!IsWebGLContext())
9036 str
= reinterpret_cast<const char*>(glGetString(name
));
9040 // For WebGL contexts, strip out the OES derivatives and
9041 // EXT frag depth extensions if they have not been enabled.
9042 if (IsWebGLContext()) {
9043 extensions
= feature_info_
->extensions();
9044 if (!derivatives_explicitly_enabled_
) {
9045 size_t offset
= extensions
.find(kOESDerivativeExtension
);
9046 if (std::string::npos
!= offset
) {
9047 extensions
.replace(offset
, arraysize(kOESDerivativeExtension
),
9051 if (!frag_depth_explicitly_enabled_
) {
9052 size_t offset
= extensions
.find(kEXTFragDepthExtension
);
9053 if (std::string::npos
!= offset
) {
9054 extensions
.replace(offset
, arraysize(kEXTFragDepthExtension
),
9058 if (!draw_buffers_explicitly_enabled_
) {
9059 size_t offset
= extensions
.find(kEXTDrawBuffersExtension
);
9060 if (std::string::npos
!= offset
) {
9061 extensions
.replace(offset
, arraysize(kEXTDrawBuffersExtension
),
9065 if (!shader_texture_lod_explicitly_enabled_
) {
9066 size_t offset
= extensions
.find(kEXTShaderTextureLodExtension
);
9067 if (std::string::npos
!= offset
) {
9068 extensions
.replace(offset
,
9069 arraysize(kEXTShaderTextureLodExtension
),
9074 extensions
= feature_info_
->extensions().c_str();
9076 if (supports_post_sub_buffer_
)
9077 extensions
+= " GL_CHROMIUM_post_sub_buffer";
9078 str
= extensions
.c_str();
9082 str
= reinterpret_cast<const char*>(glGetString(name
));
9085 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
9086 bucket
->SetFromString(str
);
9087 return error::kNoError
;
9090 error::Error
GLES2DecoderImpl::HandleBufferData(uint32 immediate_data_size
,
9091 const void* cmd_data
) {
9092 const gles2::cmds::BufferData
& c
=
9093 *static_cast<const gles2::cmds::BufferData
*>(cmd_data
);
9094 GLenum target
= static_cast<GLenum
>(c
.target
);
9095 GLsizeiptr size
= static_cast<GLsizeiptr
>(c
.size
);
9096 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
9097 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
9098 GLenum usage
= static_cast<GLenum
>(c
.usage
);
9099 const void* data
= NULL
;
9100 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
9101 data
= GetSharedMemoryAs
<const void*>(data_shm_id
, data_shm_offset
, size
);
9103 return error::kOutOfBounds
;
9106 buffer_manager()->ValidateAndDoBufferData(&state_
, target
, size
, data
, usage
);
9107 return error::kNoError
;
9110 void GLES2DecoderImpl::DoBufferSubData(
9111 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
) {
9112 // Just delegate it. Some validation is actually done before this.
9113 buffer_manager()->ValidateAndDoBufferSubData(
9114 &state_
, target
, offset
, size
, data
);
9117 bool GLES2DecoderImpl::ClearLevel(Texture
* texture
,
9126 uint32 channels
= GLES2Util::GetChannelsForFormat(format
);
9127 if ((feature_info_
->feature_flags().angle_depth_texture
||
9128 feature_info_
->IsES3Enabled())
9129 && (channels
& GLES2Util::kDepth
) != 0) {
9130 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
9131 // on depth formats.
9133 glGenFramebuffersEXT(1, &fb
);
9134 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb
);
9136 bool have_stencil
= (channels
& GLES2Util::kStencil
) != 0;
9137 GLenum attachment
= have_stencil
? GL_DEPTH_STENCIL_ATTACHMENT
:
9138 GL_DEPTH_ATTACHMENT
;
9140 glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT
, attachment
, target
,
9141 texture
->service_id(), level
);
9142 // ANGLE promises a depth only attachment ok.
9143 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT
) !=
9144 GL_FRAMEBUFFER_COMPLETE
) {
9148 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
9149 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
9151 state_
.SetDeviceDepthMask(GL_TRUE
);
9152 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
9153 glScissor(xoffset
, yoffset
, width
, height
);
9154 glClear(GL_DEPTH_BUFFER_BIT
| (have_stencil
? GL_STENCIL_BUFFER_BIT
: 0));
9156 RestoreClearState();
9158 glDeleteFramebuffersEXT(1, &fb
);
9159 Framebuffer
* framebuffer
=
9160 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
9161 GLuint fb_service_id
=
9162 framebuffer
? framebuffer
->service_id() : GetBackbufferServiceId();
9163 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb_service_id
);
9167 static const uint32 kMaxZeroSize
= 1024 * 1024 * 4;
9170 uint32 padded_row_size
;
9171 if (!GLES2Util::ComputeImageDataSizes(
9172 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &size
,
9173 NULL
, &padded_row_size
)) {
9177 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size
);
9181 if (size
> kMaxZeroSize
) {
9182 if (kMaxZeroSize
< padded_row_size
) {
9183 // That'd be an awfully large texture.
9186 // We should never have a large total size with a zero row size.
9187 DCHECK_GT(padded_row_size
, 0U);
9188 tile_height
= kMaxZeroSize
/ padded_row_size
;
9189 if (!GLES2Util::ComputeImageDataSizes(
9190 width
, tile_height
, 1, format
, type
, state_
.unpack_alignment
, &size
,
9195 tile_height
= height
;
9198 // Assumes the size has already been checked.
9199 scoped_ptr
<char[]> zero(new char[size
]);
9200 memset(zero
.get(), 0, size
);
9201 glBindTexture(texture
->target(), texture
->service_id());
9204 while (y
< height
) {
9205 GLint h
= y
+ tile_height
> height
? height
- y
: tile_height
;
9206 glTexSubImage2D(target
, level
, xoffset
, yoffset
+ y
, width
, h
, format
, type
,
9210 TextureRef
* bound_texture
=
9211 texture_manager()->GetTextureInfoForTarget(&state_
, texture
->target());
9212 glBindTexture(texture
->target(),
9213 bound_texture
? bound_texture
->service_id() : 0);
9219 const int kS3TCBlockWidth
= 4;
9220 const int kS3TCBlockHeight
= 4;
9221 const int kS3TCDXT1BlockSize
= 8;
9222 const int kS3TCDXT3AndDXT5BlockSize
= 16;
9223 const int kEACAndETC2BlockSize
= 4;
9225 bool IsValidDXTSize(GLint level
, GLsizei size
) {
9226 return (size
== 1) ||
9227 (size
== 2) || !(size
% kS3TCBlockWidth
);
9230 bool IsValidPVRTCSize(GLint level
, GLsizei size
) {
9231 return GLES2Util::IsPOT(size
);
9234 } // anonymous namespace.
9236 bool GLES2DecoderImpl::GetCompressedTexSizeInBytes(
9237 const char* function_name
, GLsizei width
, GLsizei height
, GLsizei depth
,
9238 GLenum format
, GLsizei
* size_in_bytes
) {
9239 base::CheckedNumeric
<GLsizei
> bytes_required(0);
9242 case GL_ATC_RGB_AMD
:
9243 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
9244 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
9245 case GL_ETC1_RGB8_OES
:
9247 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
9249 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
9250 bytes_required
*= kS3TCDXT1BlockSize
;
9252 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
9253 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
9254 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
9255 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
9257 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
9259 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
9260 bytes_required
*= kS3TCDXT3AndDXT5BlockSize
;
9262 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
9263 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
9264 bytes_required
= std::max(width
, 8);
9265 bytes_required
*= std::max(height
, 8);
9266 bytes_required
*= 4;
9267 bytes_required
+= 7;
9268 bytes_required
/= 8;
9270 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
9271 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
:
9272 bytes_required
= std::max(width
, 16);
9273 bytes_required
*= std::max(height
, 8);
9274 bytes_required
*= 2;
9275 bytes_required
+= 7;
9276 bytes_required
/= 8;
9280 case GL_COMPRESSED_R11_EAC
:
9281 case GL_COMPRESSED_SIGNED_R11_EAC
:
9282 case GL_COMPRESSED_RGB8_ETC2
:
9283 case GL_COMPRESSED_SRGB8_ETC2
:
9284 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9285 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9287 (width
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9289 (height
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9290 bytes_required
*= 8;
9291 bytes_required
*= depth
;
9293 case GL_COMPRESSED_RG11_EAC
:
9294 case GL_COMPRESSED_SIGNED_RG11_EAC
:
9295 case GL_COMPRESSED_RGBA8_ETC2_EAC
:
9296 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
:
9298 (width
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9300 (height
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9301 bytes_required
*= 16;
9302 bytes_required
*= depth
;
9305 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, format
, "format");
9309 if (!bytes_required
.IsValid()) {
9310 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "invalid size");
9314 *size_in_bytes
= bytes_required
.ValueOrDefault(0);
9318 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
9319 const char* function_name
, GLsizei width
, GLsizei height
, GLsizei depth
,
9320 GLenum format
, GLsizei size
) {
9321 GLsizei bytes_required
= 0;
9322 if (!GetCompressedTexSizeInBytes(
9323 function_name
, width
, height
, depth
, format
, &bytes_required
)) {
9327 if (size
!= bytes_required
) {
9329 GL_INVALID_VALUE
, function_name
, "size is not correct for dimensions");
9336 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
9337 const char* function_name
, GLenum target
, GLint level
,
9338 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
) {
9340 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
9341 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
9342 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
9343 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
9344 DCHECK_EQ(1, depth
); // 2D formats.
9345 if (!IsValidDXTSize(level
, width
) || !IsValidDXTSize(level
, height
)) {
9347 GL_INVALID_OPERATION
, function_name
,
9348 "width or height invalid for level");
9352 case GL_ATC_RGB_AMD
:
9353 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
9354 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
9355 case GL_ETC1_RGB8_OES
:
9356 DCHECK_EQ(1, depth
); // 2D formats.
9357 if (width
<= 0 || height
<= 0) {
9359 GL_INVALID_OPERATION
, function_name
,
9360 "width or height invalid for level");
9364 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
9365 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
9366 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
9367 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
:
9368 DCHECK_EQ(1, depth
); // 2D formats.
9369 if (!IsValidPVRTCSize(level
, width
) ||
9370 !IsValidPVRTCSize(level
, height
)) {
9372 GL_INVALID_OPERATION
, function_name
,
9373 "width or height invalid for level");
9379 case GL_COMPRESSED_R11_EAC
:
9380 case GL_COMPRESSED_SIGNED_R11_EAC
:
9381 case GL_COMPRESSED_RG11_EAC
:
9382 case GL_COMPRESSED_SIGNED_RG11_EAC
:
9383 case GL_COMPRESSED_RGB8_ETC2
:
9384 case GL_COMPRESSED_SRGB8_ETC2
:
9385 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9386 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9387 case GL_COMPRESSED_RGBA8_ETC2_EAC
:
9388 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
:
9389 if (width
<= 0 || height
<= 0 || depth
<= 0) {
9391 GL_INVALID_OPERATION
, function_name
,
9392 "width, height, or depth invalid");
9395 if (target
== GL_TEXTURE_3D
) {
9397 GL_INVALID_OPERATION
, function_name
,
9398 "target invalid for format");
9407 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
9408 const char* function_name
,
9409 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
9410 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
,
9412 if (xoffset
< 0 || yoffset
< 0 || zoffset
< 0) {
9414 GL_INVALID_VALUE
, function_name
, "x/y/z offset < 0");
9419 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
9420 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
9421 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
9422 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
: {
9423 const int kBlockWidth
= 4;
9424 const int kBlockHeight
= 4;
9425 if ((xoffset
% kBlockWidth
) || (yoffset
% kBlockHeight
)) {
9427 GL_INVALID_OPERATION
, function_name
,
9428 "xoffset or yoffset not multiple of 4");
9431 GLsizei tex_width
= 0;
9432 GLsizei tex_height
= 0;
9433 if (!texture
->GetLevelSize(target
, level
,
9434 &tex_width
, &tex_height
, nullptr) ||
9435 width
- xoffset
> tex_width
||
9436 height
- yoffset
> tex_height
) {
9438 GL_INVALID_OPERATION
, function_name
, "dimensions out of range");
9441 return ValidateCompressedTexDimensions(
9442 function_name
, target
, level
, width
, height
, 1, format
);
9444 case GL_ATC_RGB_AMD
:
9445 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
9446 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
: {
9448 GL_INVALID_OPERATION
, function_name
,
9449 "not supported for ATC textures");
9452 case GL_ETC1_RGB8_OES
: {
9454 GL_INVALID_OPERATION
, function_name
,
9455 "not supported for ECT1_RGB8_OES textures");
9458 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
9459 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
9460 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
9461 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
: {
9462 if ((xoffset
!= 0) || (yoffset
!= 0)) {
9464 GL_INVALID_OPERATION
, function_name
,
9465 "xoffset and yoffset must be zero");
9468 GLsizei tex_width
= 0;
9469 GLsizei tex_height
= 0;
9470 if (!texture
->GetLevelSize(target
, level
,
9471 &tex_width
, &tex_height
, nullptr) ||
9472 width
!= tex_width
||
9473 height
!= tex_height
) {
9475 GL_INVALID_OPERATION
, function_name
,
9476 "dimensions must match existing texture level dimensions");
9479 return ValidateCompressedTexDimensions(
9480 function_name
, target
, level
, width
, height
, 1, format
);
9484 case GL_COMPRESSED_R11_EAC
:
9485 case GL_COMPRESSED_SIGNED_R11_EAC
:
9486 case GL_COMPRESSED_RG11_EAC
:
9487 case GL_COMPRESSED_SIGNED_RG11_EAC
:
9488 case GL_COMPRESSED_RGB8_ETC2
:
9489 case GL_COMPRESSED_SRGB8_ETC2
:
9490 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9491 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9492 case GL_COMPRESSED_RGBA8_ETC2_EAC
:
9493 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
:
9495 const int kBlockSize
= 4;
9496 GLsizei tex_width
, tex_height
;
9497 if (target
== GL_TEXTURE_3D
||
9498 !texture
->GetLevelSize(target
, level
,
9499 &tex_width
, &tex_height
, nullptr) ||
9500 (xoffset
% kBlockSize
) || (yoffset
% kBlockSize
) ||
9501 ((width
% kBlockSize
) && xoffset
+ width
!= tex_width
) ||
9502 ((height
% kBlockSize
) && yoffset
+ height
!= tex_height
)) {
9504 GL_INVALID_OPERATION
, function_name
,
9505 "dimensions must match existing texture level dimensions");
9515 error::Error
GLES2DecoderImpl::DoCompressedTexImage2D(
9518 GLenum internal_format
,
9524 if (!validators_
->texture_target
.IsValid(target
)) {
9525 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9526 "glCompressedTexImage2D", target
, "target");
9527 return error::kNoError
;
9529 if (!validators_
->compressed_texture_format
.IsValid(
9531 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9532 "glCompressedTexImage2D", internal_format
, "internal_format");
9533 return error::kNoError
;
9535 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
9539 "glCompressedTexImage2D", "dimensions out of range");
9540 return error::kNoError
;
9542 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9547 "glCompressedTexImage2D", "unknown texture target");
9548 return error::kNoError
;
9550 Texture
* texture
= texture_ref
->texture();
9551 if (texture
->IsImmutable()) {
9553 GL_INVALID_OPERATION
,
9554 "glCompressedTexImage2D", "texture is immutable");
9555 return error::kNoError
;
9558 if (!ValidateCompressedTexDimensions("glCompressedTexImage2D", target
, level
,
9559 width
, height
, 1, internal_format
) ||
9560 !ValidateCompressedTexFuncData("glCompressedTexImage2D", width
, height
,
9561 1, internal_format
, image_size
)) {
9562 return error::kNoError
;
9565 if (!EnsureGPUMemoryAvailable(image_size
)) {
9567 GL_OUT_OF_MEMORY
, "glCompressedTexImage2D", "out of memory");
9568 return error::kNoError
;
9571 if (texture
->IsAttachedToFramebuffer()) {
9572 framebuffer_state_
.clear_state_dirty
= true;
9575 scoped_ptr
<int8
[]> zero
;
9577 zero
.reset(new int8
[image_size
]);
9578 memset(zero
.get(), 0, image_size
);
9581 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
9582 glCompressedTexImage2D(
9583 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
9584 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
9585 if (error
== GL_NO_ERROR
) {
9586 texture_manager()->SetLevelInfo(texture_ref
, target
, level
, internal_format
,
9587 width
, height
, 1, border
, 0, 0,
9588 gfx::Rect(width
, height
));
9591 // This may be a slow command. Exit command processing to allow for
9592 // context preemption and GPU watchdog checks.
9593 ExitCommandProcessingEarly();
9594 return error::kNoError
;
9597 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2D(
9598 uint32 immediate_data_size
,
9599 const void* cmd_data
) {
9600 const gles2::cmds::CompressedTexImage2D
& c
=
9601 *static_cast<const gles2::cmds::CompressedTexImage2D
*>(cmd_data
);
9602 GLenum target
= static_cast<GLenum
>(c
.target
);
9603 GLint level
= static_cast<GLint
>(c
.level
);
9604 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9605 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9606 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9607 GLint border
= static_cast<GLint
>(c
.border
);
9608 GLsizei image_size
= static_cast<GLsizei
>(c
.imageSize
);
9609 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
9610 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
9611 const void* data
= NULL
;
9612 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
9613 data
= GetSharedMemoryAs
<const void*>(
9614 data_shm_id
, data_shm_offset
, image_size
);
9616 return error::kOutOfBounds
;
9619 return DoCompressedTexImage2D(
9620 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
9623 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
9624 uint32 immediate_data_size
,
9625 const void* cmd_data
) {
9626 const gles2::cmds::CompressedTexImage2DBucket
& c
=
9627 *static_cast<const gles2::cmds::CompressedTexImage2DBucket
*>(cmd_data
);
9628 GLenum target
= static_cast<GLenum
>(c
.target
);
9629 GLint level
= static_cast<GLint
>(c
.level
);
9630 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9631 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9632 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9633 GLint border
= static_cast<GLint
>(c
.border
);
9634 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9636 return error::kInvalidArguments
;
9638 uint32 data_size
= bucket
->size();
9639 GLsizei imageSize
= data_size
;
9640 const void* data
= bucket
->GetData(0, data_size
);
9642 return error::kInvalidArguments
;
9644 return DoCompressedTexImage2D(
9645 target
, level
, internal_format
, width
, height
, border
,
9649 error::Error
GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
9650 uint32 immediate_data_size
,
9651 const void* cmd_data
) {
9652 const gles2::cmds::CompressedTexSubImage2DBucket
& c
=
9653 *static_cast<const gles2::cmds::CompressedTexSubImage2DBucket
*>(cmd_data
);
9654 GLenum target
= static_cast<GLenum
>(c
.target
);
9655 GLint level
= static_cast<GLint
>(c
.level
);
9656 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
9657 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
9658 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9659 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9660 GLenum format
= static_cast<GLenum
>(c
.format
);
9661 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9663 return error::kInvalidArguments
;
9665 uint32 data_size
= bucket
->size();
9666 GLsizei imageSize
= data_size
;
9667 const void* data
= bucket
->GetData(0, data_size
);
9669 return error::kInvalidArguments
;
9671 if (!validators_
->texture_target
.IsValid(target
)) {
9673 GL_INVALID_ENUM
, "glCompressedTexSubImage2D", "target");
9674 return error::kNoError
;
9676 if (!validators_
->compressed_texture_format
.IsValid(format
)) {
9677 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9678 "glCompressedTexSubImage2D", format
, "format");
9679 return error::kNoError
;
9683 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "width < 0");
9684 return error::kNoError
;
9688 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "height < 0");
9689 return error::kNoError
;
9691 if (imageSize
< 0) {
9693 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "imageSize < 0");
9694 return error::kNoError
;
9696 DoCompressedTexSubImage2D(
9697 target
, level
, xoffset
, yoffset
, width
, height
, format
, imageSize
, data
);
9698 return error::kNoError
;
9701 error::Error
GLES2DecoderImpl::DoCompressedTexImage3D(
9704 GLenum internal_format
,
9711 if (!validators_
->texture_3_d_target
.IsValid(target
)) {
9712 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9713 "glCompressedTexImage3D", target
, "target");
9714 return error::kNoError
;
9716 if (!validators_
->compressed_texture_format
.IsValid(
9718 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9719 "glCompressedTexImage3D", internal_format
, "internal_format");
9720 return error::kNoError
;
9722 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, depth
) ||
9726 "glCompressedTexImage3D", "dimensions out of range");
9727 return error::kNoError
;
9729 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9734 "glCompressedTexImage3D", "unknown texture target");
9735 return error::kNoError
;
9737 Texture
* texture
= texture_ref
->texture();
9738 if (texture
->IsImmutable()) {
9740 GL_INVALID_OPERATION
,
9741 "glCompressedTexImage3D", "texture is immutable");
9742 return error::kNoError
;
9745 if (!ValidateCompressedTexDimensions("glCompressedTexImage3D", target
, level
,
9746 width
, height
, depth
, internal_format
) ||
9747 !ValidateCompressedTexFuncData("glCompressedTexImage3D", width
, height
,
9748 depth
, internal_format
, image_size
)) {
9749 return error::kNoError
;
9752 if (!EnsureGPUMemoryAvailable(image_size
)) {
9754 GL_OUT_OF_MEMORY
, "glCompressedTexImage3D", "out of memory");
9755 return error::kNoError
;
9758 if (texture
->IsAttachedToFramebuffer()) {
9759 framebuffer_state_
.clear_state_dirty
= true;
9762 scoped_ptr
<int8
[]> zero
;
9764 zero
.reset(new int8
[image_size
]);
9765 memset(zero
.get(), 0, image_size
);
9768 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage3D");
9769 glCompressedTexImage3D(target
, level
, internal_format
, width
, height
, depth
,
9770 border
, image_size
, data
);
9771 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedTexImage3D");
9772 if (error
== GL_NO_ERROR
) {
9773 texture_manager()->SetLevelInfo(texture_ref
, target
, level
, internal_format
,
9774 width
, height
, depth
, border
, 0, 0,
9775 gfx::Rect(width
, height
));
9778 // This may be a slow command. Exit command processing to allow for
9779 // context preemption and GPU watchdog checks.
9780 ExitCommandProcessingEarly();
9781 return error::kNoError
;
9784 error::Error
GLES2DecoderImpl::HandleCompressedTexImage3D(
9785 uint32 immediate_data_size
, const void* cmd_data
) {
9786 if (!unsafe_es3_apis_enabled())
9787 return error::kUnknownCommand
;
9789 const gles2::cmds::CompressedTexImage3D
& c
=
9790 *static_cast<const gles2::cmds::CompressedTexImage3D
*>(cmd_data
);
9791 GLenum target
= static_cast<GLenum
>(c
.target
);
9792 GLint level
= static_cast<GLint
>(c
.level
);
9793 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9794 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9795 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9796 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9797 GLint border
= static_cast<GLint
>(c
.border
);
9798 GLsizei image_size
= static_cast<GLsizei
>(c
.imageSize
);
9799 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
9800 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
9801 const void* data
= NULL
;
9802 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
9803 data
= GetSharedMemoryAs
<const void*>(
9804 data_shm_id
, data_shm_offset
, image_size
);
9806 return error::kOutOfBounds
;
9809 return DoCompressedTexImage3D(target
, level
, internal_format
, width
, height
,
9810 depth
, border
, image_size
, data
);
9813 error::Error
GLES2DecoderImpl::HandleCompressedTexImage3DBucket(
9814 uint32 immediate_data_size
, const void* cmd_data
) {
9815 if (!unsafe_es3_apis_enabled())
9816 return error::kUnknownCommand
;
9818 const gles2::cmds::CompressedTexImage3DBucket
& c
=
9819 *static_cast<const gles2::cmds::CompressedTexImage3DBucket
*>(cmd_data
);
9820 GLenum target
= static_cast<GLenum
>(c
.target
);
9821 GLint level
= static_cast<GLint
>(c
.level
);
9822 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9823 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9824 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9825 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9826 GLint border
= static_cast<GLint
>(c
.border
);
9827 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9829 return error::kInvalidArguments
;
9831 uint32 data_size
= bucket
->size();
9832 GLsizei imageSize
= data_size
;
9833 const void* data
= bucket
->GetData(0, data_size
);
9835 return error::kInvalidArguments
;
9837 return DoCompressedTexImage3D(target
, level
, internal_format
, width
, height
,
9838 depth
, border
, imageSize
, data
);
9841 void GLES2DecoderImpl::DoCompressedTexSubImage3D(
9842 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
9843 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
,
9844 GLsizei image_size
, const void* data
) {
9845 if (!validators_
->texture_3_d_target
.IsValid(target
)) {
9847 GL_INVALID_ENUM
, "glCompressedTexSubImage3D", "target");
9850 if (!validators_
->compressed_texture_format
.IsValid(format
)) {
9851 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9852 "glCompressedTexSubImage3D", format
, "format");
9855 if (width
< 0 || height
< 0 || depth
< 0) {
9857 GL_INVALID_VALUE
, "glCompressedTexSubImage3D", "size < 0");
9860 if (image_size
< 0) {
9862 GL_INVALID_VALUE
, "glCompressedTexSubImage3D", "imageSize < 0");
9865 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9868 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCompressedTexSubImage3D",
9869 "unknown texture for target");
9872 Texture
* texture
= texture_ref
->texture();
9873 GLenum type
= 0, internal_format
= 0;
9874 if (!texture
->GetLevelType(target
, level
, &type
, &internal_format
)) {
9875 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCompressedTexSubImage3D",
9876 "level does not exist");
9879 if (internal_format
!= format
) {
9880 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCompressedTexSubImage3D",
9881 "format does not match internal format");
9884 if (!texture
->ValidForTexture(target
, level
, xoffset
, yoffset
, zoffset
,
9885 width
, height
, depth
, type
)) {
9886 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCompressedTexSubImage3D",
9890 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage3D",
9891 width
, height
, depth
, format
,
9893 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage3D",
9894 target
, level
, xoffset
, yoffset
,
9895 zoffset
, width
, height
, depth
,
9900 // Note: There is no need to deal with texture cleared tracking here
9901 // because the validation above means you can only get here if the level
9902 // is already a matching compressed format and in that case
9903 // CompressedTexImage3D already cleared the texture.
9904 glCompressedTexSubImage3D(
9905 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
, format
,
9908 // This may be a slow command. Exit command processing to allow for
9909 // context preemption and GPU watchdog checks.
9910 ExitCommandProcessingEarly();
9913 error::Error
GLES2DecoderImpl::HandleCompressedTexSubImage3DBucket(
9914 uint32 immediate_data_size
, const void* cmd_data
) {
9915 if (!unsafe_es3_apis_enabled())
9916 return error::kUnknownCommand
;
9917 const gles2::cmds::CompressedTexSubImage3DBucket
& c
=
9918 *static_cast<const gles2::cmds::CompressedTexSubImage3DBucket
*>(cmd_data
);
9919 GLenum target
= static_cast<GLenum
>(c
.target
);
9920 GLint level
= static_cast<GLint
>(c
.level
);
9921 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
9922 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
9923 GLint zoffset
= static_cast<GLint
>(c
.zoffset
);
9924 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9925 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9926 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9927 GLenum format
= static_cast<GLenum
>(c
.format
);
9928 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9930 return error::kInvalidArguments
;
9932 uint32 data_size
= bucket
->size();
9933 GLsizei image_size
= data_size
;
9934 const void* data
= bucket
->GetData(0, data_size
);
9936 return error::kInvalidArguments
;
9938 DoCompressedTexSubImage3D(
9939 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
, format
,
9941 return error::kNoError
;
9944 error::Error
GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size
,
9945 const void* cmd_data
) {
9946 const gles2::cmds::TexImage2D
& c
=
9947 *static_cast<const gles2::cmds::TexImage2D
*>(cmd_data
);
9948 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
9949 "width", c
.width
, "height", c
.height
);
9950 // Set as failed for now, but if it successed, this will be set to not failed.
9951 texture_state_
.tex_image_failed
= true;
9952 GLenum target
= static_cast<GLenum
>(c
.target
);
9953 GLint level
= static_cast<GLint
>(c
.level
);
9954 // TODO(kloveless): Change TexImage2D command to use unsigned integer
9955 // for internalformat.
9956 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9957 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9958 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9959 GLint border
= static_cast<GLint
>(c
.border
);
9960 GLenum format
= static_cast<GLenum
>(c
.format
);
9961 GLenum type
= static_cast<GLenum
>(c
.type
);
9962 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
9963 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
9965 if (!GLES2Util::ComputeImageDataSizes(
9966 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
9968 return error::kOutOfBounds
;
9970 const void* pixels
= NULL
;
9971 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
9972 pixels
= GetSharedMemoryAs
<const void*>(
9973 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
9975 return error::kOutOfBounds
;
9979 // For testing only. Allows us to stress the ability to respond to OOM errors.
9980 if (workarounds().simulate_out_of_memory_on_large_textures
&&
9981 (width
* height
>= 4096 * 4096)) {
9984 "glTexImage2D", "synthetic out of memory");
9985 return error::kNoError
;
9988 TextureManager::DoTexImageArguments args
= {
9989 target
, level
, internal_format
, width
, height
, 1, border
, format
, type
,
9990 pixels
, pixels_size
, TextureManager::DoTexImageArguments::kTexImage2D
};
9991 texture_manager()->ValidateAndDoTexImage(
9992 &texture_state_
, &state_
, &framebuffer_state_
, "glTexImage2D", args
);
9994 // This may be a slow command. Exit command processing to allow for
9995 // context preemption and GPU watchdog checks.
9996 ExitCommandProcessingEarly();
9997 return error::kNoError
;
10000 error::Error
GLES2DecoderImpl::HandleTexImage3D(uint32 immediate_data_size
,
10001 const void* cmd_data
) {
10002 if (!unsafe_es3_apis_enabled())
10003 return error::kUnknownCommand
;
10005 const gles2::cmds::TexImage3D
& c
=
10006 *static_cast<const gles2::cmds::TexImage3D
*>(cmd_data
);
10007 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage3D",
10008 "widthXheight", c
.width
* c
.height
, "depth", c
.depth
);
10009 // Set as failed for now, but if it successed, this will be set to not failed.
10010 texture_state_
.tex_image_failed
= true;
10011 GLenum target
= static_cast<GLenum
>(c
.target
);
10012 GLint level
= static_cast<GLint
>(c
.level
);
10013 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
10014 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10015 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10016 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
10017 GLint border
= static_cast<GLint
>(c
.border
);
10018 GLenum format
= static_cast<GLenum
>(c
.format
);
10019 GLenum type
= static_cast<GLenum
>(c
.type
);
10020 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
10021 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
10022 uint32 pixels_size
;
10023 if (!GLES2Util::ComputeImageDataSizes(
10024 width
, height
, depth
, format
, type
, state_
.unpack_alignment
, &pixels_size
,
10026 return error::kOutOfBounds
;
10028 const void* pixels
= NULL
;
10029 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
10030 pixels
= GetSharedMemoryAs
<const void*>(
10031 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
10033 return error::kOutOfBounds
;
10037 // For testing only. Allows us to stress the ability to respond to OOM errors.
10038 if (workarounds().simulate_out_of_memory_on_large_textures
&&
10039 (width
* height
* depth
>= 4096 * 4096)) {
10040 LOCAL_SET_GL_ERROR(
10042 "glTexImage3D", "synthetic out of memory");
10043 return error::kNoError
;
10046 TextureManager::DoTexImageArguments args
= {
10047 target
, level
, internal_format
, width
, height
, depth
, border
, format
, type
,
10048 pixels
, pixels_size
, TextureManager::DoTexImageArguments::kTexImage3D
};
10049 texture_manager()->ValidateAndDoTexImage(
10050 &texture_state_
, &state_
, &framebuffer_state_
, "glTexImage3D", args
);
10052 // This may be a slow command. Exit command processing to allow for
10053 // context preemption and GPU watchdog checks.
10054 ExitCommandProcessingEarly();
10055 return error::kNoError
;
10058 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
10066 GLsizei image_size
,
10067 const void * data
) {
10068 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10070 if (!texture_ref
) {
10071 LOCAL_SET_GL_ERROR(
10072 GL_INVALID_OPERATION
,
10073 "glCompressedTexSubImage2D", "unknown texture for target");
10076 Texture
* texture
= texture_ref
->texture();
10078 GLenum internal_format
= 0;
10079 if (!texture
->GetLevelType(target
, level
, &type
, &internal_format
)) {
10080 LOCAL_SET_GL_ERROR(
10081 GL_INVALID_OPERATION
,
10082 "glCompressedTexSubImage2D", "level does not exist.");
10085 if (internal_format
!= format
) {
10086 LOCAL_SET_GL_ERROR(
10087 GL_INVALID_OPERATION
,
10088 "glCompressedTexSubImage2D", "format does not match internal format.");
10091 if (!texture
->ValidForTexture(target
, level
, xoffset
, yoffset
, 0, width
,
10092 height
, 1, type
)) {
10093 LOCAL_SET_GL_ERROR(
10094 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "bad dimensions.");
10098 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage2D",
10099 width
, height
, 1, format
, image_size
) ||
10100 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage2D",
10101 target
, level
, xoffset
, yoffset
, 0,
10102 width
, height
, 1, format
, texture
)) {
10107 // Note: There is no need to deal with texture cleared tracking here
10108 // because the validation above means you can only get here if the level
10109 // is already a matching compressed format and in that case
10110 // CompressedTexImage2D already cleared the texture.
10111 glCompressedTexSubImage2D(
10112 target
, level
, xoffset
, yoffset
, width
, height
, format
, image_size
, data
);
10114 // This may be a slow command. Exit command processing to allow for
10115 // context preemption and GPU watchdog checks.
10116 ExitCommandProcessingEarly();
10120 GLint start
, GLint range
, GLint sourceRange
,
10121 GLint
* out_start
, GLint
* out_range
) {
10128 GLint end
= start
+ range
;
10129 if (end
> sourceRange
) {
10130 range
-= end
- sourceRange
;
10132 *out_start
= start
;
10133 *out_range
= range
;
10136 void GLES2DecoderImpl::DoCopyTexImage2D(
10139 GLenum internal_format
,
10145 DCHECK(!ShouldDeferReads());
10146 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10148 if (!texture_ref
) {
10149 LOCAL_SET_GL_ERROR(
10150 GL_INVALID_OPERATION
,
10151 "glCopyTexImage2D", "unknown texture for target");
10154 Texture
* texture
= texture_ref
->texture();
10155 if (texture
->IsImmutable()) {
10156 LOCAL_SET_GL_ERROR(
10157 GL_INVALID_OPERATION
, "glCopyTexImage2D", "texture is immutable");
10160 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
10162 LOCAL_SET_GL_ERROR(
10163 GL_INVALID_VALUE
, "glCopyTexImage2D", "dimensions out of range");
10166 if (!texture_manager()->ValidateFormatAndTypeCombination(
10167 state_
.GetErrorState(), "glCopyTexImage2D", internal_format
,
10168 GL_UNSIGNED_BYTE
)) {
10172 // Check we have compatible formats.
10173 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
10174 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
10175 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(internal_format
);
10177 if ((channels_needed
& channels_exist
) != channels_needed
) {
10178 LOCAL_SET_GL_ERROR(
10179 GL_INVALID_OPERATION
, "glCopyTexImage2D", "incompatible format");
10183 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
10184 LOCAL_SET_GL_ERROR(
10185 GL_INVALID_OPERATION
,
10186 "glCopyTexImage2D", "can not be used with depth or stencil textures");
10190 uint32 estimated_size
= 0;
10191 if (!GLES2Util::ComputeImageDataSizes(
10192 width
, height
, 1, internal_format
, GL_UNSIGNED_BYTE
,
10193 state_
.unpack_alignment
, &estimated_size
, NULL
, NULL
)) {
10194 LOCAL_SET_GL_ERROR(
10195 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too large");
10199 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
10200 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "out of memory");
10204 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexImage2D")) {
10208 if (FormsTextureCopyingFeedbackLoop(texture_ref
, level
)) {
10209 LOCAL_SET_GL_ERROR(
10210 GL_INVALID_OPERATION
,
10211 "glCopyTexImage2D", "source and destination textures are the same");
10215 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
10219 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
10220 ScopedResolvedFrameBufferBinder
binder(this, false, true);
10221 gfx::Size size
= GetBoundReadFrameBufferSize();
10223 if (texture
->IsAttachedToFramebuffer()) {
10224 framebuffer_state_
.clear_state_dirty
= true;
10227 // Clip to size to source dimensions
10230 GLint copyWidth
= 0;
10231 GLint copyHeight
= 0;
10232 Clip(x
, width
, size
.width(), ©X
, ©Width
);
10233 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
10237 copyWidth
!= width
||
10238 copyHeight
!= height
) {
10239 // some part was clipped so clear the rect.
10240 uint32 pixels_size
= 0;
10241 if (!GLES2Util::ComputeImageDataSizes(
10242 width
, height
, 1, internal_format
, GL_UNSIGNED_BYTE
,
10243 state_
.unpack_alignment
, &pixels_size
, NULL
, NULL
)) {
10244 LOCAL_SET_GL_ERROR(
10245 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too big");
10248 scoped_ptr
<char[]> zero(new char[pixels_size
]);
10249 memset(zero
.get(), 0, pixels_size
);
10250 ScopedModifyPixels
modify(texture_ref
);
10251 glTexImage2D(target
, level
, internal_format
, width
, height
, border
,
10252 internal_format
, GL_UNSIGNED_BYTE
, zero
.get());
10253 if (copyHeight
> 0 && copyWidth
> 0) {
10254 GLint dx
= copyX
- x
;
10255 GLint dy
= copyY
- y
;
10258 glCopyTexSubImage2D(target
, level
,
10259 destX
, destY
, copyX
, copyY
,
10260 copyWidth
, copyHeight
);
10263 ScopedModifyPixels
modify(texture_ref
);
10264 glCopyTexImage2D(target
, level
, internal_format
,
10265 copyX
, copyY
, copyWidth
, copyHeight
, border
);
10267 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
10268 if (error
== GL_NO_ERROR
) {
10269 texture_manager()->SetLevelInfo(texture_ref
, target
, level
, internal_format
,
10270 width
, height
, 1, border
, internal_format
,
10271 GL_UNSIGNED_BYTE
, gfx::Rect(width
, height
));
10274 // This may be a slow command. Exit command processing to allow for
10275 // context preemption and GPU watchdog checks.
10276 ExitCommandProcessingEarly();
10279 void GLES2DecoderImpl::DoCopyTexSubImage2D(
10288 DCHECK(!ShouldDeferReads());
10289 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10291 if (!texture_ref
) {
10292 LOCAL_SET_GL_ERROR(
10293 GL_INVALID_OPERATION
,
10294 "glCopyTexSubImage2D", "unknown texture for target");
10297 Texture
* texture
= texture_ref
->texture();
10300 if (!texture
->GetLevelType(target
, level
, &type
, &format
) ||
10301 !texture
->ValidForTexture(
10302 target
, level
, xoffset
, yoffset
, 0, width
, height
, 1, type
)) {
10303 LOCAL_SET_GL_ERROR(
10304 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "bad dimensions.");
10307 if (async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
10308 LOCAL_SET_GL_ERROR(
10309 GL_INVALID_OPERATION
,
10310 "glCopyTexSubImage2D", "async upload pending for texture");
10314 // Check we have compatible formats.
10315 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
10316 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
10317 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(format
);
10319 if (!channels_needed
||
10320 (channels_needed
& channels_exist
) != channels_needed
) {
10321 LOCAL_SET_GL_ERROR(
10322 GL_INVALID_OPERATION
, "glCopyTexSubImage2D", "incompatible format");
10326 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
10327 LOCAL_SET_GL_ERROR(
10328 GL_INVALID_OPERATION
,
10329 "glCopySubImage2D", "can not be used with depth or stencil textures");
10333 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexSubImage2D")) {
10337 if (FormsTextureCopyingFeedbackLoop(texture_ref
, level
)) {
10338 LOCAL_SET_GL_ERROR(
10339 GL_INVALID_OPERATION
,
10340 "glCopyTexSubImage2D", "source and destination textures are the same");
10344 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
10348 ScopedResolvedFrameBufferBinder
binder(this, false, true);
10349 gfx::Size size
= GetBoundReadFrameBufferSize();
10352 GLint copyWidth
= 0;
10353 GLint copyHeight
= 0;
10354 Clip(x
, width
, size
.width(), ©X
, ©Width
);
10355 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
10357 if (xoffset
!= 0 || yoffset
!= 0 || width
!= size
.width() ||
10358 height
!= size
.height()) {
10359 gfx::Rect cleared_rect
;
10360 if (CombineAdjacentRects(texture
->GetLevelClearedRect(target
, level
),
10361 gfx::Rect(xoffset
, yoffset
, width
, height
),
10363 DCHECK_GE(cleared_rect
.size().GetArea(),
10364 texture
->GetLevelClearedRect(target
, level
).size().GetArea());
10365 texture_manager()->SetLevelClearedRect(texture_ref
, target
, level
,
10368 // Otherwise clear part of texture level that is not already cleared.
10369 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
,
10371 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D",
10372 "dimensions too big");
10377 // Write all pixels in below.
10378 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
10383 copyWidth
!= width
||
10384 copyHeight
!= height
) {
10385 // some part was clipped so clear the sub rect.
10386 uint32 pixels_size
= 0;
10387 if (!GLES2Util::ComputeImageDataSizes(
10388 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
10390 LOCAL_SET_GL_ERROR(
10391 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "dimensions too large");
10394 scoped_ptr
<char[]> zero(new char[pixels_size
]);
10395 memset(zero
.get(), 0, pixels_size
);
10396 ScopedModifyPixels
modify(texture_ref
);
10398 target
, level
, xoffset
, yoffset
, width
, height
,
10399 format
, type
, zero
.get());
10402 if (copyHeight
> 0 && copyWidth
> 0) {
10403 GLint dx
= copyX
- x
;
10404 GLint dy
= copyY
- y
;
10405 GLint destX
= xoffset
+ dx
;
10406 GLint destY
= yoffset
+ dy
;
10407 ScopedModifyPixels
modify(texture_ref
);
10408 glCopyTexSubImage2D(target
, level
,
10409 destX
, destY
, copyX
, copyY
,
10410 copyWidth
, copyHeight
);
10413 // This may be a slow command. Exit command processing to allow for
10414 // context preemption and GPU watchdog checks.
10415 ExitCommandProcessingEarly();
10418 bool GLES2DecoderImpl::ValidateTexSubImage2D(
10419 error::Error
* error
,
10420 const char* function_name
,
10429 const void * data
) {
10430 (*error
) = error::kNoError
;
10431 if (!validators_
->texture_target
.IsValid(target
)) {
10432 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
10436 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "width < 0");
10440 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "height < 0");
10443 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10445 if (!texture_ref
) {
10446 LOCAL_SET_GL_ERROR(
10447 GL_INVALID_OPERATION
,
10448 function_name
, "unknown texture for target");
10451 Texture
* texture
= texture_ref
->texture();
10452 GLenum current_type
= 0;
10453 GLenum internal_format
= 0;
10454 if (!texture
->GetLevelType(target
, level
, ¤t_type
, &internal_format
)) {
10455 LOCAL_SET_GL_ERROR(
10456 GL_INVALID_OPERATION
, function_name
, "level does not exist.");
10459 if (!texture_manager()->ValidateTextureParameters(state_
.GetErrorState(),
10460 function_name
, format
, type
, internal_format
, level
)) {
10463 if (type
!= current_type
) {
10464 LOCAL_SET_GL_ERROR(
10465 GL_INVALID_OPERATION
,
10466 function_name
, "type does not match type of texture.");
10469 if (async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
10470 LOCAL_SET_GL_ERROR(
10471 GL_INVALID_OPERATION
,
10472 function_name
, "async upload pending for texture");
10475 if (!texture
->ValidForTexture(
10476 target
, level
, xoffset
, yoffset
, 0, width
, height
, 1, type
)) {
10477 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "bad dimensions.");
10480 if ((GLES2Util::GetChannelsForFormat(format
) &
10481 (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0
10482 && !feature_info_
->IsES3Enabled()) {
10483 LOCAL_SET_GL_ERROR(
10484 GL_INVALID_OPERATION
,
10485 function_name
, "can not supply data for depth or stencil textures");
10488 if (data
== NULL
) {
10489 (*error
) = error::kOutOfBounds
;
10495 error::Error
GLES2DecoderImpl::DoTexSubImage2D(
10504 const void * data
) {
10505 error::Error error
= error::kNoError
;
10506 if (!ValidateTexSubImage2D(&error
, "glTexSubImage2D", target
, level
,
10507 xoffset
, yoffset
, width
, height
, format
, type
, data
)) {
10510 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10512 Texture
* texture
= texture_ref
->texture();
10513 GLsizei tex_width
= 0;
10514 GLsizei tex_height
= 0;
10515 bool ok
= texture
->GetLevelSize(
10516 target
, level
, &tex_width
, &tex_height
, nullptr);
10518 if (xoffset
!= 0 || yoffset
!= 0 ||
10519 width
!= tex_width
|| height
!= tex_height
) {
10520 gfx::Rect cleared_rect
;
10521 if (CombineAdjacentRects(texture
->GetLevelClearedRect(target
, level
),
10522 gfx::Rect(xoffset
, yoffset
, width
, height
),
10524 DCHECK_GE(cleared_rect
.size().GetArea(),
10525 texture
->GetLevelClearedRect(target
, level
).size().GetArea());
10526 texture_manager()->SetLevelClearedRect(texture_ref
, target
, level
,
10529 // Otherwise clear part of texture level that is not already cleared.
10530 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
,
10532 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glTexSubImage2D",
10533 "dimensions too big");
10534 return error::kNoError
;
10537 ScopedTextureUploadTimer
timer(&texture_state_
);
10539 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
10540 return error::kNoError
;
10543 if (!texture_state_
.texsubimage_faster_than_teximage
&&
10544 !texture
->IsImmutable() &&
10545 !texture
->HasImages()) {
10546 ScopedTextureUploadTimer
timer(&texture_state_
);
10547 GLenum internal_format
;
10549 texture
->GetLevelType(target
, level
, &tex_type
, &internal_format
);
10550 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
10553 target
, level
, internal_format
, width
, height
, 0, format
, type
, data
);
10555 ScopedTextureUploadTimer
timer(&texture_state_
);
10557 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
10559 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
10561 // This may be a slow command. Exit command processing to allow for
10562 // context preemption and GPU watchdog checks.
10563 ExitCommandProcessingEarly();
10564 return error::kNoError
;
10567 error::Error
GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size
,
10568 const void* cmd_data
) {
10569 const gles2::cmds::TexSubImage2D
& c
=
10570 *static_cast<const gles2::cmds::TexSubImage2D
*>(cmd_data
);
10571 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
10572 "width", c
.width
, "height", c
.height
);
10573 GLboolean internal
= static_cast<GLboolean
>(c
.internal
);
10574 if (internal
== GL_TRUE
&& texture_state_
.tex_image_failed
)
10575 return error::kNoError
;
10577 GLenum target
= static_cast<GLenum
>(c
.target
);
10578 GLint level
= static_cast<GLint
>(c
.level
);
10579 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
10580 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
10581 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10582 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10583 GLenum format
= static_cast<GLenum
>(c
.format
);
10584 GLenum type
= static_cast<GLenum
>(c
.type
);
10586 if (!GLES2Util::ComputeImageDataSizes(
10587 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &data_size
,
10589 return error::kOutOfBounds
;
10591 const void* pixels
= GetSharedMemoryAs
<const void*>(
10592 c
.pixels_shm_id
, c
.pixels_shm_offset
, data_size
);
10593 return DoTexSubImage2D(
10594 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
);
10597 error::Error
GLES2DecoderImpl::DoTexSubImage3D(
10608 const void * data
) {
10609 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10611 if (!texture_ref
) {
10612 LOCAL_SET_GL_ERROR(
10613 GL_INVALID_ENUM
, "glTexSubImage3D", "invalid target");
10616 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexSubImage3D");
10617 ScopedTextureUploadTimer
timer(&texture_state_
);
10618 glTexSubImage3D(target
, level
, xoffset
, yoffset
, zoffset
, width
, height
,
10619 depth
, format
, type
, data
);
10620 GLenum error
= LOCAL_PEEK_GL_ERROR("glTexSubImage3D");
10621 if (error
== GL_NO_ERROR
) {
10622 // TODO(zmo): This is not 100% correct because only part of the level
10623 // image is cleared.
10624 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
10627 // This may be a slow command. Exit command processing to allow for
10628 // context preemption and GPU watchdog checks.
10629 ExitCommandProcessingEarly();
10630 return error::kNoError
;
10633 error::Error
GLES2DecoderImpl::HandleTexSubImage3D(uint32 immediate_data_size
,
10634 const void* cmd_data
) {
10635 if (!unsafe_es3_apis_enabled())
10636 return error::kUnknownCommand
;
10638 const gles2::cmds::TexSubImage3D
& c
=
10639 *static_cast<const gles2::cmds::TexSubImage3D
*>(cmd_data
);
10640 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage3D",
10641 "widthXheight", c
.width
* c
.height
, "depth", c
.depth
);
10642 GLboolean internal
= static_cast<GLboolean
>(c
.internal
);
10643 if (internal
== GL_TRUE
&& texture_state_
.tex_image_failed
)
10644 return error::kNoError
;
10646 GLenum target
= static_cast<GLenum
>(c
.target
);
10647 GLint level
= static_cast<GLint
>(c
.level
);
10648 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
10649 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
10650 GLint zoffset
= static_cast<GLint
>(c
.zoffset
);
10651 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10652 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10653 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
10654 GLenum format
= static_cast<GLenum
>(c
.format
);
10655 GLenum type
= static_cast<GLenum
>(c
.type
);
10657 if (!GLES2Util::ComputeImageDataSizes(
10658 width
, height
, depth
, format
, type
, state_
.unpack_alignment
, &data_size
,
10660 return error::kOutOfBounds
;
10662 const void* pixels
= GetSharedMemoryAs
<const void*>(
10663 c
.pixels_shm_id
, c
.pixels_shm_offset
, data_size
);
10664 return DoTexSubImage3D(target
, level
, xoffset
, yoffset
, zoffset
, width
,
10665 height
, depth
, format
, type
, pixels
);
10668 error::Error
GLES2DecoderImpl::HandleGetVertexAttribPointerv(
10669 uint32 immediate_data_size
,
10670 const void* cmd_data
) {
10671 const gles2::cmds::GetVertexAttribPointerv
& c
=
10672 *static_cast<const gles2::cmds::GetVertexAttribPointerv
*>(cmd_data
);
10673 GLuint index
= static_cast<GLuint
>(c
.index
);
10674 GLenum pname
= static_cast<GLenum
>(c
.pname
);
10675 typedef cmds::GetVertexAttribPointerv::Result Result
;
10676 Result
* result
= GetSharedMemoryAs
<Result
*>(
10677 c
.pointer_shm_id
, c
.pointer_shm_offset
, Result::ComputeSize(1));
10679 return error::kOutOfBounds
;
10681 // Check that the client initialized the result.
10682 if (result
->size
!= 0) {
10683 return error::kInvalidArguments
;
10685 if (!validators_
->vertex_pointer
.IsValid(pname
)) {
10686 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10687 "glGetVertexAttribPointerv", pname
, "pname");
10688 return error::kNoError
;
10690 if (index
>= group_
->max_vertex_attribs()) {
10691 LOCAL_SET_GL_ERROR(
10692 GL_INVALID_VALUE
, "glGetVertexAttribPointerv", "index out of range.");
10693 return error::kNoError
;
10695 result
->SetNumResults(1);
10696 *result
->GetData() =
10697 state_
.vertex_attrib_manager
->GetVertexAttrib(index
)->offset();
10698 return error::kNoError
;
10702 bool GLES2DecoderImpl::GetUniformSetup(GLuint program_id
,
10703 GLint fake_location
,
10706 error::Error
* error
,
10707 GLint
* real_location
,
10708 GLuint
* service_id
,
10709 SizedResult
<T
>** result_pointer
,
10710 GLenum
* result_type
,
10711 GLsizei
* result_size
) {
10713 DCHECK(service_id
);
10714 DCHECK(result_pointer
);
10715 DCHECK(result_type
);
10716 DCHECK(result_size
);
10717 DCHECK(real_location
);
10718 *error
= error::kNoError
;
10719 // Make sure we have enough room for the result on failure.
10720 SizedResult
<T
>* result
;
10721 result
= GetSharedMemoryAs
<SizedResult
<T
>*>(
10722 shm_id
, shm_offset
, SizedResult
<T
>::ComputeSize(0));
10724 *error
= error::kOutOfBounds
;
10727 *result_pointer
= result
;
10728 // Set the result size to 0 so the client does not have to check for success.
10729 result
->SetNumResults(0);
10730 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetUniform");
10734 if (!program
->IsValid()) {
10735 // Program was not linked successfully. (ie, glLinkProgram)
10736 LOCAL_SET_GL_ERROR(
10737 GL_INVALID_OPERATION
, "glGetUniform", "program not linked");
10740 *service_id
= program
->service_id();
10741 GLint array_index
= -1;
10742 const Program::UniformInfo
* uniform_info
=
10743 program
->GetUniformInfoByFakeLocation(
10744 fake_location
, real_location
, &array_index
);
10745 if (!uniform_info
) {
10746 // No such location.
10747 LOCAL_SET_GL_ERROR(
10748 GL_INVALID_OPERATION
, "glGetUniform", "unknown location");
10751 GLenum type
= uniform_info
->type
;
10752 uint32 num_elements
= GLES2Util::GetElementCountForUniformType(type
);
10753 if (num_elements
== 0) {
10754 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glGetUniform", "unknown type");
10757 result
= GetSharedMemoryAs
<SizedResult
<T
>*>(
10758 shm_id
, shm_offset
, SizedResult
<T
>::ComputeSize(num_elements
));
10760 *error
= error::kOutOfBounds
;
10763 result
->SetNumResults(num_elements
);
10764 *result_size
= num_elements
* sizeof(T
);
10765 *result_type
= type
;
10769 error::Error
GLES2DecoderImpl::HandleGetUniformiv(uint32 immediate_data_size
,
10770 const void* cmd_data
) {
10771 const gles2::cmds::GetUniformiv
& c
=
10772 *static_cast<const gles2::cmds::GetUniformiv
*>(cmd_data
);
10773 GLuint program
= c
.program
;
10774 GLint fake_location
= c
.location
;
10776 GLenum result_type
;
10777 GLsizei result_size
;
10778 GLint real_location
= -1;
10780 cmds::GetUniformiv::Result
* result
;
10781 if (GetUniformSetup
<GLint
>(program
, fake_location
, c
.params_shm_id
,
10782 c
.params_shm_offset
, &error
, &real_location
,
10783 &service_id
, &result
, &result_type
,
10786 service_id
, real_location
, result
->GetData());
10791 error::Error
GLES2DecoderImpl::HandleGetUniformuiv(uint32 immediate_data_size
,
10792 const void* cmd_data
) {
10793 if (!unsafe_es3_apis_enabled())
10794 return error::kUnknownCommand
;
10796 const gles2::cmds::GetUniformuiv
& c
=
10797 *static_cast<const gles2::cmds::GetUniformuiv
*>(cmd_data
);
10798 GLuint program
= c
.program
;
10799 GLint fake_location
= c
.location
;
10801 GLenum result_type
;
10802 GLsizei result_size
;
10803 GLint real_location
= -1;
10805 cmds::GetUniformuiv::Result
* result
;
10806 if (GetUniformSetup
<GLuint
>(program
, fake_location
, c
.params_shm_id
,
10807 c
.params_shm_offset
, &error
, &real_location
,
10808 &service_id
, &result
, &result_type
,
10811 service_id
, real_location
, result
->GetData());
10816 error::Error
GLES2DecoderImpl::HandleGetUniformfv(uint32 immediate_data_size
,
10817 const void* cmd_data
) {
10818 const gles2::cmds::GetUniformfv
& c
=
10819 *static_cast<const gles2::cmds::GetUniformfv
*>(cmd_data
);
10820 GLuint program
= c
.program
;
10821 GLint fake_location
= c
.location
;
10823 GLint real_location
= -1;
10825 cmds::GetUniformfv::Result
* result
;
10826 GLenum result_type
;
10827 GLsizei result_size
;
10828 if (GetUniformSetup
<GLfloat
>(program
, fake_location
, c
.params_shm_id
,
10829 c
.params_shm_offset
, &error
, &real_location
,
10830 &service_id
, &result
, &result_type
,
10832 if (result_type
== GL_BOOL
|| result_type
== GL_BOOL_VEC2
||
10833 result_type
== GL_BOOL_VEC3
|| result_type
== GL_BOOL_VEC4
) {
10834 GLsizei num_values
= result_size
/ sizeof(GLfloat
);
10835 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
10836 glGetUniformiv(service_id
, real_location
, temp
.get());
10837 GLfloat
* dst
= result
->GetData();
10838 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
10839 dst
[ii
] = (temp
[ii
] != 0);
10842 glGetUniformfv(service_id
, real_location
, result
->GetData());
10848 error::Error
GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
10849 uint32 immediate_data_size
,
10850 const void* cmd_data
) {
10851 const gles2::cmds::GetShaderPrecisionFormat
& c
=
10852 *static_cast<const gles2::cmds::GetShaderPrecisionFormat
*>(cmd_data
);
10853 GLenum shader_type
= static_cast<GLenum
>(c
.shadertype
);
10854 GLenum precision_type
= static_cast<GLenum
>(c
.precisiontype
);
10855 typedef cmds::GetShaderPrecisionFormat::Result Result
;
10856 Result
* result
= GetSharedMemoryAs
<Result
*>(
10857 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10859 return error::kOutOfBounds
;
10861 // Check that the client initialized the result.
10862 if (result
->success
!= 0) {
10863 return error::kInvalidArguments
;
10865 if (!validators_
->shader_type
.IsValid(shader_type
)) {
10866 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10867 "glGetShaderPrecisionFormat", shader_type
, "shader_type");
10868 return error::kNoError
;
10870 if (!validators_
->shader_precision
.IsValid(precision_type
)) {
10871 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10872 "glGetShaderPrecisionFormat", precision_type
, "precision_type");
10873 return error::kNoError
;
10876 result
->success
= 1; // true
10878 GLint range
[2] = { 0, 0 };
10879 GLint precision
= 0;
10880 GetShaderPrecisionFormatImpl(shader_type
, precision_type
, range
, &precision
);
10882 result
->min_range
= range
[0];
10883 result
->max_range
= range
[1];
10884 result
->precision
= precision
;
10886 return error::kNoError
;
10889 error::Error
GLES2DecoderImpl::HandleGetAttachedShaders(
10890 uint32 immediate_data_size
,
10891 const void* cmd_data
) {
10892 const gles2::cmds::GetAttachedShaders
& c
=
10893 *static_cast<const gles2::cmds::GetAttachedShaders
*>(cmd_data
);
10894 uint32 result_size
= c
.result_size
;
10895 GLuint program_id
= static_cast<GLuint
>(c
.program
);
10896 Program
* program
= GetProgramInfoNotShader(
10897 program_id
, "glGetAttachedShaders");
10899 return error::kNoError
;
10901 typedef cmds::GetAttachedShaders::Result Result
;
10902 uint32 max_count
= Result::ComputeMaxResults(result_size
);
10903 Result
* result
= GetSharedMemoryAs
<Result
*>(
10904 c
.result_shm_id
, c
.result_shm_offset
, Result::ComputeSize(max_count
));
10906 return error::kOutOfBounds
;
10908 // Check that the client initialized the result.
10909 if (result
->size
!= 0) {
10910 return error::kInvalidArguments
;
10913 glGetAttachedShaders(
10914 program
->service_id(), max_count
, &count
, result
->GetData());
10915 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
10916 if (!shader_manager()->GetClientId(result
->GetData()[ii
],
10917 &result
->GetData()[ii
])) {
10919 return error::kGenericError
;
10922 result
->SetNumResults(count
);
10923 return error::kNoError
;
10926 error::Error
GLES2DecoderImpl::HandleGetActiveUniform(
10927 uint32 immediate_data_size
,
10928 const void* cmd_data
) {
10929 const gles2::cmds::GetActiveUniform
& c
=
10930 *static_cast<const gles2::cmds::GetActiveUniform
*>(cmd_data
);
10931 GLuint program_id
= c
.program
;
10932 GLuint index
= c
.index
;
10933 uint32 name_bucket_id
= c
.name_bucket_id
;
10934 typedef cmds::GetActiveUniform::Result Result
;
10935 Result
* result
= GetSharedMemoryAs
<Result
*>(
10936 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10938 return error::kOutOfBounds
;
10940 // Check that the client initialized the result.
10941 if (result
->success
!= 0) {
10942 return error::kInvalidArguments
;
10944 Program
* program
= GetProgramInfoNotShader(
10945 program_id
, "glGetActiveUniform");
10947 return error::kNoError
;
10949 const Program::UniformInfo
* uniform_info
=
10950 program
->GetUniformInfo(index
);
10951 if (!uniform_info
) {
10952 LOCAL_SET_GL_ERROR(
10953 GL_INVALID_VALUE
, "glGetActiveUniform", "index out of range");
10954 return error::kNoError
;
10956 result
->success
= 1; // true.
10957 result
->size
= uniform_info
->size
;
10958 result
->type
= uniform_info
->type
;
10959 Bucket
* bucket
= CreateBucket(name_bucket_id
);
10960 bucket
->SetFromString(uniform_info
->name
.c_str());
10961 return error::kNoError
;
10964 error::Error
GLES2DecoderImpl::HandleGetActiveUniformBlockiv(
10965 uint32 immediate_data_size
, const void* cmd_data
) {
10966 if (!unsafe_es3_apis_enabled())
10967 return error::kUnknownCommand
;
10968 const gles2::cmds::GetActiveUniformBlockiv
& c
=
10969 *static_cast<const gles2::cmds::GetActiveUniformBlockiv
*>(cmd_data
);
10970 GLuint program_id
= c
.program
;
10971 GLuint index
= static_cast<GLuint
>(c
.index
);
10972 GLenum pname
= static_cast<GLenum
>(c
.pname
);
10973 Program
* program
= GetProgramInfoNotShader(
10974 program_id
, "glGetActiveUniformBlockiv");
10976 return error::kNoError
;
10978 GLuint service_id
= program
->service_id();
10979 GLint link_status
= GL_FALSE
;
10980 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
10981 if (link_status
!= GL_TRUE
) {
10982 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10983 "glGetActiveActiveUniformBlockiv", "program not linked");
10984 return error::kNoError
;
10986 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformBlockiv");
10987 GLsizei num_values
= 1;
10988 if (pname
== GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES
) {
10990 glGetActiveUniformBlockiv(
10991 service_id
, index
, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS
, &num
);
10992 GLenum error
= glGetError();
10993 if (error
!= GL_NO_ERROR
) {
10994 // Assume this will the same error if calling with pname.
10995 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformBlockiv", "");
10996 return error::kNoError
;
10998 num_values
= static_cast<GLsizei
>(num
);
11000 typedef cmds::GetActiveUniformBlockiv::Result Result
;
11001 Result
* result
= GetSharedMemoryAs
<Result
*>(
11002 c
.params_shm_id
, c
.params_shm_offset
, Result::ComputeSize(num_values
));
11003 GLint
* params
= result
? result
->GetData() : NULL
;
11004 if (params
== NULL
) {
11005 return error::kOutOfBounds
;
11007 // Check that the client initialized the result.
11008 if (result
->size
!= 0) {
11009 return error::kInvalidArguments
;
11011 glGetActiveUniformBlockiv(service_id
, index
, pname
, params
);
11012 GLenum error
= glGetError();
11013 if (error
== GL_NO_ERROR
) {
11014 result
->SetNumResults(num_values
);
11016 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformBlockiv", "");
11018 return error::kNoError
;
11021 error::Error
GLES2DecoderImpl::HandleGetActiveUniformBlockName(
11022 uint32 immediate_data_size
, const void* cmd_data
) {
11023 if (!unsafe_es3_apis_enabled())
11024 return error::kUnknownCommand
;
11025 const gles2::cmds::GetActiveUniformBlockName
& c
=
11026 *static_cast<const gles2::cmds::GetActiveUniformBlockName
*>(cmd_data
);
11027 GLuint program_id
= c
.program
;
11028 GLuint index
= c
.index
;
11029 uint32 name_bucket_id
= c
.name_bucket_id
;
11030 typedef cmds::GetActiveUniformBlockName::Result Result
;
11031 Result
* result
= GetSharedMemoryAs
<Result
*>(
11032 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
11034 return error::kOutOfBounds
;
11036 // Check that the client initialized the result.
11037 if (*result
!= 0) {
11038 return error::kInvalidArguments
;
11040 Program
* program
= GetProgramInfoNotShader(
11041 program_id
, "glGetActiveUniformBlockName");
11043 return error::kNoError
;
11045 GLuint service_id
= program
->service_id();
11046 GLint link_status
= GL_FALSE
;
11047 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
11048 if (link_status
!= GL_TRUE
) {
11049 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11050 "glGetActiveActiveUniformBlockName", "program not linked");
11051 return error::kNoError
;
11053 GLint max_length
= 0;
11055 service_id
, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH
, &max_length
);
11056 // Increase one so &buffer[0] is always valid.
11057 GLsizei buf_size
= static_cast<GLsizei
>(max_length
) + 1;
11058 std::vector
<char> buffer(buf_size
);
11059 GLsizei length
= 0;
11060 glGetActiveUniformBlockName(
11061 service_id
, index
, buf_size
, &length
, &buffer
[0]);
11064 return error::kNoError
;
11067 Bucket
* bucket
= CreateBucket(name_bucket_id
);
11068 DCHECK_GT(buf_size
, length
);
11069 DCHECK_EQ(0, buffer
[length
]);
11070 bucket
->SetFromString(&buffer
[0]);
11071 return error::kNoError
;
11074 error::Error
GLES2DecoderImpl::HandleGetActiveUniformsiv(
11075 uint32 immediate_data_size
, const void* cmd_data
) {
11076 if (!unsafe_es3_apis_enabled())
11077 return error::kUnknownCommand
;
11078 const gles2::cmds::GetActiveUniformsiv
& c
=
11079 *static_cast<const gles2::cmds::GetActiveUniformsiv
*>(cmd_data
);
11080 GLuint program_id
= c
.program
;
11081 GLenum pname
= static_cast<GLenum
>(c
.pname
);
11082 Bucket
* bucket
= GetBucket(c
.indices_bucket_id
);
11084 return error::kInvalidArguments
;
11086 GLsizei count
= static_cast<GLsizei
>(bucket
->size() / sizeof(GLuint
));
11087 const GLuint
* indices
= bucket
->GetDataAs
<const GLuint
*>(0, bucket
->size());
11088 typedef cmds::GetActiveUniformsiv::Result Result
;
11089 Result
* result
= GetSharedMemoryAs
<Result
*>(
11090 c
.params_shm_id
, c
.params_shm_offset
, Result::ComputeSize(count
));
11091 GLint
* params
= result
? result
->GetData() : NULL
;
11092 if (params
== NULL
) {
11093 return error::kOutOfBounds
;
11095 // Check that the client initialized the result.
11096 if (result
->size
!= 0) {
11097 return error::kInvalidArguments
;
11099 Program
* program
= GetProgramInfoNotShader(
11100 program_id
, "glGetActiveUniformsiv");
11102 return error::kNoError
;
11104 GLuint service_id
= program
->service_id();
11105 GLint link_status
= GL_FALSE
;
11106 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
11107 if (link_status
!= GL_TRUE
) {
11108 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11109 "glGetActiveUniformsiv", "program not linked");
11110 return error::kNoError
;
11112 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformsiv");
11113 glGetActiveUniformsiv(service_id
, count
, indices
, pname
, params
);
11114 GLenum error
= glGetError();
11115 if (error
== GL_NO_ERROR
) {
11116 result
->SetNumResults(count
);
11118 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformsiv", "");
11120 return error::kNoError
;
11123 error::Error
GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size
,
11124 const void* cmd_data
) {
11125 const gles2::cmds::GetActiveAttrib
& c
=
11126 *static_cast<const gles2::cmds::GetActiveAttrib
*>(cmd_data
);
11127 GLuint program_id
= c
.program
;
11128 GLuint index
= c
.index
;
11129 uint32 name_bucket_id
= c
.name_bucket_id
;
11130 typedef cmds::GetActiveAttrib::Result Result
;
11131 Result
* result
= GetSharedMemoryAs
<Result
*>(
11132 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
11134 return error::kOutOfBounds
;
11136 // Check that the client initialized the result.
11137 if (result
->success
!= 0) {
11138 return error::kInvalidArguments
;
11140 Program
* program
= GetProgramInfoNotShader(
11141 program_id
, "glGetActiveAttrib");
11143 return error::kNoError
;
11145 const Program::VertexAttrib
* attrib_info
=
11146 program
->GetAttribInfo(index
);
11147 if (!attrib_info
) {
11148 LOCAL_SET_GL_ERROR(
11149 GL_INVALID_VALUE
, "glGetActiveAttrib", "index out of range");
11150 return error::kNoError
;
11152 result
->success
= 1; // true.
11153 result
->size
= attrib_info
->size
;
11154 result
->type
= attrib_info
->type
;
11155 Bucket
* bucket
= CreateBucket(name_bucket_id
);
11156 bucket
->SetFromString(attrib_info
->name
.c_str());
11157 return error::kNoError
;
11160 error::Error
GLES2DecoderImpl::HandleShaderBinary(uint32 immediate_data_size
,
11161 const void* cmd_data
) {
11162 #if 1 // No binary shader support.
11163 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glShaderBinary", "not supported");
11164 return error::kNoError
;
11166 GLsizei n
= static_cast<GLsizei
>(c
.n
);
11168 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "n < 0");
11169 return error::kNoError
;
11171 GLsizei length
= static_cast<GLsizei
>(c
.length
);
11173 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "length < 0");
11174 return error::kNoError
;
11177 if (!SafeMultiplyUint32(n
, sizeof(GLuint
), &data_size
)) {
11178 return error::kOutOfBounds
;
11180 const GLuint
* shaders
= GetSharedMemoryAs
<const GLuint
*>(
11181 c
.shaders_shm_id
, c
.shaders_shm_offset
, data_size
);
11182 GLenum binaryformat
= static_cast<GLenum
>(c
.binaryformat
);
11183 const void* binary
= GetSharedMemoryAs
<const void*>(
11184 c
.binary_shm_id
, c
.binary_shm_offset
, length
);
11185 if (shaders
== NULL
|| binary
== NULL
) {
11186 return error::kOutOfBounds
;
11188 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
11189 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11190 Shader
* shader
= GetShader(shaders
[ii
]);
11192 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "unknown shader");
11193 return error::kNoError
;
11195 service_ids
[ii
] = shader
->service_id();
11197 // TODO(gman): call glShaderBinary
11198 return error::kNoError
;
11202 void GLES2DecoderImpl::DoSwapBuffers() {
11203 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
11205 int this_frame_number
= frame_number_
++;
11206 // TRACE_EVENT for gpu tests:
11207 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
11208 TRACE_EVENT_SCOPE_THREAD
,
11209 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
11210 "width", (is_offscreen
? offscreen_size_
.width() :
11211 surface_
->GetSize().width()));
11212 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
11213 "offscreen", is_offscreen
,
11214 "frame", this_frame_number
);
11216 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
11219 ScopedGPUTrace
scoped_gpu_trace(gpu_tracer_
.get(), kTraceDecoder
,
11220 "GLES2Decoder", "SwapBuffer");
11223 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
11226 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
11227 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
11228 is_offscreen
? offscreen_size_
: surface_
->GetSize());
11231 // If offscreen then don't actually SwapBuffers to the display. Just copy
11232 // the rendered frame to another frame buffer.
11233 if (is_offscreen
) {
11234 TRACE_EVENT2("gpu", "Offscreen",
11235 "width", offscreen_size_
.width(), "height", offscreen_size_
.height());
11236 if (offscreen_size_
!= offscreen_saved_color_texture_
->size()) {
11237 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
11238 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
11240 if (workarounds().needs_offscreen_buffer_workaround
) {
11241 offscreen_saved_frame_buffer_
->Create();
11245 // Allocate the offscreen saved color texture.
11246 DCHECK(offscreen_saved_color_format_
);
11247 offscreen_saved_color_texture_
->AllocateStorage(
11248 offscreen_size_
, offscreen_saved_color_format_
, false);
11250 offscreen_saved_frame_buffer_
->AttachRenderTexture(
11251 offscreen_saved_color_texture_
.get());
11252 if (offscreen_size_
.width() != 0 && offscreen_size_
.height() != 0) {
11253 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
11254 GL_FRAMEBUFFER_COMPLETE
) {
11255 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
11256 << "because offscreen saved FBO was incomplete.";
11257 MarkContextLost(error::kUnknown
);
11258 group_
->LoseContexts(error::kUnknown
);
11262 // Clear the offscreen color texture.
11263 // TODO(piman): Is this still necessary?
11265 ScopedFrameBufferBinder
binder(this,
11266 offscreen_saved_frame_buffer_
->id());
11267 glClearColor(0, 0, 0, 0);
11268 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
11269 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
11270 glClear(GL_COLOR_BUFFER_BIT
);
11271 RestoreClearState();
11275 UpdateParentTextureInfo();
11278 if (offscreen_size_
.width() == 0 || offscreen_size_
.height() == 0)
11280 ScopedGLErrorSuppressor
suppressor(
11281 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
11283 if (IsOffscreenBufferMultisampled()) {
11284 // For multisampled buffers, resolve the frame buffer.
11285 ScopedResolvedFrameBufferBinder
binder(this, true, false);
11287 ScopedFrameBufferBinder
binder(this,
11288 offscreen_target_frame_buffer_
->id());
11290 if (offscreen_target_buffer_preserved_
) {
11291 // Copy the target frame buffer to the saved offscreen texture.
11292 offscreen_saved_color_texture_
->Copy(
11293 offscreen_saved_color_texture_
->size(),
11294 offscreen_saved_color_format_
);
11296 // Flip the textures in the parent context via the texture manager.
11297 if (!!offscreen_saved_color_texture_info_
.get())
11298 offscreen_saved_color_texture_info_
->texture()->
11299 SetServiceId(offscreen_target_color_texture_
->id());
11301 offscreen_saved_color_texture_
.swap(offscreen_target_color_texture_
);
11302 offscreen_target_frame_buffer_
->AttachRenderTexture(
11303 offscreen_target_color_texture_
.get());
11306 // Ensure the side effects of the copy are visible to the parent
11307 // context. There is no need to do this for ANGLE because it uses a
11308 // single D3D device for all contexts.
11309 if (!feature_info_
->gl_version_info().is_angle
)
11313 if (surface_
->SwapBuffers() == gfx::SwapResult::SWAP_FAILED
) {
11314 LOG(ERROR
) << "Context lost because SwapBuffers failed.";
11315 if (!CheckResetStatus()) {
11316 MarkContextLost(error::kUnknown
);
11317 group_
->LoseContexts(error::kUnknown
);
11322 // This may be a slow command. Exit command processing to allow for
11323 // context preemption and GPU watchdog checks.
11324 ExitCommandProcessingEarly();
11327 void GLES2DecoderImpl::DoSwapInterval(int interval
) {
11328 context_
->SetSwapInterval(interval
);
11331 error::Error
GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
11332 uint32 immediate_data_size
,
11333 const void* cmd_data
) {
11334 const gles2::cmds::EnableFeatureCHROMIUM
& c
=
11335 *static_cast<const gles2::cmds::EnableFeatureCHROMIUM
*>(cmd_data
);
11336 Bucket
* bucket
= GetBucket(c
.bucket_id
);
11337 if (!bucket
|| bucket
->size() == 0) {
11338 return error::kInvalidArguments
;
11340 typedef cmds::EnableFeatureCHROMIUM::Result Result
;
11341 Result
* result
= GetSharedMemoryAs
<Result
*>(
11342 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
11344 return error::kOutOfBounds
;
11346 // Check that the client initialized the result.
11347 if (*result
!= 0) {
11348 return error::kInvalidArguments
;
11350 std::string feature_str
;
11351 if (!bucket
->GetAsString(&feature_str
)) {
11352 return error::kInvalidArguments
;
11355 // TODO(gman): make this some kind of table to function pointer thingy.
11356 if (feature_str
.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
11357 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
11358 } else if (feature_str
.compare("pepper3d_support_fixed_attribs") == 0) {
11359 buffer_manager()->set_allow_fixed_attribs(true);
11360 // TODO(gman): decide how to remove the need for this const_cast.
11361 // I could make validators_ non const but that seems bad as this is the only
11362 // place it is needed. I could make some special friend class of validators
11363 // just to allow this to set them. That seems silly. I could refactor this
11364 // code to use the extension mechanism or the initialization attributes to
11365 // turn this feature on. Given that the only real point of this is to make
11366 // the conformance tests pass and given that there is lots of real work that
11367 // needs to be done it seems like refactoring for one to one of those
11368 // methods is a very low priority.
11369 const_cast<Validators
*>(validators_
)->vertex_attrib_type
.AddValue(GL_FIXED
);
11371 return error::kNoError
;
11374 *result
= 1; // true.
11375 return error::kNoError
;
11378 error::Error
GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
11379 uint32 immediate_data_size
,
11380 const void* cmd_data
) {
11381 const gles2::cmds::GetRequestableExtensionsCHROMIUM
& c
=
11382 *static_cast<const gles2::cmds::GetRequestableExtensionsCHROMIUM
*>(
11384 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
11385 scoped_refptr
<FeatureInfo
> info(new FeatureInfo());
11386 info
->Initialize(disallowed_features_
);
11387 bucket
->SetFromString(info
->extensions().c_str());
11388 return error::kNoError
;
11391 error::Error
GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
11392 uint32 immediate_data_size
,
11393 const void* cmd_data
) {
11394 const gles2::cmds::RequestExtensionCHROMIUM
& c
=
11395 *static_cast<const gles2::cmds::RequestExtensionCHROMIUM
*>(cmd_data
);
11396 Bucket
* bucket
= GetBucket(c
.bucket_id
);
11397 if (!bucket
|| bucket
->size() == 0) {
11398 return error::kInvalidArguments
;
11400 std::string feature_str
;
11401 if (!bucket
->GetAsString(&feature_str
)) {
11402 return error::kInvalidArguments
;
11405 bool desire_standard_derivatives
= false;
11406 bool desire_frag_depth
= false;
11407 bool desire_draw_buffers
= false;
11408 bool desire_shader_texture_lod
= false;
11409 if (IsWebGLContext()) {
11410 desire_standard_derivatives
=
11411 feature_str
.find("GL_OES_standard_derivatives") != std::string::npos
;
11412 desire_frag_depth
=
11413 feature_str
.find("GL_EXT_frag_depth") != std::string::npos
;
11414 desire_draw_buffers
=
11415 feature_str
.find("GL_EXT_draw_buffers") != std::string::npos
;
11416 desire_shader_texture_lod
=
11417 feature_str
.find("GL_EXT_shader_texture_lod") != std::string::npos
;
11420 if (desire_standard_derivatives
!= derivatives_explicitly_enabled_
||
11421 desire_frag_depth
!= frag_depth_explicitly_enabled_
||
11422 desire_draw_buffers
!= draw_buffers_explicitly_enabled_
||
11423 desire_shader_texture_lod
!= shader_texture_lod_explicitly_enabled_
) {
11424 derivatives_explicitly_enabled_
|= desire_standard_derivatives
;
11425 frag_depth_explicitly_enabled_
|= desire_frag_depth
;
11426 draw_buffers_explicitly_enabled_
|= desire_draw_buffers
;
11427 shader_texture_lod_explicitly_enabled_
|= desire_shader_texture_lod
;
11428 InitializeShaderTranslator();
11431 UpdateCapabilities();
11433 return error::kNoError
;
11436 error::Error
GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
11437 uint32 immediate_data_size
,
11438 const void* cmd_data
) {
11439 const gles2::cmds::GetProgramInfoCHROMIUM
& c
=
11440 *static_cast<const gles2::cmds::GetProgramInfoCHROMIUM
*>(cmd_data
);
11441 GLuint program_id
= static_cast<GLuint
>(c
.program
);
11442 uint32 bucket_id
= c
.bucket_id
;
11443 Bucket
* bucket
= CreateBucket(bucket_id
);
11444 bucket
->SetSize(sizeof(ProgramInfoHeader
)); // in case we fail.
11445 Program
* program
= NULL
;
11446 program
= GetProgram(program_id
);
11447 if (!program
|| !program
->IsValid()) {
11448 return error::kNoError
;
11450 program
->GetProgramInfo(program_manager(), bucket
);
11451 return error::kNoError
;
11454 error::Error
GLES2DecoderImpl::HandleGetUniformBlocksCHROMIUM(
11455 uint32 immediate_data_size
, const void* cmd_data
) {
11456 if (!unsafe_es3_apis_enabled())
11457 return error::kUnknownCommand
;
11458 const gles2::cmds::GetUniformBlocksCHROMIUM
& c
=
11459 *static_cast<const gles2::cmds::GetUniformBlocksCHROMIUM
*>(cmd_data
);
11460 GLuint program_id
= static_cast<GLuint
>(c
.program
);
11461 uint32 bucket_id
= c
.bucket_id
;
11462 Bucket
* bucket
= CreateBucket(bucket_id
);
11463 bucket
->SetSize(sizeof(UniformBlocksHeader
)); // in case we fail.
11464 Program
* program
= NULL
;
11465 program
= GetProgram(program_id
);
11466 if (!program
|| !program
->IsValid()) {
11467 return error::kNoError
;
11469 program
->GetUniformBlocks(bucket
);
11470 return error::kNoError
;
11473 error::Error
GLES2DecoderImpl::HandleGetUniformsES3CHROMIUM(
11474 uint32 immediate_data_size
, const void* cmd_data
) {
11475 if (!unsafe_es3_apis_enabled())
11476 return error::kUnknownCommand
;
11477 const gles2::cmds::GetUniformsES3CHROMIUM
& c
=
11478 *static_cast<const gles2::cmds::GetUniformsES3CHROMIUM
*>(cmd_data
);
11479 GLuint program_id
= static_cast<GLuint
>(c
.program
);
11480 uint32 bucket_id
= c
.bucket_id
;
11481 Bucket
* bucket
= CreateBucket(bucket_id
);
11482 bucket
->SetSize(sizeof(UniformsES3Header
)); // in case we fail.
11483 Program
* program
= NULL
;
11484 program
= GetProgram(program_id
);
11485 if (!program
|| !program
->IsValid()) {
11486 return error::kNoError
;
11488 program
->GetUniformsES3(bucket
);
11489 return error::kNoError
;
11492 error::Error
GLES2DecoderImpl::HandleGetTransformFeedbackVarying(
11493 uint32 immediate_data_size
,
11494 const void* cmd_data
) {
11495 if (!unsafe_es3_apis_enabled())
11496 return error::kUnknownCommand
;
11497 const gles2::cmds::GetTransformFeedbackVarying
& c
=
11498 *static_cast<const gles2::cmds::GetTransformFeedbackVarying
*>(cmd_data
);
11499 GLuint program_id
= c
.program
;
11500 GLuint index
= c
.index
;
11501 uint32 name_bucket_id
= c
.name_bucket_id
;
11502 typedef cmds::GetTransformFeedbackVarying::Result Result
;
11503 Result
* result
= GetSharedMemoryAs
<Result
*>(
11504 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
11506 return error::kOutOfBounds
;
11508 // Check that the client initialized the result.
11509 if (result
->success
!= 0) {
11510 return error::kInvalidArguments
;
11512 Program
* program
= GetProgramInfoNotShader(
11513 program_id
, "glGetTransformFeedbackVarying");
11515 return error::kNoError
;
11517 GLuint service_id
= program
->service_id();
11518 GLint link_status
= GL_FALSE
;
11519 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
11520 if (link_status
!= GL_TRUE
) {
11521 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11522 "glGetTransformFeedbackVarying", "program not linked");
11523 return error::kNoError
;
11525 GLint max_length
= 0;
11527 service_id
, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH
, &max_length
);
11528 max_length
= std::max(1, max_length
);
11529 std::vector
<char> buffer(max_length
);
11530 GLsizei length
= 0;
11533 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetTransformFeedbackVarying");
11534 glGetTransformFeedbackVarying(
11535 service_id
, index
, max_length
, &length
, &size
, &type
, &buffer
[0]);
11536 GLenum error
= glGetError();
11537 if (error
!= GL_NO_ERROR
) {
11538 LOCAL_SET_GL_ERROR(error
, "glGetTransformFeedbackVarying", "");
11539 return error::kNoError
;
11541 result
->success
= 1; // true.
11542 result
->size
= static_cast<int32_t>(size
);
11543 result
->type
= static_cast<uint32_t>(type
);
11544 Bucket
* bucket
= CreateBucket(name_bucket_id
);
11545 DCHECK(length
>= 0 && length
< max_length
);
11546 buffer
[length
] = '\0'; // Just to be safe.
11547 bucket
->SetFromString(&buffer
[0]);
11548 return error::kNoError
;
11551 error::Error
GLES2DecoderImpl::HandleGetTransformFeedbackVaryingsCHROMIUM(
11552 uint32 immediate_data_size
, const void* cmd_data
) {
11553 if (!unsafe_es3_apis_enabled())
11554 return error::kUnknownCommand
;
11555 const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM
& c
=
11556 *static_cast<const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM
*>(
11558 GLuint program_id
= static_cast<GLuint
>(c
.program
);
11559 uint32 bucket_id
= c
.bucket_id
;
11560 Bucket
* bucket
= CreateBucket(bucket_id
);
11561 bucket
->SetSize(sizeof(TransformFeedbackVaryingsHeader
)); // in case we fail.
11562 Program
* program
= NULL
;
11563 program
= GetProgram(program_id
);
11564 if (!program
|| !program
->IsValid()) {
11565 return error::kNoError
;
11567 program
->GetTransformFeedbackVaryings(bucket
);
11568 return error::kNoError
;
11571 error::ContextLostReason
GLES2DecoderImpl::GetContextLostReason() {
11572 return context_lost_reason_
;
11575 error::ContextLostReason
GLES2DecoderImpl::GetContextLostReasonFromResetStatus(
11576 GLenum reset_status
) const {
11577 switch (reset_status
) {
11579 // TODO(kbr): improve the precision of the error code in this case.
11580 // Consider delegating to context for error code if MakeCurrent fails.
11581 return error::kUnknown
;
11582 case GL_GUILTY_CONTEXT_RESET_ARB
:
11583 return error::kGuilty
;
11584 case GL_INNOCENT_CONTEXT_RESET_ARB
:
11585 return error::kInnocent
;
11586 case GL_UNKNOWN_CONTEXT_RESET_ARB
:
11587 return error::kUnknown
;
11591 return error::kUnknown
;
11594 bool GLES2DecoderImpl::WasContextLost() const {
11595 return context_was_lost_
;
11598 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() const {
11599 return WasContextLost() && reset_by_robustness_extension_
;
11602 void GLES2DecoderImpl::MarkContextLost(error::ContextLostReason reason
) {
11603 // Only lose the context once.
11604 if (WasContextLost())
11607 // Don't make GL calls in here, the context might not be current.
11608 context_lost_reason_
= reason
;
11609 current_decoder_error_
= error::kLostContext
;
11610 context_was_lost_
= true;
11613 bool GLES2DecoderImpl::CheckResetStatus() {
11614 DCHECK(!WasContextLost());
11615 DCHECK(context_
->IsCurrent(NULL
));
11617 if (IsRobustnessSupported()) {
11618 // If the reason for the call was a GL error, we can try to determine the
11619 // reset status more accurately.
11620 GLenum driver_status
= glGetGraphicsResetStatusARB();
11621 if (driver_status
== GL_NO_ERROR
)
11624 LOG(ERROR
) << (surface_
->IsOffscreen() ? "Offscreen" : "Onscreen")
11625 << " context lost via ARB/EXT_robustness. Reset status = "
11626 << GLES2Util::GetStringEnum(driver_status
);
11628 // Don't pretend we know which client was responsible.
11629 if (workarounds().use_virtualized_gl_contexts
)
11630 driver_status
= GL_UNKNOWN_CONTEXT_RESET_ARB
;
11632 switch (driver_status
) {
11633 case GL_GUILTY_CONTEXT_RESET_ARB
:
11634 MarkContextLost(error::kGuilty
);
11636 case GL_INNOCENT_CONTEXT_RESET_ARB
:
11637 MarkContextLost(error::kInnocent
);
11639 case GL_UNKNOWN_CONTEXT_RESET_ARB
:
11640 MarkContextLost(error::kUnknown
);
11646 reset_by_robustness_extension_
= true;
11652 error::Error
GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
11653 uint32 immediate_data_size
,
11654 const void* cmd_data
) {
11655 return error::kUnknownCommand
;
11658 error::Error
GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
11659 uint32 immediate_data_size
,
11660 const void* cmd_data
) {
11661 const gles2::cmds::WaitSyncPointCHROMIUM
& c
=
11662 *static_cast<const gles2::cmds::WaitSyncPointCHROMIUM
*>(cmd_data
);
11663 uint32 sync_point
= c
.sync_point
;
11664 if (wait_sync_point_callback_
.is_null())
11665 return error::kNoError
;
11667 return wait_sync_point_callback_
.Run(sync_point
) ?
11668 error::kNoError
: error::kDeferCommandUntilLater
;
11671 error::Error
GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
11672 uint32 immediate_data_size
,
11673 const void* cmd_data
) {
11674 if (surface_
->DeferDraws())
11675 return error::kDeferCommandUntilLater
;
11676 if (!surface_
->SetBackbufferAllocation(false))
11677 return error::kLostContext
;
11678 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
11679 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
11680 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
11681 return error::kNoError
;
11684 bool GLES2DecoderImpl::GenQueriesEXTHelper(
11685 GLsizei n
, const GLuint
* client_ids
) {
11686 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11687 if (query_manager_
->GetQuery(client_ids
[ii
])) {
11691 query_manager_
->GenQueries(n
, client_ids
);
11695 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
11696 GLsizei n
, const GLuint
* client_ids
) {
11697 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11698 query_manager_
->RemoveQuery(client_ids
[ii
]);
11702 bool GLES2DecoderImpl::ProcessPendingQueries(bool did_finish
) {
11703 if (query_manager_
.get() == NULL
) {
11706 if (!query_manager_
->ProcessPendingQueries(did_finish
)) {
11707 current_decoder_error_
= error::kOutOfBounds
;
11709 return query_manager_
->HavePendingQueries();
11712 // Note that if there are no pending readpixels right now,
11713 // this function will call the callback immediately.
11714 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback
) {
11715 if (features().use_async_readpixels
&& !pending_readpixel_fences_
.empty()) {
11716 pending_readpixel_fences_
.back()->callbacks
.push_back(callback
);
11722 void GLES2DecoderImpl::ProcessPendingReadPixels(bool did_finish
) {
11723 // Note: |did_finish| guarantees that the GPU has passed the fence but
11724 // we cannot assume that GLFence::HasCompleted() will return true yet as
11725 // that's not guaranteed by all GLFence implementations.
11726 while (!pending_readpixel_fences_
.empty() &&
11728 pending_readpixel_fences_
.front()->fence
->HasCompleted())) {
11729 std::vector
<base::Closure
> callbacks
=
11730 pending_readpixel_fences_
.front()->callbacks
;
11731 pending_readpixel_fences_
.pop();
11732 for (size_t i
= 0; i
< callbacks
.size(); i
++) {
11733 callbacks
[i
].Run();
11738 bool GLES2DecoderImpl::HasMoreIdleWork() {
11739 return !pending_readpixel_fences_
.empty() ||
11740 async_pixel_transfer_manager_
->NeedsProcessMorePendingTransfers() ||
11741 gpu_tracer_
->HasTracesToProcess();
11744 void GLES2DecoderImpl::PerformIdleWork() {
11745 gpu_tracer_
->ProcessTraces();
11746 ProcessPendingReadPixels(false);
11747 if (!async_pixel_transfer_manager_
->NeedsProcessMorePendingTransfers())
11749 async_pixel_transfer_manager_
->ProcessMorePendingTransfers();
11750 ProcessFinishedAsyncTransfers();
11753 error::Error
GLES2DecoderImpl::HandleBeginQueryEXT(uint32 immediate_data_size
,
11754 const void* cmd_data
) {
11755 const gles2::cmds::BeginQueryEXT
& c
=
11756 *static_cast<const gles2::cmds::BeginQueryEXT
*>(cmd_data
);
11757 GLenum target
= static_cast<GLenum
>(c
.target
);
11758 GLuint client_id
= static_cast<GLuint
>(c
.id
);
11759 int32 sync_shm_id
= static_cast<int32
>(c
.sync_data_shm_id
);
11760 uint32 sync_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
11763 case GL_COMMANDS_ISSUED_CHROMIUM
:
11764 case GL_LATENCY_QUERY_CHROMIUM
:
11765 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
:
11766 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM
:
11767 case GL_GET_ERROR_QUERY_CHROMIUM
:
11769 case GL_COMMANDS_COMPLETED_CHROMIUM
:
11770 if (!features().chromium_sync_query
) {
11771 LOCAL_SET_GL_ERROR(
11772 GL_INVALID_OPERATION
, "glBeginQueryEXT",
11773 "not enabled for commands completed queries");
11774 return error::kNoError
;
11777 case GL_SAMPLES_PASSED
:
11778 case GL_ANY_SAMPLES_PASSED
:
11779 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE
:
11780 if (!features().occlusion_query_boolean
) {
11781 LOCAL_SET_GL_ERROR(
11782 GL_INVALID_OPERATION
, "glBeginQueryEXT",
11783 "not enabled for occlusion queries");
11784 return error::kNoError
;
11787 case GL_TIME_ELAPSED
:
11788 if (!query_manager_
->GPUTimingAvailable()) {
11789 LOCAL_SET_GL_ERROR(
11790 GL_INVALID_OPERATION
, "glBeginQueryEXT",
11791 "not enabled for timing queries");
11792 return error::kNoError
;
11796 LOCAL_SET_GL_ERROR(
11797 GL_INVALID_ENUM
, "glBeginQueryEXT",
11798 "unknown query target");
11799 return error::kNoError
;
11802 if (query_manager_
->GetActiveQuery(target
)) {
11803 LOCAL_SET_GL_ERROR(
11804 GL_INVALID_OPERATION
, "glBeginQueryEXT", "query already in progress");
11805 return error::kNoError
;
11808 if (client_id
== 0) {
11809 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glBeginQueryEXT", "id is 0");
11810 return error::kNoError
;
11813 QueryManager::Query
* query
= query_manager_
->GetQuery(client_id
);
11815 if (!query_manager_
->IsValidQuery(client_id
)) {
11816 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11818 "id not made by glGenQueriesEXT");
11819 return error::kNoError
;
11821 query
= query_manager_
->CreateQuery(
11822 target
, client_id
, sync_shm_id
, sync_shm_offset
);
11825 if (query
->target() != target
) {
11826 LOCAL_SET_GL_ERROR(
11827 GL_INVALID_OPERATION
, "glBeginQueryEXT", "target does not match");
11828 return error::kNoError
;
11829 } else if (query
->shm_id() != sync_shm_id
||
11830 query
->shm_offset() != sync_shm_offset
) {
11831 DLOG(ERROR
) << "Shared memory used by query not the same as before";
11832 return error::kInvalidArguments
;
11835 if (!query_manager_
->BeginQuery(query
)) {
11836 return error::kOutOfBounds
;
11839 return error::kNoError
;
11842 error::Error
GLES2DecoderImpl::HandleEndQueryEXT(uint32 immediate_data_size
,
11843 const void* cmd_data
) {
11844 const gles2::cmds::EndQueryEXT
& c
=
11845 *static_cast<const gles2::cmds::EndQueryEXT
*>(cmd_data
);
11846 GLenum target
= static_cast<GLenum
>(c
.target
);
11847 uint32 submit_count
= static_cast<GLuint
>(c
.submit_count
);
11849 QueryManager::Query
* query
= query_manager_
->GetActiveQuery(target
);
11851 LOCAL_SET_GL_ERROR(
11852 GL_INVALID_OPERATION
, "glEndQueryEXT", "No active query");
11853 return error::kNoError
;
11856 if (!query_manager_
->EndQuery(query
, submit_count
)) {
11857 return error::kOutOfBounds
;
11860 query_manager_
->ProcessPendingTransferQueries();
11862 return error::kNoError
;
11865 error::Error
GLES2DecoderImpl::HandleQueryCounterEXT(uint32 immediate_data_size
,
11866 const void* cmd_data
) {
11867 const gles2::cmds::QueryCounterEXT
& c
=
11868 *static_cast<const gles2::cmds::QueryCounterEXT
*>(cmd_data
);
11869 GLuint client_id
= static_cast<GLuint
>(c
.id
);
11870 GLenum target
= static_cast<GLenum
>(c
.target
);
11871 int32 sync_shm_id
= static_cast<int32
>(c
.sync_data_shm_id
);
11872 uint32 sync_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
11873 uint32 submit_count
= static_cast<GLuint
>(c
.submit_count
);
11877 if (!query_manager_
->GPUTimingAvailable()) {
11878 LOCAL_SET_GL_ERROR(
11879 GL_INVALID_OPERATION
, "glQueryCounterEXT",
11880 "not enabled for timing queries");
11881 return error::kNoError
;
11885 LOCAL_SET_GL_ERROR(
11886 GL_INVALID_ENUM
, "glQueryCounterEXT",
11887 "unknown query target");
11888 return error::kNoError
;
11891 QueryManager::Query
* query
= query_manager_
->GetQuery(client_id
);
11893 if (!query_manager_
->IsValidQuery(client_id
)) {
11894 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11895 "glQueryCounterEXT",
11896 "id not made by glGenQueriesEXT");
11897 return error::kNoError
;
11899 query
= query_manager_
->CreateQuery(
11900 target
, client_id
, sync_shm_id
, sync_shm_offset
);
11902 if (!query_manager_
->QueryCounter(query
, submit_count
)) {
11903 return error::kOutOfBounds
;
11906 return error::kNoError
;
11909 error::Error
GLES2DecoderImpl::HandleSetDisjointValueSyncCHROMIUM(
11910 uint32 immediate_data_size
, const void* cmd_data
) {
11911 const gles2::cmds::SetDisjointValueSyncCHROMIUM
& c
=
11912 *static_cast<const gles2::cmds::SetDisjointValueSyncCHROMIUM
*>(cmd_data
);
11913 int32 sync_shm_id
= static_cast<int32
>(c
.sync_data_shm_id
);
11914 uint32 sync_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
11916 query_manager_
->SetDisjointSync(sync_shm_id
, sync_shm_offset
);
11917 return error::kNoError
;
11920 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
11921 GLsizei n
, const GLuint
* client_ids
) {
11922 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11923 if (GetVertexAttribManager(client_ids
[ii
])) {
11928 if (!features().native_vertex_array_object
) {
11930 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11931 CreateVertexAttribManager(client_ids
[ii
], 0, true);
11934 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
11936 glGenVertexArraysOES(n
, service_ids
.get());
11937 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11938 CreateVertexAttribManager(client_ids
[ii
], service_ids
[ii
], true);
11945 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
11946 GLsizei n
, const GLuint
* client_ids
) {
11947 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11948 VertexAttribManager
* vao
=
11949 GetVertexAttribManager(client_ids
[ii
]);
11950 if (vao
&& !vao
->IsDeleted()) {
11951 if (state_
.vertex_attrib_manager
.get() == vao
) {
11952 DoBindVertexArrayOES(0);
11954 RemoveVertexAttribManager(client_ids
[ii
]);
11959 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id
) {
11960 VertexAttribManager
* vao
= NULL
;
11961 if (client_id
!= 0) {
11962 vao
= GetVertexAttribManager(client_id
);
11964 // Unlike most Bind* methods, the spec explicitly states that VertexArray
11965 // only allows names that have been previously generated. As such, we do
11966 // not generate new names here.
11967 LOCAL_SET_GL_ERROR(
11968 GL_INVALID_OPERATION
,
11969 "glBindVertexArrayOES", "bad vertex array id.");
11970 current_decoder_error_
= error::kNoError
;
11974 vao
= state_
.default_vertex_attrib_manager
.get();
11977 // Only set the VAO state if it's changed
11978 if (state_
.vertex_attrib_manager
.get() != vao
) {
11979 state_
.vertex_attrib_manager
= vao
;
11980 if (!features().native_vertex_array_object
) {
11981 EmulateVertexArrayState();
11983 GLuint service_id
= vao
->service_id();
11984 glBindVertexArrayOES(service_id
);
11989 // Used when OES_vertex_array_object isn't natively supported
11990 void GLES2DecoderImpl::EmulateVertexArrayState() {
11991 // Setup the Vertex attribute state
11992 for (uint32 vv
= 0; vv
< group_
->max_vertex_attribs(); ++vv
) {
11993 RestoreStateForAttrib(vv
, true);
11996 // Setup the element buffer
11997 Buffer
* element_array_buffer
=
11998 state_
.vertex_attrib_manager
->element_array_buffer();
11999 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
12000 element_array_buffer
? element_array_buffer
->service_id() : 0);
12003 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id
) {
12004 const VertexAttribManager
* vao
=
12005 GetVertexAttribManager(client_id
);
12006 return vao
&& vao
->IsValid() && !vao
->IsDeleted();
12009 bool GLES2DecoderImpl::DoIsPathCHROMIUM(GLuint client_id
) {
12010 GLuint service_id
= 0;
12011 return path_manager()->GetPath(client_id
, &service_id
) &&
12012 glIsPathNV(service_id
) == GL_TRUE
;
12015 #if defined(OS_MACOSX)
12016 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id
) {
12017 TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.find(
12019 if (it
!= texture_to_io_surface_map_
.end()) {
12020 // Found a previous IOSurface bound to this texture; release it.
12021 IOSurfaceRef surface
= it
->second
;
12022 CFRelease(surface
);
12023 texture_to_io_surface_map_
.erase(it
);
12028 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
12029 GLenum target
, GLsizei width
, GLsizei height
,
12030 GLuint io_surface_id
, GLuint plane
) {
12031 #if defined(OS_MACOSX)
12032 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL
) {
12033 LOCAL_SET_GL_ERROR(
12034 GL_INVALID_OPERATION
,
12035 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
12039 if (target
!= GL_TEXTURE_RECTANGLE_ARB
) {
12040 // This might be supported in the future, and if we could require
12041 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
12042 // could delete a lot of code. For now, perform strict validation so we
12043 // know what's going on.
12044 LOCAL_SET_GL_ERROR(
12045 GL_INVALID_OPERATION
,
12046 "glTexImageIOSurface2DCHROMIUM",
12047 "requires TEXTURE_RECTANGLE_ARB target");
12051 // Default target might be conceptually valid, but disallow it to avoid
12053 TextureRef
* texture_ref
=
12054 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
12055 if (!texture_ref
) {
12056 LOCAL_SET_GL_ERROR(
12057 GL_INVALID_OPERATION
,
12058 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
12062 // Look up the new IOSurface. Note that because of asynchrony
12063 // between processes this might fail; during live resizing the
12064 // plugin process might allocate and release an IOSurface before
12065 // this process gets a chance to look it up. Hold on to any old
12066 // IOSurface in this case.
12067 IOSurfaceRef surface
= IOSurfaceLookup(io_surface_id
);
12069 LOCAL_SET_GL_ERROR(
12070 GL_INVALID_OPERATION
,
12071 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
12075 // Release any IOSurface previously bound to this texture.
12076 ReleaseIOSurfaceForTexture(texture_ref
->service_id());
12078 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
12079 texture_to_io_surface_map_
.insert(
12080 std::make_pair(texture_ref
->service_id(), surface
));
12082 CGLContextObj context
=
12083 static_cast<CGLContextObj
>(context_
->GetHandle());
12085 CGLError err
= CGLTexImageIOSurface2D(
12092 GL_UNSIGNED_INT_8_8_8_8_REV
,
12096 if (err
!= kCGLNoError
) {
12097 LOCAL_SET_GL_ERROR(
12098 GL_INVALID_OPERATION
,
12099 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
12103 texture_manager()->SetLevelInfo(
12104 texture_ref
, target
, 0, GL_RGBA
, width
, height
, 1, 0, GL_BGRA
,
12105 GL_UNSIGNED_INT_8_8_8_8_REV
, gfx::Rect(width
, height
));
12108 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12109 "glTexImageIOSurface2DCHROMIUM", "not supported.");
12113 static GLenum
ExtractFormatFromStorageFormat(GLenum internalformat
) {
12114 switch (internalformat
) {
12126 return GL_RED_INTEGER
;
12138 return GL_RG_INTEGER
;
12139 case GL_ATC_RGB_AMD
:
12140 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
12141 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
12142 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
12143 case GL_ETC1_RGB8_OES
:
12145 case GL_R11F_G11F_B10F
:
12147 case GL_RGB8_SNORM
:
12158 return GL_RGB_INTEGER
;
12159 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
12160 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
12161 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
:
12162 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
12163 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
12164 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
12165 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
12167 case GL_SRGB8_ALPHA8
:
12168 case GL_RGBA8_SNORM
:
12177 case GL_RGB10_A2UI
:
12182 return GL_RGBA_INTEGER
;
12183 case GL_DEPTH_COMPONENT16
:
12184 case GL_DEPTH_COMPONENT24
:
12185 case GL_DEPTH_COMPONENT32F
:
12186 return GL_DEPTH_COMPONENT
;
12187 case GL_DEPTH24_STENCIL8
:
12188 case GL_DEPTH32F_STENCIL8
:
12189 return GL_DEPTH_STENCIL
;
12190 case GL_LUMINANCE8_ALPHA8_EXT
:
12191 return GL_LUMINANCE_ALPHA
;
12192 case GL_LUMINANCE8_EXT
:
12193 return GL_LUMINANCE
;
12194 case GL_ALPHA8_EXT
:
12196 case GL_ALPHA32F_EXT
:
12198 case GL_LUMINANCE32F_EXT
:
12199 return GL_LUMINANCE
;
12200 case GL_LUMINANCE_ALPHA32F_EXT
:
12201 return GL_LUMINANCE_ALPHA
;
12202 case GL_ALPHA16F_EXT
:
12204 case GL_LUMINANCE16F_EXT
:
12205 return GL_LUMINANCE
;
12206 case GL_LUMINANCE_ALPHA16F_EXT
:
12207 return GL_LUMINANCE_ALPHA
;
12209 return GL_BGRA_EXT
;
12215 bool GLES2DecoderImpl::ValidateCopyTextureCHROMIUM(
12216 const char* function_name
,
12218 TextureRef
* source_texture_ref
,
12219 TextureRef
* dest_texture_ref
,
12220 GLenum dest_internal_format
) {
12221 if (!source_texture_ref
|| !dest_texture_ref
) {
12222 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown texture id");
12226 if (GL_TEXTURE_2D
!= target
) {
12227 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
12228 "invalid texture target");
12232 Texture
* source_texture
= source_texture_ref
->texture();
12233 Texture
* dest_texture
= dest_texture_ref
->texture();
12234 if (source_texture
== dest_texture
) {
12235 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
12236 "source and destination textures are the same");
12240 if (dest_texture
->target() != GL_TEXTURE_2D
||
12241 (source_texture
->target() != GL_TEXTURE_2D
&&
12242 source_texture
->target() != GL_TEXTURE_RECTANGLE_ARB
&&
12243 source_texture
->target() != GL_TEXTURE_EXTERNAL_OES
)) {
12244 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
12245 "invalid texture target binding");
12249 GLenum source_type
= 0;
12250 GLenum source_internal_format
= 0;
12251 source_texture
->GetLevelType(source_texture
->target(), 0, &source_type
,
12252 &source_internal_format
);
12254 // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
12255 // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
12256 // renderable on some platforms.
12257 bool valid_dest_format
= dest_internal_format
== GL_RGB
||
12258 dest_internal_format
== GL_RGBA
||
12259 dest_internal_format
== GL_BGRA_EXT
;
12260 bool valid_source_format
=
12261 source_internal_format
== GL_R8
|| source_internal_format
== GL_ALPHA
||
12262 source_internal_format
== GL_RGB
|| source_internal_format
== GL_RGBA
||
12263 source_internal_format
== GL_LUMINANCE
||
12264 source_internal_format
== GL_LUMINANCE_ALPHA
||
12265 source_internal_format
== GL_BGRA_EXT
;
12266 if (!valid_source_format
|| !valid_dest_format
) {
12267 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
12268 "invalid internal format");
12274 bool GLES2DecoderImpl::ValidateCompressedCopyTextureCHROMIUM(
12275 const char* function_name
,
12277 TextureRef
* source_texture_ref
,
12278 TextureRef
* dest_texture_ref
) {
12279 if (!source_texture_ref
|| !dest_texture_ref
) {
12280 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown texture id");
12284 if (GL_TEXTURE_2D
!= target
) {
12285 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
12286 "invalid texture target");
12290 Texture
* source_texture
= source_texture_ref
->texture();
12291 Texture
* dest_texture
= dest_texture_ref
->texture();
12292 if (source_texture
== dest_texture
) {
12293 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
12294 "source and destination textures are the same");
12298 if (dest_texture
->target() != GL_TEXTURE_2D
||
12299 (source_texture
->target() != GL_TEXTURE_2D
&&
12300 source_texture
->target() != GL_TEXTURE_RECTANGLE_ARB
&&
12301 source_texture
->target() != GL_TEXTURE_EXTERNAL_OES
)) {
12302 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
12303 "invalid texture target binding");
12307 GLenum source_type
= 0;
12308 GLenum source_internal_format
= 0;
12309 source_texture
->GetLevelType(source_texture
->target(), 0, &source_type
,
12310 &source_internal_format
);
12312 bool valid_format
=
12313 source_internal_format
== GL_ATC_RGB_AMD
||
12314 source_internal_format
== GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
||
12315 source_internal_format
== GL_COMPRESSED_RGB_S3TC_DXT1_EXT
||
12316 source_internal_format
== GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
||
12317 source_internal_format
== GL_ETC1_RGB8_OES
;
12319 if (!valid_format
) {
12320 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
12321 "invalid internal format");
12328 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
12332 GLenum internal_format
,
12334 GLboolean unpack_flip_y
,
12335 GLboolean unpack_premultiply_alpha
,
12336 GLboolean unpack_unmultiply_alpha
) {
12337 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
12339 TextureRef
* source_texture_ref
= GetTexture(source_id
);
12340 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
12341 Texture
* source_texture
= source_texture_ref
->texture();
12342 Texture
* dest_texture
= dest_texture_ref
->texture();
12343 int source_width
= 0;
12344 int source_height
= 0;
12345 gfx::GLImage
* image
=
12346 source_texture
->GetLevelImage(source_texture
->target(), 0);
12348 gfx::Size size
= image
->GetSize();
12349 source_width
= size
.width();
12350 source_height
= size
.height();
12351 if (source_width
<= 0 || source_height
<= 0) {
12352 LOCAL_SET_GL_ERROR(
12354 "glCopyTextureChromium", "invalid image size");
12358 if (!source_texture
->GetLevelSize(source_texture
->target(), 0,
12359 &source_width
, &source_height
, nullptr)) {
12360 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
12361 "glCopyTextureChromium",
12362 "source texture has no level 0");
12366 // Check that this type of texture is allowed.
12367 if (!texture_manager()->ValidForTarget(source_texture
->target(), 0,
12368 source_width
, source_height
, 1)) {
12369 LOCAL_SET_GL_ERROR(
12370 GL_INVALID_VALUE
, "glCopyTextureCHROMIUM", "Bad dimensions");
12375 GLenum source_type
= 0;
12376 GLenum source_internal_format
= 0;
12377 source_texture
->GetLevelType(
12378 source_texture
->target(), 0, &source_type
, &source_internal_format
);
12380 if (dest_texture
->IsImmutable()) {
12381 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCopyTextureCHROMIUM",
12382 "texture is immutable");
12386 if (!ValidateCopyTextureCHROMIUM("glCopyTextureCHROMIUM", target
,
12387 source_texture_ref
, dest_texture_ref
,
12388 internal_format
)) {
12392 // Clear the source texture if necessary.
12393 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref
,
12394 source_texture
->target(), 0)) {
12395 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTextureCHROMIUM",
12396 "dimensions too big");
12400 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12401 // needed because it takes 10s of milliseconds to initialize.
12402 if (!copy_texture_CHROMIUM_
.get()) {
12403 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12404 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
12405 copy_texture_CHROMIUM_
->Initialize(this);
12406 RestoreCurrentFramebufferBindings();
12407 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR
)
12411 GLenum dest_type_previous
= dest_type
;
12412 GLenum dest_internal_format
= internal_format
;
12413 int dest_width
= 0;
12414 int dest_height
= 0;
12415 bool dest_level_defined
= dest_texture
->GetLevelSize(
12416 GL_TEXTURE_2D
, 0, &dest_width
, &dest_height
, nullptr);
12418 if (dest_level_defined
) {
12419 dest_texture
->GetLevelType(GL_TEXTURE_2D
, 0, &dest_type_previous
,
12420 &dest_internal_format
);
12423 // Resize the destination texture to the dimensions of the source texture.
12424 if (!dest_level_defined
|| dest_width
!= source_width
||
12425 dest_height
!= source_height
||
12426 dest_internal_format
!= internal_format
||
12427 dest_type_previous
!= dest_type
) {
12428 // Ensure that the glTexImage2D succeeds.
12429 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12430 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
12431 glTexImage2D(GL_TEXTURE_2D
, 0, internal_format
, source_width
, source_height
,
12432 0, internal_format
, dest_type
, NULL
);
12433 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
12434 if (error
!= GL_NO_ERROR
) {
12435 RestoreCurrentTextureBindings(&state_
, GL_TEXTURE_2D
);
12439 texture_manager()->SetLevelInfo(
12440 dest_texture_ref
, GL_TEXTURE_2D
, 0, internal_format
, source_width
,
12441 source_height
, 1, 0, internal_format
, dest_type
,
12442 gfx::Rect(source_width
, source_height
));
12444 texture_manager()->SetLevelCleared(dest_texture_ref
, GL_TEXTURE_2D
, 0,
12448 ScopedModifyPixels
modify(dest_texture_ref
);
12450 // Try using GLImage::CopyTexSubImage when possible.
12451 bool unpack_premultiply_alpha_change
=
12452 (unpack_premultiply_alpha
^ unpack_unmultiply_alpha
) != 0;
12453 if (image
&& !unpack_flip_y
&& !unpack_premultiply_alpha_change
) {
12454 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
12455 if (image
->CopyTexSubImage(GL_TEXTURE_2D
, gfx::Point(0, 0),
12456 gfx::Rect(0, 0, source_width
, source_height
))) {
12461 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
12463 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
12464 // before presenting.
12465 if (source_texture
->target() == GL_TEXTURE_EXTERNAL_OES
) {
12466 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
12467 // instead of using kIdentityMatrix crbug.com/226218.
12468 copy_texture_CHROMIUM_
->DoCopyTextureWithTransform(
12469 this, source_texture
->target(), source_texture
->service_id(),
12470 dest_texture
->service_id(), source_width
, source_height
,
12471 unpack_flip_y
== GL_TRUE
,
12472 unpack_premultiply_alpha
== GL_TRUE
,
12473 unpack_unmultiply_alpha
== GL_TRUE
,
12476 copy_texture_CHROMIUM_
->DoCopyTexture(
12477 this, source_texture
->target(), source_texture
->service_id(),
12478 source_internal_format
, dest_texture
->service_id(), internal_format
,
12479 source_width
, source_height
,
12480 unpack_flip_y
== GL_TRUE
,
12481 unpack_premultiply_alpha
== GL_TRUE
,
12482 unpack_unmultiply_alpha
== GL_TRUE
);
12485 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
12488 void GLES2DecoderImpl::DoCopySubTextureCHROMIUM(
12498 GLboolean unpack_flip_y
,
12499 GLboolean unpack_premultiply_alpha
,
12500 GLboolean unpack_unmultiply_alpha
) {
12501 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopySubTextureCHROMIUM");
12503 TextureRef
* source_texture_ref
= GetTexture(source_id
);
12504 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
12505 Texture
* source_texture
= source_texture_ref
->texture();
12506 Texture
* dest_texture
= dest_texture_ref
->texture();
12507 int source_width
= 0;
12508 int source_height
= 0;
12509 gfx::GLImage
* image
=
12510 source_texture
->GetLevelImage(source_texture
->target(), 0);
12512 gfx::Size size
= image
->GetSize();
12513 source_width
= size
.width();
12514 source_height
= size
.height();
12515 if (source_width
<= 0 || source_height
<= 0) {
12516 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
12517 "invalid image size");
12521 if (!source_texture
->GetLevelSize(source_texture
->target(), 0,
12522 &source_width
, &source_height
, nullptr)) {
12523 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
12524 "source texture has no level 0");
12528 // Check that this type of texture is allowed.
12529 if (!texture_manager()->ValidForTarget(source_texture
->target(), 0,
12530 source_width
, source_height
, 1)) {
12531 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
12532 "source texture bad dimensions");
12537 GLenum source_type
= 0;
12538 GLenum source_internal_format
= 0;
12539 source_texture
->GetLevelType(source_texture
->target(), 0, &source_type
,
12540 &source_internal_format
);
12541 if (!source_texture
->ValidForTexture(source_texture
->target(), 0, x
, y
, 0,
12542 width
, height
, 1, source_type
)) {
12543 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
12544 "source texture bad dimensions.");
12548 GLenum dest_type
= 0;
12549 GLenum dest_internal_format
= 0;
12550 bool dest_level_defined
= dest_texture
->GetLevelType(
12551 dest_texture
->target(), 0, &dest_type
, &dest_internal_format
);
12552 if (!dest_level_defined
) {
12553 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCopySubTextureCHROMIUM",
12554 "destination texture is not defined");
12557 if (!dest_texture
->ValidForTexture(dest_texture
->target(), 0, xoffset
,
12558 yoffset
, 0, width
, height
, 1, dest_type
)) {
12559 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
12560 "destination texture bad dimensions.");
12564 if (!ValidateCopyTextureCHROMIUM("glCopySubTextureCHROMIUM", target
,
12565 source_texture_ref
, dest_texture_ref
,
12566 dest_internal_format
)) {
12570 // Clear the source texture if necessary.
12571 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref
,
12572 source_texture
->target(), 0)) {
12573 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopySubTextureCHROMIUM",
12574 "source texture dimensions too big");
12578 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12579 // needed because it takes 10s of milliseconds to initialize.
12580 if (!copy_texture_CHROMIUM_
.get()) {
12581 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopySubTextureCHROMIUM");
12582 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
12583 copy_texture_CHROMIUM_
->Initialize(this);
12584 RestoreCurrentFramebufferBindings();
12585 if (LOCAL_PEEK_GL_ERROR("glCopySubTextureCHROMIUM") != GL_NO_ERROR
)
12589 int dest_width
= 0;
12590 int dest_height
= 0;
12591 bool ok
= dest_texture
->GetLevelSize(
12592 GL_TEXTURE_2D
, 0, &dest_width
, &dest_height
, nullptr);
12594 if (xoffset
!= 0 || yoffset
!= 0 || width
!= dest_width
||
12595 height
!= dest_height
) {
12596 gfx::Rect cleared_rect
;
12597 if (CombineAdjacentRects(dest_texture
->GetLevelClearedRect(target
, 0),
12598 gfx::Rect(xoffset
, yoffset
, width
, height
),
12600 DCHECK_GE(cleared_rect
.size().GetArea(),
12601 dest_texture
->GetLevelClearedRect(target
, 0).size().GetArea());
12602 texture_manager()->SetLevelClearedRect(dest_texture_ref
, target
, 0,
12605 // Otherwise clear part of texture level that is not already cleared.
12606 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref
, target
,
12608 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopySubTextureCHROMIUM",
12609 "destination texture dimensions too big");
12614 texture_manager()->SetLevelCleared(dest_texture_ref
, GL_TEXTURE_2D
, 0,
12618 ScopedModifyPixels
modify(dest_texture_ref
);
12620 // Try using GLImage::CopyTexSubImage when possible.
12621 bool unpack_premultiply_alpha_change
=
12622 (unpack_premultiply_alpha
^ unpack_unmultiply_alpha
) != 0;
12623 if (image
&& !unpack_flip_y
&& !unpack_premultiply_alpha_change
) {
12624 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
12625 if (image
->CopyTexSubImage(GL_TEXTURE_2D
, gfx::Point(xoffset
, yoffset
),
12626 gfx::Rect(x
, y
, width
, height
))) {
12631 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
12633 // TODO(hkuang): get the StreamTexture transform matrix in GPU process.
12634 // crbug.com/226218.
12635 copy_texture_CHROMIUM_
->DoCopySubTexture(
12636 this, source_texture
->target(), source_texture
->service_id(),
12637 source_internal_format
, dest_texture
->service_id(), dest_internal_format
,
12638 xoffset
, yoffset
, x
, y
, width
, height
, dest_width
, dest_height
,
12639 source_width
, source_height
,
12640 unpack_flip_y
== GL_TRUE
,
12641 unpack_premultiply_alpha
== GL_TRUE
,
12642 unpack_unmultiply_alpha
== GL_TRUE
);
12644 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
12647 void GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM(GLenum target
,
12650 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM");
12652 TextureRef
* source_texture_ref
= GetTexture(source_id
);
12653 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
12654 Texture
* source_texture
= source_texture_ref
->texture();
12655 Texture
* dest_texture
= dest_texture_ref
->texture();
12656 int source_width
= 0;
12657 int source_height
= 0;
12658 gfx::GLImage
* image
=
12659 source_texture
->GetLevelImage(source_texture
->target(), 0);
12661 gfx::Size size
= image
->GetSize();
12662 source_width
= size
.width();
12663 source_height
= size
.height();
12664 if (source_width
<= 0 || source_height
<= 0) {
12665 LOCAL_SET_GL_ERROR(
12667 "glCompressedCopyTextureCHROMIUM", "invalid image size");
12671 if (!source_texture
->GetLevelSize(source_texture
->target(), 0,
12672 &source_width
, &source_height
, nullptr)) {
12673 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
12674 "glCompressedCopyTextureCHROMIUM",
12675 "source texture has no level 0");
12679 // Check that this type of texture is allowed.
12680 if (!texture_manager()->ValidForTarget(source_texture
->target(), 0,
12681 source_width
, source_height
, 1)) {
12682 LOCAL_SET_GL_ERROR(
12683 GL_INVALID_VALUE
, "glCompressedCopyTextureCHROMIUM",
12689 GLenum source_type
= 0;
12690 GLenum source_internal_format
= 0;
12691 source_texture
->GetLevelType(
12692 source_texture
->target(), 0, &source_type
, &source_internal_format
);
12694 if (dest_texture
->IsImmutable()) {
12695 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12696 "glCompressedCopyTextureCHROMIUM",
12697 "texture is immutable");
12701 if (!ValidateCompressedCopyTextureCHROMIUM(
12702 "glCompressedCopyTextureCHROMIUM",
12704 source_texture_ref
, dest_texture_ref
)) {
12708 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12709 // needed because it takes 10s of milliseconds to initialize.
12710 if (!copy_texture_CHROMIUM_
.get()) {
12711 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12712 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
12713 copy_texture_CHROMIUM_
->Initialize(this);
12714 RestoreCurrentFramebufferBindings();
12715 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR
)
12719 // Clear the source texture if necessary.
12720 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref
,
12721 source_texture
->target(), 0)) {
12722 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCompressedCopyTextureCHROMIUM",
12723 "dimensions too big");
12727 ScopedTextureBinder
binder(
12728 &state_
, dest_texture
->service_id(), GL_TEXTURE_2D
);
12730 ScopedModifyPixels
modify(dest_texture_ref
);
12732 // Try using GLImage::CopyTexImage when possible.
12734 GLenum dest_type
= 0;
12735 GLenum dest_internal_format
= 0;
12736 int dest_width
= 0;
12737 int dest_height
= 0;
12738 bool dest_level_defined
= dest_texture
->GetLevelSize(
12739 GL_TEXTURE_2D
, 0, &dest_width
, &dest_height
, nullptr);
12741 if (dest_level_defined
) {
12742 dest_texture
->GetLevelType(GL_TEXTURE_2D
, 0, &dest_type
,
12743 &dest_internal_format
);
12746 // Resize the destination texture to the dimensions of the source texture.
12747 if (!dest_level_defined
|| dest_width
!= source_width
||
12748 dest_height
!= source_height
||
12749 dest_internal_format
!= source_internal_format
) {
12750 GLsizei source_size
= 0;
12752 bool did_get_size
= GetCompressedTexSizeInBytes(
12753 "glCompressedCopyTextureCHROMIUM", source_width
, source_height
,
12754 1, source_internal_format
, &source_size
);
12755 DCHECK(did_get_size
);
12757 // Ensure that the glCompressedTexImage2D succeeds.
12758 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
12759 glCompressedTexImage2D(GL_TEXTURE_2D
, 0, source_internal_format
,
12760 source_width
, source_height
, 0, source_size
,
12762 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedCopyTextureCHROMIUM");
12763 if (error
!= GL_NO_ERROR
) {
12764 RestoreCurrentTextureBindings(&state_
, GL_TEXTURE_2D
);
12768 texture_manager()->SetLevelInfo(
12769 dest_texture_ref
, GL_TEXTURE_2D
, 0, source_internal_format
,
12770 source_width
, source_height
, 1, 0, source_internal_format
,
12771 source_type
, gfx::Rect(source_width
, source_height
));
12773 texture_manager()->SetLevelCleared(dest_texture_ref
, GL_TEXTURE_2D
, 0,
12777 if (image
->CopyTexSubImage(GL_TEXTURE_2D
, gfx::Point(0, 0),
12778 gfx::Rect(0, 0, source_width
, source_height
))) {
12785 "GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM, fallback");
12787 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
12789 // As a fallback, copy into a non-compressed GL_RGBA texture.
12790 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
12791 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, source_width
, source_height
,
12792 0, GL_RGBA
, GL_UNSIGNED_BYTE
, NULL
);
12793 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedCopyTextureCHROMIUM");
12794 if (error
!= GL_NO_ERROR
) {
12795 RestoreCurrentTextureBindings(&state_
, GL_TEXTURE_2D
);
12799 texture_manager()->SetLevelInfo(
12800 dest_texture_ref
, GL_TEXTURE_2D
, 0, GL_RGBA
, source_width
,
12801 source_height
, 1, 0, GL_RGBA
, GL_UNSIGNED_BYTE
,
12802 gfx::Rect(source_width
, source_height
));
12804 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
12805 // before presenting.
12806 if (source_texture
->target() == GL_TEXTURE_EXTERNAL_OES
) {
12807 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
12808 // instead of using kIdentityMatrix crbug.com/226218.
12809 copy_texture_CHROMIUM_
->DoCopyTextureWithTransform(
12810 this, source_texture
->target(), source_texture
->service_id(),
12811 dest_texture
->service_id(), source_width
, source_height
,
12812 false, false, false, kIdentityMatrix
);
12814 copy_texture_CHROMIUM_
->DoCopyTexture(
12815 this, source_texture
->target(), source_texture
->service_id(),
12816 source_internal_format
, dest_texture
->service_id(), GL_RGBA
,
12817 source_width
, source_height
, false, false, false);
12820 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
12823 void GLES2DecoderImpl::DoCompressedCopySubTextureCHROMIUM(GLenum target
,
12832 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompressedCopySubTextureCHROMIUM");
12834 TextureRef
* source_texture_ref
= GetTexture(source_id
);
12835 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
12836 Texture
* source_texture
= source_texture_ref
->texture();
12837 Texture
* dest_texture
= dest_texture_ref
->texture();
12838 int source_width
= 0;
12839 int source_height
= 0;
12840 gfx::GLImage
* image
=
12841 source_texture
->GetLevelImage(source_texture
->target(), 0);
12843 gfx::Size size
= image
->GetSize();
12844 source_width
= size
.width();
12845 source_height
= size
.height();
12846 if (source_width
<= 0 || source_height
<= 0) {
12847 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCompressedCopySubTextureCHROMIUM",
12848 "invalid image size");
12852 if (!source_texture
->GetLevelSize(source_texture
->target(), 0,
12853 &source_width
, &source_height
, nullptr)) {
12854 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCompressedCopySubTextureCHROMIUM",
12855 "source texture has no level 0");
12859 // Check that this type of texture is allowed.
12860 if (!texture_manager()->ValidForTarget(source_texture
->target(), 0,
12861 source_width
, source_height
, 1)) {
12862 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCompressedCopySubTextureCHROMIUM",
12863 "source texture bad dimensions");
12868 GLenum source_type
= 0;
12869 GLenum source_internal_format
= 0;
12870 source_texture
->GetLevelType(source_texture
->target(), 0, &source_type
,
12871 &source_internal_format
);
12872 if (!source_texture
->ValidForTexture(source_texture
->target(), 0, x
, y
, 0,
12873 width
, height
, 1, source_type
)) {
12874 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCompressedCopySubTextureCHROMIUM",
12875 "source texture bad dimensions.");
12879 GLenum dest_type
= 0;
12880 GLenum dest_internal_format
= 0;
12881 bool dest_level_defined
= dest_texture
->GetLevelType(
12882 dest_texture
->target(), 0, &dest_type
, &dest_internal_format
);
12883 if (!dest_level_defined
) {
12884 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12885 "glCompressedCopySubTextureCHROMIUM",
12886 "destination texture is not defined");
12889 if (!dest_texture
->ValidForTexture(dest_texture
->target(), 0, xoffset
,
12890 yoffset
, 0, width
, height
, 1, dest_type
)) {
12891 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCompressedCopySubTextureCHROMIUM",
12892 "destination texture bad dimensions.");
12896 if (!ValidateCompressedCopyTextureCHROMIUM(
12897 "glCompressedCopySubTextureCHROMIUM", target
, source_texture_ref
,
12898 dest_texture_ref
)) {
12902 if (!ValidateCompressedTexSubDimensions("glCompressedCopySubTextureCHROMIUM",
12903 source_texture
->target(), 0, x
, y
, 0,
12905 source_internal_format
,
12907 !ValidateCompressedTexSubDimensions("glCompressedCopySubTextureCHROMIUM",
12908 dest_texture
->target(), 0,
12909 xoffset
, yoffset
, 0, width
, height
, 1,
12910 dest_internal_format
,
12915 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12916 // needed because it takes 10s of milliseconds to initialize.
12917 if (!copy_texture_CHROMIUM_
.get()) {
12918 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopySubTextureCHROMIUM");
12919 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
12920 copy_texture_CHROMIUM_
->Initialize(this);
12921 RestoreCurrentFramebufferBindings();
12922 if (LOCAL_PEEK_GL_ERROR("glCompressedCopySubTextureCHROMIUM") !=
12928 // Clear the source texture if necessary.
12929 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref
,
12930 source_texture
->target(), 0)) {
12931 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCompressedCopySubTextureCHROMIUM",
12932 "source texture dimensions too big");
12936 int dest_width
= 0;
12937 int dest_height
= 0;
12938 bool ok
= dest_texture
->GetLevelSize(
12939 GL_TEXTURE_2D
, 0, &dest_width
, &dest_height
, nullptr);
12941 if (xoffset
!= 0 || yoffset
!= 0 || width
!= dest_width
||
12942 height
!= dest_height
) {
12943 gfx::Rect cleared_rect
;
12944 if (CombineAdjacentRects(dest_texture
->GetLevelClearedRect(target
, 0),
12945 gfx::Rect(xoffset
, yoffset
, width
, height
),
12947 DCHECK_GE(cleared_rect
.size().GetArea(),
12948 dest_texture
->GetLevelClearedRect(target
, 0).size().GetArea());
12949 texture_manager()->SetLevelClearedRect(dest_texture_ref
, target
, 0,
12952 // Otherwise clear part of texture level that is not already cleared.
12953 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref
, target
,
12955 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
,
12956 "glCompressedCopySubTextureCHROMIUM",
12957 "destination texture dimensions too big");
12962 texture_manager()->SetLevelCleared(dest_texture_ref
, GL_TEXTURE_2D
, 0,
12966 ScopedTextureBinder
binder(
12967 &state_
, dest_texture
->service_id(), GL_TEXTURE_2D
);
12969 ScopedModifyPixels
modify(dest_texture_ref
);
12971 // Try using GLImage::CopyTexSubImage when possible.
12973 if (image
->CopyTexSubImage(GL_TEXTURE_2D
, gfx::Point(xoffset
, yoffset
),
12974 gfx::Rect(x
, y
, width
, height
))) {
12981 "GLES2DecoderImpl::DoCompressedCopySubTextureCHROMIUM, fallback");
12983 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
12985 // As a fallback, copy into a non-compressed GL_RGBA texture.
12986 if (dest_internal_format
!= GL_RGBA
) {
12987 // To preserve the contents of the original destination texture we must
12988 // first copy the original destination texture to a temporary storage, then
12989 // copy it back to the original destination texture.
12990 GLuint tmp_service_id
;
12991 glGenTextures(1, &tmp_service_id
);
12992 DCHECK_NE(0u, tmp_service_id
);
12994 glBindTexture(GL_TEXTURE_2D
, tmp_service_id
);
12996 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
12997 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, dest_width
, dest_height
, 0, GL_RGBA
,
12998 GL_UNSIGNED_BYTE
, NULL
);
12999 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedCopySubTextureCHROMIUM");
13000 if (error
!= GL_NO_ERROR
)
13003 copy_texture_CHROMIUM_
->DoCopyTexture(
13004 this, dest_texture
->target(), dest_texture
->service_id(),
13005 dest_internal_format
, tmp_service_id
, GL_RGBA
,
13006 dest_width
, dest_height
, false, false, false);
13008 // Redefine destination texture to use RGBA.
13009 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
13010 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
13011 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, dest_width
, dest_height
, 0, GL_RGBA
,
13012 GL_UNSIGNED_BYTE
, NULL
);
13013 error
= LOCAL_PEEK_GL_ERROR("glCompressedCopySubTextureCHROMIUM");
13014 if (error
!= GL_NO_ERROR
)
13017 texture_manager()->SetLevelInfo(
13018 dest_texture_ref
, GL_TEXTURE_2D
, 0, GL_RGBA
, dest_width
, dest_height
,
13019 1, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, gfx::Rect(dest_width
, dest_height
));
13021 copy_texture_CHROMIUM_
->DoCopyTexture(
13022 this, GL_TEXTURE_2D
, tmp_service_id
, GL_RGBA
,
13023 dest_texture
->service_id(), GL_RGBA
,
13024 dest_width
, dest_height
, false, false, false);
13026 glDeleteTextures(1, &tmp_service_id
);
13029 // TODO(hkuang): get the StreamTexture transform matrix in GPU process.
13030 // crbug.com/226218.
13031 copy_texture_CHROMIUM_
->DoCopySubTexture(
13032 this, source_texture
->target(), source_texture
->service_id(),
13033 source_internal_format
, dest_texture
->service_id(), GL_RGBA
,
13034 xoffset
, yoffset
, x
, y
, width
, height
, dest_width
, dest_height
,
13035 source_width
, source_height
, false, false, false);
13037 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
13040 static GLenum
ExtractTypeFromStorageFormat(GLenum internalformat
) {
13041 switch (internalformat
) {
13043 return GL_UNSIGNED_BYTE
;
13047 return GL_HALF_FLOAT
;
13051 return GL_UNSIGNED_BYTE
;
13055 return GL_UNSIGNED_SHORT
;
13059 return GL_UNSIGNED_INT
;
13063 return GL_UNSIGNED_BYTE
;
13067 return GL_HALF_FLOAT
;
13071 return GL_UNSIGNED_BYTE
;
13075 return GL_UNSIGNED_SHORT
;
13079 return GL_UNSIGNED_INT
;
13084 return GL_UNSIGNED_BYTE
;
13085 case GL_R11F_G11F_B10F
:
13086 return GL_UNSIGNED_INT_10F_11F_11F_REV
;
13088 return GL_UNSIGNED_SHORT_5_6_5
;
13089 case GL_RGB8_SNORM
:
13092 return GL_UNSIGNED_INT_5_9_9_9_REV
;
13094 return GL_HALF_FLOAT
;
13098 return GL_UNSIGNED_BYTE
;
13102 return GL_UNSIGNED_SHORT
;
13106 return GL_UNSIGNED_INT
;
13110 return GL_UNSIGNED_BYTE
;
13111 case GL_SRGB8_ALPHA8
:
13112 return GL_UNSIGNED_BYTE
;
13113 case GL_RGBA8_SNORM
:
13116 return GL_UNSIGNED_SHORT_4_4_4_4
;
13118 return GL_UNSIGNED_INT_2_10_10_10_REV
;
13120 return GL_UNSIGNED_SHORT_5_5_5_1
;
13122 return GL_HALF_FLOAT
;
13126 return GL_UNSIGNED_BYTE
;
13129 case GL_RGB10_A2UI
:
13130 return GL_UNSIGNED_INT_2_10_10_10_REV
;
13132 return GL_UNSIGNED_SHORT
;
13138 return GL_UNSIGNED_INT
;
13139 case GL_DEPTH_COMPONENT16
:
13140 return GL_UNSIGNED_SHORT
;
13141 case GL_DEPTH_COMPONENT24
:
13142 return GL_UNSIGNED_INT
;
13143 case GL_DEPTH_COMPONENT32F
:
13145 case GL_DEPTH24_STENCIL8
:
13146 return GL_UNSIGNED_INT_24_8
;
13147 case GL_DEPTH32F_STENCIL8
:
13148 return GL_FLOAT_32_UNSIGNED_INT_24_8_REV
;
13149 case GL_LUMINANCE8_ALPHA8_EXT
:
13150 return GL_UNSIGNED_BYTE
;
13151 case GL_LUMINANCE8_EXT
:
13152 return GL_UNSIGNED_BYTE
;
13153 case GL_ALPHA8_EXT
:
13154 return GL_UNSIGNED_BYTE
;
13155 case GL_ALPHA32F_EXT
:
13157 case GL_LUMINANCE32F_EXT
:
13159 case GL_LUMINANCE_ALPHA32F_EXT
:
13161 case GL_ALPHA16F_EXT
:
13162 return GL_HALF_FLOAT_OES
;
13163 case GL_LUMINANCE16F_EXT
:
13164 return GL_HALF_FLOAT_OES
;
13165 case GL_LUMINANCE_ALPHA16F_EXT
:
13166 return GL_HALF_FLOAT_OES
;
13168 return GL_UNSIGNED_BYTE
;
13174 void GLES2DecoderImpl::DoTexStorage2DEXT(
13177 GLenum internal_format
,
13180 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
13181 "width", width
, "height", height
);
13182 if (!texture_manager()->ValidForTarget(target
, 0, width
, height
, 1) ||
13183 TextureManager::ComputeMipMapCount(target
, width
, height
, 1) < levels
) {
13184 LOCAL_SET_GL_ERROR(
13185 GL_INVALID_VALUE
, "glTexStorage2DEXT", "dimensions out of range");
13188 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
13190 if (!texture_ref
) {
13191 LOCAL_SET_GL_ERROR(
13192 GL_INVALID_OPERATION
,
13193 "glTexStorage2DEXT", "unknown texture for target");
13196 Texture
* texture
= texture_ref
->texture();
13197 if (texture
->IsAttachedToFramebuffer()) {
13198 framebuffer_state_
.clear_state_dirty
= true;
13200 if (texture
->IsImmutable()) {
13201 LOCAL_SET_GL_ERROR(
13202 GL_INVALID_OPERATION
,
13203 "glTexStorage2DEXT", "texture is immutable");
13207 GLenum format
= ExtractFormatFromStorageFormat(internal_format
);
13208 GLenum type
= ExtractTypeFromStorageFormat(internal_format
);
13211 GLsizei level_width
= width
;
13212 GLsizei level_height
= height
;
13213 uint32 estimated_size
= 0;
13214 for (int ii
= 0; ii
< levels
; ++ii
) {
13215 uint32 level_size
= 0;
13216 if (!GLES2Util::ComputeImageDataSizes(
13217 level_width
, level_height
, 1, format
, type
, state_
.unpack_alignment
,
13218 &estimated_size
, NULL
, NULL
) ||
13219 !SafeAddUint32(estimated_size
, level_size
, &estimated_size
)) {
13220 LOCAL_SET_GL_ERROR(
13221 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "dimensions too large");
13224 level_width
= std::max(1, level_width
>> 1);
13225 level_height
= std::max(1, level_height
>> 1);
13227 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
13228 LOCAL_SET_GL_ERROR(
13229 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "out of memory");
13234 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
13235 glTexStorage2DEXT(target
, levels
, internal_format
, width
, height
);
13236 GLenum error
= LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
13237 if (error
== GL_NO_ERROR
) {
13238 GLsizei level_width
= width
;
13239 GLsizei level_height
= height
;
13241 GLenum cur_format
= feature_info_
->IsES3Enabled() ?
13242 internal_format
: format
;
13243 for (int ii
= 0; ii
< levels
; ++ii
) {
13244 if (target
== GL_TEXTURE_CUBE_MAP
) {
13245 for (int jj
= 0; jj
< 6; ++jj
) {
13246 GLenum face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ jj
;
13247 texture_manager()->SetLevelInfo(texture_ref
, face
, ii
, cur_format
,
13248 level_width
, level_height
, 1, 0,
13249 format
, type
, gfx::Rect());
13252 texture_manager()->SetLevelInfo(texture_ref
, target
, ii
, cur_format
,
13253 level_width
, level_height
, 1, 0,
13254 format
, type
, gfx::Rect());
13256 level_width
= std::max(1, level_width
>> 1);
13257 level_height
= std::max(1, level_height
>> 1);
13259 texture
->SetImmutable(true);
13263 error::Error
GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
13264 uint32 immediate_data_size
,
13265 const void* cmd_data
) {
13266 return error::kUnknownCommand
;
13269 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target
,
13270 const GLbyte
* data
) {
13271 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
13272 "context", logger_
.GetLogPrefix(),
13273 "mailbox[0]", static_cast<unsigned char>(data
[0]));
13275 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
13277 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref
, target
, data
);
13280 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id
,
13281 GLenum target
, const GLbyte
* data
) {
13282 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
13283 "context", logger_
.GetLogPrefix(),
13284 "mailbox[0]", static_cast<unsigned char>(data
[0]));
13286 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id
),
13290 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name
,
13291 TextureRef
* texture_ref
, GLenum target
, const GLbyte
* data
) {
13292 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
13293 DLOG_IF(ERROR
, !mailbox
.Verify()) << func_name
<< " was passed a "
13294 "mailbox that was not generated by "
13295 "GenMailboxCHROMIUM.";
13297 if (!texture_ref
) {
13298 LOCAL_SET_GL_ERROR(
13299 GL_INVALID_OPERATION
, func_name
.c_str(), "unknown texture for target");
13303 Texture
* produced
= texture_manager()->Produce(texture_ref
);
13305 LOCAL_SET_GL_ERROR(
13306 GL_INVALID_OPERATION
, func_name
.c_str(), "invalid texture");
13310 if (produced
->target() != target
) {
13311 LOCAL_SET_GL_ERROR(
13312 GL_INVALID_OPERATION
, func_name
.c_str(), "invalid target");
13316 group_
->mailbox_manager()->ProduceTexture(mailbox
, produced
);
13319 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target
,
13320 const GLbyte
* data
) {
13321 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
13322 "context", logger_
.GetLogPrefix(),
13323 "mailbox[0]", static_cast<unsigned char>(data
[0]));
13324 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
13325 DLOG_IF(ERROR
, !mailbox
.Verify()) << "ConsumeTextureCHROMIUM was passed a "
13326 "mailbox that was not generated by "
13327 "GenMailboxCHROMIUM.";
13329 scoped_refptr
<TextureRef
> texture_ref
=
13330 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
13331 if (!texture_ref
.get()) {
13332 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
13333 "glConsumeTextureCHROMIUM",
13334 "unknown texture for target");
13337 GLuint client_id
= texture_ref
->client_id();
13339 LOCAL_SET_GL_ERROR(
13340 GL_INVALID_OPERATION
,
13341 "glConsumeTextureCHROMIUM", "unknown texture for target");
13344 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(mailbox
);
13346 LOCAL_SET_GL_ERROR(
13347 GL_INVALID_OPERATION
,
13348 "glConsumeTextureCHROMIUM", "invalid mailbox name");
13351 if (texture
->target() != target
) {
13352 LOCAL_SET_GL_ERROR(
13353 GL_INVALID_OPERATION
,
13354 "glConsumeTextureCHROMIUM", "invalid target");
13358 DeleteTexturesHelper(1, &client_id
);
13359 texture_ref
= texture_manager()->Consume(client_id
, texture
);
13360 glBindTexture(target
, texture_ref
->service_id());
13362 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
13363 unit
.bind_target
= target
;
13365 case GL_TEXTURE_2D
:
13366 unit
.bound_texture_2d
= texture_ref
;
13368 case GL_TEXTURE_CUBE_MAP
:
13369 unit
.bound_texture_cube_map
= texture_ref
;
13371 case GL_TEXTURE_EXTERNAL_OES
:
13372 unit
.bound_texture_external_oes
= texture_ref
;
13374 case GL_TEXTURE_RECTANGLE_ARB
:
13375 unit
.bound_texture_rectangle_arb
= texture_ref
;
13378 NOTREACHED(); // Validation should prevent us getting here.
13383 void GLES2DecoderImpl::EnsureTextureForClientId(
13385 GLuint client_id
) {
13386 TextureRef
* texture_ref
= GetTexture(client_id
);
13387 if (!texture_ref
) {
13389 glGenTextures(1, &service_id
);
13390 DCHECK_NE(0u, service_id
);
13391 texture_ref
= CreateTexture(client_id
, service_id
);
13392 texture_manager()->SetTarget(texture_ref
, target
);
13393 glBindTexture(target
, service_id
);
13394 RestoreCurrentTextureBindings(&state_
, target
);
13398 // If CreateAndConsumeTexture fails we still need to ensure that the client_id
13399 // provided is associated with a service_id/TextureRef for consistency, even if
13400 // the resulting texture is incomplete.
13401 error::Error
GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
13402 uint32_t immediate_data_size
,
13403 const void* cmd_data
) {
13404 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate
& c
=
13406 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate
*>(
13408 GLenum target
= static_cast<GLenum
>(c
.target
);
13409 uint32_t data_size
;
13410 if (!ComputeDataSize(1, sizeof(GLbyte
), 64, &data_size
)) {
13411 return error::kOutOfBounds
;
13413 if (data_size
> immediate_data_size
) {
13414 return error::kOutOfBounds
;
13416 const GLbyte
* mailbox
=
13417 GetImmediateDataAs
<const GLbyte
*>(c
, data_size
, immediate_data_size
);
13418 if (!validators_
->texture_bind_target
.IsValid(target
)) {
13419 LOCAL_SET_GL_ERROR_INVALID_ENUM(
13420 "glCreateAndConsumeTextureCHROMIUM", target
, "target");
13421 return error::kNoError
;
13423 if (mailbox
== NULL
) {
13424 return error::kOutOfBounds
;
13426 uint32_t client_id
= c
.client_id
;
13427 DoCreateAndConsumeTextureCHROMIUM(target
, mailbox
, client_id
);
13428 return error::kNoError
;
13431 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target
,
13432 const GLbyte
* data
, GLuint client_id
) {
13433 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
13434 "context", logger_
.GetLogPrefix(),
13435 "mailbox[0]", static_cast<unsigned char>(data
[0]));
13436 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
13437 DLOG_IF(ERROR
, !mailbox
.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
13438 "passed a mailbox that was not "
13439 "generated by GenMailboxCHROMIUM.";
13441 TextureRef
* texture_ref
= GetTexture(client_id
);
13443 // No need to call EnsureTextureForClientId here, the client_id already has
13444 // an associated texture.
13445 LOCAL_SET_GL_ERROR(
13446 GL_INVALID_OPERATION
,
13447 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
13450 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(mailbox
);
13452 EnsureTextureForClientId(target
, client_id
);
13453 LOCAL_SET_GL_ERROR(
13454 GL_INVALID_OPERATION
,
13455 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
13459 if (texture
->target() != target
) {
13460 EnsureTextureForClientId(target
, client_id
);
13461 LOCAL_SET_GL_ERROR(
13462 GL_INVALID_OPERATION
,
13463 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
13467 texture_ref
= texture_manager()->Consume(client_id
, texture
);
13470 bool GLES2DecoderImpl::DoIsValuebufferCHROMIUM(GLuint client_id
) {
13471 const Valuebuffer
* valuebuffer
= GetValuebuffer(client_id
);
13472 return valuebuffer
&& valuebuffer
->IsValid();
13475 void GLES2DecoderImpl::DoBindValueBufferCHROMIUM(GLenum target
,
13476 GLuint client_id
) {
13477 Valuebuffer
* valuebuffer
= NULL
;
13478 if (client_id
!= 0) {
13479 valuebuffer
= GetValuebuffer(client_id
);
13480 if (!valuebuffer
) {
13481 if (!group_
->bind_generates_resource()) {
13482 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glBindValuebufferCHROMIUM",
13483 "id not generated by glBindValuebufferCHROMIUM");
13487 // It's a new id so make a valuebuffer for it.
13488 CreateValuebuffer(client_id
);
13489 valuebuffer
= GetValuebuffer(client_id
);
13491 valuebuffer
->MarkAsValid();
13493 state_
.bound_valuebuffer
= valuebuffer
;
13496 void GLES2DecoderImpl::DoSubscribeValueCHROMIUM(GLenum target
,
13497 GLenum subscription
) {
13498 if (!CheckCurrentValuebuffer("glSubscribeValueCHROMIUM")) {
13501 state_
.bound_valuebuffer
.get()->AddSubscription(subscription
);
13504 void GLES2DecoderImpl::DoPopulateSubscribedValuesCHROMIUM(GLenum target
) {
13505 if (!CheckCurrentValuebuffer("glPopulateSubscribedValuesCHROMIUM")) {
13508 valuebuffer_manager()->UpdateValuebufferState(state_
.bound_valuebuffer
.get());
13511 void GLES2DecoderImpl::DoUniformValueBufferCHROMIUM(GLint location
,
13513 GLenum subscription
) {
13514 if (!CheckCurrentValuebufferForSubscription(
13515 subscription
, "glPopulateSubscribedValuesCHROMIUM")) {
13518 if (!CheckSubscriptionTarget(location
, subscription
,
13519 "glPopulateSubscribedValuesCHROMIUM")) {
13522 const ValueState
* state
=
13523 state_
.bound_valuebuffer
.get()->GetState(subscription
);
13525 switch (subscription
) {
13526 case GL_MOUSE_POSITION_CHROMIUM
:
13527 DoUniform2iv(location
, 1, state
->int_value
);
13530 NOTREACHED() << "Unhandled uniform subscription target "
13537 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
13538 GLsizei length
, const GLchar
* marker
) {
13542 debug_marker_manager_
.SetMarker(
13543 length
? std::string(marker
, length
) : std::string(marker
));
13546 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
13547 GLsizei
/*length*/, const GLchar
* /*marker*/) {
13550 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
13553 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
13554 GLenum target
, GLint image_id
) {
13555 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
13557 if (target
== GL_TEXTURE_CUBE_MAP
) {
13558 LOCAL_SET_GL_ERROR(
13560 "glBindTexImage2DCHROMIUM", "invalid target");
13564 // Default target might be conceptually valid, but disallow it to avoid
13566 TextureRef
* texture_ref
=
13567 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
13568 if (!texture_ref
) {
13569 LOCAL_SET_GL_ERROR(
13570 GL_INVALID_OPERATION
,
13571 "glBindTexImage2DCHROMIUM", "no texture bound");
13575 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
13577 LOCAL_SET_GL_ERROR(
13578 GL_INVALID_OPERATION
,
13579 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
13584 ScopedGLErrorSuppressor
suppressor(
13585 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
13586 if (!gl_image
->BindTexImage(target
)) {
13587 LOCAL_SET_GL_ERROR(
13588 GL_INVALID_OPERATION
,
13589 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
13594 gfx::Size size
= gl_image
->GetSize();
13595 texture_manager()->SetLevelInfo(
13596 texture_ref
, target
, 0, gl_image
->GetInternalFormat(), size
.width(),
13597 size
.height(), 1, 0, gl_image
->GetInternalFormat(), GL_UNSIGNED_BYTE
,
13599 texture_manager()->SetLevelImage(texture_ref
, target
, 0, gl_image
);
13602 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
13603 GLenum target
, GLint image_id
) {
13604 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
13606 // Default target might be conceptually valid, but disallow it to avoid
13608 TextureRef
* texture_ref
=
13609 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
13610 if (!texture_ref
) {
13611 LOCAL_SET_GL_ERROR(
13612 GL_INVALID_OPERATION
,
13613 "glReleaseTexImage2DCHROMIUM", "no texture bound");
13617 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
13619 LOCAL_SET_GL_ERROR(
13620 GL_INVALID_OPERATION
,
13621 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
13625 // Do nothing when image is not currently bound.
13626 if (texture_ref
->texture()->GetLevelImage(target
, 0) != gl_image
)
13630 ScopedGLErrorSuppressor
suppressor(
13631 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
13632 gl_image
->ReleaseTexImage(target
);
13635 texture_manager()->SetLevelInfo(
13636 texture_ref
, target
, 0, gl_image
->GetInternalFormat(), 0, 0, 1, 0,
13637 gl_image
->GetInternalFormat(), GL_UNSIGNED_BYTE
, gfx::Rect());
13640 error::Error
GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
13641 uint32 immediate_data_size
,
13642 const void* cmd_data
) {
13643 const gles2::cmds::TraceBeginCHROMIUM
& c
=
13644 *static_cast<const gles2::cmds::TraceBeginCHROMIUM
*>(cmd_data
);
13645 Bucket
* category_bucket
= GetBucket(c
.category_bucket_id
);
13646 Bucket
* name_bucket
= GetBucket(c
.name_bucket_id
);
13647 if (!category_bucket
|| category_bucket
->size() == 0 ||
13648 !name_bucket
|| name_bucket
->size() == 0) {
13649 return error::kInvalidArguments
;
13652 std::string category_name
;
13653 std::string trace_name
;
13654 if (!category_bucket
->GetAsString(&category_name
) ||
13655 !name_bucket
->GetAsString(&trace_name
)) {
13656 return error::kInvalidArguments
;
13659 debug_marker_manager_
.PushGroup(trace_name
);
13660 if (!gpu_tracer_
->Begin(category_name
, trace_name
, kTraceCHROMIUM
)) {
13661 LOCAL_SET_GL_ERROR(
13662 GL_INVALID_OPERATION
,
13663 "glTraceBeginCHROMIUM", "unable to create begin trace");
13664 return error::kNoError
;
13666 return error::kNoError
;
13669 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
13670 debug_marker_manager_
.PopGroup();
13671 if (!gpu_tracer_
->End(kTraceCHROMIUM
)) {
13672 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
13673 "glTraceEndCHROMIUM", "no trace begin found");
13678 void GLES2DecoderImpl::DoDrawBuffersEXT(
13679 GLsizei count
, const GLenum
* bufs
) {
13680 if (count
> static_cast<GLsizei
>(group_
->max_draw_buffers())) {
13681 LOCAL_SET_GL_ERROR(
13683 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
13687 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
13689 for (GLsizei i
= 0; i
< count
; ++i
) {
13690 if (bufs
[i
] != static_cast<GLenum
>(GL_COLOR_ATTACHMENT0
+ i
) &&
13691 bufs
[i
] != GL_NONE
) {
13692 LOCAL_SET_GL_ERROR(
13693 GL_INVALID_OPERATION
,
13694 "glDrawBuffersEXT",
13695 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
13699 glDrawBuffersARB(count
, bufs
);
13700 framebuffer
->SetDrawBuffers(count
, bufs
);
13701 } else { // backbuffer
13703 (bufs
[0] != GL_BACK
&& bufs
[0] != GL_NONE
)) {
13704 LOCAL_SET_GL_ERROR(
13705 GL_INVALID_OPERATION
,
13706 "glDrawBuffersEXT",
13707 "more than one buffer or bufs not GL_NONE or GL_BACK");
13710 GLenum mapped_buf
= bufs
[0];
13711 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
13712 bufs
[0] == GL_BACK
) {
13713 mapped_buf
= GL_COLOR_ATTACHMENT0
;
13715 glDrawBuffersARB(count
, &mapped_buf
);
13716 back_buffer_draw_buffer_
= bufs
[0];
13720 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current
, GLenum other
) {
13721 MarkContextLost(GetContextLostReasonFromResetStatus(current
));
13722 group_
->LoseContexts(GetContextLostReasonFromResetStatus(other
));
13723 reset_by_robustness_extension_
= true;
13726 void GLES2DecoderImpl::DoFlushDriverCachesCHROMIUM(void) {
13727 // On Adreno Android devices we need to use a workaround to force caches to
13729 if (feature_info_
->workarounds().unbind_egl_context_to_flush_driver_caches
) {
13730 context_
->ReleaseCurrent(nullptr);
13731 context_
->MakeCurrent(surface_
.get());
13735 void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode
,
13736 const GLfloat
* matrix
) {
13737 DCHECK(matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
||
13738 matrix_mode
== GL_PATH_MODELVIEW_CHROMIUM
);
13739 if (!features().chromium_path_rendering
) {
13740 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
13741 "glMatrixLoadfCHROMIUM",
13742 "function not available");
13746 GLfloat
* target_matrix
= matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
13747 ? state_
.projection_matrix
13748 : state_
.modelview_matrix
;
13749 memcpy(target_matrix
, matrix
, sizeof(GLfloat
) * 16);
13750 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
13751 // since the values of the _NV and _CHROMIUM tokens match.
13752 glMatrixLoadfEXT(matrix_mode
, matrix
);
13755 void GLES2DecoderImpl::DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode
) {
13756 DCHECK(matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
||
13757 matrix_mode
== GL_PATH_MODELVIEW_CHROMIUM
);
13759 if (!features().chromium_path_rendering
) {
13760 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
13761 "glMatrixLoadIdentityCHROMIUM",
13762 "function not available");
13766 GLfloat
* target_matrix
= matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
13767 ? state_
.projection_matrix
13768 : state_
.modelview_matrix
;
13769 memcpy(target_matrix
, kIdentityMatrix
, sizeof(kIdentityMatrix
));
13770 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
13771 // since the values of the _NV and _CHROMIUM tokens match.
13772 glMatrixLoadIdentityEXT(matrix_mode
);
13775 bool GLES2DecoderImpl::ValidateAsyncTransfer(
13776 const char* function_name
,
13777 TextureRef
* texture_ref
,
13780 const void * data
) {
13781 // We only support async uploads to 2D textures for now.
13782 if (GL_TEXTURE_2D
!= target
) {
13783 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
13786 // We only support uploads to level zero for now.
13788 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "level != 0");
13791 // A transfer buffer must be bound, even for asyncTexImage2D.
13792 if (data
== NULL
) {
13793 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
, "buffer == 0");
13796 // We only support one async transfer in progress.
13797 if (!texture_ref
||
13798 async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
13799 LOCAL_SET_GL_ERROR(
13800 GL_INVALID_OPERATION
,
13801 function_name
, "transfer already in progress");
13807 base::Closure
GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
13808 uint32 async_upload_token
,
13809 uint32 sync_data_shm_id
,
13810 uint32 sync_data_shm_offset
) {
13811 scoped_refptr
<gpu::Buffer
> buffer
= GetSharedMemoryBuffer(sync_data_shm_id
);
13812 if (!buffer
.get() ||
13813 !buffer
->GetDataAddress(sync_data_shm_offset
, sizeof(AsyncUploadSync
)))
13814 return base::Closure();
13816 AsyncMemoryParams
mem_params(buffer
,
13817 sync_data_shm_offset
,
13818 sizeof(AsyncUploadSync
));
13820 scoped_refptr
<AsyncUploadTokenCompletionObserver
> observer(
13821 new AsyncUploadTokenCompletionObserver(async_upload_token
));
13824 &AsyncPixelTransferManager::AsyncNotifyCompletion
,
13825 base::Unretained(GetAsyncPixelTransferManager()),
13830 error::Error
GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
13831 uint32 immediate_data_size
,
13832 const void* cmd_data
) {
13833 const gles2::cmds::AsyncTexImage2DCHROMIUM
& c
=
13834 *static_cast<const gles2::cmds::AsyncTexImage2DCHROMIUM
*>(cmd_data
);
13835 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
13836 GLenum target
= static_cast<GLenum
>(c
.target
);
13837 GLint level
= static_cast<GLint
>(c
.level
);
13838 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
13839 GLsizei width
= static_cast<GLsizei
>(c
.width
);
13840 GLsizei height
= static_cast<GLsizei
>(c
.height
);
13841 GLint border
= static_cast<GLint
>(c
.border
);
13842 GLenum format
= static_cast<GLenum
>(c
.format
);
13843 GLenum type
= static_cast<GLenum
>(c
.type
);
13844 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
13845 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
13846 uint32 pixels_size
;
13847 uint32 async_upload_token
= static_cast<uint32
>(c
.async_upload_token
);
13848 uint32 sync_data_shm_id
= static_cast<uint32
>(c
.sync_data_shm_id
);
13849 uint32 sync_data_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
13851 base::ScopedClosureRunner scoped_completion_callback
;
13852 if (async_upload_token
) {
13853 base::Closure completion_closure
=
13854 AsyncUploadTokenCompletionClosure(async_upload_token
,
13856 sync_data_shm_offset
);
13857 if (completion_closure
.is_null())
13858 return error::kInvalidArguments
;
13860 scoped_completion_callback
.Reset(completion_closure
);
13863 // TODO(epenner): Move this and copies of this memory validation
13864 // into ValidateTexImage2D step.
13865 if (!GLES2Util::ComputeImageDataSizes(
13866 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
13868 return error::kOutOfBounds
;
13870 const void* pixels
= NULL
;
13871 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
13872 pixels
= GetSharedMemoryAs
<const void*>(
13873 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
13875 return error::kOutOfBounds
;
13879 TextureManager::DoTexImageArguments args
= {
13880 target
, level
, internal_format
, width
, height
, 1, border
, format
, type
,
13881 pixels
, pixels_size
, TextureManager::DoTexImageArguments::kTexImage2D
};
13882 TextureRef
* texture_ref
;
13883 // All the normal glTexSubImage2D validation.
13884 if (!texture_manager()->ValidateTexImage(
13885 &state_
, "glAsyncTexImage2DCHROMIUM", args
, &texture_ref
)) {
13886 return error::kNoError
;
13889 // Extra async validation.
13890 Texture
* texture
= texture_ref
->texture();
13891 if (!ValidateAsyncTransfer(
13892 "glAsyncTexImage2DCHROMIUM", texture_ref
, target
, level
, pixels
))
13893 return error::kNoError
;
13895 // Don't allow async redefinition of a textures.
13896 if (texture
->IsDefined()) {
13897 LOCAL_SET_GL_ERROR(
13898 GL_INVALID_OPERATION
,
13899 "glAsyncTexImage2DCHROMIUM", "already defined");
13900 return error::kNoError
;
13903 if (!EnsureGPUMemoryAvailable(pixels_size
)) {
13904 LOCAL_SET_GL_ERROR(
13905 GL_OUT_OF_MEMORY
, "glAsyncTexImage2DCHROMIUM", "out of memory");
13906 return error::kNoError
;
13909 // Setup the parameters.
13910 AsyncTexImage2DParams tex_params
= {
13911 target
, level
, static_cast<GLenum
>(internal_format
),
13912 width
, height
, border
, format
, type
};
13913 AsyncMemoryParams
mem_params(
13914 GetSharedMemoryBuffer(c
.pixels_shm_id
), c
.pixels_shm_offset
, pixels_size
);
13916 // Set up the async state if needed, and make the texture
13917 // immutable so the async state stays valid. The level info
13918 // is set up lazily when the transfer completes.
13919 AsyncPixelTransferDelegate
* delegate
=
13920 async_pixel_transfer_manager_
->CreatePixelTransferDelegate(texture_ref
,
13922 texture
->SetImmutable(true);
13924 delegate
->AsyncTexImage2D(
13927 base::Bind(&TextureManager::SetLevelInfoFromParams
,
13928 // The callback is only invoked if the transfer delegate still
13929 // exists, which implies through manager->texture_ref->state
13930 // ownership that both of these pointers are valid.
13931 base::Unretained(texture_manager()),
13932 base::Unretained(texture_ref
),
13934 return error::kNoError
;
13937 error::Error
GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
13938 uint32 immediate_data_size
,
13939 const void* cmd_data
) {
13940 const gles2::cmds::AsyncTexSubImage2DCHROMIUM
& c
=
13941 *static_cast<const gles2::cmds::AsyncTexSubImage2DCHROMIUM
*>(cmd_data
);
13942 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
13943 GLenum target
= static_cast<GLenum
>(c
.target
);
13944 GLint level
= static_cast<GLint
>(c
.level
);
13945 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
13946 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
13947 GLsizei width
= static_cast<GLsizei
>(c
.width
);
13948 GLsizei height
= static_cast<GLsizei
>(c
.height
);
13949 GLenum format
= static_cast<GLenum
>(c
.format
);
13950 GLenum type
= static_cast<GLenum
>(c
.type
);
13951 uint32 async_upload_token
= static_cast<uint32
>(c
.async_upload_token
);
13952 uint32 sync_data_shm_id
= static_cast<uint32
>(c
.sync_data_shm_id
);
13953 uint32 sync_data_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
13955 base::ScopedClosureRunner scoped_completion_callback
;
13956 if (async_upload_token
) {
13957 base::Closure completion_closure
=
13958 AsyncUploadTokenCompletionClosure(async_upload_token
,
13960 sync_data_shm_offset
);
13961 if (completion_closure
.is_null())
13962 return error::kInvalidArguments
;
13964 scoped_completion_callback
.Reset(completion_closure
);
13967 // TODO(epenner): Move this and copies of this memory validation
13968 // into ValidateTexSubImage2D step.
13970 if (!GLES2Util::ComputeImageDataSizes(
13971 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &data_size
,
13973 return error::kOutOfBounds
;
13975 const void* pixels
= GetSharedMemoryAs
<const void*>(
13976 c
.data_shm_id
, c
.data_shm_offset
, data_size
);
13978 // All the normal glTexSubImage2D validation.
13979 error::Error error
= error::kNoError
;
13980 if (!ValidateTexSubImage2D(&error
, "glAsyncTexSubImage2DCHROMIUM",
13981 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
)) {
13985 // Extra async validation.
13986 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
13988 Texture
* texture
= texture_ref
->texture();
13989 if (!ValidateAsyncTransfer(
13990 "glAsyncTexSubImage2DCHROMIUM", texture_ref
, target
, level
, pixels
))
13991 return error::kNoError
;
13993 // Guarantee async textures are always 'cleared' as follows:
13994 // - AsyncTexImage2D can not redefine an existing texture
13995 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
13996 // - AsyncTexSubImage2D clears synchronously if not already cleared.
13997 // - Textures become immutable after an async call.
13998 // This way we know in all cases that an async texture is always clear.
13999 if (!texture
->SafeToRenderFrom()) {
14000 if (!texture_manager()->ClearTextureLevel(this, texture_ref
,
14002 LOCAL_SET_GL_ERROR(
14004 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
14005 return error::kNoError
;
14009 // Setup the parameters.
14010 AsyncTexSubImage2DParams tex_params
= {target
, level
, xoffset
, yoffset
,
14011 width
, height
, format
, type
};
14012 AsyncMemoryParams
mem_params(
14013 GetSharedMemoryBuffer(c
.data_shm_id
), c
.data_shm_offset
, data_size
);
14014 AsyncPixelTransferDelegate
* delegate
=
14015 async_pixel_transfer_manager_
->GetPixelTransferDelegate(texture_ref
);
14017 // TODO(epenner): We may want to enforce exclusive use
14018 // of async APIs in which case this should become an error,
14019 // (the texture should have been async defined).
14020 AsyncTexImage2DParams define_params
= {target
, level
,
14022 texture
->GetLevelSize(
14023 target
, level
, &define_params
.width
, &define_params
.height
, nullptr);
14024 texture
->GetLevelType(
14025 target
, level
, &define_params
.type
, &define_params
.internal_format
);
14026 // Set up the async state if needed, and make the texture
14027 // immutable so the async state stays valid.
14028 delegate
= async_pixel_transfer_manager_
->CreatePixelTransferDelegate(
14029 texture_ref
, define_params
);
14030 texture
->SetImmutable(true);
14033 delegate
->AsyncTexSubImage2D(tex_params
, mem_params
);
14034 return error::kNoError
;
14037 error::Error
GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
14038 uint32 immediate_data_size
,
14039 const void* cmd_data
) {
14040 const gles2::cmds::WaitAsyncTexImage2DCHROMIUM
& c
=
14041 *static_cast<const gles2::cmds::WaitAsyncTexImage2DCHROMIUM
*>(cmd_data
);
14042 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
14043 GLenum target
= static_cast<GLenum
>(c
.target
);
14045 if (GL_TEXTURE_2D
!= target
) {
14046 LOCAL_SET_GL_ERROR(
14047 GL_INVALID_ENUM
, "glWaitAsyncTexImage2DCHROMIUM", "target");
14048 return error::kNoError
;
14050 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
14052 if (!texture_ref
) {
14053 LOCAL_SET_GL_ERROR(
14054 GL_INVALID_OPERATION
,
14055 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
14056 return error::kNoError
;
14058 AsyncPixelTransferDelegate
* delegate
=
14059 async_pixel_transfer_manager_
->GetPixelTransferDelegate(texture_ref
);
14061 LOCAL_SET_GL_ERROR(
14062 GL_INVALID_OPERATION
,
14063 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
14064 return error::kNoError
;
14066 delegate
->WaitForTransferCompletion();
14067 ProcessFinishedAsyncTransfers();
14068 return error::kNoError
;
14071 error::Error
GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
14072 uint32 immediate_data_size
,
14073 const void* data
) {
14074 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
14076 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
14077 ProcessFinishedAsyncTransfers();
14078 return error::kNoError
;
14081 error::Error
GLES2DecoderImpl::HandleUniformBlockBinding(
14082 uint32_t immediate_data_size
, const void* cmd_data
) {
14083 if (!unsafe_es3_apis_enabled())
14084 return error::kUnknownCommand
;
14085 const gles2::cmds::UniformBlockBinding
& c
=
14086 *static_cast<const gles2::cmds::UniformBlockBinding
*>(cmd_data
);
14087 GLuint client_id
= c
.program
;
14088 GLuint index
= static_cast<GLuint
>(c
.index
);
14089 GLuint binding
= static_cast<GLuint
>(c
.binding
);
14090 Program
* program
= GetProgramInfoNotShader(
14091 client_id
, "glUniformBlockBinding");
14093 return error::kNoError
;
14095 GLuint service_id
= program
->service_id();
14096 glUniformBlockBinding(service_id
, index
, binding
);
14097 return error::kNoError
;
14100 error::Error
GLES2DecoderImpl::HandleClientWaitSync(
14101 uint32_t immediate_data_size
, const void* cmd_data
) {
14102 if (!unsafe_es3_apis_enabled())
14103 return error::kUnknownCommand
;
14104 const gles2::cmds::ClientWaitSync
& c
=
14105 *static_cast<const gles2::cmds::ClientWaitSync
*>(cmd_data
);
14106 GLuint sync
= static_cast<GLuint
>(c
.sync
);
14107 GLbitfield flags
= static_cast<GLbitfield
>(c
.flags
);
14108 GLuint64 timeout
= GLES2Util::MapTwoUint32ToUint64(c
.timeout_0
, c
.timeout_1
);
14109 typedef cmds::ClientWaitSync::Result Result
;
14110 Result
* result_dst
= GetSharedMemoryAs
<Result
*>(
14111 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result_dst
));
14113 return error::kOutOfBounds
;
14115 if (*result_dst
!= GL_WAIT_FAILED
) {
14116 return error::kInvalidArguments
;
14118 GLsync service_sync
= 0;
14119 if (!group_
->GetSyncServiceId(sync
, &service_sync
)) {
14120 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "ClientWaitSync", "invalid sync");
14121 return error::kNoError
;
14123 *result_dst
= glClientWaitSync(service_sync
, flags
, timeout
);
14124 return error::kNoError
;
14127 error::Error
GLES2DecoderImpl::HandleWaitSync(
14128 uint32_t immediate_data_size
, const void* cmd_data
) {
14129 if (!unsafe_es3_apis_enabled())
14130 return error::kUnknownCommand
;
14131 const gles2::cmds::WaitSync
& c
=
14132 *static_cast<const gles2::cmds::WaitSync
*>(cmd_data
);
14133 GLuint sync
= static_cast<GLuint
>(c
.sync
);
14134 GLbitfield flags
= static_cast<GLbitfield
>(c
.flags
);
14135 GLuint64 timeout
= GLES2Util::MapTwoUint32ToUint64(c
.timeout_0
, c
.timeout_1
);
14136 GLsync service_sync
= 0;
14137 if (!group_
->GetSyncServiceId(sync
, &service_sync
)) {
14138 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "WaitSync", "invalid sync");
14139 return error::kNoError
;
14141 glWaitSync(service_sync
, flags
, timeout
);
14142 return error::kNoError
;
14145 error::Error
GLES2DecoderImpl::HandleGetInternalformativ(
14146 uint32_t immediate_data_size
, const void* cmd_data
) {
14147 if (!unsafe_es3_apis_enabled())
14148 return error::kUnknownCommand
;
14149 const gles2::cmds::GetInternalformativ
& c
=
14150 *static_cast<const gles2::cmds::GetInternalformativ
*>(cmd_data
);
14151 GLenum target
= static_cast<GLenum
>(c
.target
);
14152 GLenum format
= static_cast<GLenum
>(c
.format
);
14153 GLenum pname
= static_cast<GLenum
>(c
.pname
);
14154 if (!validators_
->render_buffer_target
.IsValid(target
)) {
14155 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", target
, "target");
14156 return error::kNoError
;
14158 if (!validators_
->render_buffer_format
.IsValid(format
)) {
14159 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", format
, "format");
14160 return error::kNoError
;
14162 if (!validators_
->internal_format_parameter
.IsValid(pname
)) {
14163 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", pname
, "pname");
14164 return error::kNoError
;
14166 typedef cmds::GetInternalformativ::Result Result
;
14167 GLsizei num_values
= 0;
14169 case GL_NUM_SAMPLE_COUNTS
:
14175 glGetInternalformativ(target
, format
, GL_NUM_SAMPLE_COUNTS
, 1, &value
);
14176 num_values
= static_cast<GLsizei
>(value
);
14183 Result
* result
= GetSharedMemoryAs
<Result
*>(
14184 c
.params_shm_id
, c
.params_shm_offset
, Result::ComputeSize(num_values
));
14185 GLint
* params
= result
? result
->GetData() : NULL
;
14186 if (params
== NULL
) {
14187 return error::kOutOfBounds
;
14189 // Check that the client initialized the result.
14190 if (result
->size
!= 0) {
14191 return error::kInvalidArguments
;
14193 glGetInternalformativ(target
, format
, pname
, num_values
, params
);
14194 result
->SetNumResults(num_values
);
14195 return error::kNoError
;
14198 error::Error
GLES2DecoderImpl::HandleMapBufferRange(
14199 uint32_t immediate_data_size
, const void* cmd_data
) {
14200 if (!unsafe_es3_apis_enabled()) {
14201 return error::kUnknownCommand
;
14203 const gles2::cmds::MapBufferRange
& c
=
14204 *static_cast<const gles2::cmds::MapBufferRange
*>(cmd_data
);
14205 GLenum target
= static_cast<GLenum
>(c
.target
);
14206 GLbitfield access
= static_cast<GLbitfield
>(c
.access
);
14207 GLintptr offset
= static_cast<GLintptr
>(c
.offset
);
14208 GLsizeiptr size
= static_cast<GLsizeiptr
>(c
.size
);
14210 typedef cmds::MapBufferRange::Result Result
;
14211 Result
* result
= GetSharedMemoryAs
<Result
*>(
14212 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
14214 return error::kOutOfBounds
;
14216 if (*result
!= 0) {
14218 return error::kInvalidArguments
;
14221 GetSharedMemoryAs
<int8_t*>(c
.data_shm_id
, c
.data_shm_offset
, size
);
14223 return error::kOutOfBounds
;
14226 GLbitfield mask
= GL_MAP_INVALIDATE_BUFFER_BIT
;
14227 if ((access
& mask
) == mask
) {
14228 // TODO(zmo): To be on the safe side, always map
14229 // GL_MAP_INVALIDATE_BUFFER_BIT to GL_MAP_INVALIDATE_RANGE_BIT.
14230 access
= (access
& ~GL_MAP_INVALIDATE_BUFFER_BIT
);
14231 access
= (access
| GL_MAP_INVALIDATE_RANGE_BIT
);
14233 // TODO(zmo): Always filter out GL_MAP_UNSYNCHRONIZED_BIT to get rid of
14234 // undefined behaviors.
14235 mask
= GL_MAP_READ_BIT
| GL_MAP_UNSYNCHRONIZED_BIT
;
14236 if ((access
& mask
) == mask
) {
14237 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "MapBufferRange",
14238 "incompatible access bits");
14239 return error::kNoError
;
14241 access
= (access
& ~GL_MAP_UNSYNCHRONIZED_BIT
);
14242 if ((access
& GL_MAP_WRITE_BIT
) == GL_MAP_WRITE_BIT
&&
14243 (access
& GL_MAP_INVALIDATE_RANGE_BIT
) == 0) {
14244 access
= (access
| GL_MAP_READ_BIT
);
14246 void* ptr
= glMapBufferRange(target
, offset
, size
, access
);
14247 if (ptr
== nullptr) {
14248 return error::kNoError
;
14250 Buffer
* buffer
= buffer_manager()->GetBufferInfoForTarget(&state_
, target
);
14252 buffer
->SetMappedRange(offset
, size
, access
, ptr
,
14253 GetSharedMemoryBuffer(c
.data_shm_id
));
14254 if ((access
& GL_MAP_INVALIDATE_RANGE_BIT
) == 0) {
14255 memcpy(mem
, ptr
, size
);
14258 return error::kNoError
;
14261 error::Error
GLES2DecoderImpl::HandleUnmapBuffer(
14262 uint32_t immediate_data_size
, const void* cmd_data
) {
14263 if (!unsafe_es3_apis_enabled()) {
14264 return error::kUnknownCommand
;
14266 const gles2::cmds::UnmapBuffer
& c
=
14267 *static_cast<const gles2::cmds::UnmapBuffer
*>(cmd_data
);
14268 GLenum target
= static_cast<GLenum
>(c
.target
);
14270 Buffer
* buffer
= buffer_manager()->GetBufferInfoForTarget(&state_
, target
);
14272 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "UnmapBuffer", "no buffer bound");
14273 return error::kNoError
;
14275 const Buffer::MappedRange
* mapped_range
= buffer
->GetMappedRange();
14276 if (!mapped_range
) {
14277 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "UnmapBuffer",
14278 "buffer is unmapped");
14279 return error::kNoError
;
14281 if ((mapped_range
->access
& GL_MAP_WRITE_BIT
) == 0 ||
14282 (mapped_range
->access
& GL_MAP_FLUSH_EXPLICIT_BIT
) ==
14283 GL_MAP_FLUSH_EXPLICIT_BIT
) {
14284 // If we don't need to write back, or explict flush is required, no copying
14287 void* mem
= mapped_range
->GetShmPointer();
14289 return error::kOutOfBounds
;
14291 DCHECK(mapped_range
->pointer
);
14292 memcpy(mapped_range
->pointer
, mem
, mapped_range
->size
);
14294 buffer
->RemoveMappedRange();
14295 GLboolean rt
= glUnmapBuffer(target
);
14296 if (rt
== GL_FALSE
) {
14297 // At this point, we have already done the necessary validation, so
14298 // GL_FALSE indicates data corruption.
14299 // TODO(zmo): We could redo the map / copy data / unmap to recover, but
14300 // the second unmap could still return GL_FALSE. For now, we simply lose
14301 // the contexts in the share group.
14302 LOG(ERROR
) << "glUnmapBuffer unexpectedly returned GL_FALSE";
14303 // Need to lose current context before broadcasting!
14304 MarkContextLost(error::kGuilty
);
14305 group_
->LoseContexts(error::kInnocent
);
14306 return error::kLostContext
;
14308 return error::kNoError
;
14311 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
14312 TextureRef
* texture_ref
) {
14313 Texture
* texture
= texture_ref
->texture();
14314 DoDidUseTexImageIfNeeded(texture
, texture
->target());
14317 // Note that GL_LOST_CONTEXT is specific to GLES.
14318 // For desktop GL we have to query the reset status proactively.
14319 void GLES2DecoderImpl::OnContextLostError() {
14320 if (!WasContextLost()) {
14321 // Need to lose current context before broadcasting!
14322 CheckResetStatus();
14323 group_
->LoseContexts(error::kUnknown
);
14324 reset_by_robustness_extension_
= true;
14328 void GLES2DecoderImpl::OnOutOfMemoryError() {
14329 if (lose_context_when_out_of_memory_
&& !WasContextLost()) {
14330 error::ContextLostReason other
= error::kOutOfMemory
;
14331 if (CheckResetStatus()) {
14332 other
= error::kUnknown
;
14334 // Need to lose current context before broadcasting!
14335 MarkContextLost(error::kOutOfMemory
);
14337 group_
->LoseContexts(other
);
14341 error::Error
GLES2DecoderImpl::HandleGenPathsCHROMIUM(
14342 uint32 immediate_data_size
,
14343 const void* cmd_data
) {
14344 static const char kFunctionName
[] = "glGenPathsCHROMIUM";
14345 const gles2::cmds::GenPathsCHROMIUM
& c
=
14346 *static_cast<const gles2::cmds::GenPathsCHROMIUM
*>(cmd_data
);
14347 if (!features().chromium_path_rendering
) {
14348 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14349 "function not available");
14350 return error::kNoError
;
14353 GLsizei range
= static_cast<GLsizei
>(c
.range
);
14355 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "range < 0");
14356 return error::kNoError
;
14359 GLuint first_client_id
= static_cast<GLuint
>(c
.first_client_id
);
14360 if (first_client_id
== 0)
14361 return error::kInvalidArguments
;
14364 return error::kNoError
;
14366 if (!GenPathsCHROMIUMHelper(first_client_id
, range
))
14367 return error::kInvalidArguments
;
14369 return error::kNoError
;
14371 error::Error
GLES2DecoderImpl::HandleDeletePathsCHROMIUM(
14372 uint32_t immediate_data_size
,
14373 const void* cmd_data
) {
14374 static const char kFunctionName
[] = "glDeletePathsCHROMIUM";
14375 const gles2::cmds::DeletePathsCHROMIUM
& c
=
14376 *static_cast<const gles2::cmds::DeletePathsCHROMIUM
*>(cmd_data
);
14377 if (!features().chromium_path_rendering
) {
14378 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14379 "function not available");
14380 return error::kNoError
;
14383 GLsizei range
= static_cast<GLsizei
>(c
.range
);
14385 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "range < 0");
14386 return error::kNoError
;
14390 return error::kNoError
;
14392 GLuint first_client_id
= c
.first_client_id
;
14393 // first_client_id can be 0, because non-existing path ids are skipped.
14395 if (!DeletePathsCHROMIUMHelper(first_client_id
, range
))
14396 return error::kInvalidArguments
;
14398 return error::kNoError
;
14401 error::Error
GLES2DecoderImpl::HandlePathCommandsCHROMIUM(
14402 uint32 immediate_data_size
,
14403 const void* cmd_data
) {
14404 static const char kFunctionName
[] = "glPathCommandsCHROMIUM";
14405 const gles2::cmds::PathCommandsCHROMIUM
& c
=
14406 *static_cast<const gles2::cmds::PathCommandsCHROMIUM
*>(cmd_data
);
14407 if (!features().chromium_path_rendering
) {
14408 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14409 "function not available");
14410 return error::kNoError
;
14413 GLuint service_id
= 0;
14414 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
)) {
14415 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14416 "invalid path name");
14417 return error::kNoError
;
14420 GLsizei num_commands
= static_cast<GLsizei
>(c
.numCommands
);
14421 if (num_commands
< 0) {
14422 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "numCommands < 0");
14423 return error::kNoError
;
14426 GLsizei num_coords
= static_cast<uint32
>(c
.numCoords
);
14427 if (num_coords
< 0) {
14428 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "numCoords < 0");
14429 return error::kNoError
;
14432 GLenum coord_type
= static_cast<uint32
>(c
.coordType
);
14433 if (!validators_
->path_coord_type
.IsValid(static_cast<GLint
>(coord_type
))) {
14434 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM
, kFunctionName
, "invalid coordType");
14435 return error::kNoError
;
14438 const GLubyte
* commands
= NULL
;
14439 base::CheckedNumeric
<GLsizei
> num_coords_expected
= 0;
14441 if (num_commands
> 0) {
14442 uint32 commands_shm_id
= static_cast<uint32
>(c
.commands_shm_id
);
14443 uint32 commands_shm_offset
= static_cast<uint32
>(c
.commands_shm_offset
);
14444 if (commands_shm_id
!= 0 || commands_shm_offset
!= 0)
14445 commands
= GetSharedMemoryAs
<const GLubyte
*>(
14446 commands_shm_id
, commands_shm_offset
, num_commands
);
14449 return error::kOutOfBounds
;
14451 for (GLsizei i
= 0; i
< num_commands
; ++i
) {
14452 switch (commands
[i
]) {
14453 case GL_CLOSE_PATH_CHROMIUM
:
14454 // Close has no coords.
14456 case GL_MOVE_TO_CHROMIUM
:
14458 case GL_LINE_TO_CHROMIUM
:
14459 num_coords_expected
+= 2;
14461 case GL_QUADRATIC_CURVE_TO_CHROMIUM
:
14462 num_coords_expected
+= 4;
14464 case GL_CUBIC_CURVE_TO_CHROMIUM
:
14465 num_coords_expected
+= 6;
14467 case GL_CONIC_CURVE_TO_CHROMIUM
:
14468 num_coords_expected
+= 5;
14471 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM
, kFunctionName
, "invalid command");
14472 return error::kNoError
;
14477 if (!num_coords_expected
.IsValid() ||
14478 num_coords
!= num_coords_expected
.ValueOrDie()) {
14479 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14480 "numCoords does not match commands");
14481 return error::kNoError
;
14484 const void* coords
= NULL
;
14486 if (num_coords
> 0) {
14487 uint32 coords_size
= 0;
14488 uint32 coord_type_size
=
14489 GLES2Util::GetGLTypeSizeForPathCoordType(coord_type
);
14490 if (!SafeMultiplyUint32(num_coords
, coord_type_size
, &coords_size
))
14491 return error::kOutOfBounds
;
14493 uint32 coords_shm_id
= static_cast<uint32
>(c
.coords_shm_id
);
14494 uint32 coords_shm_offset
= static_cast<uint32
>(c
.coords_shm_offset
);
14495 if (coords_shm_id
!= 0 || coords_shm_offset
!= 0)
14496 coords
= GetSharedMemoryAs
<const void*>(coords_shm_id
, coords_shm_offset
,
14500 return error::kOutOfBounds
;
14503 glPathCommandsNV(service_id
, num_commands
, commands
, num_coords
, coord_type
,
14506 return error::kNoError
;
14509 error::Error
GLES2DecoderImpl::HandlePathParameterfCHROMIUM(
14510 uint32 immediate_data_size
,
14511 const void* cmd_data
) {
14512 static const char kFunctionName
[] = "glPathParameterfCHROMIUM";
14513 const gles2::cmds::PathParameterfCHROMIUM
& c
=
14514 *static_cast<const gles2::cmds::PathParameterfCHROMIUM
*>(cmd_data
);
14515 if (!features().chromium_path_rendering
) {
14516 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14517 "function not available");
14518 return error::kNoError
;
14520 GLuint service_id
= 0;
14521 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
)) {
14522 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14523 "invalid path name");
14524 return error::kNoError
;
14527 GLenum pname
= static_cast<GLenum
>(c
.pname
);
14528 GLfloat value
= static_cast<GLfloat
>(c
.value
);
14529 bool hasValueError
= false;
14532 case GL_PATH_STROKE_WIDTH_CHROMIUM
:
14533 case GL_PATH_MITER_LIMIT_CHROMIUM
:
14534 hasValueError
= std::isnan(value
) || !std::isfinite(value
) || value
< 0;
14536 case GL_PATH_STROKE_BOUND_CHROMIUM
:
14537 value
= std::max(std::min(1.0f
, value
), 0.0f
);
14539 case GL_PATH_END_CAPS_CHROMIUM
:
14540 hasValueError
= !validators_
->path_parameter_cap_values
.IsValid(
14541 static_cast<GLint
>(value
));
14543 case GL_PATH_JOIN_STYLE_CHROMIUM
:
14544 hasValueError
= !validators_
->path_parameter_join_values
.IsValid(
14545 static_cast<GLint
>(value
));
14548 DCHECK(!validators_
->path_parameter
.IsValid(pname
));
14549 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, pname
, "pname");
14550 return error::kNoError
;
14552 DCHECK(validators_
->path_parameter
.IsValid(pname
));
14554 if (hasValueError
) {
14555 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "value not correct");
14556 return error::kNoError
;
14559 glPathParameterfNV(service_id
, pname
, value
);
14560 return error::kNoError
;
14563 error::Error
GLES2DecoderImpl::HandlePathParameteriCHROMIUM(
14564 uint32 immediate_data_size
,
14565 const void* cmd_data
) {
14566 static const char kFunctionName
[] = "glPathParameteriCHROMIUM";
14567 const gles2::cmds::PathParameteriCHROMIUM
& c
=
14568 *static_cast<const gles2::cmds::PathParameteriCHROMIUM
*>(cmd_data
);
14569 if (!features().chromium_path_rendering
) {
14570 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14571 "function not available");
14572 return error::kNoError
;
14574 GLuint service_id
= 0;
14575 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
)) {
14576 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14577 "invalid path name");
14578 return error::kNoError
;
14581 GLenum pname
= static_cast<GLenum
>(c
.pname
);
14582 GLint value
= static_cast<GLint
>(c
.value
);
14583 bool hasValueError
= false;
14586 case GL_PATH_STROKE_WIDTH_CHROMIUM
:
14587 case GL_PATH_MITER_LIMIT_CHROMIUM
:
14588 hasValueError
= value
< 0;
14590 case GL_PATH_STROKE_BOUND_CHROMIUM
:
14591 value
= std::max(std::min(1, value
), 0);
14593 case GL_PATH_END_CAPS_CHROMIUM
:
14594 hasValueError
= !validators_
->path_parameter_cap_values
.IsValid(value
);
14596 case GL_PATH_JOIN_STYLE_CHROMIUM
:
14597 hasValueError
= !validators_
->path_parameter_join_values
.IsValid(value
);
14600 DCHECK(!validators_
->path_parameter
.IsValid(pname
));
14601 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, pname
, "pname");
14602 return error::kNoError
;
14604 DCHECK(validators_
->path_parameter
.IsValid(pname
));
14606 if (hasValueError
) {
14607 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "value not correct");
14608 return error::kNoError
;
14611 glPathParameteriNV(service_id
, pname
, value
);
14612 return error::kNoError
;
14615 error::Error
GLES2DecoderImpl::HandleStencilFillPathCHROMIUM(
14616 uint32 immediate_data_size
,
14617 const void* cmd_data
) {
14618 static const char kFunctionName
[] = "glStencilFillPathCHROMIUM";
14619 const gles2::cmds::StencilFillPathCHROMIUM
& c
=
14620 *static_cast<const gles2::cmds::StencilFillPathCHROMIUM
*>(cmd_data
);
14621 if (!features().chromium_path_rendering
) {
14622 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14623 "function not available");
14624 return error::kNoError
;
14626 GLenum fill_mode
= static_cast<GLenum
>(c
.fillMode
);
14627 if (!validators_
->path_fill_mode
.IsValid(fill_mode
)) {
14628 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, fill_mode
, "fillMode");
14629 return error::kNoError
;
14631 GLuint mask
= static_cast<GLuint
>(c
.mask
);
14632 if ((fill_mode
== GL_COUNT_UP_CHROMIUM
||
14633 fill_mode
== GL_COUNT_DOWN_CHROMIUM
) &&
14634 GLES2Util::IsNPOT(mask
+ 1)) {
14635 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
,
14636 "mask + 1 is not power of two");
14637 return error::kNoError
;
14639 GLuint service_id
= 0;
14640 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
)) {
14641 // "If /path/ does not name an existing path object, the command does
14642 // nothing (and no error is generated)."
14643 // This holds for other rendering functions, too.
14644 return error::kNoError
;
14647 glStencilFillPathNV(service_id
, fill_mode
, mask
);
14648 return error::kNoError
;
14651 error::Error
GLES2DecoderImpl::HandleStencilStrokePathCHROMIUM(
14652 uint32 immediate_data_size
,
14653 const void* cmd_data
) {
14654 static const char kFunctionName
[] = "glStencilStrokePathCHROMIUM";
14655 const gles2::cmds::StencilStrokePathCHROMIUM
& c
=
14656 *static_cast<const gles2::cmds::StencilStrokePathCHROMIUM
*>(cmd_data
);
14657 if (!features().chromium_path_rendering
) {
14658 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14659 "function not available");
14660 return error::kNoError
;
14662 GLuint service_id
= 0;
14663 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
)) {
14664 return error::kNoError
;
14666 GLint reference
= static_cast<GLint
>(c
.reference
);
14667 GLuint mask
= static_cast<GLuint
>(c
.mask
);
14669 glStencilStrokePathNV(service_id
, reference
, mask
);
14670 return error::kNoError
;
14673 error::Error
GLES2DecoderImpl::HandleCoverFillPathCHROMIUM(
14674 uint32 immediate_data_size
,
14675 const void* cmd_data
) {
14676 static const char kFunctionName
[] = "glCoverFillPathCHROMIUM";
14677 const gles2::cmds::CoverFillPathCHROMIUM
& c
=
14678 *static_cast<const gles2::cmds::CoverFillPathCHROMIUM
*>(cmd_data
);
14679 if (!features().chromium_path_rendering
) {
14680 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14681 "function not available");
14682 return error::kNoError
;
14684 GLenum cover_mode
= static_cast<GLenum
>(c
.coverMode
);
14685 if (!validators_
->path_cover_mode
.IsValid(cover_mode
)) {
14686 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, cover_mode
, "coverMode");
14687 return error::kNoError
;
14689 GLuint service_id
= 0;
14690 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
))
14691 return error::kNoError
;
14694 glCoverFillPathNV(service_id
, cover_mode
);
14695 return error::kNoError
;
14698 error::Error
GLES2DecoderImpl::HandleCoverStrokePathCHROMIUM(
14699 uint32 immediate_data_size
,
14700 const void* cmd_data
) {
14701 static const char kFunctionName
[] = "glCoverStrokePathCHROMIUM";
14702 const gles2::cmds::CoverStrokePathCHROMIUM
& c
=
14703 *static_cast<const gles2::cmds::CoverStrokePathCHROMIUM
*>(cmd_data
);
14704 if (!features().chromium_path_rendering
) {
14705 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14706 "function not available");
14707 return error::kNoError
;
14709 GLenum cover_mode
= static_cast<GLenum
>(c
.coverMode
);
14710 if (!validators_
->path_cover_mode
.IsValid(cover_mode
)) {
14711 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, cover_mode
, "coverMode");
14712 return error::kNoError
;
14714 GLuint service_id
= 0;
14715 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
))
14716 return error::kNoError
;
14719 glCoverStrokePathNV(service_id
, cover_mode
);
14720 return error::kNoError
;
14723 error::Error
GLES2DecoderImpl::HandleStencilThenCoverFillPathCHROMIUM(
14724 uint32 immediate_data_size
,
14725 const void* cmd_data
) {
14726 static const char kFunctionName
[] = "glStencilThenCoverFillPathCHROMIUM";
14727 const gles2::cmds::StencilThenCoverFillPathCHROMIUM
& c
=
14728 *static_cast<const gles2::cmds::StencilThenCoverFillPathCHROMIUM
*>(
14730 if (!features().chromium_path_rendering
) {
14731 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14732 "function not available");
14733 return error::kNoError
;
14735 GLenum fill_mode
= static_cast<GLenum
>(c
.fillMode
);
14736 if (!validators_
->path_fill_mode
.IsValid(fill_mode
)) {
14737 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, fill_mode
, "fillMode");
14738 return error::kNoError
;
14740 GLuint mask
= static_cast<GLuint
>(c
.mask
);
14741 if ((fill_mode
== GL_COUNT_UP_CHROMIUM
||
14742 fill_mode
== GL_COUNT_DOWN_CHROMIUM
) &&
14743 GLES2Util::IsNPOT(mask
+ 1)) {
14744 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
,
14745 "mask + 1 is not power of two");
14746 return error::kNoError
;
14748 GLenum cover_mode
= static_cast<GLenum
>(c
.coverMode
);
14749 if (!validators_
->path_cover_mode
.IsValid(cover_mode
)) {
14750 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, cover_mode
, "coverMode");
14751 return error::kNoError
;
14753 GLuint service_id
= 0;
14754 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
))
14755 return error::kNoError
;
14758 glStencilThenCoverFillPathNV(service_id
, fill_mode
, mask
, cover_mode
);
14759 return error::kNoError
;
14762 error::Error
GLES2DecoderImpl::HandleStencilThenCoverStrokePathCHROMIUM(
14763 uint32 immediate_data_size
,
14764 const void* cmd_data
) {
14765 static const char kFunctionName
[] = "glStencilThenCoverStrokePathCHROMIUM";
14766 const gles2::cmds::StencilThenCoverStrokePathCHROMIUM
& c
=
14767 *static_cast<const gles2::cmds::StencilThenCoverStrokePathCHROMIUM
*>(
14769 if (!features().chromium_path_rendering
) {
14770 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14771 "function not available");
14772 return error::kNoError
;
14774 GLenum cover_mode
= static_cast<GLenum
>(c
.coverMode
);
14775 if (!validators_
->path_cover_mode
.IsValid(cover_mode
)) {
14776 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, cover_mode
, "coverMode");
14777 return error::kNoError
;
14779 GLuint service_id
= 0;
14780 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
))
14781 return error::kNoError
;
14783 GLint reference
= static_cast<GLint
>(c
.reference
);
14784 GLuint mask
= static_cast<GLuint
>(c
.mask
);
14786 glStencilThenCoverStrokePathNV(service_id
, reference
, mask
, cover_mode
);
14787 return error::kNoError
;
14790 // Include the auto-generated part of this file. We split this because it means
14791 // we can easily edit the non-auto generated parts right here in this file
14792 // instead of having to edit some template or the code generator.
14793 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
14795 } // namespace gles2