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
.max_copy_texture_chromium_size
=
3202 feature_info_
->workarounds().max_copy_texture_chromium_size
;
3203 caps
.render_buffer_format_bgra8888
=
3204 feature_info_
->feature_flags().ext_render_buffer_format_bgra8888
;
3205 caps
.occlusion_query_boolean
=
3206 feature_info_
->feature_flags().occlusion_query_boolean
;
3207 caps
.timer_queries
=
3208 query_manager_
->GPUTimingAvailable();
3212 void GLES2DecoderImpl::UpdateCapabilities() {
3213 util_
.set_num_compressed_texture_formats(
3214 validators_
->compressed_texture_format
.GetValues().size());
3215 util_
.set_num_shader_binary_formats(
3216 validators_
->shader_binary_format
.GetValues().size());
3219 bool GLES2DecoderImpl::InitializeShaderTranslator() {
3220 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
3222 if (!use_shader_translator_
) {
3225 ShBuiltInResources resources
;
3226 ShInitBuiltInResources(&resources
);
3227 resources
.MaxVertexAttribs
= group_
->max_vertex_attribs();
3228 resources
.MaxVertexUniformVectors
=
3229 group_
->max_vertex_uniform_vectors();
3230 resources
.MaxVaryingVectors
= group_
->max_varying_vectors();
3231 resources
.MaxVertexTextureImageUnits
=
3232 group_
->max_vertex_texture_image_units();
3233 resources
.MaxCombinedTextureImageUnits
= group_
->max_texture_units();
3234 resources
.MaxTextureImageUnits
= group_
->max_texture_image_units();
3235 resources
.MaxFragmentUniformVectors
=
3236 group_
->max_fragment_uniform_vectors();
3237 resources
.MaxDrawBuffers
= group_
->max_draw_buffers();
3238 resources
.MaxExpressionComplexity
= 256;
3239 resources
.MaxCallStackDepth
= 256;
3241 GLint range
[2] = { 0, 0 };
3242 GLint precision
= 0;
3243 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER
, GL_HIGH_FLOAT
,
3245 resources
.FragmentPrecisionHigh
=
3246 PrecisionMeetsSpecForHighpFloat(range
[0], range
[1], precision
);
3248 if (IsWebGLContext()) {
3249 resources
.OES_standard_derivatives
= derivatives_explicitly_enabled_
;
3250 resources
.EXT_frag_depth
= frag_depth_explicitly_enabled_
;
3251 resources
.EXT_draw_buffers
= draw_buffers_explicitly_enabled_
;
3252 if (!draw_buffers_explicitly_enabled_
)
3253 resources
.MaxDrawBuffers
= 1;
3254 resources
.EXT_shader_texture_lod
= shader_texture_lod_explicitly_enabled_
;
3255 resources
.NV_draw_buffers
=
3256 draw_buffers_explicitly_enabled_
&& features().nv_draw_buffers
;
3258 resources
.OES_standard_derivatives
=
3259 features().oes_standard_derivatives
? 1 : 0;
3260 resources
.ARB_texture_rectangle
=
3261 features().arb_texture_rectangle
? 1 : 0;
3262 resources
.OES_EGL_image_external
=
3263 features().oes_egl_image_external
? 1 : 0;
3264 resources
.EXT_draw_buffers
=
3265 features().ext_draw_buffers
? 1 : 0;
3266 resources
.EXT_frag_depth
=
3267 features().ext_frag_depth
? 1 : 0;
3268 resources
.EXT_shader_texture_lod
=
3269 features().ext_shader_texture_lod
? 1 : 0;
3270 resources
.NV_draw_buffers
=
3271 features().nv_draw_buffers
? 1 : 0;
3274 ShShaderSpec shader_spec
;
3275 if (IsWebGLContext()) {
3276 shader_spec
= webgl_version_
== 2 ? SH_WEBGL2_SPEC
: SH_WEBGL_SPEC
;
3278 shader_spec
= unsafe_es3_apis_enabled() ? SH_GLES3_SPEC
: SH_GLES2_SPEC
;
3281 if ((shader_spec
== SH_WEBGL_SPEC
|| shader_spec
== SH_WEBGL2_SPEC
) &&
3282 features().enable_shader_name_hashing
)
3283 resources
.HashFunction
= &CityHash64
;
3285 resources
.HashFunction
= NULL
;
3287 int driver_bug_workarounds
= 0;
3288 if (workarounds().needs_glsl_built_in_function_emulation
)
3289 driver_bug_workarounds
|= SH_EMULATE_BUILT_IN_FUNCTIONS
;
3290 if (workarounds().init_gl_position_in_vertex_shader
)
3291 driver_bug_workarounds
|= SH_INIT_GL_POSITION
;
3292 if (workarounds().unfold_short_circuit_as_ternary_operation
)
3293 driver_bug_workarounds
|= SH_UNFOLD_SHORT_CIRCUIT
;
3294 if (workarounds().init_varyings_without_static_use
)
3295 driver_bug_workarounds
|= SH_INIT_VARYINGS_WITHOUT_STATIC_USE
;
3296 if (workarounds().unroll_for_loop_with_sampler_array_index
)
3297 driver_bug_workarounds
|= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX
;
3298 if (workarounds().scalarize_vec_and_mat_constructor_args
)
3299 driver_bug_workarounds
|= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS
;
3300 if (workarounds().regenerate_struct_names
)
3301 driver_bug_workarounds
|= SH_REGENERATE_STRUCT_NAMES
;
3302 if (workarounds().remove_pow_with_constant_exponent
)
3303 driver_bug_workarounds
|= SH_REMOVE_POW_WITH_CONSTANT_EXPONENT
;
3305 if (base::CommandLine::InitializedForCurrentProcess() &&
3306 base::CommandLine::ForCurrentProcess()->HasSwitch(
3307 switches::kEmulateShaderPrecision
))
3308 resources
.WEBGL_debug_shader_precision
= true;
3310 ShShaderOutput shader_output_language
=
3311 ShaderTranslator::GetShaderOutputLanguageForContext(
3312 feature_info_
->gl_version_info());
3314 vertex_translator_
= shader_translator_cache()->GetTranslator(
3315 GL_VERTEX_SHADER
, shader_spec
, &resources
, shader_output_language
,
3316 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
3317 if (!vertex_translator_
.get()) {
3318 LOG(ERROR
) << "Could not initialize vertex shader translator.";
3323 fragment_translator_
= shader_translator_cache()->GetTranslator(
3324 GL_FRAGMENT_SHADER
, shader_spec
, &resources
, shader_output_language
,
3325 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
3326 if (!fragment_translator_
.get()) {
3327 LOG(ERROR
) << "Could not initialize fragment shader translator.";
3334 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n
, const GLuint
* client_ids
) {
3335 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3336 if (GetBuffer(client_ids
[ii
])) {
3340 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3341 glGenBuffersARB(n
, service_ids
.get());
3342 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3343 CreateBuffer(client_ids
[ii
], service_ids
[ii
]);
3348 bool GLES2DecoderImpl::GenFramebuffersHelper(
3349 GLsizei n
, const GLuint
* client_ids
) {
3350 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3351 if (GetFramebuffer(client_ids
[ii
])) {
3355 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3356 glGenFramebuffersEXT(n
, service_ids
.get());
3357 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3358 CreateFramebuffer(client_ids
[ii
], service_ids
[ii
]);
3363 bool GLES2DecoderImpl::GenRenderbuffersHelper(
3364 GLsizei n
, const GLuint
* client_ids
) {
3365 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3366 if (GetRenderbuffer(client_ids
[ii
])) {
3370 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3371 glGenRenderbuffersEXT(n
, service_ids
.get());
3372 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3373 CreateRenderbuffer(client_ids
[ii
], service_ids
[ii
]);
3378 bool GLES2DecoderImpl::GenValuebuffersCHROMIUMHelper(GLsizei n
,
3379 const GLuint
* client_ids
) {
3380 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3381 if (GetValuebuffer(client_ids
[ii
])) {
3385 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3386 CreateValuebuffer(client_ids
[ii
]);
3391 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n
, const GLuint
* client_ids
) {
3392 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3393 if (GetTexture(client_ids
[ii
])) {
3397 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3398 glGenTextures(n
, service_ids
.get());
3399 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3400 CreateTexture(client_ids
[ii
], service_ids
[ii
]);
3405 bool GLES2DecoderImpl::GenPathsCHROMIUMHelper(GLuint first_client_id
,
3407 GLuint last_client_id
;
3408 if (!SafeAddUint32(first_client_id
, range
- 1, &last_client_id
))
3411 if (path_manager()->HasPathsInRange(first_client_id
, last_client_id
))
3414 GLuint first_service_id
= glGenPathsNV(range
);
3415 if (first_service_id
== 0) {
3416 // We have to fail the connection here, because client has already
3417 // succeeded in allocating the ids. This happens if we allocate
3418 // the whole path id space (two allocations of 0x7FFFFFFF paths, for
3422 // GenPathsNV does not wrap.
3423 DCHECK(first_service_id
+ range
- 1 >= first_service_id
);
3425 path_manager()->CreatePathRange(first_client_id
, last_client_id
,
3431 bool GLES2DecoderImpl::DeletePathsCHROMIUMHelper(GLuint first_client_id
,
3433 GLuint last_client_id
;
3434 if (!SafeAddUint32(first_client_id
, range
- 1, &last_client_id
))
3437 path_manager()->RemovePaths(first_client_id
, last_client_id
);
3441 void GLES2DecoderImpl::DeleteBuffersHelper(
3442 GLsizei n
, const GLuint
* client_ids
) {
3443 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3444 Buffer
* buffer
= GetBuffer(client_ids
[ii
]);
3445 if (buffer
&& !buffer
->IsDeleted()) {
3446 buffer
->RemoveMappedRange();
3447 state_
.RemoveBoundBuffer(buffer
);
3448 RemoveBuffer(client_ids
[ii
]);
3453 void GLES2DecoderImpl::DeleteFramebuffersHelper(
3454 GLsizei n
, const GLuint
* client_ids
) {
3455 bool supports_separate_framebuffer_binds
=
3456 features().chromium_framebuffer_multisample
;
3458 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3459 Framebuffer
* framebuffer
=
3460 GetFramebuffer(client_ids
[ii
]);
3461 if (framebuffer
&& !framebuffer
->IsDeleted()) {
3462 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
3463 GLenum target
= supports_separate_framebuffer_binds
?
3464 GL_DRAW_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
3466 // Unbind attachments on FBO before deletion.
3467 if (workarounds().unbind_attachments_on_bound_render_fbo_delete
)
3468 framebuffer
->DoUnbindGLAttachmentsForWorkaround(target
);
3470 glBindFramebufferEXT(target
, GetBackbufferServiceId());
3471 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
3472 framebuffer_state_
.clear_state_dirty
= true;
3474 if (framebuffer
== framebuffer_state_
.bound_read_framebuffer
.get()) {
3475 framebuffer_state_
.bound_read_framebuffer
= NULL
;
3476 GLenum target
= supports_separate_framebuffer_binds
?
3477 GL_READ_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
3478 glBindFramebufferEXT(target
, GetBackbufferServiceId());
3481 RemoveFramebuffer(client_ids
[ii
]);
3486 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
3487 GLsizei n
, const GLuint
* client_ids
) {
3488 bool supports_separate_framebuffer_binds
=
3489 features().chromium_framebuffer_multisample
;
3490 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3491 Renderbuffer
* renderbuffer
=
3492 GetRenderbuffer(client_ids
[ii
]);
3493 if (renderbuffer
&& !renderbuffer
->IsDeleted()) {
3494 if (state_
.bound_renderbuffer
.get() == renderbuffer
) {
3495 state_
.bound_renderbuffer
= NULL
;
3497 // Unbind from current framebuffers.
3498 if (supports_separate_framebuffer_binds
) {
3499 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
3500 framebuffer_state_
.bound_read_framebuffer
3501 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT
, renderbuffer
);
3503 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3504 framebuffer_state_
.bound_draw_framebuffer
3505 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT
, renderbuffer
);
3508 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3509 framebuffer_state_
.bound_draw_framebuffer
3510 ->UnbindRenderbuffer(GL_FRAMEBUFFER
, renderbuffer
);
3513 framebuffer_state_
.clear_state_dirty
= true;
3514 RemoveRenderbuffer(client_ids
[ii
]);
3519 void GLES2DecoderImpl::DeleteValuebuffersCHROMIUMHelper(
3521 const GLuint
* client_ids
) {
3522 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3523 Valuebuffer
* valuebuffer
= GetValuebuffer(client_ids
[ii
]);
3525 if (state_
.bound_valuebuffer
.get() == valuebuffer
) {
3526 state_
.bound_valuebuffer
= NULL
;
3528 RemoveValuebuffer(client_ids
[ii
]);
3533 void GLES2DecoderImpl::DeleteTexturesHelper(
3534 GLsizei n
, const GLuint
* client_ids
) {
3535 bool supports_separate_framebuffer_binds
=
3536 features().chromium_framebuffer_multisample
;
3537 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3538 TextureRef
* texture_ref
= GetTexture(client_ids
[ii
]);
3540 Texture
* texture
= texture_ref
->texture();
3541 if (texture
->IsAttachedToFramebuffer()) {
3542 framebuffer_state_
.clear_state_dirty
= true;
3544 // Unbind texture_ref from texture_ref units.
3545 for (size_t jj
= 0; jj
< state_
.texture_units
.size(); ++jj
) {
3546 state_
.texture_units
[jj
].Unbind(texture_ref
);
3548 // Unbind from current framebuffers.
3549 if (supports_separate_framebuffer_binds
) {
3550 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
3551 framebuffer_state_
.bound_read_framebuffer
3552 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT
, texture_ref
);
3554 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3555 framebuffer_state_
.bound_draw_framebuffer
3556 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT
, texture_ref
);
3559 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3560 framebuffer_state_
.bound_draw_framebuffer
3561 ->UnbindTexture(GL_FRAMEBUFFER
, texture_ref
);
3564 #if defined(OS_MACOSX)
3565 GLuint service_id
= texture
->service_id();
3566 if (texture
->target() == GL_TEXTURE_RECTANGLE_ARB
) {
3567 ReleaseIOSurfaceForTexture(service_id
);
3570 RemoveTexture(client_ids
[ii
]);
3575 // } // anonymous namespace
3577 bool GLES2DecoderImpl::MakeCurrent() {
3578 if (!context_
.get())
3581 if (WasContextLost()) {
3582 LOG(ERROR
) << " GLES2DecoderImpl: Trying to make lost context current.";
3586 if (!context_
->MakeCurrent(surface_
.get())) {
3587 LOG(ERROR
) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3588 MarkContextLost(error::kMakeCurrentFailed
);
3589 group_
->LoseContexts(error::kUnknown
);
3593 if (CheckResetStatus()) {
3595 << " GLES2DecoderImpl: Context reset detected after MakeCurrent.";
3596 group_
->LoseContexts(error::kUnknown
);
3600 ProcessFinishedAsyncTransfers();
3602 // Rebind the FBO if it was unbound by the context.
3603 if (workarounds().unbind_fbo_on_context_switch
)
3604 RestoreFramebufferBindings();
3606 framebuffer_state_
.clear_state_dirty
= true;
3611 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3612 ProcessPendingReadPixels(false);
3613 if (engine() && query_manager_
.get())
3614 query_manager_
->ProcessPendingTransferQueries();
3616 // TODO(epenner): Is there a better place to do this?
3617 // This needs to occur before we execute any batch of commands
3618 // from the client, as the client may have recieved an async
3619 // completion while issuing those commands.
3620 // "DidFlushStart" would be ideal if we had such a callback.
3621 async_pixel_transfer_manager_
->BindCompletedAsyncTransfers();
3624 static void RebindCurrentFramebuffer(
3626 Framebuffer
* framebuffer
,
3627 GLuint back_buffer_service_id
) {
3628 GLuint framebuffer_id
= framebuffer
? framebuffer
->service_id() : 0;
3630 if (framebuffer_id
== 0) {
3631 framebuffer_id
= back_buffer_service_id
;
3634 glBindFramebufferEXT(target
, framebuffer_id
);
3637 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3638 framebuffer_state_
.clear_state_dirty
= true;
3640 if (!features().chromium_framebuffer_multisample
) {
3641 RebindCurrentFramebuffer(
3643 framebuffer_state_
.bound_draw_framebuffer
.get(),
3644 GetBackbufferServiceId());
3646 RebindCurrentFramebuffer(
3647 GL_READ_FRAMEBUFFER_EXT
,
3648 framebuffer_state_
.bound_read_framebuffer
.get(),
3649 GetBackbufferServiceId());
3650 RebindCurrentFramebuffer(
3651 GL_DRAW_FRAMEBUFFER_EXT
,
3652 framebuffer_state_
.bound_draw_framebuffer
.get(),
3653 GetBackbufferServiceId());
3658 bool GLES2DecoderImpl::CheckFramebufferValid(
3659 Framebuffer
* framebuffer
,
3660 GLenum target
, const char* func_name
) {
3664 if (backbuffer_needs_clear_bits_
) {
3665 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3666 offscreen_target_color_format_
) & 0x0008) != 0 ? 0 : 1.f
);
3667 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
3669 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
3670 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
3672 state_
.SetDeviceDepthMask(GL_TRUE
);
3673 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
3674 bool reset_draw_buffer
= false;
3675 if ((backbuffer_needs_clear_bits_
& GL_COLOR_BUFFER_BIT
) != 0 &&
3676 back_buffer_draw_buffer_
== GL_NONE
) {
3677 reset_draw_buffer
= true;
3678 GLenum buf
= GL_BACK
;
3679 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3680 buf
= GL_COLOR_ATTACHMENT0
;
3681 glDrawBuffersARB(1, &buf
);
3683 glClear(backbuffer_needs_clear_bits_
);
3684 if (reset_draw_buffer
) {
3685 GLenum buf
= GL_NONE
;
3686 glDrawBuffersARB(1, &buf
);
3688 backbuffer_needs_clear_bits_
= 0;
3689 RestoreClearState();
3694 if (framebuffer_manager()->IsComplete(framebuffer
)) {
3698 GLenum completeness
= framebuffer
->IsPossiblyComplete();
3699 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
3701 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
, "framebuffer incomplete");
3705 // Are all the attachments cleared?
3706 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3707 texture_manager()->HaveUnclearedMips()) {
3708 if (!framebuffer
->IsCleared()) {
3709 // Can we clear them?
3710 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3711 GL_FRAMEBUFFER_COMPLETE
) {
3713 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3714 "framebuffer incomplete (clear)");
3717 ClearUnclearedAttachments(target
, framebuffer
);
3721 if (!framebuffer_manager()->IsComplete(framebuffer
)) {
3722 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3723 GL_FRAMEBUFFER_COMPLETE
) {
3725 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3726 "framebuffer incomplete (check)");
3729 framebuffer_manager()->MarkAsComplete(framebuffer
);
3732 // NOTE: At this point we don't know if the framebuffer is complete but
3733 // we DO know that everything that needs to be cleared has been cleared.
3737 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name
) {
3738 if (!features().chromium_framebuffer_multisample
) {
3739 bool valid
= CheckFramebufferValid(
3740 framebuffer_state_
.bound_draw_framebuffer
.get(), GL_FRAMEBUFFER_EXT
,
3748 return CheckFramebufferValid(framebuffer_state_
.bound_draw_framebuffer
.get(),
3749 GL_DRAW_FRAMEBUFFER_EXT
,
3751 CheckFramebufferValid(framebuffer_state_
.bound_read_framebuffer
.get(),
3752 GL_READ_FRAMEBUFFER_EXT
,
3756 bool GLES2DecoderImpl::CheckBoundReadFramebufferColorAttachment(
3757 const char* func_name
) {
3758 Framebuffer
* framebuffer
= features().chromium_framebuffer_multisample
?
3759 framebuffer_state_
.bound_read_framebuffer
.get() :
3760 framebuffer_state_
.bound_draw_framebuffer
.get();
3763 if (framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
) == NULL
) {
3765 GL_INVALID_OPERATION
, func_name
, "no color image attached");
3771 bool GLES2DecoderImpl::FormsTextureCopyingFeedbackLoop(
3772 TextureRef
* texture
, GLint level
) {
3773 Framebuffer
* framebuffer
= features().chromium_framebuffer_multisample
?
3774 framebuffer_state_
.bound_read_framebuffer
.get() :
3775 framebuffer_state_
.bound_draw_framebuffer
.get();
3778 const Framebuffer::Attachment
* attachment
= framebuffer
->GetAttachment(
3779 GL_COLOR_ATTACHMENT0
);
3782 return attachment
->FormsFeedbackLoop(texture
, level
);
3785 gfx::Size
GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3786 Framebuffer
* framebuffer
=
3787 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3788 if (framebuffer
!= NULL
) {
3789 const Framebuffer::Attachment
* attachment
=
3790 framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
);
3792 return gfx::Size(attachment
->width(), attachment
->height());
3794 return gfx::Size(0, 0);
3795 } else if (offscreen_target_frame_buffer_
.get()) {
3796 return offscreen_size_
;
3798 return surface_
->GetSize();
3802 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3803 Framebuffer
* framebuffer
=
3804 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3806 return framebuffer
->GetReadBufferTextureType();
3807 } else { // Back buffer.
3808 if (back_buffer_read_buffer_
== GL_NONE
)
3810 return GL_UNSIGNED_BYTE
;
3814 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3815 Framebuffer
* framebuffer
=
3816 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3818 return framebuffer
->GetReadBufferInternalFormat();
3819 } else { // Back buffer.
3820 if (back_buffer_read_buffer_
== GL_NONE
)
3822 if (offscreen_target_frame_buffer_
.get()) {
3823 return offscreen_target_color_format_
;
3825 return back_buffer_color_format_
;
3829 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3830 if (!offscreen_saved_color_texture_info_
.get())
3832 GLenum target
= offscreen_saved_color_texture_info_
->texture()->target();
3833 glBindTexture(target
, offscreen_saved_color_texture_info_
->service_id());
3834 texture_manager()->SetLevelInfo(
3835 offscreen_saved_color_texture_info_
.get(), GL_TEXTURE_2D
,
3837 GL_RGBA
, offscreen_size_
.width(), offscreen_size_
.height(),
3840 GL_RGBA
, GL_UNSIGNED_BYTE
, gfx::Rect(offscreen_size_
));
3841 texture_manager()->SetParameteri(
3842 "UpdateParentTextureInfo",
3844 offscreen_saved_color_texture_info_
.get(),
3845 GL_TEXTURE_MAG_FILTER
,
3847 texture_manager()->SetParameteri(
3848 "UpdateParentTextureInfo",
3850 offscreen_saved_color_texture_info_
.get(),
3851 GL_TEXTURE_MIN_FILTER
,
3853 texture_manager()->SetParameteri(
3854 "UpdateParentTextureInfo",
3856 offscreen_saved_color_texture_info_
.get(),
3859 texture_manager()->SetParameteri(
3860 "UpdateParentTextureInfo",
3862 offscreen_saved_color_texture_info_
.get(),
3865 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
3867 glBindTexture(target
, texture_ref
? texture_ref
->service_id() : 0);
3870 void GLES2DecoderImpl::SetResizeCallback(
3871 const base::Callback
<void(gfx::Size
, float)>& callback
) {
3872 resize_callback_
= callback
;
3875 Logger
* GLES2DecoderImpl::GetLogger() {
3879 void GLES2DecoderImpl::BeginDecoding() {
3880 gpu_tracer_
->BeginDecoding();
3881 gpu_trace_commands_
= gpu_tracer_
->IsTracing() && *gpu_decoder_category_
;
3882 gpu_debug_commands_
= log_commands() || debug() || gpu_trace_commands_
||
3883 (*cb_command_trace_category_
!= 0);
3884 query_manager_
->ProcessFrameBeginUpdates();
3887 void GLES2DecoderImpl::EndDecoding() {
3888 gpu_tracer_
->EndDecoding();
3891 ErrorState
* GLES2DecoderImpl::GetErrorState() {
3892 return state_
.GetErrorState();
3895 void GLES2DecoderImpl::SetShaderCacheCallback(
3896 const ShaderCacheCallback
& callback
) {
3897 shader_cache_callback_
= callback
;
3900 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3901 const WaitSyncPointCallback
& callback
) {
3902 wait_sync_point_callback_
= callback
;
3905 AsyncPixelTransferManager
*
3906 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3907 return async_pixel_transfer_manager_
.get();
3910 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3911 async_pixel_transfer_manager_
.reset();
3914 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3915 AsyncPixelTransferManager
* manager
) {
3916 async_pixel_transfer_manager_
= make_scoped_ptr(manager
);
3919 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id
,
3920 uint32
* service_texture_id
) {
3921 TextureRef
* texture_ref
= texture_manager()->GetTexture(client_texture_id
);
3923 *service_texture_id
= texture_ref
->service_id();
3929 uint32
GLES2DecoderImpl::GetTextureUploadCount() {
3930 return texture_state_
.texture_upload_count
+
3931 async_pixel_transfer_manager_
->GetTextureUploadCount();
3934 base::TimeDelta
GLES2DecoderImpl::GetTotalTextureUploadTime() {
3935 return texture_state_
.total_texture_upload_time
+
3936 async_pixel_transfer_manager_
->GetTotalTextureUploadTime();
3939 base::TimeDelta
GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3940 return total_processing_commands_time_
;
3943 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time
) {
3944 total_processing_commands_time_
+= time
;
3947 void GLES2DecoderImpl::Destroy(bool have_context
) {
3951 DCHECK(!have_context
|| context_
->IsCurrent(NULL
));
3953 // Unbind everything.
3954 state_
.vertex_attrib_manager
= NULL
;
3955 state_
.default_vertex_attrib_manager
= NULL
;
3956 state_
.texture_units
.clear();
3957 state_
.bound_array_buffer
= NULL
;
3958 state_
.bound_copy_read_buffer
= NULL
;
3959 state_
.bound_copy_write_buffer
= NULL
;
3960 state_
.bound_pixel_pack_buffer
= NULL
;
3961 state_
.bound_pixel_unpack_buffer
= NULL
;
3962 state_
.bound_transform_feedback_buffer
= NULL
;
3963 state_
.bound_uniform_buffer
= NULL
;
3964 framebuffer_state_
.bound_read_framebuffer
= NULL
;
3965 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
3966 state_
.bound_renderbuffer
= NULL
;
3967 state_
.bound_valuebuffer
= NULL
;
3969 if (offscreen_saved_color_texture_info_
.get()) {
3970 DCHECK(offscreen_target_color_texture_
);
3971 DCHECK_EQ(offscreen_saved_color_texture_info_
->service_id(),
3972 offscreen_saved_color_texture_
->id());
3973 offscreen_saved_color_texture_
->Invalidate();
3974 offscreen_saved_color_texture_info_
= NULL
;
3977 if (copy_texture_CHROMIUM_
.get()) {
3978 copy_texture_CHROMIUM_
->Destroy();
3979 copy_texture_CHROMIUM_
.reset();
3982 clear_framebuffer_blit_
.reset();
3984 if (state_
.current_program
.get()) {
3985 program_manager()->UnuseProgram(shader_manager(),
3986 state_
.current_program
.get());
3989 if (attrib_0_buffer_id_
) {
3990 glDeleteBuffersARB(1, &attrib_0_buffer_id_
);
3992 if (fixed_attrib_buffer_id_
) {
3993 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_
);
3996 if (validation_texture_
) {
3997 glDeleteTextures(1, &validation_texture_
);
3998 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_
);
3999 glDeleteFramebuffersEXT(1, &validation_fbo_
);
4002 if (offscreen_target_frame_buffer_
.get())
4003 offscreen_target_frame_buffer_
->Destroy();
4004 if (offscreen_target_color_texture_
.get())
4005 offscreen_target_color_texture_
->Destroy();
4006 if (offscreen_target_color_render_buffer_
.get())
4007 offscreen_target_color_render_buffer_
->Destroy();
4008 if (offscreen_target_depth_render_buffer_
.get())
4009 offscreen_target_depth_render_buffer_
->Destroy();
4010 if (offscreen_target_stencil_render_buffer_
.get())
4011 offscreen_target_stencil_render_buffer_
->Destroy();
4012 if (offscreen_saved_frame_buffer_
.get())
4013 offscreen_saved_frame_buffer_
->Destroy();
4014 if (offscreen_saved_color_texture_
.get())
4015 offscreen_saved_color_texture_
->Destroy();
4016 if (offscreen_resolved_frame_buffer_
.get())
4017 offscreen_resolved_frame_buffer_
->Destroy();
4018 if (offscreen_resolved_color_texture_
.get())
4019 offscreen_resolved_color_texture_
->Destroy();
4021 if (offscreen_target_frame_buffer_
.get())
4022 offscreen_target_frame_buffer_
->Invalidate();
4023 if (offscreen_target_color_texture_
.get())
4024 offscreen_target_color_texture_
->Invalidate();
4025 if (offscreen_target_color_render_buffer_
.get())
4026 offscreen_target_color_render_buffer_
->Invalidate();
4027 if (offscreen_target_depth_render_buffer_
.get())
4028 offscreen_target_depth_render_buffer_
->Invalidate();
4029 if (offscreen_target_stencil_render_buffer_
.get())
4030 offscreen_target_stencil_render_buffer_
->Invalidate();
4031 if (offscreen_saved_frame_buffer_
.get())
4032 offscreen_saved_frame_buffer_
->Invalidate();
4033 if (offscreen_saved_color_texture_
.get())
4034 offscreen_saved_color_texture_
->Invalidate();
4035 if (offscreen_resolved_frame_buffer_
.get())
4036 offscreen_resolved_frame_buffer_
->Invalidate();
4037 if (offscreen_resolved_color_texture_
.get())
4038 offscreen_resolved_color_texture_
->Invalidate();
4041 // Current program must be cleared after calling ProgramManager::UnuseProgram.
4042 // Otherwise, we can leak objects. http://crbug.com/258772.
4043 // state_.current_program must be reset before group_ is reset because
4044 // the later deletes the ProgramManager object that referred by
4045 // state_.current_program object.
4046 state_
.current_program
= NULL
;
4048 copy_texture_CHROMIUM_
.reset();
4049 clear_framebuffer_blit_
.reset();
4051 if (query_manager_
.get()) {
4052 query_manager_
->Destroy(have_context
);
4053 query_manager_
.reset();
4056 if (vertex_array_manager_
.get()) {
4057 vertex_array_manager_
->Destroy(have_context
);
4058 vertex_array_manager_
.reset();
4061 if (image_manager_
.get()) {
4062 image_manager_
->Destroy(have_context
);
4063 image_manager_
.reset();
4066 offscreen_target_frame_buffer_
.reset();
4067 offscreen_target_color_texture_
.reset();
4068 offscreen_target_color_render_buffer_
.reset();
4069 offscreen_target_depth_render_buffer_
.reset();
4070 offscreen_target_stencil_render_buffer_
.reset();
4071 offscreen_saved_frame_buffer_
.reset();
4072 offscreen_saved_color_texture_
.reset();
4073 offscreen_resolved_frame_buffer_
.reset();
4074 offscreen_resolved_color_texture_
.reset();
4076 // Need to release these before releasing |group_| which may own the
4077 // ShaderTranslatorCache.
4078 fragment_translator_
= NULL
;
4079 vertex_translator_
= NULL
;
4081 // Should destroy the transfer manager before the texture manager held
4082 // by the context group.
4083 async_pixel_transfer_manager_
.reset();
4085 // Destroy the GPU Tracer which may own some in process GPU Timings.
4087 gpu_tracer_
->Destroy(have_context
);
4088 gpu_tracer_
.reset();
4092 framebuffer_manager()->RemoveObserver(this);
4093 group_
->Destroy(this, have_context
);
4097 if (context_
.get()) {
4098 context_
->ReleaseCurrent(NULL
);
4102 #if defined(OS_MACOSX)
4103 for (TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.begin();
4104 it
!= texture_to_io_surface_map_
.end(); ++it
) {
4105 CFRelease(it
->second
);
4107 texture_to_io_surface_map_
.clear();
4111 void GLES2DecoderImpl::SetSurface(
4112 const scoped_refptr
<gfx::GLSurface
>& surface
) {
4113 DCHECK(context_
->IsCurrent(NULL
));
4114 DCHECK(surface_
.get());
4116 RestoreCurrentFramebufferBindings();
4119 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox
& mailbox
) {
4120 if (!offscreen_saved_color_texture_
.get()) {
4121 LOG(ERROR
) << "Called ProduceFrontBuffer on a non-offscreen context";
4124 if (!offscreen_saved_color_texture_info_
.get()) {
4125 GLuint service_id
= offscreen_saved_color_texture_
->id();
4126 offscreen_saved_color_texture_info_
= TextureRef::Create(
4127 texture_manager(), 0, service_id
);
4128 texture_manager()->SetTarget(offscreen_saved_color_texture_info_
.get(),
4130 UpdateParentTextureInfo();
4132 mailbox_manager()->ProduceTexture(
4133 mailbox
, offscreen_saved_color_texture_info_
->texture());
4136 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size
& size
) {
4137 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
4138 if (!is_offscreen
) {
4139 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
4140 << " with an onscreen framebuffer.";
4144 if (offscreen_size_
== size
)
4147 offscreen_size_
= size
;
4148 int w
= offscreen_size_
.width();
4149 int h
= offscreen_size_
.height();
4150 if (w
< 0 || h
< 0 || h
>= (INT_MAX
/ 4) / (w
? w
: 1)) {
4151 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4152 << "to allocate storage due to excessive dimensions.";
4156 // Reallocate the offscreen target buffers.
4157 DCHECK(offscreen_target_color_format_
);
4158 if (IsOffscreenBufferMultisampled()) {
4159 if (!offscreen_target_color_render_buffer_
->AllocateStorage(
4160 feature_info_
.get(),
4162 offscreen_target_color_format_
,
4163 offscreen_target_samples_
)) {
4164 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4165 << "to allocate storage for offscreen target color buffer.";
4169 if (!offscreen_target_color_texture_
->AllocateStorage(
4170 offscreen_size_
, offscreen_target_color_format_
, false)) {
4171 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4172 << "to allocate storage for offscreen target color texture.";
4176 if (offscreen_target_depth_format_
&&
4177 !offscreen_target_depth_render_buffer_
->AllocateStorage(
4178 feature_info_
.get(),
4180 offscreen_target_depth_format_
,
4181 offscreen_target_samples_
)) {
4182 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4183 << "to allocate storage for offscreen target depth buffer.";
4186 if (offscreen_target_stencil_format_
&&
4187 !offscreen_target_stencil_render_buffer_
->AllocateStorage(
4188 feature_info_
.get(),
4190 offscreen_target_stencil_format_
,
4191 offscreen_target_samples_
)) {
4192 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4193 << "to allocate storage for offscreen target stencil buffer.";
4197 // Attach the offscreen target buffers to the target frame buffer.
4198 if (IsOffscreenBufferMultisampled()) {
4199 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4200 GL_COLOR_ATTACHMENT0
,
4201 offscreen_target_color_render_buffer_
.get());
4203 offscreen_target_frame_buffer_
->AttachRenderTexture(
4204 offscreen_target_color_texture_
.get());
4206 if (offscreen_target_depth_format_
) {
4207 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4208 GL_DEPTH_ATTACHMENT
,
4209 offscreen_target_depth_render_buffer_
.get());
4211 const bool packed_depth_stencil
=
4212 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
4213 if (packed_depth_stencil
) {
4214 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4215 GL_STENCIL_ATTACHMENT
,
4216 offscreen_target_depth_render_buffer_
.get());
4217 } else if (offscreen_target_stencil_format_
) {
4218 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4219 GL_STENCIL_ATTACHMENT
,
4220 offscreen_target_stencil_render_buffer_
.get());
4223 if (offscreen_target_frame_buffer_
->CheckStatus() !=
4224 GL_FRAMEBUFFER_COMPLETE
) {
4225 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4226 << "because offscreen FBO was incomplete.";
4230 // Clear the target frame buffer.
4232 ScopedFrameBufferBinder
binder(this, offscreen_target_frame_buffer_
->id());
4233 glClearColor(0, 0, 0, BackBufferHasAlpha() ? 0 : 1.f
);
4234 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
4236 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
4237 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
4239 state_
.SetDeviceDepthMask(GL_TRUE
);
4240 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
4241 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
4242 RestoreClearState();
4245 // Destroy the offscreen resolved framebuffers.
4246 if (offscreen_resolved_frame_buffer_
.get())
4247 offscreen_resolved_frame_buffer_
->Destroy();
4248 if (offscreen_resolved_color_texture_
.get())
4249 offscreen_resolved_color_texture_
->Destroy();
4250 offscreen_resolved_color_texture_
.reset();
4251 offscreen_resolved_frame_buffer_
.reset();
4256 error::Error
GLES2DecoderImpl::HandleResizeCHROMIUM(uint32 immediate_data_size
,
4257 const void* cmd_data
) {
4258 const gles2::cmds::ResizeCHROMIUM
& c
=
4259 *static_cast<const gles2::cmds::ResizeCHROMIUM
*>(cmd_data
);
4260 if (!offscreen_target_frame_buffer_
.get() && surface_
->DeferDraws())
4261 return error::kDeferCommandUntilLater
;
4263 GLuint width
= static_cast<GLuint
>(c
.width
);
4264 GLuint height
= static_cast<GLuint
>(c
.height
);
4265 GLfloat scale_factor
= c
.scale_factor
;
4266 TRACE_EVENT2("gpu", "glResizeChromium", "width", width
, "height", height
);
4268 width
= std::max(1U, width
);
4269 height
= std::max(1U, height
);
4271 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
4272 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
4273 // Make sure that we are done drawing to the back buffer before resizing.
4276 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
4278 if (!ResizeOffscreenFrameBuffer(gfx::Size(width
, height
))) {
4279 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because "
4280 << "ResizeOffscreenFrameBuffer failed.";
4281 return error::kLostContext
;
4285 if (!resize_callback_
.is_null()) {
4286 resize_callback_
.Run(gfx::Size(width
, height
), scale_factor
);
4287 DCHECK(context_
->IsCurrent(surface_
.get()));
4288 if (!context_
->IsCurrent(surface_
.get())) {
4289 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because context no longer "
4290 << "current after resize callback.";
4291 return error::kLostContext
;
4295 return error::kNoError
;
4298 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id
) const {
4299 if (command_id
> kStartPoint
&& command_id
< kNumCommands
) {
4300 return gles2::GetCommandName(static_cast<CommandId
>(command_id
));
4302 return GetCommonCommandName(static_cast<cmd::CommandId
>(command_id
));
4305 // Decode a command, and call the corresponding GL functions.
4306 // NOTE: DoCommand() is slower than calling DoCommands() on larger batches
4307 // of commands at once, and is now only used for tests that need to track
4308 // individual commands.
4309 error::Error
GLES2DecoderImpl::DoCommand(unsigned int command
,
4310 unsigned int arg_count
,
4311 const void* cmd_data
) {
4312 return DoCommands(1, cmd_data
, arg_count
+ 1, 0);
4315 // Decode multiple commands, and call the corresponding GL functions.
4316 // NOTE: 'buffer' is a pointer to the command buffer. As such, it could be
4317 // changed by a (malicious) client at any time, so if validation has to happen,
4318 // it should operate on a copy of them.
4319 // NOTE: This is duplicating code from AsyncAPIInterface::DoCommands() in the
4320 // interest of performance in this critical execution loop.
4321 template <bool DebugImpl
>
4322 error::Error
GLES2DecoderImpl::DoCommandsImpl(unsigned int num_commands
,
4325 int* entries_processed
) {
4326 commands_to_process_
= num_commands
;
4327 error::Error result
= error::kNoError
;
4328 const CommandBufferEntry
* cmd_data
=
4329 static_cast<const CommandBufferEntry
*>(buffer
);
4330 int process_pos
= 0;
4331 unsigned int command
= 0;
4333 while (process_pos
< num_entries
&& result
== error::kNoError
&&
4334 commands_to_process_
--) {
4335 const unsigned int size
= cmd_data
->value_header
.size
;
4336 command
= cmd_data
->value_header
.command
;
4339 result
= error::kInvalidSize
;
4343 if (static_cast<int>(size
) + process_pos
> num_entries
) {
4344 result
= error::kOutOfBounds
;
4349 TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4350 GetCommandName(command
));
4352 if (log_commands()) {
4353 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "]"
4354 << "cmd: " << GetCommandName(command
);
4358 const unsigned int arg_count
= size
- 1;
4359 unsigned int command_index
= command
- kStartPoint
- 1;
4360 if (command_index
< arraysize(command_info
)) {
4361 const CommandInfo
& info
= command_info
[command_index
];
4362 unsigned int info_arg_count
= static_cast<unsigned int>(info
.arg_count
);
4363 if ((info
.arg_flags
== cmd::kFixed
&& arg_count
== info_arg_count
) ||
4364 (info
.arg_flags
== cmd::kAtLeastN
&& arg_count
>= info_arg_count
)) {
4365 bool doing_gpu_trace
= false;
4366 if (DebugImpl
&& gpu_trace_commands_
) {
4367 if (CMD_FLAG_GET_TRACE_LEVEL(info
.cmd_flags
) <= gpu_trace_level_
) {
4368 doing_gpu_trace
= true;
4369 gpu_tracer_
->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_decoder"),
4370 GetCommandName(command
),
4375 uint32 immediate_data_size
= (arg_count
- info_arg_count
) *
4376 sizeof(CommandBufferEntry
); // NOLINT
4378 result
= (this->*info
.cmd_handler
)(immediate_data_size
, cmd_data
);
4380 if (DebugImpl
&& doing_gpu_trace
)
4381 gpu_tracer_
->End(kTraceDecoder
);
4383 if (DebugImpl
&& debug()) {
4385 while ((error
= glGetError()) != GL_NO_ERROR
) {
4386 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "] "
4387 << "GL ERROR: " << GLES2Util::GetStringEnum(error
)
4388 << " : " << GetCommandName(command
);
4389 LOCAL_SET_GL_ERROR(error
, "DoCommand", "GL error from driver");
4393 result
= error::kInvalidArguments
;
4396 result
= DoCommonCommand(command
, arg_count
, cmd_data
);
4400 TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4401 GetCommandName(command
));
4404 if (result
== error::kNoError
&&
4405 current_decoder_error_
!= error::kNoError
) {
4406 result
= current_decoder_error_
;
4407 current_decoder_error_
= error::kNoError
;
4410 if (result
!= error::kDeferCommandUntilLater
) {
4411 process_pos
+= size
;
4416 if (entries_processed
)
4417 *entries_processed
= process_pos
;
4419 if (error::IsError(result
)) {
4420 LOG(ERROR
) << "Error: " << result
<< " for Command "
4421 << GetCommandName(command
);
4427 error::Error
GLES2DecoderImpl::DoCommands(unsigned int num_commands
,
4430 int* entries_processed
) {
4431 if (gpu_debug_commands_
) {
4432 return DoCommandsImpl
<true>(
4433 num_commands
, buffer
, num_entries
, entries_processed
);
4435 return DoCommandsImpl
<false>(
4436 num_commands
, buffer
, num_entries
, entries_processed
);
4440 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id
) {
4441 buffer_manager()->RemoveBuffer(client_id
);
4444 void GLES2DecoderImpl::DoFinish() {
4446 ProcessPendingReadPixels(true);
4447 ProcessPendingQueries(true);
4450 void GLES2DecoderImpl::DoFlush() {
4452 ProcessPendingQueries(false);
4455 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit
) {
4456 GLuint texture_index
= texture_unit
- GL_TEXTURE0
;
4457 if (texture_index
>= state_
.texture_units
.size()) {
4458 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4459 "glActiveTexture", texture_unit
, "texture_unit");
4462 state_
.active_texture_unit
= texture_index
;
4463 glActiveTexture(texture_unit
);
4466 void GLES2DecoderImpl::DoBindBuffer(GLenum target
, GLuint client_id
) {
4467 Buffer
* buffer
= NULL
;
4468 GLuint service_id
= 0;
4469 if (client_id
!= 0) {
4470 buffer
= GetBuffer(client_id
);
4472 if (!group_
->bind_generates_resource()) {
4473 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4475 "id not generated by glGenBuffers");
4479 // It's a new id so make a buffer buffer for it.
4480 glGenBuffersARB(1, &service_id
);
4481 CreateBuffer(client_id
, service_id
);
4482 buffer
= GetBuffer(client_id
);
4485 LogClientServiceForInfo(buffer
, client_id
, "glBindBuffer");
4487 if (!buffer_manager()->SetTarget(buffer
, target
)) {
4489 GL_INVALID_OPERATION
,
4490 "glBindBuffer", "buffer bound to more than 1 target");
4493 service_id
= buffer
->service_id();
4495 state_
.SetBoundBuffer(target
, buffer
);
4496 glBindBuffer(target
, service_id
);
4499 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha() {
4500 Framebuffer
* framebuffer
=
4501 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4503 return framebuffer
->HasAlphaMRT();
4504 return BackBufferHasAlpha();
4507 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
4508 Framebuffer
* framebuffer
=
4509 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4511 return framebuffer
->HasDepthAttachment();
4513 if (offscreen_target_frame_buffer_
.get()) {
4514 return offscreen_target_depth_format_
!= 0;
4516 return back_buffer_has_depth_
;
4519 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
4520 Framebuffer
* framebuffer
=
4521 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4523 return framebuffer
->HasStencilAttachment();
4525 if (offscreen_target_frame_buffer_
.get()) {
4526 return offscreen_target_stencil_format_
!= 0 ||
4527 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
4529 return back_buffer_has_stencil_
;
4532 void GLES2DecoderImpl::ApplyDirtyState() {
4533 if (framebuffer_state_
.clear_state_dirty
) {
4534 bool have_alpha
= BoundFramebufferHasColorAttachmentWithAlpha();
4535 state_
.SetDeviceColorMask(state_
.color_mask_red
,
4536 state_
.color_mask_green
,
4537 state_
.color_mask_blue
,
4538 state_
.color_mask_alpha
&& have_alpha
);
4540 bool have_depth
= BoundFramebufferHasDepthAttachment();
4541 state_
.SetDeviceDepthMask(state_
.depth_mask
&& have_depth
);
4543 bool have_stencil
= BoundFramebufferHasStencilAttachment();
4544 state_
.SetDeviceStencilMaskSeparate(
4545 GL_FRONT
, have_stencil
? state_
.stencil_front_writemask
: 0);
4546 state_
.SetDeviceStencilMaskSeparate(
4547 GL_BACK
, have_stencil
? state_
.stencil_back_writemask
: 0);
4549 state_
.SetDeviceCapabilityState(
4550 GL_DEPTH_TEST
, state_
.enable_flags
.depth_test
&& have_depth
);
4551 state_
.SetDeviceCapabilityState(
4552 GL_STENCIL_TEST
, state_
.enable_flags
.stencil_test
&& have_stencil
);
4553 framebuffer_state_
.clear_state_dirty
= false;
4557 GLuint
GLES2DecoderImpl::GetBackbufferServiceId() const {
4558 return (offscreen_target_frame_buffer_
.get())
4559 ? offscreen_target_frame_buffer_
->id()
4560 : (surface_
.get() ? surface_
->GetBackingFrameBufferObject() : 0);
4563 void GLES2DecoderImpl::RestoreState(const ContextState
* prev_state
) {
4564 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
4565 "context", logger_
.GetLogPrefix());
4566 // Restore the Framebuffer first because of bugs in Intel drivers.
4567 // Intel drivers incorrectly clip the viewport settings to
4568 // the size of the current framebuffer object.
4569 RestoreFramebufferBindings();
4570 state_
.RestoreState(prev_state
);
4573 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
4575 framebuffer_state_
.bound_draw_framebuffer
.get()
4576 ? framebuffer_state_
.bound_draw_framebuffer
->service_id()
4577 : GetBackbufferServiceId();
4578 if (!features().chromium_framebuffer_multisample
) {
4579 glBindFramebufferEXT(GL_FRAMEBUFFER
, service_id
);
4581 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, service_id
);
4582 service_id
= framebuffer_state_
.bound_read_framebuffer
.get()
4583 ? framebuffer_state_
.bound_read_framebuffer
->service_id()
4584 : GetBackbufferServiceId();
4585 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, service_id
);
4590 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
4591 state_
.RestoreRenderbufferBindings();
4594 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id
) const {
4595 Texture
* texture
= texture_manager()->GetTextureForServiceId(service_id
);
4597 GLenum target
= texture
->target();
4598 glBindTexture(target
, service_id
);
4600 target
, GL_TEXTURE_WRAP_S
, texture
->wrap_s());
4602 target
, GL_TEXTURE_WRAP_T
, texture
->wrap_t());
4604 target
, GL_TEXTURE_MIN_FILTER
, texture
->min_filter());
4606 target
, GL_TEXTURE_MAG_FILTER
, texture
->mag_filter());
4607 RestoreTextureUnitBindings(state_
.active_texture_unit
);
4611 void GLES2DecoderImpl::ClearAllAttributes() const {
4612 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
4614 if (feature_info_
->feature_flags().native_vertex_array_object
)
4615 glBindVertexArrayOES(0);
4617 for (uint32 i
= 0; i
< group_
->max_vertex_attribs(); ++i
) {
4618 if (i
!= 0) // Never disable attribute 0
4619 glDisableVertexAttribArray(i
);
4620 if (features().angle_instanced_arrays
)
4621 glVertexAttribDivisorANGLE(i
, 0);
4625 void GLES2DecoderImpl::RestoreAllAttributes() const {
4626 state_
.RestoreVertexAttribs();
4629 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore
) {
4630 state_
.SetIgnoreCachedStateForTest(ignore
);
4633 void GLES2DecoderImpl::OnFboChanged() const {
4634 if (workarounds().restore_scissor_on_fbo_change
)
4635 state_
.fbo_binding_for_scissor_workaround_dirty
= true;
4637 if (workarounds().gl_begin_gl_end_on_fbo_change_to_backbuffer
) {
4638 GLint bound_fbo_unsigned
= -1;
4639 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT
, &bound_fbo_unsigned
);
4640 GLuint bound_fbo
= static_cast<GLuint
>(bound_fbo_unsigned
);
4641 if (surface_
&& surface_
->GetBackingFrameBufferObject() == bound_fbo
)
4642 surface_
->NotifyWasBound();
4646 // Called after the FBO is checked for completeness.
4647 void GLES2DecoderImpl::OnUseFramebuffer() const {
4648 if (state_
.fbo_binding_for_scissor_workaround_dirty
) {
4649 state_
.fbo_binding_for_scissor_workaround_dirty
= false;
4650 // The driver forgets the correct scissor when modifying the FBO binding.
4651 glScissor(state_
.scissor_x
,
4653 state_
.scissor_width
,
4654 state_
.scissor_height
);
4656 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
4657 // it's unclear how this bug works.
4662 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target
, GLuint client_id
) {
4663 Framebuffer
* framebuffer
= NULL
;
4664 GLuint service_id
= 0;
4665 if (client_id
!= 0) {
4666 framebuffer
= GetFramebuffer(client_id
);
4668 if (!group_
->bind_generates_resource()) {
4669 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4670 "glBindFramebuffer",
4671 "id not generated by glGenFramebuffers");
4675 // It's a new id so make a framebuffer framebuffer for it.
4676 glGenFramebuffersEXT(1, &service_id
);
4677 CreateFramebuffer(client_id
, service_id
);
4678 framebuffer
= GetFramebuffer(client_id
);
4680 service_id
= framebuffer
->service_id();
4682 framebuffer
->MarkAsValid();
4684 LogClientServiceForInfo(framebuffer
, client_id
, "glBindFramebuffer");
4686 if (target
== GL_FRAMEBUFFER
|| target
== GL_DRAW_FRAMEBUFFER_EXT
) {
4687 framebuffer_state_
.bound_draw_framebuffer
= framebuffer
;
4690 // vmiura: This looks like dup code
4691 if (target
== GL_FRAMEBUFFER
|| target
== GL_READ_FRAMEBUFFER_EXT
) {
4692 framebuffer_state_
.bound_read_framebuffer
= framebuffer
;
4695 framebuffer_state_
.clear_state_dirty
= true;
4697 // If we are rendering to the backbuffer get the FBO id for any simulated
4699 if (framebuffer
== NULL
) {
4700 service_id
= GetBackbufferServiceId();
4703 glBindFramebufferEXT(target
, service_id
);
4707 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target
, GLuint client_id
) {
4708 Renderbuffer
* renderbuffer
= NULL
;
4709 GLuint service_id
= 0;
4710 if (client_id
!= 0) {
4711 renderbuffer
= GetRenderbuffer(client_id
);
4712 if (!renderbuffer
) {
4713 if (!group_
->bind_generates_resource()) {
4714 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4715 "glBindRenderbuffer",
4716 "id not generated by glGenRenderbuffers");
4720 // It's a new id so make a renderbuffer for it.
4721 glGenRenderbuffersEXT(1, &service_id
);
4722 CreateRenderbuffer(client_id
, service_id
);
4723 renderbuffer
= GetRenderbuffer(client_id
);
4725 service_id
= renderbuffer
->service_id();
4727 renderbuffer
->MarkAsValid();
4729 LogClientServiceForInfo(renderbuffer
, client_id
, "glBindRenderbuffer");
4730 state_
.bound_renderbuffer
= renderbuffer
;
4731 state_
.bound_renderbuffer_valid
= true;
4732 glBindRenderbufferEXT(GL_RENDERBUFFER
, service_id
);
4735 void GLES2DecoderImpl::DoBindTexture(GLenum target
, GLuint client_id
) {
4736 TextureRef
* texture_ref
= NULL
;
4737 GLuint service_id
= 0;
4738 if (client_id
!= 0) {
4739 texture_ref
= GetTexture(client_id
);
4741 if (!group_
->bind_generates_resource()) {
4742 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4744 "id not generated by glGenTextures");
4748 // It's a new id so make a texture texture for it.
4749 glGenTextures(1, &service_id
);
4750 DCHECK_NE(0u, service_id
);
4751 CreateTexture(client_id
, service_id
);
4752 texture_ref
= GetTexture(client_id
);
4755 texture_ref
= texture_manager()->GetDefaultTextureInfo(target
);
4758 // Check the texture exists
4760 Texture
* texture
= texture_ref
->texture();
4761 // Check that we are not trying to bind it to a different target.
4762 if (texture
->target() != 0 && texture
->target() != target
) {
4763 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4765 "texture bound to more than 1 target.");
4768 LogClientServiceForInfo(texture
, client_id
, "glBindTexture");
4769 if (texture
->target() == 0) {
4770 texture_manager()->SetTarget(texture_ref
, target
);
4772 glBindTexture(target
, texture
->service_id());
4774 glBindTexture(target
, 0);
4777 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4778 unit
.bind_target
= target
;
4781 unit
.bound_texture_2d
= texture_ref
;
4783 case GL_TEXTURE_CUBE_MAP
:
4784 unit
.bound_texture_cube_map
= texture_ref
;
4786 case GL_TEXTURE_EXTERNAL_OES
:
4787 unit
.bound_texture_external_oes
= texture_ref
;
4789 case GL_TEXTURE_RECTANGLE_ARB
:
4790 unit
.bound_texture_rectangle_arb
= texture_ref
;
4793 unit
.bound_texture_3d
= texture_ref
;
4795 case GL_TEXTURE_2D_ARRAY
:
4796 unit
.bound_texture_2d_array
= texture_ref
;
4799 NOTREACHED(); // Validation should prevent us getting here.
4804 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index
) {
4805 if (state_
.vertex_attrib_manager
->Enable(index
, false)) {
4807 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
4808 glDisableVertexAttribArray(index
);
4813 "glDisableVertexAttribArray", "index out of range");
4817 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target
,
4818 GLsizei numAttachments
,
4819 const GLenum
* attachments
) {
4820 if (workarounds().disable_discard_framebuffer
)
4823 Framebuffer
* framebuffer
=
4824 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
4826 // Validates the attachments. If one of them fails
4827 // the whole command fails.
4828 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4830 !validators_
->attachment
.IsValid(attachments
[i
])) ||
4832 !validators_
->backbuffer_attachment
.IsValid(attachments
[i
]))) {
4833 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4834 "glDiscardFramebufferEXT", attachments
[i
], "attachments");
4839 // Marks each one of them as not cleared
4840 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4842 framebuffer
->MarkAttachmentAsCleared(renderbuffer_manager(),
4847 switch (attachments
[i
]) {
4849 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
4852 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
4853 case GL_STENCIL_EXT
:
4854 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
4863 // If the default framebuffer is bound but we are still rendering to an
4864 // FBO, translate attachment names that refer to default framebuffer
4865 // channels to corresponding framebuffer attachments.
4866 scoped_ptr
<GLenum
[]> translated_attachments(new GLenum
[numAttachments
]);
4867 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4868 GLenum attachment
= attachments
[i
];
4869 if (!framebuffer
&& GetBackbufferServiceId()) {
4870 switch (attachment
) {
4872 attachment
= GL_COLOR_ATTACHMENT0
;
4875 attachment
= GL_DEPTH_ATTACHMENT
;
4877 case GL_STENCIL_EXT
:
4878 attachment
= GL_STENCIL_ATTACHMENT
;
4885 translated_attachments
[i
] = attachment
;
4888 ScopedRenderTo
do_render(framebuffer
);
4889 if (feature_info_
->gl_version_info().is_es3
) {
4890 glInvalidateFramebuffer(
4891 target
, numAttachments
, translated_attachments
.get());
4893 glDiscardFramebufferEXT(
4894 target
, numAttachments
, translated_attachments
.get());
4898 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index
) {
4899 if (state_
.vertex_attrib_manager
->Enable(index
, true)) {
4900 glEnableVertexAttribArray(index
);
4903 GL_INVALID_VALUE
, "glEnableVertexAttribArray", "index out of range");
4907 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target
) {
4908 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
4911 !texture_manager()->CanGenerateMipmaps(texture_ref
)) {
4913 GL_INVALID_OPERATION
, "glGenerateMipmap", "Can not generate mips");
4917 if (target
== GL_TEXTURE_CUBE_MAP
) {
4918 for (int i
= 0; i
< 6; ++i
) {
4919 GLenum face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ i
;
4920 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, face
, 0)) {
4922 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
4927 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
, 0)) {
4929 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
4934 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4935 // Workaround for Mac driver bug. In the large scheme of things setting
4936 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4937 // hit so there's probably no need to make this conditional. The bug appears
4938 // to be that if the filtering mode is set to something that doesn't require
4939 // mipmaps for rendering, or is never set to something other than the default,
4940 // then glGenerateMipmap misbehaves.
4941 if (workarounds().set_texture_filter_before_generating_mipmap
) {
4942 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST_MIPMAP_NEAREST
);
4944 glGenerateMipmapEXT(target
);
4945 if (workarounds().set_texture_filter_before_generating_mipmap
) {
4946 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
,
4947 texture_ref
->texture()->min_filter());
4949 GLenum error
= LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4950 if (error
== GL_NO_ERROR
) {
4951 texture_manager()->MarkMipmapsGenerated(texture_ref
);
4955 bool GLES2DecoderImpl::GetHelper(
4956 GLenum pname
, GLint
* params
, GLsizei
* num_written
) {
4957 DCHECK(num_written
);
4958 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
4960 case GL_IMPLEMENTATION_COLOR_READ_FORMAT
:
4962 // Return the GL implementation's preferred format and (see below type)
4963 // if we have the GL extension that exposes this. This allows the GPU
4964 // client to use the implementation's preferred format for glReadPixels
4965 // for optimisation.
4967 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4968 // case when requested on integer/floating point buffers but which is
4969 // acceptable on GLES2 and with the GL_OES_read_format extension.
4971 // Therefore if an error occurs we swallow the error and use the
4972 // internal implementation.
4974 if (context_
->HasExtension("GL_OES_read_format")) {
4975 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
4977 glGetIntegerv(pname
, params
);
4978 if (glGetError() == GL_NO_ERROR
)
4981 *params
= GLES2Util::GetPreferredGLReadPixelsFormat(
4982 GetBoundReadFrameBufferInternalFormat());
4985 case GL_IMPLEMENTATION_COLOR_READ_TYPE
:
4988 if (context_
->HasExtension("GL_OES_read_format")) {
4989 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
4991 glGetIntegerv(pname
, params
);
4992 if (glGetError() == GL_NO_ERROR
)
4995 *params
= GLES2Util::GetPreferredGLReadPixelsType(
4996 GetBoundReadFrameBufferInternalFormat(),
4997 GetBoundReadFrameBufferTextureType());
5000 case GL_MAX_FRAGMENT_UNIFORM_VECTORS
:
5003 *params
= group_
->max_fragment_uniform_vectors();
5006 case GL_MAX_VARYING_VECTORS
:
5009 *params
= group_
->max_varying_vectors();
5012 case GL_MAX_VERTEX_UNIFORM_VECTORS
:
5015 *params
= group_
->max_vertex_uniform_vectors();
5020 if (unsafe_es3_apis_enabled()) {
5022 case GL_MAX_VARYING_COMPONENTS
: {
5023 if (feature_info_
->gl_version_info().is_es
) {
5024 // We can just delegate this query to the driver.
5028 // GL_MAX_VARYING_COMPONENTS is deprecated in the desktop
5029 // OpenGL core profile, so for simplicity, just compute it
5030 // from GL_MAX_VARYING_VECTORS on non-OpenGL ES
5032 GLint max_varying_vectors
= 0;
5033 glGetIntegerv(GL_MAX_VARYING_VECTORS
, &max_varying_vectors
);
5036 *params
= max_varying_vectors
* 4;
5040 case GL_READ_BUFFER
:
5043 Framebuffer
* framebuffer
=
5044 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER
);
5047 read_buffer
= framebuffer
->read_buffer();
5049 read_buffer
= back_buffer_read_buffer_
;
5051 *params
= static_cast<GLint
>(read_buffer
);
5057 case GL_MAX_VIEWPORT_DIMS
:
5058 if (offscreen_target_frame_buffer_
.get()) {
5061 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
5062 params
[1] = renderbuffer_manager()->max_renderbuffer_size();
5067 case GL_MAX_SAMPLES
:
5070 params
[0] = renderbuffer_manager()->max_samples();
5073 case GL_MAX_RENDERBUFFER_SIZE
:
5076 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
5079 case GL_MAX_TEXTURE_SIZE
:
5082 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D
);
5085 case GL_MAX_CUBE_MAP_TEXTURE_SIZE
:
5088 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP
);
5091 case GL_MAX_COLOR_ATTACHMENTS_EXT
:
5094 params
[0] = group_
->max_color_attachments();
5097 case GL_MAX_DRAW_BUFFERS_ARB
:
5100 params
[0] = group_
->max_draw_buffers();
5107 Framebuffer
* framebuffer
=
5108 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5110 if (framebuffer
->HasAlphaMRT() &&
5111 framebuffer
->HasSameInternalFormatsMRT()) {
5112 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
5113 glGetFramebufferAttachmentParameterivEXT(
5114 GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
5115 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE
, &v
);
5117 glGetIntegerv(GL_ALPHA_BITS
, &v
);
5121 v
= (BackBufferHasAlpha() ? 8 : 0);
5130 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
5131 Framebuffer
* framebuffer
=
5132 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5134 glGetFramebufferAttachmentParameterivEXT(
5135 GL_FRAMEBUFFER
, GL_DEPTH_ATTACHMENT
,
5136 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE
, &v
);
5138 v
= (back_buffer_has_depth_
? 24 : 0);
5141 glGetIntegerv(GL_DEPTH_BITS
, &v
);
5143 params
[0] = BoundFramebufferHasDepthAttachment() ? v
: 0;
5152 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
5153 Framebuffer
* framebuffer
=
5154 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5156 GLenum framebuffer_enum
= 0;
5159 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE
;
5162 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE
;
5165 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE
;
5168 glGetFramebufferAttachmentParameterivEXT(
5169 GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
, framebuffer_enum
, &v
);
5174 glGetIntegerv(pname
, &v
);
5179 case GL_STENCIL_BITS
:
5183 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
5184 Framebuffer
* framebuffer
=
5185 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5187 glGetFramebufferAttachmentParameterivEXT(
5188 GL_FRAMEBUFFER
, GL_STENCIL_ATTACHMENT
,
5189 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE
, &v
);
5191 v
= (back_buffer_has_stencil_
? 8 : 0);
5194 glGetIntegerv(GL_STENCIL_BITS
, &v
);
5196 params
[0] = BoundFramebufferHasStencilAttachment() ? v
: 0;
5199 case GL_COMPRESSED_TEXTURE_FORMATS
:
5200 *num_written
= validators_
->compressed_texture_format
.GetValues().size();
5202 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
5203 params
[ii
] = validators_
->compressed_texture_format
.GetValues()[ii
];
5207 case GL_NUM_COMPRESSED_TEXTURE_FORMATS
:
5210 *params
= validators_
->compressed_texture_format
.GetValues().size();
5213 case GL_NUM_SHADER_BINARY_FORMATS
:
5216 *params
= validators_
->shader_binary_format
.GetValues().size();
5219 case GL_SHADER_BINARY_FORMATS
:
5220 *num_written
= validators_
->shader_binary_format
.GetValues().size();
5222 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
5223 params
[ii
] = validators_
->shader_binary_format
.GetValues()[ii
];
5227 case GL_SHADER_COMPILER
:
5233 case GL_ARRAY_BUFFER_BINDING
:
5236 *params
= GetClientId(
5237 buffer_manager(), state_
.bound_array_buffer
.get());
5240 case GL_ELEMENT_ARRAY_BUFFER_BINDING
:
5243 *params
= GetClientId(
5245 state_
.vertex_attrib_manager
->element_array_buffer());
5248 case GL_COPY_READ_BUFFER_BINDING
:
5251 *params
= GetClientId(
5252 buffer_manager(), state_
.bound_copy_read_buffer
.get());
5255 case GL_COPY_WRITE_BUFFER_BINDING
:
5258 *params
= GetClientId(
5259 buffer_manager(), state_
.bound_copy_write_buffer
.get());
5262 case GL_PIXEL_PACK_BUFFER_BINDING
:
5265 *params
= GetClientId(
5266 buffer_manager(), state_
.bound_pixel_pack_buffer
.get());
5269 case GL_PIXEL_UNPACK_BUFFER_BINDING
:
5272 *params
= GetClientId(
5273 buffer_manager(), state_
.bound_pixel_unpack_buffer
.get());
5276 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING
:
5279 *params
= GetClientId(
5280 buffer_manager(), state_
.bound_transform_feedback_buffer
.get());
5283 case GL_UNIFORM_BUFFER_BINDING
:
5286 *params
= GetClientId(
5287 buffer_manager(), state_
.bound_uniform_buffer
.get());
5290 case GL_FRAMEBUFFER_BINDING
:
5291 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
5294 *params
= GetClientId(
5295 framebuffer_manager(),
5296 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
));
5299 case GL_READ_FRAMEBUFFER_BINDING_EXT
:
5302 *params
= GetClientId(
5303 framebuffer_manager(),
5304 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
));
5307 case GL_RENDERBUFFER_BINDING
:
5310 Renderbuffer
* renderbuffer
=
5311 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5313 *params
= renderbuffer
->client_id();
5319 case GL_CURRENT_PROGRAM
:
5322 *params
= GetClientId(program_manager(), state_
.current_program
.get());
5325 case GL_VERTEX_ARRAY_BINDING_OES
:
5328 if (state_
.vertex_attrib_manager
.get() !=
5329 state_
.default_vertex_attrib_manager
.get()) {
5330 GLuint client_id
= 0;
5331 vertex_array_manager_
->GetClientId(
5332 state_
.vertex_attrib_manager
->service_id(), &client_id
);
5333 *params
= client_id
;
5339 case GL_TEXTURE_BINDING_2D
:
5342 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5343 if (unit
.bound_texture_2d
.get()) {
5344 *params
= unit
.bound_texture_2d
->client_id();
5350 case GL_TEXTURE_BINDING_CUBE_MAP
:
5353 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5354 if (unit
.bound_texture_cube_map
.get()) {
5355 *params
= unit
.bound_texture_cube_map
->client_id();
5361 case GL_TEXTURE_BINDING_EXTERNAL_OES
:
5364 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5365 if (unit
.bound_texture_external_oes
.get()) {
5366 *params
= unit
.bound_texture_external_oes
->client_id();
5372 case GL_TEXTURE_BINDING_RECTANGLE_ARB
:
5375 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5376 if (unit
.bound_texture_rectangle_arb
.get()) {
5377 *params
= unit
.bound_texture_rectangle_arb
->client_id();
5383 case GL_BIND_GENERATES_RESOURCE_CHROMIUM
:
5386 params
[0] = group_
->bind_generates_resource() ? 1 : 0;
5390 if (pname
>= GL_DRAW_BUFFER0_ARB
&&
5391 pname
< GL_DRAW_BUFFER0_ARB
+ group_
->max_draw_buffers()) {
5394 Framebuffer
* framebuffer
=
5395 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
5397 params
[0] = framebuffer
->GetDrawBuffer(pname
);
5398 } else { // backbuffer
5399 if (pname
== GL_DRAW_BUFFER0_ARB
)
5400 params
[0] = back_buffer_draw_buffer_
;
5402 params
[0] = GL_NONE
;
5407 *num_written
= util_
.GLGetNumValuesReturned(pname
);
5412 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
5413 GLenum pname
, GLsizei
* num_values
) {
5414 if (state_
.GetStateAsGLint(pname
, NULL
, num_values
)) {
5417 return GetHelper(pname
, NULL
, num_values
);
5420 GLenum
GLES2DecoderImpl::AdjustGetPname(GLenum pname
) {
5421 if (GL_MAX_SAMPLES
== pname
&&
5422 features().use_img_for_multisampled_render_to_texture
) {
5423 return GL_MAX_SAMPLES_IMG
;
5428 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname
, GLboolean
* params
) {
5430 GLsizei num_written
= 0;
5431 if (GetNumValuesReturnedForGLGet(pname
, &num_written
)) {
5432 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
5433 if (!state_
.GetStateAsGLint(pname
, values
.get(), &num_written
)) {
5434 GetHelper(pname
, values
.get(), &num_written
);
5436 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
5437 params
[ii
] = static_cast<GLboolean
>(values
[ii
]);
5440 pname
= AdjustGetPname(pname
);
5441 glGetBooleanv(pname
, params
);
5445 void GLES2DecoderImpl::DoGetFloatv(GLenum pname
, GLfloat
* params
) {
5447 GLsizei num_written
= 0;
5448 if (!state_
.GetStateAsGLfloat(pname
, params
, &num_written
)) {
5449 if (GetHelper(pname
, NULL
, &num_written
)) {
5450 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
5451 GetHelper(pname
, values
.get(), &num_written
);
5452 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
5453 params
[ii
] = static_cast<GLfloat
>(values
[ii
]);
5456 pname
= AdjustGetPname(pname
);
5457 glGetFloatv(pname
, params
);
5462 void GLES2DecoderImpl::DoGetInteger64v(GLenum pname
, GLint64
* params
) {
5464 if (unsafe_es3_apis_enabled()) {
5466 case GL_MAX_ELEMENT_INDEX
: {
5467 if (feature_info_
->gl_version_info().IsAtLeastGLES(3, 0) ||
5468 feature_info_
->gl_version_info().IsAtLeastGL(4, 3)) {
5469 glGetInteger64v(GL_MAX_ELEMENT_INDEX
, params
);
5471 // Assume that desktop GL implementations can generally support
5474 *params
= std::numeric_limits
<unsigned int>::max();
5481 pname
= AdjustGetPname(pname
);
5482 glGetInteger64v(pname
, params
);
5485 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname
, GLint
* params
) {
5487 GLsizei num_written
;
5488 if (!state_
.GetStateAsGLint(pname
, params
, &num_written
) &&
5489 !GetHelper(pname
, params
, &num_written
)) {
5490 pname
= AdjustGetPname(pname
);
5491 glGetIntegerv(pname
, params
);
5495 void GLES2DecoderImpl::DoGetProgramiv(
5496 GLuint program_id
, GLenum pname
, GLint
* params
) {
5497 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetProgramiv");
5501 program
->GetProgramiv(pname
, params
);
5504 void GLES2DecoderImpl::DoGetBufferParameteri64v(
5505 GLenum target
, GLenum pname
, GLint64
* params
) {
5506 // Just delegate it. Some validation is actually done before this.
5507 buffer_manager()->ValidateAndDoGetBufferParameteri64v(
5508 &state_
, target
, pname
, params
);
5511 void GLES2DecoderImpl::DoGetBufferParameteriv(
5512 GLenum target
, GLenum pname
, GLint
* params
) {
5513 // Just delegate it. Some validation is actually done before this.
5514 buffer_manager()->ValidateAndDoGetBufferParameteriv(
5515 &state_
, target
, pname
, params
);
5518 void GLES2DecoderImpl::DoBindAttribLocation(
5519 GLuint program_id
, GLuint index
, const char* name
) {
5520 if (!StringIsValidForGLES(name
)) {
5522 GL_INVALID_VALUE
, "glBindAttribLocation", "Invalid character");
5525 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
5527 GL_INVALID_OPERATION
, "glBindAttribLocation", "reserved prefix");
5530 if (index
>= group_
->max_vertex_attribs()) {
5532 GL_INVALID_VALUE
, "glBindAttribLocation", "index out of range");
5535 Program
* program
= GetProgramInfoNotShader(
5536 program_id
, "glBindAttribLocation");
5540 // At this point, the program's shaders may not be translated yet,
5541 // therefore, we may not find the hashed attribute name.
5542 // glBindAttribLocation call with original name is useless.
5543 // So instead, we should simply cache the binding, and then call
5544 // Program::ExecuteBindAttribLocationCalls() right before link.
5545 program
->SetAttribLocationBinding(name
, static_cast<GLint
>(index
));
5546 // TODO(zmo): Get rid of the following glBindAttribLocation call.
5547 glBindAttribLocation(program
->service_id(), index
, name
);
5550 error::Error
GLES2DecoderImpl::HandleBindAttribLocationBucket(
5551 uint32 immediate_data_size
,
5552 const void* cmd_data
) {
5553 const gles2::cmds::BindAttribLocationBucket
& c
=
5554 *static_cast<const gles2::cmds::BindAttribLocationBucket
*>(cmd_data
);
5555 GLuint program
= static_cast<GLuint
>(c
.program
);
5556 GLuint index
= static_cast<GLuint
>(c
.index
);
5557 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
5558 if (!bucket
|| bucket
->size() == 0) {
5559 return error::kInvalidArguments
;
5561 std::string name_str
;
5562 if (!bucket
->GetAsString(&name_str
)) {
5563 return error::kInvalidArguments
;
5565 DoBindAttribLocation(program
, index
, name_str
.c_str());
5566 return error::kNoError
;
5569 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
5570 GLuint program_id
, GLint location
, const char* name
) {
5571 if (!StringIsValidForGLES(name
)) {
5574 "glBindUniformLocationCHROMIUM", "Invalid character");
5577 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
5579 GL_INVALID_OPERATION
,
5580 "glBindUniformLocationCHROMIUM", "reserved prefix");
5583 if (location
< 0 || static_cast<uint32
>(location
) >=
5584 (group_
->max_fragment_uniform_vectors() +
5585 group_
->max_vertex_uniform_vectors()) * 4) {
5588 "glBindUniformLocationCHROMIUM", "location out of range");
5591 Program
* program
= GetProgramInfoNotShader(
5592 program_id
, "glBindUniformLocationCHROMIUM");
5596 if (!program
->SetUniformLocationBinding(name
, location
)) {
5599 "glBindUniformLocationCHROMIUM", "location out of range");
5603 error::Error
GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
5604 uint32 immediate_data_size
,
5605 const void* cmd_data
) {
5606 const gles2::cmds::BindUniformLocationCHROMIUMBucket
& c
=
5607 *static_cast<const gles2::cmds::BindUniformLocationCHROMIUMBucket
*>(
5609 GLuint program
= static_cast<GLuint
>(c
.program
);
5610 GLint location
= static_cast<GLint
>(c
.location
);
5611 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
5612 if (!bucket
|| bucket
->size() == 0) {
5613 return error::kInvalidArguments
;
5615 std::string name_str
;
5616 if (!bucket
->GetAsString(&name_str
)) {
5617 return error::kInvalidArguments
;
5619 DoBindUniformLocationCHROMIUM(program
, location
, name_str
.c_str());
5620 return error::kNoError
;
5623 error::Error
GLES2DecoderImpl::HandleDeleteShader(uint32 immediate_data_size
,
5624 const void* cmd_data
) {
5625 const gles2::cmds::DeleteShader
& c
=
5626 *static_cast<const gles2::cmds::DeleteShader
*>(cmd_data
);
5627 GLuint client_id
= c
.shader
;
5629 Shader
* shader
= GetShader(client_id
);
5631 if (!shader
->IsDeleted()) {
5632 shader_manager()->Delete(shader
);
5635 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glDeleteShader", "unknown shader");
5638 return error::kNoError
;
5641 error::Error
GLES2DecoderImpl::HandleDeleteProgram(uint32 immediate_data_size
,
5642 const void* cmd_data
) {
5643 const gles2::cmds::DeleteProgram
& c
=
5644 *static_cast<const gles2::cmds::DeleteProgram
*>(cmd_data
);
5645 GLuint client_id
= c
.program
;
5647 Program
* program
= GetProgram(client_id
);
5649 if (!program
->IsDeleted()) {
5650 program_manager()->MarkAsDeleted(shader_manager(), program
);
5654 GL_INVALID_VALUE
, "glDeleteProgram", "unknown program");
5657 return error::kNoError
;
5660 error::Error
GLES2DecoderImpl::DoClear(GLbitfield mask
) {
5661 DCHECK(!ShouldDeferDraws());
5662 if (CheckBoundFramebuffersValid("glClear")) {
5664 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
5665 if (workarounds().gl_clear_broken
) {
5666 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::ClearWorkaround",
5668 if (!BoundFramebufferHasDepthAttachment())
5669 mask
&= ~GL_DEPTH_BUFFER_BIT
;
5670 if (!BoundFramebufferHasStencilAttachment())
5671 mask
&= ~GL_STENCIL_BUFFER_BIT
;
5672 clear_framebuffer_blit_
->ClearFramebuffer(
5673 this, GetBoundReadFrameBufferSize(), mask
, state_
.color_clear_red
,
5674 state_
.color_clear_green
, state_
.color_clear_blue
,
5675 state_
.color_clear_alpha
, state_
.depth_clear
, state_
.stencil_clear
);
5676 return error::kNoError
;
5680 return error::kNoError
;
5683 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
5684 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
5685 GLuint client_renderbuffer_id
) {
5686 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5689 GL_INVALID_OPERATION
,
5690 "glFramebufferRenderbuffer", "no framebuffer bound");
5693 GLuint service_id
= 0;
5694 Renderbuffer
* renderbuffer
= NULL
;
5695 if (client_renderbuffer_id
) {
5696 renderbuffer
= GetRenderbuffer(client_renderbuffer_id
);
5697 if (!renderbuffer
) {
5699 GL_INVALID_OPERATION
,
5700 "glFramebufferRenderbuffer", "unknown renderbuffer");
5703 service_id
= renderbuffer
->service_id();
5705 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
5706 glFramebufferRenderbufferEXT(
5707 target
, attachment
, renderbuffertarget
, service_id
);
5708 GLenum error
= LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
5709 if (error
== GL_NO_ERROR
) {
5710 framebuffer
->AttachRenderbuffer(attachment
, renderbuffer
);
5712 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
5713 framebuffer_state_
.clear_state_dirty
= true;
5718 void GLES2DecoderImpl::DoDisable(GLenum cap
) {
5719 if (SetCapabilityState(cap
, false)) {
5724 void GLES2DecoderImpl::DoEnable(GLenum cap
) {
5725 if (SetCapabilityState(cap
, true)) {
5730 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear
, GLclampf zfar
) {
5731 state_
.z_near
= std::min(1.0f
, std::max(0.0f
, znear
));
5732 state_
.z_far
= std::min(1.0f
, std::max(0.0f
, zfar
));
5733 glDepthRange(znear
, zfar
);
5736 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value
, GLboolean invert
) {
5737 state_
.sample_coverage_value
= std::min(1.0f
, std::max(0.0f
, value
));
5738 state_
.sample_coverage_invert
= (invert
!= 0);
5739 glSampleCoverage(state_
.sample_coverage_value
, invert
);
5742 // Assumes framebuffer is complete.
5743 void GLES2DecoderImpl::ClearUnclearedAttachments(
5744 GLenum target
, Framebuffer
* framebuffer
) {
5745 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
5746 // bind this to the DRAW point, clear then bind back to READ
5747 // TODO(gman): I don't think there is any guarantee that an FBO that
5748 // is complete on the READ attachment will be complete as a DRAW
5750 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, 0);
5751 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, framebuffer
->service_id());
5753 GLbitfield clear_bits
= 0;
5754 if (framebuffer
->HasUnclearedColorAttachments()) {
5755 // We should always use alpha == 0 here, because 1) some draw buffers may
5756 // have alpha and some may not; 2) we won't have the same situation as the
5757 // back buffer where alpha channel exists but is not requested.
5758 glClearColor(0.0f
, 0.0f
, 0.0f
, 0.0f
);
5759 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
5760 clear_bits
|= GL_COLOR_BUFFER_BIT
;
5761 if (feature_info_
->feature_flags().ext_draw_buffers
)
5762 framebuffer
->PrepareDrawBuffersForClear();
5765 if (framebuffer
->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT
) ||
5766 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
5768 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
5769 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
5770 clear_bits
|= GL_STENCIL_BUFFER_BIT
;
5773 if (framebuffer
->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT
) ||
5774 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
5776 state_
.SetDeviceDepthMask(GL_TRUE
);
5777 clear_bits
|= GL_DEPTH_BUFFER_BIT
;
5780 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5781 glClear(clear_bits
);
5783 if ((clear_bits
& GL_COLOR_BUFFER_BIT
) != 0 &&
5784 feature_info_
->feature_flags().ext_draw_buffers
)
5785 framebuffer
->RestoreDrawBuffersAfterClear();
5787 framebuffer_manager()->MarkAttachmentsAsCleared(
5788 framebuffer
, renderbuffer_manager(), texture_manager());
5790 RestoreClearState();
5792 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
5793 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, framebuffer
->service_id());
5794 Framebuffer
* draw_framebuffer
=
5795 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5796 GLuint service_id
= draw_framebuffer
? draw_framebuffer
->service_id() :
5797 GetBackbufferServiceId();
5798 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, service_id
);
5802 void GLES2DecoderImpl::RestoreClearState() {
5803 framebuffer_state_
.clear_state_dirty
= true;
5805 state_
.color_clear_red
, state_
.color_clear_green
, state_
.color_clear_blue
,
5806 state_
.color_clear_alpha
);
5807 glClearStencil(state_
.stencil_clear
);
5808 glClearDepth(state_
.depth_clear
);
5809 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
,
5810 state_
.enable_flags
.scissor_test
);
5811 glScissor(state_
.scissor_x
, state_
.scissor_y
, state_
.scissor_width
,
5812 state_
.scissor_height
);
5815 GLenum
GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target
) {
5816 Framebuffer
* framebuffer
=
5817 GetFramebufferInfoForTarget(target
);
5819 return GL_FRAMEBUFFER_COMPLETE
;
5821 GLenum completeness
= framebuffer
->IsPossiblyComplete();
5822 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
5823 return completeness
;
5825 return framebuffer
->GetStatus(texture_manager(), target
);
5828 void GLES2DecoderImpl::DoFramebufferTexture2D(
5829 GLenum target
, GLenum attachment
, GLenum textarget
,
5830 GLuint client_texture_id
, GLint level
) {
5831 DoFramebufferTexture2DCommon(
5832 "glFramebufferTexture2D", target
, attachment
,
5833 textarget
, client_texture_id
, level
, 0);
5836 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5837 GLenum target
, GLenum attachment
, GLenum textarget
,
5838 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
5839 DoFramebufferTexture2DCommon(
5840 "glFramebufferTexture2DMultisample", target
, attachment
,
5841 textarget
, client_texture_id
, level
, samples
);
5844 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5845 const char* name
, GLenum target
, GLenum attachment
, GLenum textarget
,
5846 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
5847 if (samples
> renderbuffer_manager()->max_samples()) {
5850 "glFramebufferTexture2DMultisample", "samples too large");
5853 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5856 GL_INVALID_OPERATION
,
5857 name
, "no framebuffer bound.");
5860 GLuint service_id
= 0;
5861 TextureRef
* texture_ref
= NULL
;
5862 if (client_texture_id
) {
5863 texture_ref
= GetTexture(client_texture_id
);
5866 GL_INVALID_OPERATION
,
5867 name
, "unknown texture_ref");
5870 service_id
= texture_ref
->service_id();
5873 if (!texture_manager()->ValidForTarget(textarget
, level
, 0, 0, 1)) {
5876 name
, "level out of range");
5881 DoWillUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
5883 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name
);
5885 glFramebufferTexture2DEXT(target
, attachment
, textarget
, service_id
, level
);
5887 if (features().use_img_for_multisampled_render_to_texture
) {
5888 glFramebufferTexture2DMultisampleIMG(target
, attachment
, textarget
,
5889 service_id
, level
, samples
);
5891 glFramebufferTexture2DMultisampleEXT(target
, attachment
, textarget
,
5892 service_id
, level
, samples
);
5895 GLenum error
= LOCAL_PEEK_GL_ERROR(name
);
5896 if (error
== GL_NO_ERROR
) {
5897 framebuffer
->AttachTexture(attachment
, texture_ref
, textarget
, level
,
5900 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
5901 framebuffer_state_
.clear_state_dirty
= true;
5905 DoDidUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
5910 void GLES2DecoderImpl::DoFramebufferTextureLayer(
5911 GLenum target
, GLenum attachment
, GLuint client_texture_id
,
5912 GLint level
, GLint layer
) {
5913 // TODO(zmo): Unsafe ES3 API, missing states update.
5914 GLuint service_id
= 0;
5915 TextureRef
* texture_ref
= NULL
;
5916 if (client_texture_id
) {
5917 texture_ref
= GetTexture(client_texture_id
);
5920 GL_INVALID_OPERATION
,
5921 "glFramebufferTextureLayer", "unknown texture_ref");
5924 service_id
= texture_ref
->service_id();
5926 glFramebufferTextureLayer(target
, attachment
, service_id
, level
, layer
);
5929 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5930 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
) {
5931 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5934 GL_INVALID_OPERATION
,
5935 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5938 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME
) {
5939 const Framebuffer::Attachment
* attachment_object
=
5940 framebuffer
->GetAttachment(attachment
);
5941 *params
= attachment_object
? attachment_object
->object_name() : 0;
5943 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT
&&
5944 features().use_img_for_multisampled_render_to_texture
) {
5945 pname
= GL_TEXTURE_SAMPLES_IMG
;
5947 glGetFramebufferAttachmentParameterivEXT(target
, attachment
, pname
, params
);
5951 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5952 GLenum target
, GLenum pname
, GLint
* params
) {
5953 Renderbuffer
* renderbuffer
=
5954 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5955 if (!renderbuffer
) {
5957 GL_INVALID_OPERATION
,
5958 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5962 EnsureRenderbufferBound();
5964 case GL_RENDERBUFFER_INTERNAL_FORMAT
:
5965 *params
= renderbuffer
->internal_format();
5967 case GL_RENDERBUFFER_WIDTH
:
5968 *params
= renderbuffer
->width();
5970 case GL_RENDERBUFFER_HEIGHT
:
5971 *params
= renderbuffer
->height();
5973 case GL_RENDERBUFFER_SAMPLES_EXT
:
5974 if (features().use_img_for_multisampled_render_to_texture
) {
5975 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_IMG
,
5978 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_EXT
,
5982 glGetRenderbufferParameterivEXT(target
, pname
, params
);
5987 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5988 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
5989 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
5990 GLbitfield mask
, GLenum filter
) {
5991 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5993 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5997 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5998 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
5999 BlitFramebufferHelper(
6000 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
6001 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
,
6002 state_
.enable_flags
.scissor_test
);
6005 void GLES2DecoderImpl::EnsureRenderbufferBound() {
6006 if (!state_
.bound_renderbuffer_valid
) {
6007 state_
.bound_renderbuffer_valid
= true;
6008 glBindRenderbufferEXT(GL_RENDERBUFFER
,
6009 state_
.bound_renderbuffer
.get()
6010 ? state_
.bound_renderbuffer
->service_id()
6015 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
6016 const FeatureInfo
* feature_info
,
6019 GLenum internal_format
,
6022 // TODO(sievers): This could be resolved at the GL binding level, but the
6023 // binding process is currently a bit too 'brute force'.
6024 if (feature_info
->gl_version_info().is_angle
) {
6025 glRenderbufferStorageMultisampleANGLE(
6026 target
, samples
, internal_format
, width
, height
);
6027 } else if (feature_info
->feature_flags().use_core_framebuffer_multisample
) {
6028 glRenderbufferStorageMultisample(
6029 target
, samples
, internal_format
, width
, height
);
6031 glRenderbufferStorageMultisampleEXT(
6032 target
, samples
, internal_format
, width
, height
);
6036 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0
,
6046 // TODO(sievers): This could be resolved at the GL binding level, but the
6047 // binding process is currently a bit too 'brute force'.
6048 if (feature_info_
->gl_version_info().is_angle
) {
6049 glBlitFramebufferANGLE(
6050 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
6051 } else if (feature_info_
->feature_flags().use_core_framebuffer_multisample
) {
6053 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
6055 glBlitFramebufferEXT(
6056 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
6060 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
6062 GLenum internalformat
,
6065 if (samples
> renderbuffer_manager()->max_samples()) {
6068 "glRenderbufferStorageMultisample", "samples too large");
6072 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
6073 height
> renderbuffer_manager()->max_renderbuffer_size()) {
6076 "glRenderbufferStorageMultisample", "dimensions too large");
6080 uint32 estimated_size
= 0;
6081 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6082 width
, height
, samples
, internalformat
, &estimated_size
)) {
6085 "glRenderbufferStorageMultisample", "dimensions too large");
6089 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
6092 "glRenderbufferStorageMultisample", "out of memory");
6099 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
6100 GLenum target
, GLsizei samples
, GLenum internalformat
,
6101 GLsizei width
, GLsizei height
) {
6102 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
6103 if (!renderbuffer
) {
6104 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
6105 "glRenderbufferStorageMultisampleCHROMIUM",
6106 "no renderbuffer bound");
6110 if (!ValidateRenderbufferStorageMultisample(
6111 samples
, internalformat
, width
, height
)) {
6115 EnsureRenderbufferBound();
6116 GLenum impl_format
=
6117 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6119 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
6120 "glRenderbufferStorageMultisampleCHROMIUM");
6121 RenderbufferStorageMultisampleHelper(
6122 feature_info_
.get(), target
, samples
, impl_format
, width
, height
);
6124 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
6125 if (error
== GL_NO_ERROR
) {
6126 if (workarounds().validate_multisample_buffer_allocation
) {
6127 if (!VerifyMultisampleRenderbufferIntegrity(
6128 renderbuffer
->service_id(), impl_format
)) {
6131 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
6136 // TODO(gman): If renderbuffers tracked which framebuffers they were
6137 // attached to we could just mark those framebuffers as not complete.
6138 framebuffer_manager()->IncFramebufferStateChangeCount();
6139 renderbuffer_manager()->SetInfo(
6140 renderbuffer
, samples
, internalformat
, width
, height
);
6144 // This is the handler for multisampled_render_to_texture extensions.
6145 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
6146 GLenum target
, GLsizei samples
, GLenum internalformat
,
6147 GLsizei width
, GLsizei height
) {
6148 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
6149 if (!renderbuffer
) {
6150 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
6151 "glRenderbufferStorageMultisampleEXT",
6152 "no renderbuffer bound");
6156 if (!ValidateRenderbufferStorageMultisample(
6157 samples
, internalformat
, width
, height
)) {
6161 EnsureRenderbufferBound();
6162 GLenum impl_format
=
6163 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6165 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
6166 if (features().use_img_for_multisampled_render_to_texture
) {
6167 glRenderbufferStorageMultisampleIMG(
6168 target
, samples
, impl_format
, width
, height
);
6170 glRenderbufferStorageMultisampleEXT(
6171 target
, samples
, impl_format
, width
, height
);
6173 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
6174 if (error
== GL_NO_ERROR
) {
6175 // TODO(gman): If renderbuffers tracked which framebuffers they were
6176 // attached to we could just mark those framebuffers as not complete.
6177 framebuffer_manager()->IncFramebufferStateChangeCount();
6178 renderbuffer_manager()->SetInfo(
6179 renderbuffer
, samples
, internalformat
, width
, height
);
6183 // This function validates the allocation of a multisampled renderbuffer
6184 // by clearing it to a key color, blitting the contents to a texture, and
6185 // reading back the color to ensure it matches the key.
6186 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
6187 GLuint renderbuffer
, GLenum format
) {
6189 // Only validate color buffers.
6190 // These formats have been selected because they are very common or are known
6191 // to be used by the WebGL backbuffer. If problems are observed with other
6192 // color formats they can be added here.
6203 GLint draw_framebuffer
, read_framebuffer
;
6205 // Cache framebuffer and texture bindings.
6206 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING
, &draw_framebuffer
);
6207 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING
, &read_framebuffer
);
6209 if (!validation_texture_
) {
6210 GLint bound_texture
;
6211 glGetIntegerv(GL_TEXTURE_BINDING_2D
, &bound_texture
);
6213 // Create additional resources needed for the verification.
6214 glGenTextures(1, &validation_texture_
);
6215 glGenFramebuffersEXT(1, &validation_fbo_multisample_
);
6216 glGenFramebuffersEXT(1, &validation_fbo_
);
6218 // Texture only needs to be 1x1.
6219 glBindTexture(GL_TEXTURE_2D
, validation_texture_
);
6220 // TODO(erikchen): When Chrome on Mac is linked against an OSX 10.9+ SDK, a
6221 // multisample will fail if the color format of the source and destination
6222 // do not match. Here, we assume that the source is GL_RGBA, and make the
6223 // destination GL_RGBA. http://crbug.com/484203
6224 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, 1, 1, 0, GL_RGBA
,
6225 GL_UNSIGNED_BYTE
, NULL
);
6227 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
6228 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
6229 GL_TEXTURE_2D
, validation_texture_
, 0);
6231 glBindTexture(GL_TEXTURE_2D
, bound_texture
);
6234 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
6235 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
6236 GL_RENDERBUFFER
, renderbuffer
);
6238 // Cache current state and reset it to the values we require.
6239 GLboolean scissor_enabled
= false;
6240 glGetBooleanv(GL_SCISSOR_TEST
, &scissor_enabled
);
6241 if (scissor_enabled
)
6242 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
6244 GLboolean color_mask
[4] = {GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
};
6245 glGetBooleanv(GL_COLOR_WRITEMASK
, color_mask
);
6246 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
6248 GLfloat clear_color
[4] = {0.0f
, 0.0f
, 0.0f
, 0.0f
};
6249 glGetFloatv(GL_COLOR_CLEAR_VALUE
, clear_color
);
6250 glClearColor(1.0f
, 0.0f
, 1.0f
, 1.0f
);
6252 // Clear the buffer to the desired key color.
6253 glClear(GL_COLOR_BUFFER_BIT
);
6255 // Blit from the multisample buffer to a standard texture.
6256 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, validation_fbo_multisample_
);
6257 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, validation_fbo_
);
6259 BlitFramebufferHelper(
6260 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
6262 // Read a pixel from the buffer.
6263 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
6265 unsigned char pixel
[3] = {0, 0, 0};
6266 glReadPixels(0, 0, 1, 1, GL_RGB
, GL_UNSIGNED_BYTE
, &pixel
);
6268 // Detach the renderbuffer.
6269 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
6270 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
6271 GL_RENDERBUFFER
, 0);
6273 // Restore cached state.
6274 if (scissor_enabled
)
6275 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
6277 state_
.SetDeviceColorMask(
6278 color_mask
[0], color_mask
[1], color_mask
[2], color_mask
[3]);
6279 glClearColor(clear_color
[0], clear_color
[1], clear_color
[2], clear_color
[3]);
6280 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, draw_framebuffer
);
6281 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, read_framebuffer
);
6283 // Return true if the pixel matched the desired key color.
6284 return (pixel
[0] == 0xFF &&
6289 void GLES2DecoderImpl::DoRenderbufferStorage(
6290 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
) {
6291 Renderbuffer
* renderbuffer
=
6292 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
6293 if (!renderbuffer
) {
6295 GL_INVALID_OPERATION
,
6296 "glRenderbufferStorage", "no renderbuffer bound");
6300 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
6301 height
> renderbuffer_manager()->max_renderbuffer_size()) {
6303 GL_INVALID_VALUE
, "glRenderbufferStorage", "dimensions too large");
6307 uint32 estimated_size
= 0;
6308 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6309 width
, height
, 1, internalformat
, &estimated_size
)) {
6311 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "dimensions too large");
6315 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
6317 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "out of memory");
6321 EnsureRenderbufferBound();
6322 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
6323 glRenderbufferStorageEXT(
6325 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6329 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
6330 if (error
== GL_NO_ERROR
) {
6331 // TODO(gman): If tetxures tracked which framebuffers they were attached to
6332 // we could just mark those framebuffers as not complete.
6333 framebuffer_manager()->IncFramebufferStateChangeCount();
6334 renderbuffer_manager()->SetInfo(
6335 renderbuffer
, 1, internalformat
, width
, height
);
6339 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id
) {
6340 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
6341 SCOPED_UMA_HISTOGRAM_TIMER("GPU.DoLinkProgramTime");
6342 Program
* program
= GetProgramInfoNotShader(
6343 program_id
, "glLinkProgram");
6348 LogClientServiceForInfo(program
, program_id
, "glLinkProgram");
6349 if (program
->Link(shader_manager(),
6350 workarounds().count_all_in_varyings_packing
?
6351 Program::kCountAll
: Program::kCountOnlyStaticallyUsed
,
6352 shader_cache_callback_
)) {
6353 if (program
== state_
.current_program
.get()) {
6354 if (workarounds().use_current_program_after_successful_link
)
6355 glUseProgram(program
->service_id());
6356 if (workarounds().clear_uniforms_before_first_program_use
)
6357 program_manager()->ClearUniforms(program
);
6361 // LinkProgram can be very slow. Exit command processing to allow for
6362 // context preemption and GPU watchdog checks.
6363 ExitCommandProcessingEarly();
6366 void GLES2DecoderImpl::DoReadBuffer(GLenum src
) {
6373 GLenum upper_limit
= static_cast<GLenum
>(
6374 group_
->max_color_attachments() + GL_COLOR_ATTACHMENT0
);
6375 if (src
< GL_COLOR_ATTACHMENT0
|| src
>= upper_limit
) {
6377 GL_INVALID_ENUM
, "glReadBuffer", "invalid enum for src");
6384 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER
);
6386 if (src
== GL_BACK
) {
6388 GL_INVALID_ENUM
, "glReadBuffer",
6389 "invalid src for a named framebuffer");
6392 framebuffer
->set_read_buffer(src
);
6394 if (src
!= GL_NONE
&& src
!= GL_BACK
) {
6396 GL_INVALID_ENUM
, "glReadBuffer",
6397 "invalid src for the default framebuffer");
6400 back_buffer_read_buffer_
= src
;
6401 if (GetBackbufferServiceId() && src
== GL_BACK
)
6402 src
= GL_COLOR_ATTACHMENT0
;
6407 void GLES2DecoderImpl::DoSamplerParameterfv(
6408 GLuint sampler
, GLenum pname
, const GLfloat
* params
) {
6410 glSamplerParameterf(sampler
, pname
, params
[0]);
6413 void GLES2DecoderImpl::DoSamplerParameteriv(
6414 GLuint sampler
, GLenum pname
, const GLint
* params
) {
6416 glSamplerParameteri(sampler
, pname
, params
[0]);
6419 void GLES2DecoderImpl::DoTexParameterf(
6420 GLenum target
, GLenum pname
, GLfloat param
) {
6421 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6424 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterf", "unknown texture");
6428 texture_manager()->SetParameterf(
6429 "glTexParameterf", GetErrorState(), texture
, pname
, param
);
6432 void GLES2DecoderImpl::DoTexParameteri(
6433 GLenum target
, GLenum pname
, GLint param
) {
6434 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6437 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameteri", "unknown texture");
6441 texture_manager()->SetParameteri(
6442 "glTexParameteri", GetErrorState(), texture
, pname
, param
);
6445 void GLES2DecoderImpl::DoTexParameterfv(
6446 GLenum target
, GLenum pname
, const GLfloat
* params
) {
6447 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6450 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterfv", "unknown texture");
6454 texture_manager()->SetParameterf(
6455 "glTexParameterfv", GetErrorState(), texture
, pname
, *params
);
6458 void GLES2DecoderImpl::DoTexParameteriv(
6459 GLenum target
, GLenum pname
, const GLint
* params
) {
6460 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6464 GL_INVALID_VALUE
, "glTexParameteriv", "unknown texture");
6468 texture_manager()->SetParameteri(
6469 "glTexParameteriv", GetErrorState(), texture
, pname
, *params
);
6472 bool GLES2DecoderImpl::CheckCurrentValuebuffer(const char* function_name
) {
6473 if (!state_
.bound_valuebuffer
.get()) {
6474 // There is no valuebuffer bound
6475 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6476 "no valuebuffer in use");
6482 bool GLES2DecoderImpl::CheckCurrentValuebufferForSubscription(
6483 GLenum subscription
,
6484 const char* function_name
) {
6485 if (!CheckCurrentValuebuffer(function_name
)) {
6488 if (!state_
.bound_valuebuffer
.get()->IsSubscribed(subscription
)) {
6489 // The valuebuffer is not subscribed to the target
6490 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6491 "valuebuffer is not subscribed");
6497 bool GLES2DecoderImpl::CheckSubscriptionTarget(GLint location
,
6498 GLenum subscription
,
6499 const char* function_name
) {
6500 if (!CheckCurrentProgramForUniform(location
, function_name
)) {
6503 GLint real_location
= -1;
6504 GLint array_index
= -1;
6505 const Program::UniformInfo
* info
=
6506 state_
.current_program
->GetUniformInfoByFakeLocation(
6507 location
, &real_location
, &array_index
);
6509 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
, "unknown location");
6512 if ((ValuebufferManager::ApiTypeForSubscriptionTarget(subscription
) &
6513 info
->accepts_api_type
) == 0) {
6514 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6515 "wrong type for subscription");
6521 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name
) {
6522 if (!state_
.current_program
.get()) {
6523 // The program does not exist.
6525 GL_INVALID_OPERATION
, function_name
, "no program in use");
6528 if (!state_
.current_program
->InUse()) {
6530 GL_INVALID_OPERATION
, function_name
, "program not linked");
6536 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
6537 GLint location
, const char* function_name
) {
6538 if (!CheckCurrentProgram(function_name
)) {
6541 return location
!= -1;
6544 bool GLES2DecoderImpl::CheckDrawingFeedbackLoops() {
6545 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
6548 const Framebuffer::Attachment
* attachment
=
6549 framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
);
6553 DCHECK(state_
.current_program
.get());
6554 const Program::SamplerIndices
& sampler_indices
=
6555 state_
.current_program
->sampler_indices();
6556 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6557 const Program::UniformInfo
* uniform_info
=
6558 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6559 DCHECK(uniform_info
);
6560 if (uniform_info
->type
!= GL_SAMPLER_2D
)
6562 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6563 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6564 if (texture_unit_index
>= state_
.texture_units
.size())
6566 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6567 TextureRef
* texture_ref
=
6568 texture_unit
.GetInfoForSamplerType(GL_SAMPLER_2D
).get();
6569 if (attachment
->IsTexture(texture_ref
))
6576 bool GLES2DecoderImpl::CheckUniformForApiType(
6577 const Program::UniformInfo
* info
,
6578 const char* function_name
,
6579 Program::UniformApiType api_type
) {
6581 if ((api_type
& info
->accepts_api_type
) == 0) {
6582 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6583 "wrong uniform function for type");
6589 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
6590 GLint fake_location
,
6591 const char* function_name
,
6592 Program::UniformApiType api_type
,
6593 GLint
* real_location
,
6598 DCHECK(real_location
);
6600 if (!CheckCurrentProgramForUniform(fake_location
, function_name
)) {
6603 GLint array_index
= -1;
6604 const Program::UniformInfo
* info
=
6605 state_
.current_program
->GetUniformInfoByFakeLocation(
6606 fake_location
, real_location
, &array_index
);
6609 GL_INVALID_OPERATION
, function_name
, "unknown location");
6612 if (!CheckUniformForApiType(info
, function_name
, api_type
)) {
6615 if (*count
> 1 && !info
->is_array
) {
6617 GL_INVALID_OPERATION
, function_name
, "count > 1 for non-array");
6620 *count
= std::min(info
->size
- array_index
, *count
);
6628 void GLES2DecoderImpl::DoUniform1i(GLint fake_location
, GLint v0
) {
6631 GLint real_location
= -1;
6632 if (!PrepForSetUniformByLocation(fake_location
,
6634 Program::kUniform1i
,
6640 if (!state_
.current_program
->SetSamplers(
6641 state_
.texture_units
.size(), fake_location
, 1, &v0
)) {
6643 GL_INVALID_VALUE
, "glUniform1i", "texture unit out of range");
6646 glUniform1i(real_location
, v0
);
6649 void GLES2DecoderImpl::DoUniform1iv(
6650 GLint fake_location
, GLsizei count
, const GLint
*value
) {
6652 GLint real_location
= -1;
6653 if (!PrepForSetUniformByLocation(fake_location
,
6655 Program::kUniform1i
,
6661 if (type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_2D_RECT_ARB
||
6662 type
== GL_SAMPLER_CUBE
|| type
== GL_SAMPLER_EXTERNAL_OES
) {
6663 if (!state_
.current_program
->SetSamplers(
6664 state_
.texture_units
.size(), fake_location
, count
, value
)) {
6666 GL_INVALID_VALUE
, "glUniform1iv", "texture unit out of range");
6670 glUniform1iv(real_location
, count
, value
);
6673 void GLES2DecoderImpl::DoUniform1fv(
6674 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6676 GLint real_location
= -1;
6677 if (!PrepForSetUniformByLocation(fake_location
,
6679 Program::kUniform1f
,
6685 if (type
== GL_BOOL
) {
6686 scoped_ptr
<GLint
[]> temp(new GLint
[count
]);
6687 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
6688 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6690 DoUniform1iv(real_location
, count
, temp
.get());
6692 glUniform1fv(real_location
, count
, value
);
6696 void GLES2DecoderImpl::DoUniform2fv(
6697 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6699 GLint real_location
= -1;
6700 if (!PrepForSetUniformByLocation(fake_location
,
6702 Program::kUniform2f
,
6708 if (type
== GL_BOOL_VEC2
) {
6709 GLsizei num_values
= count
* 2;
6710 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6711 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6712 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6714 glUniform2iv(real_location
, count
, temp
.get());
6716 glUniform2fv(real_location
, count
, value
);
6720 void GLES2DecoderImpl::DoUniform3fv(
6721 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6723 GLint real_location
= -1;
6724 if (!PrepForSetUniformByLocation(fake_location
,
6726 Program::kUniform3f
,
6732 if (type
== GL_BOOL_VEC3
) {
6733 GLsizei num_values
= count
* 3;
6734 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6735 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6736 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6738 glUniform3iv(real_location
, count
, temp
.get());
6740 glUniform3fv(real_location
, count
, value
);
6744 void GLES2DecoderImpl::DoUniform4fv(
6745 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6747 GLint real_location
= -1;
6748 if (!PrepForSetUniformByLocation(fake_location
,
6750 Program::kUniform4f
,
6756 if (type
== GL_BOOL_VEC4
) {
6757 GLsizei num_values
= count
* 4;
6758 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6759 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6760 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6762 glUniform4iv(real_location
, count
, temp
.get());
6764 glUniform4fv(real_location
, count
, value
);
6768 void GLES2DecoderImpl::DoUniform2iv(
6769 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6771 GLint real_location
= -1;
6772 if (!PrepForSetUniformByLocation(fake_location
,
6774 Program::kUniform2i
,
6780 glUniform2iv(real_location
, count
, value
);
6783 void GLES2DecoderImpl::DoUniform3iv(
6784 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6786 GLint real_location
= -1;
6787 if (!PrepForSetUniformByLocation(fake_location
,
6789 Program::kUniform3i
,
6795 glUniform3iv(real_location
, count
, value
);
6798 void GLES2DecoderImpl::DoUniform4iv(
6799 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6801 GLint real_location
= -1;
6802 if (!PrepForSetUniformByLocation(fake_location
,
6804 Program::kUniform4i
,
6810 glUniform4iv(real_location
, count
, value
);
6813 void GLES2DecoderImpl::DoUniformMatrix2fv(
6814 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6815 const GLfloat
* value
) {
6817 GLint real_location
= -1;
6818 if (!PrepForSetUniformByLocation(fake_location
,
6819 "glUniformMatrix2fv",
6820 Program::kUniformMatrix2f
,
6826 glUniformMatrix2fv(real_location
, count
, transpose
, value
);
6829 void GLES2DecoderImpl::DoUniformMatrix3fv(
6830 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6831 const GLfloat
* value
) {
6833 GLint real_location
= -1;
6834 if (!PrepForSetUniformByLocation(fake_location
,
6835 "glUniformMatrix3fv",
6836 Program::kUniformMatrix3f
,
6842 glUniformMatrix3fv(real_location
, count
, transpose
, value
);
6845 void GLES2DecoderImpl::DoUniformMatrix4fv(
6846 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6847 const GLfloat
* value
) {
6849 GLint real_location
= -1;
6850 if (!PrepForSetUniformByLocation(fake_location
,
6851 "glUniformMatrix4fv",
6852 Program::kUniformMatrix4f
,
6858 glUniformMatrix4fv(real_location
, count
, transpose
, value
);
6861 void GLES2DecoderImpl::DoUseProgram(GLuint program_id
) {
6862 GLuint service_id
= 0;
6863 Program
* program
= NULL
;
6865 program
= GetProgramInfoNotShader(program_id
, "glUseProgram");
6869 if (!program
->IsValid()) {
6870 // Program was not linked successfully. (ie, glLinkProgram)
6872 GL_INVALID_OPERATION
, "glUseProgram", "program not linked");
6875 service_id
= program
->service_id();
6877 if (state_
.current_program
.get()) {
6878 program_manager()->UnuseProgram(shader_manager(),
6879 state_
.current_program
.get());
6881 state_
.current_program
= program
;
6882 LogClientServiceMapping("glUseProgram", program_id
, service_id
);
6883 glUseProgram(service_id
);
6884 if (state_
.current_program
.get()) {
6885 program_manager()->UseProgram(state_
.current_program
.get());
6886 if (workarounds().clear_uniforms_before_first_program_use
)
6887 program_manager()->ClearUniforms(program
);
6891 void GLES2DecoderImpl::RenderWarning(
6892 const char* filename
, int line
, const std::string
& msg
) {
6893 logger_
.LogMessage(filename
, line
, std::string("RENDER WARNING: ") + msg
);
6896 void GLES2DecoderImpl::PerformanceWarning(
6897 const char* filename
, int line
, const std::string
& msg
) {
6898 logger_
.LogMessage(filename
, line
,
6899 std::string("PERFORMANCE WARNING: ") + msg
);
6902 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
6903 Texture
* texture
, GLenum textarget
) {
6904 // Image is already in use if texture is attached to a framebuffer.
6905 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
6906 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6908 ScopedGLErrorSuppressor
suppressor(
6909 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
6911 glBindTexture(textarget
, texture
->service_id());
6912 image
->WillUseTexImage();
6913 RestoreCurrentTextureBindings(&state_
, textarget
);
6918 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6919 Texture
* texture
, GLenum textarget
) {
6920 // Image is still in use if texture is attached to a framebuffer.
6921 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
6922 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6924 ScopedGLErrorSuppressor
suppressor(
6925 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6927 glBindTexture(textarget
, texture
->service_id());
6928 image
->DidUseTexImage();
6929 RestoreCurrentTextureBindings(&state_
, textarget
);
6934 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6935 DCHECK(state_
.current_program
.get());
6936 if (!texture_manager()->HaveUnrenderableTextures() &&
6937 !texture_manager()->HaveImages()) {
6941 bool textures_set
= false;
6942 const Program::SamplerIndices
& sampler_indices
=
6943 state_
.current_program
->sampler_indices();
6944 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6945 const Program::UniformInfo
* uniform_info
=
6946 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6947 DCHECK(uniform_info
);
6948 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6949 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6950 if (texture_unit_index
< state_
.texture_units
.size()) {
6951 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6952 TextureRef
* texture_ref
=
6953 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6954 GLenum textarget
= GetBindTargetForSamplerType(uniform_info
->type
);
6955 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
6956 textures_set
= true;
6957 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6960 texture_manager()->black_texture_id(uniform_info
->type
));
6962 LOCAL_RENDER_WARNING(
6963 std::string("there is no texture bound to the unit ") +
6964 base::IntToString(texture_unit_index
));
6966 LOCAL_RENDER_WARNING(
6967 std::string("texture bound to texture unit ") +
6968 base::IntToString(texture_unit_index
) +
6969 " is not renderable. It maybe non-power-of-2 and have"
6970 " incompatible texture filtering.");
6975 if (textarget
!= GL_TEXTURE_CUBE_MAP
) {
6976 Texture
* texture
= texture_ref
->texture();
6977 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6978 if (image
&& !texture
->IsAttachedToFramebuffer()) {
6979 ScopedGLErrorSuppressor
suppressor(
6980 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6981 textures_set
= true;
6982 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6983 image
->WillUseTexImage();
6988 // else: should this be an error?
6991 return !textures_set
;
6994 void GLES2DecoderImpl::RestoreStateForTextures() {
6995 DCHECK(state_
.current_program
.get());
6996 const Program::SamplerIndices
& sampler_indices
=
6997 state_
.current_program
->sampler_indices();
6998 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6999 const Program::UniformInfo
* uniform_info
=
7000 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
7001 DCHECK(uniform_info
);
7002 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
7003 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
7004 if (texture_unit_index
< state_
.texture_units
.size()) {
7005 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
7006 TextureRef
* texture_ref
=
7007 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
7008 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
7009 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
7010 // Get the texture_ref info that was previously bound here.
7011 texture_ref
= texture_unit
.bind_target
== GL_TEXTURE_2D
7012 ? texture_unit
.bound_texture_2d
.get()
7013 : texture_unit
.bound_texture_cube_map
.get();
7014 glBindTexture(texture_unit
.bind_target
,
7015 texture_ref
? texture_ref
->service_id() : 0);
7019 if (texture_unit
.bind_target
!= GL_TEXTURE_CUBE_MAP
) {
7020 Texture
* texture
= texture_ref
->texture();
7021 gfx::GLImage
* image
=
7022 texture
->GetLevelImage(texture_unit
.bind_target
, 0);
7023 if (image
&& !texture
->IsAttachedToFramebuffer()) {
7024 ScopedGLErrorSuppressor
suppressor(
7025 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
7026 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
7027 image
->DidUseTexImage();
7034 // Set the active texture back to whatever the user had it as.
7035 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
7038 bool GLES2DecoderImpl::ClearUnclearedTextures() {
7039 // Only check if there are some uncleared textures.
7040 if (!texture_manager()->HaveUnsafeTextures()) {
7044 // 1: Check all textures we are about to render with.
7045 if (state_
.current_program
.get()) {
7046 const Program::SamplerIndices
& sampler_indices
=
7047 state_
.current_program
->sampler_indices();
7048 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
7049 const Program::UniformInfo
* uniform_info
=
7050 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
7051 DCHECK(uniform_info
);
7052 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
7053 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
7054 if (texture_unit_index
< state_
.texture_units
.size()) {
7055 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
7056 TextureRef
* texture_ref
=
7057 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
7058 if (texture_ref
&& !texture_ref
->texture()->SafeToRenderFrom()) {
7059 if (!texture_manager()->ClearRenderableLevels(this, texture_ref
)) {
7070 bool GLES2DecoderImpl::IsDrawValid(
7071 const char* function_name
, GLuint max_vertex_accessed
, bool instanced
,
7072 GLsizei primcount
) {
7073 DCHECK(instanced
|| primcount
== 1);
7075 // NOTE: We specifically do not check current_program->IsValid() because
7076 // it could never be invalid since glUseProgram would have failed. While
7077 // glLinkProgram could later mark the program as invalid the previous
7078 // valid program will still function if it is still the current program.
7079 if (!state_
.current_program
.get()) {
7080 // The program does not exist.
7081 // But GL says no ERROR.
7082 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
7086 if (CheckDrawingFeedbackLoops()) {
7088 GL_INVALID_OPERATION
, function_name
,
7089 "Source and destination textures of the draw are the same.");
7093 return state_
.vertex_attrib_manager
7094 ->ValidateBindings(function_name
,
7096 feature_info_
.get(),
7097 state_
.current_program
.get(),
7098 max_vertex_accessed
,
7103 bool GLES2DecoderImpl::SimulateAttrib0(
7104 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
) {
7108 if (feature_info_
->gl_version_info().BehavesLikeGLES())
7111 const VertexAttrib
* attrib
=
7112 state_
.vertex_attrib_manager
->GetVertexAttrib(0);
7113 // If it's enabled or it's not used then we don't need to do anything.
7114 bool attrib_0_used
=
7115 state_
.current_program
->GetAttribInfoByLocation(0) != NULL
;
7116 if (attrib
->enabled() && attrib_0_used
) {
7120 // Make a buffer with a single repeated vec4 value enough to
7121 // simulate the constant value that is supposed to be here.
7122 // This is required to emulate GLES2 on GL.
7123 GLuint num_vertices
= max_vertex_accessed
+ 1;
7124 uint32 size_needed
= 0;
7126 if (num_vertices
== 0 ||
7127 !SafeMultiplyUint32(num_vertices
, sizeof(Vec4f
), &size_needed
) ||
7128 size_needed
> 0x7FFFFFFFU
) {
7129 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
7133 LOCAL_PERFORMANCE_WARNING(
7134 "Attribute 0 is disabled. This has signficant performance penalty");
7136 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
7137 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
7139 bool new_buffer
= static_cast<GLsizei
>(size_needed
) > attrib_0_size_
;
7141 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
7142 GLenum error
= glGetError();
7143 if (error
!= GL_NO_ERROR
) {
7145 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
7150 const Vec4
& value
= state_
.attrib_values
[0];
7153 (!attrib_0_buffer_matches_value_
|| !value
.Equal(attrib_0_value_
)))){
7154 // TODO(zmo): This is not 100% correct because we might lose data when
7155 // casting to float type, but it is a corner case and once we migrate to
7156 // core profiles on desktop GL, it is no longer relevant.
7157 Vec4f
fvalue(value
);
7158 std::vector
<Vec4f
> temp(num_vertices
, fvalue
);
7159 glBufferSubData(GL_ARRAY_BUFFER
, 0, size_needed
, &temp
[0].v
[0]);
7160 attrib_0_buffer_matches_value_
= true;
7161 attrib_0_value_
= value
;
7162 attrib_0_size_
= size_needed
;
7165 glVertexAttribPointer(0, 4, GL_FLOAT
, GL_FALSE
, 0, NULL
);
7167 if (attrib
->divisor())
7168 glVertexAttribDivisorANGLE(0, 0);
7174 void GLES2DecoderImpl::RestoreStateForAttrib(
7175 GLuint attrib_index
, bool restore_array_binding
) {
7176 const VertexAttrib
* attrib
=
7177 state_
.vertex_attrib_manager
->GetVertexAttrib(attrib_index
);
7178 if (restore_array_binding
) {
7179 const void* ptr
= reinterpret_cast<const void*>(attrib
->offset());
7180 Buffer
* buffer
= attrib
->buffer();
7181 glBindBuffer(GL_ARRAY_BUFFER
, buffer
? buffer
->service_id() : 0);
7182 glVertexAttribPointer(
7183 attrib_index
, attrib
->size(), attrib
->type(), attrib
->normalized(),
7184 attrib
->gl_stride(), ptr
);
7186 if (attrib
->divisor())
7187 glVertexAttribDivisorANGLE(attrib_index
, attrib
->divisor());
7189 GL_ARRAY_BUFFER
, state_
.bound_array_buffer
.get() ?
7190 state_
.bound_array_buffer
->service_id() : 0);
7192 // Never touch vertex attribute 0's state (in particular, never
7193 // disable it) when running on desktop GL because it will never be
7195 if (attrib_index
!= 0 ||
7196 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
7197 if (attrib
->enabled()) {
7198 glEnableVertexAttribArray(attrib_index
);
7200 glDisableVertexAttribArray(attrib_index
);
7205 bool GLES2DecoderImpl::SimulateFixedAttribs(
7206 const char* function_name
,
7207 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
) {
7210 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
)
7213 if (!state_
.vertex_attrib_manager
->HaveFixedAttribs()) {
7217 LOCAL_PERFORMANCE_WARNING(
7218 "GL_FIXED attributes have a signficant performance penalty");
7220 // NOTE: we could be smart and try to check if a buffer is used
7221 // twice in 2 different attribs, find the overlapping parts and therefore
7222 // duplicate the minimum amount of data but this whole code path is not meant
7223 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
7224 // tests so we just add to the buffer attrib used.
7226 GLuint elements_needed
= 0;
7227 const VertexAttribManager::VertexAttribList
& enabled_attribs
=
7228 state_
.vertex_attrib_manager
->GetEnabledVertexAttribs();
7229 for (VertexAttribManager::VertexAttribList::const_iterator it
=
7230 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
7231 const VertexAttrib
* attrib
= *it
;
7232 const Program::VertexAttrib
* attrib_info
=
7233 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
7234 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
7235 max_vertex_accessed
);
7236 GLuint num_vertices
= max_accessed
+ 1;
7237 if (num_vertices
== 0) {
7239 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
7243 attrib
->CanAccess(max_accessed
) &&
7244 attrib
->type() == GL_FIXED
) {
7245 uint32 elements_used
= 0;
7246 if (!SafeMultiplyUint32(num_vertices
, attrib
->size(), &elements_used
) ||
7247 !SafeAddUint32(elements_needed
, elements_used
, &elements_needed
)) {
7249 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
7255 const uint32 kSizeOfFloat
= sizeof(float); // NOLINT
7256 uint32 size_needed
= 0;
7257 if (!SafeMultiplyUint32(elements_needed
, kSizeOfFloat
, &size_needed
) ||
7258 size_needed
> 0x7FFFFFFFU
) {
7260 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
7264 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
7266 glBindBuffer(GL_ARRAY_BUFFER
, fixed_attrib_buffer_id_
);
7267 if (static_cast<GLsizei
>(size_needed
) > fixed_attrib_buffer_size_
) {
7268 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
7269 GLenum error
= glGetError();
7270 if (error
!= GL_NO_ERROR
) {
7272 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
7277 // Copy the elements and convert to float
7278 GLintptr offset
= 0;
7279 for (VertexAttribManager::VertexAttribList::const_iterator it
=
7280 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
7281 const VertexAttrib
* attrib
= *it
;
7282 const Program::VertexAttrib
* attrib_info
=
7283 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
7284 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
7285 max_vertex_accessed
);
7286 GLuint num_vertices
= max_accessed
+ 1;
7287 if (num_vertices
== 0) {
7289 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
7293 attrib
->CanAccess(max_accessed
) &&
7294 attrib
->type() == GL_FIXED
) {
7295 int num_elements
= attrib
->size() * num_vertices
;
7296 const int src_size
= num_elements
* sizeof(int32
);
7297 const int dst_size
= num_elements
* sizeof(float);
7298 scoped_ptr
<float[]> data(new float[num_elements
]);
7299 const int32
* src
= reinterpret_cast<const int32
*>(
7300 attrib
->buffer()->GetRange(attrib
->offset(), src_size
));
7301 const int32
* end
= src
+ num_elements
;
7302 float* dst
= data
.get();
7303 while (src
!= end
) {
7304 *dst
++ = static_cast<float>(*src
++) / 65536.0f
;
7306 glBufferSubData(GL_ARRAY_BUFFER
, offset
, dst_size
, data
.get());
7307 glVertexAttribPointer(
7308 attrib
->index(), attrib
->size(), GL_FLOAT
, false, 0,
7309 reinterpret_cast<GLvoid
*>(offset
));
7317 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
7318 // There's no need to call glVertexAttribPointer because we shadow all the
7319 // settings and passing GL_FIXED to it will not work.
7322 state_
.bound_array_buffer
.get() ? state_
.bound_array_buffer
->service_id()
7326 error::Error
GLES2DecoderImpl::DoDrawArrays(
7327 const char* function_name
,
7332 GLsizei primcount
) {
7333 error::Error error
= WillAccessBoundFramebufferForDraw();
7334 if (error
!= error::kNoError
)
7336 if (!validators_
->draw_mode
.IsValid(mode
)) {
7337 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
7338 return error::kNoError
;
7341 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
7342 return error::kNoError
;
7344 if (primcount
< 0) {
7345 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
7346 return error::kNoError
;
7348 if (!CheckBoundFramebuffersValid(function_name
)) {
7349 return error::kNoError
;
7351 // We have to check this here because the prototype for glDrawArrays
7352 // is GLint not GLsizei.
7354 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "first < 0");
7355 return error::kNoError
;
7358 if (count
== 0 || primcount
== 0) {
7359 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
7360 return error::kNoError
;
7363 GLuint max_vertex_accessed
= first
+ count
- 1;
7364 if (IsDrawValid(function_name
, max_vertex_accessed
, instanced
, primcount
)) {
7365 if (!ClearUnclearedTextures()) {
7366 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
7367 return error::kNoError
;
7369 bool simulated_attrib_0
= false;
7370 if (!SimulateAttrib0(
7371 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
7372 return error::kNoError
;
7374 bool simulated_fixed_attribs
= false;
7375 if (SimulateFixedAttribs(
7376 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
7378 bool textures_set
= !PrepareTexturesForRender();
7380 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
7382 glDrawArrays(mode
, first
, count
);
7384 glDrawArraysInstancedANGLE(mode
, first
, count
, primcount
);
7387 RestoreStateForTextures();
7389 if (simulated_fixed_attribs
) {
7390 RestoreStateForSimulatedFixedAttribs();
7393 if (simulated_attrib_0
) {
7394 // We don't have to restore attrib 0 generic data at the end of this
7395 // function even if it is simulated. This is because we will simulate
7396 // it in each draw call, and attrib 0 generic data queries use cached
7397 // values instead of passing down to the underlying driver.
7398 RestoreStateForAttrib(0, false);
7401 return error::kNoError
;
7404 error::Error
GLES2DecoderImpl::HandleDrawArrays(uint32 immediate_data_size
,
7405 const void* cmd_data
) {
7406 // TODO(zmo): crbug.com/481184
7407 // On Desktop GL with versions lower than 4.3, we need to emulate
7408 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7409 const cmds::DrawArrays
& c
= *static_cast<const cmds::DrawArrays
*>(cmd_data
);
7410 return DoDrawArrays("glDrawArrays",
7412 static_cast<GLenum
>(c
.mode
),
7413 static_cast<GLint
>(c
.first
),
7414 static_cast<GLsizei
>(c
.count
),
7418 error::Error
GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
7419 uint32 immediate_data_size
,
7420 const void* cmd_data
) {
7421 const gles2::cmds::DrawArraysInstancedANGLE
& c
=
7422 *static_cast<const gles2::cmds::DrawArraysInstancedANGLE
*>(cmd_data
);
7423 if (!features().angle_instanced_arrays
) {
7425 GL_INVALID_OPERATION
,
7426 "glDrawArraysInstancedANGLE", "function not available");
7427 return error::kNoError
;
7429 return DoDrawArrays("glDrawArraysIntancedANGLE",
7431 static_cast<GLenum
>(c
.mode
),
7432 static_cast<GLint
>(c
.first
),
7433 static_cast<GLsizei
>(c
.count
),
7434 static_cast<GLsizei
>(c
.primcount
));
7437 error::Error
GLES2DecoderImpl::DoDrawElements(
7438 const char* function_name
,
7444 GLsizei primcount
) {
7445 error::Error error
= WillAccessBoundFramebufferForDraw();
7446 if (error
!= error::kNoError
)
7448 if (!state_
.vertex_attrib_manager
->element_array_buffer()) {
7450 GL_INVALID_OPERATION
, function_name
, "No element array buffer bound");
7451 return error::kNoError
;
7455 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
7456 return error::kNoError
;
7459 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "offset < 0");
7460 return error::kNoError
;
7462 if (!validators_
->draw_mode
.IsValid(mode
)) {
7463 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
7464 return error::kNoError
;
7466 if (!validators_
->index_type
.IsValid(type
)) {
7467 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, type
, "type");
7468 return error::kNoError
;
7470 if (primcount
< 0) {
7471 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
7472 return error::kNoError
;
7475 if (!CheckBoundFramebuffersValid(function_name
)) {
7476 return error::kNoError
;
7479 if (count
== 0 || primcount
== 0) {
7480 return error::kNoError
;
7483 GLuint max_vertex_accessed
;
7484 Buffer
* element_array_buffer
=
7485 state_
.vertex_attrib_manager
->element_array_buffer();
7487 if (!element_array_buffer
->GetMaxValueForRange(
7488 offset
, count
, type
, &max_vertex_accessed
)) {
7490 GL_INVALID_OPERATION
, function_name
, "range out of bounds for buffer");
7491 return error::kNoError
;
7494 if (IsDrawValid(function_name
, max_vertex_accessed
, instanced
, primcount
)) {
7495 if (!ClearUnclearedTextures()) {
7496 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
7497 return error::kNoError
;
7499 bool simulated_attrib_0
= false;
7500 if (!SimulateAttrib0(
7501 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
7502 return error::kNoError
;
7504 bool simulated_fixed_attribs
= false;
7505 if (SimulateFixedAttribs(
7506 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
7508 bool textures_set
= !PrepareTexturesForRender();
7510 // TODO(gman): Refactor to hide these details in BufferManager or
7511 // VertexAttribManager.
7512 const GLvoid
* indices
= reinterpret_cast<const GLvoid
*>(offset
);
7513 bool used_client_side_array
= false;
7514 if (element_array_buffer
->IsClientSideArray()) {
7515 used_client_side_array
= true;
7516 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
7517 indices
= element_array_buffer
->GetRange(offset
, 0);
7520 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
7522 glDrawElements(mode
, count
, type
, indices
);
7524 glDrawElementsInstancedANGLE(mode
, count
, type
, indices
, primcount
);
7527 if (used_client_side_array
) {
7528 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
7529 element_array_buffer
->service_id());
7533 RestoreStateForTextures();
7535 if (simulated_fixed_attribs
) {
7536 RestoreStateForSimulatedFixedAttribs();
7539 if (simulated_attrib_0
) {
7540 // We don't have to restore attrib 0 generic data at the end of this
7541 // function even if it is simulated. This is because we will simulate
7542 // it in each draw call, and attrib 0 generic data queries use cached
7543 // values instead of passing down to the underlying driver.
7544 RestoreStateForAttrib(0, false);
7547 return error::kNoError
;
7550 error::Error
GLES2DecoderImpl::HandleDrawElements(uint32 immediate_data_size
,
7551 const void* cmd_data
) {
7552 // TODO(zmo): crbug.com/481184
7553 // On Desktop GL with versions lower than 4.3, we need to emulate
7554 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7555 const gles2::cmds::DrawElements
& c
=
7556 *static_cast<const gles2::cmds::DrawElements
*>(cmd_data
);
7557 return DoDrawElements("glDrawElements",
7559 static_cast<GLenum
>(c
.mode
),
7560 static_cast<GLsizei
>(c
.count
),
7561 static_cast<GLenum
>(c
.type
),
7562 static_cast<int32
>(c
.index_offset
),
7566 error::Error
GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
7567 uint32 immediate_data_size
,
7568 const void* cmd_data
) {
7569 const gles2::cmds::DrawElementsInstancedANGLE
& c
=
7570 *static_cast<const gles2::cmds::DrawElementsInstancedANGLE
*>(cmd_data
);
7571 if (!features().angle_instanced_arrays
) {
7573 GL_INVALID_OPERATION
,
7574 "glDrawElementsInstancedANGLE", "function not available");
7575 return error::kNoError
;
7577 return DoDrawElements("glDrawElementsInstancedANGLE",
7579 static_cast<GLenum
>(c
.mode
),
7580 static_cast<GLsizei
>(c
.count
),
7581 static_cast<GLenum
>(c
.type
),
7582 static_cast<int32
>(c
.index_offset
),
7583 static_cast<GLsizei
>(c
.primcount
));
7586 GLuint
GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
7587 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
7588 GLuint max_vertex_accessed
= 0;
7589 Buffer
* buffer
= GetBuffer(buffer_id
);
7591 // TODO(gman): Should this be a GL error or a command buffer error?
7593 GL_INVALID_VALUE
, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
7595 if (!buffer
->GetMaxValueForRange(
7596 offset
, count
, type
, &max_vertex_accessed
)) {
7597 // TODO(gman): Should this be a GL error or a command buffer error?
7599 GL_INVALID_OPERATION
,
7600 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
7603 return max_vertex_accessed
;
7606 void GLES2DecoderImpl::DoShaderSource(
7607 GLuint client_id
, GLsizei count
, const char** data
, const GLint
* length
) {
7609 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
7610 if (length
&& length
[ii
] > 0)
7611 str
.append(data
[ii
], length
[ii
]);
7613 str
.append(data
[ii
]);
7615 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glShaderSource");
7619 // Note: We don't actually call glShaderSource here. We wait until
7620 // we actually compile the shader.
7621 shader
->set_source(str
);
7624 void GLES2DecoderImpl::DoTransformFeedbackVaryings(
7625 GLuint client_program_id
, GLsizei count
, const char* const* varyings
,
7626 GLenum buffer_mode
) {
7627 Program
* program
= GetProgramInfoNotShader(
7628 client_program_id
, "glTransformFeedbackVaryings");
7632 program
->TransformFeedbackVaryings(count
, varyings
, buffer_mode
);
7633 glTransformFeedbackVaryings(
7634 program
->service_id(), count
, varyings
, buffer_mode
);
7637 void GLES2DecoderImpl::DoCompileShader(GLuint client_id
) {
7638 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
7639 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glCompileShader");
7644 scoped_refptr
<ShaderTranslatorInterface
> translator
;
7645 if (use_shader_translator_
) {
7646 translator
= shader
->shader_type() == GL_VERTEX_SHADER
?
7647 vertex_translator_
: fragment_translator_
;
7650 const Shader::TranslatedShaderSourceType source_type
=
7651 feature_info_
->feature_flags().angle_translated_shader_source
?
7652 Shader::kANGLE
: Shader::kGL
;
7653 shader
->RequestCompile(translator
, source_type
);
7656 void GLES2DecoderImpl::DoGetShaderiv(
7657 GLuint shader_id
, GLenum pname
, GLint
* params
) {
7658 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderiv");
7663 // Compile now for statuses that require it.
7665 case GL_COMPILE_STATUS
:
7666 case GL_INFO_LOG_LENGTH
:
7667 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE
:
7668 shader
->DoCompile();
7676 case GL_SHADER_SOURCE_LENGTH
:
7677 *params
= shader
->source().size();
7681 case GL_COMPILE_STATUS
:
7682 *params
= compile_shader_always_succeeds_
? true : shader
->valid();
7684 case GL_INFO_LOG_LENGTH
:
7685 *params
= shader
->log_info().size();
7689 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE
:
7690 *params
= shader
->translated_source().size();
7697 glGetShaderiv(shader
->service_id(), pname
, params
);
7700 error::Error
GLES2DecoderImpl::HandleGetShaderSource(uint32 immediate_data_size
,
7701 const void* cmd_data
) {
7702 const gles2::cmds::GetShaderSource
& c
=
7703 *static_cast<const gles2::cmds::GetShaderSource
*>(cmd_data
);
7704 GLuint shader_id
= c
.shader
;
7705 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7706 Bucket
* bucket
= CreateBucket(bucket_id
);
7707 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderSource");
7708 if (!shader
|| shader
->source().empty()) {
7710 return error::kNoError
;
7712 bucket
->SetFromString(shader
->source().c_str());
7713 return error::kNoError
;
7716 error::Error
GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
7717 uint32 immediate_data_size
,
7718 const void* cmd_data
) {
7719 const gles2::cmds::GetTranslatedShaderSourceANGLE
& c
=
7720 *static_cast<const gles2::cmds::GetTranslatedShaderSourceANGLE
*>(
7722 GLuint shader_id
= c
.shader
;
7723 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7724 Bucket
* bucket
= CreateBucket(bucket_id
);
7725 Shader
* shader
= GetShaderInfoNotProgram(
7726 shader_id
, "glGetTranslatedShaderSourceANGLE");
7729 return error::kNoError
;
7732 // Make sure translator has been utilized in compile.
7733 shader
->DoCompile();
7735 bucket
->SetFromString(shader
->translated_source().c_str());
7736 return error::kNoError
;
7739 error::Error
GLES2DecoderImpl::HandleGetProgramInfoLog(
7740 uint32 immediate_data_size
,
7741 const void* cmd_data
) {
7742 const gles2::cmds::GetProgramInfoLog
& c
=
7743 *static_cast<const gles2::cmds::GetProgramInfoLog
*>(cmd_data
);
7744 GLuint program_id
= c
.program
;
7745 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7746 Bucket
* bucket
= CreateBucket(bucket_id
);
7747 Program
* program
= GetProgramInfoNotShader(
7748 program_id
, "glGetProgramInfoLog");
7749 if (!program
|| !program
->log_info()) {
7750 bucket
->SetFromString("");
7751 return error::kNoError
;
7753 bucket
->SetFromString(program
->log_info()->c_str());
7754 return error::kNoError
;
7757 error::Error
GLES2DecoderImpl::HandleGetShaderInfoLog(
7758 uint32 immediate_data_size
,
7759 const void* cmd_data
) {
7760 const gles2::cmds::GetShaderInfoLog
& c
=
7761 *static_cast<const gles2::cmds::GetShaderInfoLog
*>(cmd_data
);
7762 GLuint shader_id
= c
.shader
;
7763 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7764 Bucket
* bucket
= CreateBucket(bucket_id
);
7765 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderInfoLog");
7767 bucket
->SetFromString("");
7768 return error::kNoError
;
7771 // Shader must be compiled in order to get the info log.
7772 shader
->DoCompile();
7774 bucket
->SetFromString(shader
->log_info().c_str());
7775 return error::kNoError
;
7778 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap
) {
7779 return state_
.GetEnabled(cap
);
7782 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id
) {
7783 const Buffer
* buffer
= GetBuffer(client_id
);
7784 return buffer
&& buffer
->IsValid() && !buffer
->IsDeleted();
7787 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id
) {
7788 const Framebuffer
* framebuffer
=
7789 GetFramebuffer(client_id
);
7790 return framebuffer
&& framebuffer
->IsValid() && !framebuffer
->IsDeleted();
7793 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id
) {
7794 // IsProgram is true for programs as soon as they are created, until they are
7795 // deleted and no longer in use.
7796 const Program
* program
= GetProgram(client_id
);
7797 return program
!= NULL
&& !program
->IsDeleted();
7800 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id
) {
7801 const Renderbuffer
* renderbuffer
=
7802 GetRenderbuffer(client_id
);
7803 return renderbuffer
&& renderbuffer
->IsValid() && !renderbuffer
->IsDeleted();
7806 bool GLES2DecoderImpl::DoIsShader(GLuint client_id
) {
7807 // IsShader is true for shaders as soon as they are created, until they
7808 // are deleted and not attached to any programs.
7809 const Shader
* shader
= GetShader(client_id
);
7810 return shader
!= NULL
&& !shader
->IsDeleted();
7813 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id
) {
7814 const TextureRef
* texture_ref
= GetTexture(client_id
);
7815 return texture_ref
&& texture_ref
->texture()->IsValid();
7818 void GLES2DecoderImpl::DoAttachShader(
7819 GLuint program_client_id
, GLint shader_client_id
) {
7820 Program
* program
= GetProgramInfoNotShader(
7821 program_client_id
, "glAttachShader");
7825 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glAttachShader");
7829 if (!program
->AttachShader(shader_manager(), shader
)) {
7831 GL_INVALID_OPERATION
,
7833 "can not attach more than one shader of the same type.");
7836 glAttachShader(program
->service_id(), shader
->service_id());
7839 void GLES2DecoderImpl::DoDetachShader(
7840 GLuint program_client_id
, GLint shader_client_id
) {
7841 Program
* program
= GetProgramInfoNotShader(
7842 program_client_id
, "glDetachShader");
7846 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glDetachShader");
7850 if (!program
->DetachShader(shader_manager(), shader
)) {
7852 GL_INVALID_OPERATION
,
7853 "glDetachShader", "shader not attached to program");
7856 glDetachShader(program
->service_id(), shader
->service_id());
7859 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id
) {
7860 Program
* program
= GetProgramInfoNotShader(
7861 program_client_id
, "glValidateProgram");
7865 program
->Validate();
7868 void GLES2DecoderImpl::GetVertexAttribHelper(
7869 const VertexAttrib
* attrib
, GLenum pname
, GLint
* params
) {
7871 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
:
7873 Buffer
* buffer
= attrib
->buffer();
7874 if (buffer
&& !buffer
->IsDeleted()) {
7876 buffer_manager()->GetClientId(buffer
->service_id(), &client_id
);
7877 *params
= client_id
;
7881 case GL_VERTEX_ATTRIB_ARRAY_ENABLED
:
7882 *params
= attrib
->enabled();
7884 case GL_VERTEX_ATTRIB_ARRAY_SIZE
:
7885 *params
= attrib
->size();
7887 case GL_VERTEX_ATTRIB_ARRAY_STRIDE
:
7888 *params
= attrib
->gl_stride();
7890 case GL_VERTEX_ATTRIB_ARRAY_TYPE
:
7891 *params
= attrib
->type();
7893 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED
:
7894 *params
= attrib
->normalized();
7896 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR
:
7897 *params
= attrib
->divisor();
7899 case GL_VERTEX_ATTRIB_ARRAY_INTEGER
:
7900 *params
= attrib
->integer();
7908 void GLES2DecoderImpl::DoGetTexParameterfv(
7909 GLenum target
, GLenum pname
, GLfloat
* params
) {
7910 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
7911 glGetTexParameterfv(target
, pname
, params
);
7914 void GLES2DecoderImpl::DoGetTexParameteriv(
7915 GLenum target
, GLenum pname
, GLint
* params
) {
7916 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
7917 glGetTexParameteriv(target
, pname
, params
);
7920 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
7921 GLenum target
, GLenum pname
) {
7922 if (!workarounds().init_texture_max_anisotropy
)
7924 if (pname
!= GL_TEXTURE_MAX_ANISOTROPY_EXT
||
7925 !validators_
->texture_parameter
.IsValid(pname
)) {
7929 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
7933 GL_INVALID_OPERATION
,
7934 "glGetTexParamter{fi}v", "unknown texture for target");
7937 Texture
* texture
= texture_ref
->texture();
7938 texture
->InitTextureMaxAnisotropyIfNeeded(target
);
7941 template <typename T
>
7942 void GLES2DecoderImpl::DoGetVertexAttribImpl(
7943 GLuint index
, GLenum pname
, T
* params
) {
7944 VertexAttrib
* attrib
= state_
.vertex_attrib_manager
->GetVertexAttrib(index
);
7947 GL_INVALID_VALUE
, "glGetVertexAttrib", "index out of range");
7951 case GL_CURRENT_VERTEX_ATTRIB
:
7952 state_
.attrib_values
[index
].GetValues(params
);
7956 GetVertexAttribHelper(attrib
, pname
, &value
);
7957 *params
= static_cast<T
>(value
);
7963 void GLES2DecoderImpl::DoGetVertexAttribfv(
7964 GLuint index
, GLenum pname
, GLfloat
* params
) {
7965 DoGetVertexAttribImpl
<GLfloat
>(index
, pname
, params
);
7968 void GLES2DecoderImpl::DoGetVertexAttribiv(
7969 GLuint index
, GLenum pname
, GLint
* params
) {
7970 DoGetVertexAttribImpl
<GLint
>(index
, pname
, params
);
7973 void GLES2DecoderImpl::DoGetVertexAttribIiv(
7974 GLuint index
, GLenum pname
, GLint
* params
) {
7975 DoGetVertexAttribImpl
<GLint
>(index
, pname
, params
);
7978 void GLES2DecoderImpl::DoGetVertexAttribIuiv(
7979 GLuint index
, GLenum pname
, GLuint
* params
) {
7980 DoGetVertexAttribImpl
<GLuint
>(index
, pname
, params
);
7983 template <typename T
>
7984 bool GLES2DecoderImpl::SetVertexAttribValue(
7985 const char* function_name
, GLuint index
, const T
* value
) {
7986 if (index
>= state_
.attrib_values
.size()) {
7987 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "index out of range");
7990 state_
.attrib_values
[index
].SetValues(value
);
7994 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index
, GLfloat v0
) {
7995 GLfloat v
[4] = { v0
, 0.0f
, 0.0f
, 1.0f
, };
7996 if (SetVertexAttribValue("glVertexAttrib1f", index
, v
)) {
7997 glVertexAttrib1f(index
, v0
);
8001 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
) {
8002 GLfloat v
[4] = { v0
, v1
, 0.0f
, 1.0f
, };
8003 if (SetVertexAttribValue("glVertexAttrib2f", index
, v
)) {
8004 glVertexAttrib2f(index
, v0
, v1
);
8008 void GLES2DecoderImpl::DoVertexAttrib3f(
8009 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
) {
8010 GLfloat v
[4] = { v0
, v1
, v2
, 1.0f
, };
8011 if (SetVertexAttribValue("glVertexAttrib3f", index
, v
)) {
8012 glVertexAttrib3f(index
, v0
, v1
, v2
);
8016 void GLES2DecoderImpl::DoVertexAttrib4f(
8017 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
) {
8018 GLfloat v
[4] = { v0
, v1
, v2
, v3
, };
8019 if (SetVertexAttribValue("glVertexAttrib4f", index
, v
)) {
8020 glVertexAttrib4f(index
, v0
, v1
, v2
, v3
);
8024 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index
, const GLfloat
* v
) {
8025 GLfloat t
[4] = { v
[0], 0.0f
, 0.0f
, 1.0f
, };
8026 if (SetVertexAttribValue("glVertexAttrib1fv", index
, t
)) {
8027 glVertexAttrib1fv(index
, v
);
8031 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index
, const GLfloat
* v
) {
8032 GLfloat t
[4] = { v
[0], v
[1], 0.0f
, 1.0f
, };
8033 if (SetVertexAttribValue("glVertexAttrib2fv", index
, t
)) {
8034 glVertexAttrib2fv(index
, v
);
8038 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index
, const GLfloat
* v
) {
8039 GLfloat t
[4] = { v
[0], v
[1], v
[2], 1.0f
, };
8040 if (SetVertexAttribValue("glVertexAttrib3fv", index
, t
)) {
8041 glVertexAttrib3fv(index
, v
);
8045 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index
, const GLfloat
* v
) {
8046 if (SetVertexAttribValue("glVertexAttrib4fv", index
, v
)) {
8047 glVertexAttrib4fv(index
, v
);
8051 void GLES2DecoderImpl::DoVertexAttribI4i(
8052 GLuint index
, GLint v0
, GLint v1
, GLint v2
, GLint v3
) {
8053 GLint v
[4] = { v0
, v1
, v2
, v3
};
8054 if (SetVertexAttribValue("glVertexAttribI4i", index
, v
)) {
8055 glVertexAttribI4i(index
, v0
, v1
, v2
, v3
);
8059 void GLES2DecoderImpl::DoVertexAttribI4iv(GLuint index
, const GLint
* v
) {
8060 if (SetVertexAttribValue("glVertexAttribI4iv", index
, v
)) {
8061 glVertexAttribI4iv(index
, v
);
8065 void GLES2DecoderImpl::DoVertexAttribI4ui(
8066 GLuint index
, GLuint v0
, GLuint v1
, GLuint v2
, GLuint v3
) {
8067 GLuint v
[4] = { v0
, v1
, v2
, v3
};
8068 if (SetVertexAttribValue("glVertexAttribI4ui", index
, v
)) {
8069 glVertexAttribI4ui(index
, v0
, v1
, v2
, v3
);
8073 void GLES2DecoderImpl::DoVertexAttribI4uiv(GLuint index
, const GLuint
* v
) {
8074 if (SetVertexAttribValue("glVertexAttribI4uiv", index
, v
)) {
8075 glVertexAttribI4uiv(index
, v
);
8079 error::Error
GLES2DecoderImpl::HandleVertexAttribIPointer(
8080 uint32 immediate_data_size
,
8081 const void* cmd_data
) {
8082 if (!unsafe_es3_apis_enabled())
8083 return error::kUnknownCommand
;
8084 const gles2::cmds::VertexAttribIPointer
& c
=
8085 *static_cast<const gles2::cmds::VertexAttribIPointer
*>(cmd_data
);
8087 if (!state_
.bound_array_buffer
.get() ||
8088 state_
.bound_array_buffer
->IsDeleted()) {
8089 if (state_
.vertex_attrib_manager
.get() ==
8090 state_
.default_vertex_attrib_manager
.get()) {
8092 GL_INVALID_VALUE
, "glVertexAttribIPointer", "no array buffer bound");
8093 return error::kNoError
;
8094 } else if (c
.offset
!= 0) {
8097 "glVertexAttribIPointer", "client side arrays are not allowed");
8098 return error::kNoError
;
8102 GLuint indx
= c
.indx
;
8103 GLint size
= c
.size
;
8104 GLenum type
= c
.type
;
8105 GLsizei stride
= c
.stride
;
8106 GLsizei offset
= c
.offset
;
8107 const void* ptr
= reinterpret_cast<const void*>(offset
);
8108 if (!validators_
->vertex_attrib_i_type
.IsValid(type
)) {
8109 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribIPointer", type
, "type");
8110 return error::kNoError
;
8112 if (!validators_
->vertex_attrib_size
.IsValid(size
)) {
8114 GL_INVALID_VALUE
, "glVertexAttribIPointer", "size GL_INVALID_VALUE");
8115 return error::kNoError
;
8117 if (indx
>= group_
->max_vertex_attribs()) {
8119 GL_INVALID_VALUE
, "glVertexAttribIPointer", "index out of range");
8120 return error::kNoError
;
8124 GL_INVALID_VALUE
, "glVertexAttribIPointer", "stride < 0");
8125 return error::kNoError
;
8129 GL_INVALID_VALUE
, "glVertexAttribIPointer", "stride > 255");
8130 return error::kNoError
;
8134 GL_INVALID_VALUE
, "glVertexAttribIPointer", "offset < 0");
8135 return error::kNoError
;
8137 GLsizei component_size
=
8138 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type
);
8139 // component_size must be a power of two to use & as optimized modulo.
8140 DCHECK(GLES2Util::IsPOT(component_size
));
8141 if (offset
& (component_size
- 1)) {
8143 GL_INVALID_OPERATION
,
8144 "glVertexAttribIPointer", "offset not valid for type");
8145 return error::kNoError
;
8147 if (stride
& (component_size
- 1)) {
8149 GL_INVALID_OPERATION
,
8150 "glVertexAttribIPointer", "stride not valid for type");
8151 return error::kNoError
;
8153 state_
.vertex_attrib_manager
8154 ->SetAttribInfo(indx
,
8155 state_
.bound_array_buffer
.get(),
8160 stride
!= 0 ? stride
: component_size
* size
,
8163 glVertexAttribIPointer(indx
, size
, type
, stride
, ptr
);
8164 return error::kNoError
;
8167 error::Error
GLES2DecoderImpl::HandleVertexAttribPointer(
8168 uint32 immediate_data_size
,
8169 const void* cmd_data
) {
8170 const gles2::cmds::VertexAttribPointer
& c
=
8171 *static_cast<const gles2::cmds::VertexAttribPointer
*>(cmd_data
);
8173 if (!state_
.bound_array_buffer
.get() ||
8174 state_
.bound_array_buffer
->IsDeleted()) {
8175 if (state_
.vertex_attrib_manager
.get() ==
8176 state_
.default_vertex_attrib_manager
.get()) {
8178 GL_INVALID_VALUE
, "glVertexAttribPointer", "no array buffer bound");
8179 return error::kNoError
;
8180 } else if (c
.offset
!= 0) {
8183 "glVertexAttribPointer", "client side arrays are not allowed");
8184 return error::kNoError
;
8188 GLuint indx
= c
.indx
;
8189 GLint size
= c
.size
;
8190 GLenum type
= c
.type
;
8191 GLboolean normalized
= static_cast<GLboolean
>(c
.normalized
);
8192 GLsizei stride
= c
.stride
;
8193 GLsizei offset
= c
.offset
;
8194 const void* ptr
= reinterpret_cast<const void*>(offset
);
8195 if (!validators_
->vertex_attrib_type
.IsValid(type
)) {
8196 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type
, "type");
8197 return error::kNoError
;
8199 if (!validators_
->vertex_attrib_size
.IsValid(size
)) {
8201 GL_INVALID_VALUE
, "glVertexAttribPointer", "size GL_INVALID_VALUE");
8202 return error::kNoError
;
8204 if (indx
>= group_
->max_vertex_attribs()) {
8206 GL_INVALID_VALUE
, "glVertexAttribPointer", "index out of range");
8207 return error::kNoError
;
8211 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride < 0");
8212 return error::kNoError
;
8216 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride > 255");
8217 return error::kNoError
;
8221 GL_INVALID_VALUE
, "glVertexAttribPointer", "offset < 0");
8222 return error::kNoError
;
8224 GLsizei component_size
=
8225 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type
);
8226 // component_size must be a power of two to use & as optimized modulo.
8227 DCHECK(GLES2Util::IsPOT(component_size
));
8228 if (offset
& (component_size
- 1)) {
8230 GL_INVALID_OPERATION
,
8231 "glVertexAttribPointer", "offset not valid for type");
8232 return error::kNoError
;
8234 if (stride
& (component_size
- 1)) {
8236 GL_INVALID_OPERATION
,
8237 "glVertexAttribPointer", "stride not valid for type");
8238 return error::kNoError
;
8240 state_
.vertex_attrib_manager
8241 ->SetAttribInfo(indx
,
8242 state_
.bound_array_buffer
.get(),
8247 stride
!= 0 ? stride
: component_size
* size
,
8250 // We support GL_FIXED natively on EGL/GLES2 implementations
8251 if (type
!= GL_FIXED
|| feature_info_
->gl_version_info().is_es
) {
8252 glVertexAttribPointer(indx
, size
, type
, normalized
, stride
, ptr
);
8254 return error::kNoError
;
8257 void GLES2DecoderImpl::DoViewport(GLint x
, GLint y
, GLsizei width
,
8259 state_
.viewport_x
= x
;
8260 state_
.viewport_y
= y
;
8261 state_
.viewport_width
= std::min(width
, viewport_max_width_
);
8262 state_
.viewport_height
= std::min(height
, viewport_max_height_
);
8263 glViewport(x
, y
, width
, height
);
8266 error::Error
GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
8267 uint32 immediate_data_size
,
8268 const void* cmd_data
) {
8269 const gles2::cmds::VertexAttribDivisorANGLE
& c
=
8270 *static_cast<const gles2::cmds::VertexAttribDivisorANGLE
*>(cmd_data
);
8271 if (!features().angle_instanced_arrays
) {
8273 GL_INVALID_OPERATION
,
8274 "glVertexAttribDivisorANGLE", "function not available");
8275 return error::kNoError
;
8277 GLuint index
= c
.index
;
8278 GLuint divisor
= c
.divisor
;
8279 if (index
>= group_
->max_vertex_attribs()) {
8282 "glVertexAttribDivisorANGLE", "index out of range");
8283 return error::kNoError
;
8286 state_
.vertex_attrib_manager
->SetDivisor(
8289 glVertexAttribDivisorANGLE(index
, divisor
);
8290 return error::kNoError
;
8293 template <typename pixel_data_type
>
8294 static void WriteAlphaData(
8295 void* pixels
, uint32 row_count
, uint32 channel_count
,
8296 uint32 alpha_channel_index
, uint32 unpadded_row_size
,
8297 uint32 padded_row_size
, pixel_data_type alpha_value
) {
8298 DCHECK_GT(channel_count
, 0U);
8299 DCHECK_EQ(unpadded_row_size
% sizeof(pixel_data_type
), 0U);
8300 uint32 unpadded_row_size_in_elements
=
8301 unpadded_row_size
/ sizeof(pixel_data_type
);
8302 DCHECK_EQ(padded_row_size
% sizeof(pixel_data_type
), 0U);
8303 uint32 padded_row_size_in_elements
=
8304 padded_row_size
/ sizeof(pixel_data_type
);
8305 pixel_data_type
* dst
=
8306 static_cast<pixel_data_type
*>(pixels
) + alpha_channel_index
;
8307 for (uint32 yy
= 0; yy
< row_count
; ++yy
) {
8308 pixel_data_type
* end
= dst
+ unpadded_row_size_in_elements
;
8309 for (pixel_data_type
* d
= dst
; d
< end
; d
+= channel_count
) {
8312 dst
+= padded_row_size_in_elements
;
8316 void GLES2DecoderImpl::FinishReadPixels(
8317 const cmds::ReadPixels
& c
,
8319 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
8320 GLsizei width
= c
.width
;
8321 GLsizei height
= c
.height
;
8322 GLenum format
= c
.format
;
8323 GLenum type
= c
.type
;
8324 typedef cmds::ReadPixels::Result Result
;
8326 Result
* result
= NULL
;
8327 if (c
.result_shm_id
!= 0) {
8328 result
= GetSharedMemoryAs
<Result
*>(
8329 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
8332 glDeleteBuffersARB(1, &buffer
);
8337 GLES2Util::ComputeImageDataSizes(
8338 width
, height
, 1, format
, type
, state_
.pack_alignment
, &pixels_size
,
8340 void* pixels
= GetSharedMemoryAs
<void*>(
8341 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
8344 glDeleteBuffersARB(1, &buffer
);
8350 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
8352 if (features().map_buffer_range
) {
8353 data
= glMapBufferRange(
8354 GL_PIXEL_PACK_BUFFER_ARB
, 0, pixels_size
, GL_MAP_READ_BIT
);
8356 data
= glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB
, GL_READ_ONLY
);
8359 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glMapBuffer",
8360 "Unable to map memory for readback.");
8363 memcpy(pixels
, data
, pixels_size
);
8364 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
8365 // have to restore the state.
8366 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB
);
8367 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
8368 glDeleteBuffersARB(1, &buffer
);
8371 if (result
!= NULL
) {
8375 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
8376 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
8377 if ((channels_exist
& 0x0008) == 0 &&
8378 workarounds().clear_alpha_in_readpixels
) {
8379 // Set the alpha to 255 because some drivers are buggy in this regard.
8382 uint32 unpadded_row_size
;
8383 uint32 padded_row_size
;
8384 if (!GLES2Util::ComputeImageDataSizes(
8385 width
, 2, 1, format
, type
, state_
.pack_alignment
, &temp_size
,
8386 &unpadded_row_size
, &padded_row_size
)) {
8390 uint32 channel_count
= 0;
8391 uint32 alpha_channel
= 0;
8404 if (channel_count
> 0) {
8406 case GL_UNSIGNED_BYTE
:
8407 WriteAlphaData
<uint8
>(
8408 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
8409 padded_row_size
, 0xFF);
8412 WriteAlphaData
<float>(
8413 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
8414 padded_row_size
, 1.0f
);
8417 WriteAlphaData
<uint16
>(
8418 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
8419 padded_row_size
, 0x3C00);
8426 error::Error
GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size
,
8427 const void* cmd_data
) {
8428 const gles2::cmds::ReadPixels
& c
=
8429 *static_cast<const gles2::cmds::ReadPixels
*>(cmd_data
);
8430 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
8431 error::Error fbo_error
= WillAccessBoundFramebufferForRead();
8432 if (fbo_error
!= error::kNoError
)
8436 GLsizei width
= c
.width
;
8437 GLsizei height
= c
.height
;
8438 GLenum format
= c
.format
;
8439 GLenum type
= c
.type
;
8440 GLboolean async
= static_cast<GLboolean
>(c
.async
);
8441 if (width
< 0 || height
< 0) {
8442 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glReadPixels", "dimensions < 0");
8443 return error::kNoError
;
8445 typedef cmds::ReadPixels::Result Result
;
8447 if (!GLES2Util::ComputeImageDataSizes(
8448 width
, height
, 1, format
, type
, state_
.pack_alignment
, &pixels_size
,
8450 return error::kOutOfBounds
;
8452 void* pixels
= GetSharedMemoryAs
<void*>(
8453 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
8455 return error::kOutOfBounds
;
8457 Result
* result
= NULL
;
8458 if (c
.result_shm_id
!= 0) {
8459 result
= GetSharedMemoryAs
<Result
*>(
8460 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
8462 return error::kOutOfBounds
;
8466 if (!validators_
->read_pixel_format
.IsValid(format
)) {
8467 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format
, "format");
8468 return error::kNoError
;
8470 if (!validators_
->read_pixel_type
.IsValid(type
)) {
8471 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type
, "type");
8472 return error::kNoError
;
8475 GLenum src_internal_format
= GetBoundReadFrameBufferInternalFormat();
8476 if (src_internal_format
== 0) {
8477 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glReadPixels",
8478 "no valid read buffer source");
8479 return error::kNoError
;
8481 std::vector
<GLenum
> accepted_formats
;
8482 std::vector
<GLenum
> accepted_types
;
8483 switch (src_internal_format
) {
8485 accepted_formats
.push_back(GL_RGBA
);
8486 accepted_types
.push_back(GL_UNSIGNED_INT_2_10_10_10_REV
);
8493 // All the RGB_INTEGER formats are not renderable.
8497 accepted_formats
.push_back(GL_RGBA_INTEGER
);
8498 accepted_types
.push_back(GL_UNSIGNED_INT
);
8509 accepted_formats
.push_back(GL_RGBA_INTEGER
);
8510 accepted_types
.push_back(GL_INT
);
8513 accepted_formats
.push_back(GL_RGBA
);
8515 GLenum src_type
= GetBoundReadFrameBufferTextureType();
8518 case GL_HALF_FLOAT_OES
:
8520 case GL_UNSIGNED_INT_10F_11F_11F_REV
:
8521 accepted_types
.push_back(GL_FLOAT
);
8524 accepted_types
.push_back(GL_UNSIGNED_BYTE
);
8530 if (!IsWebGLContext()) {
8531 accepted_formats
.push_back(GL_BGRA_EXT
);
8532 accepted_types
.push_back(GL_UNSIGNED_BYTE
);
8534 DCHECK_EQ(accepted_formats
.size(), accepted_types
.size());
8535 bool format_type_acceptable
= false;
8536 for (size_t ii
= 0; ii
< accepted_formats
.size(); ++ii
) {
8537 if (format
== accepted_formats
[ii
] && type
== accepted_types
[ii
]) {
8538 format_type_acceptable
= true;
8542 if (!format_type_acceptable
) {
8543 // format and type are acceptable enums but not guaranteed to be supported
8544 // for this framebuffer. Have to ask gl if they are valid.
8545 GLint preferred_format
= 0;
8546 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT
, &preferred_format
);
8547 GLint preferred_type
= 0;
8548 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE
, &preferred_type
);
8549 if (format
== static_cast<GLenum
>(preferred_format
) &&
8550 type
== static_cast<GLenum
>(preferred_type
)) {
8551 format_type_acceptable
= true;
8554 if (!format_type_acceptable
) {
8555 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glReadPixels",
8556 "format and type incompatible with the current read framebuffer");
8557 return error::kNoError
;
8559 if (width
== 0 || height
== 0) {
8560 return error::kNoError
;
8563 // Get the size of the current fbo or backbuffer.
8564 gfx::Size max_size
= GetBoundReadFrameBufferSize();
8568 if (!SafeAddInt32(x
, width
, &max_x
) || !SafeAddInt32(y
, height
, &max_y
)) {
8570 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
8571 return error::kNoError
;
8574 if (!CheckBoundFramebuffersValid("glReadPixels")) {
8575 return error::kNoError
;
8578 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
8580 ScopedResolvedFrameBufferBinder
binder(this, false, true);
8582 if (x
< 0 || y
< 0 || max_x
> max_size
.width() || max_y
> max_size
.height()) {
8583 // The user requested an out of range area. Get the results 1 line
8586 uint32 unpadded_row_size
;
8587 uint32 padded_row_size
;
8588 if (!GLES2Util::ComputeImageDataSizes(
8589 width
, 2, 1, format
, type
, state_
.pack_alignment
, &temp_size
,
8590 &unpadded_row_size
, &padded_row_size
)) {
8592 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
8593 return error::kNoError
;
8596 GLint dest_x_offset
= std::max(-x
, 0);
8597 uint32 dest_row_offset
;
8598 if (!GLES2Util::ComputeImageDataSizes(
8599 dest_x_offset
, 1, 1, format
, type
, state_
.pack_alignment
,
8600 &dest_row_offset
, NULL
, NULL
)) {
8602 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
8603 return error::kNoError
;
8606 // Copy each row into the larger dest rect.
8607 int8
* dst
= static_cast<int8
*>(pixels
);
8608 GLint read_x
= std::max(0, x
);
8609 GLint read_end_x
= std::max(0, std::min(max_size
.width(), max_x
));
8610 GLint read_width
= read_end_x
- read_x
;
8611 for (GLint yy
= 0; yy
< height
; ++yy
) {
8615 memset(dst
, 0, unpadded_row_size
);
8617 // If the row is in range, copy it.
8618 if (ry
>= 0 && ry
< max_size
.height() && read_width
> 0) {
8620 read_x
, ry
, read_width
, 1, format
, type
, dst
+ dest_row_offset
);
8622 dst
+= padded_row_size
;
8625 if (async
&& features().use_async_readpixels
) {
8627 glGenBuffersARB(1, &buffer
);
8628 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
8629 // For ANGLE client version 2, GL_STREAM_READ is not available.
8630 const GLenum usage_hint
= feature_info_
->gl_version_info().is_angle
?
8631 GL_STATIC_DRAW
: GL_STREAM_READ
;
8632 glBufferData(GL_PIXEL_PACK_BUFFER_ARB
, pixels_size
, NULL
, usage_hint
);
8633 GLenum error
= glGetError();
8634 if (error
== GL_NO_ERROR
) {
8635 glReadPixels(x
, y
, width
, height
, format
, type
, 0);
8636 pending_readpixel_fences_
.push(linked_ptr
<FenceCallback
>(
8637 new FenceCallback()));
8638 WaitForReadPixels(base::Bind(
8639 &GLES2DecoderImpl::FinishReadPixels
,
8640 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
8641 <GLES2DecoderImpl
>(this),
8643 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
8644 return error::kNoError
;
8646 // On error, unbind pack buffer and fall through to sync readpixels
8647 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
8648 glDeleteBuffersARB(1, &buffer
);
8651 glReadPixels(x
, y
, width
, height
, format
, type
, pixels
);
8653 GLenum error
= LOCAL_PEEK_GL_ERROR("glReadPixels");
8654 if (error
== GL_NO_ERROR
) {
8655 if (result
!= NULL
) {
8658 FinishReadPixels(c
, 0);
8661 return error::kNoError
;
8664 error::Error
GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size
,
8665 const void* cmd_data
) {
8666 const gles2::cmds::PixelStorei
& c
=
8667 *static_cast<const gles2::cmds::PixelStorei
*>(cmd_data
);
8668 GLenum pname
= c
.pname
;
8669 GLenum param
= c
.param
;
8670 if (!validators_
->pixel_store
.IsValid(pname
)) {
8671 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname
, "pname");
8672 return error::kNoError
;
8675 case GL_PACK_ALIGNMENT
:
8676 case GL_UNPACK_ALIGNMENT
:
8677 if (!validators_
->pixel_store_alignment
.IsValid(param
)) {
8679 GL_INVALID_VALUE
, "glPixelStorei", "param GL_INVALID_VALUE");
8680 return error::kNoError
;
8686 glPixelStorei(pname
, param
);
8688 case GL_PACK_ALIGNMENT
:
8689 state_
.pack_alignment
= param
;
8691 case GL_PACK_REVERSE_ROW_ORDER_ANGLE
:
8692 state_
.pack_reverse_row_order
= (param
!= 0);
8694 case GL_UNPACK_ALIGNMENT
:
8695 state_
.unpack_alignment
= param
;
8698 // Validation should have prevented us from getting here.
8702 return error::kNoError
;
8705 error::Error
GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
8706 uint32 immediate_data_size
,
8707 const void* cmd_data
) {
8708 const gles2::cmds::PostSubBufferCHROMIUM
& c
=
8709 *static_cast<const gles2::cmds::PostSubBufferCHROMIUM
*>(cmd_data
);
8710 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
8712 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
8714 if (!supports_post_sub_buffer_
) {
8716 GL_INVALID_OPERATION
,
8717 "glPostSubBufferCHROMIUM", "command not supported by surface");
8718 return error::kNoError
;
8721 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
8724 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
8725 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
8726 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
8727 is_offscreen
? offscreen_size_
: surface_
->GetSize());
8729 if (surface_
->PostSubBuffer(c
.x
, c
.y
, c
.width
, c
.height
) !=
8730 gfx::SwapResult::SWAP_FAILED
) {
8731 return error::kNoError
;
8733 LOG(ERROR
) << "Context lost because PostSubBuffer failed.";
8734 return error::kLostContext
;
8738 error::Error
GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
8739 uint32 immediate_data_size
,
8740 const void* cmd_data
) {
8741 const gles2::cmds::ScheduleOverlayPlaneCHROMIUM
& c
=
8742 *static_cast<const gles2::cmds::ScheduleOverlayPlaneCHROMIUM
*>(cmd_data
);
8743 TextureRef
* ref
= texture_manager()->GetTexture(c
.overlay_texture_id
);
8745 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
8746 "glScheduleOverlayPlaneCHROMIUM",
8748 return error::kNoError
;
8750 gfx::GLImage
* image
=
8751 ref
->texture()->GetLevelImage(ref
->texture()->target(), 0);
8753 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
8754 "glScheduleOverlayPlaneCHROMIUM",
8755 "unsupported texture format");
8756 return error::kNoError
;
8758 gfx::OverlayTransform transform
= GetGFXOverlayTransform(c
.plane_transform
);
8759 if (transform
== gfx::OVERLAY_TRANSFORM_INVALID
) {
8760 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM
,
8761 "glScheduleOverlayPlaneCHROMIUM",
8762 "invalid transform enum");
8763 return error::kNoError
;
8765 if (!surface_
->ScheduleOverlayPlane(
8769 gfx::Rect(c
.bounds_x
, c
.bounds_y
, c
.bounds_width
, c
.bounds_height
),
8770 gfx::RectF(c
.uv_x
, c
.uv_y
, c
.uv_width
, c
.uv_height
))) {
8771 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
8772 "glScheduleOverlayPlaneCHROMIUM",
8773 "failed to schedule overlay");
8775 return error::kNoError
;
8778 error::Error
GLES2DecoderImpl::GetAttribLocationHelper(
8779 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8780 const std::string
& name_str
) {
8781 if (!StringIsValidForGLES(name_str
.c_str())) {
8783 GL_INVALID_VALUE
, "glGetAttribLocation", "Invalid character");
8784 return error::kNoError
;
8786 Program
* program
= GetProgramInfoNotShader(
8787 client_id
, "glGetAttribLocation");
8789 return error::kNoError
;
8791 if (!program
->IsValid()) {
8793 GL_INVALID_OPERATION
, "glGetAttribLocation", "program not linked");
8794 return error::kNoError
;
8796 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8797 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8799 return error::kOutOfBounds
;
8801 // Require the client to init this incase the context is lost and we are no
8802 // longer executing commands.
8803 if (*location
!= -1) {
8804 return error::kGenericError
;
8806 *location
= program
->GetAttribLocation(name_str
);
8807 return error::kNoError
;
8810 error::Error
GLES2DecoderImpl::HandleGetAttribLocation(
8811 uint32 immediate_data_size
,
8812 const void* cmd_data
) {
8813 const gles2::cmds::GetAttribLocation
& c
=
8814 *static_cast<const gles2::cmds::GetAttribLocation
*>(cmd_data
);
8815 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8817 return error::kInvalidArguments
;
8819 std::string name_str
;
8820 if (!bucket
->GetAsString(&name_str
)) {
8821 return error::kInvalidArguments
;
8823 return GetAttribLocationHelper(
8824 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8827 error::Error
GLES2DecoderImpl::GetUniformLocationHelper(
8828 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8829 const std::string
& name_str
) {
8830 if (!StringIsValidForGLES(name_str
.c_str())) {
8832 GL_INVALID_VALUE
, "glGetUniformLocation", "Invalid character");
8833 return error::kNoError
;
8835 Program
* program
= GetProgramInfoNotShader(
8836 client_id
, "glGetUniformLocation");
8838 return error::kNoError
;
8840 if (!program
->IsValid()) {
8842 GL_INVALID_OPERATION
, "glGetUniformLocation", "program not linked");
8843 return error::kNoError
;
8845 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8846 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8848 return error::kOutOfBounds
;
8850 // Require the client to init this incase the context is lost an we are no
8851 // longer executing commands.
8852 if (*location
!= -1) {
8853 return error::kGenericError
;
8855 *location
= program
->GetUniformFakeLocation(name_str
);
8856 return error::kNoError
;
8859 error::Error
GLES2DecoderImpl::HandleGetUniformLocation(
8860 uint32 immediate_data_size
,
8861 const void* cmd_data
) {
8862 const gles2::cmds::GetUniformLocation
& c
=
8863 *static_cast<const gles2::cmds::GetUniformLocation
*>(cmd_data
);
8864 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8866 return error::kInvalidArguments
;
8868 std::string name_str
;
8869 if (!bucket
->GetAsString(&name_str
)) {
8870 return error::kInvalidArguments
;
8872 return GetUniformLocationHelper(
8873 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8876 error::Error
GLES2DecoderImpl::HandleGetUniformIndices(
8877 uint32 immediate_data_size
,
8878 const void* cmd_data
) {
8879 if (!unsafe_es3_apis_enabled())
8880 return error::kUnknownCommand
;
8881 const gles2::cmds::GetUniformIndices
& c
=
8882 *static_cast<const gles2::cmds::GetUniformIndices
*>(cmd_data
);
8883 Bucket
* bucket
= GetBucket(c
.names_bucket_id
);
8885 return error::kInvalidArguments
;
8888 std::vector
<char*> names
;
8889 std::vector
<GLint
> len
;
8890 if (!bucket
->GetAsStrings(&count
, &names
, &len
) || count
<= 0) {
8891 return error::kInvalidArguments
;
8893 typedef cmds::GetUniformIndices::Result Result
;
8894 Result
* result
= GetSharedMemoryAs
<Result
*>(
8895 c
.indices_shm_id
, c
.indices_shm_offset
,
8896 Result::ComputeSize(static_cast<size_t>(count
)));
8897 GLuint
* indices
= result
? result
->GetData() : NULL
;
8898 if (indices
== NULL
) {
8899 return error::kOutOfBounds
;
8901 // Check that the client initialized the result.
8902 if (result
->size
!= 0) {
8903 return error::kInvalidArguments
;
8905 Program
* program
= GetProgramInfoNotShader(c
.program
, "glGetUniformIndices");
8907 return error::kNoError
;
8909 GLuint service_id
= program
->service_id();
8910 GLint link_status
= GL_FALSE
;
8911 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
8912 if (link_status
!= GL_TRUE
) {
8913 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
8914 "glGetUniformIndices", "program not linked");
8915 return error::kNoError
;
8917 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetUniformIndices");
8918 glGetUniformIndices(service_id
, count
, &names
[0], indices
);
8919 GLenum error
= glGetError();
8920 if (error
== GL_NO_ERROR
) {
8921 result
->SetNumResults(count
);
8923 LOCAL_SET_GL_ERROR(error
, "GetUniformIndices", "");
8925 return error::kNoError
;
8928 error::Error
GLES2DecoderImpl::GetFragDataLocationHelper(
8929 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8930 const std::string
& name_str
) {
8931 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8932 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8934 return error::kOutOfBounds
;
8936 // Require the client to init this incase the context is lost and we are no
8937 // longer executing commands.
8938 if (*location
!= -1) {
8939 return error::kGenericError
;
8941 Program
* program
= GetProgramInfoNotShader(
8942 client_id
, "glGetFragDataLocation");
8944 return error::kNoError
;
8946 *location
= glGetFragDataLocation(program
->service_id(), name_str
.c_str());
8947 return error::kNoError
;
8950 error::Error
GLES2DecoderImpl::HandleGetFragDataLocation(
8951 uint32 immediate_data_size
,
8952 const void* cmd_data
) {
8953 if (!unsafe_es3_apis_enabled())
8954 return error::kUnknownCommand
;
8955 const gles2::cmds::GetFragDataLocation
& c
=
8956 *static_cast<const gles2::cmds::GetFragDataLocation
*>(cmd_data
);
8957 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8959 return error::kInvalidArguments
;
8961 std::string name_str
;
8962 if (!bucket
->GetAsString(&name_str
)) {
8963 return error::kInvalidArguments
;
8965 return GetFragDataLocationHelper(
8966 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8969 error::Error
GLES2DecoderImpl::HandleGetUniformBlockIndex(
8970 uint32 immediate_data_size
, const void* cmd_data
) {
8971 if (!unsafe_es3_apis_enabled())
8972 return error::kUnknownCommand
;
8973 const gles2::cmds::GetUniformBlockIndex
& c
=
8974 *static_cast<const gles2::cmds::GetUniformBlockIndex
*>(cmd_data
);
8975 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8977 return error::kInvalidArguments
;
8979 std::string name_str
;
8980 if (!bucket
->GetAsString(&name_str
)) {
8981 return error::kInvalidArguments
;
8983 GLuint
* index
= GetSharedMemoryAs
<GLuint
*>(
8984 c
.index_shm_id
, c
.index_shm_offset
, sizeof(GLuint
));
8986 return error::kOutOfBounds
;
8988 // Require the client to init this in case the context is lost and we are no
8989 // longer executing commands.
8990 if (*index
!= GL_INVALID_INDEX
) {
8991 return error::kGenericError
;
8993 Program
* program
= GetProgramInfoNotShader(
8994 c
.program
, "glGetUniformBlockIndex");
8996 return error::kNoError
;
8998 *index
= glGetUniformBlockIndex(program
->service_id(), name_str
.c_str());
8999 return error::kNoError
;
9002 error::Error
GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size
,
9003 const void* cmd_data
) {
9004 const gles2::cmds::GetString
& c
=
9005 *static_cast<const gles2::cmds::GetString
*>(cmd_data
);
9006 GLenum name
= static_cast<GLenum
>(c
.name
);
9007 if (!validators_
->string_type
.IsValid(name
)) {
9008 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name
, "name");
9009 return error::kNoError
;
9012 const char* str
= nullptr;
9013 std::string extensions
;
9016 if (unsafe_es3_apis_enabled())
9017 str
= "OpenGL ES 3.0 Chromium";
9019 str
= "OpenGL ES 2.0 Chromium";
9021 case GL_SHADING_LANGUAGE_VERSION
:
9022 if (unsafe_es3_apis_enabled())
9023 str
= "OpenGL ES GLSL ES 3.0 Chromium";
9025 str
= "OpenGL ES GLSL ES 1.0 Chromium";
9029 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
9030 // They are used by WEBGL_debug_renderer_info.
9031 if (!IsWebGLContext())
9034 str
= reinterpret_cast<const char*>(glGetString(name
));
9038 // For WebGL contexts, strip out the OES derivatives and
9039 // EXT frag depth extensions if they have not been enabled.
9040 if (IsWebGLContext()) {
9041 extensions
= feature_info_
->extensions();
9042 if (!derivatives_explicitly_enabled_
) {
9043 size_t offset
= extensions
.find(kOESDerivativeExtension
);
9044 if (std::string::npos
!= offset
) {
9045 extensions
.replace(offset
, arraysize(kOESDerivativeExtension
),
9049 if (!frag_depth_explicitly_enabled_
) {
9050 size_t offset
= extensions
.find(kEXTFragDepthExtension
);
9051 if (std::string::npos
!= offset
) {
9052 extensions
.replace(offset
, arraysize(kEXTFragDepthExtension
),
9056 if (!draw_buffers_explicitly_enabled_
) {
9057 size_t offset
= extensions
.find(kEXTDrawBuffersExtension
);
9058 if (std::string::npos
!= offset
) {
9059 extensions
.replace(offset
, arraysize(kEXTDrawBuffersExtension
),
9063 if (!shader_texture_lod_explicitly_enabled_
) {
9064 size_t offset
= extensions
.find(kEXTShaderTextureLodExtension
);
9065 if (std::string::npos
!= offset
) {
9066 extensions
.replace(offset
,
9067 arraysize(kEXTShaderTextureLodExtension
),
9072 extensions
= feature_info_
->extensions().c_str();
9074 if (supports_post_sub_buffer_
)
9075 extensions
+= " GL_CHROMIUM_post_sub_buffer";
9076 str
= extensions
.c_str();
9080 str
= reinterpret_cast<const char*>(glGetString(name
));
9083 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
9084 bucket
->SetFromString(str
);
9085 return error::kNoError
;
9088 error::Error
GLES2DecoderImpl::HandleBufferData(uint32 immediate_data_size
,
9089 const void* cmd_data
) {
9090 const gles2::cmds::BufferData
& c
=
9091 *static_cast<const gles2::cmds::BufferData
*>(cmd_data
);
9092 GLenum target
= static_cast<GLenum
>(c
.target
);
9093 GLsizeiptr size
= static_cast<GLsizeiptr
>(c
.size
);
9094 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
9095 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
9096 GLenum usage
= static_cast<GLenum
>(c
.usage
);
9097 const void* data
= NULL
;
9098 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
9099 data
= GetSharedMemoryAs
<const void*>(data_shm_id
, data_shm_offset
, size
);
9101 return error::kOutOfBounds
;
9104 buffer_manager()->ValidateAndDoBufferData(&state_
, target
, size
, data
, usage
);
9105 return error::kNoError
;
9108 void GLES2DecoderImpl::DoBufferSubData(
9109 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
) {
9110 // Just delegate it. Some validation is actually done before this.
9111 buffer_manager()->ValidateAndDoBufferSubData(
9112 &state_
, target
, offset
, size
, data
);
9115 bool GLES2DecoderImpl::ClearLevel(Texture
* texture
,
9124 uint32 channels
= GLES2Util::GetChannelsForFormat(format
);
9125 if ((feature_info_
->feature_flags().angle_depth_texture
||
9126 feature_info_
->IsES3Enabled())
9127 && (channels
& GLES2Util::kDepth
) != 0) {
9128 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
9129 // on depth formats.
9131 glGenFramebuffersEXT(1, &fb
);
9132 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb
);
9134 bool have_stencil
= (channels
& GLES2Util::kStencil
) != 0;
9135 GLenum attachment
= have_stencil
? GL_DEPTH_STENCIL_ATTACHMENT
:
9136 GL_DEPTH_ATTACHMENT
;
9138 glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT
, attachment
, target
,
9139 texture
->service_id(), level
);
9140 // ANGLE promises a depth only attachment ok.
9141 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT
) !=
9142 GL_FRAMEBUFFER_COMPLETE
) {
9146 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
9147 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
9149 state_
.SetDeviceDepthMask(GL_TRUE
);
9150 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
9151 glScissor(xoffset
, yoffset
, width
, height
);
9152 glClear(GL_DEPTH_BUFFER_BIT
| (have_stencil
? GL_STENCIL_BUFFER_BIT
: 0));
9154 RestoreClearState();
9156 glDeleteFramebuffersEXT(1, &fb
);
9157 Framebuffer
* framebuffer
=
9158 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
9159 GLuint fb_service_id
=
9160 framebuffer
? framebuffer
->service_id() : GetBackbufferServiceId();
9161 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb_service_id
);
9165 static const uint32 kMaxZeroSize
= 1024 * 1024 * 4;
9168 uint32 padded_row_size
;
9169 if (!GLES2Util::ComputeImageDataSizes(
9170 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &size
,
9171 NULL
, &padded_row_size
)) {
9175 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size
);
9179 if (size
> kMaxZeroSize
) {
9180 if (kMaxZeroSize
< padded_row_size
) {
9181 // That'd be an awfully large texture.
9184 // We should never have a large total size with a zero row size.
9185 DCHECK_GT(padded_row_size
, 0U);
9186 tile_height
= kMaxZeroSize
/ padded_row_size
;
9187 if (!GLES2Util::ComputeImageDataSizes(
9188 width
, tile_height
, 1, format
, type
, state_
.unpack_alignment
, &size
,
9193 tile_height
= height
;
9196 // Assumes the size has already been checked.
9197 scoped_ptr
<char[]> zero(new char[size
]);
9198 memset(zero
.get(), 0, size
);
9199 glBindTexture(texture
->target(), texture
->service_id());
9202 while (y
< height
) {
9203 GLint h
= y
+ tile_height
> height
? height
- y
: tile_height
;
9204 glTexSubImage2D(target
, level
, xoffset
, yoffset
+ y
, width
, h
, format
, type
,
9208 TextureRef
* bound_texture
=
9209 texture_manager()->GetTextureInfoForTarget(&state_
, texture
->target());
9210 glBindTexture(texture
->target(),
9211 bound_texture
? bound_texture
->service_id() : 0);
9217 const int kS3TCBlockWidth
= 4;
9218 const int kS3TCBlockHeight
= 4;
9219 const int kS3TCDXT1BlockSize
= 8;
9220 const int kS3TCDXT3AndDXT5BlockSize
= 16;
9221 const int kEACAndETC2BlockSize
= 4;
9223 bool IsValidDXTSize(GLint level
, GLsizei size
) {
9224 return (size
== 1) ||
9225 (size
== 2) || !(size
% kS3TCBlockWidth
);
9228 bool IsValidPVRTCSize(GLint level
, GLsizei size
) {
9229 return GLES2Util::IsPOT(size
);
9232 } // anonymous namespace.
9234 bool GLES2DecoderImpl::GetCompressedTexSizeInBytes(
9235 const char* function_name
, GLsizei width
, GLsizei height
, GLsizei depth
,
9236 GLenum format
, GLsizei
* size_in_bytes
) {
9237 base::CheckedNumeric
<GLsizei
> bytes_required(0);
9240 case GL_ATC_RGB_AMD
:
9241 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
9242 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
9243 case GL_ETC1_RGB8_OES
:
9245 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
9247 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
9248 bytes_required
*= kS3TCDXT1BlockSize
;
9250 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
9251 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
9252 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
9253 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
9255 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
9257 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
9258 bytes_required
*= kS3TCDXT3AndDXT5BlockSize
;
9260 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
9261 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
9262 bytes_required
= std::max(width
, 8);
9263 bytes_required
*= std::max(height
, 8);
9264 bytes_required
*= 4;
9265 bytes_required
+= 7;
9266 bytes_required
/= 8;
9268 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
9269 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
:
9270 bytes_required
= std::max(width
, 16);
9271 bytes_required
*= std::max(height
, 8);
9272 bytes_required
*= 2;
9273 bytes_required
+= 7;
9274 bytes_required
/= 8;
9278 case GL_COMPRESSED_R11_EAC
:
9279 case GL_COMPRESSED_SIGNED_R11_EAC
:
9280 case GL_COMPRESSED_RGB8_ETC2
:
9281 case GL_COMPRESSED_SRGB8_ETC2
:
9282 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9283 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9285 (width
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9287 (height
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9288 bytes_required
*= 8;
9289 bytes_required
*= depth
;
9291 case GL_COMPRESSED_RG11_EAC
:
9292 case GL_COMPRESSED_SIGNED_RG11_EAC
:
9293 case GL_COMPRESSED_RGBA8_ETC2_EAC
:
9294 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
:
9296 (width
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9298 (height
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9299 bytes_required
*= 16;
9300 bytes_required
*= depth
;
9303 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, format
, "format");
9307 if (!bytes_required
.IsValid()) {
9308 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "invalid size");
9312 *size_in_bytes
= bytes_required
.ValueOrDefault(0);
9316 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
9317 const char* function_name
, GLsizei width
, GLsizei height
, GLsizei depth
,
9318 GLenum format
, GLsizei size
) {
9319 GLsizei bytes_required
= 0;
9320 if (!GetCompressedTexSizeInBytes(
9321 function_name
, width
, height
, depth
, format
, &bytes_required
)) {
9325 if (size
!= bytes_required
) {
9327 GL_INVALID_VALUE
, function_name
, "size is not correct for dimensions");
9334 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
9335 const char* function_name
, GLenum target
, GLint level
,
9336 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
) {
9338 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
9339 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
9340 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
9341 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
9342 DCHECK_EQ(1, depth
); // 2D formats.
9343 if (!IsValidDXTSize(level
, width
) || !IsValidDXTSize(level
, height
)) {
9345 GL_INVALID_OPERATION
, function_name
,
9346 "width or height invalid for level");
9350 case GL_ATC_RGB_AMD
:
9351 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
9352 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
9353 case GL_ETC1_RGB8_OES
:
9354 DCHECK_EQ(1, depth
); // 2D formats.
9355 if (width
<= 0 || height
<= 0) {
9357 GL_INVALID_OPERATION
, function_name
,
9358 "width or height invalid for level");
9362 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
9363 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
9364 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
9365 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
:
9366 DCHECK_EQ(1, depth
); // 2D formats.
9367 if (!IsValidPVRTCSize(level
, width
) ||
9368 !IsValidPVRTCSize(level
, height
)) {
9370 GL_INVALID_OPERATION
, function_name
,
9371 "width or height invalid for level");
9377 case GL_COMPRESSED_R11_EAC
:
9378 case GL_COMPRESSED_SIGNED_R11_EAC
:
9379 case GL_COMPRESSED_RG11_EAC
:
9380 case GL_COMPRESSED_SIGNED_RG11_EAC
:
9381 case GL_COMPRESSED_RGB8_ETC2
:
9382 case GL_COMPRESSED_SRGB8_ETC2
:
9383 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9384 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9385 case GL_COMPRESSED_RGBA8_ETC2_EAC
:
9386 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
:
9387 if (width
<= 0 || height
<= 0 || depth
<= 0) {
9389 GL_INVALID_OPERATION
, function_name
,
9390 "width, height, or depth invalid");
9393 if (target
== GL_TEXTURE_3D
) {
9395 GL_INVALID_OPERATION
, function_name
,
9396 "target invalid for format");
9405 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
9406 const char* function_name
,
9407 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
9408 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
,
9410 if (xoffset
< 0 || yoffset
< 0 || zoffset
< 0) {
9412 GL_INVALID_VALUE
, function_name
, "x/y/z offset < 0");
9417 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
9418 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
9419 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
9420 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
: {
9421 const int kBlockWidth
= 4;
9422 const int kBlockHeight
= 4;
9423 if ((xoffset
% kBlockWidth
) || (yoffset
% kBlockHeight
)) {
9425 GL_INVALID_OPERATION
, function_name
,
9426 "xoffset or yoffset not multiple of 4");
9429 GLsizei tex_width
= 0;
9430 GLsizei tex_height
= 0;
9431 if (!texture
->GetLevelSize(target
, level
,
9432 &tex_width
, &tex_height
, nullptr) ||
9433 width
- xoffset
> tex_width
||
9434 height
- yoffset
> tex_height
) {
9436 GL_INVALID_OPERATION
, function_name
, "dimensions out of range");
9439 return ValidateCompressedTexDimensions(
9440 function_name
, target
, level
, width
, height
, 1, format
);
9442 case GL_ATC_RGB_AMD
:
9443 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
9444 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
: {
9446 GL_INVALID_OPERATION
, function_name
,
9447 "not supported for ATC textures");
9450 case GL_ETC1_RGB8_OES
: {
9452 GL_INVALID_OPERATION
, function_name
,
9453 "not supported for ECT1_RGB8_OES textures");
9456 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
9457 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
9458 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
9459 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
: {
9460 if ((xoffset
!= 0) || (yoffset
!= 0)) {
9462 GL_INVALID_OPERATION
, function_name
,
9463 "xoffset and yoffset must be zero");
9466 GLsizei tex_width
= 0;
9467 GLsizei tex_height
= 0;
9468 if (!texture
->GetLevelSize(target
, level
,
9469 &tex_width
, &tex_height
, nullptr) ||
9470 width
!= tex_width
||
9471 height
!= tex_height
) {
9473 GL_INVALID_OPERATION
, function_name
,
9474 "dimensions must match existing texture level dimensions");
9477 return ValidateCompressedTexDimensions(
9478 function_name
, target
, level
, width
, height
, 1, format
);
9482 case GL_COMPRESSED_R11_EAC
:
9483 case GL_COMPRESSED_SIGNED_R11_EAC
:
9484 case GL_COMPRESSED_RG11_EAC
:
9485 case GL_COMPRESSED_SIGNED_RG11_EAC
:
9486 case GL_COMPRESSED_RGB8_ETC2
:
9487 case GL_COMPRESSED_SRGB8_ETC2
:
9488 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9489 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9490 case GL_COMPRESSED_RGBA8_ETC2_EAC
:
9491 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
:
9493 const int kBlockSize
= 4;
9494 GLsizei tex_width
, tex_height
;
9495 if (target
== GL_TEXTURE_3D
||
9496 !texture
->GetLevelSize(target
, level
,
9497 &tex_width
, &tex_height
, nullptr) ||
9498 (xoffset
% kBlockSize
) || (yoffset
% kBlockSize
) ||
9499 ((width
% kBlockSize
) && xoffset
+ width
!= tex_width
) ||
9500 ((height
% kBlockSize
) && yoffset
+ height
!= tex_height
)) {
9502 GL_INVALID_OPERATION
, function_name
,
9503 "dimensions must match existing texture level dimensions");
9513 error::Error
GLES2DecoderImpl::DoCompressedTexImage2D(
9516 GLenum internal_format
,
9522 if (!validators_
->texture_target
.IsValid(target
)) {
9523 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9524 "glCompressedTexImage2D", target
, "target");
9525 return error::kNoError
;
9527 if (!validators_
->compressed_texture_format
.IsValid(
9529 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9530 "glCompressedTexImage2D", internal_format
, "internal_format");
9531 return error::kNoError
;
9533 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
9537 "glCompressedTexImage2D", "dimensions out of range");
9538 return error::kNoError
;
9540 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9545 "glCompressedTexImage2D", "unknown texture target");
9546 return error::kNoError
;
9548 Texture
* texture
= texture_ref
->texture();
9549 if (texture
->IsImmutable()) {
9551 GL_INVALID_OPERATION
,
9552 "glCompressedTexImage2D", "texture is immutable");
9553 return error::kNoError
;
9556 if (!ValidateCompressedTexDimensions("glCompressedTexImage2D", target
, level
,
9557 width
, height
, 1, internal_format
) ||
9558 !ValidateCompressedTexFuncData("glCompressedTexImage2D", width
, height
,
9559 1, internal_format
, image_size
)) {
9560 return error::kNoError
;
9563 if (!EnsureGPUMemoryAvailable(image_size
)) {
9565 GL_OUT_OF_MEMORY
, "glCompressedTexImage2D", "out of memory");
9566 return error::kNoError
;
9569 if (texture
->IsAttachedToFramebuffer()) {
9570 framebuffer_state_
.clear_state_dirty
= true;
9573 scoped_ptr
<int8
[]> zero
;
9575 zero
.reset(new int8
[image_size
]);
9576 memset(zero
.get(), 0, image_size
);
9579 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
9580 glCompressedTexImage2D(
9581 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
9582 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
9583 if (error
== GL_NO_ERROR
) {
9584 texture_manager()->SetLevelInfo(texture_ref
, target
, level
, internal_format
,
9585 width
, height
, 1, border
, 0, 0,
9586 gfx::Rect(width
, height
));
9589 // This may be a slow command. Exit command processing to allow for
9590 // context preemption and GPU watchdog checks.
9591 ExitCommandProcessingEarly();
9592 return error::kNoError
;
9595 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2D(
9596 uint32 immediate_data_size
,
9597 const void* cmd_data
) {
9598 const gles2::cmds::CompressedTexImage2D
& c
=
9599 *static_cast<const gles2::cmds::CompressedTexImage2D
*>(cmd_data
);
9600 GLenum target
= static_cast<GLenum
>(c
.target
);
9601 GLint level
= static_cast<GLint
>(c
.level
);
9602 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9603 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9604 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9605 GLint border
= static_cast<GLint
>(c
.border
);
9606 GLsizei image_size
= static_cast<GLsizei
>(c
.imageSize
);
9607 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
9608 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
9609 const void* data
= NULL
;
9610 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
9611 data
= GetSharedMemoryAs
<const void*>(
9612 data_shm_id
, data_shm_offset
, image_size
);
9614 return error::kOutOfBounds
;
9617 return DoCompressedTexImage2D(
9618 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
9621 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
9622 uint32 immediate_data_size
,
9623 const void* cmd_data
) {
9624 const gles2::cmds::CompressedTexImage2DBucket
& c
=
9625 *static_cast<const gles2::cmds::CompressedTexImage2DBucket
*>(cmd_data
);
9626 GLenum target
= static_cast<GLenum
>(c
.target
);
9627 GLint level
= static_cast<GLint
>(c
.level
);
9628 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9629 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9630 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9631 GLint border
= static_cast<GLint
>(c
.border
);
9632 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9634 return error::kInvalidArguments
;
9636 uint32 data_size
= bucket
->size();
9637 GLsizei imageSize
= data_size
;
9638 const void* data
= bucket
->GetData(0, data_size
);
9640 return error::kInvalidArguments
;
9642 return DoCompressedTexImage2D(
9643 target
, level
, internal_format
, width
, height
, border
,
9647 error::Error
GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
9648 uint32 immediate_data_size
,
9649 const void* cmd_data
) {
9650 const gles2::cmds::CompressedTexSubImage2DBucket
& c
=
9651 *static_cast<const gles2::cmds::CompressedTexSubImage2DBucket
*>(cmd_data
);
9652 GLenum target
= static_cast<GLenum
>(c
.target
);
9653 GLint level
= static_cast<GLint
>(c
.level
);
9654 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
9655 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
9656 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9657 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9658 GLenum format
= static_cast<GLenum
>(c
.format
);
9659 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9661 return error::kInvalidArguments
;
9663 uint32 data_size
= bucket
->size();
9664 GLsizei imageSize
= data_size
;
9665 const void* data
= bucket
->GetData(0, data_size
);
9667 return error::kInvalidArguments
;
9669 if (!validators_
->texture_target
.IsValid(target
)) {
9671 GL_INVALID_ENUM
, "glCompressedTexSubImage2D", "target");
9672 return error::kNoError
;
9674 if (!validators_
->compressed_texture_format
.IsValid(format
)) {
9675 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9676 "glCompressedTexSubImage2D", format
, "format");
9677 return error::kNoError
;
9681 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "width < 0");
9682 return error::kNoError
;
9686 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "height < 0");
9687 return error::kNoError
;
9689 if (imageSize
< 0) {
9691 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "imageSize < 0");
9692 return error::kNoError
;
9694 DoCompressedTexSubImage2D(
9695 target
, level
, xoffset
, yoffset
, width
, height
, format
, imageSize
, data
);
9696 return error::kNoError
;
9699 error::Error
GLES2DecoderImpl::DoCompressedTexImage3D(
9702 GLenum internal_format
,
9709 if (!validators_
->texture_3_d_target
.IsValid(target
)) {
9710 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9711 "glCompressedTexImage3D", target
, "target");
9712 return error::kNoError
;
9714 if (!validators_
->compressed_texture_format
.IsValid(
9716 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9717 "glCompressedTexImage3D", internal_format
, "internal_format");
9718 return error::kNoError
;
9720 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, depth
) ||
9724 "glCompressedTexImage3D", "dimensions out of range");
9725 return error::kNoError
;
9727 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9732 "glCompressedTexImage3D", "unknown texture target");
9733 return error::kNoError
;
9735 Texture
* texture
= texture_ref
->texture();
9736 if (texture
->IsImmutable()) {
9738 GL_INVALID_OPERATION
,
9739 "glCompressedTexImage3D", "texture is immutable");
9740 return error::kNoError
;
9743 if (!ValidateCompressedTexDimensions("glCompressedTexImage3D", target
, level
,
9744 width
, height
, depth
, internal_format
) ||
9745 !ValidateCompressedTexFuncData("glCompressedTexImage3D", width
, height
,
9746 depth
, internal_format
, image_size
)) {
9747 return error::kNoError
;
9750 if (!EnsureGPUMemoryAvailable(image_size
)) {
9752 GL_OUT_OF_MEMORY
, "glCompressedTexImage3D", "out of memory");
9753 return error::kNoError
;
9756 if (texture
->IsAttachedToFramebuffer()) {
9757 framebuffer_state_
.clear_state_dirty
= true;
9760 scoped_ptr
<int8
[]> zero
;
9762 zero
.reset(new int8
[image_size
]);
9763 memset(zero
.get(), 0, image_size
);
9766 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage3D");
9767 glCompressedTexImage3D(target
, level
, internal_format
, width
, height
, depth
,
9768 border
, image_size
, data
);
9769 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedTexImage3D");
9770 if (error
== GL_NO_ERROR
) {
9771 texture_manager()->SetLevelInfo(texture_ref
, target
, level
, internal_format
,
9772 width
, height
, depth
, border
, 0, 0,
9773 gfx::Rect(width
, height
));
9776 // This may be a slow command. Exit command processing to allow for
9777 // context preemption and GPU watchdog checks.
9778 ExitCommandProcessingEarly();
9779 return error::kNoError
;
9782 error::Error
GLES2DecoderImpl::HandleCompressedTexImage3D(
9783 uint32 immediate_data_size
, const void* cmd_data
) {
9784 if (!unsafe_es3_apis_enabled())
9785 return error::kUnknownCommand
;
9787 const gles2::cmds::CompressedTexImage3D
& c
=
9788 *static_cast<const gles2::cmds::CompressedTexImage3D
*>(cmd_data
);
9789 GLenum target
= static_cast<GLenum
>(c
.target
);
9790 GLint level
= static_cast<GLint
>(c
.level
);
9791 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9792 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9793 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9794 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9795 GLint border
= static_cast<GLint
>(c
.border
);
9796 GLsizei image_size
= static_cast<GLsizei
>(c
.imageSize
);
9797 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
9798 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
9799 const void* data
= NULL
;
9800 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
9801 data
= GetSharedMemoryAs
<const void*>(
9802 data_shm_id
, data_shm_offset
, image_size
);
9804 return error::kOutOfBounds
;
9807 return DoCompressedTexImage3D(target
, level
, internal_format
, width
, height
,
9808 depth
, border
, image_size
, data
);
9811 error::Error
GLES2DecoderImpl::HandleCompressedTexImage3DBucket(
9812 uint32 immediate_data_size
, const void* cmd_data
) {
9813 if (!unsafe_es3_apis_enabled())
9814 return error::kUnknownCommand
;
9816 const gles2::cmds::CompressedTexImage3DBucket
& c
=
9817 *static_cast<const gles2::cmds::CompressedTexImage3DBucket
*>(cmd_data
);
9818 GLenum target
= static_cast<GLenum
>(c
.target
);
9819 GLint level
= static_cast<GLint
>(c
.level
);
9820 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9821 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9822 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9823 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9824 GLint border
= static_cast<GLint
>(c
.border
);
9825 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9827 return error::kInvalidArguments
;
9829 uint32 data_size
= bucket
->size();
9830 GLsizei imageSize
= data_size
;
9831 const void* data
= bucket
->GetData(0, data_size
);
9833 return error::kInvalidArguments
;
9835 return DoCompressedTexImage3D(target
, level
, internal_format
, width
, height
,
9836 depth
, border
, imageSize
, data
);
9839 void GLES2DecoderImpl::DoCompressedTexSubImage3D(
9840 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
9841 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
,
9842 GLsizei image_size
, const void* data
) {
9843 if (!validators_
->texture_3_d_target
.IsValid(target
)) {
9845 GL_INVALID_ENUM
, "glCompressedTexSubImage3D", "target");
9848 if (!validators_
->compressed_texture_format
.IsValid(format
)) {
9849 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9850 "glCompressedTexSubImage3D", format
, "format");
9853 if (width
< 0 || height
< 0 || depth
< 0) {
9855 GL_INVALID_VALUE
, "glCompressedTexSubImage3D", "size < 0");
9858 if (image_size
< 0) {
9860 GL_INVALID_VALUE
, "glCompressedTexSubImage3D", "imageSize < 0");
9863 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9866 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCompressedTexSubImage3D",
9867 "unknown texture for target");
9870 Texture
* texture
= texture_ref
->texture();
9871 GLenum type
= 0, internal_format
= 0;
9872 if (!texture
->GetLevelType(target
, level
, &type
, &internal_format
)) {
9873 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCompressedTexSubImage3D",
9874 "level does not exist");
9877 if (internal_format
!= format
) {
9878 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCompressedTexSubImage3D",
9879 "format does not match internal format");
9882 if (!texture
->ValidForTexture(target
, level
, xoffset
, yoffset
, zoffset
,
9883 width
, height
, depth
, type
)) {
9884 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCompressedTexSubImage3D",
9888 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage3D",
9889 width
, height
, depth
, format
,
9891 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage3D",
9892 target
, level
, xoffset
, yoffset
,
9893 zoffset
, width
, height
, depth
,
9898 // Note: There is no need to deal with texture cleared tracking here
9899 // because the validation above means you can only get here if the level
9900 // is already a matching compressed format and in that case
9901 // CompressedTexImage3D already cleared the texture.
9902 glCompressedTexSubImage3D(
9903 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
, format
,
9906 // This may be a slow command. Exit command processing to allow for
9907 // context preemption and GPU watchdog checks.
9908 ExitCommandProcessingEarly();
9911 error::Error
GLES2DecoderImpl::HandleCompressedTexSubImage3DBucket(
9912 uint32 immediate_data_size
, const void* cmd_data
) {
9913 if (!unsafe_es3_apis_enabled())
9914 return error::kUnknownCommand
;
9915 const gles2::cmds::CompressedTexSubImage3DBucket
& c
=
9916 *static_cast<const gles2::cmds::CompressedTexSubImage3DBucket
*>(cmd_data
);
9917 GLenum target
= static_cast<GLenum
>(c
.target
);
9918 GLint level
= static_cast<GLint
>(c
.level
);
9919 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
9920 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
9921 GLint zoffset
= static_cast<GLint
>(c
.zoffset
);
9922 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9923 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9924 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9925 GLenum format
= static_cast<GLenum
>(c
.format
);
9926 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9928 return error::kInvalidArguments
;
9930 uint32 data_size
= bucket
->size();
9931 GLsizei image_size
= data_size
;
9932 const void* data
= bucket
->GetData(0, data_size
);
9934 return error::kInvalidArguments
;
9936 DoCompressedTexSubImage3D(
9937 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
, format
,
9939 return error::kNoError
;
9942 error::Error
GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size
,
9943 const void* cmd_data
) {
9944 const gles2::cmds::TexImage2D
& c
=
9945 *static_cast<const gles2::cmds::TexImage2D
*>(cmd_data
);
9946 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
9947 "width", c
.width
, "height", c
.height
);
9948 // Set as failed for now, but if it successed, this will be set to not failed.
9949 texture_state_
.tex_image_failed
= true;
9950 GLenum target
= static_cast<GLenum
>(c
.target
);
9951 GLint level
= static_cast<GLint
>(c
.level
);
9952 // TODO(kloveless): Change TexImage2D command to use unsigned integer
9953 // for internalformat.
9954 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9955 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9956 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9957 GLint border
= static_cast<GLint
>(c
.border
);
9958 GLenum format
= static_cast<GLenum
>(c
.format
);
9959 GLenum type
= static_cast<GLenum
>(c
.type
);
9960 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
9961 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
9963 if (!GLES2Util::ComputeImageDataSizes(
9964 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
9966 return error::kOutOfBounds
;
9968 const void* pixels
= NULL
;
9969 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
9970 pixels
= GetSharedMemoryAs
<const void*>(
9971 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
9973 return error::kOutOfBounds
;
9977 // For testing only. Allows us to stress the ability to respond to OOM errors.
9978 if (workarounds().simulate_out_of_memory_on_large_textures
&&
9979 (width
* height
>= 4096 * 4096)) {
9982 "glTexImage2D", "synthetic out of memory");
9983 return error::kNoError
;
9986 TextureManager::DoTexImageArguments args
= {
9987 target
, level
, internal_format
, width
, height
, 1, border
, format
, type
,
9988 pixels
, pixels_size
, TextureManager::DoTexImageArguments::kTexImage2D
};
9989 texture_manager()->ValidateAndDoTexImage(
9990 &texture_state_
, &state_
, &framebuffer_state_
, "glTexImage2D", args
);
9992 // This may be a slow command. Exit command processing to allow for
9993 // context preemption and GPU watchdog checks.
9994 ExitCommandProcessingEarly();
9995 return error::kNoError
;
9998 error::Error
GLES2DecoderImpl::HandleTexImage3D(uint32 immediate_data_size
,
9999 const void* cmd_data
) {
10000 if (!unsafe_es3_apis_enabled())
10001 return error::kUnknownCommand
;
10003 const gles2::cmds::TexImage3D
& c
=
10004 *static_cast<const gles2::cmds::TexImage3D
*>(cmd_data
);
10005 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage3D",
10006 "widthXheight", c
.width
* c
.height
, "depth", c
.depth
);
10007 // Set as failed for now, but if it successed, this will be set to not failed.
10008 texture_state_
.tex_image_failed
= true;
10009 GLenum target
= static_cast<GLenum
>(c
.target
);
10010 GLint level
= static_cast<GLint
>(c
.level
);
10011 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
10012 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10013 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10014 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
10015 GLint border
= static_cast<GLint
>(c
.border
);
10016 GLenum format
= static_cast<GLenum
>(c
.format
);
10017 GLenum type
= static_cast<GLenum
>(c
.type
);
10018 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
10019 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
10020 uint32 pixels_size
;
10021 if (!GLES2Util::ComputeImageDataSizes(
10022 width
, height
, depth
, format
, type
, state_
.unpack_alignment
, &pixels_size
,
10024 return error::kOutOfBounds
;
10026 const void* pixels
= NULL
;
10027 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
10028 pixels
= GetSharedMemoryAs
<const void*>(
10029 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
10031 return error::kOutOfBounds
;
10035 // For testing only. Allows us to stress the ability to respond to OOM errors.
10036 if (workarounds().simulate_out_of_memory_on_large_textures
&&
10037 (width
* height
* depth
>= 4096 * 4096)) {
10038 LOCAL_SET_GL_ERROR(
10040 "glTexImage3D", "synthetic out of memory");
10041 return error::kNoError
;
10044 TextureManager::DoTexImageArguments args
= {
10045 target
, level
, internal_format
, width
, height
, depth
, border
, format
, type
,
10046 pixels
, pixels_size
, TextureManager::DoTexImageArguments::kTexImage3D
};
10047 texture_manager()->ValidateAndDoTexImage(
10048 &texture_state_
, &state_
, &framebuffer_state_
, "glTexImage3D", args
);
10050 // This may be a slow command. Exit command processing to allow for
10051 // context preemption and GPU watchdog checks.
10052 ExitCommandProcessingEarly();
10053 return error::kNoError
;
10056 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
10064 GLsizei image_size
,
10065 const void * data
) {
10066 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10068 if (!texture_ref
) {
10069 LOCAL_SET_GL_ERROR(
10070 GL_INVALID_OPERATION
,
10071 "glCompressedTexSubImage2D", "unknown texture for target");
10074 Texture
* texture
= texture_ref
->texture();
10076 GLenum internal_format
= 0;
10077 if (!texture
->GetLevelType(target
, level
, &type
, &internal_format
)) {
10078 LOCAL_SET_GL_ERROR(
10079 GL_INVALID_OPERATION
,
10080 "glCompressedTexSubImage2D", "level does not exist.");
10083 if (internal_format
!= format
) {
10084 LOCAL_SET_GL_ERROR(
10085 GL_INVALID_OPERATION
,
10086 "glCompressedTexSubImage2D", "format does not match internal format.");
10089 if (!texture
->ValidForTexture(target
, level
, xoffset
, yoffset
, 0, width
,
10090 height
, 1, type
)) {
10091 LOCAL_SET_GL_ERROR(
10092 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "bad dimensions.");
10096 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage2D",
10097 width
, height
, 1, format
, image_size
) ||
10098 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage2D",
10099 target
, level
, xoffset
, yoffset
, 0,
10100 width
, height
, 1, format
, texture
)) {
10105 // Note: There is no need to deal with texture cleared tracking here
10106 // because the validation above means you can only get here if the level
10107 // is already a matching compressed format and in that case
10108 // CompressedTexImage2D already cleared the texture.
10109 glCompressedTexSubImage2D(
10110 target
, level
, xoffset
, yoffset
, width
, height
, format
, image_size
, data
);
10112 // This may be a slow command. Exit command processing to allow for
10113 // context preemption and GPU watchdog checks.
10114 ExitCommandProcessingEarly();
10118 GLint start
, GLint range
, GLint sourceRange
,
10119 GLint
* out_start
, GLint
* out_range
) {
10126 GLint end
= start
+ range
;
10127 if (end
> sourceRange
) {
10128 range
-= end
- sourceRange
;
10130 *out_start
= start
;
10131 *out_range
= range
;
10134 void GLES2DecoderImpl::DoCopyTexImage2D(
10137 GLenum internal_format
,
10143 DCHECK(!ShouldDeferReads());
10144 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10146 if (!texture_ref
) {
10147 LOCAL_SET_GL_ERROR(
10148 GL_INVALID_OPERATION
,
10149 "glCopyTexImage2D", "unknown texture for target");
10152 Texture
* texture
= texture_ref
->texture();
10153 if (texture
->IsImmutable()) {
10154 LOCAL_SET_GL_ERROR(
10155 GL_INVALID_OPERATION
, "glCopyTexImage2D", "texture is immutable");
10158 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
10160 LOCAL_SET_GL_ERROR(
10161 GL_INVALID_VALUE
, "glCopyTexImage2D", "dimensions out of range");
10164 if (!texture_manager()->ValidateFormatAndTypeCombination(
10165 state_
.GetErrorState(), "glCopyTexImage2D", internal_format
,
10166 GL_UNSIGNED_BYTE
)) {
10170 // Check we have compatible formats.
10171 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
10172 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
10173 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(internal_format
);
10175 if ((channels_needed
& channels_exist
) != channels_needed
) {
10176 LOCAL_SET_GL_ERROR(
10177 GL_INVALID_OPERATION
, "glCopyTexImage2D", "incompatible format");
10181 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
10182 LOCAL_SET_GL_ERROR(
10183 GL_INVALID_OPERATION
,
10184 "glCopyTexImage2D", "can not be used with depth or stencil textures");
10188 uint32 estimated_size
= 0;
10189 if (!GLES2Util::ComputeImageDataSizes(
10190 width
, height
, 1, internal_format
, GL_UNSIGNED_BYTE
,
10191 state_
.unpack_alignment
, &estimated_size
, NULL
, NULL
)) {
10192 LOCAL_SET_GL_ERROR(
10193 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too large");
10197 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
10198 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "out of memory");
10202 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexImage2D")) {
10206 if (FormsTextureCopyingFeedbackLoop(texture_ref
, level
)) {
10207 LOCAL_SET_GL_ERROR(
10208 GL_INVALID_OPERATION
,
10209 "glCopyTexImage2D", "source and destination textures are the same");
10213 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
10217 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
10218 ScopedResolvedFrameBufferBinder
binder(this, false, true);
10219 gfx::Size size
= GetBoundReadFrameBufferSize();
10221 if (texture
->IsAttachedToFramebuffer()) {
10222 framebuffer_state_
.clear_state_dirty
= true;
10225 // Clip to size to source dimensions
10228 GLint copyWidth
= 0;
10229 GLint copyHeight
= 0;
10230 Clip(x
, width
, size
.width(), ©X
, ©Width
);
10231 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
10235 copyWidth
!= width
||
10236 copyHeight
!= height
) {
10237 // some part was clipped so clear the rect.
10238 uint32 pixels_size
= 0;
10239 if (!GLES2Util::ComputeImageDataSizes(
10240 width
, height
, 1, internal_format
, GL_UNSIGNED_BYTE
,
10241 state_
.unpack_alignment
, &pixels_size
, NULL
, NULL
)) {
10242 LOCAL_SET_GL_ERROR(
10243 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too big");
10246 scoped_ptr
<char[]> zero(new char[pixels_size
]);
10247 memset(zero
.get(), 0, pixels_size
);
10248 ScopedModifyPixels
modify(texture_ref
);
10249 glTexImage2D(target
, level
, internal_format
, width
, height
, border
,
10250 internal_format
, GL_UNSIGNED_BYTE
, zero
.get());
10251 if (copyHeight
> 0 && copyWidth
> 0) {
10252 GLint dx
= copyX
- x
;
10253 GLint dy
= copyY
- y
;
10256 glCopyTexSubImage2D(target
, level
,
10257 destX
, destY
, copyX
, copyY
,
10258 copyWidth
, copyHeight
);
10261 ScopedModifyPixels
modify(texture_ref
);
10262 glCopyTexImage2D(target
, level
, internal_format
,
10263 copyX
, copyY
, copyWidth
, copyHeight
, border
);
10265 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
10266 if (error
== GL_NO_ERROR
) {
10267 texture_manager()->SetLevelInfo(texture_ref
, target
, level
, internal_format
,
10268 width
, height
, 1, border
, internal_format
,
10269 GL_UNSIGNED_BYTE
, gfx::Rect(width
, height
));
10272 // This may be a slow command. Exit command processing to allow for
10273 // context preemption and GPU watchdog checks.
10274 ExitCommandProcessingEarly();
10277 void GLES2DecoderImpl::DoCopyTexSubImage2D(
10286 DCHECK(!ShouldDeferReads());
10287 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10289 if (!texture_ref
) {
10290 LOCAL_SET_GL_ERROR(
10291 GL_INVALID_OPERATION
,
10292 "glCopyTexSubImage2D", "unknown texture for target");
10295 Texture
* texture
= texture_ref
->texture();
10298 if (!texture
->GetLevelType(target
, level
, &type
, &format
) ||
10299 !texture
->ValidForTexture(
10300 target
, level
, xoffset
, yoffset
, 0, width
, height
, 1, type
)) {
10301 LOCAL_SET_GL_ERROR(
10302 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "bad dimensions.");
10305 if (async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
10306 LOCAL_SET_GL_ERROR(
10307 GL_INVALID_OPERATION
,
10308 "glCopyTexSubImage2D", "async upload pending for texture");
10312 // Check we have compatible formats.
10313 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
10314 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
10315 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(format
);
10317 if (!channels_needed
||
10318 (channels_needed
& channels_exist
) != channels_needed
) {
10319 LOCAL_SET_GL_ERROR(
10320 GL_INVALID_OPERATION
, "glCopyTexSubImage2D", "incompatible format");
10324 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
10325 LOCAL_SET_GL_ERROR(
10326 GL_INVALID_OPERATION
,
10327 "glCopySubImage2D", "can not be used with depth or stencil textures");
10331 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexSubImage2D")) {
10335 if (FormsTextureCopyingFeedbackLoop(texture_ref
, level
)) {
10336 LOCAL_SET_GL_ERROR(
10337 GL_INVALID_OPERATION
,
10338 "glCopyTexSubImage2D", "source and destination textures are the same");
10342 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
10346 ScopedResolvedFrameBufferBinder
binder(this, false, true);
10347 gfx::Size size
= GetBoundReadFrameBufferSize();
10350 GLint copyWidth
= 0;
10351 GLint copyHeight
= 0;
10352 Clip(x
, width
, size
.width(), ©X
, ©Width
);
10353 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
10355 if (xoffset
!= 0 || yoffset
!= 0 || width
!= size
.width() ||
10356 height
!= size
.height()) {
10357 gfx::Rect cleared_rect
;
10358 if (CombineAdjacentRects(texture
->GetLevelClearedRect(target
, level
),
10359 gfx::Rect(xoffset
, yoffset
, width
, height
),
10361 DCHECK_GE(cleared_rect
.size().GetArea(),
10362 texture
->GetLevelClearedRect(target
, level
).size().GetArea());
10363 texture_manager()->SetLevelClearedRect(texture_ref
, target
, level
,
10366 // Otherwise clear part of texture level that is not already cleared.
10367 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
,
10369 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D",
10370 "dimensions too big");
10375 // Write all pixels in below.
10376 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
10381 copyWidth
!= width
||
10382 copyHeight
!= height
) {
10383 // some part was clipped so clear the sub rect.
10384 uint32 pixels_size
= 0;
10385 if (!GLES2Util::ComputeImageDataSizes(
10386 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
10388 LOCAL_SET_GL_ERROR(
10389 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "dimensions too large");
10392 scoped_ptr
<char[]> zero(new char[pixels_size
]);
10393 memset(zero
.get(), 0, pixels_size
);
10394 ScopedModifyPixels
modify(texture_ref
);
10396 target
, level
, xoffset
, yoffset
, width
, height
,
10397 format
, type
, zero
.get());
10400 if (copyHeight
> 0 && copyWidth
> 0) {
10401 GLint dx
= copyX
- x
;
10402 GLint dy
= copyY
- y
;
10403 GLint destX
= xoffset
+ dx
;
10404 GLint destY
= yoffset
+ dy
;
10405 ScopedModifyPixels
modify(texture_ref
);
10406 glCopyTexSubImage2D(target
, level
,
10407 destX
, destY
, copyX
, copyY
,
10408 copyWidth
, copyHeight
);
10411 // This may be a slow command. Exit command processing to allow for
10412 // context preemption and GPU watchdog checks.
10413 ExitCommandProcessingEarly();
10416 bool GLES2DecoderImpl::ValidateTexSubImage2D(
10417 error::Error
* error
,
10418 const char* function_name
,
10427 const void * data
) {
10428 (*error
) = error::kNoError
;
10429 if (!validators_
->texture_target
.IsValid(target
)) {
10430 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
10434 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "width < 0");
10438 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "height < 0");
10441 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10443 if (!texture_ref
) {
10444 LOCAL_SET_GL_ERROR(
10445 GL_INVALID_OPERATION
,
10446 function_name
, "unknown texture for target");
10449 Texture
* texture
= texture_ref
->texture();
10450 GLenum current_type
= 0;
10451 GLenum internal_format
= 0;
10452 if (!texture
->GetLevelType(target
, level
, ¤t_type
, &internal_format
)) {
10453 LOCAL_SET_GL_ERROR(
10454 GL_INVALID_OPERATION
, function_name
, "level does not exist.");
10457 if (!texture_manager()->ValidateTextureParameters(state_
.GetErrorState(),
10458 function_name
, format
, type
, internal_format
, level
)) {
10461 if (type
!= current_type
) {
10462 LOCAL_SET_GL_ERROR(
10463 GL_INVALID_OPERATION
,
10464 function_name
, "type does not match type of texture.");
10467 if (async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
10468 LOCAL_SET_GL_ERROR(
10469 GL_INVALID_OPERATION
,
10470 function_name
, "async upload pending for texture");
10473 if (!texture
->ValidForTexture(
10474 target
, level
, xoffset
, yoffset
, 0, width
, height
, 1, type
)) {
10475 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "bad dimensions.");
10478 if ((GLES2Util::GetChannelsForFormat(format
) &
10479 (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0
10480 && !feature_info_
->IsES3Enabled()) {
10481 LOCAL_SET_GL_ERROR(
10482 GL_INVALID_OPERATION
,
10483 function_name
, "can not supply data for depth or stencil textures");
10486 if (data
== NULL
) {
10487 (*error
) = error::kOutOfBounds
;
10493 error::Error
GLES2DecoderImpl::DoTexSubImage2D(
10502 const void * data
) {
10503 error::Error error
= error::kNoError
;
10504 if (!ValidateTexSubImage2D(&error
, "glTexSubImage2D", target
, level
,
10505 xoffset
, yoffset
, width
, height
, format
, type
, data
)) {
10508 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10510 Texture
* texture
= texture_ref
->texture();
10511 GLsizei tex_width
= 0;
10512 GLsizei tex_height
= 0;
10513 bool ok
= texture
->GetLevelSize(
10514 target
, level
, &tex_width
, &tex_height
, nullptr);
10516 if (xoffset
!= 0 || yoffset
!= 0 ||
10517 width
!= tex_width
|| height
!= tex_height
) {
10518 gfx::Rect cleared_rect
;
10519 if (CombineAdjacentRects(texture
->GetLevelClearedRect(target
, level
),
10520 gfx::Rect(xoffset
, yoffset
, width
, height
),
10522 DCHECK_GE(cleared_rect
.size().GetArea(),
10523 texture
->GetLevelClearedRect(target
, level
).size().GetArea());
10524 texture_manager()->SetLevelClearedRect(texture_ref
, target
, level
,
10527 // Otherwise clear part of texture level that is not already cleared.
10528 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
,
10530 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glTexSubImage2D",
10531 "dimensions too big");
10532 return error::kNoError
;
10535 ScopedTextureUploadTimer
timer(&texture_state_
);
10537 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
10538 return error::kNoError
;
10541 if (!texture_state_
.texsubimage_faster_than_teximage
&&
10542 !texture
->IsImmutable() &&
10543 !texture
->HasImages()) {
10544 ScopedTextureUploadTimer
timer(&texture_state_
);
10545 GLenum internal_format
;
10547 texture
->GetLevelType(target
, level
, &tex_type
, &internal_format
);
10548 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
10551 target
, level
, internal_format
, width
, height
, 0, format
, type
, data
);
10553 ScopedTextureUploadTimer
timer(&texture_state_
);
10555 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
10557 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
10559 // This may be a slow command. Exit command processing to allow for
10560 // context preemption and GPU watchdog checks.
10561 ExitCommandProcessingEarly();
10562 return error::kNoError
;
10565 error::Error
GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size
,
10566 const void* cmd_data
) {
10567 const gles2::cmds::TexSubImage2D
& c
=
10568 *static_cast<const gles2::cmds::TexSubImage2D
*>(cmd_data
);
10569 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
10570 "width", c
.width
, "height", c
.height
);
10571 GLboolean internal
= static_cast<GLboolean
>(c
.internal
);
10572 if (internal
== GL_TRUE
&& texture_state_
.tex_image_failed
)
10573 return error::kNoError
;
10575 GLenum target
= static_cast<GLenum
>(c
.target
);
10576 GLint level
= static_cast<GLint
>(c
.level
);
10577 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
10578 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
10579 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10580 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10581 GLenum format
= static_cast<GLenum
>(c
.format
);
10582 GLenum type
= static_cast<GLenum
>(c
.type
);
10584 if (!GLES2Util::ComputeImageDataSizes(
10585 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &data_size
,
10587 return error::kOutOfBounds
;
10589 const void* pixels
= GetSharedMemoryAs
<const void*>(
10590 c
.pixels_shm_id
, c
.pixels_shm_offset
, data_size
);
10591 return DoTexSubImage2D(
10592 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
);
10595 error::Error
GLES2DecoderImpl::DoTexSubImage3D(
10606 const void * data
) {
10607 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10609 if (!texture_ref
) {
10610 LOCAL_SET_GL_ERROR(
10611 GL_INVALID_ENUM
, "glTexSubImage3D", "invalid target");
10614 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexSubImage3D");
10615 ScopedTextureUploadTimer
timer(&texture_state_
);
10616 glTexSubImage3D(target
, level
, xoffset
, yoffset
, zoffset
, width
, height
,
10617 depth
, format
, type
, data
);
10618 GLenum error
= LOCAL_PEEK_GL_ERROR("glTexSubImage3D");
10619 if (error
== GL_NO_ERROR
) {
10620 // TODO(zmo): This is not 100% correct because only part of the level
10621 // image is cleared.
10622 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
10625 // This may be a slow command. Exit command processing to allow for
10626 // context preemption and GPU watchdog checks.
10627 ExitCommandProcessingEarly();
10628 return error::kNoError
;
10631 error::Error
GLES2DecoderImpl::HandleTexSubImage3D(uint32 immediate_data_size
,
10632 const void* cmd_data
) {
10633 if (!unsafe_es3_apis_enabled())
10634 return error::kUnknownCommand
;
10636 const gles2::cmds::TexSubImage3D
& c
=
10637 *static_cast<const gles2::cmds::TexSubImage3D
*>(cmd_data
);
10638 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage3D",
10639 "widthXheight", c
.width
* c
.height
, "depth", c
.depth
);
10640 GLboolean internal
= static_cast<GLboolean
>(c
.internal
);
10641 if (internal
== GL_TRUE
&& texture_state_
.tex_image_failed
)
10642 return error::kNoError
;
10644 GLenum target
= static_cast<GLenum
>(c
.target
);
10645 GLint level
= static_cast<GLint
>(c
.level
);
10646 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
10647 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
10648 GLint zoffset
= static_cast<GLint
>(c
.zoffset
);
10649 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10650 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10651 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
10652 GLenum format
= static_cast<GLenum
>(c
.format
);
10653 GLenum type
= static_cast<GLenum
>(c
.type
);
10655 if (!GLES2Util::ComputeImageDataSizes(
10656 width
, height
, depth
, format
, type
, state_
.unpack_alignment
, &data_size
,
10658 return error::kOutOfBounds
;
10660 const void* pixels
= GetSharedMemoryAs
<const void*>(
10661 c
.pixels_shm_id
, c
.pixels_shm_offset
, data_size
);
10662 return DoTexSubImage3D(target
, level
, xoffset
, yoffset
, zoffset
, width
,
10663 height
, depth
, format
, type
, pixels
);
10666 error::Error
GLES2DecoderImpl::HandleGetVertexAttribPointerv(
10667 uint32 immediate_data_size
,
10668 const void* cmd_data
) {
10669 const gles2::cmds::GetVertexAttribPointerv
& c
=
10670 *static_cast<const gles2::cmds::GetVertexAttribPointerv
*>(cmd_data
);
10671 GLuint index
= static_cast<GLuint
>(c
.index
);
10672 GLenum pname
= static_cast<GLenum
>(c
.pname
);
10673 typedef cmds::GetVertexAttribPointerv::Result Result
;
10674 Result
* result
= GetSharedMemoryAs
<Result
*>(
10675 c
.pointer_shm_id
, c
.pointer_shm_offset
, Result::ComputeSize(1));
10677 return error::kOutOfBounds
;
10679 // Check that the client initialized the result.
10680 if (result
->size
!= 0) {
10681 return error::kInvalidArguments
;
10683 if (!validators_
->vertex_pointer
.IsValid(pname
)) {
10684 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10685 "glGetVertexAttribPointerv", pname
, "pname");
10686 return error::kNoError
;
10688 if (index
>= group_
->max_vertex_attribs()) {
10689 LOCAL_SET_GL_ERROR(
10690 GL_INVALID_VALUE
, "glGetVertexAttribPointerv", "index out of range.");
10691 return error::kNoError
;
10693 result
->SetNumResults(1);
10694 *result
->GetData() =
10695 state_
.vertex_attrib_manager
->GetVertexAttrib(index
)->offset();
10696 return error::kNoError
;
10700 bool GLES2DecoderImpl::GetUniformSetup(GLuint program_id
,
10701 GLint fake_location
,
10704 error::Error
* error
,
10705 GLint
* real_location
,
10706 GLuint
* service_id
,
10707 SizedResult
<T
>** result_pointer
,
10708 GLenum
* result_type
,
10709 GLsizei
* result_size
) {
10711 DCHECK(service_id
);
10712 DCHECK(result_pointer
);
10713 DCHECK(result_type
);
10714 DCHECK(result_size
);
10715 DCHECK(real_location
);
10716 *error
= error::kNoError
;
10717 // Make sure we have enough room for the result on failure.
10718 SizedResult
<T
>* result
;
10719 result
= GetSharedMemoryAs
<SizedResult
<T
>*>(
10720 shm_id
, shm_offset
, SizedResult
<T
>::ComputeSize(0));
10722 *error
= error::kOutOfBounds
;
10725 *result_pointer
= result
;
10726 // Set the result size to 0 so the client does not have to check for success.
10727 result
->SetNumResults(0);
10728 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetUniform");
10732 if (!program
->IsValid()) {
10733 // Program was not linked successfully. (ie, glLinkProgram)
10734 LOCAL_SET_GL_ERROR(
10735 GL_INVALID_OPERATION
, "glGetUniform", "program not linked");
10738 *service_id
= program
->service_id();
10739 GLint array_index
= -1;
10740 const Program::UniformInfo
* uniform_info
=
10741 program
->GetUniformInfoByFakeLocation(
10742 fake_location
, real_location
, &array_index
);
10743 if (!uniform_info
) {
10744 // No such location.
10745 LOCAL_SET_GL_ERROR(
10746 GL_INVALID_OPERATION
, "glGetUniform", "unknown location");
10749 GLenum type
= uniform_info
->type
;
10750 uint32 num_elements
= GLES2Util::GetElementCountForUniformType(type
);
10751 if (num_elements
== 0) {
10752 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glGetUniform", "unknown type");
10755 result
= GetSharedMemoryAs
<SizedResult
<T
>*>(
10756 shm_id
, shm_offset
, SizedResult
<T
>::ComputeSize(num_elements
));
10758 *error
= error::kOutOfBounds
;
10761 result
->SetNumResults(num_elements
);
10762 *result_size
= num_elements
* sizeof(T
);
10763 *result_type
= type
;
10767 error::Error
GLES2DecoderImpl::HandleGetUniformiv(uint32 immediate_data_size
,
10768 const void* cmd_data
) {
10769 const gles2::cmds::GetUniformiv
& c
=
10770 *static_cast<const gles2::cmds::GetUniformiv
*>(cmd_data
);
10771 GLuint program
= c
.program
;
10772 GLint fake_location
= c
.location
;
10774 GLenum result_type
;
10775 GLsizei result_size
;
10776 GLint real_location
= -1;
10778 cmds::GetUniformiv::Result
* result
;
10779 if (GetUniformSetup
<GLint
>(program
, fake_location
, c
.params_shm_id
,
10780 c
.params_shm_offset
, &error
, &real_location
,
10781 &service_id
, &result
, &result_type
,
10784 service_id
, real_location
, result
->GetData());
10789 error::Error
GLES2DecoderImpl::HandleGetUniformuiv(uint32 immediate_data_size
,
10790 const void* cmd_data
) {
10791 if (!unsafe_es3_apis_enabled())
10792 return error::kUnknownCommand
;
10794 const gles2::cmds::GetUniformuiv
& c
=
10795 *static_cast<const gles2::cmds::GetUniformuiv
*>(cmd_data
);
10796 GLuint program
= c
.program
;
10797 GLint fake_location
= c
.location
;
10799 GLenum result_type
;
10800 GLsizei result_size
;
10801 GLint real_location
= -1;
10803 cmds::GetUniformuiv::Result
* result
;
10804 if (GetUniformSetup
<GLuint
>(program
, fake_location
, c
.params_shm_id
,
10805 c
.params_shm_offset
, &error
, &real_location
,
10806 &service_id
, &result
, &result_type
,
10809 service_id
, real_location
, result
->GetData());
10814 error::Error
GLES2DecoderImpl::HandleGetUniformfv(uint32 immediate_data_size
,
10815 const void* cmd_data
) {
10816 const gles2::cmds::GetUniformfv
& c
=
10817 *static_cast<const gles2::cmds::GetUniformfv
*>(cmd_data
);
10818 GLuint program
= c
.program
;
10819 GLint fake_location
= c
.location
;
10821 GLint real_location
= -1;
10823 cmds::GetUniformfv::Result
* result
;
10824 GLenum result_type
;
10825 GLsizei result_size
;
10826 if (GetUniformSetup
<GLfloat
>(program
, fake_location
, c
.params_shm_id
,
10827 c
.params_shm_offset
, &error
, &real_location
,
10828 &service_id
, &result
, &result_type
,
10830 if (result_type
== GL_BOOL
|| result_type
== GL_BOOL_VEC2
||
10831 result_type
== GL_BOOL_VEC3
|| result_type
== GL_BOOL_VEC4
) {
10832 GLsizei num_values
= result_size
/ sizeof(GLfloat
);
10833 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
10834 glGetUniformiv(service_id
, real_location
, temp
.get());
10835 GLfloat
* dst
= result
->GetData();
10836 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
10837 dst
[ii
] = (temp
[ii
] != 0);
10840 glGetUniformfv(service_id
, real_location
, result
->GetData());
10846 error::Error
GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
10847 uint32 immediate_data_size
,
10848 const void* cmd_data
) {
10849 const gles2::cmds::GetShaderPrecisionFormat
& c
=
10850 *static_cast<const gles2::cmds::GetShaderPrecisionFormat
*>(cmd_data
);
10851 GLenum shader_type
= static_cast<GLenum
>(c
.shadertype
);
10852 GLenum precision_type
= static_cast<GLenum
>(c
.precisiontype
);
10853 typedef cmds::GetShaderPrecisionFormat::Result Result
;
10854 Result
* result
= GetSharedMemoryAs
<Result
*>(
10855 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10857 return error::kOutOfBounds
;
10859 // Check that the client initialized the result.
10860 if (result
->success
!= 0) {
10861 return error::kInvalidArguments
;
10863 if (!validators_
->shader_type
.IsValid(shader_type
)) {
10864 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10865 "glGetShaderPrecisionFormat", shader_type
, "shader_type");
10866 return error::kNoError
;
10868 if (!validators_
->shader_precision
.IsValid(precision_type
)) {
10869 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10870 "glGetShaderPrecisionFormat", precision_type
, "precision_type");
10871 return error::kNoError
;
10874 result
->success
= 1; // true
10876 GLint range
[2] = { 0, 0 };
10877 GLint precision
= 0;
10878 GetShaderPrecisionFormatImpl(shader_type
, precision_type
, range
, &precision
);
10880 result
->min_range
= range
[0];
10881 result
->max_range
= range
[1];
10882 result
->precision
= precision
;
10884 return error::kNoError
;
10887 error::Error
GLES2DecoderImpl::HandleGetAttachedShaders(
10888 uint32 immediate_data_size
,
10889 const void* cmd_data
) {
10890 const gles2::cmds::GetAttachedShaders
& c
=
10891 *static_cast<const gles2::cmds::GetAttachedShaders
*>(cmd_data
);
10892 uint32 result_size
= c
.result_size
;
10893 GLuint program_id
= static_cast<GLuint
>(c
.program
);
10894 Program
* program
= GetProgramInfoNotShader(
10895 program_id
, "glGetAttachedShaders");
10897 return error::kNoError
;
10899 typedef cmds::GetAttachedShaders::Result Result
;
10900 uint32 max_count
= Result::ComputeMaxResults(result_size
);
10901 Result
* result
= GetSharedMemoryAs
<Result
*>(
10902 c
.result_shm_id
, c
.result_shm_offset
, Result::ComputeSize(max_count
));
10904 return error::kOutOfBounds
;
10906 // Check that the client initialized the result.
10907 if (result
->size
!= 0) {
10908 return error::kInvalidArguments
;
10911 glGetAttachedShaders(
10912 program
->service_id(), max_count
, &count
, result
->GetData());
10913 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
10914 if (!shader_manager()->GetClientId(result
->GetData()[ii
],
10915 &result
->GetData()[ii
])) {
10917 return error::kGenericError
;
10920 result
->SetNumResults(count
);
10921 return error::kNoError
;
10924 error::Error
GLES2DecoderImpl::HandleGetActiveUniform(
10925 uint32 immediate_data_size
,
10926 const void* cmd_data
) {
10927 const gles2::cmds::GetActiveUniform
& c
=
10928 *static_cast<const gles2::cmds::GetActiveUniform
*>(cmd_data
);
10929 GLuint program_id
= c
.program
;
10930 GLuint index
= c
.index
;
10931 uint32 name_bucket_id
= c
.name_bucket_id
;
10932 typedef cmds::GetActiveUniform::Result Result
;
10933 Result
* result
= GetSharedMemoryAs
<Result
*>(
10934 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10936 return error::kOutOfBounds
;
10938 // Check that the client initialized the result.
10939 if (result
->success
!= 0) {
10940 return error::kInvalidArguments
;
10942 Program
* program
= GetProgramInfoNotShader(
10943 program_id
, "glGetActiveUniform");
10945 return error::kNoError
;
10947 const Program::UniformInfo
* uniform_info
=
10948 program
->GetUniformInfo(index
);
10949 if (!uniform_info
) {
10950 LOCAL_SET_GL_ERROR(
10951 GL_INVALID_VALUE
, "glGetActiveUniform", "index out of range");
10952 return error::kNoError
;
10954 result
->success
= 1; // true.
10955 result
->size
= uniform_info
->size
;
10956 result
->type
= uniform_info
->type
;
10957 Bucket
* bucket
= CreateBucket(name_bucket_id
);
10958 bucket
->SetFromString(uniform_info
->name
.c_str());
10959 return error::kNoError
;
10962 error::Error
GLES2DecoderImpl::HandleGetActiveUniformBlockiv(
10963 uint32 immediate_data_size
, const void* cmd_data
) {
10964 if (!unsafe_es3_apis_enabled())
10965 return error::kUnknownCommand
;
10966 const gles2::cmds::GetActiveUniformBlockiv
& c
=
10967 *static_cast<const gles2::cmds::GetActiveUniformBlockiv
*>(cmd_data
);
10968 GLuint program_id
= c
.program
;
10969 GLuint index
= static_cast<GLuint
>(c
.index
);
10970 GLenum pname
= static_cast<GLenum
>(c
.pname
);
10971 Program
* program
= GetProgramInfoNotShader(
10972 program_id
, "glGetActiveUniformBlockiv");
10974 return error::kNoError
;
10976 GLuint service_id
= program
->service_id();
10977 GLint link_status
= GL_FALSE
;
10978 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
10979 if (link_status
!= GL_TRUE
) {
10980 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10981 "glGetActiveActiveUniformBlockiv", "program not linked");
10982 return error::kNoError
;
10984 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformBlockiv");
10985 GLsizei num_values
= 1;
10986 if (pname
== GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES
) {
10988 glGetActiveUniformBlockiv(
10989 service_id
, index
, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS
, &num
);
10990 GLenum error
= glGetError();
10991 if (error
!= GL_NO_ERROR
) {
10992 // Assume this will the same error if calling with pname.
10993 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformBlockiv", "");
10994 return error::kNoError
;
10996 num_values
= static_cast<GLsizei
>(num
);
10998 typedef cmds::GetActiveUniformBlockiv::Result Result
;
10999 Result
* result
= GetSharedMemoryAs
<Result
*>(
11000 c
.params_shm_id
, c
.params_shm_offset
, Result::ComputeSize(num_values
));
11001 GLint
* params
= result
? result
->GetData() : NULL
;
11002 if (params
== NULL
) {
11003 return error::kOutOfBounds
;
11005 // Check that the client initialized the result.
11006 if (result
->size
!= 0) {
11007 return error::kInvalidArguments
;
11009 glGetActiveUniformBlockiv(service_id
, index
, pname
, params
);
11010 GLenum error
= glGetError();
11011 if (error
== GL_NO_ERROR
) {
11012 result
->SetNumResults(num_values
);
11014 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformBlockiv", "");
11016 return error::kNoError
;
11019 error::Error
GLES2DecoderImpl::HandleGetActiveUniformBlockName(
11020 uint32 immediate_data_size
, const void* cmd_data
) {
11021 if (!unsafe_es3_apis_enabled())
11022 return error::kUnknownCommand
;
11023 const gles2::cmds::GetActiveUniformBlockName
& c
=
11024 *static_cast<const gles2::cmds::GetActiveUniformBlockName
*>(cmd_data
);
11025 GLuint program_id
= c
.program
;
11026 GLuint index
= c
.index
;
11027 uint32 name_bucket_id
= c
.name_bucket_id
;
11028 typedef cmds::GetActiveUniformBlockName::Result Result
;
11029 Result
* result
= GetSharedMemoryAs
<Result
*>(
11030 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
11032 return error::kOutOfBounds
;
11034 // Check that the client initialized the result.
11035 if (*result
!= 0) {
11036 return error::kInvalidArguments
;
11038 Program
* program
= GetProgramInfoNotShader(
11039 program_id
, "glGetActiveUniformBlockName");
11041 return error::kNoError
;
11043 GLuint service_id
= program
->service_id();
11044 GLint link_status
= GL_FALSE
;
11045 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
11046 if (link_status
!= GL_TRUE
) {
11047 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11048 "glGetActiveActiveUniformBlockName", "program not linked");
11049 return error::kNoError
;
11051 GLint max_length
= 0;
11053 service_id
, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH
, &max_length
);
11054 // Increase one so &buffer[0] is always valid.
11055 GLsizei buf_size
= static_cast<GLsizei
>(max_length
) + 1;
11056 std::vector
<char> buffer(buf_size
);
11057 GLsizei length
= 0;
11058 glGetActiveUniformBlockName(
11059 service_id
, index
, buf_size
, &length
, &buffer
[0]);
11062 return error::kNoError
;
11065 Bucket
* bucket
= CreateBucket(name_bucket_id
);
11066 DCHECK_GT(buf_size
, length
);
11067 DCHECK_EQ(0, buffer
[length
]);
11068 bucket
->SetFromString(&buffer
[0]);
11069 return error::kNoError
;
11072 error::Error
GLES2DecoderImpl::HandleGetActiveUniformsiv(
11073 uint32 immediate_data_size
, const void* cmd_data
) {
11074 if (!unsafe_es3_apis_enabled())
11075 return error::kUnknownCommand
;
11076 const gles2::cmds::GetActiveUniformsiv
& c
=
11077 *static_cast<const gles2::cmds::GetActiveUniformsiv
*>(cmd_data
);
11078 GLuint program_id
= c
.program
;
11079 GLenum pname
= static_cast<GLenum
>(c
.pname
);
11080 Bucket
* bucket
= GetBucket(c
.indices_bucket_id
);
11082 return error::kInvalidArguments
;
11084 GLsizei count
= static_cast<GLsizei
>(bucket
->size() / sizeof(GLuint
));
11085 const GLuint
* indices
= bucket
->GetDataAs
<const GLuint
*>(0, bucket
->size());
11086 typedef cmds::GetActiveUniformsiv::Result Result
;
11087 Result
* result
= GetSharedMemoryAs
<Result
*>(
11088 c
.params_shm_id
, c
.params_shm_offset
, Result::ComputeSize(count
));
11089 GLint
* params
= result
? result
->GetData() : NULL
;
11090 if (params
== NULL
) {
11091 return error::kOutOfBounds
;
11093 // Check that the client initialized the result.
11094 if (result
->size
!= 0) {
11095 return error::kInvalidArguments
;
11097 Program
* program
= GetProgramInfoNotShader(
11098 program_id
, "glGetActiveUniformsiv");
11100 return error::kNoError
;
11102 GLuint service_id
= program
->service_id();
11103 GLint link_status
= GL_FALSE
;
11104 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
11105 if (link_status
!= GL_TRUE
) {
11106 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11107 "glGetActiveUniformsiv", "program not linked");
11108 return error::kNoError
;
11110 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformsiv");
11111 glGetActiveUniformsiv(service_id
, count
, indices
, pname
, params
);
11112 GLenum error
= glGetError();
11113 if (error
== GL_NO_ERROR
) {
11114 result
->SetNumResults(count
);
11116 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformsiv", "");
11118 return error::kNoError
;
11121 error::Error
GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size
,
11122 const void* cmd_data
) {
11123 const gles2::cmds::GetActiveAttrib
& c
=
11124 *static_cast<const gles2::cmds::GetActiveAttrib
*>(cmd_data
);
11125 GLuint program_id
= c
.program
;
11126 GLuint index
= c
.index
;
11127 uint32 name_bucket_id
= c
.name_bucket_id
;
11128 typedef cmds::GetActiveAttrib::Result Result
;
11129 Result
* result
= GetSharedMemoryAs
<Result
*>(
11130 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
11132 return error::kOutOfBounds
;
11134 // Check that the client initialized the result.
11135 if (result
->success
!= 0) {
11136 return error::kInvalidArguments
;
11138 Program
* program
= GetProgramInfoNotShader(
11139 program_id
, "glGetActiveAttrib");
11141 return error::kNoError
;
11143 const Program::VertexAttrib
* attrib_info
=
11144 program
->GetAttribInfo(index
);
11145 if (!attrib_info
) {
11146 LOCAL_SET_GL_ERROR(
11147 GL_INVALID_VALUE
, "glGetActiveAttrib", "index out of range");
11148 return error::kNoError
;
11150 result
->success
= 1; // true.
11151 result
->size
= attrib_info
->size
;
11152 result
->type
= attrib_info
->type
;
11153 Bucket
* bucket
= CreateBucket(name_bucket_id
);
11154 bucket
->SetFromString(attrib_info
->name
.c_str());
11155 return error::kNoError
;
11158 error::Error
GLES2DecoderImpl::HandleShaderBinary(uint32 immediate_data_size
,
11159 const void* cmd_data
) {
11160 #if 1 // No binary shader support.
11161 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glShaderBinary", "not supported");
11162 return error::kNoError
;
11164 GLsizei n
= static_cast<GLsizei
>(c
.n
);
11166 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "n < 0");
11167 return error::kNoError
;
11169 GLsizei length
= static_cast<GLsizei
>(c
.length
);
11171 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "length < 0");
11172 return error::kNoError
;
11175 if (!SafeMultiplyUint32(n
, sizeof(GLuint
), &data_size
)) {
11176 return error::kOutOfBounds
;
11178 const GLuint
* shaders
= GetSharedMemoryAs
<const GLuint
*>(
11179 c
.shaders_shm_id
, c
.shaders_shm_offset
, data_size
);
11180 GLenum binaryformat
= static_cast<GLenum
>(c
.binaryformat
);
11181 const void* binary
= GetSharedMemoryAs
<const void*>(
11182 c
.binary_shm_id
, c
.binary_shm_offset
, length
);
11183 if (shaders
== NULL
|| binary
== NULL
) {
11184 return error::kOutOfBounds
;
11186 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
11187 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11188 Shader
* shader
= GetShader(shaders
[ii
]);
11190 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "unknown shader");
11191 return error::kNoError
;
11193 service_ids
[ii
] = shader
->service_id();
11195 // TODO(gman): call glShaderBinary
11196 return error::kNoError
;
11200 void GLES2DecoderImpl::DoSwapBuffers() {
11201 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
11203 int this_frame_number
= frame_number_
++;
11204 // TRACE_EVENT for gpu tests:
11205 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
11206 TRACE_EVENT_SCOPE_THREAD
,
11207 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
11208 "width", (is_offscreen
? offscreen_size_
.width() :
11209 surface_
->GetSize().width()));
11210 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
11211 "offscreen", is_offscreen
,
11212 "frame", this_frame_number
);
11214 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
11217 ScopedGPUTrace
scoped_gpu_trace(gpu_tracer_
.get(), kTraceDecoder
,
11218 "GLES2Decoder", "SwapBuffer");
11221 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
11224 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
11225 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
11226 is_offscreen
? offscreen_size_
: surface_
->GetSize());
11229 // If offscreen then don't actually SwapBuffers to the display. Just copy
11230 // the rendered frame to another frame buffer.
11231 if (is_offscreen
) {
11232 TRACE_EVENT2("gpu", "Offscreen",
11233 "width", offscreen_size_
.width(), "height", offscreen_size_
.height());
11234 if (offscreen_size_
!= offscreen_saved_color_texture_
->size()) {
11235 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
11236 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
11238 if (workarounds().needs_offscreen_buffer_workaround
) {
11239 offscreen_saved_frame_buffer_
->Create();
11243 // Allocate the offscreen saved color texture.
11244 DCHECK(offscreen_saved_color_format_
);
11245 offscreen_saved_color_texture_
->AllocateStorage(
11246 offscreen_size_
, offscreen_saved_color_format_
, false);
11248 offscreen_saved_frame_buffer_
->AttachRenderTexture(
11249 offscreen_saved_color_texture_
.get());
11250 if (offscreen_size_
.width() != 0 && offscreen_size_
.height() != 0) {
11251 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
11252 GL_FRAMEBUFFER_COMPLETE
) {
11253 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
11254 << "because offscreen saved FBO was incomplete.";
11255 MarkContextLost(error::kUnknown
);
11256 group_
->LoseContexts(error::kUnknown
);
11260 // Clear the offscreen color texture.
11261 // TODO(piman): Is this still necessary?
11263 ScopedFrameBufferBinder
binder(this,
11264 offscreen_saved_frame_buffer_
->id());
11265 glClearColor(0, 0, 0, 0);
11266 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
11267 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
11268 glClear(GL_COLOR_BUFFER_BIT
);
11269 RestoreClearState();
11273 UpdateParentTextureInfo();
11276 if (offscreen_size_
.width() == 0 || offscreen_size_
.height() == 0)
11278 ScopedGLErrorSuppressor
suppressor(
11279 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
11281 if (IsOffscreenBufferMultisampled()) {
11282 // For multisampled buffers, resolve the frame buffer.
11283 ScopedResolvedFrameBufferBinder
binder(this, true, false);
11285 ScopedFrameBufferBinder
binder(this,
11286 offscreen_target_frame_buffer_
->id());
11288 if (offscreen_target_buffer_preserved_
) {
11289 // Copy the target frame buffer to the saved offscreen texture.
11290 offscreen_saved_color_texture_
->Copy(
11291 offscreen_saved_color_texture_
->size(),
11292 offscreen_saved_color_format_
);
11294 // Flip the textures in the parent context via the texture manager.
11295 if (!!offscreen_saved_color_texture_info_
.get())
11296 offscreen_saved_color_texture_info_
->texture()->
11297 SetServiceId(offscreen_target_color_texture_
->id());
11299 offscreen_saved_color_texture_
.swap(offscreen_target_color_texture_
);
11300 offscreen_target_frame_buffer_
->AttachRenderTexture(
11301 offscreen_target_color_texture_
.get());
11304 // Ensure the side effects of the copy are visible to the parent
11305 // context. There is no need to do this for ANGLE because it uses a
11306 // single D3D device for all contexts.
11307 if (!feature_info_
->gl_version_info().is_angle
)
11311 if (surface_
->SwapBuffers() == gfx::SwapResult::SWAP_FAILED
) {
11312 LOG(ERROR
) << "Context lost because SwapBuffers failed.";
11313 if (!CheckResetStatus()) {
11314 MarkContextLost(error::kUnknown
);
11315 group_
->LoseContexts(error::kUnknown
);
11320 // This may be a slow command. Exit command processing to allow for
11321 // context preemption and GPU watchdog checks.
11322 ExitCommandProcessingEarly();
11325 void GLES2DecoderImpl::DoSwapInterval(int interval
) {
11326 context_
->SetSwapInterval(interval
);
11329 error::Error
GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
11330 uint32 immediate_data_size
,
11331 const void* cmd_data
) {
11332 const gles2::cmds::EnableFeatureCHROMIUM
& c
=
11333 *static_cast<const gles2::cmds::EnableFeatureCHROMIUM
*>(cmd_data
);
11334 Bucket
* bucket
= GetBucket(c
.bucket_id
);
11335 if (!bucket
|| bucket
->size() == 0) {
11336 return error::kInvalidArguments
;
11338 typedef cmds::EnableFeatureCHROMIUM::Result Result
;
11339 Result
* result
= GetSharedMemoryAs
<Result
*>(
11340 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
11342 return error::kOutOfBounds
;
11344 // Check that the client initialized the result.
11345 if (*result
!= 0) {
11346 return error::kInvalidArguments
;
11348 std::string feature_str
;
11349 if (!bucket
->GetAsString(&feature_str
)) {
11350 return error::kInvalidArguments
;
11353 // TODO(gman): make this some kind of table to function pointer thingy.
11354 if (feature_str
.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
11355 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
11356 } else if (feature_str
.compare("pepper3d_support_fixed_attribs") == 0) {
11357 buffer_manager()->set_allow_fixed_attribs(true);
11358 // TODO(gman): decide how to remove the need for this const_cast.
11359 // I could make validators_ non const but that seems bad as this is the only
11360 // place it is needed. I could make some special friend class of validators
11361 // just to allow this to set them. That seems silly. I could refactor this
11362 // code to use the extension mechanism or the initialization attributes to
11363 // turn this feature on. Given that the only real point of this is to make
11364 // the conformance tests pass and given that there is lots of real work that
11365 // needs to be done it seems like refactoring for one to one of those
11366 // methods is a very low priority.
11367 const_cast<Validators
*>(validators_
)->vertex_attrib_type
.AddValue(GL_FIXED
);
11369 return error::kNoError
;
11372 *result
= 1; // true.
11373 return error::kNoError
;
11376 error::Error
GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
11377 uint32 immediate_data_size
,
11378 const void* cmd_data
) {
11379 const gles2::cmds::GetRequestableExtensionsCHROMIUM
& c
=
11380 *static_cast<const gles2::cmds::GetRequestableExtensionsCHROMIUM
*>(
11382 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
11383 scoped_refptr
<FeatureInfo
> info(new FeatureInfo());
11384 info
->Initialize(disallowed_features_
);
11385 bucket
->SetFromString(info
->extensions().c_str());
11386 return error::kNoError
;
11389 error::Error
GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
11390 uint32 immediate_data_size
,
11391 const void* cmd_data
) {
11392 const gles2::cmds::RequestExtensionCHROMIUM
& c
=
11393 *static_cast<const gles2::cmds::RequestExtensionCHROMIUM
*>(cmd_data
);
11394 Bucket
* bucket
= GetBucket(c
.bucket_id
);
11395 if (!bucket
|| bucket
->size() == 0) {
11396 return error::kInvalidArguments
;
11398 std::string feature_str
;
11399 if (!bucket
->GetAsString(&feature_str
)) {
11400 return error::kInvalidArguments
;
11403 bool desire_standard_derivatives
= false;
11404 bool desire_frag_depth
= false;
11405 bool desire_draw_buffers
= false;
11406 bool desire_shader_texture_lod
= false;
11407 if (IsWebGLContext()) {
11408 desire_standard_derivatives
=
11409 feature_str
.find("GL_OES_standard_derivatives") != std::string::npos
;
11410 desire_frag_depth
=
11411 feature_str
.find("GL_EXT_frag_depth") != std::string::npos
;
11412 desire_draw_buffers
=
11413 feature_str
.find("GL_EXT_draw_buffers") != std::string::npos
;
11414 desire_shader_texture_lod
=
11415 feature_str
.find("GL_EXT_shader_texture_lod") != std::string::npos
;
11418 if (desire_standard_derivatives
!= derivatives_explicitly_enabled_
||
11419 desire_frag_depth
!= frag_depth_explicitly_enabled_
||
11420 desire_draw_buffers
!= draw_buffers_explicitly_enabled_
||
11421 desire_shader_texture_lod
!= shader_texture_lod_explicitly_enabled_
) {
11422 derivatives_explicitly_enabled_
|= desire_standard_derivatives
;
11423 frag_depth_explicitly_enabled_
|= desire_frag_depth
;
11424 draw_buffers_explicitly_enabled_
|= desire_draw_buffers
;
11425 shader_texture_lod_explicitly_enabled_
|= desire_shader_texture_lod
;
11426 InitializeShaderTranslator();
11429 UpdateCapabilities();
11431 return error::kNoError
;
11434 error::Error
GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
11435 uint32 immediate_data_size
,
11436 const void* cmd_data
) {
11437 const gles2::cmds::GetProgramInfoCHROMIUM
& c
=
11438 *static_cast<const gles2::cmds::GetProgramInfoCHROMIUM
*>(cmd_data
);
11439 GLuint program_id
= static_cast<GLuint
>(c
.program
);
11440 uint32 bucket_id
= c
.bucket_id
;
11441 Bucket
* bucket
= CreateBucket(bucket_id
);
11442 bucket
->SetSize(sizeof(ProgramInfoHeader
)); // in case we fail.
11443 Program
* program
= NULL
;
11444 program
= GetProgram(program_id
);
11445 if (!program
|| !program
->IsValid()) {
11446 return error::kNoError
;
11448 program
->GetProgramInfo(program_manager(), bucket
);
11449 return error::kNoError
;
11452 error::Error
GLES2DecoderImpl::HandleGetUniformBlocksCHROMIUM(
11453 uint32 immediate_data_size
, const void* cmd_data
) {
11454 if (!unsafe_es3_apis_enabled())
11455 return error::kUnknownCommand
;
11456 const gles2::cmds::GetUniformBlocksCHROMIUM
& c
=
11457 *static_cast<const gles2::cmds::GetUniformBlocksCHROMIUM
*>(cmd_data
);
11458 GLuint program_id
= static_cast<GLuint
>(c
.program
);
11459 uint32 bucket_id
= c
.bucket_id
;
11460 Bucket
* bucket
= CreateBucket(bucket_id
);
11461 bucket
->SetSize(sizeof(UniformBlocksHeader
)); // in case we fail.
11462 Program
* program
= NULL
;
11463 program
= GetProgram(program_id
);
11464 if (!program
|| !program
->IsValid()) {
11465 return error::kNoError
;
11467 program
->GetUniformBlocks(bucket
);
11468 return error::kNoError
;
11471 error::Error
GLES2DecoderImpl::HandleGetUniformsES3CHROMIUM(
11472 uint32 immediate_data_size
, const void* cmd_data
) {
11473 if (!unsafe_es3_apis_enabled())
11474 return error::kUnknownCommand
;
11475 const gles2::cmds::GetUniformsES3CHROMIUM
& c
=
11476 *static_cast<const gles2::cmds::GetUniformsES3CHROMIUM
*>(cmd_data
);
11477 GLuint program_id
= static_cast<GLuint
>(c
.program
);
11478 uint32 bucket_id
= c
.bucket_id
;
11479 Bucket
* bucket
= CreateBucket(bucket_id
);
11480 bucket
->SetSize(sizeof(UniformsES3Header
)); // in case we fail.
11481 Program
* program
= NULL
;
11482 program
= GetProgram(program_id
);
11483 if (!program
|| !program
->IsValid()) {
11484 return error::kNoError
;
11486 program
->GetUniformsES3(bucket
);
11487 return error::kNoError
;
11490 error::Error
GLES2DecoderImpl::HandleGetTransformFeedbackVarying(
11491 uint32 immediate_data_size
,
11492 const void* cmd_data
) {
11493 if (!unsafe_es3_apis_enabled())
11494 return error::kUnknownCommand
;
11495 const gles2::cmds::GetTransformFeedbackVarying
& c
=
11496 *static_cast<const gles2::cmds::GetTransformFeedbackVarying
*>(cmd_data
);
11497 GLuint program_id
= c
.program
;
11498 GLuint index
= c
.index
;
11499 uint32 name_bucket_id
= c
.name_bucket_id
;
11500 typedef cmds::GetTransformFeedbackVarying::Result Result
;
11501 Result
* result
= GetSharedMemoryAs
<Result
*>(
11502 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
11504 return error::kOutOfBounds
;
11506 // Check that the client initialized the result.
11507 if (result
->success
!= 0) {
11508 return error::kInvalidArguments
;
11510 Program
* program
= GetProgramInfoNotShader(
11511 program_id
, "glGetTransformFeedbackVarying");
11513 return error::kNoError
;
11515 GLuint service_id
= program
->service_id();
11516 GLint link_status
= GL_FALSE
;
11517 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
11518 if (link_status
!= GL_TRUE
) {
11519 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11520 "glGetTransformFeedbackVarying", "program not linked");
11521 return error::kNoError
;
11523 GLint max_length
= 0;
11525 service_id
, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH
, &max_length
);
11526 max_length
= std::max(1, max_length
);
11527 std::vector
<char> buffer(max_length
);
11528 GLsizei length
= 0;
11531 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetTransformFeedbackVarying");
11532 glGetTransformFeedbackVarying(
11533 service_id
, index
, max_length
, &length
, &size
, &type
, &buffer
[0]);
11534 GLenum error
= glGetError();
11535 if (error
!= GL_NO_ERROR
) {
11536 LOCAL_SET_GL_ERROR(error
, "glGetTransformFeedbackVarying", "");
11537 return error::kNoError
;
11539 result
->success
= 1; // true.
11540 result
->size
= static_cast<int32_t>(size
);
11541 result
->type
= static_cast<uint32_t>(type
);
11542 Bucket
* bucket
= CreateBucket(name_bucket_id
);
11543 DCHECK(length
>= 0 && length
< max_length
);
11544 buffer
[length
] = '\0'; // Just to be safe.
11545 bucket
->SetFromString(&buffer
[0]);
11546 return error::kNoError
;
11549 error::Error
GLES2DecoderImpl::HandleGetTransformFeedbackVaryingsCHROMIUM(
11550 uint32 immediate_data_size
, const void* cmd_data
) {
11551 if (!unsafe_es3_apis_enabled())
11552 return error::kUnknownCommand
;
11553 const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM
& c
=
11554 *static_cast<const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM
*>(
11556 GLuint program_id
= static_cast<GLuint
>(c
.program
);
11557 uint32 bucket_id
= c
.bucket_id
;
11558 Bucket
* bucket
= CreateBucket(bucket_id
);
11559 bucket
->SetSize(sizeof(TransformFeedbackVaryingsHeader
)); // in case we fail.
11560 Program
* program
= NULL
;
11561 program
= GetProgram(program_id
);
11562 if (!program
|| !program
->IsValid()) {
11563 return error::kNoError
;
11565 program
->GetTransformFeedbackVaryings(bucket
);
11566 return error::kNoError
;
11569 error::ContextLostReason
GLES2DecoderImpl::GetContextLostReason() {
11570 return context_lost_reason_
;
11573 error::ContextLostReason
GLES2DecoderImpl::GetContextLostReasonFromResetStatus(
11574 GLenum reset_status
) const {
11575 switch (reset_status
) {
11577 // TODO(kbr): improve the precision of the error code in this case.
11578 // Consider delegating to context for error code if MakeCurrent fails.
11579 return error::kUnknown
;
11580 case GL_GUILTY_CONTEXT_RESET_ARB
:
11581 return error::kGuilty
;
11582 case GL_INNOCENT_CONTEXT_RESET_ARB
:
11583 return error::kInnocent
;
11584 case GL_UNKNOWN_CONTEXT_RESET_ARB
:
11585 return error::kUnknown
;
11589 return error::kUnknown
;
11592 bool GLES2DecoderImpl::WasContextLost() const {
11593 return context_was_lost_
;
11596 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() const {
11597 return WasContextLost() && reset_by_robustness_extension_
;
11600 void GLES2DecoderImpl::MarkContextLost(error::ContextLostReason reason
) {
11601 // Only lose the context once.
11602 if (WasContextLost())
11605 // Don't make GL calls in here, the context might not be current.
11606 context_lost_reason_
= reason
;
11607 current_decoder_error_
= error::kLostContext
;
11608 context_was_lost_
= true;
11611 bool GLES2DecoderImpl::CheckResetStatus() {
11612 DCHECK(!WasContextLost());
11613 DCHECK(context_
->IsCurrent(NULL
));
11615 if (IsRobustnessSupported()) {
11616 // If the reason for the call was a GL error, we can try to determine the
11617 // reset status more accurately.
11618 GLenum driver_status
= glGetGraphicsResetStatusARB();
11619 if (driver_status
== GL_NO_ERROR
)
11622 LOG(ERROR
) << (surface_
->IsOffscreen() ? "Offscreen" : "Onscreen")
11623 << " context lost via ARB/EXT_robustness. Reset status = "
11624 << GLES2Util::GetStringEnum(driver_status
);
11626 // Don't pretend we know which client was responsible.
11627 if (workarounds().use_virtualized_gl_contexts
)
11628 driver_status
= GL_UNKNOWN_CONTEXT_RESET_ARB
;
11630 switch (driver_status
) {
11631 case GL_GUILTY_CONTEXT_RESET_ARB
:
11632 MarkContextLost(error::kGuilty
);
11634 case GL_INNOCENT_CONTEXT_RESET_ARB
:
11635 MarkContextLost(error::kInnocent
);
11637 case GL_UNKNOWN_CONTEXT_RESET_ARB
:
11638 MarkContextLost(error::kUnknown
);
11644 reset_by_robustness_extension_
= true;
11650 error::Error
GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
11651 uint32 immediate_data_size
,
11652 const void* cmd_data
) {
11653 return error::kUnknownCommand
;
11656 error::Error
GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
11657 uint32 immediate_data_size
,
11658 const void* cmd_data
) {
11659 const gles2::cmds::WaitSyncPointCHROMIUM
& c
=
11660 *static_cast<const gles2::cmds::WaitSyncPointCHROMIUM
*>(cmd_data
);
11661 uint32 sync_point
= c
.sync_point
;
11662 if (wait_sync_point_callback_
.is_null())
11663 return error::kNoError
;
11665 return wait_sync_point_callback_
.Run(sync_point
) ?
11666 error::kNoError
: error::kDeferCommandUntilLater
;
11669 error::Error
GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
11670 uint32 immediate_data_size
,
11671 const void* cmd_data
) {
11672 if (surface_
->DeferDraws())
11673 return error::kDeferCommandUntilLater
;
11674 if (!surface_
->SetBackbufferAllocation(false))
11675 return error::kLostContext
;
11676 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
11677 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
11678 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
11679 return error::kNoError
;
11682 bool GLES2DecoderImpl::GenQueriesEXTHelper(
11683 GLsizei n
, const GLuint
* client_ids
) {
11684 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11685 if (query_manager_
->GetQuery(client_ids
[ii
])) {
11689 query_manager_
->GenQueries(n
, client_ids
);
11693 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
11694 GLsizei n
, const GLuint
* client_ids
) {
11695 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11696 query_manager_
->RemoveQuery(client_ids
[ii
]);
11700 bool GLES2DecoderImpl::ProcessPendingQueries(bool did_finish
) {
11701 if (query_manager_
.get() == NULL
) {
11704 if (!query_manager_
->ProcessPendingQueries(did_finish
)) {
11705 current_decoder_error_
= error::kOutOfBounds
;
11707 return query_manager_
->HavePendingQueries();
11710 // Note that if there are no pending readpixels right now,
11711 // this function will call the callback immediately.
11712 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback
) {
11713 if (features().use_async_readpixels
&& !pending_readpixel_fences_
.empty()) {
11714 pending_readpixel_fences_
.back()->callbacks
.push_back(callback
);
11720 void GLES2DecoderImpl::ProcessPendingReadPixels(bool did_finish
) {
11721 // Note: |did_finish| guarantees that the GPU has passed the fence but
11722 // we cannot assume that GLFence::HasCompleted() will return true yet as
11723 // that's not guaranteed by all GLFence implementations.
11724 while (!pending_readpixel_fences_
.empty() &&
11726 pending_readpixel_fences_
.front()->fence
->HasCompleted())) {
11727 std::vector
<base::Closure
> callbacks
=
11728 pending_readpixel_fences_
.front()->callbacks
;
11729 pending_readpixel_fences_
.pop();
11730 for (size_t i
= 0; i
< callbacks
.size(); i
++) {
11731 callbacks
[i
].Run();
11736 bool GLES2DecoderImpl::HasMoreIdleWork() {
11737 return !pending_readpixel_fences_
.empty() ||
11738 async_pixel_transfer_manager_
->NeedsProcessMorePendingTransfers() ||
11739 gpu_tracer_
->HasTracesToProcess();
11742 void GLES2DecoderImpl::PerformIdleWork() {
11743 gpu_tracer_
->ProcessTraces();
11744 ProcessPendingReadPixels(false);
11745 if (!async_pixel_transfer_manager_
->NeedsProcessMorePendingTransfers())
11747 async_pixel_transfer_manager_
->ProcessMorePendingTransfers();
11748 ProcessFinishedAsyncTransfers();
11751 error::Error
GLES2DecoderImpl::HandleBeginQueryEXT(uint32 immediate_data_size
,
11752 const void* cmd_data
) {
11753 const gles2::cmds::BeginQueryEXT
& c
=
11754 *static_cast<const gles2::cmds::BeginQueryEXT
*>(cmd_data
);
11755 GLenum target
= static_cast<GLenum
>(c
.target
);
11756 GLuint client_id
= static_cast<GLuint
>(c
.id
);
11757 int32 sync_shm_id
= static_cast<int32
>(c
.sync_data_shm_id
);
11758 uint32 sync_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
11761 case GL_COMMANDS_ISSUED_CHROMIUM
:
11762 case GL_LATENCY_QUERY_CHROMIUM
:
11763 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
:
11764 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM
:
11765 case GL_GET_ERROR_QUERY_CHROMIUM
:
11767 case GL_COMMANDS_COMPLETED_CHROMIUM
:
11768 if (!features().chromium_sync_query
) {
11769 LOCAL_SET_GL_ERROR(
11770 GL_INVALID_OPERATION
, "glBeginQueryEXT",
11771 "not enabled for commands completed queries");
11772 return error::kNoError
;
11775 case GL_SAMPLES_PASSED
:
11776 case GL_ANY_SAMPLES_PASSED
:
11777 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE
:
11778 if (!features().occlusion_query_boolean
) {
11779 LOCAL_SET_GL_ERROR(
11780 GL_INVALID_OPERATION
, "glBeginQueryEXT",
11781 "not enabled for occlusion queries");
11782 return error::kNoError
;
11785 case GL_TIME_ELAPSED
:
11786 if (!query_manager_
->GPUTimingAvailable()) {
11787 LOCAL_SET_GL_ERROR(
11788 GL_INVALID_OPERATION
, "glBeginQueryEXT",
11789 "not enabled for timing queries");
11790 return error::kNoError
;
11794 LOCAL_SET_GL_ERROR(
11795 GL_INVALID_ENUM
, "glBeginQueryEXT",
11796 "unknown query target");
11797 return error::kNoError
;
11800 if (query_manager_
->GetActiveQuery(target
)) {
11801 LOCAL_SET_GL_ERROR(
11802 GL_INVALID_OPERATION
, "glBeginQueryEXT", "query already in progress");
11803 return error::kNoError
;
11806 if (client_id
== 0) {
11807 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glBeginQueryEXT", "id is 0");
11808 return error::kNoError
;
11811 QueryManager::Query
* query
= query_manager_
->GetQuery(client_id
);
11813 if (!query_manager_
->IsValidQuery(client_id
)) {
11814 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11816 "id not made by glGenQueriesEXT");
11817 return error::kNoError
;
11819 query
= query_manager_
->CreateQuery(
11820 target
, client_id
, sync_shm_id
, sync_shm_offset
);
11823 if (query
->target() != target
) {
11824 LOCAL_SET_GL_ERROR(
11825 GL_INVALID_OPERATION
, "glBeginQueryEXT", "target does not match");
11826 return error::kNoError
;
11827 } else if (query
->shm_id() != sync_shm_id
||
11828 query
->shm_offset() != sync_shm_offset
) {
11829 DLOG(ERROR
) << "Shared memory used by query not the same as before";
11830 return error::kInvalidArguments
;
11833 if (!query_manager_
->BeginQuery(query
)) {
11834 return error::kOutOfBounds
;
11837 return error::kNoError
;
11840 error::Error
GLES2DecoderImpl::HandleEndQueryEXT(uint32 immediate_data_size
,
11841 const void* cmd_data
) {
11842 const gles2::cmds::EndQueryEXT
& c
=
11843 *static_cast<const gles2::cmds::EndQueryEXT
*>(cmd_data
);
11844 GLenum target
= static_cast<GLenum
>(c
.target
);
11845 uint32 submit_count
= static_cast<GLuint
>(c
.submit_count
);
11847 QueryManager::Query
* query
= query_manager_
->GetActiveQuery(target
);
11849 LOCAL_SET_GL_ERROR(
11850 GL_INVALID_OPERATION
, "glEndQueryEXT", "No active query");
11851 return error::kNoError
;
11854 if (!query_manager_
->EndQuery(query
, submit_count
)) {
11855 return error::kOutOfBounds
;
11858 query_manager_
->ProcessPendingTransferQueries();
11860 return error::kNoError
;
11863 error::Error
GLES2DecoderImpl::HandleQueryCounterEXT(uint32 immediate_data_size
,
11864 const void* cmd_data
) {
11865 const gles2::cmds::QueryCounterEXT
& c
=
11866 *static_cast<const gles2::cmds::QueryCounterEXT
*>(cmd_data
);
11867 GLuint client_id
= static_cast<GLuint
>(c
.id
);
11868 GLenum target
= static_cast<GLenum
>(c
.target
);
11869 int32 sync_shm_id
= static_cast<int32
>(c
.sync_data_shm_id
);
11870 uint32 sync_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
11871 uint32 submit_count
= static_cast<GLuint
>(c
.submit_count
);
11875 if (!query_manager_
->GPUTimingAvailable()) {
11876 LOCAL_SET_GL_ERROR(
11877 GL_INVALID_OPERATION
, "glQueryCounterEXT",
11878 "not enabled for timing queries");
11879 return error::kNoError
;
11883 LOCAL_SET_GL_ERROR(
11884 GL_INVALID_ENUM
, "glQueryCounterEXT",
11885 "unknown query target");
11886 return error::kNoError
;
11889 QueryManager::Query
* query
= query_manager_
->GetQuery(client_id
);
11891 if (!query_manager_
->IsValidQuery(client_id
)) {
11892 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11893 "glQueryCounterEXT",
11894 "id not made by glGenQueriesEXT");
11895 return error::kNoError
;
11897 query
= query_manager_
->CreateQuery(
11898 target
, client_id
, sync_shm_id
, sync_shm_offset
);
11900 if (!query_manager_
->QueryCounter(query
, submit_count
)) {
11901 return error::kOutOfBounds
;
11904 return error::kNoError
;
11907 error::Error
GLES2DecoderImpl::HandleSetDisjointValueSyncCHROMIUM(
11908 uint32 immediate_data_size
, const void* cmd_data
) {
11909 const gles2::cmds::SetDisjointValueSyncCHROMIUM
& c
=
11910 *static_cast<const gles2::cmds::SetDisjointValueSyncCHROMIUM
*>(cmd_data
);
11911 int32 sync_shm_id
= static_cast<int32
>(c
.sync_data_shm_id
);
11912 uint32 sync_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
11914 query_manager_
->SetDisjointSync(sync_shm_id
, sync_shm_offset
);
11915 return error::kNoError
;
11918 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
11919 GLsizei n
, const GLuint
* client_ids
) {
11920 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11921 if (GetVertexAttribManager(client_ids
[ii
])) {
11926 if (!features().native_vertex_array_object
) {
11928 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11929 CreateVertexAttribManager(client_ids
[ii
], 0, true);
11932 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
11934 glGenVertexArraysOES(n
, service_ids
.get());
11935 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11936 CreateVertexAttribManager(client_ids
[ii
], service_ids
[ii
], true);
11943 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
11944 GLsizei n
, const GLuint
* client_ids
) {
11945 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11946 VertexAttribManager
* vao
=
11947 GetVertexAttribManager(client_ids
[ii
]);
11948 if (vao
&& !vao
->IsDeleted()) {
11949 if (state_
.vertex_attrib_manager
.get() == vao
) {
11950 DoBindVertexArrayOES(0);
11952 RemoveVertexAttribManager(client_ids
[ii
]);
11957 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id
) {
11958 VertexAttribManager
* vao
= NULL
;
11959 if (client_id
!= 0) {
11960 vao
= GetVertexAttribManager(client_id
);
11962 // Unlike most Bind* methods, the spec explicitly states that VertexArray
11963 // only allows names that have been previously generated. As such, we do
11964 // not generate new names here.
11965 LOCAL_SET_GL_ERROR(
11966 GL_INVALID_OPERATION
,
11967 "glBindVertexArrayOES", "bad vertex array id.");
11968 current_decoder_error_
= error::kNoError
;
11972 vao
= state_
.default_vertex_attrib_manager
.get();
11975 // Only set the VAO state if it's changed
11976 if (state_
.vertex_attrib_manager
.get() != vao
) {
11977 state_
.vertex_attrib_manager
= vao
;
11978 if (!features().native_vertex_array_object
) {
11979 EmulateVertexArrayState();
11981 GLuint service_id
= vao
->service_id();
11982 glBindVertexArrayOES(service_id
);
11987 // Used when OES_vertex_array_object isn't natively supported
11988 void GLES2DecoderImpl::EmulateVertexArrayState() {
11989 // Setup the Vertex attribute state
11990 for (uint32 vv
= 0; vv
< group_
->max_vertex_attribs(); ++vv
) {
11991 RestoreStateForAttrib(vv
, true);
11994 // Setup the element buffer
11995 Buffer
* element_array_buffer
=
11996 state_
.vertex_attrib_manager
->element_array_buffer();
11997 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
11998 element_array_buffer
? element_array_buffer
->service_id() : 0);
12001 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id
) {
12002 const VertexAttribManager
* vao
=
12003 GetVertexAttribManager(client_id
);
12004 return vao
&& vao
->IsValid() && !vao
->IsDeleted();
12007 bool GLES2DecoderImpl::DoIsPathCHROMIUM(GLuint client_id
) {
12008 GLuint service_id
= 0;
12009 return path_manager()->GetPath(client_id
, &service_id
) &&
12010 glIsPathNV(service_id
) == GL_TRUE
;
12013 #if defined(OS_MACOSX)
12014 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id
) {
12015 TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.find(
12017 if (it
!= texture_to_io_surface_map_
.end()) {
12018 // Found a previous IOSurface bound to this texture; release it.
12019 IOSurfaceRef surface
= it
->second
;
12020 CFRelease(surface
);
12021 texture_to_io_surface_map_
.erase(it
);
12026 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
12027 GLenum target
, GLsizei width
, GLsizei height
,
12028 GLuint io_surface_id
, GLuint plane
) {
12029 #if defined(OS_MACOSX)
12030 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL
) {
12031 LOCAL_SET_GL_ERROR(
12032 GL_INVALID_OPERATION
,
12033 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
12037 if (target
!= GL_TEXTURE_RECTANGLE_ARB
) {
12038 // This might be supported in the future, and if we could require
12039 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
12040 // could delete a lot of code. For now, perform strict validation so we
12041 // know what's going on.
12042 LOCAL_SET_GL_ERROR(
12043 GL_INVALID_OPERATION
,
12044 "glTexImageIOSurface2DCHROMIUM",
12045 "requires TEXTURE_RECTANGLE_ARB target");
12049 // Default target might be conceptually valid, but disallow it to avoid
12051 TextureRef
* texture_ref
=
12052 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
12053 if (!texture_ref
) {
12054 LOCAL_SET_GL_ERROR(
12055 GL_INVALID_OPERATION
,
12056 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
12060 // Look up the new IOSurface. Note that because of asynchrony
12061 // between processes this might fail; during live resizing the
12062 // plugin process might allocate and release an IOSurface before
12063 // this process gets a chance to look it up. Hold on to any old
12064 // IOSurface in this case.
12065 IOSurfaceRef surface
= IOSurfaceLookup(io_surface_id
);
12067 LOCAL_SET_GL_ERROR(
12068 GL_INVALID_OPERATION
,
12069 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
12073 // Release any IOSurface previously bound to this texture.
12074 ReleaseIOSurfaceForTexture(texture_ref
->service_id());
12076 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
12077 texture_to_io_surface_map_
.insert(
12078 std::make_pair(texture_ref
->service_id(), surface
));
12080 CGLContextObj context
=
12081 static_cast<CGLContextObj
>(context_
->GetHandle());
12083 CGLError err
= CGLTexImageIOSurface2D(
12090 GL_UNSIGNED_INT_8_8_8_8_REV
,
12094 if (err
!= kCGLNoError
) {
12095 LOCAL_SET_GL_ERROR(
12096 GL_INVALID_OPERATION
,
12097 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
12101 texture_manager()->SetLevelInfo(
12102 texture_ref
, target
, 0, GL_RGBA
, width
, height
, 1, 0, GL_BGRA
,
12103 GL_UNSIGNED_INT_8_8_8_8_REV
, gfx::Rect(width
, height
));
12106 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12107 "glTexImageIOSurface2DCHROMIUM", "not supported.");
12111 static GLenum
ExtractFormatFromStorageFormat(GLenum internalformat
) {
12112 switch (internalformat
) {
12124 return GL_RED_INTEGER
;
12136 return GL_RG_INTEGER
;
12137 case GL_ATC_RGB_AMD
:
12138 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
12139 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
12140 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
12141 case GL_ETC1_RGB8_OES
:
12143 case GL_R11F_G11F_B10F
:
12145 case GL_RGB8_SNORM
:
12156 return GL_RGB_INTEGER
;
12157 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
12158 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
12159 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
:
12160 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
12161 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
12162 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
12163 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
12165 case GL_SRGB8_ALPHA8
:
12166 case GL_RGBA8_SNORM
:
12175 case GL_RGB10_A2UI
:
12180 return GL_RGBA_INTEGER
;
12181 case GL_DEPTH_COMPONENT16
:
12182 case GL_DEPTH_COMPONENT24
:
12183 case GL_DEPTH_COMPONENT32F
:
12184 return GL_DEPTH_COMPONENT
;
12185 case GL_DEPTH24_STENCIL8
:
12186 case GL_DEPTH32F_STENCIL8
:
12187 return GL_DEPTH_STENCIL
;
12188 case GL_LUMINANCE8_ALPHA8_EXT
:
12189 return GL_LUMINANCE_ALPHA
;
12190 case GL_LUMINANCE8_EXT
:
12191 return GL_LUMINANCE
;
12192 case GL_ALPHA8_EXT
:
12194 case GL_ALPHA32F_EXT
:
12196 case GL_LUMINANCE32F_EXT
:
12197 return GL_LUMINANCE
;
12198 case GL_LUMINANCE_ALPHA32F_EXT
:
12199 return GL_LUMINANCE_ALPHA
;
12200 case GL_ALPHA16F_EXT
:
12202 case GL_LUMINANCE16F_EXT
:
12203 return GL_LUMINANCE
;
12204 case GL_LUMINANCE_ALPHA16F_EXT
:
12205 return GL_LUMINANCE_ALPHA
;
12207 return GL_BGRA_EXT
;
12213 bool GLES2DecoderImpl::ValidateCopyTextureCHROMIUM(
12214 const char* function_name
,
12216 TextureRef
* source_texture_ref
,
12217 TextureRef
* dest_texture_ref
,
12218 GLenum dest_internal_format
) {
12219 if (!source_texture_ref
|| !dest_texture_ref
) {
12220 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown texture id");
12224 if (GL_TEXTURE_2D
!= target
) {
12225 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
12226 "invalid texture target");
12230 Texture
* source_texture
= source_texture_ref
->texture();
12231 Texture
* dest_texture
= dest_texture_ref
->texture();
12232 if (source_texture
== dest_texture
) {
12233 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
12234 "source and destination textures are the same");
12238 if (dest_texture
->target() != GL_TEXTURE_2D
||
12239 (source_texture
->target() != GL_TEXTURE_2D
&&
12240 source_texture
->target() != GL_TEXTURE_RECTANGLE_ARB
&&
12241 source_texture
->target() != GL_TEXTURE_EXTERNAL_OES
)) {
12242 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
12243 "invalid texture target binding");
12247 GLenum source_type
= 0;
12248 GLenum source_internal_format
= 0;
12249 source_texture
->GetLevelType(source_texture
->target(), 0, &source_type
,
12250 &source_internal_format
);
12252 // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
12253 // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
12254 // renderable on some platforms.
12255 bool valid_dest_format
= dest_internal_format
== GL_RGB
||
12256 dest_internal_format
== GL_RGBA
||
12257 dest_internal_format
== GL_BGRA_EXT
;
12258 bool valid_source_format
=
12259 source_internal_format
== GL_R8
|| source_internal_format
== GL_ALPHA
||
12260 source_internal_format
== GL_RGB
|| source_internal_format
== GL_RGBA
||
12261 source_internal_format
== GL_LUMINANCE
||
12262 source_internal_format
== GL_LUMINANCE_ALPHA
||
12263 source_internal_format
== GL_BGRA_EXT
;
12264 if (!valid_source_format
|| !valid_dest_format
) {
12265 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
12266 "invalid internal format");
12272 bool GLES2DecoderImpl::ValidateCompressedCopyTextureCHROMIUM(
12273 const char* function_name
,
12275 TextureRef
* source_texture_ref
,
12276 TextureRef
* dest_texture_ref
) {
12277 if (!source_texture_ref
|| !dest_texture_ref
) {
12278 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown texture id");
12282 if (GL_TEXTURE_2D
!= target
) {
12283 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
12284 "invalid texture target");
12288 Texture
* source_texture
= source_texture_ref
->texture();
12289 Texture
* dest_texture
= dest_texture_ref
->texture();
12290 if (source_texture
== dest_texture
) {
12291 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
12292 "source and destination textures are the same");
12296 if (dest_texture
->target() != GL_TEXTURE_2D
||
12297 (source_texture
->target() != GL_TEXTURE_2D
&&
12298 source_texture
->target() != GL_TEXTURE_RECTANGLE_ARB
&&
12299 source_texture
->target() != GL_TEXTURE_EXTERNAL_OES
)) {
12300 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
12301 "invalid texture target binding");
12305 GLenum source_type
= 0;
12306 GLenum source_internal_format
= 0;
12307 source_texture
->GetLevelType(source_texture
->target(), 0, &source_type
,
12308 &source_internal_format
);
12310 bool valid_format
=
12311 source_internal_format
== GL_ATC_RGB_AMD
||
12312 source_internal_format
== GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
||
12313 source_internal_format
== GL_COMPRESSED_RGB_S3TC_DXT1_EXT
||
12314 source_internal_format
== GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
||
12315 source_internal_format
== GL_ETC1_RGB8_OES
;
12317 if (!valid_format
) {
12318 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
12319 "invalid internal format");
12326 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
12330 GLenum internal_format
,
12332 GLboolean unpack_flip_y
,
12333 GLboolean unpack_premultiply_alpha
,
12334 GLboolean unpack_unmultiply_alpha
) {
12335 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
12337 TextureRef
* source_texture_ref
= GetTexture(source_id
);
12338 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
12339 Texture
* source_texture
= source_texture_ref
->texture();
12340 Texture
* dest_texture
= dest_texture_ref
->texture();
12341 int source_width
= 0;
12342 int source_height
= 0;
12343 gfx::GLImage
* image
=
12344 source_texture
->GetLevelImage(source_texture
->target(), 0);
12346 gfx::Size size
= image
->GetSize();
12347 source_width
= size
.width();
12348 source_height
= size
.height();
12349 if (source_width
<= 0 || source_height
<= 0) {
12350 LOCAL_SET_GL_ERROR(
12352 "glCopyTextureChromium", "invalid image size");
12356 if (!source_texture
->GetLevelSize(source_texture
->target(), 0,
12357 &source_width
, &source_height
, nullptr)) {
12358 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
12359 "glCopyTextureChromium",
12360 "source texture has no level 0");
12364 // Check that this type of texture is allowed.
12365 if (!texture_manager()->ValidForTarget(source_texture
->target(), 0,
12366 source_width
, source_height
, 1)) {
12367 LOCAL_SET_GL_ERROR(
12368 GL_INVALID_VALUE
, "glCopyTextureCHROMIUM", "Bad dimensions");
12373 GLenum source_type
= 0;
12374 GLenum source_internal_format
= 0;
12375 source_texture
->GetLevelType(
12376 source_texture
->target(), 0, &source_type
, &source_internal_format
);
12378 if (dest_texture
->IsImmutable()) {
12379 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCopyTextureCHROMIUM",
12380 "texture is immutable");
12384 if (!ValidateCopyTextureCHROMIUM("glCopyTextureCHROMIUM", target
,
12385 source_texture_ref
, dest_texture_ref
,
12386 internal_format
)) {
12390 // Clear the source texture if necessary.
12391 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref
,
12392 source_texture
->target(), 0)) {
12393 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTextureCHROMIUM",
12394 "dimensions too big");
12398 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12399 // needed because it takes 10s of milliseconds to initialize.
12400 if (!copy_texture_CHROMIUM_
.get()) {
12401 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12402 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
12403 copy_texture_CHROMIUM_
->Initialize(this);
12404 RestoreCurrentFramebufferBindings();
12405 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR
)
12409 GLenum dest_type_previous
= dest_type
;
12410 GLenum dest_internal_format
= internal_format
;
12411 int dest_width
= 0;
12412 int dest_height
= 0;
12413 bool dest_level_defined
= dest_texture
->GetLevelSize(
12414 GL_TEXTURE_2D
, 0, &dest_width
, &dest_height
, nullptr);
12416 if (dest_level_defined
) {
12417 dest_texture
->GetLevelType(GL_TEXTURE_2D
, 0, &dest_type_previous
,
12418 &dest_internal_format
);
12421 // Resize the destination texture to the dimensions of the source texture.
12422 if (!dest_level_defined
|| dest_width
!= source_width
||
12423 dest_height
!= source_height
||
12424 dest_internal_format
!= internal_format
||
12425 dest_type_previous
!= dest_type
) {
12426 // Ensure that the glTexImage2D succeeds.
12427 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12428 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
12429 glTexImage2D(GL_TEXTURE_2D
, 0, internal_format
, source_width
, source_height
,
12430 0, internal_format
, dest_type
, NULL
);
12431 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
12432 if (error
!= GL_NO_ERROR
) {
12433 RestoreCurrentTextureBindings(&state_
, GL_TEXTURE_2D
);
12437 texture_manager()->SetLevelInfo(
12438 dest_texture_ref
, GL_TEXTURE_2D
, 0, internal_format
, source_width
,
12439 source_height
, 1, 0, internal_format
, dest_type
,
12440 gfx::Rect(source_width
, source_height
));
12442 texture_manager()->SetLevelCleared(dest_texture_ref
, GL_TEXTURE_2D
, 0,
12446 ScopedModifyPixels
modify(dest_texture_ref
);
12448 // Try using GLImage::CopyTexSubImage when possible.
12449 bool unpack_premultiply_alpha_change
=
12450 (unpack_premultiply_alpha
^ unpack_unmultiply_alpha
) != 0;
12451 if (image
&& !unpack_flip_y
&& !unpack_premultiply_alpha_change
) {
12452 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
12453 if (image
->CopyTexSubImage(GL_TEXTURE_2D
, gfx::Point(0, 0),
12454 gfx::Rect(0, 0, source_width
, source_height
))) {
12459 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
12461 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
12462 // before presenting.
12463 if (source_texture
->target() == GL_TEXTURE_EXTERNAL_OES
) {
12464 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
12465 // instead of using kIdentityMatrix crbug.com/226218.
12466 copy_texture_CHROMIUM_
->DoCopyTextureWithTransform(
12467 this, source_texture
->target(), source_texture
->service_id(),
12468 dest_texture
->service_id(), source_width
, source_height
,
12469 unpack_flip_y
== GL_TRUE
,
12470 unpack_premultiply_alpha
== GL_TRUE
,
12471 unpack_unmultiply_alpha
== GL_TRUE
,
12474 copy_texture_CHROMIUM_
->DoCopyTexture(
12475 this, source_texture
->target(), source_texture
->service_id(),
12476 source_internal_format
, dest_texture
->service_id(), internal_format
,
12477 source_width
, source_height
,
12478 unpack_flip_y
== GL_TRUE
,
12479 unpack_premultiply_alpha
== GL_TRUE
,
12480 unpack_unmultiply_alpha
== GL_TRUE
);
12483 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
12486 void GLES2DecoderImpl::DoCopySubTextureCHROMIUM(
12496 GLboolean unpack_flip_y
,
12497 GLboolean unpack_premultiply_alpha
,
12498 GLboolean unpack_unmultiply_alpha
) {
12499 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopySubTextureCHROMIUM");
12501 TextureRef
* source_texture_ref
= GetTexture(source_id
);
12502 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
12503 Texture
* source_texture
= source_texture_ref
->texture();
12504 Texture
* dest_texture
= dest_texture_ref
->texture();
12505 int source_width
= 0;
12506 int source_height
= 0;
12507 gfx::GLImage
* image
=
12508 source_texture
->GetLevelImage(source_texture
->target(), 0);
12510 gfx::Size size
= image
->GetSize();
12511 source_width
= size
.width();
12512 source_height
= size
.height();
12513 if (source_width
<= 0 || source_height
<= 0) {
12514 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
12515 "invalid image size");
12519 if (!source_texture
->GetLevelSize(source_texture
->target(), 0,
12520 &source_width
, &source_height
, nullptr)) {
12521 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
12522 "source texture has no level 0");
12526 // Check that this type of texture is allowed.
12527 if (!texture_manager()->ValidForTarget(source_texture
->target(), 0,
12528 source_width
, source_height
, 1)) {
12529 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
12530 "source texture bad dimensions");
12535 GLenum source_type
= 0;
12536 GLenum source_internal_format
= 0;
12537 source_texture
->GetLevelType(source_texture
->target(), 0, &source_type
,
12538 &source_internal_format
);
12539 if (!source_texture
->ValidForTexture(source_texture
->target(), 0, x
, y
, 0,
12540 width
, height
, 1, source_type
)) {
12541 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
12542 "source texture bad dimensions.");
12546 GLenum dest_type
= 0;
12547 GLenum dest_internal_format
= 0;
12548 bool dest_level_defined
= dest_texture
->GetLevelType(
12549 dest_texture
->target(), 0, &dest_type
, &dest_internal_format
);
12550 if (!dest_level_defined
) {
12551 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCopySubTextureCHROMIUM",
12552 "destination texture is not defined");
12555 if (!dest_texture
->ValidForTexture(dest_texture
->target(), 0, xoffset
,
12556 yoffset
, 0, width
, height
, 1, dest_type
)) {
12557 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
12558 "destination texture bad dimensions.");
12562 if (!ValidateCopyTextureCHROMIUM("glCopySubTextureCHROMIUM", target
,
12563 source_texture_ref
, dest_texture_ref
,
12564 dest_internal_format
)) {
12568 // Clear the source texture if necessary.
12569 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref
,
12570 source_texture
->target(), 0)) {
12571 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopySubTextureCHROMIUM",
12572 "source texture dimensions too big");
12576 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12577 // needed because it takes 10s of milliseconds to initialize.
12578 if (!copy_texture_CHROMIUM_
.get()) {
12579 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopySubTextureCHROMIUM");
12580 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
12581 copy_texture_CHROMIUM_
->Initialize(this);
12582 RestoreCurrentFramebufferBindings();
12583 if (LOCAL_PEEK_GL_ERROR("glCopySubTextureCHROMIUM") != GL_NO_ERROR
)
12587 int dest_width
= 0;
12588 int dest_height
= 0;
12589 bool ok
= dest_texture
->GetLevelSize(
12590 GL_TEXTURE_2D
, 0, &dest_width
, &dest_height
, nullptr);
12592 if (xoffset
!= 0 || yoffset
!= 0 || width
!= dest_width
||
12593 height
!= dest_height
) {
12594 gfx::Rect cleared_rect
;
12595 if (CombineAdjacentRects(dest_texture
->GetLevelClearedRect(target
, 0),
12596 gfx::Rect(xoffset
, yoffset
, width
, height
),
12598 DCHECK_GE(cleared_rect
.size().GetArea(),
12599 dest_texture
->GetLevelClearedRect(target
, 0).size().GetArea());
12600 texture_manager()->SetLevelClearedRect(dest_texture_ref
, target
, 0,
12603 // Otherwise clear part of texture level that is not already cleared.
12604 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref
, target
,
12606 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopySubTextureCHROMIUM",
12607 "destination texture dimensions too big");
12612 texture_manager()->SetLevelCleared(dest_texture_ref
, GL_TEXTURE_2D
, 0,
12616 ScopedModifyPixels
modify(dest_texture_ref
);
12618 // Try using GLImage::CopyTexSubImage when possible.
12619 bool unpack_premultiply_alpha_change
=
12620 (unpack_premultiply_alpha
^ unpack_unmultiply_alpha
) != 0;
12621 if (image
&& !unpack_flip_y
&& !unpack_premultiply_alpha_change
) {
12622 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
12623 if (image
->CopyTexSubImage(GL_TEXTURE_2D
, gfx::Point(xoffset
, yoffset
),
12624 gfx::Rect(x
, y
, width
, height
))) {
12629 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
12631 // TODO(hkuang): get the StreamTexture transform matrix in GPU process.
12632 // crbug.com/226218.
12633 copy_texture_CHROMIUM_
->DoCopySubTexture(
12634 this, source_texture
->target(), source_texture
->service_id(),
12635 source_internal_format
, dest_texture
->service_id(), dest_internal_format
,
12636 xoffset
, yoffset
, x
, y
, width
, height
, dest_width
, dest_height
,
12637 source_width
, source_height
,
12638 unpack_flip_y
== GL_TRUE
,
12639 unpack_premultiply_alpha
== GL_TRUE
,
12640 unpack_unmultiply_alpha
== GL_TRUE
);
12642 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
12645 void GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM(GLenum target
,
12648 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM");
12650 TextureRef
* source_texture_ref
= GetTexture(source_id
);
12651 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
12652 Texture
* source_texture
= source_texture_ref
->texture();
12653 Texture
* dest_texture
= dest_texture_ref
->texture();
12654 int source_width
= 0;
12655 int source_height
= 0;
12656 gfx::GLImage
* image
=
12657 source_texture
->GetLevelImage(source_texture
->target(), 0);
12659 gfx::Size size
= image
->GetSize();
12660 source_width
= size
.width();
12661 source_height
= size
.height();
12662 if (source_width
<= 0 || source_height
<= 0) {
12663 LOCAL_SET_GL_ERROR(
12665 "glCompressedCopyTextureCHROMIUM", "invalid image size");
12669 if (!source_texture
->GetLevelSize(source_texture
->target(), 0,
12670 &source_width
, &source_height
, nullptr)) {
12671 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
12672 "glCompressedCopyTextureCHROMIUM",
12673 "source texture has no level 0");
12677 // Check that this type of texture is allowed.
12678 if (!texture_manager()->ValidForTarget(source_texture
->target(), 0,
12679 source_width
, source_height
, 1)) {
12680 LOCAL_SET_GL_ERROR(
12681 GL_INVALID_VALUE
, "glCompressedCopyTextureCHROMIUM",
12687 GLenum source_type
= 0;
12688 GLenum source_internal_format
= 0;
12689 source_texture
->GetLevelType(
12690 source_texture
->target(), 0, &source_type
, &source_internal_format
);
12692 if (dest_texture
->IsImmutable()) {
12693 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12694 "glCompressedCopyTextureCHROMIUM",
12695 "texture is immutable");
12699 if (!ValidateCompressedCopyTextureCHROMIUM(
12700 "glCompressedCopyTextureCHROMIUM",
12702 source_texture_ref
, dest_texture_ref
)) {
12706 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12707 // needed because it takes 10s of milliseconds to initialize.
12708 if (!copy_texture_CHROMIUM_
.get()) {
12709 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12710 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
12711 copy_texture_CHROMIUM_
->Initialize(this);
12712 RestoreCurrentFramebufferBindings();
12713 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR
)
12717 // Clear the source texture if necessary.
12718 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref
,
12719 source_texture
->target(), 0)) {
12720 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCompressedCopyTextureCHROMIUM",
12721 "dimensions too big");
12725 ScopedTextureBinder
binder(
12726 &state_
, dest_texture
->service_id(), GL_TEXTURE_2D
);
12728 ScopedModifyPixels
modify(dest_texture_ref
);
12730 // Try using GLImage::CopyTexImage when possible.
12732 GLenum dest_type
= 0;
12733 GLenum dest_internal_format
= 0;
12734 int dest_width
= 0;
12735 int dest_height
= 0;
12736 bool dest_level_defined
= dest_texture
->GetLevelSize(
12737 GL_TEXTURE_2D
, 0, &dest_width
, &dest_height
, nullptr);
12739 if (dest_level_defined
) {
12740 dest_texture
->GetLevelType(GL_TEXTURE_2D
, 0, &dest_type
,
12741 &dest_internal_format
);
12744 // Resize the destination texture to the dimensions of the source texture.
12745 if (!dest_level_defined
|| dest_width
!= source_width
||
12746 dest_height
!= source_height
||
12747 dest_internal_format
!= source_internal_format
) {
12748 GLsizei source_size
= 0;
12750 bool did_get_size
= GetCompressedTexSizeInBytes(
12751 "glCompressedCopyTextureCHROMIUM", source_width
, source_height
,
12752 1, source_internal_format
, &source_size
);
12753 DCHECK(did_get_size
);
12755 // Ensure that the glCompressedTexImage2D succeeds.
12756 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
12757 glCompressedTexImage2D(GL_TEXTURE_2D
, 0, source_internal_format
,
12758 source_width
, source_height
, 0, source_size
,
12760 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedCopyTextureCHROMIUM");
12761 if (error
!= GL_NO_ERROR
) {
12762 RestoreCurrentTextureBindings(&state_
, GL_TEXTURE_2D
);
12766 texture_manager()->SetLevelInfo(
12767 dest_texture_ref
, GL_TEXTURE_2D
, 0, source_internal_format
,
12768 source_width
, source_height
, 1, 0, source_internal_format
,
12769 source_type
, gfx::Rect(source_width
, source_height
));
12771 texture_manager()->SetLevelCleared(dest_texture_ref
, GL_TEXTURE_2D
, 0,
12775 if (image
->CopyTexSubImage(GL_TEXTURE_2D
, gfx::Point(0, 0),
12776 gfx::Rect(0, 0, source_width
, source_height
))) {
12783 "GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM, fallback");
12785 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
12787 // As a fallback, copy into a non-compressed GL_RGBA texture.
12788 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
12789 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, source_width
, source_height
,
12790 0, GL_RGBA
, GL_UNSIGNED_BYTE
, NULL
);
12791 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedCopyTextureCHROMIUM");
12792 if (error
!= GL_NO_ERROR
) {
12793 RestoreCurrentTextureBindings(&state_
, GL_TEXTURE_2D
);
12797 texture_manager()->SetLevelInfo(
12798 dest_texture_ref
, GL_TEXTURE_2D
, 0, GL_RGBA
, source_width
,
12799 source_height
, 1, 0, GL_RGBA
, GL_UNSIGNED_BYTE
,
12800 gfx::Rect(source_width
, source_height
));
12802 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
12803 // before presenting.
12804 if (source_texture
->target() == GL_TEXTURE_EXTERNAL_OES
) {
12805 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
12806 // instead of using kIdentityMatrix crbug.com/226218.
12807 copy_texture_CHROMIUM_
->DoCopyTextureWithTransform(
12808 this, source_texture
->target(), source_texture
->service_id(),
12809 dest_texture
->service_id(), source_width
, source_height
,
12810 false, false, false, kIdentityMatrix
);
12812 copy_texture_CHROMIUM_
->DoCopyTexture(
12813 this, source_texture
->target(), source_texture
->service_id(),
12814 source_internal_format
, dest_texture
->service_id(), GL_RGBA
,
12815 source_width
, source_height
, false, false, false);
12818 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
12821 void GLES2DecoderImpl::DoCompressedCopySubTextureCHROMIUM(GLenum target
,
12830 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompressedCopySubTextureCHROMIUM");
12832 TextureRef
* source_texture_ref
= GetTexture(source_id
);
12833 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
12834 Texture
* source_texture
= source_texture_ref
->texture();
12835 Texture
* dest_texture
= dest_texture_ref
->texture();
12836 int source_width
= 0;
12837 int source_height
= 0;
12838 gfx::GLImage
* image
=
12839 source_texture
->GetLevelImage(source_texture
->target(), 0);
12841 gfx::Size size
= image
->GetSize();
12842 source_width
= size
.width();
12843 source_height
= size
.height();
12844 if (source_width
<= 0 || source_height
<= 0) {
12845 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCompressedCopySubTextureCHROMIUM",
12846 "invalid image size");
12850 if (!source_texture
->GetLevelSize(source_texture
->target(), 0,
12851 &source_width
, &source_height
, nullptr)) {
12852 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCompressedCopySubTextureCHROMIUM",
12853 "source texture has no level 0");
12857 // Check that this type of texture is allowed.
12858 if (!texture_manager()->ValidForTarget(source_texture
->target(), 0,
12859 source_width
, source_height
, 1)) {
12860 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCompressedCopySubTextureCHROMIUM",
12861 "source texture bad dimensions");
12866 GLenum source_type
= 0;
12867 GLenum source_internal_format
= 0;
12868 source_texture
->GetLevelType(source_texture
->target(), 0, &source_type
,
12869 &source_internal_format
);
12870 if (!source_texture
->ValidForTexture(source_texture
->target(), 0, x
, y
, 0,
12871 width
, height
, 1, source_type
)) {
12872 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCompressedCopySubTextureCHROMIUM",
12873 "source texture bad dimensions.");
12877 GLenum dest_type
= 0;
12878 GLenum dest_internal_format
= 0;
12879 bool dest_level_defined
= dest_texture
->GetLevelType(
12880 dest_texture
->target(), 0, &dest_type
, &dest_internal_format
);
12881 if (!dest_level_defined
) {
12882 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12883 "glCompressedCopySubTextureCHROMIUM",
12884 "destination texture is not defined");
12887 if (!dest_texture
->ValidForTexture(dest_texture
->target(), 0, xoffset
,
12888 yoffset
, 0, width
, height
, 1, dest_type
)) {
12889 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCompressedCopySubTextureCHROMIUM",
12890 "destination texture bad dimensions.");
12894 if (!ValidateCompressedCopyTextureCHROMIUM(
12895 "glCompressedCopySubTextureCHROMIUM", target
, source_texture_ref
,
12896 dest_texture_ref
)) {
12900 if (!ValidateCompressedTexSubDimensions("glCompressedCopySubTextureCHROMIUM",
12901 source_texture
->target(), 0, x
, y
, 0,
12903 source_internal_format
,
12905 !ValidateCompressedTexSubDimensions("glCompressedCopySubTextureCHROMIUM",
12906 dest_texture
->target(), 0,
12907 xoffset
, yoffset
, 0, width
, height
, 1,
12908 dest_internal_format
,
12913 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12914 // needed because it takes 10s of milliseconds to initialize.
12915 if (!copy_texture_CHROMIUM_
.get()) {
12916 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopySubTextureCHROMIUM");
12917 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
12918 copy_texture_CHROMIUM_
->Initialize(this);
12919 RestoreCurrentFramebufferBindings();
12920 if (LOCAL_PEEK_GL_ERROR("glCompressedCopySubTextureCHROMIUM") !=
12926 // Clear the source texture if necessary.
12927 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref
,
12928 source_texture
->target(), 0)) {
12929 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCompressedCopySubTextureCHROMIUM",
12930 "source texture dimensions too big");
12934 int dest_width
= 0;
12935 int dest_height
= 0;
12936 bool ok
= dest_texture
->GetLevelSize(
12937 GL_TEXTURE_2D
, 0, &dest_width
, &dest_height
, nullptr);
12939 if (xoffset
!= 0 || yoffset
!= 0 || width
!= dest_width
||
12940 height
!= dest_height
) {
12941 gfx::Rect cleared_rect
;
12942 if (CombineAdjacentRects(dest_texture
->GetLevelClearedRect(target
, 0),
12943 gfx::Rect(xoffset
, yoffset
, width
, height
),
12945 DCHECK_GE(cleared_rect
.size().GetArea(),
12946 dest_texture
->GetLevelClearedRect(target
, 0).size().GetArea());
12947 texture_manager()->SetLevelClearedRect(dest_texture_ref
, target
, 0,
12950 // Otherwise clear part of texture level that is not already cleared.
12951 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref
, target
,
12953 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
,
12954 "glCompressedCopySubTextureCHROMIUM",
12955 "destination texture dimensions too big");
12960 texture_manager()->SetLevelCleared(dest_texture_ref
, GL_TEXTURE_2D
, 0,
12964 ScopedTextureBinder
binder(
12965 &state_
, dest_texture
->service_id(), GL_TEXTURE_2D
);
12967 ScopedModifyPixels
modify(dest_texture_ref
);
12969 // Try using GLImage::CopyTexSubImage when possible.
12971 if (image
->CopyTexSubImage(GL_TEXTURE_2D
, gfx::Point(xoffset
, yoffset
),
12972 gfx::Rect(x
, y
, width
, height
))) {
12979 "GLES2DecoderImpl::DoCompressedCopySubTextureCHROMIUM, fallback");
12981 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
12983 // As a fallback, copy into a non-compressed GL_RGBA texture.
12984 if (dest_internal_format
!= GL_RGBA
) {
12985 // To preserve the contents of the original destination texture we must
12986 // first copy the original destination texture to a temporary storage, then
12987 // copy it back to the original destination texture.
12988 GLuint tmp_service_id
;
12989 glGenTextures(1, &tmp_service_id
);
12990 DCHECK_NE(0u, tmp_service_id
);
12992 glBindTexture(GL_TEXTURE_2D
, tmp_service_id
);
12994 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
12995 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, dest_width
, dest_height
, 0, GL_RGBA
,
12996 GL_UNSIGNED_BYTE
, NULL
);
12997 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedCopySubTextureCHROMIUM");
12998 if (error
!= GL_NO_ERROR
)
13001 copy_texture_CHROMIUM_
->DoCopyTexture(
13002 this, dest_texture
->target(), dest_texture
->service_id(),
13003 dest_internal_format
, tmp_service_id
, GL_RGBA
,
13004 dest_width
, dest_height
, false, false, false);
13006 // Redefine destination texture to use RGBA.
13007 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
13008 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
13009 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, dest_width
, dest_height
, 0, GL_RGBA
,
13010 GL_UNSIGNED_BYTE
, NULL
);
13011 error
= LOCAL_PEEK_GL_ERROR("glCompressedCopySubTextureCHROMIUM");
13012 if (error
!= GL_NO_ERROR
)
13015 texture_manager()->SetLevelInfo(
13016 dest_texture_ref
, GL_TEXTURE_2D
, 0, GL_RGBA
, dest_width
, dest_height
,
13017 1, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, gfx::Rect(dest_width
, dest_height
));
13019 copy_texture_CHROMIUM_
->DoCopyTexture(
13020 this, GL_TEXTURE_2D
, tmp_service_id
, GL_RGBA
,
13021 dest_texture
->service_id(), GL_RGBA
,
13022 dest_width
, dest_height
, false, false, false);
13024 glDeleteTextures(1, &tmp_service_id
);
13027 // TODO(hkuang): get the StreamTexture transform matrix in GPU process.
13028 // crbug.com/226218.
13029 copy_texture_CHROMIUM_
->DoCopySubTexture(
13030 this, source_texture
->target(), source_texture
->service_id(),
13031 source_internal_format
, dest_texture
->service_id(), GL_RGBA
,
13032 xoffset
, yoffset
, x
, y
, width
, height
, dest_width
, dest_height
,
13033 source_width
, source_height
, false, false, false);
13035 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
13038 static GLenum
ExtractTypeFromStorageFormat(GLenum internalformat
) {
13039 switch (internalformat
) {
13041 return GL_UNSIGNED_BYTE
;
13045 return GL_HALF_FLOAT
;
13049 return GL_UNSIGNED_BYTE
;
13053 return GL_UNSIGNED_SHORT
;
13057 return GL_UNSIGNED_INT
;
13061 return GL_UNSIGNED_BYTE
;
13065 return GL_HALF_FLOAT
;
13069 return GL_UNSIGNED_BYTE
;
13073 return GL_UNSIGNED_SHORT
;
13077 return GL_UNSIGNED_INT
;
13082 return GL_UNSIGNED_BYTE
;
13083 case GL_R11F_G11F_B10F
:
13084 return GL_UNSIGNED_INT_10F_11F_11F_REV
;
13086 return GL_UNSIGNED_SHORT_5_6_5
;
13087 case GL_RGB8_SNORM
:
13090 return GL_UNSIGNED_INT_5_9_9_9_REV
;
13092 return GL_HALF_FLOAT
;
13096 return GL_UNSIGNED_BYTE
;
13100 return GL_UNSIGNED_SHORT
;
13104 return GL_UNSIGNED_INT
;
13108 return GL_UNSIGNED_BYTE
;
13109 case GL_SRGB8_ALPHA8
:
13110 return GL_UNSIGNED_BYTE
;
13111 case GL_RGBA8_SNORM
:
13114 return GL_UNSIGNED_SHORT_4_4_4_4
;
13116 return GL_UNSIGNED_INT_2_10_10_10_REV
;
13118 return GL_UNSIGNED_SHORT_5_5_5_1
;
13120 return GL_HALF_FLOAT
;
13124 return GL_UNSIGNED_BYTE
;
13127 case GL_RGB10_A2UI
:
13128 return GL_UNSIGNED_INT_2_10_10_10_REV
;
13130 return GL_UNSIGNED_SHORT
;
13136 return GL_UNSIGNED_INT
;
13137 case GL_DEPTH_COMPONENT16
:
13138 return GL_UNSIGNED_SHORT
;
13139 case GL_DEPTH_COMPONENT24
:
13140 return GL_UNSIGNED_INT
;
13141 case GL_DEPTH_COMPONENT32F
:
13143 case GL_DEPTH24_STENCIL8
:
13144 return GL_UNSIGNED_INT_24_8
;
13145 case GL_DEPTH32F_STENCIL8
:
13146 return GL_FLOAT_32_UNSIGNED_INT_24_8_REV
;
13147 case GL_LUMINANCE8_ALPHA8_EXT
:
13148 return GL_UNSIGNED_BYTE
;
13149 case GL_LUMINANCE8_EXT
:
13150 return GL_UNSIGNED_BYTE
;
13151 case GL_ALPHA8_EXT
:
13152 return GL_UNSIGNED_BYTE
;
13153 case GL_ALPHA32F_EXT
:
13155 case GL_LUMINANCE32F_EXT
:
13157 case GL_LUMINANCE_ALPHA32F_EXT
:
13159 case GL_ALPHA16F_EXT
:
13160 return GL_HALF_FLOAT_OES
;
13161 case GL_LUMINANCE16F_EXT
:
13162 return GL_HALF_FLOAT_OES
;
13163 case GL_LUMINANCE_ALPHA16F_EXT
:
13164 return GL_HALF_FLOAT_OES
;
13166 return GL_UNSIGNED_BYTE
;
13172 void GLES2DecoderImpl::DoTexStorage2DEXT(
13175 GLenum internal_format
,
13178 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
13179 "width", width
, "height", height
);
13180 if (!texture_manager()->ValidForTarget(target
, 0, width
, height
, 1) ||
13181 TextureManager::ComputeMipMapCount(target
, width
, height
, 1) < levels
) {
13182 LOCAL_SET_GL_ERROR(
13183 GL_INVALID_VALUE
, "glTexStorage2DEXT", "dimensions out of range");
13186 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
13188 if (!texture_ref
) {
13189 LOCAL_SET_GL_ERROR(
13190 GL_INVALID_OPERATION
,
13191 "glTexStorage2DEXT", "unknown texture for target");
13194 Texture
* texture
= texture_ref
->texture();
13195 if (texture
->IsAttachedToFramebuffer()) {
13196 framebuffer_state_
.clear_state_dirty
= true;
13198 if (texture
->IsImmutable()) {
13199 LOCAL_SET_GL_ERROR(
13200 GL_INVALID_OPERATION
,
13201 "glTexStorage2DEXT", "texture is immutable");
13205 GLenum format
= ExtractFormatFromStorageFormat(internal_format
);
13206 GLenum type
= ExtractTypeFromStorageFormat(internal_format
);
13209 GLsizei level_width
= width
;
13210 GLsizei level_height
= height
;
13211 uint32 estimated_size
= 0;
13212 for (int ii
= 0; ii
< levels
; ++ii
) {
13213 uint32 level_size
= 0;
13214 if (!GLES2Util::ComputeImageDataSizes(
13215 level_width
, level_height
, 1, format
, type
, state_
.unpack_alignment
,
13216 &estimated_size
, NULL
, NULL
) ||
13217 !SafeAddUint32(estimated_size
, level_size
, &estimated_size
)) {
13218 LOCAL_SET_GL_ERROR(
13219 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "dimensions too large");
13222 level_width
= std::max(1, level_width
>> 1);
13223 level_height
= std::max(1, level_height
>> 1);
13225 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
13226 LOCAL_SET_GL_ERROR(
13227 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "out of memory");
13232 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
13233 glTexStorage2DEXT(target
, levels
, internal_format
, width
, height
);
13234 GLenum error
= LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
13235 if (error
== GL_NO_ERROR
) {
13236 GLsizei level_width
= width
;
13237 GLsizei level_height
= height
;
13239 GLenum cur_format
= feature_info_
->IsES3Enabled() ?
13240 internal_format
: format
;
13241 for (int ii
= 0; ii
< levels
; ++ii
) {
13242 if (target
== GL_TEXTURE_CUBE_MAP
) {
13243 for (int jj
= 0; jj
< 6; ++jj
) {
13244 GLenum face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ jj
;
13245 texture_manager()->SetLevelInfo(texture_ref
, face
, ii
, cur_format
,
13246 level_width
, level_height
, 1, 0,
13247 format
, type
, gfx::Rect());
13250 texture_manager()->SetLevelInfo(texture_ref
, target
, ii
, cur_format
,
13251 level_width
, level_height
, 1, 0,
13252 format
, type
, gfx::Rect());
13254 level_width
= std::max(1, level_width
>> 1);
13255 level_height
= std::max(1, level_height
>> 1);
13257 texture
->SetImmutable(true);
13261 error::Error
GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
13262 uint32 immediate_data_size
,
13263 const void* cmd_data
) {
13264 return error::kUnknownCommand
;
13267 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target
,
13268 const GLbyte
* data
) {
13269 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
13270 "context", logger_
.GetLogPrefix(),
13271 "mailbox[0]", static_cast<unsigned char>(data
[0]));
13273 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
13275 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref
, target
, data
);
13278 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id
,
13279 GLenum target
, const GLbyte
* data
) {
13280 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
13281 "context", logger_
.GetLogPrefix(),
13282 "mailbox[0]", static_cast<unsigned char>(data
[0]));
13284 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id
),
13288 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name
,
13289 TextureRef
* texture_ref
, GLenum target
, const GLbyte
* data
) {
13290 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
13291 DLOG_IF(ERROR
, !mailbox
.Verify()) << func_name
<< " was passed a "
13292 "mailbox that was not generated by "
13293 "GenMailboxCHROMIUM.";
13295 if (!texture_ref
) {
13296 LOCAL_SET_GL_ERROR(
13297 GL_INVALID_OPERATION
, func_name
.c_str(), "unknown texture for target");
13301 Texture
* produced
= texture_manager()->Produce(texture_ref
);
13303 LOCAL_SET_GL_ERROR(
13304 GL_INVALID_OPERATION
, func_name
.c_str(), "invalid texture");
13308 if (produced
->target() != target
) {
13309 LOCAL_SET_GL_ERROR(
13310 GL_INVALID_OPERATION
, func_name
.c_str(), "invalid target");
13314 group_
->mailbox_manager()->ProduceTexture(mailbox
, produced
);
13317 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target
,
13318 const GLbyte
* data
) {
13319 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
13320 "context", logger_
.GetLogPrefix(),
13321 "mailbox[0]", static_cast<unsigned char>(data
[0]));
13322 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
13323 DLOG_IF(ERROR
, !mailbox
.Verify()) << "ConsumeTextureCHROMIUM was passed a "
13324 "mailbox that was not generated by "
13325 "GenMailboxCHROMIUM.";
13327 scoped_refptr
<TextureRef
> texture_ref
=
13328 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
13329 if (!texture_ref
.get()) {
13330 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
13331 "glConsumeTextureCHROMIUM",
13332 "unknown texture for target");
13335 GLuint client_id
= texture_ref
->client_id();
13337 LOCAL_SET_GL_ERROR(
13338 GL_INVALID_OPERATION
,
13339 "glConsumeTextureCHROMIUM", "unknown texture for target");
13342 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(mailbox
);
13344 LOCAL_SET_GL_ERROR(
13345 GL_INVALID_OPERATION
,
13346 "glConsumeTextureCHROMIUM", "invalid mailbox name");
13349 if (texture
->target() != target
) {
13350 LOCAL_SET_GL_ERROR(
13351 GL_INVALID_OPERATION
,
13352 "glConsumeTextureCHROMIUM", "invalid target");
13356 DeleteTexturesHelper(1, &client_id
);
13357 texture_ref
= texture_manager()->Consume(client_id
, texture
);
13358 glBindTexture(target
, texture_ref
->service_id());
13360 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
13361 unit
.bind_target
= target
;
13363 case GL_TEXTURE_2D
:
13364 unit
.bound_texture_2d
= texture_ref
;
13366 case GL_TEXTURE_CUBE_MAP
:
13367 unit
.bound_texture_cube_map
= texture_ref
;
13369 case GL_TEXTURE_EXTERNAL_OES
:
13370 unit
.bound_texture_external_oes
= texture_ref
;
13372 case GL_TEXTURE_RECTANGLE_ARB
:
13373 unit
.bound_texture_rectangle_arb
= texture_ref
;
13376 NOTREACHED(); // Validation should prevent us getting here.
13381 void GLES2DecoderImpl::EnsureTextureForClientId(
13383 GLuint client_id
) {
13384 TextureRef
* texture_ref
= GetTexture(client_id
);
13385 if (!texture_ref
) {
13387 glGenTextures(1, &service_id
);
13388 DCHECK_NE(0u, service_id
);
13389 texture_ref
= CreateTexture(client_id
, service_id
);
13390 texture_manager()->SetTarget(texture_ref
, target
);
13391 glBindTexture(target
, service_id
);
13392 RestoreCurrentTextureBindings(&state_
, target
);
13396 // If CreateAndConsumeTexture fails we still need to ensure that the client_id
13397 // provided is associated with a service_id/TextureRef for consistency, even if
13398 // the resulting texture is incomplete.
13399 error::Error
GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
13400 uint32_t immediate_data_size
,
13401 const void* cmd_data
) {
13402 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate
& c
=
13404 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate
*>(
13406 GLenum target
= static_cast<GLenum
>(c
.target
);
13407 uint32_t data_size
;
13408 if (!ComputeDataSize(1, sizeof(GLbyte
), 64, &data_size
)) {
13409 return error::kOutOfBounds
;
13411 if (data_size
> immediate_data_size
) {
13412 return error::kOutOfBounds
;
13414 const GLbyte
* mailbox
=
13415 GetImmediateDataAs
<const GLbyte
*>(c
, data_size
, immediate_data_size
);
13416 if (!validators_
->texture_bind_target
.IsValid(target
)) {
13417 LOCAL_SET_GL_ERROR_INVALID_ENUM(
13418 "glCreateAndConsumeTextureCHROMIUM", target
, "target");
13419 return error::kNoError
;
13421 if (mailbox
== NULL
) {
13422 return error::kOutOfBounds
;
13424 uint32_t client_id
= c
.client_id
;
13425 DoCreateAndConsumeTextureCHROMIUM(target
, mailbox
, client_id
);
13426 return error::kNoError
;
13429 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target
,
13430 const GLbyte
* data
, GLuint client_id
) {
13431 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
13432 "context", logger_
.GetLogPrefix(),
13433 "mailbox[0]", static_cast<unsigned char>(data
[0]));
13434 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
13435 DLOG_IF(ERROR
, !mailbox
.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
13436 "passed a mailbox that was not "
13437 "generated by GenMailboxCHROMIUM.";
13439 TextureRef
* texture_ref
= GetTexture(client_id
);
13441 // No need to call EnsureTextureForClientId here, the client_id already has
13442 // an associated texture.
13443 LOCAL_SET_GL_ERROR(
13444 GL_INVALID_OPERATION
,
13445 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
13448 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(mailbox
);
13450 EnsureTextureForClientId(target
, client_id
);
13451 LOCAL_SET_GL_ERROR(
13452 GL_INVALID_OPERATION
,
13453 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
13457 if (texture
->target() != target
) {
13458 EnsureTextureForClientId(target
, client_id
);
13459 LOCAL_SET_GL_ERROR(
13460 GL_INVALID_OPERATION
,
13461 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
13465 texture_ref
= texture_manager()->Consume(client_id
, texture
);
13468 bool GLES2DecoderImpl::DoIsValuebufferCHROMIUM(GLuint client_id
) {
13469 const Valuebuffer
* valuebuffer
= GetValuebuffer(client_id
);
13470 return valuebuffer
&& valuebuffer
->IsValid();
13473 void GLES2DecoderImpl::DoBindValueBufferCHROMIUM(GLenum target
,
13474 GLuint client_id
) {
13475 Valuebuffer
* valuebuffer
= NULL
;
13476 if (client_id
!= 0) {
13477 valuebuffer
= GetValuebuffer(client_id
);
13478 if (!valuebuffer
) {
13479 if (!group_
->bind_generates_resource()) {
13480 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glBindValuebufferCHROMIUM",
13481 "id not generated by glBindValuebufferCHROMIUM");
13485 // It's a new id so make a valuebuffer for it.
13486 CreateValuebuffer(client_id
);
13487 valuebuffer
= GetValuebuffer(client_id
);
13489 valuebuffer
->MarkAsValid();
13491 state_
.bound_valuebuffer
= valuebuffer
;
13494 void GLES2DecoderImpl::DoSubscribeValueCHROMIUM(GLenum target
,
13495 GLenum subscription
) {
13496 if (!CheckCurrentValuebuffer("glSubscribeValueCHROMIUM")) {
13499 state_
.bound_valuebuffer
.get()->AddSubscription(subscription
);
13502 void GLES2DecoderImpl::DoPopulateSubscribedValuesCHROMIUM(GLenum target
) {
13503 if (!CheckCurrentValuebuffer("glPopulateSubscribedValuesCHROMIUM")) {
13506 valuebuffer_manager()->UpdateValuebufferState(state_
.bound_valuebuffer
.get());
13509 void GLES2DecoderImpl::DoUniformValueBufferCHROMIUM(GLint location
,
13511 GLenum subscription
) {
13512 if (!CheckCurrentValuebufferForSubscription(
13513 subscription
, "glPopulateSubscribedValuesCHROMIUM")) {
13516 if (!CheckSubscriptionTarget(location
, subscription
,
13517 "glPopulateSubscribedValuesCHROMIUM")) {
13520 const ValueState
* state
=
13521 state_
.bound_valuebuffer
.get()->GetState(subscription
);
13523 switch (subscription
) {
13524 case GL_MOUSE_POSITION_CHROMIUM
:
13525 DoUniform2iv(location
, 1, state
->int_value
);
13528 NOTREACHED() << "Unhandled uniform subscription target "
13535 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
13536 GLsizei length
, const GLchar
* marker
) {
13540 debug_marker_manager_
.SetMarker(
13541 length
? std::string(marker
, length
) : std::string(marker
));
13544 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
13545 GLsizei
/*length*/, const GLchar
* /*marker*/) {
13548 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
13551 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
13552 GLenum target
, GLint image_id
) {
13553 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
13555 if (target
== GL_TEXTURE_CUBE_MAP
) {
13556 LOCAL_SET_GL_ERROR(
13558 "glBindTexImage2DCHROMIUM", "invalid target");
13562 // Default target might be conceptually valid, but disallow it to avoid
13564 TextureRef
* texture_ref
=
13565 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
13566 if (!texture_ref
) {
13567 LOCAL_SET_GL_ERROR(
13568 GL_INVALID_OPERATION
,
13569 "glBindTexImage2DCHROMIUM", "no texture bound");
13573 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
13575 LOCAL_SET_GL_ERROR(
13576 GL_INVALID_OPERATION
,
13577 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
13582 ScopedGLErrorSuppressor
suppressor(
13583 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
13584 if (!gl_image
->BindTexImage(target
)) {
13585 LOCAL_SET_GL_ERROR(
13586 GL_INVALID_OPERATION
,
13587 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
13592 gfx::Size size
= gl_image
->GetSize();
13593 texture_manager()->SetLevelInfo(
13594 texture_ref
, target
, 0, gl_image
->GetInternalFormat(), size
.width(),
13595 size
.height(), 1, 0, gl_image
->GetInternalFormat(), GL_UNSIGNED_BYTE
,
13597 texture_manager()->SetLevelImage(texture_ref
, target
, 0, gl_image
);
13600 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
13601 GLenum target
, GLint image_id
) {
13602 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
13604 // Default target might be conceptually valid, but disallow it to avoid
13606 TextureRef
* texture_ref
=
13607 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
13608 if (!texture_ref
) {
13609 LOCAL_SET_GL_ERROR(
13610 GL_INVALID_OPERATION
,
13611 "glReleaseTexImage2DCHROMIUM", "no texture bound");
13615 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
13617 LOCAL_SET_GL_ERROR(
13618 GL_INVALID_OPERATION
,
13619 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
13623 // Do nothing when image is not currently bound.
13624 if (texture_ref
->texture()->GetLevelImage(target
, 0) != gl_image
)
13628 ScopedGLErrorSuppressor
suppressor(
13629 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
13630 gl_image
->ReleaseTexImage(target
);
13633 texture_manager()->SetLevelInfo(
13634 texture_ref
, target
, 0, gl_image
->GetInternalFormat(), 0, 0, 1, 0,
13635 gl_image
->GetInternalFormat(), GL_UNSIGNED_BYTE
, gfx::Rect());
13638 error::Error
GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
13639 uint32 immediate_data_size
,
13640 const void* cmd_data
) {
13641 const gles2::cmds::TraceBeginCHROMIUM
& c
=
13642 *static_cast<const gles2::cmds::TraceBeginCHROMIUM
*>(cmd_data
);
13643 Bucket
* category_bucket
= GetBucket(c
.category_bucket_id
);
13644 Bucket
* name_bucket
= GetBucket(c
.name_bucket_id
);
13645 if (!category_bucket
|| category_bucket
->size() == 0 ||
13646 !name_bucket
|| name_bucket
->size() == 0) {
13647 return error::kInvalidArguments
;
13650 std::string category_name
;
13651 std::string trace_name
;
13652 if (!category_bucket
->GetAsString(&category_name
) ||
13653 !name_bucket
->GetAsString(&trace_name
)) {
13654 return error::kInvalidArguments
;
13657 debug_marker_manager_
.PushGroup(trace_name
);
13658 if (!gpu_tracer_
->Begin(category_name
, trace_name
, kTraceCHROMIUM
)) {
13659 LOCAL_SET_GL_ERROR(
13660 GL_INVALID_OPERATION
,
13661 "glTraceBeginCHROMIUM", "unable to create begin trace");
13662 return error::kNoError
;
13664 return error::kNoError
;
13667 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
13668 debug_marker_manager_
.PopGroup();
13669 if (!gpu_tracer_
->End(kTraceCHROMIUM
)) {
13670 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
13671 "glTraceEndCHROMIUM", "no trace begin found");
13676 void GLES2DecoderImpl::DoDrawBuffersEXT(
13677 GLsizei count
, const GLenum
* bufs
) {
13678 if (count
> static_cast<GLsizei
>(group_
->max_draw_buffers())) {
13679 LOCAL_SET_GL_ERROR(
13681 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
13685 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
13687 for (GLsizei i
= 0; i
< count
; ++i
) {
13688 if (bufs
[i
] != static_cast<GLenum
>(GL_COLOR_ATTACHMENT0
+ i
) &&
13689 bufs
[i
] != GL_NONE
) {
13690 LOCAL_SET_GL_ERROR(
13691 GL_INVALID_OPERATION
,
13692 "glDrawBuffersEXT",
13693 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
13697 glDrawBuffersARB(count
, bufs
);
13698 framebuffer
->SetDrawBuffers(count
, bufs
);
13699 } else { // backbuffer
13701 (bufs
[0] != GL_BACK
&& bufs
[0] != GL_NONE
)) {
13702 LOCAL_SET_GL_ERROR(
13703 GL_INVALID_OPERATION
,
13704 "glDrawBuffersEXT",
13705 "more than one buffer or bufs not GL_NONE or GL_BACK");
13708 GLenum mapped_buf
= bufs
[0];
13709 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
13710 bufs
[0] == GL_BACK
) {
13711 mapped_buf
= GL_COLOR_ATTACHMENT0
;
13713 glDrawBuffersARB(count
, &mapped_buf
);
13714 back_buffer_draw_buffer_
= bufs
[0];
13718 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current
, GLenum other
) {
13719 MarkContextLost(GetContextLostReasonFromResetStatus(current
));
13720 group_
->LoseContexts(GetContextLostReasonFromResetStatus(other
));
13721 reset_by_robustness_extension_
= true;
13724 void GLES2DecoderImpl::DoFlushDriverCachesCHROMIUM(void) {
13725 // On Adreno Android devices we need to use a workaround to force caches to
13727 if (feature_info_
->workarounds().unbind_egl_context_to_flush_driver_caches
) {
13728 context_
->ReleaseCurrent(nullptr);
13729 context_
->MakeCurrent(surface_
.get());
13733 void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode
,
13734 const GLfloat
* matrix
) {
13735 DCHECK(matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
||
13736 matrix_mode
== GL_PATH_MODELVIEW_CHROMIUM
);
13737 if (!features().chromium_path_rendering
) {
13738 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
13739 "glMatrixLoadfCHROMIUM",
13740 "function not available");
13744 GLfloat
* target_matrix
= matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
13745 ? state_
.projection_matrix
13746 : state_
.modelview_matrix
;
13747 memcpy(target_matrix
, matrix
, sizeof(GLfloat
) * 16);
13748 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
13749 // since the values of the _NV and _CHROMIUM tokens match.
13750 glMatrixLoadfEXT(matrix_mode
, matrix
);
13753 void GLES2DecoderImpl::DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode
) {
13754 DCHECK(matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
||
13755 matrix_mode
== GL_PATH_MODELVIEW_CHROMIUM
);
13757 if (!features().chromium_path_rendering
) {
13758 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
13759 "glMatrixLoadIdentityCHROMIUM",
13760 "function not available");
13764 GLfloat
* target_matrix
= matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
13765 ? state_
.projection_matrix
13766 : state_
.modelview_matrix
;
13767 memcpy(target_matrix
, kIdentityMatrix
, sizeof(kIdentityMatrix
));
13768 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
13769 // since the values of the _NV and _CHROMIUM tokens match.
13770 glMatrixLoadIdentityEXT(matrix_mode
);
13773 bool GLES2DecoderImpl::ValidateAsyncTransfer(
13774 const char* function_name
,
13775 TextureRef
* texture_ref
,
13778 const void * data
) {
13779 // We only support async uploads to 2D textures for now.
13780 if (GL_TEXTURE_2D
!= target
) {
13781 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
13784 // We only support uploads to level zero for now.
13786 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "level != 0");
13789 // A transfer buffer must be bound, even for asyncTexImage2D.
13790 if (data
== NULL
) {
13791 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
, "buffer == 0");
13794 // We only support one async transfer in progress.
13795 if (!texture_ref
||
13796 async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
13797 LOCAL_SET_GL_ERROR(
13798 GL_INVALID_OPERATION
,
13799 function_name
, "transfer already in progress");
13805 base::Closure
GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
13806 uint32 async_upload_token
,
13807 uint32 sync_data_shm_id
,
13808 uint32 sync_data_shm_offset
) {
13809 scoped_refptr
<gpu::Buffer
> buffer
= GetSharedMemoryBuffer(sync_data_shm_id
);
13810 if (!buffer
.get() ||
13811 !buffer
->GetDataAddress(sync_data_shm_offset
, sizeof(AsyncUploadSync
)))
13812 return base::Closure();
13814 AsyncMemoryParams
mem_params(buffer
,
13815 sync_data_shm_offset
,
13816 sizeof(AsyncUploadSync
));
13818 scoped_refptr
<AsyncUploadTokenCompletionObserver
> observer(
13819 new AsyncUploadTokenCompletionObserver(async_upload_token
));
13822 &AsyncPixelTransferManager::AsyncNotifyCompletion
,
13823 base::Unretained(GetAsyncPixelTransferManager()),
13828 error::Error
GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
13829 uint32 immediate_data_size
,
13830 const void* cmd_data
) {
13831 const gles2::cmds::AsyncTexImage2DCHROMIUM
& c
=
13832 *static_cast<const gles2::cmds::AsyncTexImage2DCHROMIUM
*>(cmd_data
);
13833 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
13834 GLenum target
= static_cast<GLenum
>(c
.target
);
13835 GLint level
= static_cast<GLint
>(c
.level
);
13836 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
13837 GLsizei width
= static_cast<GLsizei
>(c
.width
);
13838 GLsizei height
= static_cast<GLsizei
>(c
.height
);
13839 GLint border
= static_cast<GLint
>(c
.border
);
13840 GLenum format
= static_cast<GLenum
>(c
.format
);
13841 GLenum type
= static_cast<GLenum
>(c
.type
);
13842 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
13843 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
13844 uint32 pixels_size
;
13845 uint32 async_upload_token
= static_cast<uint32
>(c
.async_upload_token
);
13846 uint32 sync_data_shm_id
= static_cast<uint32
>(c
.sync_data_shm_id
);
13847 uint32 sync_data_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
13849 base::ScopedClosureRunner scoped_completion_callback
;
13850 if (async_upload_token
) {
13851 base::Closure completion_closure
=
13852 AsyncUploadTokenCompletionClosure(async_upload_token
,
13854 sync_data_shm_offset
);
13855 if (completion_closure
.is_null())
13856 return error::kInvalidArguments
;
13858 scoped_completion_callback
.Reset(completion_closure
);
13861 // TODO(epenner): Move this and copies of this memory validation
13862 // into ValidateTexImage2D step.
13863 if (!GLES2Util::ComputeImageDataSizes(
13864 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
13866 return error::kOutOfBounds
;
13868 const void* pixels
= NULL
;
13869 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
13870 pixels
= GetSharedMemoryAs
<const void*>(
13871 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
13873 return error::kOutOfBounds
;
13877 TextureManager::DoTexImageArguments args
= {
13878 target
, level
, internal_format
, width
, height
, 1, border
, format
, type
,
13879 pixels
, pixels_size
, TextureManager::DoTexImageArguments::kTexImage2D
};
13880 TextureRef
* texture_ref
;
13881 // All the normal glTexSubImage2D validation.
13882 if (!texture_manager()->ValidateTexImage(
13883 &state_
, "glAsyncTexImage2DCHROMIUM", args
, &texture_ref
)) {
13884 return error::kNoError
;
13887 // Extra async validation.
13888 Texture
* texture
= texture_ref
->texture();
13889 if (!ValidateAsyncTransfer(
13890 "glAsyncTexImage2DCHROMIUM", texture_ref
, target
, level
, pixels
))
13891 return error::kNoError
;
13893 // Don't allow async redefinition of a textures.
13894 if (texture
->IsDefined()) {
13895 LOCAL_SET_GL_ERROR(
13896 GL_INVALID_OPERATION
,
13897 "glAsyncTexImage2DCHROMIUM", "already defined");
13898 return error::kNoError
;
13901 if (!EnsureGPUMemoryAvailable(pixels_size
)) {
13902 LOCAL_SET_GL_ERROR(
13903 GL_OUT_OF_MEMORY
, "glAsyncTexImage2DCHROMIUM", "out of memory");
13904 return error::kNoError
;
13907 // Setup the parameters.
13908 AsyncTexImage2DParams tex_params
= {
13909 target
, level
, static_cast<GLenum
>(internal_format
),
13910 width
, height
, border
, format
, type
};
13911 AsyncMemoryParams
mem_params(
13912 GetSharedMemoryBuffer(c
.pixels_shm_id
), c
.pixels_shm_offset
, pixels_size
);
13914 // Set up the async state if needed, and make the texture
13915 // immutable so the async state stays valid. The level info
13916 // is set up lazily when the transfer completes.
13917 AsyncPixelTransferDelegate
* delegate
=
13918 async_pixel_transfer_manager_
->CreatePixelTransferDelegate(texture_ref
,
13920 texture
->SetImmutable(true);
13922 delegate
->AsyncTexImage2D(
13925 base::Bind(&TextureManager::SetLevelInfoFromParams
,
13926 // The callback is only invoked if the transfer delegate still
13927 // exists, which implies through manager->texture_ref->state
13928 // ownership that both of these pointers are valid.
13929 base::Unretained(texture_manager()),
13930 base::Unretained(texture_ref
),
13932 return error::kNoError
;
13935 error::Error
GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
13936 uint32 immediate_data_size
,
13937 const void* cmd_data
) {
13938 const gles2::cmds::AsyncTexSubImage2DCHROMIUM
& c
=
13939 *static_cast<const gles2::cmds::AsyncTexSubImage2DCHROMIUM
*>(cmd_data
);
13940 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
13941 GLenum target
= static_cast<GLenum
>(c
.target
);
13942 GLint level
= static_cast<GLint
>(c
.level
);
13943 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
13944 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
13945 GLsizei width
= static_cast<GLsizei
>(c
.width
);
13946 GLsizei height
= static_cast<GLsizei
>(c
.height
);
13947 GLenum format
= static_cast<GLenum
>(c
.format
);
13948 GLenum type
= static_cast<GLenum
>(c
.type
);
13949 uint32 async_upload_token
= static_cast<uint32
>(c
.async_upload_token
);
13950 uint32 sync_data_shm_id
= static_cast<uint32
>(c
.sync_data_shm_id
);
13951 uint32 sync_data_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
13953 base::ScopedClosureRunner scoped_completion_callback
;
13954 if (async_upload_token
) {
13955 base::Closure completion_closure
=
13956 AsyncUploadTokenCompletionClosure(async_upload_token
,
13958 sync_data_shm_offset
);
13959 if (completion_closure
.is_null())
13960 return error::kInvalidArguments
;
13962 scoped_completion_callback
.Reset(completion_closure
);
13965 // TODO(epenner): Move this and copies of this memory validation
13966 // into ValidateTexSubImage2D step.
13968 if (!GLES2Util::ComputeImageDataSizes(
13969 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &data_size
,
13971 return error::kOutOfBounds
;
13973 const void* pixels
= GetSharedMemoryAs
<const void*>(
13974 c
.data_shm_id
, c
.data_shm_offset
, data_size
);
13976 // All the normal glTexSubImage2D validation.
13977 error::Error error
= error::kNoError
;
13978 if (!ValidateTexSubImage2D(&error
, "glAsyncTexSubImage2DCHROMIUM",
13979 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
)) {
13983 // Extra async validation.
13984 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
13986 Texture
* texture
= texture_ref
->texture();
13987 if (!ValidateAsyncTransfer(
13988 "glAsyncTexSubImage2DCHROMIUM", texture_ref
, target
, level
, pixels
))
13989 return error::kNoError
;
13991 // Guarantee async textures are always 'cleared' as follows:
13992 // - AsyncTexImage2D can not redefine an existing texture
13993 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
13994 // - AsyncTexSubImage2D clears synchronously if not already cleared.
13995 // - Textures become immutable after an async call.
13996 // This way we know in all cases that an async texture is always clear.
13997 if (!texture
->SafeToRenderFrom()) {
13998 if (!texture_manager()->ClearTextureLevel(this, texture_ref
,
14000 LOCAL_SET_GL_ERROR(
14002 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
14003 return error::kNoError
;
14007 // Setup the parameters.
14008 AsyncTexSubImage2DParams tex_params
= {target
, level
, xoffset
, yoffset
,
14009 width
, height
, format
, type
};
14010 AsyncMemoryParams
mem_params(
14011 GetSharedMemoryBuffer(c
.data_shm_id
), c
.data_shm_offset
, data_size
);
14012 AsyncPixelTransferDelegate
* delegate
=
14013 async_pixel_transfer_manager_
->GetPixelTransferDelegate(texture_ref
);
14015 // TODO(epenner): We may want to enforce exclusive use
14016 // of async APIs in which case this should become an error,
14017 // (the texture should have been async defined).
14018 AsyncTexImage2DParams define_params
= {target
, level
,
14020 texture
->GetLevelSize(
14021 target
, level
, &define_params
.width
, &define_params
.height
, nullptr);
14022 texture
->GetLevelType(
14023 target
, level
, &define_params
.type
, &define_params
.internal_format
);
14024 // Set up the async state if needed, and make the texture
14025 // immutable so the async state stays valid.
14026 delegate
= async_pixel_transfer_manager_
->CreatePixelTransferDelegate(
14027 texture_ref
, define_params
);
14028 texture
->SetImmutable(true);
14031 delegate
->AsyncTexSubImage2D(tex_params
, mem_params
);
14032 return error::kNoError
;
14035 error::Error
GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
14036 uint32 immediate_data_size
,
14037 const void* cmd_data
) {
14038 const gles2::cmds::WaitAsyncTexImage2DCHROMIUM
& c
=
14039 *static_cast<const gles2::cmds::WaitAsyncTexImage2DCHROMIUM
*>(cmd_data
);
14040 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
14041 GLenum target
= static_cast<GLenum
>(c
.target
);
14043 if (GL_TEXTURE_2D
!= target
) {
14044 LOCAL_SET_GL_ERROR(
14045 GL_INVALID_ENUM
, "glWaitAsyncTexImage2DCHROMIUM", "target");
14046 return error::kNoError
;
14048 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
14050 if (!texture_ref
) {
14051 LOCAL_SET_GL_ERROR(
14052 GL_INVALID_OPERATION
,
14053 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
14054 return error::kNoError
;
14056 AsyncPixelTransferDelegate
* delegate
=
14057 async_pixel_transfer_manager_
->GetPixelTransferDelegate(texture_ref
);
14059 LOCAL_SET_GL_ERROR(
14060 GL_INVALID_OPERATION
,
14061 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
14062 return error::kNoError
;
14064 delegate
->WaitForTransferCompletion();
14065 ProcessFinishedAsyncTransfers();
14066 return error::kNoError
;
14069 error::Error
GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
14070 uint32 immediate_data_size
,
14071 const void* data
) {
14072 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
14074 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
14075 ProcessFinishedAsyncTransfers();
14076 return error::kNoError
;
14079 error::Error
GLES2DecoderImpl::HandleUniformBlockBinding(
14080 uint32_t immediate_data_size
, const void* cmd_data
) {
14081 if (!unsafe_es3_apis_enabled())
14082 return error::kUnknownCommand
;
14083 const gles2::cmds::UniformBlockBinding
& c
=
14084 *static_cast<const gles2::cmds::UniformBlockBinding
*>(cmd_data
);
14085 GLuint client_id
= c
.program
;
14086 GLuint index
= static_cast<GLuint
>(c
.index
);
14087 GLuint binding
= static_cast<GLuint
>(c
.binding
);
14088 Program
* program
= GetProgramInfoNotShader(
14089 client_id
, "glUniformBlockBinding");
14091 return error::kNoError
;
14093 GLuint service_id
= program
->service_id();
14094 glUniformBlockBinding(service_id
, index
, binding
);
14095 return error::kNoError
;
14098 error::Error
GLES2DecoderImpl::HandleClientWaitSync(
14099 uint32_t immediate_data_size
, const void* cmd_data
) {
14100 if (!unsafe_es3_apis_enabled())
14101 return error::kUnknownCommand
;
14102 const gles2::cmds::ClientWaitSync
& c
=
14103 *static_cast<const gles2::cmds::ClientWaitSync
*>(cmd_data
);
14104 GLuint sync
= static_cast<GLuint
>(c
.sync
);
14105 GLbitfield flags
= static_cast<GLbitfield
>(c
.flags
);
14106 GLuint64 timeout
= GLES2Util::MapTwoUint32ToUint64(c
.timeout_0
, c
.timeout_1
);
14107 typedef cmds::ClientWaitSync::Result Result
;
14108 Result
* result_dst
= GetSharedMemoryAs
<Result
*>(
14109 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result_dst
));
14111 return error::kOutOfBounds
;
14113 if (*result_dst
!= GL_WAIT_FAILED
) {
14114 return error::kInvalidArguments
;
14116 GLsync service_sync
= 0;
14117 if (!group_
->GetSyncServiceId(sync
, &service_sync
)) {
14118 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "ClientWaitSync", "invalid sync");
14119 return error::kNoError
;
14121 *result_dst
= glClientWaitSync(service_sync
, flags
, timeout
);
14122 return error::kNoError
;
14125 error::Error
GLES2DecoderImpl::HandleWaitSync(
14126 uint32_t immediate_data_size
, const void* cmd_data
) {
14127 if (!unsafe_es3_apis_enabled())
14128 return error::kUnknownCommand
;
14129 const gles2::cmds::WaitSync
& c
=
14130 *static_cast<const gles2::cmds::WaitSync
*>(cmd_data
);
14131 GLuint sync
= static_cast<GLuint
>(c
.sync
);
14132 GLbitfield flags
= static_cast<GLbitfield
>(c
.flags
);
14133 GLuint64 timeout
= GLES2Util::MapTwoUint32ToUint64(c
.timeout_0
, c
.timeout_1
);
14134 GLsync service_sync
= 0;
14135 if (!group_
->GetSyncServiceId(sync
, &service_sync
)) {
14136 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "WaitSync", "invalid sync");
14137 return error::kNoError
;
14139 glWaitSync(service_sync
, flags
, timeout
);
14140 return error::kNoError
;
14143 error::Error
GLES2DecoderImpl::HandleGetInternalformativ(
14144 uint32_t immediate_data_size
, const void* cmd_data
) {
14145 if (!unsafe_es3_apis_enabled())
14146 return error::kUnknownCommand
;
14147 const gles2::cmds::GetInternalformativ
& c
=
14148 *static_cast<const gles2::cmds::GetInternalformativ
*>(cmd_data
);
14149 GLenum target
= static_cast<GLenum
>(c
.target
);
14150 GLenum format
= static_cast<GLenum
>(c
.format
);
14151 GLenum pname
= static_cast<GLenum
>(c
.pname
);
14152 if (!validators_
->render_buffer_target
.IsValid(target
)) {
14153 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", target
, "target");
14154 return error::kNoError
;
14156 if (!validators_
->render_buffer_format
.IsValid(format
)) {
14157 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", format
, "format");
14158 return error::kNoError
;
14160 if (!validators_
->internal_format_parameter
.IsValid(pname
)) {
14161 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", pname
, "pname");
14162 return error::kNoError
;
14164 typedef cmds::GetInternalformativ::Result Result
;
14165 GLsizei num_values
= 0;
14167 case GL_NUM_SAMPLE_COUNTS
:
14173 glGetInternalformativ(target
, format
, GL_NUM_SAMPLE_COUNTS
, 1, &value
);
14174 num_values
= static_cast<GLsizei
>(value
);
14181 Result
* result
= GetSharedMemoryAs
<Result
*>(
14182 c
.params_shm_id
, c
.params_shm_offset
, Result::ComputeSize(num_values
));
14183 GLint
* params
= result
? result
->GetData() : NULL
;
14184 if (params
== NULL
) {
14185 return error::kOutOfBounds
;
14187 // Check that the client initialized the result.
14188 if (result
->size
!= 0) {
14189 return error::kInvalidArguments
;
14191 glGetInternalformativ(target
, format
, pname
, num_values
, params
);
14192 result
->SetNumResults(num_values
);
14193 return error::kNoError
;
14196 error::Error
GLES2DecoderImpl::HandleMapBufferRange(
14197 uint32_t immediate_data_size
, const void* cmd_data
) {
14198 if (!unsafe_es3_apis_enabled()) {
14199 return error::kUnknownCommand
;
14201 const gles2::cmds::MapBufferRange
& c
=
14202 *static_cast<const gles2::cmds::MapBufferRange
*>(cmd_data
);
14203 GLenum target
= static_cast<GLenum
>(c
.target
);
14204 GLbitfield access
= static_cast<GLbitfield
>(c
.access
);
14205 GLintptr offset
= static_cast<GLintptr
>(c
.offset
);
14206 GLsizeiptr size
= static_cast<GLsizeiptr
>(c
.size
);
14208 typedef cmds::MapBufferRange::Result Result
;
14209 Result
* result
= GetSharedMemoryAs
<Result
*>(
14210 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
14212 return error::kOutOfBounds
;
14214 if (*result
!= 0) {
14216 return error::kInvalidArguments
;
14219 GetSharedMemoryAs
<int8_t*>(c
.data_shm_id
, c
.data_shm_offset
, size
);
14221 return error::kOutOfBounds
;
14224 GLbitfield mask
= GL_MAP_INVALIDATE_BUFFER_BIT
;
14225 if ((access
& mask
) == mask
) {
14226 // TODO(zmo): To be on the safe side, always map
14227 // GL_MAP_INVALIDATE_BUFFER_BIT to GL_MAP_INVALIDATE_RANGE_BIT.
14228 access
= (access
& ~GL_MAP_INVALIDATE_BUFFER_BIT
);
14229 access
= (access
| GL_MAP_INVALIDATE_RANGE_BIT
);
14231 // TODO(zmo): Always filter out GL_MAP_UNSYNCHRONIZED_BIT to get rid of
14232 // undefined behaviors.
14233 mask
= GL_MAP_READ_BIT
| GL_MAP_UNSYNCHRONIZED_BIT
;
14234 if ((access
& mask
) == mask
) {
14235 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "MapBufferRange",
14236 "incompatible access bits");
14237 return error::kNoError
;
14239 access
= (access
& ~GL_MAP_UNSYNCHRONIZED_BIT
);
14240 if ((access
& GL_MAP_WRITE_BIT
) == GL_MAP_WRITE_BIT
&&
14241 (access
& GL_MAP_INVALIDATE_RANGE_BIT
) == 0) {
14242 access
= (access
| GL_MAP_READ_BIT
);
14244 void* ptr
= glMapBufferRange(target
, offset
, size
, access
);
14245 if (ptr
== nullptr) {
14246 return error::kNoError
;
14248 Buffer
* buffer
= buffer_manager()->GetBufferInfoForTarget(&state_
, target
);
14250 buffer
->SetMappedRange(offset
, size
, access
, ptr
,
14251 GetSharedMemoryBuffer(c
.data_shm_id
));
14252 if ((access
& GL_MAP_INVALIDATE_RANGE_BIT
) == 0) {
14253 memcpy(mem
, ptr
, size
);
14256 return error::kNoError
;
14259 error::Error
GLES2DecoderImpl::HandleUnmapBuffer(
14260 uint32_t immediate_data_size
, const void* cmd_data
) {
14261 if (!unsafe_es3_apis_enabled()) {
14262 return error::kUnknownCommand
;
14264 const gles2::cmds::UnmapBuffer
& c
=
14265 *static_cast<const gles2::cmds::UnmapBuffer
*>(cmd_data
);
14266 GLenum target
= static_cast<GLenum
>(c
.target
);
14268 Buffer
* buffer
= buffer_manager()->GetBufferInfoForTarget(&state_
, target
);
14270 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "UnmapBuffer", "no buffer bound");
14271 return error::kNoError
;
14273 const Buffer::MappedRange
* mapped_range
= buffer
->GetMappedRange();
14274 if (!mapped_range
) {
14275 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "UnmapBuffer",
14276 "buffer is unmapped");
14277 return error::kNoError
;
14279 if ((mapped_range
->access
& GL_MAP_WRITE_BIT
) == 0 ||
14280 (mapped_range
->access
& GL_MAP_FLUSH_EXPLICIT_BIT
) ==
14281 GL_MAP_FLUSH_EXPLICIT_BIT
) {
14282 // If we don't need to write back, or explict flush is required, no copying
14285 void* mem
= mapped_range
->GetShmPointer();
14287 return error::kOutOfBounds
;
14289 DCHECK(mapped_range
->pointer
);
14290 memcpy(mapped_range
->pointer
, mem
, mapped_range
->size
);
14292 buffer
->RemoveMappedRange();
14293 GLboolean rt
= glUnmapBuffer(target
);
14294 if (rt
== GL_FALSE
) {
14295 // At this point, we have already done the necessary validation, so
14296 // GL_FALSE indicates data corruption.
14297 // TODO(zmo): We could redo the map / copy data / unmap to recover, but
14298 // the second unmap could still return GL_FALSE. For now, we simply lose
14299 // the contexts in the share group.
14300 LOG(ERROR
) << "glUnmapBuffer unexpectedly returned GL_FALSE";
14301 // Need to lose current context before broadcasting!
14302 MarkContextLost(error::kGuilty
);
14303 group_
->LoseContexts(error::kInnocent
);
14304 return error::kLostContext
;
14306 return error::kNoError
;
14309 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
14310 TextureRef
* texture_ref
) {
14311 Texture
* texture
= texture_ref
->texture();
14312 DoDidUseTexImageIfNeeded(texture
, texture
->target());
14315 // Note that GL_LOST_CONTEXT is specific to GLES.
14316 // For desktop GL we have to query the reset status proactively.
14317 void GLES2DecoderImpl::OnContextLostError() {
14318 if (!WasContextLost()) {
14319 // Need to lose current context before broadcasting!
14320 CheckResetStatus();
14321 group_
->LoseContexts(error::kUnknown
);
14322 reset_by_robustness_extension_
= true;
14326 void GLES2DecoderImpl::OnOutOfMemoryError() {
14327 if (lose_context_when_out_of_memory_
&& !WasContextLost()) {
14328 error::ContextLostReason other
= error::kOutOfMemory
;
14329 if (CheckResetStatus()) {
14330 other
= error::kUnknown
;
14332 // Need to lose current context before broadcasting!
14333 MarkContextLost(error::kOutOfMemory
);
14335 group_
->LoseContexts(other
);
14339 error::Error
GLES2DecoderImpl::HandleGenPathsCHROMIUM(
14340 uint32 immediate_data_size
,
14341 const void* cmd_data
) {
14342 static const char kFunctionName
[] = "glGenPathsCHROMIUM";
14343 const gles2::cmds::GenPathsCHROMIUM
& c
=
14344 *static_cast<const gles2::cmds::GenPathsCHROMIUM
*>(cmd_data
);
14345 if (!features().chromium_path_rendering
) {
14346 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14347 "function not available");
14348 return error::kNoError
;
14351 GLsizei range
= static_cast<GLsizei
>(c
.range
);
14353 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "range < 0");
14354 return error::kNoError
;
14357 GLuint first_client_id
= static_cast<GLuint
>(c
.first_client_id
);
14358 if (first_client_id
== 0)
14359 return error::kInvalidArguments
;
14362 return error::kNoError
;
14364 if (!GenPathsCHROMIUMHelper(first_client_id
, range
))
14365 return error::kInvalidArguments
;
14367 return error::kNoError
;
14369 error::Error
GLES2DecoderImpl::HandleDeletePathsCHROMIUM(
14370 uint32_t immediate_data_size
,
14371 const void* cmd_data
) {
14372 static const char kFunctionName
[] = "glDeletePathsCHROMIUM";
14373 const gles2::cmds::DeletePathsCHROMIUM
& c
=
14374 *static_cast<const gles2::cmds::DeletePathsCHROMIUM
*>(cmd_data
);
14375 if (!features().chromium_path_rendering
) {
14376 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14377 "function not available");
14378 return error::kNoError
;
14381 GLsizei range
= static_cast<GLsizei
>(c
.range
);
14383 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "range < 0");
14384 return error::kNoError
;
14388 return error::kNoError
;
14390 GLuint first_client_id
= c
.first_client_id
;
14391 // first_client_id can be 0, because non-existing path ids are skipped.
14393 if (!DeletePathsCHROMIUMHelper(first_client_id
, range
))
14394 return error::kInvalidArguments
;
14396 return error::kNoError
;
14399 error::Error
GLES2DecoderImpl::HandlePathCommandsCHROMIUM(
14400 uint32 immediate_data_size
,
14401 const void* cmd_data
) {
14402 static const char kFunctionName
[] = "glPathCommandsCHROMIUM";
14403 const gles2::cmds::PathCommandsCHROMIUM
& c
=
14404 *static_cast<const gles2::cmds::PathCommandsCHROMIUM
*>(cmd_data
);
14405 if (!features().chromium_path_rendering
) {
14406 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14407 "function not available");
14408 return error::kNoError
;
14411 GLuint service_id
= 0;
14412 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
)) {
14413 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14414 "invalid path name");
14415 return error::kNoError
;
14418 GLsizei num_commands
= static_cast<GLsizei
>(c
.numCommands
);
14419 if (num_commands
< 0) {
14420 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "numCommands < 0");
14421 return error::kNoError
;
14424 GLsizei num_coords
= static_cast<uint32
>(c
.numCoords
);
14425 if (num_coords
< 0) {
14426 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "numCoords < 0");
14427 return error::kNoError
;
14430 GLenum coord_type
= static_cast<uint32
>(c
.coordType
);
14431 if (!validators_
->path_coord_type
.IsValid(static_cast<GLint
>(coord_type
))) {
14432 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM
, kFunctionName
, "invalid coordType");
14433 return error::kNoError
;
14436 const GLubyte
* commands
= NULL
;
14437 base::CheckedNumeric
<GLsizei
> num_coords_expected
= 0;
14439 if (num_commands
> 0) {
14440 uint32 commands_shm_id
= static_cast<uint32
>(c
.commands_shm_id
);
14441 uint32 commands_shm_offset
= static_cast<uint32
>(c
.commands_shm_offset
);
14442 if (commands_shm_id
!= 0 || commands_shm_offset
!= 0)
14443 commands
= GetSharedMemoryAs
<const GLubyte
*>(
14444 commands_shm_id
, commands_shm_offset
, num_commands
);
14447 return error::kOutOfBounds
;
14449 for (GLsizei i
= 0; i
< num_commands
; ++i
) {
14450 switch (commands
[i
]) {
14451 case GL_CLOSE_PATH_CHROMIUM
:
14452 // Close has no coords.
14454 case GL_MOVE_TO_CHROMIUM
:
14456 case GL_LINE_TO_CHROMIUM
:
14457 num_coords_expected
+= 2;
14459 case GL_QUADRATIC_CURVE_TO_CHROMIUM
:
14460 num_coords_expected
+= 4;
14462 case GL_CUBIC_CURVE_TO_CHROMIUM
:
14463 num_coords_expected
+= 6;
14465 case GL_CONIC_CURVE_TO_CHROMIUM
:
14466 num_coords_expected
+= 5;
14469 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM
, kFunctionName
, "invalid command");
14470 return error::kNoError
;
14475 if (!num_coords_expected
.IsValid() ||
14476 num_coords
!= num_coords_expected
.ValueOrDie()) {
14477 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14478 "numCoords does not match commands");
14479 return error::kNoError
;
14482 const void* coords
= NULL
;
14484 if (num_coords
> 0) {
14485 uint32 coords_size
= 0;
14486 uint32 coord_type_size
=
14487 GLES2Util::GetGLTypeSizeForPathCoordType(coord_type
);
14488 if (!SafeMultiplyUint32(num_coords
, coord_type_size
, &coords_size
))
14489 return error::kOutOfBounds
;
14491 uint32 coords_shm_id
= static_cast<uint32
>(c
.coords_shm_id
);
14492 uint32 coords_shm_offset
= static_cast<uint32
>(c
.coords_shm_offset
);
14493 if (coords_shm_id
!= 0 || coords_shm_offset
!= 0)
14494 coords
= GetSharedMemoryAs
<const void*>(coords_shm_id
, coords_shm_offset
,
14498 return error::kOutOfBounds
;
14501 glPathCommandsNV(service_id
, num_commands
, commands
, num_coords
, coord_type
,
14504 return error::kNoError
;
14507 error::Error
GLES2DecoderImpl::HandlePathParameterfCHROMIUM(
14508 uint32 immediate_data_size
,
14509 const void* cmd_data
) {
14510 static const char kFunctionName
[] = "glPathParameterfCHROMIUM";
14511 const gles2::cmds::PathParameterfCHROMIUM
& c
=
14512 *static_cast<const gles2::cmds::PathParameterfCHROMIUM
*>(cmd_data
);
14513 if (!features().chromium_path_rendering
) {
14514 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14515 "function not available");
14516 return error::kNoError
;
14518 GLuint service_id
= 0;
14519 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
)) {
14520 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14521 "invalid path name");
14522 return error::kNoError
;
14525 GLenum pname
= static_cast<GLenum
>(c
.pname
);
14526 GLfloat value
= static_cast<GLfloat
>(c
.value
);
14527 bool hasValueError
= false;
14530 case GL_PATH_STROKE_WIDTH_CHROMIUM
:
14531 case GL_PATH_MITER_LIMIT_CHROMIUM
:
14532 hasValueError
= std::isnan(value
) || !std::isfinite(value
) || value
< 0;
14534 case GL_PATH_STROKE_BOUND_CHROMIUM
:
14535 value
= std::max(std::min(1.0f
, value
), 0.0f
);
14537 case GL_PATH_END_CAPS_CHROMIUM
:
14538 hasValueError
= !validators_
->path_parameter_cap_values
.IsValid(
14539 static_cast<GLint
>(value
));
14541 case GL_PATH_JOIN_STYLE_CHROMIUM
:
14542 hasValueError
= !validators_
->path_parameter_join_values
.IsValid(
14543 static_cast<GLint
>(value
));
14546 DCHECK(!validators_
->path_parameter
.IsValid(pname
));
14547 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, pname
, "pname");
14548 return error::kNoError
;
14550 DCHECK(validators_
->path_parameter
.IsValid(pname
));
14552 if (hasValueError
) {
14553 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "value not correct");
14554 return error::kNoError
;
14557 glPathParameterfNV(service_id
, pname
, value
);
14558 return error::kNoError
;
14561 error::Error
GLES2DecoderImpl::HandlePathParameteriCHROMIUM(
14562 uint32 immediate_data_size
,
14563 const void* cmd_data
) {
14564 static const char kFunctionName
[] = "glPathParameteriCHROMIUM";
14565 const gles2::cmds::PathParameteriCHROMIUM
& c
=
14566 *static_cast<const gles2::cmds::PathParameteriCHROMIUM
*>(cmd_data
);
14567 if (!features().chromium_path_rendering
) {
14568 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14569 "function not available");
14570 return error::kNoError
;
14572 GLuint service_id
= 0;
14573 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
)) {
14574 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14575 "invalid path name");
14576 return error::kNoError
;
14579 GLenum pname
= static_cast<GLenum
>(c
.pname
);
14580 GLint value
= static_cast<GLint
>(c
.value
);
14581 bool hasValueError
= false;
14584 case GL_PATH_STROKE_WIDTH_CHROMIUM
:
14585 case GL_PATH_MITER_LIMIT_CHROMIUM
:
14586 hasValueError
= value
< 0;
14588 case GL_PATH_STROKE_BOUND_CHROMIUM
:
14589 value
= std::max(std::min(1, value
), 0);
14591 case GL_PATH_END_CAPS_CHROMIUM
:
14592 hasValueError
= !validators_
->path_parameter_cap_values
.IsValid(value
);
14594 case GL_PATH_JOIN_STYLE_CHROMIUM
:
14595 hasValueError
= !validators_
->path_parameter_join_values
.IsValid(value
);
14598 DCHECK(!validators_
->path_parameter
.IsValid(pname
));
14599 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, pname
, "pname");
14600 return error::kNoError
;
14602 DCHECK(validators_
->path_parameter
.IsValid(pname
));
14604 if (hasValueError
) {
14605 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "value not correct");
14606 return error::kNoError
;
14609 glPathParameteriNV(service_id
, pname
, value
);
14610 return error::kNoError
;
14613 error::Error
GLES2DecoderImpl::HandleStencilFillPathCHROMIUM(
14614 uint32 immediate_data_size
,
14615 const void* cmd_data
) {
14616 static const char kFunctionName
[] = "glStencilFillPathCHROMIUM";
14617 const gles2::cmds::StencilFillPathCHROMIUM
& c
=
14618 *static_cast<const gles2::cmds::StencilFillPathCHROMIUM
*>(cmd_data
);
14619 if (!features().chromium_path_rendering
) {
14620 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14621 "function not available");
14622 return error::kNoError
;
14624 GLenum fill_mode
= static_cast<GLenum
>(c
.fillMode
);
14625 if (!validators_
->path_fill_mode
.IsValid(fill_mode
)) {
14626 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, fill_mode
, "fillMode");
14627 return error::kNoError
;
14629 GLuint mask
= static_cast<GLuint
>(c
.mask
);
14630 if ((fill_mode
== GL_COUNT_UP_CHROMIUM
||
14631 fill_mode
== GL_COUNT_DOWN_CHROMIUM
) &&
14632 GLES2Util::IsNPOT(mask
+ 1)) {
14633 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
,
14634 "mask + 1 is not power of two");
14635 return error::kNoError
;
14637 GLuint service_id
= 0;
14638 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
)) {
14639 // "If /path/ does not name an existing path object, the command does
14640 // nothing (and no error is generated)."
14641 // This holds for other rendering functions, too.
14642 return error::kNoError
;
14645 glStencilFillPathNV(service_id
, fill_mode
, mask
);
14646 return error::kNoError
;
14649 error::Error
GLES2DecoderImpl::HandleStencilStrokePathCHROMIUM(
14650 uint32 immediate_data_size
,
14651 const void* cmd_data
) {
14652 static const char kFunctionName
[] = "glStencilStrokePathCHROMIUM";
14653 const gles2::cmds::StencilStrokePathCHROMIUM
& c
=
14654 *static_cast<const gles2::cmds::StencilStrokePathCHROMIUM
*>(cmd_data
);
14655 if (!features().chromium_path_rendering
) {
14656 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14657 "function not available");
14658 return error::kNoError
;
14660 GLuint service_id
= 0;
14661 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
)) {
14662 return error::kNoError
;
14664 GLint reference
= static_cast<GLint
>(c
.reference
);
14665 GLuint mask
= static_cast<GLuint
>(c
.mask
);
14667 glStencilStrokePathNV(service_id
, reference
, mask
);
14668 return error::kNoError
;
14671 error::Error
GLES2DecoderImpl::HandleCoverFillPathCHROMIUM(
14672 uint32 immediate_data_size
,
14673 const void* cmd_data
) {
14674 static const char kFunctionName
[] = "glCoverFillPathCHROMIUM";
14675 const gles2::cmds::CoverFillPathCHROMIUM
& c
=
14676 *static_cast<const gles2::cmds::CoverFillPathCHROMIUM
*>(cmd_data
);
14677 if (!features().chromium_path_rendering
) {
14678 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14679 "function not available");
14680 return error::kNoError
;
14682 GLenum cover_mode
= static_cast<GLenum
>(c
.coverMode
);
14683 if (!validators_
->path_cover_mode
.IsValid(cover_mode
)) {
14684 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, cover_mode
, "coverMode");
14685 return error::kNoError
;
14687 GLuint service_id
= 0;
14688 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
))
14689 return error::kNoError
;
14692 glCoverFillPathNV(service_id
, cover_mode
);
14693 return error::kNoError
;
14696 error::Error
GLES2DecoderImpl::HandleCoverStrokePathCHROMIUM(
14697 uint32 immediate_data_size
,
14698 const void* cmd_data
) {
14699 static const char kFunctionName
[] = "glCoverStrokePathCHROMIUM";
14700 const gles2::cmds::CoverStrokePathCHROMIUM
& c
=
14701 *static_cast<const gles2::cmds::CoverStrokePathCHROMIUM
*>(cmd_data
);
14702 if (!features().chromium_path_rendering
) {
14703 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14704 "function not available");
14705 return error::kNoError
;
14707 GLenum cover_mode
= static_cast<GLenum
>(c
.coverMode
);
14708 if (!validators_
->path_cover_mode
.IsValid(cover_mode
)) {
14709 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, cover_mode
, "coverMode");
14710 return error::kNoError
;
14712 GLuint service_id
= 0;
14713 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
))
14714 return error::kNoError
;
14717 glCoverStrokePathNV(service_id
, cover_mode
);
14718 return error::kNoError
;
14721 error::Error
GLES2DecoderImpl::HandleStencilThenCoverFillPathCHROMIUM(
14722 uint32 immediate_data_size
,
14723 const void* cmd_data
) {
14724 static const char kFunctionName
[] = "glStencilThenCoverFillPathCHROMIUM";
14725 const gles2::cmds::StencilThenCoverFillPathCHROMIUM
& c
=
14726 *static_cast<const gles2::cmds::StencilThenCoverFillPathCHROMIUM
*>(
14728 if (!features().chromium_path_rendering
) {
14729 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14730 "function not available");
14731 return error::kNoError
;
14733 GLenum fill_mode
= static_cast<GLenum
>(c
.fillMode
);
14734 if (!validators_
->path_fill_mode
.IsValid(fill_mode
)) {
14735 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, fill_mode
, "fillMode");
14736 return error::kNoError
;
14738 GLuint mask
= static_cast<GLuint
>(c
.mask
);
14739 if ((fill_mode
== GL_COUNT_UP_CHROMIUM
||
14740 fill_mode
== GL_COUNT_DOWN_CHROMIUM
) &&
14741 GLES2Util::IsNPOT(mask
+ 1)) {
14742 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
,
14743 "mask + 1 is not power of two");
14744 return error::kNoError
;
14746 GLenum cover_mode
= static_cast<GLenum
>(c
.coverMode
);
14747 if (!validators_
->path_cover_mode
.IsValid(cover_mode
)) {
14748 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, cover_mode
, "coverMode");
14749 return error::kNoError
;
14751 GLuint service_id
= 0;
14752 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
))
14753 return error::kNoError
;
14756 glStencilThenCoverFillPathNV(service_id
, fill_mode
, mask
, cover_mode
);
14757 return error::kNoError
;
14760 error::Error
GLES2DecoderImpl::HandleStencilThenCoverStrokePathCHROMIUM(
14761 uint32 immediate_data_size
,
14762 const void* cmd_data
) {
14763 static const char kFunctionName
[] = "glStencilThenCoverStrokePathCHROMIUM";
14764 const gles2::cmds::StencilThenCoverStrokePathCHROMIUM
& c
=
14765 *static_cast<const gles2::cmds::StencilThenCoverStrokePathCHROMIUM
*>(
14767 if (!features().chromium_path_rendering
) {
14768 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14769 "function not available");
14770 return error::kNoError
;
14772 GLenum cover_mode
= static_cast<GLenum
>(c
.coverMode
);
14773 if (!validators_
->path_cover_mode
.IsValid(cover_mode
)) {
14774 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, cover_mode
, "coverMode");
14775 return error::kNoError
;
14777 GLuint service_id
= 0;
14778 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
))
14779 return error::kNoError
;
14781 GLint reference
= static_cast<GLint
>(c
.reference
);
14782 GLuint mask
= static_cast<GLuint
>(c
.mask
);
14784 glStencilThenCoverStrokePathNV(service_id
, reference
, mask
, cover_mode
);
14785 return error::kNoError
;
14788 // Include the auto-generated part of this file. We split this because it means
14789 // we can easily edit the non-auto generated parts right here in this file
14790 // instead of having to edit some template or the code generator.
14791 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
14793 } // namespace gles2