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 // Wrapper for TexStorage2DEXT.
1068 void DoTexStorage2DEXT(
1071 GLenum internal_format
,
1075 void DoProduceTextureCHROMIUM(GLenum target
, const GLbyte
* key
);
1076 void DoProduceTextureDirectCHROMIUM(GLuint texture
, GLenum target
,
1078 void ProduceTextureRef(std::string func_name
, TextureRef
* texture_ref
,
1079 GLenum target
, const GLbyte
* data
);
1081 void EnsureTextureForClientId(GLenum target
, GLuint client_id
);
1082 void DoConsumeTextureCHROMIUM(GLenum target
, const GLbyte
* key
);
1083 void DoCreateAndConsumeTextureCHROMIUM(GLenum target
, const GLbyte
* key
,
1086 bool DoIsValuebufferCHROMIUM(GLuint client_id
);
1087 void DoBindValueBufferCHROMIUM(GLenum target
, GLuint valuebuffer
);
1088 void DoSubscribeValueCHROMIUM(GLenum target
, GLenum subscription
);
1089 void DoPopulateSubscribedValuesCHROMIUM(GLenum target
);
1090 void DoUniformValueBufferCHROMIUM(GLint location
,
1092 GLenum subscription
);
1094 void DoBindTexImage2DCHROMIUM(
1097 void DoReleaseTexImage2DCHROMIUM(
1101 void DoTraceEndCHROMIUM(void);
1103 void DoDrawBuffersEXT(GLsizei count
, const GLenum
* bufs
);
1105 void DoLoseContextCHROMIUM(GLenum current
, GLenum other
);
1107 void DoFlushDriverCachesCHROMIUM(void);
1109 void DoMatrixLoadfCHROMIUM(GLenum matrix_mode
, const GLfloat
* matrix
);
1110 void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode
);
1112 // Creates a Program for the given program.
1113 Program
* CreateProgram(
1114 GLuint client_id
, GLuint service_id
) {
1115 return program_manager()->CreateProgram(client_id
, service_id
);
1118 // Gets the program info for the given program. Returns NULL if none exists.
1119 Program
* GetProgram(GLuint client_id
) {
1120 return program_manager()->GetProgram(client_id
);
1124 void LogClientServiceMapping(
1125 const char* /* function_name */,
1126 GLuint
/* client_id */,
1127 GLuint
/* service_id */) {
1129 template<typename T
>
1130 void LogClientServiceForInfo(
1131 T
* /* info */, GLuint
/* client_id */, const char* /* function_name */) {
1134 void LogClientServiceMapping(
1135 const char* function_name
, GLuint client_id
, GLuint service_id
) {
1136 if (service_logging_
) {
1137 VLOG(1) << "[" << logger_
.GetLogPrefix() << "] " << function_name
1138 << ": client_id = " << client_id
1139 << ", service_id = " << service_id
;
1142 template<typename T
>
1143 void LogClientServiceForInfo(
1144 T
* info
, GLuint client_id
, const char* function_name
) {
1146 LogClientServiceMapping(function_name
, client_id
, info
->service_id());
1151 // Gets the program info for the given program. If it's not a program
1152 // generates a GL error. Returns NULL if not program.
1153 Program
* GetProgramInfoNotShader(
1154 GLuint client_id
, const char* function_name
) {
1155 Program
* program
= GetProgram(client_id
);
1157 if (GetShader(client_id
)) {
1159 GL_INVALID_OPERATION
, function_name
, "shader passed for program");
1161 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown program");
1164 LogClientServiceForInfo(program
, client_id
, function_name
);
1169 // Creates a Shader for the given shader.
1170 Shader
* CreateShader(
1173 GLenum shader_type
) {
1174 return shader_manager()->CreateShader(
1175 client_id
, service_id
, shader_type
);
1178 // Gets the shader info for the given shader. Returns NULL if none exists.
1179 Shader
* GetShader(GLuint client_id
) {
1180 return shader_manager()->GetShader(client_id
);
1183 // Gets the shader info for the given shader. If it's not a shader generates a
1184 // GL error. Returns NULL if not shader.
1185 Shader
* GetShaderInfoNotProgram(
1186 GLuint client_id
, const char* function_name
) {
1187 Shader
* shader
= GetShader(client_id
);
1189 if (GetProgram(client_id
)) {
1191 GL_INVALID_OPERATION
, function_name
, "program passed for shader");
1194 GL_INVALID_VALUE
, function_name
, "unknown shader");
1197 LogClientServiceForInfo(shader
, client_id
, function_name
);
1201 // Creates a buffer info for the given buffer.
1202 void CreateBuffer(GLuint client_id
, GLuint service_id
) {
1203 return buffer_manager()->CreateBuffer(client_id
, service_id
);
1206 // Gets the buffer info for the given buffer.
1207 Buffer
* GetBuffer(GLuint client_id
) {
1208 Buffer
* buffer
= buffer_manager()->GetBuffer(client_id
);
1212 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1213 // on glDeleteBuffers so we can make sure the user does not try to render
1214 // with deleted buffers.
1215 void RemoveBuffer(GLuint client_id
);
1217 // Creates a framebuffer info for the given framebuffer.
1218 void CreateFramebuffer(GLuint client_id
, GLuint service_id
) {
1219 return framebuffer_manager()->CreateFramebuffer(client_id
, service_id
);
1222 // Gets the framebuffer info for the given framebuffer.
1223 Framebuffer
* GetFramebuffer(GLuint client_id
) {
1224 return framebuffer_manager()->GetFramebuffer(client_id
);
1227 // Removes the framebuffer info for the given framebuffer.
1228 void RemoveFramebuffer(GLuint client_id
) {
1229 framebuffer_manager()->RemoveFramebuffer(client_id
);
1232 // Creates a renderbuffer info for the given renderbuffer.
1233 void CreateRenderbuffer(GLuint client_id
, GLuint service_id
) {
1234 return renderbuffer_manager()->CreateRenderbuffer(
1235 client_id
, service_id
);
1238 // Gets the renderbuffer info for the given renderbuffer.
1239 Renderbuffer
* GetRenderbuffer(GLuint client_id
) {
1240 return renderbuffer_manager()->GetRenderbuffer(client_id
);
1243 // Removes the renderbuffer info for the given renderbuffer.
1244 void RemoveRenderbuffer(GLuint client_id
) {
1245 renderbuffer_manager()->RemoveRenderbuffer(client_id
);
1248 // Creates a valuebuffer info for the given valuebuffer.
1249 void CreateValuebuffer(GLuint client_id
) {
1250 return valuebuffer_manager()->CreateValuebuffer(client_id
);
1253 // Gets the valuebuffer info for a given valuebuffer.
1254 Valuebuffer
* GetValuebuffer(GLuint client_id
) {
1255 return valuebuffer_manager()->GetValuebuffer(client_id
);
1258 // Removes the valuebuffer info for the given valuebuffer.
1259 void RemoveValuebuffer(GLuint client_id
) {
1260 valuebuffer_manager()->RemoveValuebuffer(client_id
);
1263 // Gets the vertex attrib manager for the given vertex array.
1264 VertexAttribManager
* GetVertexAttribManager(GLuint client_id
) {
1265 VertexAttribManager
* info
=
1266 vertex_array_manager()->GetVertexAttribManager(client_id
);
1270 // Removes the vertex attrib manager for the given vertex array.
1271 void RemoveVertexAttribManager(GLuint client_id
) {
1272 vertex_array_manager()->RemoveVertexAttribManager(client_id
);
1275 // Creates a vertex attrib manager for the given vertex array.
1276 scoped_refptr
<VertexAttribManager
> CreateVertexAttribManager(
1279 bool client_visible
) {
1280 return vertex_array_manager()->CreateVertexAttribManager(
1281 client_id
, service_id
, group_
->max_vertex_attribs(), client_visible
);
1284 void DoBindAttribLocation(GLuint client_id
, GLuint index
, const char* name
);
1285 void DoBindUniformLocationCHROMIUM(
1286 GLuint client_id
, GLint location
, const char* name
);
1288 error::Error
GetAttribLocationHelper(
1289 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1290 const std::string
& name_str
);
1292 error::Error
GetUniformLocationHelper(
1293 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1294 const std::string
& name_str
);
1296 error::Error
GetFragDataLocationHelper(
1297 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1298 const std::string
& name_str
);
1300 // Wrapper for glShaderSource.
1301 void DoShaderSource(
1302 GLuint client_id
, GLsizei count
, const char** data
, const GLint
* length
);
1304 // Wrapper for glTransformFeedbackVaryings.
1305 void DoTransformFeedbackVaryings(
1306 GLuint client_program_id
, GLsizei count
, const char* const* varyings
,
1307 GLenum buffer_mode
);
1309 // Clear any textures used by the current program.
1310 bool ClearUnclearedTextures();
1312 // Clears any uncleared attachments attached to the given frame buffer.
1313 // Returns false if there was a generated GL error.
1314 void ClearUnclearedAttachments(GLenum target
, Framebuffer
* framebuffer
);
1316 // overridden from GLES2Decoder
1317 bool ClearLevel(Texture
* texture
,
1325 int height
) override
;
1327 // Restore all GL state that affects clearing.
1328 void RestoreClearState();
1330 // Remembers the state of some capabilities.
1331 // Returns: true if glEnable/glDisable should actually be called.
1332 bool SetCapabilityState(GLenum cap
, bool enabled
);
1334 // Check that the currently bound framebuffers are valid.
1335 // Generates GL error if not.
1336 bool CheckBoundFramebuffersValid(const char* func_name
);
1338 // Check that the currently bound read framebuffer has a color image
1339 // attached. Generates GL error if not.
1340 bool CheckBoundReadFramebufferColorAttachment(const char* func_name
);
1342 // Check that the currently bound read framebuffer's color image
1343 // isn't the target texture of the glCopyTex{Sub}Image2D.
1344 bool FormsTextureCopyingFeedbackLoop(TextureRef
* texture
, GLint level
);
1346 // Check if a framebuffer meets our requirements.
1347 bool CheckFramebufferValid(
1348 Framebuffer
* framebuffer
,
1350 const char* func_name
);
1352 // Check if the current valuebuffer exists and is valid. If not generates
1353 // the appropriate GL error. Returns true if the current valuebuffer is in
1355 bool CheckCurrentValuebuffer(const char* function_name
);
1357 // Check if the current valuebuffer exists and is valiud and that the
1358 // value buffer is actually subscribed to the given subscription
1359 bool CheckCurrentValuebufferForSubscription(GLenum subscription
,
1360 const char* function_name
);
1362 // Check if the location can be used for the given subscription target. If not
1363 // generates the appropriate GL error. Returns true if the location is usable
1364 bool CheckSubscriptionTarget(GLint location
,
1365 GLenum subscription
,
1366 const char* function_name
);
1368 // Checks if the current program exists and is valid. If not generates the
1369 // appropriate GL error. Returns true if the current program is in a usable
1371 bool CheckCurrentProgram(const char* function_name
);
1373 // Checks if the current program exists and is valid and that location is not
1374 // -1. If the current program is not valid generates the appropriate GL
1375 // error. Returns true if the current program is in a usable state and
1376 // location is not -1.
1377 bool CheckCurrentProgramForUniform(GLint location
, const char* function_name
);
1379 // Checks if the current program samples a texture that is also the color
1380 // image of the current bound framebuffer, i.e., the source and destination
1381 // of the draw operation are the same.
1382 bool CheckDrawingFeedbackLoops();
1384 // Checks if |api_type| is valid for the given uniform
1385 // If the api type is not valid generates the appropriate GL
1386 // error. Returns true if |api_type| is valid for the uniform
1387 bool CheckUniformForApiType(const Program::UniformInfo
* info
,
1388 const char* function_name
,
1389 Program::UniformApiType api_type
);
1391 // Gets the type of a uniform for a location in the current program. Sets GL
1392 // errors if the current program is not valid. Returns true if the current
1393 // program is valid and the location exists. Adjusts count so it
1394 // does not overflow the uniform.
1395 bool PrepForSetUniformByLocation(GLint fake_location
,
1396 const char* function_name
,
1397 Program::UniformApiType api_type
,
1398 GLint
* real_location
,
1402 // Gets the service id for any simulated backbuffer fbo.
1403 GLuint
GetBackbufferServiceId() const;
1405 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1406 bool GetHelper(GLenum pname
, GLint
* params
, GLsizei
* num_written
);
1408 // Helper for glGetVertexAttrib
1409 void GetVertexAttribHelper(
1410 const VertexAttrib
* attrib
, GLenum pname
, GLint
* param
);
1412 // Wrapper for glActiveTexture
1413 void DoActiveTexture(GLenum texture_unit
);
1415 // Wrapper for glAttachShader
1416 void DoAttachShader(GLuint client_program_id
, GLint client_shader_id
);
1418 // Wrapper for glBindBuffer since we need to track the current targets.
1419 void DoBindBuffer(GLenum target
, GLuint buffer
);
1421 // Wrapper for glBindFramebuffer since we need to track the current targets.
1422 void DoBindFramebuffer(GLenum target
, GLuint framebuffer
);
1424 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1425 void DoBindRenderbuffer(GLenum target
, GLuint renderbuffer
);
1427 // Wrapper for glBindTexture since we need to track the current targets.
1428 void DoBindTexture(GLenum target
, GLuint texture
);
1430 // Wrapper for glBindVertexArrayOES
1431 void DoBindVertexArrayOES(GLuint array
);
1432 void EmulateVertexArrayState();
1434 // Wrapper for glBlitFramebufferCHROMIUM.
1435 void DoBlitFramebufferCHROMIUM(
1436 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
1437 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
1438 GLbitfield mask
, GLenum filter
);
1440 // Wrapper for glBufferSubData.
1441 void DoBufferSubData(
1442 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
);
1444 // Wrapper for glCheckFramebufferStatus
1445 GLenum
DoCheckFramebufferStatus(GLenum target
);
1447 // Wrapper for glClear
1448 error::Error
DoClear(GLbitfield mask
);
1450 // Wrappers for various state.
1451 void DoDepthRangef(GLclampf znear
, GLclampf zfar
);
1452 void DoSampleCoverage(GLclampf value
, GLboolean invert
);
1454 // Wrapper for glCompileShader.
1455 void DoCompileShader(GLuint shader
);
1457 // Wrapper for glDetachShader
1458 void DoDetachShader(GLuint client_program_id
, GLint client_shader_id
);
1460 // Wrapper for glDisable
1461 void DoDisable(GLenum cap
);
1463 // Wrapper for glDisableVertexAttribArray.
1464 void DoDisableVertexAttribArray(GLuint index
);
1466 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1468 void DoDiscardFramebufferEXT(GLenum target
,
1469 GLsizei numAttachments
,
1470 const GLenum
* attachments
);
1472 // Wrapper for glEnable
1473 void DoEnable(GLenum cap
);
1475 // Wrapper for glEnableVertexAttribArray.
1476 void DoEnableVertexAttribArray(GLuint index
);
1478 // Wrapper for glFinish.
1481 // Wrapper for glFlush.
1484 // Wrapper for glFramebufferRenderbufffer.
1485 void DoFramebufferRenderbuffer(
1486 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
1487 GLuint renderbuffer
);
1489 // Wrapper for glFramebufferTexture2D.
1490 void DoFramebufferTexture2D(
1491 GLenum target
, GLenum attachment
, GLenum textarget
, GLuint texture
,
1494 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1495 void DoFramebufferTexture2DMultisample(
1496 GLenum target
, GLenum attachment
, GLenum textarget
,
1497 GLuint texture
, GLint level
, GLsizei samples
);
1499 // Common implementation for both DoFramebufferTexture2D wrappers.
1500 void DoFramebufferTexture2DCommon(const char* name
,
1501 GLenum target
, GLenum attachment
, GLenum textarget
,
1502 GLuint texture
, GLint level
, GLsizei samples
);
1504 // Wrapper for glFramebufferTextureLayer.
1505 void DoFramebufferTextureLayer(
1506 GLenum target
, GLenum attachment
, GLuint texture
, GLint level
,
1509 // Wrapper for glGenerateMipmap
1510 void DoGenerateMipmap(GLenum target
);
1512 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1513 // to account for different pname values defined in different extension
1515 GLenum
AdjustGetPname(GLenum pname
);
1517 // Wrapper for DoGetBooleanv.
1518 void DoGetBooleanv(GLenum pname
, GLboolean
* params
);
1520 // Wrapper for DoGetFloatv.
1521 void DoGetFloatv(GLenum pname
, GLfloat
* params
);
1523 // Wrapper for glGetFramebufferAttachmentParameteriv.
1524 void DoGetFramebufferAttachmentParameteriv(
1525 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
);
1527 // Wrapper for glGetInteger64v.
1528 void DoGetInteger64v(GLenum pname
, GLint64
* params
);
1530 // Wrapper for glGetIntegerv.
1531 void DoGetIntegerv(GLenum pname
, GLint
* params
);
1533 // Gets the max value in a range in a buffer.
1534 GLuint
DoGetMaxValueInBufferCHROMIUM(
1535 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
);
1537 // Wrapper for glGetBufferParameteri64v.
1538 void DoGetBufferParameteri64v(
1539 GLenum target
, GLenum pname
, GLint64
* params
);
1541 // Wrapper for glGetBufferParameteriv.
1542 void DoGetBufferParameteriv(
1543 GLenum target
, GLenum pname
, GLint
* params
);
1545 // Wrapper for glGetProgramiv.
1546 void DoGetProgramiv(
1547 GLuint program_id
, GLenum pname
, GLint
* params
);
1549 // Wrapper for glRenderbufferParameteriv.
1550 void DoGetRenderbufferParameteriv(
1551 GLenum target
, GLenum pname
, GLint
* params
);
1553 // Wrapper for glGetShaderiv
1554 void DoGetShaderiv(GLuint shader
, GLenum pname
, GLint
* params
);
1556 // Wrappers for glGetTexParameter.
1557 void DoGetTexParameterfv(GLenum target
, GLenum pname
, GLfloat
* params
);
1558 void DoGetTexParameteriv(GLenum target
, GLenum pname
, GLint
* params
);
1559 void InitTextureMaxAnisotropyIfNeeded(GLenum target
, GLenum pname
);
1561 // Wrappers for glGetVertexAttrib.
1562 template <typename T
>
1563 void DoGetVertexAttribImpl(GLuint index
, GLenum pname
, T
* params
);
1564 void DoGetVertexAttribfv(GLuint index
, GLenum pname
, GLfloat
* params
);
1565 void DoGetVertexAttribiv(GLuint index
, GLenum pname
, GLint
* params
);
1566 void DoGetVertexAttribIiv(GLuint index
, GLenum pname
, GLint
* params
);
1567 void DoGetVertexAttribIuiv(GLuint index
, GLenum pname
, GLuint
* params
);
1569 // Wrappers for glIsXXX functions.
1570 bool DoIsEnabled(GLenum cap
);
1571 bool DoIsBuffer(GLuint client_id
);
1572 bool DoIsFramebuffer(GLuint client_id
);
1573 bool DoIsProgram(GLuint client_id
);
1574 bool DoIsRenderbuffer(GLuint client_id
);
1575 bool DoIsShader(GLuint client_id
);
1576 bool DoIsTexture(GLuint client_id
);
1577 bool DoIsVertexArrayOES(GLuint client_id
);
1578 bool DoIsPathCHROMIUM(GLuint client_id
);
1580 // Wrapper for glLinkProgram
1581 void DoLinkProgram(GLuint program
);
1583 // Wrapper for glReadBuffer
1584 void DoReadBuffer(GLenum src
);
1586 // Wrapper for glRenderbufferStorage.
1587 void DoRenderbufferStorage(
1588 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
);
1590 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1591 void DoRenderbufferStorageMultisampleCHROMIUM(
1592 GLenum target
, GLsizei samples
, GLenum internalformat
,
1593 GLsizei width
, GLsizei height
);
1595 // Handler for glRenderbufferStorageMultisampleEXT
1596 // (multisampled_render_to_texture).
1597 void DoRenderbufferStorageMultisampleEXT(
1598 GLenum target
, GLsizei samples
, GLenum internalformat
,
1599 GLsizei width
, GLsizei height
);
1601 // Common validation for multisample extensions.
1602 bool ValidateRenderbufferStorageMultisample(GLsizei samples
,
1603 GLenum internalformat
,
1607 // Verifies that the currently bound multisample renderbuffer is valid
1608 // Very slow! Only done on platforms with driver bugs that return invalid
1609 // buffers under memory pressure
1610 bool VerifyMultisampleRenderbufferIntegrity(
1611 GLuint renderbuffer
, GLenum format
);
1613 // Wrapper for glReleaseShaderCompiler.
1614 void DoReleaseShaderCompiler() { }
1616 // Wrappers for glSamplerParameter*v functions.
1617 void DoSamplerParameterfv(
1618 GLuint sampler
, GLenum pname
, const GLfloat
* params
);
1619 void DoSamplerParameteriv(GLuint sampler
, GLenum pname
, const GLint
* params
);
1621 // Wrappers for glTexParameter functions.
1622 void DoTexParameterf(GLenum target
, GLenum pname
, GLfloat param
);
1623 void DoTexParameteri(GLenum target
, GLenum pname
, GLint param
);
1624 void DoTexParameterfv(GLenum target
, GLenum pname
, const GLfloat
* params
);
1625 void DoTexParameteriv(GLenum target
, GLenum pname
, const GLint
* params
);
1627 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1628 // spec only these 2 functions can be used to set sampler uniforms.
1629 void DoUniform1i(GLint fake_location
, GLint v0
);
1630 void DoUniform1iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1631 void DoUniform2iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1632 void DoUniform3iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1633 void DoUniform4iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1635 // Wrappers for glUniformfv because some drivers don't correctly accept
1637 void DoUniform1fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1638 void DoUniform2fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1639 void DoUniform3fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1640 void DoUniform4fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1642 void DoUniformMatrix2fv(
1643 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1644 const GLfloat
* value
);
1645 void DoUniformMatrix3fv(
1646 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1647 const GLfloat
* value
);
1648 void DoUniformMatrix4fv(
1649 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1650 const GLfloat
* value
);
1652 template <typename T
>
1653 bool SetVertexAttribValue(
1654 const char* function_name
, GLuint index
, const T
* value
);
1656 // Wrappers for glVertexAttrib??
1657 void DoVertexAttrib1f(GLuint index
, GLfloat v0
);
1658 void DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
);
1659 void DoVertexAttrib3f(GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
);
1660 void DoVertexAttrib4f(
1661 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
);
1662 void DoVertexAttrib1fv(GLuint index
, const GLfloat
* v
);
1663 void DoVertexAttrib2fv(GLuint index
, const GLfloat
* v
);
1664 void DoVertexAttrib3fv(GLuint index
, const GLfloat
* v
);
1665 void DoVertexAttrib4fv(GLuint index
, const GLfloat
* v
);
1666 void DoVertexAttribI4i(GLuint index
, GLint v0
, GLint v1
, GLint v2
, GLint v3
);
1667 void DoVertexAttribI4iv(GLuint index
, const GLint
* v
);
1668 void DoVertexAttribI4ui(
1669 GLuint index
, GLuint v0
, GLuint v1
, GLuint v2
, GLuint v3
);
1670 void DoVertexAttribI4uiv(GLuint index
, const GLuint
* v
);
1672 // Wrapper for glViewport
1673 void DoViewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
1675 // Wrapper for glUseProgram
1676 void DoUseProgram(GLuint program
);
1678 // Wrapper for glValidateProgram.
1679 void DoValidateProgram(GLuint program_client_id
);
1681 void DoInsertEventMarkerEXT(GLsizei length
, const GLchar
* marker
);
1682 void DoPushGroupMarkerEXT(GLsizei length
, const GLchar
* group
);
1683 void DoPopGroupMarkerEXT(void);
1685 // Gets the number of values that will be returned by glGetXXX. Returns
1686 // false if pname is unknown.
1687 bool GetNumValuesReturnedForGLGet(GLenum pname
, GLsizei
* num_values
);
1689 // Checks if the current program and vertex attributes are valid for drawing.
1691 const char* function_name
, GLuint max_vertex_accessed
, bool instanced
,
1694 // Returns true if successful, simulated will be true if attrib0 was
1696 bool SimulateAttrib0(
1697 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
);
1698 void RestoreStateForAttrib(GLuint attrib
, bool restore_array_binding
);
1700 // If an image is bound to texture, this will call Will/DidUseTexImage
1702 void DoWillUseTexImageIfNeeded(Texture
* texture
, GLenum textarget
);
1703 void DoDidUseTexImageIfNeeded(Texture
* texture
, GLenum textarget
);
1705 // Returns false if textures were replaced.
1706 bool PrepareTexturesForRender();
1707 void RestoreStateForTextures();
1709 // Returns true if GL_FIXED attribs were simulated.
1710 bool SimulateFixedAttribs(
1711 const char* function_name
,
1712 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
);
1713 void RestoreStateForSimulatedFixedAttribs();
1715 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1716 // cases (primcount is always 1 for non-instanced).
1717 error::Error
DoDrawArrays(
1718 const char* function_name
,
1719 bool instanced
, GLenum mode
, GLint first
, GLsizei count
,
1721 error::Error
DoDrawElements(
1722 const char* function_name
,
1723 bool instanced
, GLenum mode
, GLsizei count
, GLenum type
,
1724 int32 offset
, GLsizei primcount
);
1726 GLenum
GetBindTargetForSamplerType(GLenum type
) {
1727 DCHECK(type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_CUBE
||
1728 type
== GL_SAMPLER_EXTERNAL_OES
|| type
== GL_SAMPLER_2D_RECT_ARB
);
1731 return GL_TEXTURE_2D
;
1732 case GL_SAMPLER_CUBE
:
1733 return GL_TEXTURE_CUBE_MAP
;
1734 case GL_SAMPLER_EXTERNAL_OES
:
1735 return GL_TEXTURE_EXTERNAL_OES
;
1736 case GL_SAMPLER_2D_RECT_ARB
:
1737 return GL_TEXTURE_RECTANGLE_ARB
;
1744 // Gets the framebuffer info for a particular target.
1745 Framebuffer
* GetFramebufferInfoForTarget(GLenum target
) {
1746 Framebuffer
* framebuffer
= NULL
;
1748 case GL_FRAMEBUFFER
:
1749 case GL_DRAW_FRAMEBUFFER_EXT
:
1750 framebuffer
= framebuffer_state_
.bound_draw_framebuffer
.get();
1752 case GL_READ_FRAMEBUFFER_EXT
:
1753 framebuffer
= framebuffer_state_
.bound_read_framebuffer
.get();
1762 Renderbuffer
* GetRenderbufferInfoForTarget(
1764 Renderbuffer
* renderbuffer
= NULL
;
1766 case GL_RENDERBUFFER
:
1767 renderbuffer
= state_
.bound_renderbuffer
.get();
1773 return renderbuffer
;
1776 // Validates the program and location for a glGetUniform call and returns
1777 // a SizeResult setup to receive the result. Returns true if glGetUniform
1778 // should be called.
1780 bool GetUniformSetup(GLuint program
,
1781 GLint fake_location
,
1784 error::Error
* error
,
1785 GLint
* real_location
,
1787 SizedResult
<T
>** result
,
1788 GLenum
* result_type
,
1789 GLsizei
* result_size
);
1791 bool WasContextLost() const override
;
1792 bool WasContextLostByRobustnessExtension() const override
;
1793 void MarkContextLost(error::ContextLostReason reason
) override
;
1794 bool CheckResetStatus();
1796 #if defined(OS_MACOSX)
1797 void ReleaseIOSurfaceForTexture(GLuint texture_id
);
1800 bool GetCompressedTexSizeInBytes(
1801 const char* function_name
, GLsizei width
, GLsizei height
, GLsizei depth
,
1802 GLenum format
, GLsizei
* size_in_bytes
);
1804 bool ValidateCompressedTexDimensions(
1805 const char* function_name
, GLenum target
, GLint level
,
1806 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
);
1807 bool ValidateCompressedTexFuncData(
1808 const char* function_name
, GLsizei width
, GLsizei height
, GLsizei depth
,
1809 GLenum format
, GLsizei size
);
1810 bool ValidateCompressedTexSubDimensions(
1811 const char* function_name
,
1812 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
1813 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
,
1815 bool ValidateCopyTextureCHROMIUM(const char* function_name
,
1817 TextureRef
* source_texture_ref
,
1818 TextureRef
* dest_texture_ref
,
1819 GLenum dest_internal_format
);
1820 bool ValidateCompressedCopyTextureCHROMIUM(const char* function_name
,
1822 TextureRef
* source_texture_ref
,
1823 TextureRef
* dest_texture_ref
);
1825 void RenderWarning(const char* filename
, int line
, const std::string
& msg
);
1826 void PerformanceWarning(
1827 const char* filename
, int line
, const std::string
& msg
);
1829 const FeatureInfo::FeatureFlags
& features() const {
1830 return feature_info_
->feature_flags();
1833 const FeatureInfo::Workarounds
& workarounds() const {
1834 return feature_info_
->workarounds();
1837 bool ShouldDeferDraws() {
1838 return !offscreen_target_frame_buffer_
.get() &&
1839 framebuffer_state_
.bound_draw_framebuffer
.get() == NULL
&&
1840 surface_
->DeferDraws();
1843 bool ShouldDeferReads() {
1844 return !offscreen_target_frame_buffer_
.get() &&
1845 framebuffer_state_
.bound_read_framebuffer
.get() == NULL
&&
1846 surface_
->DeferDraws();
1849 bool IsRobustnessSupported() {
1850 return has_robustness_extension_
&&
1851 context_
->WasAllocatedUsingRobustnessExtension();
1854 error::Error
WillAccessBoundFramebufferForDraw() {
1855 if (ShouldDeferDraws())
1856 return error::kDeferCommandUntilLater
;
1857 if (!offscreen_target_frame_buffer_
.get() &&
1858 !framebuffer_state_
.bound_draw_framebuffer
.get() &&
1859 !surface_
->SetBackbufferAllocation(true))
1860 return error::kLostContext
;
1861 return error::kNoError
;
1864 error::Error
WillAccessBoundFramebufferForRead() {
1865 if (ShouldDeferReads())
1866 return error::kDeferCommandUntilLater
;
1867 if (!offscreen_target_frame_buffer_
.get() &&
1868 !framebuffer_state_
.bound_read_framebuffer
.get() &&
1869 !surface_
->SetBackbufferAllocation(true))
1870 return error::kLostContext
;
1871 return error::kNoError
;
1874 bool BackBufferHasAlpha() const {
1875 if (back_buffer_draw_buffer_
== GL_NONE
)
1877 if (offscreen_target_frame_buffer_
.get()) {
1878 return (offscreen_target_color_format_
== GL_RGBA
||
1879 offscreen_target_color_format_
== GL_RGBA8
);
1881 return (back_buffer_color_format_
== GL_RGBA
||
1882 back_buffer_color_format_
== GL_RGBA8
);
1885 // Set remaining commands to process to 0 to force DoCommands to return
1886 // and allow context preemption and GPU watchdog checks in GpuScheduler().
1887 void ExitCommandProcessingEarly() { commands_to_process_
= 0; }
1889 void ProcessPendingReadPixels(bool did_finish
);
1890 void FinishReadPixels(const cmds::ReadPixels
& c
, GLuint buffer
);
1892 // Generate a member function prototype for each command in an automated and
1894 #define GLES2_CMD_OP(name) \
1895 Error Handle##name(uint32 immediate_data_size, const void* data);
1897 GLES2_COMMAND_LIST(GLES2_CMD_OP
)
1901 // The GL context this decoder renders to on behalf of the client.
1902 scoped_refptr
<gfx::GLSurface
> surface_
;
1903 scoped_refptr
<gfx::GLContext
> context_
;
1905 // The ContextGroup for this decoder uses to track resources.
1906 scoped_refptr
<ContextGroup
> group_
;
1908 DebugMarkerManager debug_marker_manager_
;
1911 // All the state for this context.
1912 ContextState state_
;
1914 // Current width and height of the offscreen frame buffer.
1915 gfx::Size offscreen_size_
;
1917 // Util to help with GL.
1920 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1921 GLuint attrib_0_buffer_id_
;
1923 // The value currently in attrib_0.
1924 Vec4 attrib_0_value_
;
1926 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1927 bool attrib_0_buffer_matches_value_
;
1929 // The size of attrib 0.
1930 GLsizei attrib_0_size_
;
1932 // The buffer used to simulate GL_FIXED attribs.
1933 GLuint fixed_attrib_buffer_id_
;
1935 // The size of fiixed attrib buffer.
1936 GLsizei fixed_attrib_buffer_size_
;
1938 // The offscreen frame buffer that the client renders to. With EGL, the
1939 // depth and stencil buffers are separate. With regular GL there is a single
1940 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1941 // offscreen_target_stencil_render_buffer_ is unused.
1942 scoped_ptr
<BackFramebuffer
> offscreen_target_frame_buffer_
;
1943 scoped_ptr
<BackTexture
> offscreen_target_color_texture_
;
1944 scoped_ptr
<BackRenderbuffer
> offscreen_target_color_render_buffer_
;
1945 scoped_ptr
<BackRenderbuffer
> offscreen_target_depth_render_buffer_
;
1946 scoped_ptr
<BackRenderbuffer
> offscreen_target_stencil_render_buffer_
;
1947 GLenum offscreen_target_color_format_
;
1948 GLenum offscreen_target_depth_format_
;
1949 GLenum offscreen_target_stencil_format_
;
1950 GLsizei offscreen_target_samples_
;
1951 GLboolean offscreen_target_buffer_preserved_
;
1953 // The copy that is saved when SwapBuffers is called.
1954 scoped_ptr
<BackFramebuffer
> offscreen_saved_frame_buffer_
;
1955 scoped_ptr
<BackTexture
> offscreen_saved_color_texture_
;
1956 scoped_refptr
<TextureRef
>
1957 offscreen_saved_color_texture_info_
;
1959 // The copy that is used as the destination for multi-sample resolves.
1960 scoped_ptr
<BackFramebuffer
> offscreen_resolved_frame_buffer_
;
1961 scoped_ptr
<BackTexture
> offscreen_resolved_color_texture_
;
1962 GLenum offscreen_saved_color_format_
;
1964 scoped_ptr
<QueryManager
> query_manager_
;
1966 scoped_ptr
<VertexArrayManager
> vertex_array_manager_
;
1968 scoped_ptr
<ImageManager
> image_manager_
;
1970 base::Callback
<void(gfx::Size
, float)> resize_callback_
;
1972 WaitSyncPointCallback wait_sync_point_callback_
;
1974 ShaderCacheCallback shader_cache_callback_
;
1976 scoped_ptr
<AsyncPixelTransferManager
> async_pixel_transfer_manager_
;
1978 // The format of the back buffer_
1979 GLenum back_buffer_color_format_
;
1980 bool back_buffer_has_depth_
;
1981 bool back_buffer_has_stencil_
;
1983 // Tracks read buffer and draw buffer for backbuffer, whether it's onscreen
1985 // TODO(zmo): when ES3 APIs are exposed to Nacl, make sure read_buffer_
1986 // setting is set correctly when SwapBuffers().
1987 GLenum back_buffer_read_buffer_
;
1988 GLenum back_buffer_draw_buffer_
;
1992 // Backbuffer attachments that are currently undefined.
1993 uint32 backbuffer_needs_clear_bits_
;
1995 // The current decoder error communicates the decoder error through command
1996 // processing functions that do not return the error value. Should be set only
1997 // if not returning an error.
1998 error::Error current_decoder_error_
;
2000 bool use_shader_translator_
;
2001 scoped_refptr
<ShaderTranslatorInterface
> vertex_translator_
;
2002 scoped_refptr
<ShaderTranslatorInterface
> fragment_translator_
;
2004 DisallowedFeatures disallowed_features_
;
2006 // Cached from ContextGroup
2007 const Validators
* validators_
;
2008 scoped_refptr
<FeatureInfo
> feature_info_
;
2012 // Number of commands remaining to be processed in DoCommands().
2013 int commands_to_process_
;
2015 bool has_robustness_extension_
;
2016 error::ContextLostReason context_lost_reason_
;
2017 bool context_was_lost_
;
2018 bool reset_by_robustness_extension_
;
2019 bool supports_post_sub_buffer_
;
2021 // Indicates whether this is a context for WebGL1, WebGL2, or others.
2025 unsigned webgl_version_
;
2027 // These flags are used to override the state of the shared feature_info_
2028 // member. Because the same FeatureInfo instance may be shared among many
2029 // contexts, the assumptions on the availablity of extensions in WebGL
2030 // contexts may be broken. These flags override the shared state to preserve
2032 bool derivatives_explicitly_enabled_
;
2033 bool frag_depth_explicitly_enabled_
;
2034 bool draw_buffers_explicitly_enabled_
;
2035 bool shader_texture_lod_explicitly_enabled_
;
2037 bool compile_shader_always_succeeds_
;
2039 // An optional behaviour to lose the context and group when OOM.
2040 bool lose_context_when_out_of_memory_
;
2043 bool service_logging_
;
2045 #if defined(OS_MACOSX)
2046 typedef std::map
<GLuint
, IOSurfaceRef
> TextureToIOSurfaceMap
;
2047 TextureToIOSurfaceMap texture_to_io_surface_map_
;
2050 scoped_ptr
<CopyTextureCHROMIUMResourceManager
> copy_texture_CHROMIUM_
;
2051 scoped_ptr
<ClearFramebufferResourceManager
> clear_framebuffer_blit_
;
2053 // Cached values of the currently assigned viewport dimensions.
2054 GLsizei viewport_max_width_
;
2055 GLsizei viewport_max_height_
;
2057 // Command buffer stats.
2058 base::TimeDelta total_processing_commands_time_
;
2060 // States related to each manager.
2061 DecoderTextureState texture_state_
;
2062 DecoderFramebufferState framebuffer_state_
;
2064 scoped_ptr
<GPUTracer
> gpu_tracer_
;
2065 scoped_ptr
<GPUStateTracer
> gpu_state_tracer_
;
2066 const unsigned char* cb_command_trace_category_
;
2067 const unsigned char* gpu_decoder_category_
;
2068 int gpu_trace_level_
;
2069 bool gpu_trace_commands_
;
2070 bool gpu_debug_commands_
;
2072 std::queue
<linked_ptr
<FenceCallback
> > pending_readpixel_fences_
;
2074 // Used to validate multisample renderbuffers if needed
2075 GLuint validation_texture_
;
2076 GLuint validation_fbo_multisample_
;
2077 GLuint validation_fbo_
;
2079 typedef gpu::gles2::GLES2Decoder::Error (GLES2DecoderImpl::*CmdHandler
)(
2080 uint32 immediate_data_size
,
2083 // A struct to hold info about each command.
2084 struct CommandInfo
{
2085 CmdHandler cmd_handler
;
2086 uint8 arg_flags
; // How to handle the arguments for this command
2087 uint8 cmd_flags
; // How to handle this command
2088 uint16 arg_count
; // How many arguments are expected for this command.
2091 // A table of CommandInfo for all the commands.
2092 static const CommandInfo command_info
[kNumCommands
- kStartPoint
];
2094 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl
);
2097 const GLES2DecoderImpl::CommandInfo
GLES2DecoderImpl::command_info
[] = {
2098 #define GLES2_CMD_OP(name) \
2100 &GLES2DecoderImpl::Handle##name, cmds::name::kArgFlags, \
2101 cmds::name::cmd_flags, \
2102 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, \
2105 GLES2_COMMAND_LIST(GLES2_CMD_OP
)
2109 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
2110 const char* function_name
, ErrorState
* error_state
)
2111 : function_name_(function_name
),
2112 error_state_(error_state
) {
2113 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_
, function_name_
);
2116 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
2117 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_
, function_name_
);
2120 static void RestoreCurrentTextureBindings(ContextState
* state
, GLenum target
) {
2121 TextureUnit
& info
= state
->texture_units
[0];
2123 scoped_refptr
<TextureRef
> texture_ref
;
2126 texture_ref
= info
.bound_texture_2d
;
2128 case GL_TEXTURE_CUBE_MAP
:
2129 texture_ref
= info
.bound_texture_cube_map
;
2131 case GL_TEXTURE_EXTERNAL_OES
:
2132 texture_ref
= info
.bound_texture_external_oes
;
2134 case GL_TEXTURE_RECTANGLE_ARB
:
2135 texture_ref
= info
.bound_texture_rectangle_arb
;
2141 if (texture_ref
.get()) {
2142 last_id
= texture_ref
->service_id();
2147 glBindTexture(target
, last_id
);
2148 glActiveTexture(GL_TEXTURE0
+ state
->active_texture_unit
);
2151 ScopedTextureBinder::ScopedTextureBinder(ContextState
* state
,
2156 ScopedGLErrorSuppressor
suppressor(
2157 "ScopedTextureBinder::ctor", state_
->GetErrorState());
2159 // TODO(apatrick): Check if there are any other states that need to be reset
2160 // before binding a new texture.
2161 glActiveTexture(GL_TEXTURE0
);
2162 glBindTexture(target
, id
);
2165 ScopedTextureBinder::~ScopedTextureBinder() {
2166 ScopedGLErrorSuppressor
suppressor(
2167 "ScopedTextureBinder::dtor", state_
->GetErrorState());
2168 RestoreCurrentTextureBindings(state_
, target_
);
2171 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState
* state
,
2174 ScopedGLErrorSuppressor
suppressor(
2175 "ScopedRenderBufferBinder::ctor", state_
->GetErrorState());
2176 glBindRenderbufferEXT(GL_RENDERBUFFER
, id
);
2179 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
2180 ScopedGLErrorSuppressor
suppressor(
2181 "ScopedRenderBufferBinder::dtor", state_
->GetErrorState());
2182 state_
->RestoreRenderbufferBindings();
2185 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl
* decoder
,
2187 : decoder_(decoder
) {
2188 ScopedGLErrorSuppressor
suppressor(
2189 "ScopedFrameBufferBinder::ctor", decoder_
->GetErrorState());
2190 glBindFramebufferEXT(GL_FRAMEBUFFER
, id
);
2191 decoder
->OnFboChanged();
2194 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
2195 ScopedGLErrorSuppressor
suppressor(
2196 "ScopedFrameBufferBinder::dtor", decoder_
->GetErrorState());
2197 decoder_
->RestoreCurrentFramebufferBindings();
2200 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
2201 GLES2DecoderImpl
* decoder
, bool enforce_internal_framebuffer
, bool internal
)
2202 : decoder_(decoder
) {
2203 resolve_and_bind_
= (
2204 decoder_
->offscreen_target_frame_buffer_
.get() &&
2205 decoder_
->IsOffscreenBufferMultisampled() &&
2206 (!decoder_
->framebuffer_state_
.bound_read_framebuffer
.get() ||
2207 enforce_internal_framebuffer
));
2208 if (!resolve_and_bind_
)
2211 ScopedGLErrorSuppressor
suppressor(
2212 "ScopedResolvedFrameBufferBinder::ctor", decoder_
->GetErrorState());
2213 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
,
2214 decoder_
->offscreen_target_frame_buffer_
->id());
2217 if (!decoder_
->offscreen_resolved_frame_buffer_
.get()) {
2218 decoder_
->offscreen_resolved_frame_buffer_
.reset(
2219 new BackFramebuffer(decoder_
));
2220 decoder_
->offscreen_resolved_frame_buffer_
->Create();
2221 decoder_
->offscreen_resolved_color_texture_
.reset(
2222 new BackTexture(decoder
->memory_tracker(), &decoder
->state_
));
2223 decoder_
->offscreen_resolved_color_texture_
->Create();
2225 DCHECK(decoder_
->offscreen_saved_color_format_
);
2226 decoder_
->offscreen_resolved_color_texture_
->AllocateStorage(
2227 decoder_
->offscreen_size_
, decoder_
->offscreen_saved_color_format_
,
2229 decoder_
->offscreen_resolved_frame_buffer_
->AttachRenderTexture(
2230 decoder_
->offscreen_resolved_color_texture_
.get());
2231 if (decoder_
->offscreen_resolved_frame_buffer_
->CheckStatus() !=
2232 GL_FRAMEBUFFER_COMPLETE
) {
2233 LOG(ERROR
) << "ScopedResolvedFrameBufferBinder failed "
2234 << "because offscreen resolved FBO was incomplete.";
2238 targetid
= decoder_
->offscreen_resolved_frame_buffer_
->id();
2240 targetid
= decoder_
->offscreen_saved_frame_buffer_
->id();
2242 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, targetid
);
2243 const int width
= decoder_
->offscreen_size_
.width();
2244 const int height
= decoder_
->offscreen_size_
.height();
2245 decoder
->state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
2246 decoder
->BlitFramebufferHelper(0,
2254 GL_COLOR_BUFFER_BIT
,
2256 glBindFramebufferEXT(GL_FRAMEBUFFER
, targetid
);
2259 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
2260 if (!resolve_and_bind_
)
2263 ScopedGLErrorSuppressor
suppressor(
2264 "ScopedResolvedFrameBufferBinder::dtor", decoder_
->GetErrorState());
2265 decoder_
->RestoreCurrentFramebufferBindings();
2266 if (decoder_
->state_
.enable_flags
.scissor_test
) {
2267 decoder_
->state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
2271 BackTexture::BackTexture(
2272 MemoryTracker
* memory_tracker
,
2273 ContextState
* state
)
2274 : memory_tracker_(memory_tracker
, MemoryTracker::kUnmanaged
),
2276 bytes_allocated_(0),
2280 BackTexture::~BackTexture() {
2281 // This does not destroy the render texture because that would require that
2282 // the associated GL context was current. Just check that it was explicitly
2287 void BackTexture::Create() {
2288 ScopedGLErrorSuppressor
suppressor("BackTexture::Create",
2289 state_
->GetErrorState());
2291 glGenTextures(1, &id_
);
2292 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2293 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
2294 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
2295 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
2296 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
2298 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
2299 // never called on an offscreen context, no data will ever be uploaded to the
2300 // saved offscreen color texture (it is deferred until to when SwapBuffers
2301 // is called). My idea is that some nvidia drivers might have a bug where
2302 // deleting a texture that has never been populated might cause a
2305 GL_TEXTURE_2D
, 0, GL_RGBA
, 16, 16, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, NULL
);
2307 bytes_allocated_
= 16u * 16u * 4u;
2308 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2311 bool BackTexture::AllocateStorage(
2312 const gfx::Size
& size
, GLenum format
, bool zero
) {
2314 ScopedGLErrorSuppressor
suppressor("BackTexture::AllocateStorage",
2315 state_
->GetErrorState());
2316 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2317 uint32 image_size
= 0;
2318 GLES2Util::ComputeImageDataSizes(
2319 size
.width(), size
.height(), 1, format
, GL_UNSIGNED_BYTE
, 8, &image_size
,
2322 if (!memory_tracker_
.EnsureGPUMemoryAvailable(image_size
)) {
2326 scoped_ptr
<char[]> zero_data
;
2328 zero_data
.reset(new char[image_size
]);
2329 memset(zero_data
.get(), 0, image_size
);
2332 glTexImage2D(GL_TEXTURE_2D
,
2344 bool success
= glGetError() == GL_NO_ERROR
;
2346 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2347 bytes_allocated_
= image_size
;
2348 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2353 void BackTexture::Copy(const gfx::Size
& size
, GLenum format
) {
2355 ScopedGLErrorSuppressor
suppressor("BackTexture::Copy",
2356 state_
->GetErrorState());
2357 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2358 glCopyTexImage2D(GL_TEXTURE_2D
,
2367 void BackTexture::Destroy() {
2369 ScopedGLErrorSuppressor
suppressor("BackTexture::Destroy",
2370 state_
->GetErrorState());
2371 glDeleteTextures(1, &id_
);
2374 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2375 bytes_allocated_
= 0;
2378 void BackTexture::Invalidate() {
2382 BackRenderbuffer::BackRenderbuffer(
2383 RenderbufferManager
* renderbuffer_manager
,
2384 MemoryTracker
* memory_tracker
,
2385 ContextState
* state
)
2386 : renderbuffer_manager_(renderbuffer_manager
),
2387 memory_tracker_(memory_tracker
, MemoryTracker::kUnmanaged
),
2389 bytes_allocated_(0),
2393 BackRenderbuffer::~BackRenderbuffer() {
2394 // This does not destroy the render buffer because that would require that
2395 // the associated GL context was current. Just check that it was explicitly
2400 void BackRenderbuffer::Create() {
2401 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Create",
2402 state_
->GetErrorState());
2404 glGenRenderbuffersEXT(1, &id_
);
2407 bool BackRenderbuffer::AllocateStorage(const FeatureInfo
* feature_info
,
2408 const gfx::Size
& size
,
2411 ScopedGLErrorSuppressor
suppressor(
2412 "BackRenderbuffer::AllocateStorage", state_
->GetErrorState());
2413 ScopedRenderBufferBinder
binder(state_
, id_
);
2415 uint32 estimated_size
= 0;
2416 if (!renderbuffer_manager_
->ComputeEstimatedRenderbufferSize(
2417 size
.width(), size
.height(), samples
, format
, &estimated_size
)) {
2421 if (!memory_tracker_
.EnsureGPUMemoryAvailable(estimated_size
)) {
2426 glRenderbufferStorageEXT(GL_RENDERBUFFER
,
2431 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info
,
2438 bool success
= glGetError() == GL_NO_ERROR
;
2440 // Mark the previously allocated bytes as free.
2441 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2442 bytes_allocated_
= estimated_size
;
2443 // Track the newly allocated bytes.
2444 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2449 void BackRenderbuffer::Destroy() {
2451 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Destroy",
2452 state_
->GetErrorState());
2453 glDeleteRenderbuffersEXT(1, &id_
);
2456 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2457 bytes_allocated_
= 0;
2460 void BackRenderbuffer::Invalidate() {
2464 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl
* decoder
)
2465 : decoder_(decoder
),
2469 BackFramebuffer::~BackFramebuffer() {
2470 // This does not destroy the frame buffer because that would require that
2471 // the associated GL context was current. Just check that it was explicitly
2476 void BackFramebuffer::Create() {
2477 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Create",
2478 decoder_
->GetErrorState());
2480 glGenFramebuffersEXT(1, &id_
);
2483 void BackFramebuffer::AttachRenderTexture(BackTexture
* texture
) {
2485 ScopedGLErrorSuppressor
suppressor(
2486 "BackFramebuffer::AttachRenderTexture", decoder_
->GetErrorState());
2487 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2488 GLuint attach_id
= texture
? texture
->id() : 0;
2489 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
,
2490 GL_COLOR_ATTACHMENT0
,
2496 void BackFramebuffer::AttachRenderBuffer(GLenum target
,
2497 BackRenderbuffer
* render_buffer
) {
2499 ScopedGLErrorSuppressor
suppressor(
2500 "BackFramebuffer::AttachRenderBuffer", decoder_
->GetErrorState());
2501 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2502 GLuint attach_id
= render_buffer
? render_buffer
->id() : 0;
2503 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
,
2509 void BackFramebuffer::Destroy() {
2511 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Destroy",
2512 decoder_
->GetErrorState());
2513 glDeleteFramebuffersEXT(1, &id_
);
2518 void BackFramebuffer::Invalidate() {
2522 GLenum
BackFramebuffer::CheckStatus() {
2524 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::CheckStatus",
2525 decoder_
->GetErrorState());
2526 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2527 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER
);
2530 GLES2Decoder
* GLES2Decoder::Create(ContextGroup
* group
) {
2531 return new GLES2DecoderImpl(group
);
2534 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup
* group
)
2537 logger_(&debug_marker_manager_
),
2538 state_(group_
->feature_info(), this, &logger_
),
2539 attrib_0_buffer_id_(0),
2540 attrib_0_buffer_matches_value_(true),
2542 fixed_attrib_buffer_id_(0),
2543 fixed_attrib_buffer_size_(0),
2544 offscreen_target_color_format_(0),
2545 offscreen_target_depth_format_(0),
2546 offscreen_target_stencil_format_(0),
2547 offscreen_target_samples_(0),
2548 offscreen_target_buffer_preserved_(true),
2549 offscreen_saved_color_format_(0),
2550 back_buffer_color_format_(0),
2551 back_buffer_has_depth_(false),
2552 back_buffer_has_stencil_(false),
2553 back_buffer_read_buffer_(GL_BACK
),
2554 back_buffer_draw_buffer_(GL_BACK
),
2555 surfaceless_(false),
2556 backbuffer_needs_clear_bits_(0),
2557 current_decoder_error_(error::kNoError
),
2558 use_shader_translator_(true),
2559 validators_(group_
->feature_info()->validators()),
2560 feature_info_(group_
->feature_info()),
2562 has_robustness_extension_(false),
2563 context_lost_reason_(error::kUnknown
),
2564 context_was_lost_(false),
2565 reset_by_robustness_extension_(false),
2566 supports_post_sub_buffer_(false),
2568 derivatives_explicitly_enabled_(false),
2569 frag_depth_explicitly_enabled_(false),
2570 draw_buffers_explicitly_enabled_(false),
2571 shader_texture_lod_explicitly_enabled_(false),
2572 compile_shader_always_succeeds_(false),
2573 lose_context_when_out_of_memory_(false),
2574 service_logging_(base::CommandLine::InitializedForCurrentProcess()
2575 ? base::CommandLine::ForCurrentProcess()->HasSwitch(
2576 switches::kEnableGPUServiceLoggingGPU
)
2578 viewport_max_width_(0),
2579 viewport_max_height_(0),
2580 texture_state_(group_
->feature_info()->workarounds()),
2581 cb_command_trace_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2582 TRACE_DISABLED_BY_DEFAULT("cb_command"))),
2583 gpu_decoder_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2584 TRACE_DISABLED_BY_DEFAULT("gpu_decoder"))),
2585 gpu_trace_level_(2),
2586 gpu_trace_commands_(false),
2587 gpu_debug_commands_(false),
2588 validation_texture_(0),
2589 validation_fbo_multisample_(0),
2590 validation_fbo_(0) {
2593 // The shader translator is used for WebGL even when running on EGL
2594 // because additional restrictions are needed (like only enabling
2595 // GL_OES_standard_derivatives on demand). It is used for the unit
2596 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2597 // the empty string to CompileShader and this is not a valid shader.
2598 bool disable_translator
=
2599 base::CommandLine::InitializedForCurrentProcess()
2600 ? base::CommandLine::ForCurrentProcess()->HasSwitch(
2601 switches::kDisableGLSLTranslator
)
2603 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL
||
2604 disable_translator
) {
2605 use_shader_translator_
= false;
2609 GLES2DecoderImpl::~GLES2DecoderImpl() {
2612 bool GLES2DecoderImpl::Initialize(
2613 const scoped_refptr
<gfx::GLSurface
>& surface
,
2614 const scoped_refptr
<gfx::GLContext
>& context
,
2616 const gfx::Size
& offscreen_size
,
2617 const DisallowedFeatures
& disallowed_features
,
2618 const std::vector
<int32
>& attribs
) {
2619 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2620 DCHECK(context
->IsCurrent(surface
.get()));
2621 DCHECK(!context_
.get());
2622 DCHECK(!offscreen
|| !offscreen_size
.IsEmpty());
2624 ContextCreationAttribHelper attrib_parser
;
2625 if (!attrib_parser
.Parse(attribs
))
2627 webgl_version_
= attrib_parser
.webgl_version
;
2629 surfaceless_
= surface
->IsSurfaceless() && !offscreen
;
2632 gpu_state_tracer_
= GPUStateTracer::Create(&state_
);
2634 if (base::CommandLine::InitializedForCurrentProcess()) {
2635 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2636 switches::kEnableGPUDebugging
)) {
2640 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2641 switches::kEnableGPUCommandLogging
)) {
2642 set_log_commands(true);
2645 compile_shader_always_succeeds_
=
2646 base::CommandLine::ForCurrentProcess()->HasSwitch(
2647 switches::kCompileShaderAlwaysSucceeds
);
2650 // Take ownership of the context and surface. The surface can be replaced with
2655 // Create GPU Tracer for timing values.
2656 gpu_tracer_
.reset(new GPUTracer(this));
2658 if (feature_info_
->workarounds().disable_timestamp_queries
) {
2659 // Forcing time elapsed query for any GPU Timing Client forces it for all
2660 // clients in the context.
2661 GetGLContext()->CreateGPUTimingClient()->ForceTimeElapsedQuery();
2664 // Save the loseContextWhenOutOfMemory context creation attribute.
2665 lose_context_when_out_of_memory_
=
2666 attrib_parser
.lose_context_when_out_of_memory
;
2668 // If the failIfMajorPerformanceCaveat context creation attribute was true
2669 // and we are using a software renderer, fail.
2670 if (attrib_parser
.fail_if_major_perf_caveat
&&
2671 feature_info_
->feature_flags().is_swiftshader
) {
2672 group_
= NULL
; // Must not destroy ContextGroup if it is not initialized.
2677 disallowed_features_
= disallowed_features
;
2678 if (webgl_version_
== 1) {
2679 disallowed_features_
.npot_support
= true;
2682 if (!group_
->Initialize(this,
2683 ContextGroup::GetContextType(webgl_version_
),
2684 disallowed_features_
)) {
2685 group_
= NULL
; // Must not destroy ContextGroup if it is not initialized.
2691 if (webgl_version_
== 2) {
2692 if (!feature_info_
->IsES3Capable()) {
2693 LOG(ERROR
) << "Underlying driver does not support ES3.";
2697 feature_info_
->EnableES3Validators();
2698 set_unsafe_es3_apis_enabled(true);
2701 state_
.attrib_values
.resize(group_
->max_vertex_attribs());
2702 vertex_array_manager_
.reset(new VertexArrayManager());
2704 GLuint default_vertex_attrib_service_id
= 0;
2705 if (features().native_vertex_array_object
) {
2706 glGenVertexArraysOES(1, &default_vertex_attrib_service_id
);
2707 glBindVertexArrayOES(default_vertex_attrib_service_id
);
2710 state_
.default_vertex_attrib_manager
=
2711 CreateVertexAttribManager(0, default_vertex_attrib_service_id
, false);
2713 state_
.default_vertex_attrib_manager
->Initialize(
2714 group_
->max_vertex_attribs(),
2715 feature_info_
->workarounds().init_vertex_attributes
);
2717 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2718 DoBindVertexArrayOES(0);
2720 query_manager_
.reset(new QueryManager(this, feature_info_
.get()));
2722 image_manager_
.reset(new ImageManager
);
2724 util_
.set_num_compressed_texture_formats(
2725 validators_
->compressed_texture_format
.GetValues().size());
2727 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
2728 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2729 // OpenGL ES 2.0 does not have this issue.
2730 glEnableVertexAttribArray(0);
2732 glGenBuffersARB(1, &attrib_0_buffer_id_
);
2733 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
2734 glVertexAttribPointer(0, 1, GL_FLOAT
, GL_FALSE
, 0, NULL
);
2735 glBindBuffer(GL_ARRAY_BUFFER
, 0);
2736 glGenBuffersARB(1, &fixed_attrib_buffer_id_
);
2738 state_
.texture_units
.resize(group_
->max_texture_units());
2739 for (uint32 tt
= 0; tt
< state_
.texture_units
.size(); ++tt
) {
2740 glActiveTexture(GL_TEXTURE0
+ tt
);
2741 // We want the last bind to be 2D.
2743 if (features().oes_egl_image_external
) {
2744 ref
= texture_manager()->GetDefaultTextureInfo(
2745 GL_TEXTURE_EXTERNAL_OES
);
2746 state_
.texture_units
[tt
].bound_texture_external_oes
= ref
;
2747 glBindTexture(GL_TEXTURE_EXTERNAL_OES
, ref
? ref
->service_id() : 0);
2749 if (features().arb_texture_rectangle
) {
2750 ref
= texture_manager()->GetDefaultTextureInfo(
2751 GL_TEXTURE_RECTANGLE_ARB
);
2752 state_
.texture_units
[tt
].bound_texture_rectangle_arb
= ref
;
2753 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, ref
? ref
->service_id() : 0);
2755 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP
);
2756 state_
.texture_units
[tt
].bound_texture_cube_map
= ref
;
2757 glBindTexture(GL_TEXTURE_CUBE_MAP
, ref
? ref
->service_id() : 0);
2758 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D
);
2759 state_
.texture_units
[tt
].bound_texture_2d
= ref
;
2760 glBindTexture(GL_TEXTURE_2D
, ref
? ref
->service_id() : 0);
2762 glActiveTexture(GL_TEXTURE0
);
2765 // cache ALPHA_BITS result for re-use with clear behaviour
2766 GLint alpha_bits
= 0;
2769 if (attrib_parser
.samples
> 0 && attrib_parser
.sample_buffers
> 0 &&
2770 features().chromium_framebuffer_multisample
) {
2771 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2772 // max_sample_count must be initialized to a sane value. If
2773 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2774 GLint max_sample_count
= 1;
2775 glGetIntegerv(GL_MAX_SAMPLES_EXT
, &max_sample_count
);
2776 offscreen_target_samples_
= std::min(attrib_parser
.samples
,
2779 offscreen_target_samples_
= 1;
2781 offscreen_target_buffer_preserved_
= attrib_parser
.buffer_preserved
;
2783 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
2784 const bool rgb8_supported
=
2785 context_
->HasExtension("GL_OES_rgb8_rgba8");
2786 // The only available default render buffer formats in GLES2 have very
2787 // little precision. Don't enable multisampling unless 8-bit render
2788 // buffer formats are available--instead fall back to 8-bit textures.
2789 if (rgb8_supported
&& offscreen_target_samples_
> 1) {
2790 offscreen_target_color_format_
= attrib_parser
.alpha_size
> 0 ?
2793 offscreen_target_samples_
= 1;
2794 offscreen_target_color_format_
=
2795 attrib_parser
.alpha_size
> 0 || workarounds().disable_gl_rgb_format
2800 // ANGLE only supports packed depth/stencil formats, so use it if it is
2802 const bool depth24_stencil8_supported
=
2803 feature_info_
->feature_flags().packed_depth24_stencil8
;
2804 VLOG(1) << "GL_OES_packed_depth_stencil "
2805 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2806 if ((attrib_parser
.depth_size
> 0 || attrib_parser
.stencil_size
> 0) &&
2807 depth24_stencil8_supported
) {
2808 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2809 offscreen_target_stencil_format_
= 0;
2811 // It may be the case that this depth/stencil combination is not
2812 // supported, but this will be checked later by CheckFramebufferStatus.
2813 offscreen_target_depth_format_
= attrib_parser
.depth_size
> 0 ?
2814 GL_DEPTH_COMPONENT16
: 0;
2815 offscreen_target_stencil_format_
= attrib_parser
.stencil_size
> 0 ?
2816 GL_STENCIL_INDEX8
: 0;
2819 offscreen_target_color_format_
=
2820 attrib_parser
.alpha_size
> 0 || workarounds().disable_gl_rgb_format
2824 // If depth is requested at all, use the packed depth stencil format if
2825 // it's available, as some desktop GL drivers don't support any non-packed
2826 // formats for depth attachments.
2827 const bool depth24_stencil8_supported
=
2828 feature_info_
->feature_flags().packed_depth24_stencil8
;
2829 VLOG(1) << "GL_EXT_packed_depth_stencil "
2830 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2832 if ((attrib_parser
.depth_size
> 0 || attrib_parser
.stencil_size
> 0) &&
2833 depth24_stencil8_supported
) {
2834 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2835 offscreen_target_stencil_format_
= 0;
2837 offscreen_target_depth_format_
= attrib_parser
.depth_size
> 0 ?
2838 GL_DEPTH_COMPONENT
: 0;
2839 offscreen_target_stencil_format_
= attrib_parser
.stencil_size
> 0 ?
2840 GL_STENCIL_INDEX
: 0;
2844 offscreen_saved_color_format_
=
2845 attrib_parser
.alpha_size
> 0 || workarounds().disable_gl_rgb_format
2849 // Create the target frame buffer. This is the one that the client renders
2851 offscreen_target_frame_buffer_
.reset(new BackFramebuffer(this));
2852 offscreen_target_frame_buffer_
->Create();
2853 // Due to GLES2 format limitations, either the color texture (for
2854 // non-multisampling) or the color render buffer (for multisampling) will be
2855 // attached to the offscreen frame buffer. The render buffer has more
2856 // limited formats available to it, but the texture can't do multisampling.
2857 if (IsOffscreenBufferMultisampled()) {
2858 offscreen_target_color_render_buffer_
.reset(new BackRenderbuffer(
2859 renderbuffer_manager(), memory_tracker(), &state_
));
2860 offscreen_target_color_render_buffer_
->Create();
2862 offscreen_target_color_texture_
.reset(new BackTexture(
2863 memory_tracker(), &state_
));
2864 offscreen_target_color_texture_
->Create();
2866 offscreen_target_depth_render_buffer_
.reset(new BackRenderbuffer(
2867 renderbuffer_manager(), memory_tracker(), &state_
));
2868 offscreen_target_depth_render_buffer_
->Create();
2869 offscreen_target_stencil_render_buffer_
.reset(new BackRenderbuffer(
2870 renderbuffer_manager(), memory_tracker(), &state_
));
2871 offscreen_target_stencil_render_buffer_
->Create();
2873 // Create the saved offscreen texture. The target frame buffer is copied
2874 // here when SwapBuffers is called.
2875 offscreen_saved_frame_buffer_
.reset(new BackFramebuffer(this));
2876 offscreen_saved_frame_buffer_
->Create();
2878 offscreen_saved_color_texture_
.reset(new BackTexture(
2879 memory_tracker(), &state_
));
2880 offscreen_saved_color_texture_
->Create();
2882 // Allocate the render buffers at their initial size and check the status
2883 // of the frame buffers is okay.
2884 if (!ResizeOffscreenFrameBuffer(offscreen_size
)) {
2885 LOG(ERROR
) << "Could not allocate offscreen buffer storage.";
2890 state_
.viewport_width
= offscreen_size
.width();
2891 state_
.viewport_height
= offscreen_size
.height();
2893 // Allocate the offscreen saved color texture.
2894 DCHECK(offscreen_saved_color_format_
);
2895 offscreen_saved_color_texture_
->AllocateStorage(
2896 gfx::Size(1, 1), offscreen_saved_color_format_
, true);
2898 offscreen_saved_frame_buffer_
->AttachRenderTexture(
2899 offscreen_saved_color_texture_
.get());
2900 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
2901 GL_FRAMEBUFFER_COMPLETE
) {
2902 LOG(ERROR
) << "Offscreen saved FBO was incomplete.";
2907 // Bind to the new default frame buffer (the offscreen target frame buffer).
2908 // This should now be associated with ID zero.
2909 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
2911 glBindFramebufferEXT(GL_FRAMEBUFFER
, GetBackbufferServiceId());
2912 // These are NOT if the back buffer has these proprorties. They are
2913 // if we want the command buffer to enforce them regardless of what
2914 // the real backbuffer is assuming the real back buffer gives us more than
2915 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2916 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2917 // can't do anything about that.
2919 if (!surfaceless_
) {
2920 GLint depth_bits
= 0;
2921 GLint stencil_bits
= 0;
2923 bool default_fb
= (GetBackbufferServiceId() == 0);
2925 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
2926 glGetFramebufferAttachmentParameterivEXT(
2928 default_fb
? GL_BACK_LEFT
: GL_COLOR_ATTACHMENT0
,
2929 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE
, &alpha_bits
);
2930 glGetFramebufferAttachmentParameterivEXT(
2932 default_fb
? GL_DEPTH
: GL_DEPTH_ATTACHMENT
,
2933 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE
, &depth_bits
);
2934 glGetFramebufferAttachmentParameterivEXT(
2936 default_fb
? GL_STENCIL
: GL_STENCIL_ATTACHMENT
,
2937 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE
, &stencil_bits
);
2939 glGetIntegerv(GL_ALPHA_BITS
, &alpha_bits
);
2940 glGetIntegerv(GL_DEPTH_BITS
, &depth_bits
);
2941 glGetIntegerv(GL_STENCIL_BITS
, &stencil_bits
);
2944 // This checks if the user requested RGBA and we have RGBA then RGBA. If
2945 // the user requested RGB then RGB. If the user did not specify a
2946 // preference than use whatever we were given. Same for DEPTH and STENCIL.
2947 back_buffer_color_format_
=
2948 (attrib_parser
.alpha_size
!= 0 && alpha_bits
> 0) ? GL_RGBA
: GL_RGB
;
2949 back_buffer_has_depth_
= attrib_parser
.depth_size
!= 0 && depth_bits
> 0;
2950 back_buffer_has_stencil_
=
2951 attrib_parser
.stencil_size
!= 0 && stencil_bits
> 0;
2954 state_
.viewport_width
= surface
->GetSize().width();
2955 state_
.viewport_height
= surface
->GetSize().height();
2958 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2959 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2960 // isn't well documented; it was discovered in the Khronos OpenGL ES
2961 // mailing list archives. It also implicitly enables the desktop GL
2962 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2963 // variable in fragment shaders.
2964 if (!feature_info_
->gl_version_info().BehavesLikeGLES()) {
2965 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE
);
2966 glEnable(GL_POINT_SPRITE
);
2969 has_robustness_extension_
=
2970 context
->HasExtension("GL_ARB_robustness") ||
2971 context
->HasExtension("GL_KHR_robustness") ||
2972 context
->HasExtension("GL_EXT_robustness");
2974 if (!InitializeShaderTranslator()) {
2978 GLint viewport_params
[4] = { 0 };
2979 glGetIntegerv(GL_MAX_VIEWPORT_DIMS
, viewport_params
);
2980 viewport_max_width_
= viewport_params
[0];
2981 viewport_max_height_
= viewport_params
[1];
2983 state_
.scissor_width
= state_
.viewport_width
;
2984 state_
.scissor_height
= state_
.viewport_height
;
2986 // Set all the default state because some GL drivers get it wrong.
2987 state_
.InitCapabilities(NULL
);
2988 state_
.InitState(NULL
);
2989 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
2991 DoBindBuffer(GL_ARRAY_BUFFER
, 0);
2992 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
2993 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
2994 DoBindRenderbuffer(GL_RENDERBUFFER
, 0);
2995 DoBindValueBufferCHROMIUM(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM
, 0);
2997 bool call_gl_clear
= !surfaceless_
;
2998 #if defined(OS_ANDROID)
2999 // Temporary workaround for Android WebView because this clear ignores the
3000 // clip and corrupts that external UI of the App. Not calling glClear is ok
3001 // because the system already clears the buffer before each draw. Proper
3002 // fix might be setting the scissor clip properly before initialize. See
3003 // crbug.com/259023 for details.
3004 call_gl_clear
= surface_
->GetHandle();
3006 if (call_gl_clear
) {
3007 // On configs where we report no alpha, if the underlying surface has
3008 // alpha, clear the surface alpha to 1.0 to be correct on ReadPixels/etc.
3009 bool clear_alpha
= back_buffer_color_format_
== GL_RGB
&& alpha_bits
> 0;
3011 glClearColor(0.0f
, 0.0f
, 0.0f
, 1.0f
);
3014 // Clear the backbuffer.
3015 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
3017 // Restore alpha clear value if we changed it.
3019 glClearColor(0.0f
, 0.0f
, 0.0f
, 0.0f
);
3023 supports_post_sub_buffer_
= surface
->SupportsPostSubBuffer();
3024 if (feature_info_
->workarounds()
3025 .disable_post_sub_buffers_for_onscreen_surfaces
&&
3026 !surface
->IsOffscreen())
3027 supports_post_sub_buffer_
= false;
3029 if (feature_info_
->workarounds().reverse_point_sprite_coord_origin
) {
3030 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN
, GL_LOWER_LEFT
);
3033 if (feature_info_
->workarounds().unbind_fbo_on_context_switch
) {
3034 context_
->SetUnbindFboOnMakeCurrent();
3037 // Only compositor contexts are known to use only the subset of GL
3038 // that can be safely migrated between the iGPU and the dGPU. Mark
3039 // those contexts as safe to forcibly transition between the GPUs.
3040 // http://crbug.com/180876, http://crbug.com/227228
3042 context_
->SetSafeToForceGpuSwitch();
3044 async_pixel_transfer_manager_
.reset(
3045 AsyncPixelTransferManager::Create(context
.get()));
3046 async_pixel_transfer_manager_
->Initialize(texture_manager());
3048 if (workarounds().gl_clear_broken
) {
3049 DCHECK(!clear_framebuffer_blit_
.get());
3050 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glClearWorkaroundInit");
3051 clear_framebuffer_blit_
.reset(new ClearFramebufferResourceManager(this));
3052 if (LOCAL_PEEK_GL_ERROR("glClearWorkaroundInit") != GL_NO_ERROR
)
3056 framebuffer_manager()->AddObserver(this);
3061 Capabilities
GLES2DecoderImpl::GetCapabilities() {
3062 DCHECK(initialized());
3064 caps
.VisitPrecisions([](GLenum shader
, GLenum type
,
3065 Capabilities::ShaderPrecision
* shader_precision
) {
3066 GLint range
[2] = {0, 0};
3067 GLint precision
= 0;
3068 GetShaderPrecisionFormatImpl(shader
, type
, range
, &precision
);
3069 shader_precision
->min_range
= range
[0];
3070 shader_precision
->max_range
= range
[1];
3071 shader_precision
->precision
= precision
;
3073 DoGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
,
3074 &caps
.max_combined_texture_image_units
);
3075 DoGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE
, &caps
.max_cube_map_texture_size
);
3076 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS
,
3077 &caps
.max_fragment_uniform_vectors
);
3078 DoGetIntegerv(GL_MAX_RENDERBUFFER_SIZE
, &caps
.max_renderbuffer_size
);
3079 DoGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS
, &caps
.max_texture_image_units
);
3080 DoGetIntegerv(GL_MAX_TEXTURE_SIZE
, &caps
.max_texture_size
);
3081 DoGetIntegerv(GL_MAX_VARYING_VECTORS
, &caps
.max_varying_vectors
);
3082 DoGetIntegerv(GL_MAX_VERTEX_ATTRIBS
, &caps
.max_vertex_attribs
);
3083 DoGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS
,
3084 &caps
.max_vertex_texture_image_units
);
3085 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS
,
3086 &caps
.max_vertex_uniform_vectors
);
3087 DoGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS
,
3088 &caps
.num_compressed_texture_formats
);
3089 DoGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS
, &caps
.num_shader_binary_formats
);
3090 DoGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM
,
3091 &caps
.bind_generates_resource_chromium
);
3092 if (unsafe_es3_apis_enabled()) {
3093 // TODO(zmo): Note that some parameter values could be more than 32-bit,
3094 // but for now we clamp them to 32-bit max.
3095 DoGetIntegerv(GL_MAX_3D_TEXTURE_SIZE
, &caps
.max_3d_texture_size
);
3096 DoGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS
, &caps
.max_array_texture_layers
);
3097 DoGetIntegerv(GL_MAX_COLOR_ATTACHMENTS
, &caps
.max_color_attachments
);
3098 DoGetInteger64v(GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS
,
3099 &caps
.max_combined_fragment_uniform_components
);
3100 DoGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS
,
3101 &caps
.max_combined_uniform_blocks
);
3102 DoGetInteger64v(GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS
,
3103 &caps
.max_combined_vertex_uniform_components
);
3104 DoGetIntegerv(GL_MAX_DRAW_BUFFERS
, &caps
.max_draw_buffers
);
3105 DoGetInteger64v(GL_MAX_ELEMENT_INDEX
, &caps
.max_element_index
);
3106 DoGetIntegerv(GL_MAX_ELEMENTS_INDICES
, &caps
.max_elements_indices
);
3107 DoGetIntegerv(GL_MAX_ELEMENTS_VERTICES
, &caps
.max_elements_vertices
);
3108 DoGetIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS
,
3109 &caps
.max_fragment_input_components
);
3110 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS
,
3111 &caps
.max_fragment_uniform_blocks
);
3112 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS
,
3113 &caps
.max_fragment_uniform_components
);
3114 DoGetIntegerv(GL_MAX_PROGRAM_TEXEL_OFFSET
,
3115 &caps
.max_program_texel_offset
);
3116 DoGetInteger64v(GL_MAX_SERVER_WAIT_TIMEOUT
, &caps
.max_server_wait_timeout
);
3117 // Work around Linux NVIDIA driver bug where GL_TIMEOUT_IGNORED is
3119 if (caps
.max_server_wait_timeout
< 0)
3120 caps
.max_server_wait_timeout
= 0;
3121 DoGetFloatv(GL_MAX_TEXTURE_LOD_BIAS
, &caps
.max_texture_lod_bias
);
3122 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS
,
3123 &caps
.max_transform_feedback_interleaved_components
);
3124 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS
,
3125 &caps
.max_transform_feedback_separate_attribs
);
3126 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS
,
3127 &caps
.max_transform_feedback_separate_components
);
3128 DoGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE
, &caps
.max_uniform_block_size
);
3129 DoGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS
,
3130 &caps
.max_uniform_buffer_bindings
);
3131 DoGetIntegerv(GL_MAX_VARYING_COMPONENTS
, &caps
.max_varying_components
);
3132 DoGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS
,
3133 &caps
.max_vertex_output_components
);
3134 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS
,
3135 &caps
.max_vertex_uniform_blocks
);
3136 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS
,
3137 &caps
.max_vertex_uniform_components
);
3138 DoGetIntegerv(GL_MIN_PROGRAM_TEXEL_OFFSET
, &caps
.min_program_texel_offset
);
3139 DoGetIntegerv(GL_NUM_EXTENSIONS
, &caps
.num_extensions
);
3140 DoGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS
,
3141 &caps
.num_program_binary_formats
);
3142 DoGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
,
3143 &caps
.uniform_buffer_offset_alignment
);
3144 // TODO(zmo): once we switch to MANGLE, we should query version numbers.
3145 caps
.major_version
= 3;
3146 caps
.minor_version
= 0;
3148 if (feature_info_
->feature_flags().multisampled_render_to_texture
||
3149 feature_info_
->feature_flags().chromium_framebuffer_multisample
||
3150 unsafe_es3_apis_enabled()) {
3151 DoGetIntegerv(GL_MAX_SAMPLES
, &caps
.max_samples
);
3154 caps
.egl_image_external
=
3155 feature_info_
->feature_flags().oes_egl_image_external
;
3156 caps
.texture_format_atc
=
3157 feature_info_
->feature_flags().ext_texture_format_atc
;
3158 caps
.texture_format_bgra8888
=
3159 feature_info_
->feature_flags().ext_texture_format_bgra8888
;
3160 caps
.texture_format_dxt1
=
3161 feature_info_
->feature_flags().ext_texture_format_dxt1
;
3162 caps
.texture_format_dxt5
=
3163 feature_info_
->feature_flags().ext_texture_format_dxt5
;
3164 caps
.texture_format_etc1
=
3165 feature_info_
->feature_flags().oes_compressed_etc1_rgb8_texture
;
3166 caps
.texture_format_etc1_npot
=
3167 caps
.texture_format_etc1
&& !workarounds().etc1_power_of_two_only
;
3168 caps
.texture_rectangle
= feature_info_
->feature_flags().arb_texture_rectangle
;
3169 caps
.texture_usage
= feature_info_
->feature_flags().angle_texture_usage
;
3170 caps
.texture_storage
= feature_info_
->feature_flags().ext_texture_storage
;
3171 caps
.discard_framebuffer
=
3172 feature_info_
->feature_flags().ext_discard_framebuffer
;
3173 caps
.sync_query
= feature_info_
->feature_flags().chromium_sync_query
;
3175 #if defined(OS_MACOSX)
3176 // This is unconditionally true on mac, no need to test for it at runtime.
3177 caps
.iosurface
= true;
3180 caps
.post_sub_buffer
= supports_post_sub_buffer_
;
3182 caps
.surfaceless
= surfaceless_
;
3184 caps
.blend_equation_advanced
=
3185 feature_info_
->feature_flags().blend_equation_advanced
;
3186 caps
.blend_equation_advanced_coherent
=
3187 feature_info_
->feature_flags().blend_equation_advanced_coherent
;
3188 caps
.texture_rg
= feature_info_
->feature_flags().ext_texture_rg
;
3189 caps
.max_copy_texture_chromium_size
=
3190 feature_info_
->workarounds().max_copy_texture_chromium_size
;
3191 caps
.render_buffer_format_bgra8888
=
3192 feature_info_
->feature_flags().ext_render_buffer_format_bgra8888
;
3193 caps
.occlusion_query_boolean
=
3194 feature_info_
->feature_flags().occlusion_query_boolean
;
3195 caps
.timer_queries
=
3196 query_manager_
->GPUTimingAvailable();
3200 void GLES2DecoderImpl::UpdateCapabilities() {
3201 util_
.set_num_compressed_texture_formats(
3202 validators_
->compressed_texture_format
.GetValues().size());
3203 util_
.set_num_shader_binary_formats(
3204 validators_
->shader_binary_format
.GetValues().size());
3207 bool GLES2DecoderImpl::InitializeShaderTranslator() {
3208 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
3210 if (!use_shader_translator_
) {
3213 ShBuiltInResources resources
;
3214 ShInitBuiltInResources(&resources
);
3215 resources
.MaxVertexAttribs
= group_
->max_vertex_attribs();
3216 resources
.MaxVertexUniformVectors
=
3217 group_
->max_vertex_uniform_vectors();
3218 resources
.MaxVaryingVectors
= group_
->max_varying_vectors();
3219 resources
.MaxVertexTextureImageUnits
=
3220 group_
->max_vertex_texture_image_units();
3221 resources
.MaxCombinedTextureImageUnits
= group_
->max_texture_units();
3222 resources
.MaxTextureImageUnits
= group_
->max_texture_image_units();
3223 resources
.MaxFragmentUniformVectors
=
3224 group_
->max_fragment_uniform_vectors();
3225 resources
.MaxDrawBuffers
= group_
->max_draw_buffers();
3226 resources
.MaxExpressionComplexity
= 256;
3227 resources
.MaxCallStackDepth
= 256;
3229 GLint range
[2] = { 0, 0 };
3230 GLint precision
= 0;
3231 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER
, GL_HIGH_FLOAT
,
3233 resources
.FragmentPrecisionHigh
=
3234 PrecisionMeetsSpecForHighpFloat(range
[0], range
[1], precision
);
3236 if (IsWebGLContext()) {
3237 resources
.OES_standard_derivatives
= derivatives_explicitly_enabled_
;
3238 resources
.EXT_frag_depth
= frag_depth_explicitly_enabled_
;
3239 resources
.EXT_draw_buffers
= draw_buffers_explicitly_enabled_
;
3240 if (!draw_buffers_explicitly_enabled_
)
3241 resources
.MaxDrawBuffers
= 1;
3242 resources
.EXT_shader_texture_lod
= shader_texture_lod_explicitly_enabled_
;
3243 resources
.NV_draw_buffers
=
3244 draw_buffers_explicitly_enabled_
&& features().nv_draw_buffers
;
3246 resources
.OES_standard_derivatives
=
3247 features().oes_standard_derivatives
? 1 : 0;
3248 resources
.ARB_texture_rectangle
=
3249 features().arb_texture_rectangle
? 1 : 0;
3250 resources
.OES_EGL_image_external
=
3251 features().oes_egl_image_external
? 1 : 0;
3252 resources
.EXT_draw_buffers
=
3253 features().ext_draw_buffers
? 1 : 0;
3254 resources
.EXT_frag_depth
=
3255 features().ext_frag_depth
? 1 : 0;
3256 resources
.EXT_shader_texture_lod
=
3257 features().ext_shader_texture_lod
? 1 : 0;
3258 resources
.NV_draw_buffers
=
3259 features().nv_draw_buffers
? 1 : 0;
3262 ShShaderSpec shader_spec
;
3263 if (IsWebGLContext()) {
3264 shader_spec
= webgl_version_
== 2 ? SH_WEBGL2_SPEC
: SH_WEBGL_SPEC
;
3266 shader_spec
= unsafe_es3_apis_enabled() ? SH_GLES3_SPEC
: SH_GLES2_SPEC
;
3269 if ((shader_spec
== SH_WEBGL_SPEC
|| shader_spec
== SH_WEBGL2_SPEC
) &&
3270 features().enable_shader_name_hashing
)
3271 resources
.HashFunction
= &CityHash64
;
3273 resources
.HashFunction
= NULL
;
3275 int driver_bug_workarounds
= 0;
3276 if (workarounds().needs_glsl_built_in_function_emulation
)
3277 driver_bug_workarounds
|= SH_EMULATE_BUILT_IN_FUNCTIONS
;
3278 if (workarounds().init_gl_position_in_vertex_shader
)
3279 driver_bug_workarounds
|= SH_INIT_GL_POSITION
;
3280 if (workarounds().unfold_short_circuit_as_ternary_operation
)
3281 driver_bug_workarounds
|= SH_UNFOLD_SHORT_CIRCUIT
;
3282 if (workarounds().init_varyings_without_static_use
)
3283 driver_bug_workarounds
|= SH_INIT_VARYINGS_WITHOUT_STATIC_USE
;
3284 if (workarounds().unroll_for_loop_with_sampler_array_index
)
3285 driver_bug_workarounds
|= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX
;
3286 if (workarounds().scalarize_vec_and_mat_constructor_args
)
3287 driver_bug_workarounds
|= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS
;
3288 if (workarounds().regenerate_struct_names
)
3289 driver_bug_workarounds
|= SH_REGENERATE_STRUCT_NAMES
;
3290 if (workarounds().remove_pow_with_constant_exponent
)
3291 driver_bug_workarounds
|= SH_REMOVE_POW_WITH_CONSTANT_EXPONENT
;
3293 if (base::CommandLine::InitializedForCurrentProcess() &&
3294 base::CommandLine::ForCurrentProcess()->HasSwitch(
3295 switches::kEmulateShaderPrecision
))
3296 resources
.WEBGL_debug_shader_precision
= true;
3298 ShShaderOutput shader_output_language
=
3299 ShaderTranslator::GetShaderOutputLanguageForContext(
3300 feature_info_
->gl_version_info());
3302 vertex_translator_
= shader_translator_cache()->GetTranslator(
3303 GL_VERTEX_SHADER
, shader_spec
, &resources
, shader_output_language
,
3304 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
3305 if (!vertex_translator_
.get()) {
3306 LOG(ERROR
) << "Could not initialize vertex shader translator.";
3311 fragment_translator_
= shader_translator_cache()->GetTranslator(
3312 GL_FRAGMENT_SHADER
, shader_spec
, &resources
, shader_output_language
,
3313 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
3314 if (!fragment_translator_
.get()) {
3315 LOG(ERROR
) << "Could not initialize fragment shader translator.";
3322 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n
, const GLuint
* client_ids
) {
3323 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3324 if (GetBuffer(client_ids
[ii
])) {
3328 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3329 glGenBuffersARB(n
, service_ids
.get());
3330 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3331 CreateBuffer(client_ids
[ii
], service_ids
[ii
]);
3336 bool GLES2DecoderImpl::GenFramebuffersHelper(
3337 GLsizei n
, const GLuint
* client_ids
) {
3338 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3339 if (GetFramebuffer(client_ids
[ii
])) {
3343 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3344 glGenFramebuffersEXT(n
, service_ids
.get());
3345 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3346 CreateFramebuffer(client_ids
[ii
], service_ids
[ii
]);
3351 bool GLES2DecoderImpl::GenRenderbuffersHelper(
3352 GLsizei n
, const GLuint
* client_ids
) {
3353 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3354 if (GetRenderbuffer(client_ids
[ii
])) {
3358 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3359 glGenRenderbuffersEXT(n
, service_ids
.get());
3360 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3361 CreateRenderbuffer(client_ids
[ii
], service_ids
[ii
]);
3366 bool GLES2DecoderImpl::GenValuebuffersCHROMIUMHelper(GLsizei n
,
3367 const GLuint
* client_ids
) {
3368 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3369 if (GetValuebuffer(client_ids
[ii
])) {
3373 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3374 CreateValuebuffer(client_ids
[ii
]);
3379 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n
, const GLuint
* client_ids
) {
3380 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3381 if (GetTexture(client_ids
[ii
])) {
3385 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3386 glGenTextures(n
, service_ids
.get());
3387 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3388 CreateTexture(client_ids
[ii
], service_ids
[ii
]);
3393 bool GLES2DecoderImpl::GenPathsCHROMIUMHelper(GLuint first_client_id
,
3395 GLuint last_client_id
;
3396 if (!SafeAddUint32(first_client_id
, range
- 1, &last_client_id
))
3399 if (path_manager()->HasPathsInRange(first_client_id
, last_client_id
))
3402 GLuint first_service_id
= glGenPathsNV(range
);
3403 if (first_service_id
== 0) {
3404 // We have to fail the connection here, because client has already
3405 // succeeded in allocating the ids. This happens if we allocate
3406 // the whole path id space (two allocations of 0x7FFFFFFF paths, for
3410 // GenPathsNV does not wrap.
3411 DCHECK(first_service_id
+ range
- 1 >= first_service_id
);
3413 path_manager()->CreatePathRange(first_client_id
, last_client_id
,
3419 bool GLES2DecoderImpl::DeletePathsCHROMIUMHelper(GLuint first_client_id
,
3421 GLuint last_client_id
;
3422 if (!SafeAddUint32(first_client_id
, range
- 1, &last_client_id
))
3425 path_manager()->RemovePaths(first_client_id
, last_client_id
);
3429 void GLES2DecoderImpl::DeleteBuffersHelper(
3430 GLsizei n
, const GLuint
* client_ids
) {
3431 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3432 Buffer
* buffer
= GetBuffer(client_ids
[ii
]);
3433 if (buffer
&& !buffer
->IsDeleted()) {
3434 buffer
->RemoveMappedRange();
3435 state_
.RemoveBoundBuffer(buffer
);
3436 RemoveBuffer(client_ids
[ii
]);
3441 void GLES2DecoderImpl::DeleteFramebuffersHelper(
3442 GLsizei n
, const GLuint
* client_ids
) {
3443 bool supports_separate_framebuffer_binds
=
3444 features().chromium_framebuffer_multisample
;
3446 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3447 Framebuffer
* framebuffer
=
3448 GetFramebuffer(client_ids
[ii
]);
3449 if (framebuffer
&& !framebuffer
->IsDeleted()) {
3450 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
3451 GLenum target
= supports_separate_framebuffer_binds
?
3452 GL_DRAW_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
3454 // Unbind attachments on FBO before deletion.
3455 if (workarounds().unbind_attachments_on_bound_render_fbo_delete
)
3456 framebuffer
->DoUnbindGLAttachmentsForWorkaround(target
);
3458 glBindFramebufferEXT(target
, GetBackbufferServiceId());
3459 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
3460 framebuffer_state_
.clear_state_dirty
= true;
3462 if (framebuffer
== framebuffer_state_
.bound_read_framebuffer
.get()) {
3463 framebuffer_state_
.bound_read_framebuffer
= NULL
;
3464 GLenum target
= supports_separate_framebuffer_binds
?
3465 GL_READ_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
3466 glBindFramebufferEXT(target
, GetBackbufferServiceId());
3469 RemoveFramebuffer(client_ids
[ii
]);
3474 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
3475 GLsizei n
, const GLuint
* client_ids
) {
3476 bool supports_separate_framebuffer_binds
=
3477 features().chromium_framebuffer_multisample
;
3478 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3479 Renderbuffer
* renderbuffer
=
3480 GetRenderbuffer(client_ids
[ii
]);
3481 if (renderbuffer
&& !renderbuffer
->IsDeleted()) {
3482 if (state_
.bound_renderbuffer
.get() == renderbuffer
) {
3483 state_
.bound_renderbuffer
= NULL
;
3485 // Unbind from current framebuffers.
3486 if (supports_separate_framebuffer_binds
) {
3487 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
3488 framebuffer_state_
.bound_read_framebuffer
3489 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT
, renderbuffer
);
3491 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3492 framebuffer_state_
.bound_draw_framebuffer
3493 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT
, renderbuffer
);
3496 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3497 framebuffer_state_
.bound_draw_framebuffer
3498 ->UnbindRenderbuffer(GL_FRAMEBUFFER
, renderbuffer
);
3501 framebuffer_state_
.clear_state_dirty
= true;
3502 RemoveRenderbuffer(client_ids
[ii
]);
3507 void GLES2DecoderImpl::DeleteValuebuffersCHROMIUMHelper(
3509 const GLuint
* client_ids
) {
3510 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3511 Valuebuffer
* valuebuffer
= GetValuebuffer(client_ids
[ii
]);
3513 if (state_
.bound_valuebuffer
.get() == valuebuffer
) {
3514 state_
.bound_valuebuffer
= NULL
;
3516 RemoveValuebuffer(client_ids
[ii
]);
3521 void GLES2DecoderImpl::DeleteTexturesHelper(
3522 GLsizei n
, const GLuint
* client_ids
) {
3523 bool supports_separate_framebuffer_binds
=
3524 features().chromium_framebuffer_multisample
;
3525 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3526 TextureRef
* texture_ref
= GetTexture(client_ids
[ii
]);
3528 Texture
* texture
= texture_ref
->texture();
3529 if (texture
->IsAttachedToFramebuffer()) {
3530 framebuffer_state_
.clear_state_dirty
= true;
3532 // Unbind texture_ref from texture_ref units.
3533 for (size_t jj
= 0; jj
< state_
.texture_units
.size(); ++jj
) {
3534 state_
.texture_units
[jj
].Unbind(texture_ref
);
3536 // Unbind from current framebuffers.
3537 if (supports_separate_framebuffer_binds
) {
3538 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
3539 framebuffer_state_
.bound_read_framebuffer
3540 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT
, texture_ref
);
3542 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3543 framebuffer_state_
.bound_draw_framebuffer
3544 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT
, texture_ref
);
3547 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3548 framebuffer_state_
.bound_draw_framebuffer
3549 ->UnbindTexture(GL_FRAMEBUFFER
, texture_ref
);
3552 #if defined(OS_MACOSX)
3553 GLuint service_id
= texture
->service_id();
3554 if (texture
->target() == GL_TEXTURE_RECTANGLE_ARB
) {
3555 ReleaseIOSurfaceForTexture(service_id
);
3558 RemoveTexture(client_ids
[ii
]);
3563 // } // anonymous namespace
3565 bool GLES2DecoderImpl::MakeCurrent() {
3566 if (!context_
.get())
3569 if (WasContextLost()) {
3570 LOG(ERROR
) << " GLES2DecoderImpl: Trying to make lost context current.";
3574 if (!context_
->MakeCurrent(surface_
.get())) {
3575 LOG(ERROR
) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3576 MarkContextLost(error::kMakeCurrentFailed
);
3577 group_
->LoseContexts(error::kUnknown
);
3581 if (CheckResetStatus()) {
3583 << " GLES2DecoderImpl: Context reset detected after MakeCurrent.";
3584 group_
->LoseContexts(error::kUnknown
);
3588 ProcessFinishedAsyncTransfers();
3590 // Rebind the FBO if it was unbound by the context.
3591 if (workarounds().unbind_fbo_on_context_switch
)
3592 RestoreFramebufferBindings();
3594 framebuffer_state_
.clear_state_dirty
= true;
3599 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3600 ProcessPendingReadPixels(false);
3601 if (engine() && query_manager_
.get())
3602 query_manager_
->ProcessPendingTransferQueries();
3604 // TODO(epenner): Is there a better place to do this?
3605 // This needs to occur before we execute any batch of commands
3606 // from the client, as the client may have recieved an async
3607 // completion while issuing those commands.
3608 // "DidFlushStart" would be ideal if we had such a callback.
3609 async_pixel_transfer_manager_
->BindCompletedAsyncTransfers();
3612 static void RebindCurrentFramebuffer(
3614 Framebuffer
* framebuffer
,
3615 GLuint back_buffer_service_id
) {
3616 GLuint framebuffer_id
= framebuffer
? framebuffer
->service_id() : 0;
3618 if (framebuffer_id
== 0) {
3619 framebuffer_id
= back_buffer_service_id
;
3622 glBindFramebufferEXT(target
, framebuffer_id
);
3625 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3626 framebuffer_state_
.clear_state_dirty
= true;
3628 if (!features().chromium_framebuffer_multisample
) {
3629 RebindCurrentFramebuffer(
3631 framebuffer_state_
.bound_draw_framebuffer
.get(),
3632 GetBackbufferServiceId());
3634 RebindCurrentFramebuffer(
3635 GL_READ_FRAMEBUFFER_EXT
,
3636 framebuffer_state_
.bound_read_framebuffer
.get(),
3637 GetBackbufferServiceId());
3638 RebindCurrentFramebuffer(
3639 GL_DRAW_FRAMEBUFFER_EXT
,
3640 framebuffer_state_
.bound_draw_framebuffer
.get(),
3641 GetBackbufferServiceId());
3646 bool GLES2DecoderImpl::CheckFramebufferValid(
3647 Framebuffer
* framebuffer
,
3648 GLenum target
, const char* func_name
) {
3652 if (backbuffer_needs_clear_bits_
) {
3653 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3654 offscreen_target_color_format_
) & 0x0008) != 0 ? 0 : 1.f
);
3655 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
3657 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
3658 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
3660 state_
.SetDeviceDepthMask(GL_TRUE
);
3661 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
3662 bool reset_draw_buffer
= false;
3663 if ((backbuffer_needs_clear_bits_
& GL_COLOR_BUFFER_BIT
) != 0 &&
3664 back_buffer_draw_buffer_
== GL_NONE
) {
3665 reset_draw_buffer
= true;
3666 GLenum buf
= GL_BACK
;
3667 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3668 buf
= GL_COLOR_ATTACHMENT0
;
3669 glDrawBuffersARB(1, &buf
);
3671 glClear(backbuffer_needs_clear_bits_
);
3672 if (reset_draw_buffer
) {
3673 GLenum buf
= GL_NONE
;
3674 glDrawBuffersARB(1, &buf
);
3676 backbuffer_needs_clear_bits_
= 0;
3677 RestoreClearState();
3682 if (framebuffer_manager()->IsComplete(framebuffer
)) {
3686 GLenum completeness
= framebuffer
->IsPossiblyComplete();
3687 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
3689 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
, "framebuffer incomplete");
3693 // Are all the attachments cleared?
3694 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3695 texture_manager()->HaveUnclearedMips()) {
3696 if (!framebuffer
->IsCleared()) {
3697 // Can we clear them?
3698 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3699 GL_FRAMEBUFFER_COMPLETE
) {
3701 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3702 "framebuffer incomplete (clear)");
3705 ClearUnclearedAttachments(target
, framebuffer
);
3709 if (!framebuffer_manager()->IsComplete(framebuffer
)) {
3710 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3711 GL_FRAMEBUFFER_COMPLETE
) {
3713 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3714 "framebuffer incomplete (check)");
3717 framebuffer_manager()->MarkAsComplete(framebuffer
);
3720 // NOTE: At this point we don't know if the framebuffer is complete but
3721 // we DO know that everything that needs to be cleared has been cleared.
3725 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name
) {
3726 if (!features().chromium_framebuffer_multisample
) {
3727 bool valid
= CheckFramebufferValid(
3728 framebuffer_state_
.bound_draw_framebuffer
.get(), GL_FRAMEBUFFER_EXT
,
3736 return CheckFramebufferValid(framebuffer_state_
.bound_draw_framebuffer
.get(),
3737 GL_DRAW_FRAMEBUFFER_EXT
,
3739 CheckFramebufferValid(framebuffer_state_
.bound_read_framebuffer
.get(),
3740 GL_READ_FRAMEBUFFER_EXT
,
3744 bool GLES2DecoderImpl::CheckBoundReadFramebufferColorAttachment(
3745 const char* func_name
) {
3746 Framebuffer
* framebuffer
= features().chromium_framebuffer_multisample
?
3747 framebuffer_state_
.bound_read_framebuffer
.get() :
3748 framebuffer_state_
.bound_draw_framebuffer
.get();
3751 if (framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
) == NULL
) {
3753 GL_INVALID_OPERATION
, func_name
, "no color image attached");
3759 bool GLES2DecoderImpl::FormsTextureCopyingFeedbackLoop(
3760 TextureRef
* texture
, GLint level
) {
3761 Framebuffer
* framebuffer
= features().chromium_framebuffer_multisample
?
3762 framebuffer_state_
.bound_read_framebuffer
.get() :
3763 framebuffer_state_
.bound_draw_framebuffer
.get();
3766 const Framebuffer::Attachment
* attachment
= framebuffer
->GetAttachment(
3767 GL_COLOR_ATTACHMENT0
);
3770 return attachment
->FormsFeedbackLoop(texture
, level
);
3773 gfx::Size
GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3774 Framebuffer
* framebuffer
=
3775 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3776 if (framebuffer
!= NULL
) {
3777 const Framebuffer::Attachment
* attachment
=
3778 framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
);
3780 return gfx::Size(attachment
->width(), attachment
->height());
3782 return gfx::Size(0, 0);
3783 } else if (offscreen_target_frame_buffer_
.get()) {
3784 return offscreen_size_
;
3786 return surface_
->GetSize();
3790 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3791 Framebuffer
* framebuffer
=
3792 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3794 return framebuffer
->GetReadBufferTextureType();
3795 } else { // Back buffer.
3796 if (back_buffer_read_buffer_
== GL_NONE
)
3798 return GL_UNSIGNED_BYTE
;
3802 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3803 Framebuffer
* framebuffer
=
3804 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3806 return framebuffer
->GetReadBufferInternalFormat();
3807 } else { // Back buffer.
3808 if (back_buffer_read_buffer_
== GL_NONE
)
3810 if (offscreen_target_frame_buffer_
.get()) {
3811 return offscreen_target_color_format_
;
3813 return back_buffer_color_format_
;
3817 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3818 if (!offscreen_saved_color_texture_info_
.get())
3820 GLenum target
= offscreen_saved_color_texture_info_
->texture()->target();
3821 glBindTexture(target
, offscreen_saved_color_texture_info_
->service_id());
3822 texture_manager()->SetLevelInfo(
3823 offscreen_saved_color_texture_info_
.get(), GL_TEXTURE_2D
,
3825 GL_RGBA
, offscreen_size_
.width(), offscreen_size_
.height(),
3828 GL_RGBA
, GL_UNSIGNED_BYTE
, gfx::Rect(offscreen_size_
));
3829 texture_manager()->SetParameteri(
3830 "UpdateParentTextureInfo",
3832 offscreen_saved_color_texture_info_
.get(),
3833 GL_TEXTURE_MAG_FILTER
,
3835 texture_manager()->SetParameteri(
3836 "UpdateParentTextureInfo",
3838 offscreen_saved_color_texture_info_
.get(),
3839 GL_TEXTURE_MIN_FILTER
,
3841 texture_manager()->SetParameteri(
3842 "UpdateParentTextureInfo",
3844 offscreen_saved_color_texture_info_
.get(),
3847 texture_manager()->SetParameteri(
3848 "UpdateParentTextureInfo",
3850 offscreen_saved_color_texture_info_
.get(),
3853 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
3855 glBindTexture(target
, texture_ref
? texture_ref
->service_id() : 0);
3858 void GLES2DecoderImpl::SetResizeCallback(
3859 const base::Callback
<void(gfx::Size
, float)>& callback
) {
3860 resize_callback_
= callback
;
3863 Logger
* GLES2DecoderImpl::GetLogger() {
3867 void GLES2DecoderImpl::BeginDecoding() {
3868 gpu_tracer_
->BeginDecoding();
3869 gpu_trace_commands_
= gpu_tracer_
->IsTracing() && *gpu_decoder_category_
;
3870 gpu_debug_commands_
= log_commands() || debug() || gpu_trace_commands_
||
3871 (*cb_command_trace_category_
!= 0);
3872 query_manager_
->ProcessFrameBeginUpdates();
3875 void GLES2DecoderImpl::EndDecoding() {
3876 gpu_tracer_
->EndDecoding();
3879 ErrorState
* GLES2DecoderImpl::GetErrorState() {
3880 return state_
.GetErrorState();
3883 void GLES2DecoderImpl::SetShaderCacheCallback(
3884 const ShaderCacheCallback
& callback
) {
3885 shader_cache_callback_
= callback
;
3888 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3889 const WaitSyncPointCallback
& callback
) {
3890 wait_sync_point_callback_
= callback
;
3893 AsyncPixelTransferManager
*
3894 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3895 return async_pixel_transfer_manager_
.get();
3898 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3899 async_pixel_transfer_manager_
.reset();
3902 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3903 AsyncPixelTransferManager
* manager
) {
3904 async_pixel_transfer_manager_
= make_scoped_ptr(manager
);
3907 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id
,
3908 uint32
* service_texture_id
) {
3909 TextureRef
* texture_ref
= texture_manager()->GetTexture(client_texture_id
);
3911 *service_texture_id
= texture_ref
->service_id();
3917 uint32
GLES2DecoderImpl::GetTextureUploadCount() {
3918 return texture_state_
.texture_upload_count
+
3919 async_pixel_transfer_manager_
->GetTextureUploadCount();
3922 base::TimeDelta
GLES2DecoderImpl::GetTotalTextureUploadTime() {
3923 return texture_state_
.total_texture_upload_time
+
3924 async_pixel_transfer_manager_
->GetTotalTextureUploadTime();
3927 base::TimeDelta
GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3928 return total_processing_commands_time_
;
3931 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time
) {
3932 total_processing_commands_time_
+= time
;
3935 void GLES2DecoderImpl::Destroy(bool have_context
) {
3939 DCHECK(!have_context
|| context_
->IsCurrent(NULL
));
3941 // Unbind everything.
3942 state_
.vertex_attrib_manager
= NULL
;
3943 state_
.default_vertex_attrib_manager
= NULL
;
3944 state_
.texture_units
.clear();
3945 state_
.bound_array_buffer
= NULL
;
3946 state_
.bound_copy_read_buffer
= NULL
;
3947 state_
.bound_copy_write_buffer
= NULL
;
3948 state_
.bound_pixel_pack_buffer
= NULL
;
3949 state_
.bound_pixel_unpack_buffer
= NULL
;
3950 state_
.bound_transform_feedback_buffer
= NULL
;
3951 state_
.bound_uniform_buffer
= NULL
;
3952 framebuffer_state_
.bound_read_framebuffer
= NULL
;
3953 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
3954 state_
.bound_renderbuffer
= NULL
;
3955 state_
.bound_valuebuffer
= NULL
;
3957 if (offscreen_saved_color_texture_info_
.get()) {
3958 DCHECK(offscreen_target_color_texture_
);
3959 DCHECK_EQ(offscreen_saved_color_texture_info_
->service_id(),
3960 offscreen_saved_color_texture_
->id());
3961 offscreen_saved_color_texture_
->Invalidate();
3962 offscreen_saved_color_texture_info_
= NULL
;
3965 if (copy_texture_CHROMIUM_
.get()) {
3966 copy_texture_CHROMIUM_
->Destroy();
3967 copy_texture_CHROMIUM_
.reset();
3970 clear_framebuffer_blit_
.reset();
3972 if (state_
.current_program
.get()) {
3973 program_manager()->UnuseProgram(shader_manager(),
3974 state_
.current_program
.get());
3977 if (attrib_0_buffer_id_
) {
3978 glDeleteBuffersARB(1, &attrib_0_buffer_id_
);
3980 if (fixed_attrib_buffer_id_
) {
3981 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_
);
3984 if (validation_texture_
) {
3985 glDeleteTextures(1, &validation_texture_
);
3986 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_
);
3987 glDeleteFramebuffersEXT(1, &validation_fbo_
);
3990 if (offscreen_target_frame_buffer_
.get())
3991 offscreen_target_frame_buffer_
->Destroy();
3992 if (offscreen_target_color_texture_
.get())
3993 offscreen_target_color_texture_
->Destroy();
3994 if (offscreen_target_color_render_buffer_
.get())
3995 offscreen_target_color_render_buffer_
->Destroy();
3996 if (offscreen_target_depth_render_buffer_
.get())
3997 offscreen_target_depth_render_buffer_
->Destroy();
3998 if (offscreen_target_stencil_render_buffer_
.get())
3999 offscreen_target_stencil_render_buffer_
->Destroy();
4000 if (offscreen_saved_frame_buffer_
.get())
4001 offscreen_saved_frame_buffer_
->Destroy();
4002 if (offscreen_saved_color_texture_
.get())
4003 offscreen_saved_color_texture_
->Destroy();
4004 if (offscreen_resolved_frame_buffer_
.get())
4005 offscreen_resolved_frame_buffer_
->Destroy();
4006 if (offscreen_resolved_color_texture_
.get())
4007 offscreen_resolved_color_texture_
->Destroy();
4009 if (offscreen_target_frame_buffer_
.get())
4010 offscreen_target_frame_buffer_
->Invalidate();
4011 if (offscreen_target_color_texture_
.get())
4012 offscreen_target_color_texture_
->Invalidate();
4013 if (offscreen_target_color_render_buffer_
.get())
4014 offscreen_target_color_render_buffer_
->Invalidate();
4015 if (offscreen_target_depth_render_buffer_
.get())
4016 offscreen_target_depth_render_buffer_
->Invalidate();
4017 if (offscreen_target_stencil_render_buffer_
.get())
4018 offscreen_target_stencil_render_buffer_
->Invalidate();
4019 if (offscreen_saved_frame_buffer_
.get())
4020 offscreen_saved_frame_buffer_
->Invalidate();
4021 if (offscreen_saved_color_texture_
.get())
4022 offscreen_saved_color_texture_
->Invalidate();
4023 if (offscreen_resolved_frame_buffer_
.get())
4024 offscreen_resolved_frame_buffer_
->Invalidate();
4025 if (offscreen_resolved_color_texture_
.get())
4026 offscreen_resolved_color_texture_
->Invalidate();
4029 // Current program must be cleared after calling ProgramManager::UnuseProgram.
4030 // Otherwise, we can leak objects. http://crbug.com/258772.
4031 // state_.current_program must be reset before group_ is reset because
4032 // the later deletes the ProgramManager object that referred by
4033 // state_.current_program object.
4034 state_
.current_program
= NULL
;
4036 copy_texture_CHROMIUM_
.reset();
4037 clear_framebuffer_blit_
.reset();
4039 if (query_manager_
.get()) {
4040 query_manager_
->Destroy(have_context
);
4041 query_manager_
.reset();
4044 if (vertex_array_manager_
.get()) {
4045 vertex_array_manager_
->Destroy(have_context
);
4046 vertex_array_manager_
.reset();
4049 if (image_manager_
.get()) {
4050 image_manager_
->Destroy(have_context
);
4051 image_manager_
.reset();
4054 offscreen_target_frame_buffer_
.reset();
4055 offscreen_target_color_texture_
.reset();
4056 offscreen_target_color_render_buffer_
.reset();
4057 offscreen_target_depth_render_buffer_
.reset();
4058 offscreen_target_stencil_render_buffer_
.reset();
4059 offscreen_saved_frame_buffer_
.reset();
4060 offscreen_saved_color_texture_
.reset();
4061 offscreen_resolved_frame_buffer_
.reset();
4062 offscreen_resolved_color_texture_
.reset();
4064 // Need to release these before releasing |group_| which may own the
4065 // ShaderTranslatorCache.
4066 fragment_translator_
= NULL
;
4067 vertex_translator_
= NULL
;
4069 // Should destroy the transfer manager before the texture manager held
4070 // by the context group.
4071 async_pixel_transfer_manager_
.reset();
4073 // Destroy the GPU Tracer which may own some in process GPU Timings.
4075 gpu_tracer_
->Destroy(have_context
);
4076 gpu_tracer_
.reset();
4080 framebuffer_manager()->RemoveObserver(this);
4081 group_
->Destroy(this, have_context
);
4085 if (context_
.get()) {
4086 context_
->ReleaseCurrent(NULL
);
4090 #if defined(OS_MACOSX)
4091 for (TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.begin();
4092 it
!= texture_to_io_surface_map_
.end(); ++it
) {
4093 CFRelease(it
->second
);
4095 texture_to_io_surface_map_
.clear();
4099 void GLES2DecoderImpl::SetSurface(
4100 const scoped_refptr
<gfx::GLSurface
>& surface
) {
4101 DCHECK(context_
->IsCurrent(NULL
));
4102 DCHECK(surface_
.get());
4104 RestoreCurrentFramebufferBindings();
4107 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox
& mailbox
) {
4108 if (!offscreen_saved_color_texture_
.get()) {
4109 LOG(ERROR
) << "Called ProduceFrontBuffer on a non-offscreen context";
4112 if (!offscreen_saved_color_texture_info_
.get()) {
4113 GLuint service_id
= offscreen_saved_color_texture_
->id();
4114 offscreen_saved_color_texture_info_
= TextureRef::Create(
4115 texture_manager(), 0, service_id
);
4116 texture_manager()->SetTarget(offscreen_saved_color_texture_info_
.get(),
4118 UpdateParentTextureInfo();
4120 mailbox_manager()->ProduceTexture(
4121 mailbox
, offscreen_saved_color_texture_info_
->texture());
4124 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size
& size
) {
4125 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
4126 if (!is_offscreen
) {
4127 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
4128 << " with an onscreen framebuffer.";
4132 if (offscreen_size_
== size
)
4135 offscreen_size_
= size
;
4136 int w
= offscreen_size_
.width();
4137 int h
= offscreen_size_
.height();
4138 if (w
< 0 || h
< 0 || h
>= (INT_MAX
/ 4) / (w
? w
: 1)) {
4139 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4140 << "to allocate storage due to excessive dimensions.";
4144 // Reallocate the offscreen target buffers.
4145 DCHECK(offscreen_target_color_format_
);
4146 if (IsOffscreenBufferMultisampled()) {
4147 if (!offscreen_target_color_render_buffer_
->AllocateStorage(
4148 feature_info_
.get(),
4150 offscreen_target_color_format_
,
4151 offscreen_target_samples_
)) {
4152 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4153 << "to allocate storage for offscreen target color buffer.";
4157 if (!offscreen_target_color_texture_
->AllocateStorage(
4158 offscreen_size_
, offscreen_target_color_format_
, false)) {
4159 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4160 << "to allocate storage for offscreen target color texture.";
4164 if (offscreen_target_depth_format_
&&
4165 !offscreen_target_depth_render_buffer_
->AllocateStorage(
4166 feature_info_
.get(),
4168 offscreen_target_depth_format_
,
4169 offscreen_target_samples_
)) {
4170 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4171 << "to allocate storage for offscreen target depth buffer.";
4174 if (offscreen_target_stencil_format_
&&
4175 !offscreen_target_stencil_render_buffer_
->AllocateStorage(
4176 feature_info_
.get(),
4178 offscreen_target_stencil_format_
,
4179 offscreen_target_samples_
)) {
4180 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4181 << "to allocate storage for offscreen target stencil buffer.";
4185 // Attach the offscreen target buffers to the target frame buffer.
4186 if (IsOffscreenBufferMultisampled()) {
4187 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4188 GL_COLOR_ATTACHMENT0
,
4189 offscreen_target_color_render_buffer_
.get());
4191 offscreen_target_frame_buffer_
->AttachRenderTexture(
4192 offscreen_target_color_texture_
.get());
4194 if (offscreen_target_depth_format_
) {
4195 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4196 GL_DEPTH_ATTACHMENT
,
4197 offscreen_target_depth_render_buffer_
.get());
4199 const bool packed_depth_stencil
=
4200 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
4201 if (packed_depth_stencil
) {
4202 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4203 GL_STENCIL_ATTACHMENT
,
4204 offscreen_target_depth_render_buffer_
.get());
4205 } else if (offscreen_target_stencil_format_
) {
4206 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4207 GL_STENCIL_ATTACHMENT
,
4208 offscreen_target_stencil_render_buffer_
.get());
4211 if (offscreen_target_frame_buffer_
->CheckStatus() !=
4212 GL_FRAMEBUFFER_COMPLETE
) {
4213 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4214 << "because offscreen FBO was incomplete.";
4218 // Clear the target frame buffer.
4220 ScopedFrameBufferBinder
binder(this, offscreen_target_frame_buffer_
->id());
4221 glClearColor(0, 0, 0, BackBufferHasAlpha() ? 0 : 1.f
);
4222 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
4224 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
4225 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
4227 state_
.SetDeviceDepthMask(GL_TRUE
);
4228 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
4229 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
4230 RestoreClearState();
4233 // Destroy the offscreen resolved framebuffers.
4234 if (offscreen_resolved_frame_buffer_
.get())
4235 offscreen_resolved_frame_buffer_
->Destroy();
4236 if (offscreen_resolved_color_texture_
.get())
4237 offscreen_resolved_color_texture_
->Destroy();
4238 offscreen_resolved_color_texture_
.reset();
4239 offscreen_resolved_frame_buffer_
.reset();
4244 error::Error
GLES2DecoderImpl::HandleResizeCHROMIUM(uint32 immediate_data_size
,
4245 const void* cmd_data
) {
4246 const gles2::cmds::ResizeCHROMIUM
& c
=
4247 *static_cast<const gles2::cmds::ResizeCHROMIUM
*>(cmd_data
);
4248 if (!offscreen_target_frame_buffer_
.get() && surface_
->DeferDraws())
4249 return error::kDeferCommandUntilLater
;
4251 GLuint width
= static_cast<GLuint
>(c
.width
);
4252 GLuint height
= static_cast<GLuint
>(c
.height
);
4253 GLfloat scale_factor
= c
.scale_factor
;
4254 TRACE_EVENT2("gpu", "glResizeChromium", "width", width
, "height", height
);
4256 width
= std::max(1U, width
);
4257 height
= std::max(1U, height
);
4259 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
4260 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
4261 // Make sure that we are done drawing to the back buffer before resizing.
4264 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
4266 if (!ResizeOffscreenFrameBuffer(gfx::Size(width
, height
))) {
4267 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because "
4268 << "ResizeOffscreenFrameBuffer failed.";
4269 return error::kLostContext
;
4273 if (!resize_callback_
.is_null()) {
4274 resize_callback_
.Run(gfx::Size(width
, height
), scale_factor
);
4275 DCHECK(context_
->IsCurrent(surface_
.get()));
4276 if (!context_
->IsCurrent(surface_
.get())) {
4277 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because context no longer "
4278 << "current after resize callback.";
4279 return error::kLostContext
;
4283 return error::kNoError
;
4286 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id
) const {
4287 if (command_id
> kStartPoint
&& command_id
< kNumCommands
) {
4288 return gles2::GetCommandName(static_cast<CommandId
>(command_id
));
4290 return GetCommonCommandName(static_cast<cmd::CommandId
>(command_id
));
4293 // Decode a command, and call the corresponding GL functions.
4294 // NOTE: DoCommand() is slower than calling DoCommands() on larger batches
4295 // of commands at once, and is now only used for tests that need to track
4296 // individual commands.
4297 error::Error
GLES2DecoderImpl::DoCommand(unsigned int command
,
4298 unsigned int arg_count
,
4299 const void* cmd_data
) {
4300 return DoCommands(1, cmd_data
, arg_count
+ 1, 0);
4303 // Decode multiple commands, and call the corresponding GL functions.
4304 // NOTE: 'buffer' is a pointer to the command buffer. As such, it could be
4305 // changed by a (malicious) client at any time, so if validation has to happen,
4306 // it should operate on a copy of them.
4307 // NOTE: This is duplicating code from AsyncAPIInterface::DoCommands() in the
4308 // interest of performance in this critical execution loop.
4309 template <bool DebugImpl
>
4310 error::Error
GLES2DecoderImpl::DoCommandsImpl(unsigned int num_commands
,
4313 int* entries_processed
) {
4314 commands_to_process_
= num_commands
;
4315 error::Error result
= error::kNoError
;
4316 const CommandBufferEntry
* cmd_data
=
4317 static_cast<const CommandBufferEntry
*>(buffer
);
4318 int process_pos
= 0;
4319 unsigned int command
= 0;
4321 while (process_pos
< num_entries
&& result
== error::kNoError
&&
4322 commands_to_process_
--) {
4323 const unsigned int size
= cmd_data
->value_header
.size
;
4324 command
= cmd_data
->value_header
.command
;
4327 result
= error::kInvalidSize
;
4331 if (static_cast<int>(size
) + process_pos
> num_entries
) {
4332 result
= error::kOutOfBounds
;
4337 TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4338 GetCommandName(command
));
4340 if (log_commands()) {
4341 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "]"
4342 << "cmd: " << GetCommandName(command
);
4346 const unsigned int arg_count
= size
- 1;
4347 unsigned int command_index
= command
- kStartPoint
- 1;
4348 if (command_index
< arraysize(command_info
)) {
4349 const CommandInfo
& info
= command_info
[command_index
];
4350 unsigned int info_arg_count
= static_cast<unsigned int>(info
.arg_count
);
4351 if ((info
.arg_flags
== cmd::kFixed
&& arg_count
== info_arg_count
) ||
4352 (info
.arg_flags
== cmd::kAtLeastN
&& arg_count
>= info_arg_count
)) {
4353 bool doing_gpu_trace
= false;
4354 if (DebugImpl
&& gpu_trace_commands_
) {
4355 if (CMD_FLAG_GET_TRACE_LEVEL(info
.cmd_flags
) <= gpu_trace_level_
) {
4356 doing_gpu_trace
= true;
4357 gpu_tracer_
->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_decoder"),
4358 GetCommandName(command
),
4363 uint32 immediate_data_size
= (arg_count
- info_arg_count
) *
4364 sizeof(CommandBufferEntry
); // NOLINT
4366 result
= (this->*info
.cmd_handler
)(immediate_data_size
, cmd_data
);
4368 if (DebugImpl
&& doing_gpu_trace
)
4369 gpu_tracer_
->End(kTraceDecoder
);
4371 if (DebugImpl
&& debug()) {
4373 while ((error
= glGetError()) != GL_NO_ERROR
) {
4374 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "] "
4375 << "GL ERROR: " << GLES2Util::GetStringEnum(error
)
4376 << " : " << GetCommandName(command
);
4377 LOCAL_SET_GL_ERROR(error
, "DoCommand", "GL error from driver");
4381 result
= error::kInvalidArguments
;
4384 result
= DoCommonCommand(command
, arg_count
, cmd_data
);
4388 TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4389 GetCommandName(command
));
4392 if (result
== error::kNoError
&&
4393 current_decoder_error_
!= error::kNoError
) {
4394 result
= current_decoder_error_
;
4395 current_decoder_error_
= error::kNoError
;
4398 if (result
!= error::kDeferCommandUntilLater
) {
4399 process_pos
+= size
;
4404 if (entries_processed
)
4405 *entries_processed
= process_pos
;
4407 if (error::IsError(result
)) {
4408 LOG(ERROR
) << "Error: " << result
<< " for Command "
4409 << GetCommandName(command
);
4415 error::Error
GLES2DecoderImpl::DoCommands(unsigned int num_commands
,
4418 int* entries_processed
) {
4419 if (gpu_debug_commands_
) {
4420 return DoCommandsImpl
<true>(
4421 num_commands
, buffer
, num_entries
, entries_processed
);
4423 return DoCommandsImpl
<false>(
4424 num_commands
, buffer
, num_entries
, entries_processed
);
4428 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id
) {
4429 buffer_manager()->RemoveBuffer(client_id
);
4432 void GLES2DecoderImpl::DoFinish() {
4434 ProcessPendingReadPixels(true);
4435 ProcessPendingQueries(true);
4438 void GLES2DecoderImpl::DoFlush() {
4440 ProcessPendingQueries(false);
4443 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit
) {
4444 GLuint texture_index
= texture_unit
- GL_TEXTURE0
;
4445 if (texture_index
>= state_
.texture_units
.size()) {
4446 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4447 "glActiveTexture", texture_unit
, "texture_unit");
4450 state_
.active_texture_unit
= texture_index
;
4451 glActiveTexture(texture_unit
);
4454 void GLES2DecoderImpl::DoBindBuffer(GLenum target
, GLuint client_id
) {
4455 Buffer
* buffer
= NULL
;
4456 GLuint service_id
= 0;
4457 if (client_id
!= 0) {
4458 buffer
= GetBuffer(client_id
);
4460 if (!group_
->bind_generates_resource()) {
4461 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4463 "id not generated by glGenBuffers");
4467 // It's a new id so make a buffer buffer for it.
4468 glGenBuffersARB(1, &service_id
);
4469 CreateBuffer(client_id
, service_id
);
4470 buffer
= GetBuffer(client_id
);
4473 LogClientServiceForInfo(buffer
, client_id
, "glBindBuffer");
4475 if (!buffer_manager()->SetTarget(buffer
, target
)) {
4477 GL_INVALID_OPERATION
,
4478 "glBindBuffer", "buffer bound to more than 1 target");
4481 service_id
= buffer
->service_id();
4483 state_
.SetBoundBuffer(target
, buffer
);
4484 glBindBuffer(target
, service_id
);
4487 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha() {
4488 Framebuffer
* framebuffer
=
4489 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4491 return framebuffer
->HasAlphaMRT();
4492 return BackBufferHasAlpha();
4495 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
4496 Framebuffer
* framebuffer
=
4497 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4499 return framebuffer
->HasDepthAttachment();
4501 if (offscreen_target_frame_buffer_
.get()) {
4502 return offscreen_target_depth_format_
!= 0;
4504 return back_buffer_has_depth_
;
4507 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
4508 Framebuffer
* framebuffer
=
4509 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4511 return framebuffer
->HasStencilAttachment();
4513 if (offscreen_target_frame_buffer_
.get()) {
4514 return offscreen_target_stencil_format_
!= 0 ||
4515 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
4517 return back_buffer_has_stencil_
;
4520 void GLES2DecoderImpl::ApplyDirtyState() {
4521 if (framebuffer_state_
.clear_state_dirty
) {
4522 bool have_alpha
= BoundFramebufferHasColorAttachmentWithAlpha();
4523 state_
.SetDeviceColorMask(state_
.color_mask_red
,
4524 state_
.color_mask_green
,
4525 state_
.color_mask_blue
,
4526 state_
.color_mask_alpha
&& have_alpha
);
4528 bool have_depth
= BoundFramebufferHasDepthAttachment();
4529 state_
.SetDeviceDepthMask(state_
.depth_mask
&& have_depth
);
4531 bool have_stencil
= BoundFramebufferHasStencilAttachment();
4532 state_
.SetDeviceStencilMaskSeparate(
4533 GL_FRONT
, have_stencil
? state_
.stencil_front_writemask
: 0);
4534 state_
.SetDeviceStencilMaskSeparate(
4535 GL_BACK
, have_stencil
? state_
.stencil_back_writemask
: 0);
4537 state_
.SetDeviceCapabilityState(
4538 GL_DEPTH_TEST
, state_
.enable_flags
.depth_test
&& have_depth
);
4539 state_
.SetDeviceCapabilityState(
4540 GL_STENCIL_TEST
, state_
.enable_flags
.stencil_test
&& have_stencil
);
4541 framebuffer_state_
.clear_state_dirty
= false;
4545 GLuint
GLES2DecoderImpl::GetBackbufferServiceId() const {
4546 return (offscreen_target_frame_buffer_
.get())
4547 ? offscreen_target_frame_buffer_
->id()
4548 : (surface_
.get() ? surface_
->GetBackingFrameBufferObject() : 0);
4551 void GLES2DecoderImpl::RestoreState(const ContextState
* prev_state
) {
4552 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
4553 "context", logger_
.GetLogPrefix());
4554 // Restore the Framebuffer first because of bugs in Intel drivers.
4555 // Intel drivers incorrectly clip the viewport settings to
4556 // the size of the current framebuffer object.
4557 RestoreFramebufferBindings();
4558 state_
.RestoreState(prev_state
);
4561 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
4563 framebuffer_state_
.bound_draw_framebuffer
.get()
4564 ? framebuffer_state_
.bound_draw_framebuffer
->service_id()
4565 : GetBackbufferServiceId();
4566 if (!features().chromium_framebuffer_multisample
) {
4567 glBindFramebufferEXT(GL_FRAMEBUFFER
, service_id
);
4569 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, service_id
);
4570 service_id
= framebuffer_state_
.bound_read_framebuffer
.get()
4571 ? framebuffer_state_
.bound_read_framebuffer
->service_id()
4572 : GetBackbufferServiceId();
4573 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, service_id
);
4578 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
4579 state_
.RestoreRenderbufferBindings();
4582 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id
) const {
4583 Texture
* texture
= texture_manager()->GetTextureForServiceId(service_id
);
4585 GLenum target
= texture
->target();
4586 glBindTexture(target
, service_id
);
4588 target
, GL_TEXTURE_WRAP_S
, texture
->wrap_s());
4590 target
, GL_TEXTURE_WRAP_T
, texture
->wrap_t());
4592 target
, GL_TEXTURE_MIN_FILTER
, texture
->min_filter());
4594 target
, GL_TEXTURE_MAG_FILTER
, texture
->mag_filter());
4595 RestoreTextureUnitBindings(state_
.active_texture_unit
);
4599 void GLES2DecoderImpl::ClearAllAttributes() const {
4600 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
4602 if (feature_info_
->feature_flags().native_vertex_array_object
)
4603 glBindVertexArrayOES(0);
4605 for (uint32 i
= 0; i
< group_
->max_vertex_attribs(); ++i
) {
4606 if (i
!= 0) // Never disable attribute 0
4607 glDisableVertexAttribArray(i
);
4608 if (features().angle_instanced_arrays
)
4609 glVertexAttribDivisorANGLE(i
, 0);
4613 void GLES2DecoderImpl::RestoreAllAttributes() const {
4614 state_
.RestoreVertexAttribs();
4617 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore
) {
4618 state_
.SetIgnoreCachedStateForTest(ignore
);
4621 void GLES2DecoderImpl::OnFboChanged() const {
4622 if (workarounds().restore_scissor_on_fbo_change
)
4623 state_
.fbo_binding_for_scissor_workaround_dirty
= true;
4625 if (workarounds().gl_begin_gl_end_on_fbo_change_to_backbuffer
) {
4626 GLint bound_fbo_unsigned
= -1;
4627 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT
, &bound_fbo_unsigned
);
4628 GLuint bound_fbo
= static_cast<GLuint
>(bound_fbo_unsigned
);
4629 if (surface_
&& surface_
->GetBackingFrameBufferObject() == bound_fbo
)
4630 surface_
->NotifyWasBound();
4634 // Called after the FBO is checked for completeness.
4635 void GLES2DecoderImpl::OnUseFramebuffer() const {
4636 if (state_
.fbo_binding_for_scissor_workaround_dirty
) {
4637 state_
.fbo_binding_for_scissor_workaround_dirty
= false;
4638 // The driver forgets the correct scissor when modifying the FBO binding.
4639 glScissor(state_
.scissor_x
,
4641 state_
.scissor_width
,
4642 state_
.scissor_height
);
4644 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
4645 // it's unclear how this bug works.
4650 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target
, GLuint client_id
) {
4651 Framebuffer
* framebuffer
= NULL
;
4652 GLuint service_id
= 0;
4653 if (client_id
!= 0) {
4654 framebuffer
= GetFramebuffer(client_id
);
4656 if (!group_
->bind_generates_resource()) {
4657 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4658 "glBindFramebuffer",
4659 "id not generated by glGenFramebuffers");
4663 // It's a new id so make a framebuffer framebuffer for it.
4664 glGenFramebuffersEXT(1, &service_id
);
4665 CreateFramebuffer(client_id
, service_id
);
4666 framebuffer
= GetFramebuffer(client_id
);
4668 service_id
= framebuffer
->service_id();
4670 framebuffer
->MarkAsValid();
4672 LogClientServiceForInfo(framebuffer
, client_id
, "glBindFramebuffer");
4674 if (target
== GL_FRAMEBUFFER
|| target
== GL_DRAW_FRAMEBUFFER_EXT
) {
4675 framebuffer_state_
.bound_draw_framebuffer
= framebuffer
;
4678 // vmiura: This looks like dup code
4679 if (target
== GL_FRAMEBUFFER
|| target
== GL_READ_FRAMEBUFFER_EXT
) {
4680 framebuffer_state_
.bound_read_framebuffer
= framebuffer
;
4683 framebuffer_state_
.clear_state_dirty
= true;
4685 // If we are rendering to the backbuffer get the FBO id for any simulated
4687 if (framebuffer
== NULL
) {
4688 service_id
= GetBackbufferServiceId();
4691 glBindFramebufferEXT(target
, service_id
);
4695 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target
, GLuint client_id
) {
4696 Renderbuffer
* renderbuffer
= NULL
;
4697 GLuint service_id
= 0;
4698 if (client_id
!= 0) {
4699 renderbuffer
= GetRenderbuffer(client_id
);
4700 if (!renderbuffer
) {
4701 if (!group_
->bind_generates_resource()) {
4702 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4703 "glBindRenderbuffer",
4704 "id not generated by glGenRenderbuffers");
4708 // It's a new id so make a renderbuffer for it.
4709 glGenRenderbuffersEXT(1, &service_id
);
4710 CreateRenderbuffer(client_id
, service_id
);
4711 renderbuffer
= GetRenderbuffer(client_id
);
4713 service_id
= renderbuffer
->service_id();
4715 renderbuffer
->MarkAsValid();
4717 LogClientServiceForInfo(renderbuffer
, client_id
, "glBindRenderbuffer");
4718 state_
.bound_renderbuffer
= renderbuffer
;
4719 state_
.bound_renderbuffer_valid
= true;
4720 glBindRenderbufferEXT(GL_RENDERBUFFER
, service_id
);
4723 void GLES2DecoderImpl::DoBindTexture(GLenum target
, GLuint client_id
) {
4724 TextureRef
* texture_ref
= NULL
;
4725 GLuint service_id
= 0;
4726 if (client_id
!= 0) {
4727 texture_ref
= GetTexture(client_id
);
4729 if (!group_
->bind_generates_resource()) {
4730 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4732 "id not generated by glGenTextures");
4736 // It's a new id so make a texture texture for it.
4737 glGenTextures(1, &service_id
);
4738 DCHECK_NE(0u, service_id
);
4739 CreateTexture(client_id
, service_id
);
4740 texture_ref
= GetTexture(client_id
);
4743 texture_ref
= texture_manager()->GetDefaultTextureInfo(target
);
4746 // Check the texture exists
4748 Texture
* texture
= texture_ref
->texture();
4749 // Check that we are not trying to bind it to a different target.
4750 if (texture
->target() != 0 && texture
->target() != target
) {
4751 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4753 "texture bound to more than 1 target.");
4756 LogClientServiceForInfo(texture
, client_id
, "glBindTexture");
4757 if (texture
->target() == 0) {
4758 texture_manager()->SetTarget(texture_ref
, target
);
4760 glBindTexture(target
, texture
->service_id());
4762 glBindTexture(target
, 0);
4765 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4766 unit
.bind_target
= target
;
4769 unit
.bound_texture_2d
= texture_ref
;
4771 case GL_TEXTURE_CUBE_MAP
:
4772 unit
.bound_texture_cube_map
= texture_ref
;
4774 case GL_TEXTURE_EXTERNAL_OES
:
4775 unit
.bound_texture_external_oes
= texture_ref
;
4777 case GL_TEXTURE_RECTANGLE_ARB
:
4778 unit
.bound_texture_rectangle_arb
= texture_ref
;
4781 unit
.bound_texture_3d
= texture_ref
;
4783 case GL_TEXTURE_2D_ARRAY
:
4784 unit
.bound_texture_2d_array
= texture_ref
;
4787 NOTREACHED(); // Validation should prevent us getting here.
4792 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index
) {
4793 if (state_
.vertex_attrib_manager
->Enable(index
, false)) {
4795 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
4796 glDisableVertexAttribArray(index
);
4801 "glDisableVertexAttribArray", "index out of range");
4805 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target
,
4806 GLsizei numAttachments
,
4807 const GLenum
* attachments
) {
4808 if (workarounds().disable_discard_framebuffer
)
4811 Framebuffer
* framebuffer
=
4812 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
4814 // Validates the attachments. If one of them fails
4815 // the whole command fails.
4816 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4818 !validators_
->attachment
.IsValid(attachments
[i
])) ||
4820 !validators_
->backbuffer_attachment
.IsValid(attachments
[i
]))) {
4821 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4822 "glDiscardFramebufferEXT", attachments
[i
], "attachments");
4827 // Marks each one of them as not cleared
4828 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4830 framebuffer
->MarkAttachmentAsCleared(renderbuffer_manager(),
4835 switch (attachments
[i
]) {
4837 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
4840 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
4841 case GL_STENCIL_EXT
:
4842 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
4851 // If the default framebuffer is bound but we are still rendering to an
4852 // FBO, translate attachment names that refer to default framebuffer
4853 // channels to corresponding framebuffer attachments.
4854 scoped_ptr
<GLenum
[]> translated_attachments(new GLenum
[numAttachments
]);
4855 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4856 GLenum attachment
= attachments
[i
];
4857 if (!framebuffer
&& GetBackbufferServiceId()) {
4858 switch (attachment
) {
4860 attachment
= GL_COLOR_ATTACHMENT0
;
4863 attachment
= GL_DEPTH_ATTACHMENT
;
4865 case GL_STENCIL_EXT
:
4866 attachment
= GL_STENCIL_ATTACHMENT
;
4873 translated_attachments
[i
] = attachment
;
4876 ScopedRenderTo
do_render(framebuffer
);
4877 if (feature_info_
->gl_version_info().is_es3
) {
4878 glInvalidateFramebuffer(
4879 target
, numAttachments
, translated_attachments
.get());
4881 glDiscardFramebufferEXT(
4882 target
, numAttachments
, translated_attachments
.get());
4886 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index
) {
4887 if (state_
.vertex_attrib_manager
->Enable(index
, true)) {
4888 glEnableVertexAttribArray(index
);
4891 GL_INVALID_VALUE
, "glEnableVertexAttribArray", "index out of range");
4895 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target
) {
4896 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
4899 !texture_manager()->CanGenerateMipmaps(texture_ref
)) {
4901 GL_INVALID_OPERATION
, "glGenerateMipmap", "Can not generate mips");
4905 if (target
== GL_TEXTURE_CUBE_MAP
) {
4906 for (int i
= 0; i
< 6; ++i
) {
4907 GLenum face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ i
;
4908 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, face
, 0)) {
4910 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
4915 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
, 0)) {
4917 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
4922 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4923 // Workaround for Mac driver bug. In the large scheme of things setting
4924 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4925 // hit so there's probably no need to make this conditional. The bug appears
4926 // to be that if the filtering mode is set to something that doesn't require
4927 // mipmaps for rendering, or is never set to something other than the default,
4928 // then glGenerateMipmap misbehaves.
4929 if (workarounds().set_texture_filter_before_generating_mipmap
) {
4930 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST_MIPMAP_NEAREST
);
4932 glGenerateMipmapEXT(target
);
4933 if (workarounds().set_texture_filter_before_generating_mipmap
) {
4934 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
,
4935 texture_ref
->texture()->min_filter());
4937 GLenum error
= LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4938 if (error
== GL_NO_ERROR
) {
4939 texture_manager()->MarkMipmapsGenerated(texture_ref
);
4943 bool GLES2DecoderImpl::GetHelper(
4944 GLenum pname
, GLint
* params
, GLsizei
* num_written
) {
4945 DCHECK(num_written
);
4946 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
4948 case GL_IMPLEMENTATION_COLOR_READ_FORMAT
:
4950 // Return the GL implementation's preferred format and (see below type)
4951 // if we have the GL extension that exposes this. This allows the GPU
4952 // client to use the implementation's preferred format for glReadPixels
4953 // for optimisation.
4955 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4956 // case when requested on integer/floating point buffers but which is
4957 // acceptable on GLES2 and with the GL_OES_read_format extension.
4959 // Therefore if an error occurs we swallow the error and use the
4960 // internal implementation.
4962 if (context_
->HasExtension("GL_OES_read_format")) {
4963 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
4965 glGetIntegerv(pname
, params
);
4966 if (glGetError() == GL_NO_ERROR
)
4969 *params
= GLES2Util::GetPreferredGLReadPixelsFormat(
4970 GetBoundReadFrameBufferInternalFormat());
4973 case GL_IMPLEMENTATION_COLOR_READ_TYPE
:
4976 if (context_
->HasExtension("GL_OES_read_format")) {
4977 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
4979 glGetIntegerv(pname
, params
);
4980 if (glGetError() == GL_NO_ERROR
)
4983 *params
= GLES2Util::GetPreferredGLReadPixelsType(
4984 GetBoundReadFrameBufferInternalFormat(),
4985 GetBoundReadFrameBufferTextureType());
4988 case GL_MAX_FRAGMENT_UNIFORM_VECTORS
:
4991 *params
= group_
->max_fragment_uniform_vectors();
4994 case GL_MAX_VARYING_VECTORS
:
4997 *params
= group_
->max_varying_vectors();
5000 case GL_MAX_VERTEX_UNIFORM_VECTORS
:
5003 *params
= group_
->max_vertex_uniform_vectors();
5008 if (unsafe_es3_apis_enabled()) {
5010 case GL_MAX_VARYING_COMPONENTS
: {
5011 if (feature_info_
->gl_version_info().is_es
) {
5012 // We can just delegate this query to the driver.
5016 // GL_MAX_VARYING_COMPONENTS is deprecated in the desktop
5017 // OpenGL core profile, so for simplicity, just compute it
5018 // from GL_MAX_VARYING_VECTORS on non-OpenGL ES
5020 GLint max_varying_vectors
= 0;
5021 glGetIntegerv(GL_MAX_VARYING_VECTORS
, &max_varying_vectors
);
5024 *params
= max_varying_vectors
* 4;
5028 case GL_READ_BUFFER
:
5031 Framebuffer
* framebuffer
=
5032 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER
);
5035 read_buffer
= framebuffer
->read_buffer();
5037 read_buffer
= back_buffer_read_buffer_
;
5039 *params
= static_cast<GLint
>(read_buffer
);
5045 case GL_MAX_VIEWPORT_DIMS
:
5046 if (offscreen_target_frame_buffer_
.get()) {
5049 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
5050 params
[1] = renderbuffer_manager()->max_renderbuffer_size();
5055 case GL_MAX_SAMPLES
:
5058 params
[0] = renderbuffer_manager()->max_samples();
5061 case GL_MAX_RENDERBUFFER_SIZE
:
5064 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
5067 case GL_MAX_TEXTURE_SIZE
:
5070 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D
);
5073 case GL_MAX_CUBE_MAP_TEXTURE_SIZE
:
5076 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP
);
5079 case GL_MAX_COLOR_ATTACHMENTS_EXT
:
5082 params
[0] = group_
->max_color_attachments();
5085 case GL_MAX_DRAW_BUFFERS_ARB
:
5088 params
[0] = group_
->max_draw_buffers();
5095 Framebuffer
* framebuffer
=
5096 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5098 if (framebuffer
->HasAlphaMRT() &&
5099 framebuffer
->HasSameInternalFormatsMRT()) {
5100 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
5101 glGetFramebufferAttachmentParameterivEXT(
5102 GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
5103 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE
, &v
);
5105 glGetIntegerv(GL_ALPHA_BITS
, &v
);
5109 v
= (BackBufferHasAlpha() ? 8 : 0);
5118 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
5119 Framebuffer
* framebuffer
=
5120 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5122 glGetFramebufferAttachmentParameterivEXT(
5123 GL_FRAMEBUFFER
, GL_DEPTH_ATTACHMENT
,
5124 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE
, &v
);
5126 v
= (back_buffer_has_depth_
? 24 : 0);
5129 glGetIntegerv(GL_DEPTH_BITS
, &v
);
5131 params
[0] = BoundFramebufferHasDepthAttachment() ? v
: 0;
5140 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
5141 Framebuffer
* framebuffer
=
5142 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5144 GLenum framebuffer_enum
= 0;
5147 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE
;
5150 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE
;
5153 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE
;
5156 glGetFramebufferAttachmentParameterivEXT(
5157 GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
, framebuffer_enum
, &v
);
5162 glGetIntegerv(pname
, &v
);
5167 case GL_STENCIL_BITS
:
5171 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
5172 Framebuffer
* framebuffer
=
5173 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5175 glGetFramebufferAttachmentParameterivEXT(
5176 GL_FRAMEBUFFER
, GL_STENCIL_ATTACHMENT
,
5177 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE
, &v
);
5179 v
= (back_buffer_has_stencil_
? 8 : 0);
5182 glGetIntegerv(GL_STENCIL_BITS
, &v
);
5184 params
[0] = BoundFramebufferHasStencilAttachment() ? v
: 0;
5187 case GL_COMPRESSED_TEXTURE_FORMATS
:
5188 *num_written
= validators_
->compressed_texture_format
.GetValues().size();
5190 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
5191 params
[ii
] = validators_
->compressed_texture_format
.GetValues()[ii
];
5195 case GL_NUM_COMPRESSED_TEXTURE_FORMATS
:
5198 *params
= validators_
->compressed_texture_format
.GetValues().size();
5201 case GL_NUM_SHADER_BINARY_FORMATS
:
5204 *params
= validators_
->shader_binary_format
.GetValues().size();
5207 case GL_SHADER_BINARY_FORMATS
:
5208 *num_written
= validators_
->shader_binary_format
.GetValues().size();
5210 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
5211 params
[ii
] = validators_
->shader_binary_format
.GetValues()[ii
];
5215 case GL_SHADER_COMPILER
:
5221 case GL_ARRAY_BUFFER_BINDING
:
5224 *params
= GetClientId(
5225 buffer_manager(), state_
.bound_array_buffer
.get());
5228 case GL_ELEMENT_ARRAY_BUFFER_BINDING
:
5231 *params
= GetClientId(
5233 state_
.vertex_attrib_manager
->element_array_buffer());
5236 case GL_COPY_READ_BUFFER_BINDING
:
5239 *params
= GetClientId(
5240 buffer_manager(), state_
.bound_copy_read_buffer
.get());
5243 case GL_COPY_WRITE_BUFFER_BINDING
:
5246 *params
= GetClientId(
5247 buffer_manager(), state_
.bound_copy_write_buffer
.get());
5250 case GL_PIXEL_PACK_BUFFER_BINDING
:
5253 *params
= GetClientId(
5254 buffer_manager(), state_
.bound_pixel_pack_buffer
.get());
5257 case GL_PIXEL_UNPACK_BUFFER_BINDING
:
5260 *params
= GetClientId(
5261 buffer_manager(), state_
.bound_pixel_unpack_buffer
.get());
5264 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING
:
5267 *params
= GetClientId(
5268 buffer_manager(), state_
.bound_transform_feedback_buffer
.get());
5271 case GL_UNIFORM_BUFFER_BINDING
:
5274 *params
= GetClientId(
5275 buffer_manager(), state_
.bound_uniform_buffer
.get());
5278 case GL_FRAMEBUFFER_BINDING
:
5279 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
5282 *params
= GetClientId(
5283 framebuffer_manager(),
5284 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
));
5287 case GL_READ_FRAMEBUFFER_BINDING_EXT
:
5290 *params
= GetClientId(
5291 framebuffer_manager(),
5292 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
));
5295 case GL_RENDERBUFFER_BINDING
:
5298 Renderbuffer
* renderbuffer
=
5299 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5301 *params
= renderbuffer
->client_id();
5307 case GL_CURRENT_PROGRAM
:
5310 *params
= GetClientId(program_manager(), state_
.current_program
.get());
5313 case GL_VERTEX_ARRAY_BINDING_OES
:
5316 if (state_
.vertex_attrib_manager
.get() !=
5317 state_
.default_vertex_attrib_manager
.get()) {
5318 GLuint client_id
= 0;
5319 vertex_array_manager_
->GetClientId(
5320 state_
.vertex_attrib_manager
->service_id(), &client_id
);
5321 *params
= client_id
;
5327 case GL_TEXTURE_BINDING_2D
:
5330 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5331 if (unit
.bound_texture_2d
.get()) {
5332 *params
= unit
.bound_texture_2d
->client_id();
5338 case GL_TEXTURE_BINDING_CUBE_MAP
:
5341 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5342 if (unit
.bound_texture_cube_map
.get()) {
5343 *params
= unit
.bound_texture_cube_map
->client_id();
5349 case GL_TEXTURE_BINDING_EXTERNAL_OES
:
5352 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5353 if (unit
.bound_texture_external_oes
.get()) {
5354 *params
= unit
.bound_texture_external_oes
->client_id();
5360 case GL_TEXTURE_BINDING_RECTANGLE_ARB
:
5363 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5364 if (unit
.bound_texture_rectangle_arb
.get()) {
5365 *params
= unit
.bound_texture_rectangle_arb
->client_id();
5371 case GL_BIND_GENERATES_RESOURCE_CHROMIUM
:
5374 params
[0] = group_
->bind_generates_resource() ? 1 : 0;
5378 if (pname
>= GL_DRAW_BUFFER0_ARB
&&
5379 pname
< GL_DRAW_BUFFER0_ARB
+ group_
->max_draw_buffers()) {
5382 Framebuffer
* framebuffer
=
5383 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
5385 params
[0] = framebuffer
->GetDrawBuffer(pname
);
5386 } else { // backbuffer
5387 if (pname
== GL_DRAW_BUFFER0_ARB
)
5388 params
[0] = back_buffer_draw_buffer_
;
5390 params
[0] = GL_NONE
;
5395 *num_written
= util_
.GLGetNumValuesReturned(pname
);
5400 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
5401 GLenum pname
, GLsizei
* num_values
) {
5402 if (state_
.GetStateAsGLint(pname
, NULL
, num_values
)) {
5405 return GetHelper(pname
, NULL
, num_values
);
5408 GLenum
GLES2DecoderImpl::AdjustGetPname(GLenum pname
) {
5409 if (GL_MAX_SAMPLES
== pname
&&
5410 features().use_img_for_multisampled_render_to_texture
) {
5411 return GL_MAX_SAMPLES_IMG
;
5416 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname
, GLboolean
* params
) {
5418 GLsizei num_written
= 0;
5419 if (GetNumValuesReturnedForGLGet(pname
, &num_written
)) {
5420 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
5421 if (!state_
.GetStateAsGLint(pname
, values
.get(), &num_written
)) {
5422 GetHelper(pname
, values
.get(), &num_written
);
5424 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
5425 params
[ii
] = static_cast<GLboolean
>(values
[ii
]);
5428 pname
= AdjustGetPname(pname
);
5429 glGetBooleanv(pname
, params
);
5433 void GLES2DecoderImpl::DoGetFloatv(GLenum pname
, GLfloat
* params
) {
5435 GLsizei num_written
= 0;
5436 if (!state_
.GetStateAsGLfloat(pname
, params
, &num_written
)) {
5437 if (GetHelper(pname
, NULL
, &num_written
)) {
5438 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
5439 GetHelper(pname
, values
.get(), &num_written
);
5440 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
5441 params
[ii
] = static_cast<GLfloat
>(values
[ii
]);
5444 pname
= AdjustGetPname(pname
);
5445 glGetFloatv(pname
, params
);
5450 void GLES2DecoderImpl::DoGetInteger64v(GLenum pname
, GLint64
* params
) {
5452 if (unsafe_es3_apis_enabled()) {
5454 case GL_MAX_ELEMENT_INDEX
: {
5455 if (feature_info_
->gl_version_info().IsAtLeastGLES(3, 0) ||
5456 feature_info_
->gl_version_info().IsAtLeastGL(4, 3)) {
5457 glGetInteger64v(GL_MAX_ELEMENT_INDEX
, params
);
5459 // Assume that desktop GL implementations can generally support
5462 *params
= std::numeric_limits
<unsigned int>::max();
5469 pname
= AdjustGetPname(pname
);
5470 glGetInteger64v(pname
, params
);
5473 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname
, GLint
* params
) {
5475 GLsizei num_written
;
5476 if (!state_
.GetStateAsGLint(pname
, params
, &num_written
) &&
5477 !GetHelper(pname
, params
, &num_written
)) {
5478 pname
= AdjustGetPname(pname
);
5479 glGetIntegerv(pname
, params
);
5483 void GLES2DecoderImpl::DoGetProgramiv(
5484 GLuint program_id
, GLenum pname
, GLint
* params
) {
5485 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetProgramiv");
5489 program
->GetProgramiv(pname
, params
);
5492 void GLES2DecoderImpl::DoGetBufferParameteri64v(
5493 GLenum target
, GLenum pname
, GLint64
* params
) {
5494 // Just delegate it. Some validation is actually done before this.
5495 buffer_manager()->ValidateAndDoGetBufferParameteri64v(
5496 &state_
, target
, pname
, params
);
5499 void GLES2DecoderImpl::DoGetBufferParameteriv(
5500 GLenum target
, GLenum pname
, GLint
* params
) {
5501 // Just delegate it. Some validation is actually done before this.
5502 buffer_manager()->ValidateAndDoGetBufferParameteriv(
5503 &state_
, target
, pname
, params
);
5506 void GLES2DecoderImpl::DoBindAttribLocation(
5507 GLuint program_id
, GLuint index
, const char* name
) {
5508 if (!StringIsValidForGLES(name
)) {
5510 GL_INVALID_VALUE
, "glBindAttribLocation", "Invalid character");
5513 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
5515 GL_INVALID_OPERATION
, "glBindAttribLocation", "reserved prefix");
5518 if (index
>= group_
->max_vertex_attribs()) {
5520 GL_INVALID_VALUE
, "glBindAttribLocation", "index out of range");
5523 Program
* program
= GetProgramInfoNotShader(
5524 program_id
, "glBindAttribLocation");
5528 // At this point, the program's shaders may not be translated yet,
5529 // therefore, we may not find the hashed attribute name.
5530 // glBindAttribLocation call with original name is useless.
5531 // So instead, we should simply cache the binding, and then call
5532 // Program::ExecuteBindAttribLocationCalls() right before link.
5533 program
->SetAttribLocationBinding(name
, static_cast<GLint
>(index
));
5534 // TODO(zmo): Get rid of the following glBindAttribLocation call.
5535 glBindAttribLocation(program
->service_id(), index
, name
);
5538 error::Error
GLES2DecoderImpl::HandleBindAttribLocationBucket(
5539 uint32 immediate_data_size
,
5540 const void* cmd_data
) {
5541 const gles2::cmds::BindAttribLocationBucket
& c
=
5542 *static_cast<const gles2::cmds::BindAttribLocationBucket
*>(cmd_data
);
5543 GLuint program
= static_cast<GLuint
>(c
.program
);
5544 GLuint index
= static_cast<GLuint
>(c
.index
);
5545 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
5546 if (!bucket
|| bucket
->size() == 0) {
5547 return error::kInvalidArguments
;
5549 std::string name_str
;
5550 if (!bucket
->GetAsString(&name_str
)) {
5551 return error::kInvalidArguments
;
5553 DoBindAttribLocation(program
, index
, name_str
.c_str());
5554 return error::kNoError
;
5557 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
5558 GLuint program_id
, GLint location
, const char* name
) {
5559 if (!StringIsValidForGLES(name
)) {
5562 "glBindUniformLocationCHROMIUM", "Invalid character");
5565 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
5567 GL_INVALID_OPERATION
,
5568 "glBindUniformLocationCHROMIUM", "reserved prefix");
5571 if (location
< 0 || static_cast<uint32
>(location
) >=
5572 (group_
->max_fragment_uniform_vectors() +
5573 group_
->max_vertex_uniform_vectors()) * 4) {
5576 "glBindUniformLocationCHROMIUM", "location out of range");
5579 Program
* program
= GetProgramInfoNotShader(
5580 program_id
, "glBindUniformLocationCHROMIUM");
5584 if (!program
->SetUniformLocationBinding(name
, location
)) {
5587 "glBindUniformLocationCHROMIUM", "location out of range");
5591 error::Error
GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
5592 uint32 immediate_data_size
,
5593 const void* cmd_data
) {
5594 const gles2::cmds::BindUniformLocationCHROMIUMBucket
& c
=
5595 *static_cast<const gles2::cmds::BindUniformLocationCHROMIUMBucket
*>(
5597 GLuint program
= static_cast<GLuint
>(c
.program
);
5598 GLint location
= static_cast<GLint
>(c
.location
);
5599 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
5600 if (!bucket
|| bucket
->size() == 0) {
5601 return error::kInvalidArguments
;
5603 std::string name_str
;
5604 if (!bucket
->GetAsString(&name_str
)) {
5605 return error::kInvalidArguments
;
5607 DoBindUniformLocationCHROMIUM(program
, location
, name_str
.c_str());
5608 return error::kNoError
;
5611 error::Error
GLES2DecoderImpl::HandleDeleteShader(uint32 immediate_data_size
,
5612 const void* cmd_data
) {
5613 const gles2::cmds::DeleteShader
& c
=
5614 *static_cast<const gles2::cmds::DeleteShader
*>(cmd_data
);
5615 GLuint client_id
= c
.shader
;
5617 Shader
* shader
= GetShader(client_id
);
5619 if (!shader
->IsDeleted()) {
5620 shader_manager()->Delete(shader
);
5623 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glDeleteShader", "unknown shader");
5626 return error::kNoError
;
5629 error::Error
GLES2DecoderImpl::HandleDeleteProgram(uint32 immediate_data_size
,
5630 const void* cmd_data
) {
5631 const gles2::cmds::DeleteProgram
& c
=
5632 *static_cast<const gles2::cmds::DeleteProgram
*>(cmd_data
);
5633 GLuint client_id
= c
.program
;
5635 Program
* program
= GetProgram(client_id
);
5637 if (!program
->IsDeleted()) {
5638 program_manager()->MarkAsDeleted(shader_manager(), program
);
5642 GL_INVALID_VALUE
, "glDeleteProgram", "unknown program");
5645 return error::kNoError
;
5648 error::Error
GLES2DecoderImpl::DoClear(GLbitfield mask
) {
5649 DCHECK(!ShouldDeferDraws());
5650 if (CheckBoundFramebuffersValid("glClear")) {
5652 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
5653 if (workarounds().gl_clear_broken
) {
5654 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::ClearWorkaround",
5656 if (!BoundFramebufferHasDepthAttachment())
5657 mask
&= ~GL_DEPTH_BUFFER_BIT
;
5658 if (!BoundFramebufferHasStencilAttachment())
5659 mask
&= ~GL_STENCIL_BUFFER_BIT
;
5660 clear_framebuffer_blit_
->ClearFramebuffer(
5661 this, GetBoundReadFrameBufferSize(), mask
, state_
.color_clear_red
,
5662 state_
.color_clear_green
, state_
.color_clear_blue
,
5663 state_
.color_clear_alpha
, state_
.depth_clear
, state_
.stencil_clear
);
5664 return error::kNoError
;
5668 return error::kNoError
;
5671 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
5672 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
5673 GLuint client_renderbuffer_id
) {
5674 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5677 GL_INVALID_OPERATION
,
5678 "glFramebufferRenderbuffer", "no framebuffer bound");
5681 GLuint service_id
= 0;
5682 Renderbuffer
* renderbuffer
= NULL
;
5683 if (client_renderbuffer_id
) {
5684 renderbuffer
= GetRenderbuffer(client_renderbuffer_id
);
5685 if (!renderbuffer
) {
5687 GL_INVALID_OPERATION
,
5688 "glFramebufferRenderbuffer", "unknown renderbuffer");
5691 service_id
= renderbuffer
->service_id();
5693 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
5694 glFramebufferRenderbufferEXT(
5695 target
, attachment
, renderbuffertarget
, service_id
);
5696 GLenum error
= LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
5697 if (error
== GL_NO_ERROR
) {
5698 framebuffer
->AttachRenderbuffer(attachment
, renderbuffer
);
5700 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
5701 framebuffer_state_
.clear_state_dirty
= true;
5706 void GLES2DecoderImpl::DoDisable(GLenum cap
) {
5707 if (SetCapabilityState(cap
, false)) {
5712 void GLES2DecoderImpl::DoEnable(GLenum cap
) {
5713 if (SetCapabilityState(cap
, true)) {
5718 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear
, GLclampf zfar
) {
5719 state_
.z_near
= std::min(1.0f
, std::max(0.0f
, znear
));
5720 state_
.z_far
= std::min(1.0f
, std::max(0.0f
, zfar
));
5721 glDepthRange(znear
, zfar
);
5724 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value
, GLboolean invert
) {
5725 state_
.sample_coverage_value
= std::min(1.0f
, std::max(0.0f
, value
));
5726 state_
.sample_coverage_invert
= (invert
!= 0);
5727 glSampleCoverage(state_
.sample_coverage_value
, invert
);
5730 // Assumes framebuffer is complete.
5731 void GLES2DecoderImpl::ClearUnclearedAttachments(
5732 GLenum target
, Framebuffer
* framebuffer
) {
5733 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
5734 // bind this to the DRAW point, clear then bind back to READ
5735 // TODO(gman): I don't think there is any guarantee that an FBO that
5736 // is complete on the READ attachment will be complete as a DRAW
5738 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, 0);
5739 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, framebuffer
->service_id());
5741 GLbitfield clear_bits
= 0;
5742 if (framebuffer
->HasUnclearedColorAttachments()) {
5743 // We should always use alpha == 0 here, because 1) some draw buffers may
5744 // have alpha and some may not; 2) we won't have the same situation as the
5745 // back buffer where alpha channel exists but is not requested.
5746 glClearColor(0.0f
, 0.0f
, 0.0f
, 0.0f
);
5747 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
5748 clear_bits
|= GL_COLOR_BUFFER_BIT
;
5749 if (feature_info_
->feature_flags().ext_draw_buffers
)
5750 framebuffer
->PrepareDrawBuffersForClear();
5753 if (framebuffer
->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT
) ||
5754 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
5756 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
5757 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
5758 clear_bits
|= GL_STENCIL_BUFFER_BIT
;
5761 if (framebuffer
->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT
) ||
5762 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
5764 state_
.SetDeviceDepthMask(GL_TRUE
);
5765 clear_bits
|= GL_DEPTH_BUFFER_BIT
;
5768 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5769 glClear(clear_bits
);
5771 if ((clear_bits
& GL_COLOR_BUFFER_BIT
) != 0 &&
5772 feature_info_
->feature_flags().ext_draw_buffers
)
5773 framebuffer
->RestoreDrawBuffersAfterClear();
5775 framebuffer_manager()->MarkAttachmentsAsCleared(
5776 framebuffer
, renderbuffer_manager(), texture_manager());
5778 RestoreClearState();
5780 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
5781 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, framebuffer
->service_id());
5782 Framebuffer
* draw_framebuffer
=
5783 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5784 GLuint service_id
= draw_framebuffer
? draw_framebuffer
->service_id() :
5785 GetBackbufferServiceId();
5786 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, service_id
);
5790 void GLES2DecoderImpl::RestoreClearState() {
5791 framebuffer_state_
.clear_state_dirty
= true;
5793 state_
.color_clear_red
, state_
.color_clear_green
, state_
.color_clear_blue
,
5794 state_
.color_clear_alpha
);
5795 glClearStencil(state_
.stencil_clear
);
5796 glClearDepth(state_
.depth_clear
);
5797 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
,
5798 state_
.enable_flags
.scissor_test
);
5799 glScissor(state_
.scissor_x
, state_
.scissor_y
, state_
.scissor_width
,
5800 state_
.scissor_height
);
5803 GLenum
GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target
) {
5804 Framebuffer
* framebuffer
=
5805 GetFramebufferInfoForTarget(target
);
5807 return GL_FRAMEBUFFER_COMPLETE
;
5809 GLenum completeness
= framebuffer
->IsPossiblyComplete();
5810 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
5811 return completeness
;
5813 return framebuffer
->GetStatus(texture_manager(), target
);
5816 void GLES2DecoderImpl::DoFramebufferTexture2D(
5817 GLenum target
, GLenum attachment
, GLenum textarget
,
5818 GLuint client_texture_id
, GLint level
) {
5819 DoFramebufferTexture2DCommon(
5820 "glFramebufferTexture2D", target
, attachment
,
5821 textarget
, client_texture_id
, level
, 0);
5824 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5825 GLenum target
, GLenum attachment
, GLenum textarget
,
5826 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
5827 DoFramebufferTexture2DCommon(
5828 "glFramebufferTexture2DMultisample", target
, attachment
,
5829 textarget
, client_texture_id
, level
, samples
);
5832 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5833 const char* name
, GLenum target
, GLenum attachment
, GLenum textarget
,
5834 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
5835 if (samples
> renderbuffer_manager()->max_samples()) {
5838 "glFramebufferTexture2DMultisample", "samples too large");
5841 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5844 GL_INVALID_OPERATION
,
5845 name
, "no framebuffer bound.");
5848 GLuint service_id
= 0;
5849 TextureRef
* texture_ref
= NULL
;
5850 if (client_texture_id
) {
5851 texture_ref
= GetTexture(client_texture_id
);
5854 GL_INVALID_OPERATION
,
5855 name
, "unknown texture_ref");
5858 service_id
= texture_ref
->service_id();
5861 if (!texture_manager()->ValidForTarget(textarget
, level
, 0, 0, 1)) {
5864 name
, "level out of range");
5869 DoWillUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
5871 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name
);
5873 glFramebufferTexture2DEXT(target
, attachment
, textarget
, service_id
, level
);
5875 if (features().use_img_for_multisampled_render_to_texture
) {
5876 glFramebufferTexture2DMultisampleIMG(target
, attachment
, textarget
,
5877 service_id
, level
, samples
);
5879 glFramebufferTexture2DMultisampleEXT(target
, attachment
, textarget
,
5880 service_id
, level
, samples
);
5883 GLenum error
= LOCAL_PEEK_GL_ERROR(name
);
5884 if (error
== GL_NO_ERROR
) {
5885 framebuffer
->AttachTexture(attachment
, texture_ref
, textarget
, level
,
5888 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
5889 framebuffer_state_
.clear_state_dirty
= true;
5893 DoDidUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
5898 void GLES2DecoderImpl::DoFramebufferTextureLayer(
5899 GLenum target
, GLenum attachment
, GLuint client_texture_id
,
5900 GLint level
, GLint layer
) {
5901 // TODO(zmo): Unsafe ES3 API, missing states update.
5902 GLuint service_id
= 0;
5903 TextureRef
* texture_ref
= NULL
;
5904 if (client_texture_id
) {
5905 texture_ref
= GetTexture(client_texture_id
);
5908 GL_INVALID_OPERATION
,
5909 "glFramebufferTextureLayer", "unknown texture_ref");
5912 service_id
= texture_ref
->service_id();
5914 glFramebufferTextureLayer(target
, attachment
, service_id
, level
, layer
);
5917 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5918 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
) {
5919 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5922 GL_INVALID_OPERATION
,
5923 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5926 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME
) {
5927 const Framebuffer::Attachment
* attachment_object
=
5928 framebuffer
->GetAttachment(attachment
);
5929 *params
= attachment_object
? attachment_object
->object_name() : 0;
5931 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT
&&
5932 features().use_img_for_multisampled_render_to_texture
) {
5933 pname
= GL_TEXTURE_SAMPLES_IMG
;
5935 glGetFramebufferAttachmentParameterivEXT(target
, attachment
, pname
, params
);
5939 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5940 GLenum target
, GLenum pname
, GLint
* params
) {
5941 Renderbuffer
* renderbuffer
=
5942 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5943 if (!renderbuffer
) {
5945 GL_INVALID_OPERATION
,
5946 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5950 EnsureRenderbufferBound();
5952 case GL_RENDERBUFFER_INTERNAL_FORMAT
:
5953 *params
= renderbuffer
->internal_format();
5955 case GL_RENDERBUFFER_WIDTH
:
5956 *params
= renderbuffer
->width();
5958 case GL_RENDERBUFFER_HEIGHT
:
5959 *params
= renderbuffer
->height();
5961 case GL_RENDERBUFFER_SAMPLES_EXT
:
5962 if (features().use_img_for_multisampled_render_to_texture
) {
5963 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_IMG
,
5966 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_EXT
,
5970 glGetRenderbufferParameterivEXT(target
, pname
, params
);
5975 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5976 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
5977 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
5978 GLbitfield mask
, GLenum filter
) {
5979 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5981 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5985 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5986 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
5987 BlitFramebufferHelper(
5988 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5989 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
,
5990 state_
.enable_flags
.scissor_test
);
5993 void GLES2DecoderImpl::EnsureRenderbufferBound() {
5994 if (!state_
.bound_renderbuffer_valid
) {
5995 state_
.bound_renderbuffer_valid
= true;
5996 glBindRenderbufferEXT(GL_RENDERBUFFER
,
5997 state_
.bound_renderbuffer
.get()
5998 ? state_
.bound_renderbuffer
->service_id()
6003 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
6004 const FeatureInfo
* feature_info
,
6007 GLenum internal_format
,
6010 // TODO(sievers): This could be resolved at the GL binding level, but the
6011 // binding process is currently a bit too 'brute force'.
6012 if (feature_info
->gl_version_info().is_angle
) {
6013 glRenderbufferStorageMultisampleANGLE(
6014 target
, samples
, internal_format
, width
, height
);
6015 } else if (feature_info
->feature_flags().use_core_framebuffer_multisample
) {
6016 glRenderbufferStorageMultisample(
6017 target
, samples
, internal_format
, width
, height
);
6019 glRenderbufferStorageMultisampleEXT(
6020 target
, samples
, internal_format
, width
, height
);
6024 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0
,
6034 // TODO(sievers): This could be resolved at the GL binding level, but the
6035 // binding process is currently a bit too 'brute force'.
6036 if (feature_info_
->gl_version_info().is_angle
) {
6037 glBlitFramebufferANGLE(
6038 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
6039 } else if (feature_info_
->feature_flags().use_core_framebuffer_multisample
) {
6041 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
6043 glBlitFramebufferEXT(
6044 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
6048 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
6050 GLenum internalformat
,
6053 if (samples
> renderbuffer_manager()->max_samples()) {
6056 "glRenderbufferStorageMultisample", "samples too large");
6060 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
6061 height
> renderbuffer_manager()->max_renderbuffer_size()) {
6064 "glRenderbufferStorageMultisample", "dimensions too large");
6068 uint32 estimated_size
= 0;
6069 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6070 width
, height
, samples
, internalformat
, &estimated_size
)) {
6073 "glRenderbufferStorageMultisample", "dimensions too large");
6077 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
6080 "glRenderbufferStorageMultisample", "out of memory");
6087 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
6088 GLenum target
, GLsizei samples
, GLenum internalformat
,
6089 GLsizei width
, GLsizei height
) {
6090 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
6091 if (!renderbuffer
) {
6092 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
6093 "glRenderbufferStorageMultisampleCHROMIUM",
6094 "no renderbuffer bound");
6098 if (!ValidateRenderbufferStorageMultisample(
6099 samples
, internalformat
, width
, height
)) {
6103 EnsureRenderbufferBound();
6104 GLenum impl_format
=
6105 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6107 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
6108 "glRenderbufferStorageMultisampleCHROMIUM");
6109 RenderbufferStorageMultisampleHelper(
6110 feature_info_
.get(), target
, samples
, impl_format
, width
, height
);
6112 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
6113 if (error
== GL_NO_ERROR
) {
6114 if (workarounds().validate_multisample_buffer_allocation
) {
6115 if (!VerifyMultisampleRenderbufferIntegrity(
6116 renderbuffer
->service_id(), impl_format
)) {
6119 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
6124 // TODO(gman): If renderbuffers tracked which framebuffers they were
6125 // attached to we could just mark those framebuffers as not complete.
6126 framebuffer_manager()->IncFramebufferStateChangeCount();
6127 renderbuffer_manager()->SetInfo(
6128 renderbuffer
, samples
, internalformat
, width
, height
);
6132 // This is the handler for multisampled_render_to_texture extensions.
6133 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
6134 GLenum target
, GLsizei samples
, GLenum internalformat
,
6135 GLsizei width
, GLsizei height
) {
6136 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
6137 if (!renderbuffer
) {
6138 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
6139 "glRenderbufferStorageMultisampleEXT",
6140 "no renderbuffer bound");
6144 if (!ValidateRenderbufferStorageMultisample(
6145 samples
, internalformat
, width
, height
)) {
6149 EnsureRenderbufferBound();
6150 GLenum impl_format
=
6151 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6153 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
6154 if (features().use_img_for_multisampled_render_to_texture
) {
6155 glRenderbufferStorageMultisampleIMG(
6156 target
, samples
, impl_format
, width
, height
);
6158 glRenderbufferStorageMultisampleEXT(
6159 target
, samples
, impl_format
, width
, height
);
6161 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
6162 if (error
== GL_NO_ERROR
) {
6163 // TODO(gman): If renderbuffers tracked which framebuffers they were
6164 // attached to we could just mark those framebuffers as not complete.
6165 framebuffer_manager()->IncFramebufferStateChangeCount();
6166 renderbuffer_manager()->SetInfo(
6167 renderbuffer
, samples
, internalformat
, width
, height
);
6171 // This function validates the allocation of a multisampled renderbuffer
6172 // by clearing it to a key color, blitting the contents to a texture, and
6173 // reading back the color to ensure it matches the key.
6174 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
6175 GLuint renderbuffer
, GLenum format
) {
6177 // Only validate color buffers.
6178 // These formats have been selected because they are very common or are known
6179 // to be used by the WebGL backbuffer. If problems are observed with other
6180 // color formats they can be added here.
6191 GLint draw_framebuffer
, read_framebuffer
;
6193 // Cache framebuffer and texture bindings.
6194 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING
, &draw_framebuffer
);
6195 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING
, &read_framebuffer
);
6197 if (!validation_texture_
) {
6198 GLint bound_texture
;
6199 glGetIntegerv(GL_TEXTURE_BINDING_2D
, &bound_texture
);
6201 // Create additional resources needed for the verification.
6202 glGenTextures(1, &validation_texture_
);
6203 glGenFramebuffersEXT(1, &validation_fbo_multisample_
);
6204 glGenFramebuffersEXT(1, &validation_fbo_
);
6206 // Texture only needs to be 1x1.
6207 glBindTexture(GL_TEXTURE_2D
, validation_texture_
);
6208 // TODO(erikchen): When Chrome on Mac is linked against an OSX 10.9+ SDK, a
6209 // multisample will fail if the color format of the source and destination
6210 // do not match. Here, we assume that the source is GL_RGBA, and make the
6211 // destination GL_RGBA. http://crbug.com/484203
6212 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, 1, 1, 0, GL_RGBA
,
6213 GL_UNSIGNED_BYTE
, NULL
);
6215 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
6216 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
6217 GL_TEXTURE_2D
, validation_texture_
, 0);
6219 glBindTexture(GL_TEXTURE_2D
, bound_texture
);
6222 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
6223 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
6224 GL_RENDERBUFFER
, renderbuffer
);
6226 // Cache current state and reset it to the values we require.
6227 GLboolean scissor_enabled
= false;
6228 glGetBooleanv(GL_SCISSOR_TEST
, &scissor_enabled
);
6229 if (scissor_enabled
)
6230 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
6232 GLboolean color_mask
[4] = {GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
};
6233 glGetBooleanv(GL_COLOR_WRITEMASK
, color_mask
);
6234 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
6236 GLfloat clear_color
[4] = {0.0f
, 0.0f
, 0.0f
, 0.0f
};
6237 glGetFloatv(GL_COLOR_CLEAR_VALUE
, clear_color
);
6238 glClearColor(1.0f
, 0.0f
, 1.0f
, 1.0f
);
6240 // Clear the buffer to the desired key color.
6241 glClear(GL_COLOR_BUFFER_BIT
);
6243 // Blit from the multisample buffer to a standard texture.
6244 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, validation_fbo_multisample_
);
6245 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, validation_fbo_
);
6247 BlitFramebufferHelper(
6248 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
6250 // Read a pixel from the buffer.
6251 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
6253 unsigned char pixel
[3] = {0, 0, 0};
6254 glReadPixels(0, 0, 1, 1, GL_RGB
, GL_UNSIGNED_BYTE
, &pixel
);
6256 // Detach the renderbuffer.
6257 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
6258 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
6259 GL_RENDERBUFFER
, 0);
6261 // Restore cached state.
6262 if (scissor_enabled
)
6263 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
6265 state_
.SetDeviceColorMask(
6266 color_mask
[0], color_mask
[1], color_mask
[2], color_mask
[3]);
6267 glClearColor(clear_color
[0], clear_color
[1], clear_color
[2], clear_color
[3]);
6268 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, draw_framebuffer
);
6269 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, read_framebuffer
);
6271 // Return true if the pixel matched the desired key color.
6272 return (pixel
[0] == 0xFF &&
6277 void GLES2DecoderImpl::DoRenderbufferStorage(
6278 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
) {
6279 Renderbuffer
* renderbuffer
=
6280 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
6281 if (!renderbuffer
) {
6283 GL_INVALID_OPERATION
,
6284 "glRenderbufferStorage", "no renderbuffer bound");
6288 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
6289 height
> renderbuffer_manager()->max_renderbuffer_size()) {
6291 GL_INVALID_VALUE
, "glRenderbufferStorage", "dimensions too large");
6295 uint32 estimated_size
= 0;
6296 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6297 width
, height
, 1, internalformat
, &estimated_size
)) {
6299 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "dimensions too large");
6303 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
6305 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "out of memory");
6309 EnsureRenderbufferBound();
6310 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
6311 glRenderbufferStorageEXT(
6313 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6317 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
6318 if (error
== GL_NO_ERROR
) {
6319 // TODO(gman): If tetxures tracked which framebuffers they were attached to
6320 // we could just mark those framebuffers as not complete.
6321 framebuffer_manager()->IncFramebufferStateChangeCount();
6322 renderbuffer_manager()->SetInfo(
6323 renderbuffer
, 1, internalformat
, width
, height
);
6327 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id
) {
6328 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
6329 SCOPED_UMA_HISTOGRAM_TIMER("GPU.DoLinkProgramTime");
6330 Program
* program
= GetProgramInfoNotShader(
6331 program_id
, "glLinkProgram");
6336 LogClientServiceForInfo(program
, program_id
, "glLinkProgram");
6337 if (program
->Link(shader_manager(),
6338 workarounds().count_all_in_varyings_packing
?
6339 Program::kCountAll
: Program::kCountOnlyStaticallyUsed
,
6340 shader_cache_callback_
)) {
6341 if (program
== state_
.current_program
.get()) {
6342 if (workarounds().use_current_program_after_successful_link
)
6343 glUseProgram(program
->service_id());
6344 if (workarounds().clear_uniforms_before_first_program_use
)
6345 program_manager()->ClearUniforms(program
);
6349 // LinkProgram can be very slow. Exit command processing to allow for
6350 // context preemption and GPU watchdog checks.
6351 ExitCommandProcessingEarly();
6354 void GLES2DecoderImpl::DoReadBuffer(GLenum src
) {
6361 GLenum upper_limit
= static_cast<GLenum
>(
6362 group_
->max_color_attachments() + GL_COLOR_ATTACHMENT0
);
6363 if (src
< GL_COLOR_ATTACHMENT0
|| src
>= upper_limit
) {
6365 GL_INVALID_ENUM
, "glReadBuffer", "invalid enum for src");
6372 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER
);
6374 if (src
== GL_BACK
) {
6376 GL_INVALID_ENUM
, "glReadBuffer",
6377 "invalid src for a named framebuffer");
6380 framebuffer
->set_read_buffer(src
);
6382 if (src
!= GL_NONE
&& src
!= GL_BACK
) {
6384 GL_INVALID_ENUM
, "glReadBuffer",
6385 "invalid src for the default framebuffer");
6388 back_buffer_read_buffer_
= src
;
6389 if (GetBackbufferServiceId() && src
== GL_BACK
)
6390 src
= GL_COLOR_ATTACHMENT0
;
6395 void GLES2DecoderImpl::DoSamplerParameterfv(
6396 GLuint sampler
, GLenum pname
, const GLfloat
* params
) {
6398 glSamplerParameterf(sampler
, pname
, params
[0]);
6401 void GLES2DecoderImpl::DoSamplerParameteriv(
6402 GLuint sampler
, GLenum pname
, const GLint
* params
) {
6404 glSamplerParameteri(sampler
, pname
, params
[0]);
6407 void GLES2DecoderImpl::DoTexParameterf(
6408 GLenum target
, GLenum pname
, GLfloat param
) {
6409 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6412 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterf", "unknown texture");
6416 texture_manager()->SetParameterf(
6417 "glTexParameterf", GetErrorState(), texture
, pname
, param
);
6420 void GLES2DecoderImpl::DoTexParameteri(
6421 GLenum target
, GLenum pname
, GLint param
) {
6422 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6425 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameteri", "unknown texture");
6429 texture_manager()->SetParameteri(
6430 "glTexParameteri", GetErrorState(), texture
, pname
, param
);
6433 void GLES2DecoderImpl::DoTexParameterfv(
6434 GLenum target
, GLenum pname
, const GLfloat
* params
) {
6435 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6438 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterfv", "unknown texture");
6442 texture_manager()->SetParameterf(
6443 "glTexParameterfv", GetErrorState(), texture
, pname
, *params
);
6446 void GLES2DecoderImpl::DoTexParameteriv(
6447 GLenum target
, GLenum pname
, const GLint
* params
) {
6448 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6452 GL_INVALID_VALUE
, "glTexParameteriv", "unknown texture");
6456 texture_manager()->SetParameteri(
6457 "glTexParameteriv", GetErrorState(), texture
, pname
, *params
);
6460 bool GLES2DecoderImpl::CheckCurrentValuebuffer(const char* function_name
) {
6461 if (!state_
.bound_valuebuffer
.get()) {
6462 // There is no valuebuffer bound
6463 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6464 "no valuebuffer in use");
6470 bool GLES2DecoderImpl::CheckCurrentValuebufferForSubscription(
6471 GLenum subscription
,
6472 const char* function_name
) {
6473 if (!CheckCurrentValuebuffer(function_name
)) {
6476 if (!state_
.bound_valuebuffer
.get()->IsSubscribed(subscription
)) {
6477 // The valuebuffer is not subscribed to the target
6478 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6479 "valuebuffer is not subscribed");
6485 bool GLES2DecoderImpl::CheckSubscriptionTarget(GLint location
,
6486 GLenum subscription
,
6487 const char* function_name
) {
6488 if (!CheckCurrentProgramForUniform(location
, function_name
)) {
6491 GLint real_location
= -1;
6492 GLint array_index
= -1;
6493 const Program::UniformInfo
* info
=
6494 state_
.current_program
->GetUniformInfoByFakeLocation(
6495 location
, &real_location
, &array_index
);
6497 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
, "unknown location");
6500 if ((ValuebufferManager::ApiTypeForSubscriptionTarget(subscription
) &
6501 info
->accepts_api_type
) == 0) {
6502 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6503 "wrong type for subscription");
6509 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name
) {
6510 if (!state_
.current_program
.get()) {
6511 // The program does not exist.
6513 GL_INVALID_OPERATION
, function_name
, "no program in use");
6516 if (!state_
.current_program
->InUse()) {
6518 GL_INVALID_OPERATION
, function_name
, "program not linked");
6524 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
6525 GLint location
, const char* function_name
) {
6526 if (!CheckCurrentProgram(function_name
)) {
6529 return location
!= -1;
6532 bool GLES2DecoderImpl::CheckDrawingFeedbackLoops() {
6533 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
6536 const Framebuffer::Attachment
* attachment
=
6537 framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
);
6541 DCHECK(state_
.current_program
.get());
6542 const Program::SamplerIndices
& sampler_indices
=
6543 state_
.current_program
->sampler_indices();
6544 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6545 const Program::UniformInfo
* uniform_info
=
6546 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6547 DCHECK(uniform_info
);
6548 if (uniform_info
->type
!= GL_SAMPLER_2D
)
6550 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6551 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6552 if (texture_unit_index
>= state_
.texture_units
.size())
6554 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6555 TextureRef
* texture_ref
=
6556 texture_unit
.GetInfoForSamplerType(GL_SAMPLER_2D
).get();
6557 if (attachment
->IsTexture(texture_ref
))
6564 bool GLES2DecoderImpl::CheckUniformForApiType(
6565 const Program::UniformInfo
* info
,
6566 const char* function_name
,
6567 Program::UniformApiType api_type
) {
6569 if ((api_type
& info
->accepts_api_type
) == 0) {
6570 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6571 "wrong uniform function for type");
6577 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
6578 GLint fake_location
,
6579 const char* function_name
,
6580 Program::UniformApiType api_type
,
6581 GLint
* real_location
,
6586 DCHECK(real_location
);
6588 if (!CheckCurrentProgramForUniform(fake_location
, function_name
)) {
6591 GLint array_index
= -1;
6592 const Program::UniformInfo
* info
=
6593 state_
.current_program
->GetUniformInfoByFakeLocation(
6594 fake_location
, real_location
, &array_index
);
6597 GL_INVALID_OPERATION
, function_name
, "unknown location");
6600 if (!CheckUniformForApiType(info
, function_name
, api_type
)) {
6603 if (*count
> 1 && !info
->is_array
) {
6605 GL_INVALID_OPERATION
, function_name
, "count > 1 for non-array");
6608 *count
= std::min(info
->size
- array_index
, *count
);
6616 void GLES2DecoderImpl::DoUniform1i(GLint fake_location
, GLint v0
) {
6619 GLint real_location
= -1;
6620 if (!PrepForSetUniformByLocation(fake_location
,
6622 Program::kUniform1i
,
6628 if (!state_
.current_program
->SetSamplers(
6629 state_
.texture_units
.size(), fake_location
, 1, &v0
)) {
6631 GL_INVALID_VALUE
, "glUniform1i", "texture unit out of range");
6634 glUniform1i(real_location
, v0
);
6637 void GLES2DecoderImpl::DoUniform1iv(
6638 GLint fake_location
, GLsizei count
, const GLint
*value
) {
6640 GLint real_location
= -1;
6641 if (!PrepForSetUniformByLocation(fake_location
,
6643 Program::kUniform1i
,
6649 if (type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_2D_RECT_ARB
||
6650 type
== GL_SAMPLER_CUBE
|| type
== GL_SAMPLER_EXTERNAL_OES
) {
6651 if (!state_
.current_program
->SetSamplers(
6652 state_
.texture_units
.size(), fake_location
, count
, value
)) {
6654 GL_INVALID_VALUE
, "glUniform1iv", "texture unit out of range");
6658 glUniform1iv(real_location
, count
, value
);
6661 void GLES2DecoderImpl::DoUniform1fv(
6662 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6664 GLint real_location
= -1;
6665 if (!PrepForSetUniformByLocation(fake_location
,
6667 Program::kUniform1f
,
6673 if (type
== GL_BOOL
) {
6674 scoped_ptr
<GLint
[]> temp(new GLint
[count
]);
6675 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
6676 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6678 DoUniform1iv(real_location
, count
, temp
.get());
6680 glUniform1fv(real_location
, count
, value
);
6684 void GLES2DecoderImpl::DoUniform2fv(
6685 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6687 GLint real_location
= -1;
6688 if (!PrepForSetUniformByLocation(fake_location
,
6690 Program::kUniform2f
,
6696 if (type
== GL_BOOL_VEC2
) {
6697 GLsizei num_values
= count
* 2;
6698 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6699 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6700 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6702 glUniform2iv(real_location
, count
, temp
.get());
6704 glUniform2fv(real_location
, count
, value
);
6708 void GLES2DecoderImpl::DoUniform3fv(
6709 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6711 GLint real_location
= -1;
6712 if (!PrepForSetUniformByLocation(fake_location
,
6714 Program::kUniform3f
,
6720 if (type
== GL_BOOL_VEC3
) {
6721 GLsizei num_values
= count
* 3;
6722 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6723 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6724 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6726 glUniform3iv(real_location
, count
, temp
.get());
6728 glUniform3fv(real_location
, count
, value
);
6732 void GLES2DecoderImpl::DoUniform4fv(
6733 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6735 GLint real_location
= -1;
6736 if (!PrepForSetUniformByLocation(fake_location
,
6738 Program::kUniform4f
,
6744 if (type
== GL_BOOL_VEC4
) {
6745 GLsizei num_values
= count
* 4;
6746 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6747 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6748 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6750 glUniform4iv(real_location
, count
, temp
.get());
6752 glUniform4fv(real_location
, count
, value
);
6756 void GLES2DecoderImpl::DoUniform2iv(
6757 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6759 GLint real_location
= -1;
6760 if (!PrepForSetUniformByLocation(fake_location
,
6762 Program::kUniform2i
,
6768 glUniform2iv(real_location
, count
, value
);
6771 void GLES2DecoderImpl::DoUniform3iv(
6772 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6774 GLint real_location
= -1;
6775 if (!PrepForSetUniformByLocation(fake_location
,
6777 Program::kUniform3i
,
6783 glUniform3iv(real_location
, count
, value
);
6786 void GLES2DecoderImpl::DoUniform4iv(
6787 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6789 GLint real_location
= -1;
6790 if (!PrepForSetUniformByLocation(fake_location
,
6792 Program::kUniform4i
,
6798 glUniform4iv(real_location
, count
, value
);
6801 void GLES2DecoderImpl::DoUniformMatrix2fv(
6802 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6803 const GLfloat
* value
) {
6805 GLint real_location
= -1;
6806 if (!PrepForSetUniformByLocation(fake_location
,
6807 "glUniformMatrix2fv",
6808 Program::kUniformMatrix2f
,
6814 glUniformMatrix2fv(real_location
, count
, transpose
, value
);
6817 void GLES2DecoderImpl::DoUniformMatrix3fv(
6818 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6819 const GLfloat
* value
) {
6821 GLint real_location
= -1;
6822 if (!PrepForSetUniformByLocation(fake_location
,
6823 "glUniformMatrix3fv",
6824 Program::kUniformMatrix3f
,
6830 glUniformMatrix3fv(real_location
, count
, transpose
, value
);
6833 void GLES2DecoderImpl::DoUniformMatrix4fv(
6834 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6835 const GLfloat
* value
) {
6837 GLint real_location
= -1;
6838 if (!PrepForSetUniformByLocation(fake_location
,
6839 "glUniformMatrix4fv",
6840 Program::kUniformMatrix4f
,
6846 glUniformMatrix4fv(real_location
, count
, transpose
, value
);
6849 void GLES2DecoderImpl::DoUseProgram(GLuint program_id
) {
6850 GLuint service_id
= 0;
6851 Program
* program
= NULL
;
6853 program
= GetProgramInfoNotShader(program_id
, "glUseProgram");
6857 if (!program
->IsValid()) {
6858 // Program was not linked successfully. (ie, glLinkProgram)
6860 GL_INVALID_OPERATION
, "glUseProgram", "program not linked");
6863 service_id
= program
->service_id();
6865 if (state_
.current_program
.get()) {
6866 program_manager()->UnuseProgram(shader_manager(),
6867 state_
.current_program
.get());
6869 state_
.current_program
= program
;
6870 LogClientServiceMapping("glUseProgram", program_id
, service_id
);
6871 glUseProgram(service_id
);
6872 if (state_
.current_program
.get()) {
6873 program_manager()->UseProgram(state_
.current_program
.get());
6874 if (workarounds().clear_uniforms_before_first_program_use
)
6875 program_manager()->ClearUniforms(program
);
6879 void GLES2DecoderImpl::RenderWarning(
6880 const char* filename
, int line
, const std::string
& msg
) {
6881 logger_
.LogMessage(filename
, line
, std::string("RENDER WARNING: ") + msg
);
6884 void GLES2DecoderImpl::PerformanceWarning(
6885 const char* filename
, int line
, const std::string
& msg
) {
6886 logger_
.LogMessage(filename
, line
,
6887 std::string("PERFORMANCE WARNING: ") + msg
);
6890 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
6891 Texture
* texture
, GLenum textarget
) {
6892 // Image is already in use if texture is attached to a framebuffer.
6893 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
6894 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6896 ScopedGLErrorSuppressor
suppressor(
6897 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
6899 glBindTexture(textarget
, texture
->service_id());
6900 image
->WillUseTexImage();
6901 RestoreCurrentTextureBindings(&state_
, textarget
);
6906 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6907 Texture
* texture
, GLenum textarget
) {
6908 // Image is still in use if texture is attached to a framebuffer.
6909 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
6910 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6912 ScopedGLErrorSuppressor
suppressor(
6913 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6915 glBindTexture(textarget
, texture
->service_id());
6916 image
->DidUseTexImage();
6917 RestoreCurrentTextureBindings(&state_
, textarget
);
6922 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6923 DCHECK(state_
.current_program
.get());
6924 if (!texture_manager()->HaveUnrenderableTextures() &&
6925 !texture_manager()->HaveImages()) {
6929 bool textures_set
= false;
6930 const Program::SamplerIndices
& sampler_indices
=
6931 state_
.current_program
->sampler_indices();
6932 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6933 const Program::UniformInfo
* uniform_info
=
6934 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6935 DCHECK(uniform_info
);
6936 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6937 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6938 if (texture_unit_index
< state_
.texture_units
.size()) {
6939 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6940 TextureRef
* texture_ref
=
6941 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6942 GLenum textarget
= GetBindTargetForSamplerType(uniform_info
->type
);
6943 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
6944 textures_set
= true;
6945 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6948 texture_manager()->black_texture_id(uniform_info
->type
));
6950 LOCAL_RENDER_WARNING(
6951 std::string("there is no texture bound to the unit ") +
6952 base::IntToString(texture_unit_index
));
6954 LOCAL_RENDER_WARNING(
6955 std::string("texture bound to texture unit ") +
6956 base::IntToString(texture_unit_index
) +
6957 " is not renderable. It maybe non-power-of-2 and have"
6958 " incompatible texture filtering.");
6963 if (textarget
!= GL_TEXTURE_CUBE_MAP
) {
6964 Texture
* texture
= texture_ref
->texture();
6965 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6966 if (image
&& !texture
->IsAttachedToFramebuffer()) {
6967 ScopedGLErrorSuppressor
suppressor(
6968 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6969 textures_set
= true;
6970 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6971 image
->WillUseTexImage();
6976 // else: should this be an error?
6979 return !textures_set
;
6982 void GLES2DecoderImpl::RestoreStateForTextures() {
6983 DCHECK(state_
.current_program
.get());
6984 const Program::SamplerIndices
& sampler_indices
=
6985 state_
.current_program
->sampler_indices();
6986 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6987 const Program::UniformInfo
* uniform_info
=
6988 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6989 DCHECK(uniform_info
);
6990 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6991 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6992 if (texture_unit_index
< state_
.texture_units
.size()) {
6993 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6994 TextureRef
* texture_ref
=
6995 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6996 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
6997 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6998 // Get the texture_ref info that was previously bound here.
6999 texture_ref
= texture_unit
.bind_target
== GL_TEXTURE_2D
7000 ? texture_unit
.bound_texture_2d
.get()
7001 : texture_unit
.bound_texture_cube_map
.get();
7002 glBindTexture(texture_unit
.bind_target
,
7003 texture_ref
? texture_ref
->service_id() : 0);
7007 if (texture_unit
.bind_target
!= GL_TEXTURE_CUBE_MAP
) {
7008 Texture
* texture
= texture_ref
->texture();
7009 gfx::GLImage
* image
=
7010 texture
->GetLevelImage(texture_unit
.bind_target
, 0);
7011 if (image
&& !texture
->IsAttachedToFramebuffer()) {
7012 ScopedGLErrorSuppressor
suppressor(
7013 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
7014 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
7015 image
->DidUseTexImage();
7022 // Set the active texture back to whatever the user had it as.
7023 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
7026 bool GLES2DecoderImpl::ClearUnclearedTextures() {
7027 // Only check if there are some uncleared textures.
7028 if (!texture_manager()->HaveUnsafeTextures()) {
7032 // 1: Check all textures we are about to render with.
7033 if (state_
.current_program
.get()) {
7034 const Program::SamplerIndices
& sampler_indices
=
7035 state_
.current_program
->sampler_indices();
7036 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
7037 const Program::UniformInfo
* uniform_info
=
7038 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
7039 DCHECK(uniform_info
);
7040 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
7041 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
7042 if (texture_unit_index
< state_
.texture_units
.size()) {
7043 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
7044 TextureRef
* texture_ref
=
7045 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
7046 if (texture_ref
&& !texture_ref
->texture()->SafeToRenderFrom()) {
7047 if (!texture_manager()->ClearRenderableLevels(this, texture_ref
)) {
7058 bool GLES2DecoderImpl::IsDrawValid(
7059 const char* function_name
, GLuint max_vertex_accessed
, bool instanced
,
7060 GLsizei primcount
) {
7061 DCHECK(instanced
|| primcount
== 1);
7063 // NOTE: We specifically do not check current_program->IsValid() because
7064 // it could never be invalid since glUseProgram would have failed. While
7065 // glLinkProgram could later mark the program as invalid the previous
7066 // valid program will still function if it is still the current program.
7067 if (!state_
.current_program
.get()) {
7068 // The program does not exist.
7069 // But GL says no ERROR.
7070 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
7074 if (CheckDrawingFeedbackLoops()) {
7076 GL_INVALID_OPERATION
, function_name
,
7077 "Source and destination textures of the draw are the same.");
7081 return state_
.vertex_attrib_manager
7082 ->ValidateBindings(function_name
,
7084 feature_info_
.get(),
7085 state_
.current_program
.get(),
7086 max_vertex_accessed
,
7091 bool GLES2DecoderImpl::SimulateAttrib0(
7092 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
) {
7096 if (feature_info_
->gl_version_info().BehavesLikeGLES())
7099 const VertexAttrib
* attrib
=
7100 state_
.vertex_attrib_manager
->GetVertexAttrib(0);
7101 // If it's enabled or it's not used then we don't need to do anything.
7102 bool attrib_0_used
=
7103 state_
.current_program
->GetAttribInfoByLocation(0) != NULL
;
7104 if (attrib
->enabled() && attrib_0_used
) {
7108 // Make a buffer with a single repeated vec4 value enough to
7109 // simulate the constant value that is supposed to be here.
7110 // This is required to emulate GLES2 on GL.
7111 GLuint num_vertices
= max_vertex_accessed
+ 1;
7112 uint32 size_needed
= 0;
7114 if (num_vertices
== 0 ||
7115 !SafeMultiplyUint32(num_vertices
, sizeof(Vec4f
), &size_needed
) ||
7116 size_needed
> 0x7FFFFFFFU
) {
7117 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
7121 LOCAL_PERFORMANCE_WARNING(
7122 "Attribute 0 is disabled. This has signficant performance penalty");
7124 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
7125 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
7127 bool new_buffer
= static_cast<GLsizei
>(size_needed
) > attrib_0_size_
;
7129 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
7130 GLenum error
= glGetError();
7131 if (error
!= GL_NO_ERROR
) {
7133 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
7138 const Vec4
& value
= state_
.attrib_values
[0];
7141 (!attrib_0_buffer_matches_value_
|| !value
.Equal(attrib_0_value_
)))){
7142 // TODO(zmo): This is not 100% correct because we might lose data when
7143 // casting to float type, but it is a corner case and once we migrate to
7144 // core profiles on desktop GL, it is no longer relevant.
7145 Vec4f
fvalue(value
);
7146 std::vector
<Vec4f
> temp(num_vertices
, fvalue
);
7147 glBufferSubData(GL_ARRAY_BUFFER
, 0, size_needed
, &temp
[0].v
[0]);
7148 attrib_0_buffer_matches_value_
= true;
7149 attrib_0_value_
= value
;
7150 attrib_0_size_
= size_needed
;
7153 glVertexAttribPointer(0, 4, GL_FLOAT
, GL_FALSE
, 0, NULL
);
7155 if (attrib
->divisor())
7156 glVertexAttribDivisorANGLE(0, 0);
7162 void GLES2DecoderImpl::RestoreStateForAttrib(
7163 GLuint attrib_index
, bool restore_array_binding
) {
7164 const VertexAttrib
* attrib
=
7165 state_
.vertex_attrib_manager
->GetVertexAttrib(attrib_index
);
7166 if (restore_array_binding
) {
7167 const void* ptr
= reinterpret_cast<const void*>(attrib
->offset());
7168 Buffer
* buffer
= attrib
->buffer();
7169 glBindBuffer(GL_ARRAY_BUFFER
, buffer
? buffer
->service_id() : 0);
7170 glVertexAttribPointer(
7171 attrib_index
, attrib
->size(), attrib
->type(), attrib
->normalized(),
7172 attrib
->gl_stride(), ptr
);
7174 if (attrib
->divisor())
7175 glVertexAttribDivisorANGLE(attrib_index
, attrib
->divisor());
7177 GL_ARRAY_BUFFER
, state_
.bound_array_buffer
.get() ?
7178 state_
.bound_array_buffer
->service_id() : 0);
7180 // Never touch vertex attribute 0's state (in particular, never
7181 // disable it) when running on desktop GL because it will never be
7183 if (attrib_index
!= 0 ||
7184 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
7185 if (attrib
->enabled()) {
7186 glEnableVertexAttribArray(attrib_index
);
7188 glDisableVertexAttribArray(attrib_index
);
7193 bool GLES2DecoderImpl::SimulateFixedAttribs(
7194 const char* function_name
,
7195 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
) {
7198 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
)
7201 if (!state_
.vertex_attrib_manager
->HaveFixedAttribs()) {
7205 LOCAL_PERFORMANCE_WARNING(
7206 "GL_FIXED attributes have a signficant performance penalty");
7208 // NOTE: we could be smart and try to check if a buffer is used
7209 // twice in 2 different attribs, find the overlapping parts and therefore
7210 // duplicate the minimum amount of data but this whole code path is not meant
7211 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
7212 // tests so we just add to the buffer attrib used.
7214 GLuint elements_needed
= 0;
7215 const VertexAttribManager::VertexAttribList
& enabled_attribs
=
7216 state_
.vertex_attrib_manager
->GetEnabledVertexAttribs();
7217 for (VertexAttribManager::VertexAttribList::const_iterator it
=
7218 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
7219 const VertexAttrib
* attrib
= *it
;
7220 const Program::VertexAttrib
* attrib_info
=
7221 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
7222 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
7223 max_vertex_accessed
);
7224 GLuint num_vertices
= max_accessed
+ 1;
7225 if (num_vertices
== 0) {
7227 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
7231 attrib
->CanAccess(max_accessed
) &&
7232 attrib
->type() == GL_FIXED
) {
7233 uint32 elements_used
= 0;
7234 if (!SafeMultiplyUint32(num_vertices
, attrib
->size(), &elements_used
) ||
7235 !SafeAddUint32(elements_needed
, elements_used
, &elements_needed
)) {
7237 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
7243 const uint32 kSizeOfFloat
= sizeof(float); // NOLINT
7244 uint32 size_needed
= 0;
7245 if (!SafeMultiplyUint32(elements_needed
, kSizeOfFloat
, &size_needed
) ||
7246 size_needed
> 0x7FFFFFFFU
) {
7248 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
7252 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
7254 glBindBuffer(GL_ARRAY_BUFFER
, fixed_attrib_buffer_id_
);
7255 if (static_cast<GLsizei
>(size_needed
) > fixed_attrib_buffer_size_
) {
7256 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
7257 GLenum error
= glGetError();
7258 if (error
!= GL_NO_ERROR
) {
7260 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
7265 // Copy the elements and convert to float
7266 GLintptr offset
= 0;
7267 for (VertexAttribManager::VertexAttribList::const_iterator it
=
7268 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
7269 const VertexAttrib
* attrib
= *it
;
7270 const Program::VertexAttrib
* attrib_info
=
7271 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
7272 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
7273 max_vertex_accessed
);
7274 GLuint num_vertices
= max_accessed
+ 1;
7275 if (num_vertices
== 0) {
7277 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
7281 attrib
->CanAccess(max_accessed
) &&
7282 attrib
->type() == GL_FIXED
) {
7283 int num_elements
= attrib
->size() * num_vertices
;
7284 const int src_size
= num_elements
* sizeof(int32
);
7285 const int dst_size
= num_elements
* sizeof(float);
7286 scoped_ptr
<float[]> data(new float[num_elements
]);
7287 const int32
* src
= reinterpret_cast<const int32
*>(
7288 attrib
->buffer()->GetRange(attrib
->offset(), src_size
));
7289 const int32
* end
= src
+ num_elements
;
7290 float* dst
= data
.get();
7291 while (src
!= end
) {
7292 *dst
++ = static_cast<float>(*src
++) / 65536.0f
;
7294 glBufferSubData(GL_ARRAY_BUFFER
, offset
, dst_size
, data
.get());
7295 glVertexAttribPointer(
7296 attrib
->index(), attrib
->size(), GL_FLOAT
, false, 0,
7297 reinterpret_cast<GLvoid
*>(offset
));
7305 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
7306 // There's no need to call glVertexAttribPointer because we shadow all the
7307 // settings and passing GL_FIXED to it will not work.
7310 state_
.bound_array_buffer
.get() ? state_
.bound_array_buffer
->service_id()
7314 error::Error
GLES2DecoderImpl::DoDrawArrays(
7315 const char* function_name
,
7320 GLsizei primcount
) {
7321 error::Error error
= WillAccessBoundFramebufferForDraw();
7322 if (error
!= error::kNoError
)
7324 if (!validators_
->draw_mode
.IsValid(mode
)) {
7325 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
7326 return error::kNoError
;
7329 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
7330 return error::kNoError
;
7332 if (primcount
< 0) {
7333 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
7334 return error::kNoError
;
7336 if (!CheckBoundFramebuffersValid(function_name
)) {
7337 return error::kNoError
;
7339 // We have to check this here because the prototype for glDrawArrays
7340 // is GLint not GLsizei.
7342 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "first < 0");
7343 return error::kNoError
;
7346 if (count
== 0 || primcount
== 0) {
7347 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
7348 return error::kNoError
;
7351 GLuint max_vertex_accessed
= first
+ count
- 1;
7352 if (IsDrawValid(function_name
, max_vertex_accessed
, instanced
, primcount
)) {
7353 if (!ClearUnclearedTextures()) {
7354 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
7355 return error::kNoError
;
7357 bool simulated_attrib_0
= false;
7358 if (!SimulateAttrib0(
7359 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
7360 return error::kNoError
;
7362 bool simulated_fixed_attribs
= false;
7363 if (SimulateFixedAttribs(
7364 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
7366 bool textures_set
= !PrepareTexturesForRender();
7368 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
7370 glDrawArrays(mode
, first
, count
);
7372 glDrawArraysInstancedANGLE(mode
, first
, count
, primcount
);
7375 RestoreStateForTextures();
7377 if (simulated_fixed_attribs
) {
7378 RestoreStateForSimulatedFixedAttribs();
7381 if (simulated_attrib_0
) {
7382 // We don't have to restore attrib 0 generic data at the end of this
7383 // function even if it is simulated. This is because we will simulate
7384 // it in each draw call, and attrib 0 generic data queries use cached
7385 // values instead of passing down to the underlying driver.
7386 RestoreStateForAttrib(0, false);
7389 return error::kNoError
;
7392 error::Error
GLES2DecoderImpl::HandleDrawArrays(uint32 immediate_data_size
,
7393 const void* cmd_data
) {
7394 // TODO(zmo): crbug.com/481184
7395 // On Desktop GL with versions lower than 4.3, we need to emulate
7396 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7397 const cmds::DrawArrays
& c
= *static_cast<const cmds::DrawArrays
*>(cmd_data
);
7398 return DoDrawArrays("glDrawArrays",
7400 static_cast<GLenum
>(c
.mode
),
7401 static_cast<GLint
>(c
.first
),
7402 static_cast<GLsizei
>(c
.count
),
7406 error::Error
GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
7407 uint32 immediate_data_size
,
7408 const void* cmd_data
) {
7409 const gles2::cmds::DrawArraysInstancedANGLE
& c
=
7410 *static_cast<const gles2::cmds::DrawArraysInstancedANGLE
*>(cmd_data
);
7411 if (!features().angle_instanced_arrays
) {
7413 GL_INVALID_OPERATION
,
7414 "glDrawArraysInstancedANGLE", "function not available");
7415 return error::kNoError
;
7417 return DoDrawArrays("glDrawArraysIntancedANGLE",
7419 static_cast<GLenum
>(c
.mode
),
7420 static_cast<GLint
>(c
.first
),
7421 static_cast<GLsizei
>(c
.count
),
7422 static_cast<GLsizei
>(c
.primcount
));
7425 error::Error
GLES2DecoderImpl::DoDrawElements(
7426 const char* function_name
,
7432 GLsizei primcount
) {
7433 error::Error error
= WillAccessBoundFramebufferForDraw();
7434 if (error
!= error::kNoError
)
7436 if (!state_
.vertex_attrib_manager
->element_array_buffer()) {
7438 GL_INVALID_OPERATION
, function_name
, "No element array buffer bound");
7439 return error::kNoError
;
7443 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
7444 return error::kNoError
;
7447 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "offset < 0");
7448 return error::kNoError
;
7450 if (!validators_
->draw_mode
.IsValid(mode
)) {
7451 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
7452 return error::kNoError
;
7454 if (!validators_
->index_type
.IsValid(type
)) {
7455 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, type
, "type");
7456 return error::kNoError
;
7458 if (primcount
< 0) {
7459 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
7460 return error::kNoError
;
7463 if (!CheckBoundFramebuffersValid(function_name
)) {
7464 return error::kNoError
;
7467 if (count
== 0 || primcount
== 0) {
7468 return error::kNoError
;
7471 GLuint max_vertex_accessed
;
7472 Buffer
* element_array_buffer
=
7473 state_
.vertex_attrib_manager
->element_array_buffer();
7475 if (!element_array_buffer
->GetMaxValueForRange(
7476 offset
, count
, type
, &max_vertex_accessed
)) {
7478 GL_INVALID_OPERATION
, function_name
, "range out of bounds for buffer");
7479 return error::kNoError
;
7482 if (IsDrawValid(function_name
, max_vertex_accessed
, instanced
, primcount
)) {
7483 if (!ClearUnclearedTextures()) {
7484 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
7485 return error::kNoError
;
7487 bool simulated_attrib_0
= false;
7488 if (!SimulateAttrib0(
7489 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
7490 return error::kNoError
;
7492 bool simulated_fixed_attribs
= false;
7493 if (SimulateFixedAttribs(
7494 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
7496 bool textures_set
= !PrepareTexturesForRender();
7498 // TODO(gman): Refactor to hide these details in BufferManager or
7499 // VertexAttribManager.
7500 const GLvoid
* indices
= reinterpret_cast<const GLvoid
*>(offset
);
7501 bool used_client_side_array
= false;
7502 if (element_array_buffer
->IsClientSideArray()) {
7503 used_client_side_array
= true;
7504 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
7505 indices
= element_array_buffer
->GetRange(offset
, 0);
7508 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
7510 glDrawElements(mode
, count
, type
, indices
);
7512 glDrawElementsInstancedANGLE(mode
, count
, type
, indices
, primcount
);
7515 if (used_client_side_array
) {
7516 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
7517 element_array_buffer
->service_id());
7521 RestoreStateForTextures();
7523 if (simulated_fixed_attribs
) {
7524 RestoreStateForSimulatedFixedAttribs();
7527 if (simulated_attrib_0
) {
7528 // We don't have to restore attrib 0 generic data at the end of this
7529 // function even if it is simulated. This is because we will simulate
7530 // it in each draw call, and attrib 0 generic data queries use cached
7531 // values instead of passing down to the underlying driver.
7532 RestoreStateForAttrib(0, false);
7535 return error::kNoError
;
7538 error::Error
GLES2DecoderImpl::HandleDrawElements(uint32 immediate_data_size
,
7539 const void* cmd_data
) {
7540 // TODO(zmo): crbug.com/481184
7541 // On Desktop GL with versions lower than 4.3, we need to emulate
7542 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7543 const gles2::cmds::DrawElements
& c
=
7544 *static_cast<const gles2::cmds::DrawElements
*>(cmd_data
);
7545 return DoDrawElements("glDrawElements",
7547 static_cast<GLenum
>(c
.mode
),
7548 static_cast<GLsizei
>(c
.count
),
7549 static_cast<GLenum
>(c
.type
),
7550 static_cast<int32
>(c
.index_offset
),
7554 error::Error
GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
7555 uint32 immediate_data_size
,
7556 const void* cmd_data
) {
7557 const gles2::cmds::DrawElementsInstancedANGLE
& c
=
7558 *static_cast<const gles2::cmds::DrawElementsInstancedANGLE
*>(cmd_data
);
7559 if (!features().angle_instanced_arrays
) {
7561 GL_INVALID_OPERATION
,
7562 "glDrawElementsInstancedANGLE", "function not available");
7563 return error::kNoError
;
7565 return DoDrawElements("glDrawElementsInstancedANGLE",
7567 static_cast<GLenum
>(c
.mode
),
7568 static_cast<GLsizei
>(c
.count
),
7569 static_cast<GLenum
>(c
.type
),
7570 static_cast<int32
>(c
.index_offset
),
7571 static_cast<GLsizei
>(c
.primcount
));
7574 GLuint
GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
7575 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
7576 GLuint max_vertex_accessed
= 0;
7577 Buffer
* buffer
= GetBuffer(buffer_id
);
7579 // TODO(gman): Should this be a GL error or a command buffer error?
7581 GL_INVALID_VALUE
, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
7583 if (!buffer
->GetMaxValueForRange(
7584 offset
, count
, type
, &max_vertex_accessed
)) {
7585 // TODO(gman): Should this be a GL error or a command buffer error?
7587 GL_INVALID_OPERATION
,
7588 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
7591 return max_vertex_accessed
;
7594 void GLES2DecoderImpl::DoShaderSource(
7595 GLuint client_id
, GLsizei count
, const char** data
, const GLint
* length
) {
7597 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
7598 if (length
&& length
[ii
] > 0)
7599 str
.append(data
[ii
], length
[ii
]);
7601 str
.append(data
[ii
]);
7603 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glShaderSource");
7607 // Note: We don't actually call glShaderSource here. We wait until
7608 // we actually compile the shader.
7609 shader
->set_source(str
);
7612 void GLES2DecoderImpl::DoTransformFeedbackVaryings(
7613 GLuint client_program_id
, GLsizei count
, const char* const* varyings
,
7614 GLenum buffer_mode
) {
7615 Program
* program
= GetProgramInfoNotShader(
7616 client_program_id
, "glTransformFeedbackVaryings");
7620 program
->TransformFeedbackVaryings(count
, varyings
, buffer_mode
);
7621 glTransformFeedbackVaryings(
7622 program
->service_id(), count
, varyings
, buffer_mode
);
7625 void GLES2DecoderImpl::DoCompileShader(GLuint client_id
) {
7626 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
7627 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glCompileShader");
7632 scoped_refptr
<ShaderTranslatorInterface
> translator
;
7633 if (use_shader_translator_
) {
7634 translator
= shader
->shader_type() == GL_VERTEX_SHADER
?
7635 vertex_translator_
: fragment_translator_
;
7638 const Shader::TranslatedShaderSourceType source_type
=
7639 feature_info_
->feature_flags().angle_translated_shader_source
?
7640 Shader::kANGLE
: Shader::kGL
;
7641 shader
->RequestCompile(translator
, source_type
);
7644 void GLES2DecoderImpl::DoGetShaderiv(
7645 GLuint shader_id
, GLenum pname
, GLint
* params
) {
7646 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderiv");
7651 // Compile now for statuses that require it.
7653 case GL_COMPILE_STATUS
:
7654 case GL_INFO_LOG_LENGTH
:
7655 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE
:
7656 shader
->DoCompile();
7664 case GL_SHADER_SOURCE_LENGTH
:
7665 *params
= shader
->source().size();
7669 case GL_COMPILE_STATUS
:
7670 *params
= compile_shader_always_succeeds_
? true : shader
->valid();
7672 case GL_INFO_LOG_LENGTH
:
7673 *params
= shader
->log_info().size();
7677 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE
:
7678 *params
= shader
->translated_source().size();
7685 glGetShaderiv(shader
->service_id(), pname
, params
);
7688 error::Error
GLES2DecoderImpl::HandleGetShaderSource(uint32 immediate_data_size
,
7689 const void* cmd_data
) {
7690 const gles2::cmds::GetShaderSource
& c
=
7691 *static_cast<const gles2::cmds::GetShaderSource
*>(cmd_data
);
7692 GLuint shader_id
= c
.shader
;
7693 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7694 Bucket
* bucket
= CreateBucket(bucket_id
);
7695 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderSource");
7696 if (!shader
|| shader
->source().empty()) {
7698 return error::kNoError
;
7700 bucket
->SetFromString(shader
->source().c_str());
7701 return error::kNoError
;
7704 error::Error
GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
7705 uint32 immediate_data_size
,
7706 const void* cmd_data
) {
7707 const gles2::cmds::GetTranslatedShaderSourceANGLE
& c
=
7708 *static_cast<const gles2::cmds::GetTranslatedShaderSourceANGLE
*>(
7710 GLuint shader_id
= c
.shader
;
7711 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7712 Bucket
* bucket
= CreateBucket(bucket_id
);
7713 Shader
* shader
= GetShaderInfoNotProgram(
7714 shader_id
, "glGetTranslatedShaderSourceANGLE");
7717 return error::kNoError
;
7720 // Make sure translator has been utilized in compile.
7721 shader
->DoCompile();
7723 bucket
->SetFromString(shader
->translated_source().c_str());
7724 return error::kNoError
;
7727 error::Error
GLES2DecoderImpl::HandleGetProgramInfoLog(
7728 uint32 immediate_data_size
,
7729 const void* cmd_data
) {
7730 const gles2::cmds::GetProgramInfoLog
& c
=
7731 *static_cast<const gles2::cmds::GetProgramInfoLog
*>(cmd_data
);
7732 GLuint program_id
= c
.program
;
7733 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7734 Bucket
* bucket
= CreateBucket(bucket_id
);
7735 Program
* program
= GetProgramInfoNotShader(
7736 program_id
, "glGetProgramInfoLog");
7737 if (!program
|| !program
->log_info()) {
7738 bucket
->SetFromString("");
7739 return error::kNoError
;
7741 bucket
->SetFromString(program
->log_info()->c_str());
7742 return error::kNoError
;
7745 error::Error
GLES2DecoderImpl::HandleGetShaderInfoLog(
7746 uint32 immediate_data_size
,
7747 const void* cmd_data
) {
7748 const gles2::cmds::GetShaderInfoLog
& c
=
7749 *static_cast<const gles2::cmds::GetShaderInfoLog
*>(cmd_data
);
7750 GLuint shader_id
= c
.shader
;
7751 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7752 Bucket
* bucket
= CreateBucket(bucket_id
);
7753 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderInfoLog");
7755 bucket
->SetFromString("");
7756 return error::kNoError
;
7759 // Shader must be compiled in order to get the info log.
7760 shader
->DoCompile();
7762 bucket
->SetFromString(shader
->log_info().c_str());
7763 return error::kNoError
;
7766 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap
) {
7767 return state_
.GetEnabled(cap
);
7770 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id
) {
7771 const Buffer
* buffer
= GetBuffer(client_id
);
7772 return buffer
&& buffer
->IsValid() && !buffer
->IsDeleted();
7775 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id
) {
7776 const Framebuffer
* framebuffer
=
7777 GetFramebuffer(client_id
);
7778 return framebuffer
&& framebuffer
->IsValid() && !framebuffer
->IsDeleted();
7781 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id
) {
7782 // IsProgram is true for programs as soon as they are created, until they are
7783 // deleted and no longer in use.
7784 const Program
* program
= GetProgram(client_id
);
7785 return program
!= NULL
&& !program
->IsDeleted();
7788 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id
) {
7789 const Renderbuffer
* renderbuffer
=
7790 GetRenderbuffer(client_id
);
7791 return renderbuffer
&& renderbuffer
->IsValid() && !renderbuffer
->IsDeleted();
7794 bool GLES2DecoderImpl::DoIsShader(GLuint client_id
) {
7795 // IsShader is true for shaders as soon as they are created, until they
7796 // are deleted and not attached to any programs.
7797 const Shader
* shader
= GetShader(client_id
);
7798 return shader
!= NULL
&& !shader
->IsDeleted();
7801 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id
) {
7802 const TextureRef
* texture_ref
= GetTexture(client_id
);
7803 return texture_ref
&& texture_ref
->texture()->IsValid();
7806 void GLES2DecoderImpl::DoAttachShader(
7807 GLuint program_client_id
, GLint shader_client_id
) {
7808 Program
* program
= GetProgramInfoNotShader(
7809 program_client_id
, "glAttachShader");
7813 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glAttachShader");
7817 if (!program
->AttachShader(shader_manager(), shader
)) {
7819 GL_INVALID_OPERATION
,
7821 "can not attach more than one shader of the same type.");
7824 glAttachShader(program
->service_id(), shader
->service_id());
7827 void GLES2DecoderImpl::DoDetachShader(
7828 GLuint program_client_id
, GLint shader_client_id
) {
7829 Program
* program
= GetProgramInfoNotShader(
7830 program_client_id
, "glDetachShader");
7834 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glDetachShader");
7838 if (!program
->DetachShader(shader_manager(), shader
)) {
7840 GL_INVALID_OPERATION
,
7841 "glDetachShader", "shader not attached to program");
7844 glDetachShader(program
->service_id(), shader
->service_id());
7847 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id
) {
7848 Program
* program
= GetProgramInfoNotShader(
7849 program_client_id
, "glValidateProgram");
7853 program
->Validate();
7856 void GLES2DecoderImpl::GetVertexAttribHelper(
7857 const VertexAttrib
* attrib
, GLenum pname
, GLint
* params
) {
7859 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
:
7861 Buffer
* buffer
= attrib
->buffer();
7862 if (buffer
&& !buffer
->IsDeleted()) {
7864 buffer_manager()->GetClientId(buffer
->service_id(), &client_id
);
7865 *params
= client_id
;
7869 case GL_VERTEX_ATTRIB_ARRAY_ENABLED
:
7870 *params
= attrib
->enabled();
7872 case GL_VERTEX_ATTRIB_ARRAY_SIZE
:
7873 *params
= attrib
->size();
7875 case GL_VERTEX_ATTRIB_ARRAY_STRIDE
:
7876 *params
= attrib
->gl_stride();
7878 case GL_VERTEX_ATTRIB_ARRAY_TYPE
:
7879 *params
= attrib
->type();
7881 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED
:
7882 *params
= attrib
->normalized();
7884 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR
:
7885 *params
= attrib
->divisor();
7887 case GL_VERTEX_ATTRIB_ARRAY_INTEGER
:
7888 *params
= attrib
->integer();
7896 void GLES2DecoderImpl::DoGetTexParameterfv(
7897 GLenum target
, GLenum pname
, GLfloat
* params
) {
7898 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
7899 glGetTexParameterfv(target
, pname
, params
);
7902 void GLES2DecoderImpl::DoGetTexParameteriv(
7903 GLenum target
, GLenum pname
, GLint
* params
) {
7904 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
7905 glGetTexParameteriv(target
, pname
, params
);
7908 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
7909 GLenum target
, GLenum pname
) {
7910 if (!workarounds().init_texture_max_anisotropy
)
7912 if (pname
!= GL_TEXTURE_MAX_ANISOTROPY_EXT
||
7913 !validators_
->texture_parameter
.IsValid(pname
)) {
7917 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
7921 GL_INVALID_OPERATION
,
7922 "glGetTexParamter{fi}v", "unknown texture for target");
7925 Texture
* texture
= texture_ref
->texture();
7926 texture
->InitTextureMaxAnisotropyIfNeeded(target
);
7929 template <typename T
>
7930 void GLES2DecoderImpl::DoGetVertexAttribImpl(
7931 GLuint index
, GLenum pname
, T
* params
) {
7932 VertexAttrib
* attrib
= state_
.vertex_attrib_manager
->GetVertexAttrib(index
);
7935 GL_INVALID_VALUE
, "glGetVertexAttrib", "index out of range");
7939 case GL_CURRENT_VERTEX_ATTRIB
:
7940 state_
.attrib_values
[index
].GetValues(params
);
7944 GetVertexAttribHelper(attrib
, pname
, &value
);
7945 *params
= static_cast<T
>(value
);
7951 void GLES2DecoderImpl::DoGetVertexAttribfv(
7952 GLuint index
, GLenum pname
, GLfloat
* params
) {
7953 DoGetVertexAttribImpl
<GLfloat
>(index
, pname
, params
);
7956 void GLES2DecoderImpl::DoGetVertexAttribiv(
7957 GLuint index
, GLenum pname
, GLint
* params
) {
7958 DoGetVertexAttribImpl
<GLint
>(index
, pname
, params
);
7961 void GLES2DecoderImpl::DoGetVertexAttribIiv(
7962 GLuint index
, GLenum pname
, GLint
* params
) {
7963 DoGetVertexAttribImpl
<GLint
>(index
, pname
, params
);
7966 void GLES2DecoderImpl::DoGetVertexAttribIuiv(
7967 GLuint index
, GLenum pname
, GLuint
* params
) {
7968 DoGetVertexAttribImpl
<GLuint
>(index
, pname
, params
);
7971 template <typename T
>
7972 bool GLES2DecoderImpl::SetVertexAttribValue(
7973 const char* function_name
, GLuint index
, const T
* value
) {
7974 if (index
>= state_
.attrib_values
.size()) {
7975 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "index out of range");
7978 state_
.attrib_values
[index
].SetValues(value
);
7982 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index
, GLfloat v0
) {
7983 GLfloat v
[4] = { v0
, 0.0f
, 0.0f
, 1.0f
, };
7984 if (SetVertexAttribValue("glVertexAttrib1f", index
, v
)) {
7985 glVertexAttrib1f(index
, v0
);
7989 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
) {
7990 GLfloat v
[4] = { v0
, v1
, 0.0f
, 1.0f
, };
7991 if (SetVertexAttribValue("glVertexAttrib2f", index
, v
)) {
7992 glVertexAttrib2f(index
, v0
, v1
);
7996 void GLES2DecoderImpl::DoVertexAttrib3f(
7997 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
) {
7998 GLfloat v
[4] = { v0
, v1
, v2
, 1.0f
, };
7999 if (SetVertexAttribValue("glVertexAttrib3f", index
, v
)) {
8000 glVertexAttrib3f(index
, v0
, v1
, v2
);
8004 void GLES2DecoderImpl::DoVertexAttrib4f(
8005 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
) {
8006 GLfloat v
[4] = { v0
, v1
, v2
, v3
, };
8007 if (SetVertexAttribValue("glVertexAttrib4f", index
, v
)) {
8008 glVertexAttrib4f(index
, v0
, v1
, v2
, v3
);
8012 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index
, const GLfloat
* v
) {
8013 GLfloat t
[4] = { v
[0], 0.0f
, 0.0f
, 1.0f
, };
8014 if (SetVertexAttribValue("glVertexAttrib1fv", index
, t
)) {
8015 glVertexAttrib1fv(index
, v
);
8019 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index
, const GLfloat
* v
) {
8020 GLfloat t
[4] = { v
[0], v
[1], 0.0f
, 1.0f
, };
8021 if (SetVertexAttribValue("glVertexAttrib2fv", index
, t
)) {
8022 glVertexAttrib2fv(index
, v
);
8026 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index
, const GLfloat
* v
) {
8027 GLfloat t
[4] = { v
[0], v
[1], v
[2], 1.0f
, };
8028 if (SetVertexAttribValue("glVertexAttrib3fv", index
, t
)) {
8029 glVertexAttrib3fv(index
, v
);
8033 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index
, const GLfloat
* v
) {
8034 if (SetVertexAttribValue("glVertexAttrib4fv", index
, v
)) {
8035 glVertexAttrib4fv(index
, v
);
8039 void GLES2DecoderImpl::DoVertexAttribI4i(
8040 GLuint index
, GLint v0
, GLint v1
, GLint v2
, GLint v3
) {
8041 GLint v
[4] = { v0
, v1
, v2
, v3
};
8042 if (SetVertexAttribValue("glVertexAttribI4i", index
, v
)) {
8043 glVertexAttribI4i(index
, v0
, v1
, v2
, v3
);
8047 void GLES2DecoderImpl::DoVertexAttribI4iv(GLuint index
, const GLint
* v
) {
8048 if (SetVertexAttribValue("glVertexAttribI4iv", index
, v
)) {
8049 glVertexAttribI4iv(index
, v
);
8053 void GLES2DecoderImpl::DoVertexAttribI4ui(
8054 GLuint index
, GLuint v0
, GLuint v1
, GLuint v2
, GLuint v3
) {
8055 GLuint v
[4] = { v0
, v1
, v2
, v3
};
8056 if (SetVertexAttribValue("glVertexAttribI4ui", index
, v
)) {
8057 glVertexAttribI4ui(index
, v0
, v1
, v2
, v3
);
8061 void GLES2DecoderImpl::DoVertexAttribI4uiv(GLuint index
, const GLuint
* v
) {
8062 if (SetVertexAttribValue("glVertexAttribI4uiv", index
, v
)) {
8063 glVertexAttribI4uiv(index
, v
);
8067 error::Error
GLES2DecoderImpl::HandleVertexAttribIPointer(
8068 uint32 immediate_data_size
,
8069 const void* cmd_data
) {
8070 if (!unsafe_es3_apis_enabled())
8071 return error::kUnknownCommand
;
8072 const gles2::cmds::VertexAttribIPointer
& c
=
8073 *static_cast<const gles2::cmds::VertexAttribIPointer
*>(cmd_data
);
8075 if (!state_
.bound_array_buffer
.get() ||
8076 state_
.bound_array_buffer
->IsDeleted()) {
8077 if (state_
.vertex_attrib_manager
.get() ==
8078 state_
.default_vertex_attrib_manager
.get()) {
8080 GL_INVALID_VALUE
, "glVertexAttribIPointer", "no array buffer bound");
8081 return error::kNoError
;
8082 } else if (c
.offset
!= 0) {
8085 "glVertexAttribIPointer", "client side arrays are not allowed");
8086 return error::kNoError
;
8090 GLuint indx
= c
.indx
;
8091 GLint size
= c
.size
;
8092 GLenum type
= c
.type
;
8093 GLsizei stride
= c
.stride
;
8094 GLsizei offset
= c
.offset
;
8095 const void* ptr
= reinterpret_cast<const void*>(offset
);
8096 if (!validators_
->vertex_attrib_i_type
.IsValid(type
)) {
8097 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribIPointer", type
, "type");
8098 return error::kNoError
;
8100 if (!validators_
->vertex_attrib_size
.IsValid(size
)) {
8102 GL_INVALID_VALUE
, "glVertexAttribIPointer", "size GL_INVALID_VALUE");
8103 return error::kNoError
;
8105 if (indx
>= group_
->max_vertex_attribs()) {
8107 GL_INVALID_VALUE
, "glVertexAttribIPointer", "index out of range");
8108 return error::kNoError
;
8112 GL_INVALID_VALUE
, "glVertexAttribIPointer", "stride < 0");
8113 return error::kNoError
;
8117 GL_INVALID_VALUE
, "glVertexAttribIPointer", "stride > 255");
8118 return error::kNoError
;
8122 GL_INVALID_VALUE
, "glVertexAttribIPointer", "offset < 0");
8123 return error::kNoError
;
8125 GLsizei component_size
=
8126 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type
);
8127 // component_size must be a power of two to use & as optimized modulo.
8128 DCHECK(GLES2Util::IsPOT(component_size
));
8129 if (offset
& (component_size
- 1)) {
8131 GL_INVALID_OPERATION
,
8132 "glVertexAttribIPointer", "offset not valid for type");
8133 return error::kNoError
;
8135 if (stride
& (component_size
- 1)) {
8137 GL_INVALID_OPERATION
,
8138 "glVertexAttribIPointer", "stride not valid for type");
8139 return error::kNoError
;
8141 state_
.vertex_attrib_manager
8142 ->SetAttribInfo(indx
,
8143 state_
.bound_array_buffer
.get(),
8148 stride
!= 0 ? stride
: component_size
* size
,
8151 glVertexAttribIPointer(indx
, size
, type
, stride
, ptr
);
8152 return error::kNoError
;
8155 error::Error
GLES2DecoderImpl::HandleVertexAttribPointer(
8156 uint32 immediate_data_size
,
8157 const void* cmd_data
) {
8158 const gles2::cmds::VertexAttribPointer
& c
=
8159 *static_cast<const gles2::cmds::VertexAttribPointer
*>(cmd_data
);
8161 if (!state_
.bound_array_buffer
.get() ||
8162 state_
.bound_array_buffer
->IsDeleted()) {
8163 if (state_
.vertex_attrib_manager
.get() ==
8164 state_
.default_vertex_attrib_manager
.get()) {
8166 GL_INVALID_VALUE
, "glVertexAttribPointer", "no array buffer bound");
8167 return error::kNoError
;
8168 } else if (c
.offset
!= 0) {
8171 "glVertexAttribPointer", "client side arrays are not allowed");
8172 return error::kNoError
;
8176 GLuint indx
= c
.indx
;
8177 GLint size
= c
.size
;
8178 GLenum type
= c
.type
;
8179 GLboolean normalized
= static_cast<GLboolean
>(c
.normalized
);
8180 GLsizei stride
= c
.stride
;
8181 GLsizei offset
= c
.offset
;
8182 const void* ptr
= reinterpret_cast<const void*>(offset
);
8183 if (!validators_
->vertex_attrib_type
.IsValid(type
)) {
8184 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type
, "type");
8185 return error::kNoError
;
8187 if (!validators_
->vertex_attrib_size
.IsValid(size
)) {
8189 GL_INVALID_VALUE
, "glVertexAttribPointer", "size GL_INVALID_VALUE");
8190 return error::kNoError
;
8192 if (indx
>= group_
->max_vertex_attribs()) {
8194 GL_INVALID_VALUE
, "glVertexAttribPointer", "index out of range");
8195 return error::kNoError
;
8199 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride < 0");
8200 return error::kNoError
;
8204 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride > 255");
8205 return error::kNoError
;
8209 GL_INVALID_VALUE
, "glVertexAttribPointer", "offset < 0");
8210 return error::kNoError
;
8212 GLsizei component_size
=
8213 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type
);
8214 // component_size must be a power of two to use & as optimized modulo.
8215 DCHECK(GLES2Util::IsPOT(component_size
));
8216 if (offset
& (component_size
- 1)) {
8218 GL_INVALID_OPERATION
,
8219 "glVertexAttribPointer", "offset not valid for type");
8220 return error::kNoError
;
8222 if (stride
& (component_size
- 1)) {
8224 GL_INVALID_OPERATION
,
8225 "glVertexAttribPointer", "stride not valid for type");
8226 return error::kNoError
;
8228 state_
.vertex_attrib_manager
8229 ->SetAttribInfo(indx
,
8230 state_
.bound_array_buffer
.get(),
8235 stride
!= 0 ? stride
: component_size
* size
,
8238 // We support GL_FIXED natively on EGL/GLES2 implementations
8239 if (type
!= GL_FIXED
|| feature_info_
->gl_version_info().is_es
) {
8240 glVertexAttribPointer(indx
, size
, type
, normalized
, stride
, ptr
);
8242 return error::kNoError
;
8245 void GLES2DecoderImpl::DoViewport(GLint x
, GLint y
, GLsizei width
,
8247 state_
.viewport_x
= x
;
8248 state_
.viewport_y
= y
;
8249 state_
.viewport_width
= std::min(width
, viewport_max_width_
);
8250 state_
.viewport_height
= std::min(height
, viewport_max_height_
);
8251 glViewport(x
, y
, width
, height
);
8254 error::Error
GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
8255 uint32 immediate_data_size
,
8256 const void* cmd_data
) {
8257 const gles2::cmds::VertexAttribDivisorANGLE
& c
=
8258 *static_cast<const gles2::cmds::VertexAttribDivisorANGLE
*>(cmd_data
);
8259 if (!features().angle_instanced_arrays
) {
8261 GL_INVALID_OPERATION
,
8262 "glVertexAttribDivisorANGLE", "function not available");
8263 return error::kNoError
;
8265 GLuint index
= c
.index
;
8266 GLuint divisor
= c
.divisor
;
8267 if (index
>= group_
->max_vertex_attribs()) {
8270 "glVertexAttribDivisorANGLE", "index out of range");
8271 return error::kNoError
;
8274 state_
.vertex_attrib_manager
->SetDivisor(
8277 glVertexAttribDivisorANGLE(index
, divisor
);
8278 return error::kNoError
;
8281 template <typename pixel_data_type
>
8282 static void WriteAlphaData(
8283 void* pixels
, uint32 row_count
, uint32 channel_count
,
8284 uint32 alpha_channel_index
, uint32 unpadded_row_size
,
8285 uint32 padded_row_size
, pixel_data_type alpha_value
) {
8286 DCHECK_GT(channel_count
, 0U);
8287 DCHECK_EQ(unpadded_row_size
% sizeof(pixel_data_type
), 0U);
8288 uint32 unpadded_row_size_in_elements
=
8289 unpadded_row_size
/ sizeof(pixel_data_type
);
8290 DCHECK_EQ(padded_row_size
% sizeof(pixel_data_type
), 0U);
8291 uint32 padded_row_size_in_elements
=
8292 padded_row_size
/ sizeof(pixel_data_type
);
8293 pixel_data_type
* dst
=
8294 static_cast<pixel_data_type
*>(pixels
) + alpha_channel_index
;
8295 for (uint32 yy
= 0; yy
< row_count
; ++yy
) {
8296 pixel_data_type
* end
= dst
+ unpadded_row_size_in_elements
;
8297 for (pixel_data_type
* d
= dst
; d
< end
; d
+= channel_count
) {
8300 dst
+= padded_row_size_in_elements
;
8304 void GLES2DecoderImpl::FinishReadPixels(
8305 const cmds::ReadPixels
& c
,
8307 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
8308 GLsizei width
= c
.width
;
8309 GLsizei height
= c
.height
;
8310 GLenum format
= c
.format
;
8311 GLenum type
= c
.type
;
8312 typedef cmds::ReadPixels::Result Result
;
8314 Result
* result
= NULL
;
8315 if (c
.result_shm_id
!= 0) {
8316 result
= GetSharedMemoryAs
<Result
*>(
8317 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
8320 glDeleteBuffersARB(1, &buffer
);
8325 GLES2Util::ComputeImageDataSizes(
8326 width
, height
, 1, format
, type
, state_
.pack_alignment
, &pixels_size
,
8328 void* pixels
= GetSharedMemoryAs
<void*>(
8329 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
8332 glDeleteBuffersARB(1, &buffer
);
8338 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
8340 if (features().map_buffer_range
) {
8341 data
= glMapBufferRange(
8342 GL_PIXEL_PACK_BUFFER_ARB
, 0, pixels_size
, GL_MAP_READ_BIT
);
8344 data
= glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB
, GL_READ_ONLY
);
8347 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glMapBuffer",
8348 "Unable to map memory for readback.");
8351 memcpy(pixels
, data
, pixels_size
);
8352 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
8353 // have to restore the state.
8354 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB
);
8355 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
8356 glDeleteBuffersARB(1, &buffer
);
8359 if (result
!= NULL
) {
8363 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
8364 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
8365 if ((channels_exist
& 0x0008) == 0 &&
8366 workarounds().clear_alpha_in_readpixels
) {
8367 // Set the alpha to 255 because some drivers are buggy in this regard.
8370 uint32 unpadded_row_size
;
8371 uint32 padded_row_size
;
8372 if (!GLES2Util::ComputeImageDataSizes(
8373 width
, 2, 1, format
, type
, state_
.pack_alignment
, &temp_size
,
8374 &unpadded_row_size
, &padded_row_size
)) {
8378 uint32 channel_count
= 0;
8379 uint32 alpha_channel
= 0;
8392 if (channel_count
> 0) {
8394 case GL_UNSIGNED_BYTE
:
8395 WriteAlphaData
<uint8
>(
8396 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
8397 padded_row_size
, 0xFF);
8400 WriteAlphaData
<float>(
8401 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
8402 padded_row_size
, 1.0f
);
8405 WriteAlphaData
<uint16
>(
8406 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
8407 padded_row_size
, 0x3C00);
8414 error::Error
GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size
,
8415 const void* cmd_data
) {
8416 const gles2::cmds::ReadPixels
& c
=
8417 *static_cast<const gles2::cmds::ReadPixels
*>(cmd_data
);
8418 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
8419 error::Error fbo_error
= WillAccessBoundFramebufferForRead();
8420 if (fbo_error
!= error::kNoError
)
8424 GLsizei width
= c
.width
;
8425 GLsizei height
= c
.height
;
8426 GLenum format
= c
.format
;
8427 GLenum type
= c
.type
;
8428 GLboolean async
= static_cast<GLboolean
>(c
.async
);
8429 if (width
< 0 || height
< 0) {
8430 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glReadPixels", "dimensions < 0");
8431 return error::kNoError
;
8433 typedef cmds::ReadPixels::Result Result
;
8435 if (!GLES2Util::ComputeImageDataSizes(
8436 width
, height
, 1, format
, type
, state_
.pack_alignment
, &pixels_size
,
8438 return error::kOutOfBounds
;
8440 void* pixels
= GetSharedMemoryAs
<void*>(
8441 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
8443 return error::kOutOfBounds
;
8445 Result
* result
= NULL
;
8446 if (c
.result_shm_id
!= 0) {
8447 result
= GetSharedMemoryAs
<Result
*>(
8448 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
8450 return error::kOutOfBounds
;
8454 if (!validators_
->read_pixel_format
.IsValid(format
)) {
8455 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format
, "format");
8456 return error::kNoError
;
8458 if (!validators_
->read_pixel_type
.IsValid(type
)) {
8459 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type
, "type");
8460 return error::kNoError
;
8463 GLenum src_internal_format
= GetBoundReadFrameBufferInternalFormat();
8464 if (src_internal_format
== 0) {
8465 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glReadPixels",
8466 "no valid read buffer source");
8467 return error::kNoError
;
8469 std::vector
<GLenum
> accepted_formats
;
8470 std::vector
<GLenum
> accepted_types
;
8471 switch (src_internal_format
) {
8473 accepted_formats
.push_back(GL_RGBA
);
8474 accepted_types
.push_back(GL_UNSIGNED_INT_2_10_10_10_REV
);
8481 // All the RGB_INTEGER formats are not renderable.
8485 accepted_formats
.push_back(GL_RGBA_INTEGER
);
8486 accepted_types
.push_back(GL_UNSIGNED_INT
);
8497 accepted_formats
.push_back(GL_RGBA_INTEGER
);
8498 accepted_types
.push_back(GL_INT
);
8501 accepted_formats
.push_back(GL_RGBA
);
8503 GLenum src_type
= GetBoundReadFrameBufferTextureType();
8506 case GL_HALF_FLOAT_OES
:
8508 case GL_UNSIGNED_INT_10F_11F_11F_REV
:
8509 accepted_types
.push_back(GL_FLOAT
);
8512 accepted_types
.push_back(GL_UNSIGNED_BYTE
);
8518 if (!IsWebGLContext()) {
8519 accepted_formats
.push_back(GL_BGRA_EXT
);
8520 accepted_types
.push_back(GL_UNSIGNED_BYTE
);
8522 DCHECK_EQ(accepted_formats
.size(), accepted_types
.size());
8523 bool format_type_acceptable
= false;
8524 for (size_t ii
= 0; ii
< accepted_formats
.size(); ++ii
) {
8525 if (format
== accepted_formats
[ii
] && type
== accepted_types
[ii
]) {
8526 format_type_acceptable
= true;
8530 if (!format_type_acceptable
) {
8531 // format and type are acceptable enums but not guaranteed to be supported
8532 // for this framebuffer. Have to ask gl if they are valid.
8533 GLint preferred_format
= 0;
8534 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT
, &preferred_format
);
8535 GLint preferred_type
= 0;
8536 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE
, &preferred_type
);
8537 if (format
== static_cast<GLenum
>(preferred_format
) &&
8538 type
== static_cast<GLenum
>(preferred_type
)) {
8539 format_type_acceptable
= true;
8542 if (!format_type_acceptable
) {
8543 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glReadPixels",
8544 "format and type incompatible with the current read framebuffer");
8545 return error::kNoError
;
8547 if (width
== 0 || height
== 0) {
8548 return error::kNoError
;
8551 // Get the size of the current fbo or backbuffer.
8552 gfx::Size max_size
= GetBoundReadFrameBufferSize();
8556 if (!SafeAddInt32(x
, width
, &max_x
) || !SafeAddInt32(y
, height
, &max_y
)) {
8558 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
8559 return error::kNoError
;
8562 if (!CheckBoundFramebuffersValid("glReadPixels")) {
8563 return error::kNoError
;
8566 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
8568 ScopedResolvedFrameBufferBinder
binder(this, false, true);
8570 if (x
< 0 || y
< 0 || max_x
> max_size
.width() || max_y
> max_size
.height()) {
8571 // The user requested an out of range area. Get the results 1 line
8574 uint32 unpadded_row_size
;
8575 uint32 padded_row_size
;
8576 if (!GLES2Util::ComputeImageDataSizes(
8577 width
, 2, 1, format
, type
, state_
.pack_alignment
, &temp_size
,
8578 &unpadded_row_size
, &padded_row_size
)) {
8580 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
8581 return error::kNoError
;
8584 GLint dest_x_offset
= std::max(-x
, 0);
8585 uint32 dest_row_offset
;
8586 if (!GLES2Util::ComputeImageDataSizes(
8587 dest_x_offset
, 1, 1, format
, type
, state_
.pack_alignment
,
8588 &dest_row_offset
, NULL
, NULL
)) {
8590 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
8591 return error::kNoError
;
8594 // Copy each row into the larger dest rect.
8595 int8
* dst
= static_cast<int8
*>(pixels
);
8596 GLint read_x
= std::max(0, x
);
8597 GLint read_end_x
= std::max(0, std::min(max_size
.width(), max_x
));
8598 GLint read_width
= read_end_x
- read_x
;
8599 for (GLint yy
= 0; yy
< height
; ++yy
) {
8603 memset(dst
, 0, unpadded_row_size
);
8605 // If the row is in range, copy it.
8606 if (ry
>= 0 && ry
< max_size
.height() && read_width
> 0) {
8608 read_x
, ry
, read_width
, 1, format
, type
, dst
+ dest_row_offset
);
8610 dst
+= padded_row_size
;
8613 if (async
&& features().use_async_readpixels
) {
8615 glGenBuffersARB(1, &buffer
);
8616 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
8617 // For ANGLE client version 2, GL_STREAM_READ is not available.
8618 const GLenum usage_hint
= feature_info_
->gl_version_info().is_angle
?
8619 GL_STATIC_DRAW
: GL_STREAM_READ
;
8620 glBufferData(GL_PIXEL_PACK_BUFFER_ARB
, pixels_size
, NULL
, usage_hint
);
8621 GLenum error
= glGetError();
8622 if (error
== GL_NO_ERROR
) {
8623 glReadPixels(x
, y
, width
, height
, format
, type
, 0);
8624 pending_readpixel_fences_
.push(linked_ptr
<FenceCallback
>(
8625 new FenceCallback()));
8626 WaitForReadPixels(base::Bind(
8627 &GLES2DecoderImpl::FinishReadPixels
,
8628 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
8629 <GLES2DecoderImpl
>(this),
8631 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
8632 return error::kNoError
;
8634 // On error, unbind pack buffer and fall through to sync readpixels
8635 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
8636 glDeleteBuffersARB(1, &buffer
);
8639 glReadPixels(x
, y
, width
, height
, format
, type
, pixels
);
8641 GLenum error
= LOCAL_PEEK_GL_ERROR("glReadPixels");
8642 if (error
== GL_NO_ERROR
) {
8643 if (result
!= NULL
) {
8646 FinishReadPixels(c
, 0);
8649 return error::kNoError
;
8652 error::Error
GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size
,
8653 const void* cmd_data
) {
8654 const gles2::cmds::PixelStorei
& c
=
8655 *static_cast<const gles2::cmds::PixelStorei
*>(cmd_data
);
8656 GLenum pname
= c
.pname
;
8657 GLenum param
= c
.param
;
8658 if (!validators_
->pixel_store
.IsValid(pname
)) {
8659 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname
, "pname");
8660 return error::kNoError
;
8663 case GL_PACK_ALIGNMENT
:
8664 case GL_UNPACK_ALIGNMENT
:
8665 if (!validators_
->pixel_store_alignment
.IsValid(param
)) {
8667 GL_INVALID_VALUE
, "glPixelStorei", "param GL_INVALID_VALUE");
8668 return error::kNoError
;
8674 glPixelStorei(pname
, param
);
8676 case GL_PACK_ALIGNMENT
:
8677 state_
.pack_alignment
= param
;
8679 case GL_PACK_REVERSE_ROW_ORDER_ANGLE
:
8680 state_
.pack_reverse_row_order
= (param
!= 0);
8682 case GL_UNPACK_ALIGNMENT
:
8683 state_
.unpack_alignment
= param
;
8686 // Validation should have prevented us from getting here.
8690 return error::kNoError
;
8693 error::Error
GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
8694 uint32 immediate_data_size
,
8695 const void* cmd_data
) {
8696 const gles2::cmds::PostSubBufferCHROMIUM
& c
=
8697 *static_cast<const gles2::cmds::PostSubBufferCHROMIUM
*>(cmd_data
);
8698 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
8700 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
8702 if (!supports_post_sub_buffer_
) {
8704 GL_INVALID_OPERATION
,
8705 "glPostSubBufferCHROMIUM", "command not supported by surface");
8706 return error::kNoError
;
8709 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
8712 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
8713 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
8714 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
8715 is_offscreen
? offscreen_size_
: surface_
->GetSize());
8717 if (surface_
->PostSubBuffer(c
.x
, c
.y
, c
.width
, c
.height
) !=
8718 gfx::SwapResult::SWAP_FAILED
) {
8719 return error::kNoError
;
8721 LOG(ERROR
) << "Context lost because PostSubBuffer failed.";
8722 return error::kLostContext
;
8726 error::Error
GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
8727 uint32 immediate_data_size
,
8728 const void* cmd_data
) {
8729 const gles2::cmds::ScheduleOverlayPlaneCHROMIUM
& c
=
8730 *static_cast<const gles2::cmds::ScheduleOverlayPlaneCHROMIUM
*>(cmd_data
);
8731 TextureRef
* ref
= texture_manager()->GetTexture(c
.overlay_texture_id
);
8733 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
8734 "glScheduleOverlayPlaneCHROMIUM",
8736 return error::kNoError
;
8738 gfx::GLImage
* image
=
8739 ref
->texture()->GetLevelImage(ref
->texture()->target(), 0);
8741 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
8742 "glScheduleOverlayPlaneCHROMIUM",
8743 "unsupported texture format");
8744 return error::kNoError
;
8746 gfx::OverlayTransform transform
= GetGFXOverlayTransform(c
.plane_transform
);
8747 if (transform
== gfx::OVERLAY_TRANSFORM_INVALID
) {
8748 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM
,
8749 "glScheduleOverlayPlaneCHROMIUM",
8750 "invalid transform enum");
8751 return error::kNoError
;
8753 if (!surface_
->ScheduleOverlayPlane(
8757 gfx::Rect(c
.bounds_x
, c
.bounds_y
, c
.bounds_width
, c
.bounds_height
),
8758 gfx::RectF(c
.uv_x
, c
.uv_y
, c
.uv_width
, c
.uv_height
))) {
8759 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
8760 "glScheduleOverlayPlaneCHROMIUM",
8761 "failed to schedule overlay");
8763 return error::kNoError
;
8766 error::Error
GLES2DecoderImpl::GetAttribLocationHelper(
8767 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8768 const std::string
& name_str
) {
8769 if (!StringIsValidForGLES(name_str
.c_str())) {
8771 GL_INVALID_VALUE
, "glGetAttribLocation", "Invalid character");
8772 return error::kNoError
;
8774 Program
* program
= GetProgramInfoNotShader(
8775 client_id
, "glGetAttribLocation");
8777 return error::kNoError
;
8779 if (!program
->IsValid()) {
8781 GL_INVALID_OPERATION
, "glGetAttribLocation", "program not linked");
8782 return error::kNoError
;
8784 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8785 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8787 return error::kOutOfBounds
;
8789 // Require the client to init this incase the context is lost and we are no
8790 // longer executing commands.
8791 if (*location
!= -1) {
8792 return error::kGenericError
;
8794 *location
= program
->GetAttribLocation(name_str
);
8795 return error::kNoError
;
8798 error::Error
GLES2DecoderImpl::HandleGetAttribLocation(
8799 uint32 immediate_data_size
,
8800 const void* cmd_data
) {
8801 const gles2::cmds::GetAttribLocation
& c
=
8802 *static_cast<const gles2::cmds::GetAttribLocation
*>(cmd_data
);
8803 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8805 return error::kInvalidArguments
;
8807 std::string name_str
;
8808 if (!bucket
->GetAsString(&name_str
)) {
8809 return error::kInvalidArguments
;
8811 return GetAttribLocationHelper(
8812 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8815 error::Error
GLES2DecoderImpl::GetUniformLocationHelper(
8816 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8817 const std::string
& name_str
) {
8818 if (!StringIsValidForGLES(name_str
.c_str())) {
8820 GL_INVALID_VALUE
, "glGetUniformLocation", "Invalid character");
8821 return error::kNoError
;
8823 Program
* program
= GetProgramInfoNotShader(
8824 client_id
, "glGetUniformLocation");
8826 return error::kNoError
;
8828 if (!program
->IsValid()) {
8830 GL_INVALID_OPERATION
, "glGetUniformLocation", "program not linked");
8831 return error::kNoError
;
8833 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8834 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8836 return error::kOutOfBounds
;
8838 // Require the client to init this incase the context is lost an we are no
8839 // longer executing commands.
8840 if (*location
!= -1) {
8841 return error::kGenericError
;
8843 *location
= program
->GetUniformFakeLocation(name_str
);
8844 return error::kNoError
;
8847 error::Error
GLES2DecoderImpl::HandleGetUniformLocation(
8848 uint32 immediate_data_size
,
8849 const void* cmd_data
) {
8850 const gles2::cmds::GetUniformLocation
& c
=
8851 *static_cast<const gles2::cmds::GetUniformLocation
*>(cmd_data
);
8852 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8854 return error::kInvalidArguments
;
8856 std::string name_str
;
8857 if (!bucket
->GetAsString(&name_str
)) {
8858 return error::kInvalidArguments
;
8860 return GetUniformLocationHelper(
8861 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8864 error::Error
GLES2DecoderImpl::HandleGetUniformIndices(
8865 uint32 immediate_data_size
,
8866 const void* cmd_data
) {
8867 if (!unsafe_es3_apis_enabled())
8868 return error::kUnknownCommand
;
8869 const gles2::cmds::GetUniformIndices
& c
=
8870 *static_cast<const gles2::cmds::GetUniformIndices
*>(cmd_data
);
8871 Bucket
* bucket
= GetBucket(c
.names_bucket_id
);
8873 return error::kInvalidArguments
;
8876 std::vector
<char*> names
;
8877 std::vector
<GLint
> len
;
8878 if (!bucket
->GetAsStrings(&count
, &names
, &len
) || count
<= 0) {
8879 return error::kInvalidArguments
;
8881 typedef cmds::GetUniformIndices::Result Result
;
8882 Result
* result
= GetSharedMemoryAs
<Result
*>(
8883 c
.indices_shm_id
, c
.indices_shm_offset
,
8884 Result::ComputeSize(static_cast<size_t>(count
)));
8885 GLuint
* indices
= result
? result
->GetData() : NULL
;
8886 if (indices
== NULL
) {
8887 return error::kOutOfBounds
;
8889 // Check that the client initialized the result.
8890 if (result
->size
!= 0) {
8891 return error::kInvalidArguments
;
8893 Program
* program
= GetProgramInfoNotShader(c
.program
, "glGetUniformIndices");
8895 return error::kNoError
;
8897 GLuint service_id
= program
->service_id();
8898 GLint link_status
= GL_FALSE
;
8899 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
8900 if (link_status
!= GL_TRUE
) {
8901 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
8902 "glGetUniformIndices", "program not linked");
8903 return error::kNoError
;
8905 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetUniformIndices");
8906 glGetUniformIndices(service_id
, count
, &names
[0], indices
);
8907 GLenum error
= glGetError();
8908 if (error
== GL_NO_ERROR
) {
8909 result
->SetNumResults(count
);
8911 LOCAL_SET_GL_ERROR(error
, "GetUniformIndices", "");
8913 return error::kNoError
;
8916 error::Error
GLES2DecoderImpl::GetFragDataLocationHelper(
8917 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8918 const std::string
& name_str
) {
8919 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8920 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8922 return error::kOutOfBounds
;
8924 // Require the client to init this incase the context is lost and we are no
8925 // longer executing commands.
8926 if (*location
!= -1) {
8927 return error::kGenericError
;
8929 Program
* program
= GetProgramInfoNotShader(
8930 client_id
, "glGetFragDataLocation");
8932 return error::kNoError
;
8934 *location
= glGetFragDataLocation(program
->service_id(), name_str
.c_str());
8935 return error::kNoError
;
8938 error::Error
GLES2DecoderImpl::HandleGetFragDataLocation(
8939 uint32 immediate_data_size
,
8940 const void* cmd_data
) {
8941 if (!unsafe_es3_apis_enabled())
8942 return error::kUnknownCommand
;
8943 const gles2::cmds::GetFragDataLocation
& c
=
8944 *static_cast<const gles2::cmds::GetFragDataLocation
*>(cmd_data
);
8945 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8947 return error::kInvalidArguments
;
8949 std::string name_str
;
8950 if (!bucket
->GetAsString(&name_str
)) {
8951 return error::kInvalidArguments
;
8953 return GetFragDataLocationHelper(
8954 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8957 error::Error
GLES2DecoderImpl::HandleGetUniformBlockIndex(
8958 uint32 immediate_data_size
, const void* cmd_data
) {
8959 if (!unsafe_es3_apis_enabled())
8960 return error::kUnknownCommand
;
8961 const gles2::cmds::GetUniformBlockIndex
& c
=
8962 *static_cast<const gles2::cmds::GetUniformBlockIndex
*>(cmd_data
);
8963 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8965 return error::kInvalidArguments
;
8967 std::string name_str
;
8968 if (!bucket
->GetAsString(&name_str
)) {
8969 return error::kInvalidArguments
;
8971 GLuint
* index
= GetSharedMemoryAs
<GLuint
*>(
8972 c
.index_shm_id
, c
.index_shm_offset
, sizeof(GLuint
));
8974 return error::kOutOfBounds
;
8976 // Require the client to init this in case the context is lost and we are no
8977 // longer executing commands.
8978 if (*index
!= GL_INVALID_INDEX
) {
8979 return error::kGenericError
;
8981 Program
* program
= GetProgramInfoNotShader(
8982 c
.program
, "glGetUniformBlockIndex");
8984 return error::kNoError
;
8986 *index
= glGetUniformBlockIndex(program
->service_id(), name_str
.c_str());
8987 return error::kNoError
;
8990 error::Error
GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size
,
8991 const void* cmd_data
) {
8992 const gles2::cmds::GetString
& c
=
8993 *static_cast<const gles2::cmds::GetString
*>(cmd_data
);
8994 GLenum name
= static_cast<GLenum
>(c
.name
);
8995 if (!validators_
->string_type
.IsValid(name
)) {
8996 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name
, "name");
8997 return error::kNoError
;
9000 const char* str
= nullptr;
9001 std::string extensions
;
9004 if (unsafe_es3_apis_enabled())
9005 str
= "OpenGL ES 3.0 Chromium";
9007 str
= "OpenGL ES 2.0 Chromium";
9009 case GL_SHADING_LANGUAGE_VERSION
:
9010 if (unsafe_es3_apis_enabled())
9011 str
= "OpenGL ES GLSL ES 3.0 Chromium";
9013 str
= "OpenGL ES GLSL ES 1.0 Chromium";
9017 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
9018 // They are used by WEBGL_debug_renderer_info.
9019 if (!IsWebGLContext())
9022 str
= reinterpret_cast<const char*>(glGetString(name
));
9026 // For WebGL contexts, strip out the OES derivatives and
9027 // EXT frag depth extensions if they have not been enabled.
9028 if (IsWebGLContext()) {
9029 extensions
= feature_info_
->extensions();
9030 if (!derivatives_explicitly_enabled_
) {
9031 size_t offset
= extensions
.find(kOESDerivativeExtension
);
9032 if (std::string::npos
!= offset
) {
9033 extensions
.replace(offset
, arraysize(kOESDerivativeExtension
),
9037 if (!frag_depth_explicitly_enabled_
) {
9038 size_t offset
= extensions
.find(kEXTFragDepthExtension
);
9039 if (std::string::npos
!= offset
) {
9040 extensions
.replace(offset
, arraysize(kEXTFragDepthExtension
),
9044 if (!draw_buffers_explicitly_enabled_
) {
9045 size_t offset
= extensions
.find(kEXTDrawBuffersExtension
);
9046 if (std::string::npos
!= offset
) {
9047 extensions
.replace(offset
, arraysize(kEXTDrawBuffersExtension
),
9051 if (!shader_texture_lod_explicitly_enabled_
) {
9052 size_t offset
= extensions
.find(kEXTShaderTextureLodExtension
);
9053 if (std::string::npos
!= offset
) {
9054 extensions
.replace(offset
,
9055 arraysize(kEXTShaderTextureLodExtension
),
9060 extensions
= feature_info_
->extensions().c_str();
9062 if (supports_post_sub_buffer_
)
9063 extensions
+= " GL_CHROMIUM_post_sub_buffer";
9064 str
= extensions
.c_str();
9068 str
= reinterpret_cast<const char*>(glGetString(name
));
9071 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
9072 bucket
->SetFromString(str
);
9073 return error::kNoError
;
9076 error::Error
GLES2DecoderImpl::HandleBufferData(uint32 immediate_data_size
,
9077 const void* cmd_data
) {
9078 const gles2::cmds::BufferData
& c
=
9079 *static_cast<const gles2::cmds::BufferData
*>(cmd_data
);
9080 GLenum target
= static_cast<GLenum
>(c
.target
);
9081 GLsizeiptr size
= static_cast<GLsizeiptr
>(c
.size
);
9082 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
9083 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
9084 GLenum usage
= static_cast<GLenum
>(c
.usage
);
9085 const void* data
= NULL
;
9086 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
9087 data
= GetSharedMemoryAs
<const void*>(data_shm_id
, data_shm_offset
, size
);
9089 return error::kOutOfBounds
;
9092 buffer_manager()->ValidateAndDoBufferData(&state_
, target
, size
, data
, usage
);
9093 return error::kNoError
;
9096 void GLES2DecoderImpl::DoBufferSubData(
9097 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
) {
9098 // Just delegate it. Some validation is actually done before this.
9099 buffer_manager()->ValidateAndDoBufferSubData(
9100 &state_
, target
, offset
, size
, data
);
9103 bool GLES2DecoderImpl::ClearLevel(Texture
* texture
,
9112 uint32 channels
= GLES2Util::GetChannelsForFormat(format
);
9113 if ((feature_info_
->feature_flags().angle_depth_texture
||
9114 feature_info_
->IsES3Enabled())
9115 && (channels
& GLES2Util::kDepth
) != 0) {
9116 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
9117 // on depth formats.
9119 glGenFramebuffersEXT(1, &fb
);
9120 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb
);
9122 bool have_stencil
= (channels
& GLES2Util::kStencil
) != 0;
9123 GLenum attachment
= have_stencil
? GL_DEPTH_STENCIL_ATTACHMENT
:
9124 GL_DEPTH_ATTACHMENT
;
9126 glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT
, attachment
, target
,
9127 texture
->service_id(), level
);
9128 // ANGLE promises a depth only attachment ok.
9129 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT
) !=
9130 GL_FRAMEBUFFER_COMPLETE
) {
9134 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
9135 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
9137 state_
.SetDeviceDepthMask(GL_TRUE
);
9138 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
9139 glScissor(xoffset
, yoffset
, width
, height
);
9140 glClear(GL_DEPTH_BUFFER_BIT
| (have_stencil
? GL_STENCIL_BUFFER_BIT
: 0));
9142 RestoreClearState();
9144 glDeleteFramebuffersEXT(1, &fb
);
9145 Framebuffer
* framebuffer
=
9146 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
9147 GLuint fb_service_id
=
9148 framebuffer
? framebuffer
->service_id() : GetBackbufferServiceId();
9149 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb_service_id
);
9153 static const uint32 kMaxZeroSize
= 1024 * 1024 * 4;
9156 uint32 padded_row_size
;
9157 if (!GLES2Util::ComputeImageDataSizes(
9158 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &size
,
9159 NULL
, &padded_row_size
)) {
9163 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size
);
9167 if (size
> kMaxZeroSize
) {
9168 if (kMaxZeroSize
< padded_row_size
) {
9169 // That'd be an awfully large texture.
9172 // We should never have a large total size with a zero row size.
9173 DCHECK_GT(padded_row_size
, 0U);
9174 tile_height
= kMaxZeroSize
/ padded_row_size
;
9175 if (!GLES2Util::ComputeImageDataSizes(
9176 width
, tile_height
, 1, format
, type
, state_
.unpack_alignment
, &size
,
9181 tile_height
= height
;
9184 // Assumes the size has already been checked.
9185 scoped_ptr
<char[]> zero(new char[size
]);
9186 memset(zero
.get(), 0, size
);
9187 glBindTexture(texture
->target(), texture
->service_id());
9190 while (y
< height
) {
9191 GLint h
= y
+ tile_height
> height
? height
- y
: tile_height
;
9192 glTexSubImage2D(target
, level
, xoffset
, yoffset
+ y
, width
, h
, format
, type
,
9196 TextureRef
* bound_texture
=
9197 texture_manager()->GetTextureInfoForTarget(&state_
, texture
->target());
9198 glBindTexture(texture
->target(),
9199 bound_texture
? bound_texture
->service_id() : 0);
9205 const int kS3TCBlockWidth
= 4;
9206 const int kS3TCBlockHeight
= 4;
9207 const int kS3TCDXT1BlockSize
= 8;
9208 const int kS3TCDXT3AndDXT5BlockSize
= 16;
9209 const int kEACAndETC2BlockSize
= 4;
9211 bool IsValidDXTSize(GLint level
, GLsizei size
) {
9212 return (size
== 1) ||
9213 (size
== 2) || !(size
% kS3TCBlockWidth
);
9216 bool IsValidPVRTCSize(GLint level
, GLsizei size
) {
9217 return GLES2Util::IsPOT(size
);
9220 } // anonymous namespace.
9222 bool GLES2DecoderImpl::GetCompressedTexSizeInBytes(
9223 const char* function_name
, GLsizei width
, GLsizei height
, GLsizei depth
,
9224 GLenum format
, GLsizei
* size_in_bytes
) {
9225 base::CheckedNumeric
<GLsizei
> bytes_required(0);
9228 case GL_ATC_RGB_AMD
:
9229 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
9230 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
9231 case GL_ETC1_RGB8_OES
:
9233 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
9235 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
9236 bytes_required
*= kS3TCDXT1BlockSize
;
9238 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
9239 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
9240 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
9241 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
9243 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
9245 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
9246 bytes_required
*= kS3TCDXT3AndDXT5BlockSize
;
9248 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
9249 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
9250 bytes_required
= std::max(width
, 8);
9251 bytes_required
*= std::max(height
, 8);
9252 bytes_required
*= 4;
9253 bytes_required
+= 7;
9254 bytes_required
/= 8;
9256 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
9257 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
:
9258 bytes_required
= std::max(width
, 16);
9259 bytes_required
*= std::max(height
, 8);
9260 bytes_required
*= 2;
9261 bytes_required
+= 7;
9262 bytes_required
/= 8;
9266 case GL_COMPRESSED_R11_EAC
:
9267 case GL_COMPRESSED_SIGNED_R11_EAC
:
9268 case GL_COMPRESSED_RGB8_ETC2
:
9269 case GL_COMPRESSED_SRGB8_ETC2
:
9270 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9271 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9273 (width
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9275 (height
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9276 bytes_required
*= 8;
9277 bytes_required
*= depth
;
9279 case GL_COMPRESSED_RG11_EAC
:
9280 case GL_COMPRESSED_SIGNED_RG11_EAC
:
9281 case GL_COMPRESSED_RGBA8_ETC2_EAC
:
9282 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
:
9284 (width
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9286 (height
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9287 bytes_required
*= 16;
9288 bytes_required
*= depth
;
9291 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, format
, "format");
9295 if (!bytes_required
.IsValid()) {
9296 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "invalid size");
9300 *size_in_bytes
= bytes_required
.ValueOrDefault(0);
9304 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
9305 const char* function_name
, GLsizei width
, GLsizei height
, GLsizei depth
,
9306 GLenum format
, GLsizei size
) {
9307 GLsizei bytes_required
= 0;
9308 if (!GetCompressedTexSizeInBytes(
9309 function_name
, width
, height
, depth
, format
, &bytes_required
)) {
9313 if (size
!= bytes_required
) {
9315 GL_INVALID_VALUE
, function_name
, "size is not correct for dimensions");
9322 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
9323 const char* function_name
, GLenum target
, GLint level
,
9324 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
) {
9326 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
9327 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
9328 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
9329 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
9330 DCHECK_EQ(1, depth
); // 2D formats.
9331 if (!IsValidDXTSize(level
, width
) || !IsValidDXTSize(level
, height
)) {
9333 GL_INVALID_OPERATION
, function_name
,
9334 "width or height invalid for level");
9338 case GL_ATC_RGB_AMD
:
9339 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
9340 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
9341 case GL_ETC1_RGB8_OES
:
9342 DCHECK_EQ(1, depth
); // 2D formats.
9343 if (width
<= 0 || height
<= 0) {
9345 GL_INVALID_OPERATION
, function_name
,
9346 "width or height invalid for level");
9350 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
9351 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
9352 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
9353 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
:
9354 DCHECK_EQ(1, depth
); // 2D formats.
9355 if (!IsValidPVRTCSize(level
, width
) ||
9356 !IsValidPVRTCSize(level
, height
)) {
9358 GL_INVALID_OPERATION
, function_name
,
9359 "width or height invalid for level");
9365 case GL_COMPRESSED_R11_EAC
:
9366 case GL_COMPRESSED_SIGNED_R11_EAC
:
9367 case GL_COMPRESSED_RG11_EAC
:
9368 case GL_COMPRESSED_SIGNED_RG11_EAC
:
9369 case GL_COMPRESSED_RGB8_ETC2
:
9370 case GL_COMPRESSED_SRGB8_ETC2
:
9371 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9372 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9373 case GL_COMPRESSED_RGBA8_ETC2_EAC
:
9374 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
:
9375 if (width
<= 0 || height
<= 0 || depth
<= 0) {
9377 GL_INVALID_OPERATION
, function_name
,
9378 "width, height, or depth invalid");
9381 if (target
== GL_TEXTURE_3D
) {
9383 GL_INVALID_OPERATION
, function_name
,
9384 "target invalid for format");
9393 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
9394 const char* function_name
,
9395 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
9396 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
,
9398 if (xoffset
< 0 || yoffset
< 0 || zoffset
< 0) {
9400 GL_INVALID_VALUE
, function_name
, "x/y/z offset < 0");
9405 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
9406 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
9407 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
9408 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
: {
9409 const int kBlockWidth
= 4;
9410 const int kBlockHeight
= 4;
9411 if ((xoffset
% kBlockWidth
) || (yoffset
% kBlockHeight
)) {
9413 GL_INVALID_OPERATION
, function_name
,
9414 "xoffset or yoffset not multiple of 4");
9417 GLsizei tex_width
= 0;
9418 GLsizei tex_height
= 0;
9419 if (!texture
->GetLevelSize(target
, level
,
9420 &tex_width
, &tex_height
, nullptr) ||
9421 width
- xoffset
> tex_width
||
9422 height
- yoffset
> tex_height
) {
9424 GL_INVALID_OPERATION
, function_name
, "dimensions out of range");
9427 return ValidateCompressedTexDimensions(
9428 function_name
, target
, level
, width
, height
, 1, format
);
9430 case GL_ATC_RGB_AMD
:
9431 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
9432 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
: {
9434 GL_INVALID_OPERATION
, function_name
,
9435 "not supported for ATC textures");
9438 case GL_ETC1_RGB8_OES
: {
9440 GL_INVALID_OPERATION
, function_name
,
9441 "not supported for ECT1_RGB8_OES textures");
9444 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
9445 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
9446 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
9447 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
: {
9448 if ((xoffset
!= 0) || (yoffset
!= 0)) {
9450 GL_INVALID_OPERATION
, function_name
,
9451 "xoffset and yoffset must be zero");
9454 GLsizei tex_width
= 0;
9455 GLsizei tex_height
= 0;
9456 if (!texture
->GetLevelSize(target
, level
,
9457 &tex_width
, &tex_height
, nullptr) ||
9458 width
!= tex_width
||
9459 height
!= tex_height
) {
9461 GL_INVALID_OPERATION
, function_name
,
9462 "dimensions must match existing texture level dimensions");
9465 return ValidateCompressedTexDimensions(
9466 function_name
, target
, level
, width
, height
, 1, format
);
9470 case GL_COMPRESSED_R11_EAC
:
9471 case GL_COMPRESSED_SIGNED_R11_EAC
:
9472 case GL_COMPRESSED_RG11_EAC
:
9473 case GL_COMPRESSED_SIGNED_RG11_EAC
:
9474 case GL_COMPRESSED_RGB8_ETC2
:
9475 case GL_COMPRESSED_SRGB8_ETC2
:
9476 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9477 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9478 case GL_COMPRESSED_RGBA8_ETC2_EAC
:
9479 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
:
9481 const int kBlockSize
= 4;
9482 GLsizei tex_width
, tex_height
;
9483 if (target
== GL_TEXTURE_3D
||
9484 !texture
->GetLevelSize(target
, level
,
9485 &tex_width
, &tex_height
, nullptr) ||
9486 (xoffset
% kBlockSize
) || (yoffset
% kBlockSize
) ||
9487 ((width
% kBlockSize
) && xoffset
+ width
!= tex_width
) ||
9488 ((height
% kBlockSize
) && yoffset
+ height
!= tex_height
)) {
9490 GL_INVALID_OPERATION
, function_name
,
9491 "dimensions must match existing texture level dimensions");
9501 error::Error
GLES2DecoderImpl::DoCompressedTexImage2D(
9504 GLenum internal_format
,
9510 if (!validators_
->texture_target
.IsValid(target
)) {
9511 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9512 "glCompressedTexImage2D", target
, "target");
9513 return error::kNoError
;
9515 if (!validators_
->compressed_texture_format
.IsValid(
9517 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9518 "glCompressedTexImage2D", internal_format
, "internal_format");
9519 return error::kNoError
;
9521 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
9525 "glCompressedTexImage2D", "dimensions out of range");
9526 return error::kNoError
;
9528 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9533 "glCompressedTexImage2D", "unknown texture target");
9534 return error::kNoError
;
9536 Texture
* texture
= texture_ref
->texture();
9537 if (texture
->IsImmutable()) {
9539 GL_INVALID_OPERATION
,
9540 "glCompressedTexImage2D", "texture is immutable");
9541 return error::kNoError
;
9544 if (!ValidateCompressedTexDimensions("glCompressedTexImage2D", target
, level
,
9545 width
, height
, 1, internal_format
) ||
9546 !ValidateCompressedTexFuncData("glCompressedTexImage2D", width
, height
,
9547 1, internal_format
, image_size
)) {
9548 return error::kNoError
;
9551 if (!EnsureGPUMemoryAvailable(image_size
)) {
9553 GL_OUT_OF_MEMORY
, "glCompressedTexImage2D", "out of memory");
9554 return error::kNoError
;
9557 if (texture
->IsAttachedToFramebuffer()) {
9558 framebuffer_state_
.clear_state_dirty
= true;
9561 scoped_ptr
<int8
[]> zero
;
9563 zero
.reset(new int8
[image_size
]);
9564 memset(zero
.get(), 0, image_size
);
9567 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
9568 glCompressedTexImage2D(
9569 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
9570 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
9571 if (error
== GL_NO_ERROR
) {
9572 texture_manager()->SetLevelInfo(texture_ref
, target
, level
, internal_format
,
9573 width
, height
, 1, border
, 0, 0,
9574 gfx::Rect(width
, height
));
9577 // This may be a slow command. Exit command processing to allow for
9578 // context preemption and GPU watchdog checks.
9579 ExitCommandProcessingEarly();
9580 return error::kNoError
;
9583 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2D(
9584 uint32 immediate_data_size
,
9585 const void* cmd_data
) {
9586 const gles2::cmds::CompressedTexImage2D
& c
=
9587 *static_cast<const gles2::cmds::CompressedTexImage2D
*>(cmd_data
);
9588 GLenum target
= static_cast<GLenum
>(c
.target
);
9589 GLint level
= static_cast<GLint
>(c
.level
);
9590 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9591 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9592 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9593 GLint border
= static_cast<GLint
>(c
.border
);
9594 GLsizei image_size
= static_cast<GLsizei
>(c
.imageSize
);
9595 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
9596 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
9597 const void* data
= NULL
;
9598 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
9599 data
= GetSharedMemoryAs
<const void*>(
9600 data_shm_id
, data_shm_offset
, image_size
);
9602 return error::kOutOfBounds
;
9605 return DoCompressedTexImage2D(
9606 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
9609 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
9610 uint32 immediate_data_size
,
9611 const void* cmd_data
) {
9612 const gles2::cmds::CompressedTexImage2DBucket
& c
=
9613 *static_cast<const gles2::cmds::CompressedTexImage2DBucket
*>(cmd_data
);
9614 GLenum target
= static_cast<GLenum
>(c
.target
);
9615 GLint level
= static_cast<GLint
>(c
.level
);
9616 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9617 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9618 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9619 GLint border
= static_cast<GLint
>(c
.border
);
9620 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9622 return error::kInvalidArguments
;
9624 uint32 data_size
= bucket
->size();
9625 GLsizei imageSize
= data_size
;
9626 const void* data
= bucket
->GetData(0, data_size
);
9628 return error::kInvalidArguments
;
9630 return DoCompressedTexImage2D(
9631 target
, level
, internal_format
, width
, height
, border
,
9635 error::Error
GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
9636 uint32 immediate_data_size
,
9637 const void* cmd_data
) {
9638 const gles2::cmds::CompressedTexSubImage2DBucket
& c
=
9639 *static_cast<const gles2::cmds::CompressedTexSubImage2DBucket
*>(cmd_data
);
9640 GLenum target
= static_cast<GLenum
>(c
.target
);
9641 GLint level
= static_cast<GLint
>(c
.level
);
9642 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
9643 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
9644 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9645 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9646 GLenum format
= static_cast<GLenum
>(c
.format
);
9647 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9649 return error::kInvalidArguments
;
9651 uint32 data_size
= bucket
->size();
9652 GLsizei imageSize
= data_size
;
9653 const void* data
= bucket
->GetData(0, data_size
);
9655 return error::kInvalidArguments
;
9657 if (!validators_
->texture_target
.IsValid(target
)) {
9659 GL_INVALID_ENUM
, "glCompressedTexSubImage2D", "target");
9660 return error::kNoError
;
9662 if (!validators_
->compressed_texture_format
.IsValid(format
)) {
9663 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9664 "glCompressedTexSubImage2D", format
, "format");
9665 return error::kNoError
;
9669 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "width < 0");
9670 return error::kNoError
;
9674 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "height < 0");
9675 return error::kNoError
;
9677 if (imageSize
< 0) {
9679 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "imageSize < 0");
9680 return error::kNoError
;
9682 DoCompressedTexSubImage2D(
9683 target
, level
, xoffset
, yoffset
, width
, height
, format
, imageSize
, data
);
9684 return error::kNoError
;
9687 error::Error
GLES2DecoderImpl::DoCompressedTexImage3D(
9690 GLenum internal_format
,
9697 if (!validators_
->texture_3_d_target
.IsValid(target
)) {
9698 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9699 "glCompressedTexImage3D", target
, "target");
9700 return error::kNoError
;
9702 if (!validators_
->compressed_texture_format
.IsValid(
9704 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9705 "glCompressedTexImage3D", internal_format
, "internal_format");
9706 return error::kNoError
;
9708 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, depth
) ||
9712 "glCompressedTexImage3D", "dimensions out of range");
9713 return error::kNoError
;
9715 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9720 "glCompressedTexImage3D", "unknown texture target");
9721 return error::kNoError
;
9723 Texture
* texture
= texture_ref
->texture();
9724 if (texture
->IsImmutable()) {
9726 GL_INVALID_OPERATION
,
9727 "glCompressedTexImage3D", "texture is immutable");
9728 return error::kNoError
;
9731 if (!ValidateCompressedTexDimensions("glCompressedTexImage3D", target
, level
,
9732 width
, height
, depth
, internal_format
) ||
9733 !ValidateCompressedTexFuncData("glCompressedTexImage3D", width
, height
,
9734 depth
, internal_format
, image_size
)) {
9735 return error::kNoError
;
9738 if (!EnsureGPUMemoryAvailable(image_size
)) {
9740 GL_OUT_OF_MEMORY
, "glCompressedTexImage3D", "out of memory");
9741 return error::kNoError
;
9744 if (texture
->IsAttachedToFramebuffer()) {
9745 framebuffer_state_
.clear_state_dirty
= true;
9748 scoped_ptr
<int8
[]> zero
;
9750 zero
.reset(new int8
[image_size
]);
9751 memset(zero
.get(), 0, image_size
);
9754 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage3D");
9755 glCompressedTexImage3D(target
, level
, internal_format
, width
, height
, depth
,
9756 border
, image_size
, data
);
9757 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedTexImage3D");
9758 if (error
== GL_NO_ERROR
) {
9759 texture_manager()->SetLevelInfo(texture_ref
, target
, level
, internal_format
,
9760 width
, height
, depth
, border
, 0, 0,
9761 gfx::Rect(width
, height
));
9764 // This may be a slow command. Exit command processing to allow for
9765 // context preemption and GPU watchdog checks.
9766 ExitCommandProcessingEarly();
9767 return error::kNoError
;
9770 error::Error
GLES2DecoderImpl::HandleCompressedTexImage3D(
9771 uint32 immediate_data_size
, const void* cmd_data
) {
9772 if (!unsafe_es3_apis_enabled())
9773 return error::kUnknownCommand
;
9775 const gles2::cmds::CompressedTexImage3D
& c
=
9776 *static_cast<const gles2::cmds::CompressedTexImage3D
*>(cmd_data
);
9777 GLenum target
= static_cast<GLenum
>(c
.target
);
9778 GLint level
= static_cast<GLint
>(c
.level
);
9779 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9780 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9781 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9782 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9783 GLint border
= static_cast<GLint
>(c
.border
);
9784 GLsizei image_size
= static_cast<GLsizei
>(c
.imageSize
);
9785 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
9786 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
9787 const void* data
= NULL
;
9788 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
9789 data
= GetSharedMemoryAs
<const void*>(
9790 data_shm_id
, data_shm_offset
, image_size
);
9792 return error::kOutOfBounds
;
9795 return DoCompressedTexImage3D(target
, level
, internal_format
, width
, height
,
9796 depth
, border
, image_size
, data
);
9799 error::Error
GLES2DecoderImpl::HandleCompressedTexImage3DBucket(
9800 uint32 immediate_data_size
, const void* cmd_data
) {
9801 if (!unsafe_es3_apis_enabled())
9802 return error::kUnknownCommand
;
9804 const gles2::cmds::CompressedTexImage3DBucket
& c
=
9805 *static_cast<const gles2::cmds::CompressedTexImage3DBucket
*>(cmd_data
);
9806 GLenum target
= static_cast<GLenum
>(c
.target
);
9807 GLint level
= static_cast<GLint
>(c
.level
);
9808 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9809 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9810 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9811 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9812 GLint border
= static_cast<GLint
>(c
.border
);
9813 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9815 return error::kInvalidArguments
;
9817 uint32 data_size
= bucket
->size();
9818 GLsizei imageSize
= data_size
;
9819 const void* data
= bucket
->GetData(0, data_size
);
9821 return error::kInvalidArguments
;
9823 return DoCompressedTexImage3D(target
, level
, internal_format
, width
, height
,
9824 depth
, border
, imageSize
, data
);
9827 void GLES2DecoderImpl::DoCompressedTexSubImage3D(
9828 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
9829 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
,
9830 GLsizei image_size
, const void* data
) {
9831 if (!validators_
->texture_3_d_target
.IsValid(target
)) {
9833 GL_INVALID_ENUM
, "glCompressedTexSubImage3D", "target");
9836 if (!validators_
->compressed_texture_format
.IsValid(format
)) {
9837 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9838 "glCompressedTexSubImage3D", format
, "format");
9841 if (width
< 0 || height
< 0 || depth
< 0) {
9843 GL_INVALID_VALUE
, "glCompressedTexSubImage3D", "size < 0");
9846 if (image_size
< 0) {
9848 GL_INVALID_VALUE
, "glCompressedTexSubImage3D", "imageSize < 0");
9851 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9854 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCompressedTexSubImage3D",
9855 "unknown texture for target");
9858 Texture
* texture
= texture_ref
->texture();
9859 GLenum type
= 0, internal_format
= 0;
9860 if (!texture
->GetLevelType(target
, level
, &type
, &internal_format
)) {
9861 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCompressedTexSubImage3D",
9862 "level does not exist");
9865 if (internal_format
!= format
) {
9866 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCompressedTexSubImage3D",
9867 "format does not match internal format");
9870 if (!texture
->ValidForTexture(target
, level
, xoffset
, yoffset
, zoffset
,
9871 width
, height
, depth
, type
)) {
9872 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCompressedTexSubImage3D",
9876 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage3D",
9877 width
, height
, depth
, format
,
9879 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage3D",
9880 target
, level
, xoffset
, yoffset
,
9881 zoffset
, width
, height
, depth
,
9886 // Note: There is no need to deal with texture cleared tracking here
9887 // because the validation above means you can only get here if the level
9888 // is already a matching compressed format and in that case
9889 // CompressedTexImage3D already cleared the texture.
9890 glCompressedTexSubImage3D(
9891 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
, format
,
9894 // This may be a slow command. Exit command processing to allow for
9895 // context preemption and GPU watchdog checks.
9896 ExitCommandProcessingEarly();
9899 error::Error
GLES2DecoderImpl::HandleCompressedTexSubImage3DBucket(
9900 uint32 immediate_data_size
, const void* cmd_data
) {
9901 if (!unsafe_es3_apis_enabled())
9902 return error::kUnknownCommand
;
9903 const gles2::cmds::CompressedTexSubImage3DBucket
& c
=
9904 *static_cast<const gles2::cmds::CompressedTexSubImage3DBucket
*>(cmd_data
);
9905 GLenum target
= static_cast<GLenum
>(c
.target
);
9906 GLint level
= static_cast<GLint
>(c
.level
);
9907 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
9908 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
9909 GLint zoffset
= static_cast<GLint
>(c
.zoffset
);
9910 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9911 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9912 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9913 GLenum format
= static_cast<GLenum
>(c
.format
);
9914 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9916 return error::kInvalidArguments
;
9918 uint32 data_size
= bucket
->size();
9919 GLsizei image_size
= data_size
;
9920 const void* data
= bucket
->GetData(0, data_size
);
9922 return error::kInvalidArguments
;
9924 DoCompressedTexSubImage3D(
9925 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
, format
,
9927 return error::kNoError
;
9930 error::Error
GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size
,
9931 const void* cmd_data
) {
9932 const gles2::cmds::TexImage2D
& c
=
9933 *static_cast<const gles2::cmds::TexImage2D
*>(cmd_data
);
9934 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
9935 "width", c
.width
, "height", c
.height
);
9936 // Set as failed for now, but if it successed, this will be set to not failed.
9937 texture_state_
.tex_image_failed
= true;
9938 GLenum target
= static_cast<GLenum
>(c
.target
);
9939 GLint level
= static_cast<GLint
>(c
.level
);
9940 // TODO(kloveless): Change TexImage2D command to use unsigned integer
9941 // for internalformat.
9942 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9943 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9944 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9945 GLint border
= static_cast<GLint
>(c
.border
);
9946 GLenum format
= static_cast<GLenum
>(c
.format
);
9947 GLenum type
= static_cast<GLenum
>(c
.type
);
9948 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
9949 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
9951 if (!GLES2Util::ComputeImageDataSizes(
9952 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
9954 return error::kOutOfBounds
;
9956 const void* pixels
= NULL
;
9957 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
9958 pixels
= GetSharedMemoryAs
<const void*>(
9959 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
9961 return error::kOutOfBounds
;
9965 // For testing only. Allows us to stress the ability to respond to OOM errors.
9966 if (workarounds().simulate_out_of_memory_on_large_textures
&&
9967 (width
* height
>= 4096 * 4096)) {
9970 "glTexImage2D", "synthetic out of memory");
9971 return error::kNoError
;
9974 TextureManager::DoTexImageArguments args
= {
9975 target
, level
, internal_format
, width
, height
, 1, border
, format
, type
,
9976 pixels
, pixels_size
, TextureManager::DoTexImageArguments::kTexImage2D
};
9977 texture_manager()->ValidateAndDoTexImage(
9978 &texture_state_
, &state_
, &framebuffer_state_
, "glTexImage2D", args
);
9980 // This may be a slow command. Exit command processing to allow for
9981 // context preemption and GPU watchdog checks.
9982 ExitCommandProcessingEarly();
9983 return error::kNoError
;
9986 error::Error
GLES2DecoderImpl::HandleTexImage3D(uint32 immediate_data_size
,
9987 const void* cmd_data
) {
9988 if (!unsafe_es3_apis_enabled())
9989 return error::kUnknownCommand
;
9991 const gles2::cmds::TexImage3D
& c
=
9992 *static_cast<const gles2::cmds::TexImage3D
*>(cmd_data
);
9993 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage3D",
9994 "widthXheight", c
.width
* c
.height
, "depth", c
.depth
);
9995 // Set as failed for now, but if it successed, this will be set to not failed.
9996 texture_state_
.tex_image_failed
= true;
9997 GLenum target
= static_cast<GLenum
>(c
.target
);
9998 GLint level
= static_cast<GLint
>(c
.level
);
9999 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
10000 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10001 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10002 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
10003 GLint border
= static_cast<GLint
>(c
.border
);
10004 GLenum format
= static_cast<GLenum
>(c
.format
);
10005 GLenum type
= static_cast<GLenum
>(c
.type
);
10006 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
10007 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
10008 uint32 pixels_size
;
10009 if (!GLES2Util::ComputeImageDataSizes(
10010 width
, height
, depth
, format
, type
, state_
.unpack_alignment
, &pixels_size
,
10012 return error::kOutOfBounds
;
10014 const void* pixels
= NULL
;
10015 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
10016 pixels
= GetSharedMemoryAs
<const void*>(
10017 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
10019 return error::kOutOfBounds
;
10023 // For testing only. Allows us to stress the ability to respond to OOM errors.
10024 if (workarounds().simulate_out_of_memory_on_large_textures
&&
10025 (width
* height
* depth
>= 4096 * 4096)) {
10026 LOCAL_SET_GL_ERROR(
10028 "glTexImage3D", "synthetic out of memory");
10029 return error::kNoError
;
10032 TextureManager::DoTexImageArguments args
= {
10033 target
, level
, internal_format
, width
, height
, depth
, border
, format
, type
,
10034 pixels
, pixels_size
, TextureManager::DoTexImageArguments::kTexImage3D
};
10035 texture_manager()->ValidateAndDoTexImage(
10036 &texture_state_
, &state_
, &framebuffer_state_
, "glTexImage3D", args
);
10038 // This may be a slow command. Exit command processing to allow for
10039 // context preemption and GPU watchdog checks.
10040 ExitCommandProcessingEarly();
10041 return error::kNoError
;
10044 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
10052 GLsizei image_size
,
10053 const void * data
) {
10054 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10056 if (!texture_ref
) {
10057 LOCAL_SET_GL_ERROR(
10058 GL_INVALID_OPERATION
,
10059 "glCompressedTexSubImage2D", "unknown texture for target");
10062 Texture
* texture
= texture_ref
->texture();
10064 GLenum internal_format
= 0;
10065 if (!texture
->GetLevelType(target
, level
, &type
, &internal_format
)) {
10066 LOCAL_SET_GL_ERROR(
10067 GL_INVALID_OPERATION
,
10068 "glCompressedTexSubImage2D", "level does not exist.");
10071 if (internal_format
!= format
) {
10072 LOCAL_SET_GL_ERROR(
10073 GL_INVALID_OPERATION
,
10074 "glCompressedTexSubImage2D", "format does not match internal format.");
10077 if (!texture
->ValidForTexture(target
, level
, xoffset
, yoffset
, 0, width
,
10078 height
, 1, type
)) {
10079 LOCAL_SET_GL_ERROR(
10080 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "bad dimensions.");
10084 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage2D",
10085 width
, height
, 1, format
, image_size
) ||
10086 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage2D",
10087 target
, level
, xoffset
, yoffset
, 0,
10088 width
, height
, 1, format
, texture
)) {
10093 // Note: There is no need to deal with texture cleared tracking here
10094 // because the validation above means you can only get here if the level
10095 // is already a matching compressed format and in that case
10096 // CompressedTexImage2D already cleared the texture.
10097 glCompressedTexSubImage2D(
10098 target
, level
, xoffset
, yoffset
, width
, height
, format
, image_size
, data
);
10100 // This may be a slow command. Exit command processing to allow for
10101 // context preemption and GPU watchdog checks.
10102 ExitCommandProcessingEarly();
10106 GLint start
, GLint range
, GLint sourceRange
,
10107 GLint
* out_start
, GLint
* out_range
) {
10114 GLint end
= start
+ range
;
10115 if (end
> sourceRange
) {
10116 range
-= end
- sourceRange
;
10118 *out_start
= start
;
10119 *out_range
= range
;
10122 void GLES2DecoderImpl::DoCopyTexImage2D(
10125 GLenum internal_format
,
10131 DCHECK(!ShouldDeferReads());
10132 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10134 if (!texture_ref
) {
10135 LOCAL_SET_GL_ERROR(
10136 GL_INVALID_OPERATION
,
10137 "glCopyTexImage2D", "unknown texture for target");
10140 Texture
* texture
= texture_ref
->texture();
10141 if (texture
->IsImmutable()) {
10142 LOCAL_SET_GL_ERROR(
10143 GL_INVALID_OPERATION
, "glCopyTexImage2D", "texture is immutable");
10146 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
10148 LOCAL_SET_GL_ERROR(
10149 GL_INVALID_VALUE
, "glCopyTexImage2D", "dimensions out of range");
10152 if (!texture_manager()->ValidateFormatAndTypeCombination(
10153 state_
.GetErrorState(), "glCopyTexImage2D", internal_format
,
10154 GL_UNSIGNED_BYTE
)) {
10158 // Check we have compatible formats.
10159 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
10160 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
10161 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(internal_format
);
10163 if ((channels_needed
& channels_exist
) != channels_needed
) {
10164 LOCAL_SET_GL_ERROR(
10165 GL_INVALID_OPERATION
, "glCopyTexImage2D", "incompatible format");
10169 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
10170 LOCAL_SET_GL_ERROR(
10171 GL_INVALID_OPERATION
,
10172 "glCopyTexImage2D", "can not be used with depth or stencil textures");
10176 uint32 estimated_size
= 0;
10177 if (!GLES2Util::ComputeImageDataSizes(
10178 width
, height
, 1, internal_format
, GL_UNSIGNED_BYTE
,
10179 state_
.unpack_alignment
, &estimated_size
, NULL
, NULL
)) {
10180 LOCAL_SET_GL_ERROR(
10181 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too large");
10185 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
10186 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "out of memory");
10190 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexImage2D")) {
10194 if (FormsTextureCopyingFeedbackLoop(texture_ref
, level
)) {
10195 LOCAL_SET_GL_ERROR(
10196 GL_INVALID_OPERATION
,
10197 "glCopyTexImage2D", "source and destination textures are the same");
10201 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
10205 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
10206 ScopedResolvedFrameBufferBinder
binder(this, false, true);
10207 gfx::Size size
= GetBoundReadFrameBufferSize();
10209 if (texture
->IsAttachedToFramebuffer()) {
10210 framebuffer_state_
.clear_state_dirty
= true;
10213 // Clip to size to source dimensions
10216 GLint copyWidth
= 0;
10217 GLint copyHeight
= 0;
10218 Clip(x
, width
, size
.width(), ©X
, ©Width
);
10219 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
10223 copyWidth
!= width
||
10224 copyHeight
!= height
) {
10225 // some part was clipped so clear the rect.
10226 uint32 pixels_size
= 0;
10227 if (!GLES2Util::ComputeImageDataSizes(
10228 width
, height
, 1, internal_format
, GL_UNSIGNED_BYTE
,
10229 state_
.unpack_alignment
, &pixels_size
, NULL
, NULL
)) {
10230 LOCAL_SET_GL_ERROR(
10231 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too big");
10234 scoped_ptr
<char[]> zero(new char[pixels_size
]);
10235 memset(zero
.get(), 0, pixels_size
);
10236 ScopedModifyPixels
modify(texture_ref
);
10237 glTexImage2D(target
, level
, internal_format
, width
, height
, border
,
10238 internal_format
, GL_UNSIGNED_BYTE
, zero
.get());
10239 if (copyHeight
> 0 && copyWidth
> 0) {
10240 GLint dx
= copyX
- x
;
10241 GLint dy
= copyY
- y
;
10244 glCopyTexSubImage2D(target
, level
,
10245 destX
, destY
, copyX
, copyY
,
10246 copyWidth
, copyHeight
);
10249 ScopedModifyPixels
modify(texture_ref
);
10250 glCopyTexImage2D(target
, level
, internal_format
,
10251 copyX
, copyY
, copyWidth
, copyHeight
, border
);
10253 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
10254 if (error
== GL_NO_ERROR
) {
10255 texture_manager()->SetLevelInfo(texture_ref
, target
, level
, internal_format
,
10256 width
, height
, 1, border
, internal_format
,
10257 GL_UNSIGNED_BYTE
, gfx::Rect(width
, height
));
10260 // This may be a slow command. Exit command processing to allow for
10261 // context preemption and GPU watchdog checks.
10262 ExitCommandProcessingEarly();
10265 void GLES2DecoderImpl::DoCopyTexSubImage2D(
10274 DCHECK(!ShouldDeferReads());
10275 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10277 if (!texture_ref
) {
10278 LOCAL_SET_GL_ERROR(
10279 GL_INVALID_OPERATION
,
10280 "glCopyTexSubImage2D", "unknown texture for target");
10283 Texture
* texture
= texture_ref
->texture();
10286 if (!texture
->GetLevelType(target
, level
, &type
, &format
) ||
10287 !texture
->ValidForTexture(
10288 target
, level
, xoffset
, yoffset
, 0, width
, height
, 1, type
)) {
10289 LOCAL_SET_GL_ERROR(
10290 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "bad dimensions.");
10293 if (async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
10294 LOCAL_SET_GL_ERROR(
10295 GL_INVALID_OPERATION
,
10296 "glCopyTexSubImage2D", "async upload pending for texture");
10300 // Check we have compatible formats.
10301 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
10302 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
10303 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(format
);
10305 if (!channels_needed
||
10306 (channels_needed
& channels_exist
) != channels_needed
) {
10307 LOCAL_SET_GL_ERROR(
10308 GL_INVALID_OPERATION
, "glCopyTexSubImage2D", "incompatible format");
10312 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
10313 LOCAL_SET_GL_ERROR(
10314 GL_INVALID_OPERATION
,
10315 "glCopySubImage2D", "can not be used with depth or stencil textures");
10319 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexSubImage2D")) {
10323 if (FormsTextureCopyingFeedbackLoop(texture_ref
, level
)) {
10324 LOCAL_SET_GL_ERROR(
10325 GL_INVALID_OPERATION
,
10326 "glCopyTexSubImage2D", "source and destination textures are the same");
10330 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
10334 ScopedResolvedFrameBufferBinder
binder(this, false, true);
10335 gfx::Size size
= GetBoundReadFrameBufferSize();
10338 GLint copyWidth
= 0;
10339 GLint copyHeight
= 0;
10340 Clip(x
, width
, size
.width(), ©X
, ©Width
);
10341 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
10343 if (xoffset
!= 0 || yoffset
!= 0 || width
!= size
.width() ||
10344 height
!= size
.height()) {
10345 gfx::Rect cleared_rect
;
10346 if (CombineAdjacentRects(texture
->GetLevelClearedRect(target
, level
),
10347 gfx::Rect(xoffset
, yoffset
, width
, height
),
10349 DCHECK_GE(cleared_rect
.size().GetArea(),
10350 texture
->GetLevelClearedRect(target
, level
).size().GetArea());
10351 texture_manager()->SetLevelClearedRect(texture_ref
, target
, level
,
10354 // Otherwise clear part of texture level that is not already cleared.
10355 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
,
10357 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D",
10358 "dimensions too big");
10363 // Write all pixels in below.
10364 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
10369 copyWidth
!= width
||
10370 copyHeight
!= height
) {
10371 // some part was clipped so clear the sub rect.
10372 uint32 pixels_size
= 0;
10373 if (!GLES2Util::ComputeImageDataSizes(
10374 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
10376 LOCAL_SET_GL_ERROR(
10377 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "dimensions too large");
10380 scoped_ptr
<char[]> zero(new char[pixels_size
]);
10381 memset(zero
.get(), 0, pixels_size
);
10382 ScopedModifyPixels
modify(texture_ref
);
10384 target
, level
, xoffset
, yoffset
, width
, height
,
10385 format
, type
, zero
.get());
10388 if (copyHeight
> 0 && copyWidth
> 0) {
10389 GLint dx
= copyX
- x
;
10390 GLint dy
= copyY
- y
;
10391 GLint destX
= xoffset
+ dx
;
10392 GLint destY
= yoffset
+ dy
;
10393 ScopedModifyPixels
modify(texture_ref
);
10394 glCopyTexSubImage2D(target
, level
,
10395 destX
, destY
, copyX
, copyY
,
10396 copyWidth
, copyHeight
);
10399 // This may be a slow command. Exit command processing to allow for
10400 // context preemption and GPU watchdog checks.
10401 ExitCommandProcessingEarly();
10404 bool GLES2DecoderImpl::ValidateTexSubImage2D(
10405 error::Error
* error
,
10406 const char* function_name
,
10415 const void * data
) {
10416 (*error
) = error::kNoError
;
10417 if (!validators_
->texture_target
.IsValid(target
)) {
10418 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
10422 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "width < 0");
10426 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "height < 0");
10429 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10431 if (!texture_ref
) {
10432 LOCAL_SET_GL_ERROR(
10433 GL_INVALID_OPERATION
,
10434 function_name
, "unknown texture for target");
10437 Texture
* texture
= texture_ref
->texture();
10438 GLenum current_type
= 0;
10439 GLenum internal_format
= 0;
10440 if (!texture
->GetLevelType(target
, level
, ¤t_type
, &internal_format
)) {
10441 LOCAL_SET_GL_ERROR(
10442 GL_INVALID_OPERATION
, function_name
, "level does not exist.");
10445 if (!texture_manager()->ValidateTextureParameters(state_
.GetErrorState(),
10446 function_name
, format
, type
, internal_format
, level
)) {
10449 if (type
!= current_type
) {
10450 LOCAL_SET_GL_ERROR(
10451 GL_INVALID_OPERATION
,
10452 function_name
, "type does not match type of texture.");
10455 if (async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
10456 LOCAL_SET_GL_ERROR(
10457 GL_INVALID_OPERATION
,
10458 function_name
, "async upload pending for texture");
10461 if (!texture
->ValidForTexture(
10462 target
, level
, xoffset
, yoffset
, 0, width
, height
, 1, type
)) {
10463 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "bad dimensions.");
10466 if ((GLES2Util::GetChannelsForFormat(format
) &
10467 (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0
10468 && !feature_info_
->IsES3Enabled()) {
10469 LOCAL_SET_GL_ERROR(
10470 GL_INVALID_OPERATION
,
10471 function_name
, "can not supply data for depth or stencil textures");
10474 if (data
== NULL
) {
10475 (*error
) = error::kOutOfBounds
;
10481 error::Error
GLES2DecoderImpl::DoTexSubImage2D(
10490 const void * data
) {
10491 error::Error error
= error::kNoError
;
10492 if (!ValidateTexSubImage2D(&error
, "glTexSubImage2D", target
, level
,
10493 xoffset
, yoffset
, width
, height
, format
, type
, data
)) {
10496 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10498 Texture
* texture
= texture_ref
->texture();
10499 GLsizei tex_width
= 0;
10500 GLsizei tex_height
= 0;
10501 bool ok
= texture
->GetLevelSize(
10502 target
, level
, &tex_width
, &tex_height
, nullptr);
10504 if (xoffset
!= 0 || yoffset
!= 0 ||
10505 width
!= tex_width
|| height
!= tex_height
) {
10506 gfx::Rect cleared_rect
;
10507 if (CombineAdjacentRects(texture
->GetLevelClearedRect(target
, level
),
10508 gfx::Rect(xoffset
, yoffset
, width
, height
),
10510 DCHECK_GE(cleared_rect
.size().GetArea(),
10511 texture
->GetLevelClearedRect(target
, level
).size().GetArea());
10512 texture_manager()->SetLevelClearedRect(texture_ref
, target
, level
,
10515 // Otherwise clear part of texture level that is not already cleared.
10516 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
,
10518 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glTexSubImage2D",
10519 "dimensions too big");
10520 return error::kNoError
;
10523 ScopedTextureUploadTimer
timer(&texture_state_
);
10525 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
10526 return error::kNoError
;
10529 if (!texture_state_
.texsubimage_faster_than_teximage
&&
10530 !texture
->IsImmutable() &&
10531 !texture
->HasImages()) {
10532 ScopedTextureUploadTimer
timer(&texture_state_
);
10533 GLenum internal_format
;
10535 texture
->GetLevelType(target
, level
, &tex_type
, &internal_format
);
10536 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
10539 target
, level
, internal_format
, width
, height
, 0, format
, type
, data
);
10541 ScopedTextureUploadTimer
timer(&texture_state_
);
10543 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
10545 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
10547 // This may be a slow command. Exit command processing to allow for
10548 // context preemption and GPU watchdog checks.
10549 ExitCommandProcessingEarly();
10550 return error::kNoError
;
10553 error::Error
GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size
,
10554 const void* cmd_data
) {
10555 const gles2::cmds::TexSubImage2D
& c
=
10556 *static_cast<const gles2::cmds::TexSubImage2D
*>(cmd_data
);
10557 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
10558 "width", c
.width
, "height", c
.height
);
10559 GLboolean internal
= static_cast<GLboolean
>(c
.internal
);
10560 if (internal
== GL_TRUE
&& texture_state_
.tex_image_failed
)
10561 return error::kNoError
;
10563 GLenum target
= static_cast<GLenum
>(c
.target
);
10564 GLint level
= static_cast<GLint
>(c
.level
);
10565 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
10566 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
10567 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10568 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10569 GLenum format
= static_cast<GLenum
>(c
.format
);
10570 GLenum type
= static_cast<GLenum
>(c
.type
);
10572 if (!GLES2Util::ComputeImageDataSizes(
10573 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &data_size
,
10575 return error::kOutOfBounds
;
10577 const void* pixels
= GetSharedMemoryAs
<const void*>(
10578 c
.pixels_shm_id
, c
.pixels_shm_offset
, data_size
);
10579 return DoTexSubImage2D(
10580 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
);
10583 error::Error
GLES2DecoderImpl::DoTexSubImage3D(
10594 const void * data
) {
10595 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10597 if (!texture_ref
) {
10598 LOCAL_SET_GL_ERROR(
10599 GL_INVALID_ENUM
, "glTexSubImage3D", "invalid target");
10602 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexSubImage3D");
10603 ScopedTextureUploadTimer
timer(&texture_state_
);
10604 glTexSubImage3D(target
, level
, xoffset
, yoffset
, zoffset
, width
, height
,
10605 depth
, format
, type
, data
);
10606 GLenum error
= LOCAL_PEEK_GL_ERROR("glTexSubImage3D");
10607 if (error
== GL_NO_ERROR
) {
10608 // TODO(zmo): This is not 100% correct because only part of the level
10609 // image is cleared.
10610 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
10613 // This may be a slow command. Exit command processing to allow for
10614 // context preemption and GPU watchdog checks.
10615 ExitCommandProcessingEarly();
10616 return error::kNoError
;
10619 error::Error
GLES2DecoderImpl::HandleTexSubImage3D(uint32 immediate_data_size
,
10620 const void* cmd_data
) {
10621 if (!unsafe_es3_apis_enabled())
10622 return error::kUnknownCommand
;
10624 const gles2::cmds::TexSubImage3D
& c
=
10625 *static_cast<const gles2::cmds::TexSubImage3D
*>(cmd_data
);
10626 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage3D",
10627 "widthXheight", c
.width
* c
.height
, "depth", c
.depth
);
10628 GLboolean internal
= static_cast<GLboolean
>(c
.internal
);
10629 if (internal
== GL_TRUE
&& texture_state_
.tex_image_failed
)
10630 return error::kNoError
;
10632 GLenum target
= static_cast<GLenum
>(c
.target
);
10633 GLint level
= static_cast<GLint
>(c
.level
);
10634 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
10635 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
10636 GLint zoffset
= static_cast<GLint
>(c
.zoffset
);
10637 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10638 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10639 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
10640 GLenum format
= static_cast<GLenum
>(c
.format
);
10641 GLenum type
= static_cast<GLenum
>(c
.type
);
10643 if (!GLES2Util::ComputeImageDataSizes(
10644 width
, height
, depth
, format
, type
, state_
.unpack_alignment
, &data_size
,
10646 return error::kOutOfBounds
;
10648 const void* pixels
= GetSharedMemoryAs
<const void*>(
10649 c
.pixels_shm_id
, c
.pixels_shm_offset
, data_size
);
10650 return DoTexSubImage3D(target
, level
, xoffset
, yoffset
, zoffset
, width
,
10651 height
, depth
, format
, type
, pixels
);
10654 error::Error
GLES2DecoderImpl::HandleGetVertexAttribPointerv(
10655 uint32 immediate_data_size
,
10656 const void* cmd_data
) {
10657 const gles2::cmds::GetVertexAttribPointerv
& c
=
10658 *static_cast<const gles2::cmds::GetVertexAttribPointerv
*>(cmd_data
);
10659 GLuint index
= static_cast<GLuint
>(c
.index
);
10660 GLenum pname
= static_cast<GLenum
>(c
.pname
);
10661 typedef cmds::GetVertexAttribPointerv::Result Result
;
10662 Result
* result
= GetSharedMemoryAs
<Result
*>(
10663 c
.pointer_shm_id
, c
.pointer_shm_offset
, Result::ComputeSize(1));
10665 return error::kOutOfBounds
;
10667 // Check that the client initialized the result.
10668 if (result
->size
!= 0) {
10669 return error::kInvalidArguments
;
10671 if (!validators_
->vertex_pointer
.IsValid(pname
)) {
10672 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10673 "glGetVertexAttribPointerv", pname
, "pname");
10674 return error::kNoError
;
10676 if (index
>= group_
->max_vertex_attribs()) {
10677 LOCAL_SET_GL_ERROR(
10678 GL_INVALID_VALUE
, "glGetVertexAttribPointerv", "index out of range.");
10679 return error::kNoError
;
10681 result
->SetNumResults(1);
10682 *result
->GetData() =
10683 state_
.vertex_attrib_manager
->GetVertexAttrib(index
)->offset();
10684 return error::kNoError
;
10688 bool GLES2DecoderImpl::GetUniformSetup(GLuint program_id
,
10689 GLint fake_location
,
10692 error::Error
* error
,
10693 GLint
* real_location
,
10694 GLuint
* service_id
,
10695 SizedResult
<T
>** result_pointer
,
10696 GLenum
* result_type
,
10697 GLsizei
* result_size
) {
10699 DCHECK(service_id
);
10700 DCHECK(result_pointer
);
10701 DCHECK(result_type
);
10702 DCHECK(result_size
);
10703 DCHECK(real_location
);
10704 *error
= error::kNoError
;
10705 // Make sure we have enough room for the result on failure.
10706 SizedResult
<T
>* result
;
10707 result
= GetSharedMemoryAs
<SizedResult
<T
>*>(
10708 shm_id
, shm_offset
, SizedResult
<T
>::ComputeSize(0));
10710 *error
= error::kOutOfBounds
;
10713 *result_pointer
= result
;
10714 // Set the result size to 0 so the client does not have to check for success.
10715 result
->SetNumResults(0);
10716 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetUniform");
10720 if (!program
->IsValid()) {
10721 // Program was not linked successfully. (ie, glLinkProgram)
10722 LOCAL_SET_GL_ERROR(
10723 GL_INVALID_OPERATION
, "glGetUniform", "program not linked");
10726 *service_id
= program
->service_id();
10727 GLint array_index
= -1;
10728 const Program::UniformInfo
* uniform_info
=
10729 program
->GetUniformInfoByFakeLocation(
10730 fake_location
, real_location
, &array_index
);
10731 if (!uniform_info
) {
10732 // No such location.
10733 LOCAL_SET_GL_ERROR(
10734 GL_INVALID_OPERATION
, "glGetUniform", "unknown location");
10737 GLenum type
= uniform_info
->type
;
10738 uint32 num_elements
= GLES2Util::GetElementCountForUniformType(type
);
10739 if (num_elements
== 0) {
10740 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glGetUniform", "unknown type");
10743 result
= GetSharedMemoryAs
<SizedResult
<T
>*>(
10744 shm_id
, shm_offset
, SizedResult
<T
>::ComputeSize(num_elements
));
10746 *error
= error::kOutOfBounds
;
10749 result
->SetNumResults(num_elements
);
10750 *result_size
= num_elements
* sizeof(T
);
10751 *result_type
= type
;
10755 error::Error
GLES2DecoderImpl::HandleGetUniformiv(uint32 immediate_data_size
,
10756 const void* cmd_data
) {
10757 const gles2::cmds::GetUniformiv
& c
=
10758 *static_cast<const gles2::cmds::GetUniformiv
*>(cmd_data
);
10759 GLuint program
= c
.program
;
10760 GLint fake_location
= c
.location
;
10762 GLenum result_type
;
10763 GLsizei result_size
;
10764 GLint real_location
= -1;
10766 cmds::GetUniformiv::Result
* result
;
10767 if (GetUniformSetup
<GLint
>(program
, fake_location
, c
.params_shm_id
,
10768 c
.params_shm_offset
, &error
, &real_location
,
10769 &service_id
, &result
, &result_type
,
10772 service_id
, real_location
, result
->GetData());
10777 error::Error
GLES2DecoderImpl::HandleGetUniformuiv(uint32 immediate_data_size
,
10778 const void* cmd_data
) {
10779 if (!unsafe_es3_apis_enabled())
10780 return error::kUnknownCommand
;
10782 const gles2::cmds::GetUniformuiv
& c
=
10783 *static_cast<const gles2::cmds::GetUniformuiv
*>(cmd_data
);
10784 GLuint program
= c
.program
;
10785 GLint fake_location
= c
.location
;
10787 GLenum result_type
;
10788 GLsizei result_size
;
10789 GLint real_location
= -1;
10791 cmds::GetUniformuiv::Result
* result
;
10792 if (GetUniformSetup
<GLuint
>(program
, fake_location
, c
.params_shm_id
,
10793 c
.params_shm_offset
, &error
, &real_location
,
10794 &service_id
, &result
, &result_type
,
10797 service_id
, real_location
, result
->GetData());
10802 error::Error
GLES2DecoderImpl::HandleGetUniformfv(uint32 immediate_data_size
,
10803 const void* cmd_data
) {
10804 const gles2::cmds::GetUniformfv
& c
=
10805 *static_cast<const gles2::cmds::GetUniformfv
*>(cmd_data
);
10806 GLuint program
= c
.program
;
10807 GLint fake_location
= c
.location
;
10809 GLint real_location
= -1;
10811 cmds::GetUniformfv::Result
* result
;
10812 GLenum result_type
;
10813 GLsizei result_size
;
10814 if (GetUniformSetup
<GLfloat
>(program
, fake_location
, c
.params_shm_id
,
10815 c
.params_shm_offset
, &error
, &real_location
,
10816 &service_id
, &result
, &result_type
,
10818 if (result_type
== GL_BOOL
|| result_type
== GL_BOOL_VEC2
||
10819 result_type
== GL_BOOL_VEC3
|| result_type
== GL_BOOL_VEC4
) {
10820 GLsizei num_values
= result_size
/ sizeof(GLfloat
);
10821 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
10822 glGetUniformiv(service_id
, real_location
, temp
.get());
10823 GLfloat
* dst
= result
->GetData();
10824 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
10825 dst
[ii
] = (temp
[ii
] != 0);
10828 glGetUniformfv(service_id
, real_location
, result
->GetData());
10834 error::Error
GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
10835 uint32 immediate_data_size
,
10836 const void* cmd_data
) {
10837 const gles2::cmds::GetShaderPrecisionFormat
& c
=
10838 *static_cast<const gles2::cmds::GetShaderPrecisionFormat
*>(cmd_data
);
10839 GLenum shader_type
= static_cast<GLenum
>(c
.shadertype
);
10840 GLenum precision_type
= static_cast<GLenum
>(c
.precisiontype
);
10841 typedef cmds::GetShaderPrecisionFormat::Result Result
;
10842 Result
* result
= GetSharedMemoryAs
<Result
*>(
10843 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10845 return error::kOutOfBounds
;
10847 // Check that the client initialized the result.
10848 if (result
->success
!= 0) {
10849 return error::kInvalidArguments
;
10851 if (!validators_
->shader_type
.IsValid(shader_type
)) {
10852 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10853 "glGetShaderPrecisionFormat", shader_type
, "shader_type");
10854 return error::kNoError
;
10856 if (!validators_
->shader_precision
.IsValid(precision_type
)) {
10857 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10858 "glGetShaderPrecisionFormat", precision_type
, "precision_type");
10859 return error::kNoError
;
10862 result
->success
= 1; // true
10864 GLint range
[2] = { 0, 0 };
10865 GLint precision
= 0;
10866 GetShaderPrecisionFormatImpl(shader_type
, precision_type
, range
, &precision
);
10868 result
->min_range
= range
[0];
10869 result
->max_range
= range
[1];
10870 result
->precision
= precision
;
10872 return error::kNoError
;
10875 error::Error
GLES2DecoderImpl::HandleGetAttachedShaders(
10876 uint32 immediate_data_size
,
10877 const void* cmd_data
) {
10878 const gles2::cmds::GetAttachedShaders
& c
=
10879 *static_cast<const gles2::cmds::GetAttachedShaders
*>(cmd_data
);
10880 uint32 result_size
= c
.result_size
;
10881 GLuint program_id
= static_cast<GLuint
>(c
.program
);
10882 Program
* program
= GetProgramInfoNotShader(
10883 program_id
, "glGetAttachedShaders");
10885 return error::kNoError
;
10887 typedef cmds::GetAttachedShaders::Result Result
;
10888 uint32 max_count
= Result::ComputeMaxResults(result_size
);
10889 Result
* result
= GetSharedMemoryAs
<Result
*>(
10890 c
.result_shm_id
, c
.result_shm_offset
, Result::ComputeSize(max_count
));
10892 return error::kOutOfBounds
;
10894 // Check that the client initialized the result.
10895 if (result
->size
!= 0) {
10896 return error::kInvalidArguments
;
10899 glGetAttachedShaders(
10900 program
->service_id(), max_count
, &count
, result
->GetData());
10901 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
10902 if (!shader_manager()->GetClientId(result
->GetData()[ii
],
10903 &result
->GetData()[ii
])) {
10905 return error::kGenericError
;
10908 result
->SetNumResults(count
);
10909 return error::kNoError
;
10912 error::Error
GLES2DecoderImpl::HandleGetActiveUniform(
10913 uint32 immediate_data_size
,
10914 const void* cmd_data
) {
10915 const gles2::cmds::GetActiveUniform
& c
=
10916 *static_cast<const gles2::cmds::GetActiveUniform
*>(cmd_data
);
10917 GLuint program_id
= c
.program
;
10918 GLuint index
= c
.index
;
10919 uint32 name_bucket_id
= c
.name_bucket_id
;
10920 typedef cmds::GetActiveUniform::Result Result
;
10921 Result
* result
= GetSharedMemoryAs
<Result
*>(
10922 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10924 return error::kOutOfBounds
;
10926 // Check that the client initialized the result.
10927 if (result
->success
!= 0) {
10928 return error::kInvalidArguments
;
10930 Program
* program
= GetProgramInfoNotShader(
10931 program_id
, "glGetActiveUniform");
10933 return error::kNoError
;
10935 const Program::UniformInfo
* uniform_info
=
10936 program
->GetUniformInfo(index
);
10937 if (!uniform_info
) {
10938 LOCAL_SET_GL_ERROR(
10939 GL_INVALID_VALUE
, "glGetActiveUniform", "index out of range");
10940 return error::kNoError
;
10942 result
->success
= 1; // true.
10943 result
->size
= uniform_info
->size
;
10944 result
->type
= uniform_info
->type
;
10945 Bucket
* bucket
= CreateBucket(name_bucket_id
);
10946 bucket
->SetFromString(uniform_info
->name
.c_str());
10947 return error::kNoError
;
10950 error::Error
GLES2DecoderImpl::HandleGetActiveUniformBlockiv(
10951 uint32 immediate_data_size
, const void* cmd_data
) {
10952 if (!unsafe_es3_apis_enabled())
10953 return error::kUnknownCommand
;
10954 const gles2::cmds::GetActiveUniformBlockiv
& c
=
10955 *static_cast<const gles2::cmds::GetActiveUniformBlockiv
*>(cmd_data
);
10956 GLuint program_id
= c
.program
;
10957 GLuint index
= static_cast<GLuint
>(c
.index
);
10958 GLenum pname
= static_cast<GLenum
>(c
.pname
);
10959 Program
* program
= GetProgramInfoNotShader(
10960 program_id
, "glGetActiveUniformBlockiv");
10962 return error::kNoError
;
10964 GLuint service_id
= program
->service_id();
10965 GLint link_status
= GL_FALSE
;
10966 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
10967 if (link_status
!= GL_TRUE
) {
10968 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10969 "glGetActiveActiveUniformBlockiv", "program not linked");
10970 return error::kNoError
;
10972 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformBlockiv");
10973 GLsizei num_values
= 1;
10974 if (pname
== GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES
) {
10976 glGetActiveUniformBlockiv(
10977 service_id
, index
, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS
, &num
);
10978 GLenum error
= glGetError();
10979 if (error
!= GL_NO_ERROR
) {
10980 // Assume this will the same error if calling with pname.
10981 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformBlockiv", "");
10982 return error::kNoError
;
10984 num_values
= static_cast<GLsizei
>(num
);
10986 typedef cmds::GetActiveUniformBlockiv::Result Result
;
10987 Result
* result
= GetSharedMemoryAs
<Result
*>(
10988 c
.params_shm_id
, c
.params_shm_offset
, Result::ComputeSize(num_values
));
10989 GLint
* params
= result
? result
->GetData() : NULL
;
10990 if (params
== NULL
) {
10991 return error::kOutOfBounds
;
10993 // Check that the client initialized the result.
10994 if (result
->size
!= 0) {
10995 return error::kInvalidArguments
;
10997 glGetActiveUniformBlockiv(service_id
, index
, pname
, params
);
10998 GLenum error
= glGetError();
10999 if (error
== GL_NO_ERROR
) {
11000 result
->SetNumResults(num_values
);
11002 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformBlockiv", "");
11004 return error::kNoError
;
11007 error::Error
GLES2DecoderImpl::HandleGetActiveUniformBlockName(
11008 uint32 immediate_data_size
, const void* cmd_data
) {
11009 if (!unsafe_es3_apis_enabled())
11010 return error::kUnknownCommand
;
11011 const gles2::cmds::GetActiveUniformBlockName
& c
=
11012 *static_cast<const gles2::cmds::GetActiveUniformBlockName
*>(cmd_data
);
11013 GLuint program_id
= c
.program
;
11014 GLuint index
= c
.index
;
11015 uint32 name_bucket_id
= c
.name_bucket_id
;
11016 typedef cmds::GetActiveUniformBlockName::Result Result
;
11017 Result
* result
= GetSharedMemoryAs
<Result
*>(
11018 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
11020 return error::kOutOfBounds
;
11022 // Check that the client initialized the result.
11023 if (*result
!= 0) {
11024 return error::kInvalidArguments
;
11026 Program
* program
= GetProgramInfoNotShader(
11027 program_id
, "glGetActiveUniformBlockName");
11029 return error::kNoError
;
11031 GLuint service_id
= program
->service_id();
11032 GLint link_status
= GL_FALSE
;
11033 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
11034 if (link_status
!= GL_TRUE
) {
11035 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11036 "glGetActiveActiveUniformBlockName", "program not linked");
11037 return error::kNoError
;
11039 GLint max_length
= 0;
11041 service_id
, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH
, &max_length
);
11042 // Increase one so &buffer[0] is always valid.
11043 GLsizei buf_size
= static_cast<GLsizei
>(max_length
) + 1;
11044 std::vector
<char> buffer(buf_size
);
11045 GLsizei length
= 0;
11046 glGetActiveUniformBlockName(
11047 service_id
, index
, buf_size
, &length
, &buffer
[0]);
11050 return error::kNoError
;
11053 Bucket
* bucket
= CreateBucket(name_bucket_id
);
11054 DCHECK_GT(buf_size
, length
);
11055 DCHECK_EQ(0, buffer
[length
]);
11056 bucket
->SetFromString(&buffer
[0]);
11057 return error::kNoError
;
11060 error::Error
GLES2DecoderImpl::HandleGetActiveUniformsiv(
11061 uint32 immediate_data_size
, const void* cmd_data
) {
11062 if (!unsafe_es3_apis_enabled())
11063 return error::kUnknownCommand
;
11064 const gles2::cmds::GetActiveUniformsiv
& c
=
11065 *static_cast<const gles2::cmds::GetActiveUniformsiv
*>(cmd_data
);
11066 GLuint program_id
= c
.program
;
11067 GLenum pname
= static_cast<GLenum
>(c
.pname
);
11068 Bucket
* bucket
= GetBucket(c
.indices_bucket_id
);
11070 return error::kInvalidArguments
;
11072 GLsizei count
= static_cast<GLsizei
>(bucket
->size() / sizeof(GLuint
));
11073 const GLuint
* indices
= bucket
->GetDataAs
<const GLuint
*>(0, bucket
->size());
11074 typedef cmds::GetActiveUniformsiv::Result Result
;
11075 Result
* result
= GetSharedMemoryAs
<Result
*>(
11076 c
.params_shm_id
, c
.params_shm_offset
, Result::ComputeSize(count
));
11077 GLint
* params
= result
? result
->GetData() : NULL
;
11078 if (params
== NULL
) {
11079 return error::kOutOfBounds
;
11081 // Check that the client initialized the result.
11082 if (result
->size
!= 0) {
11083 return error::kInvalidArguments
;
11085 Program
* program
= GetProgramInfoNotShader(
11086 program_id
, "glGetActiveUniformsiv");
11088 return error::kNoError
;
11090 GLuint service_id
= program
->service_id();
11091 GLint link_status
= GL_FALSE
;
11092 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
11093 if (link_status
!= GL_TRUE
) {
11094 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11095 "glGetActiveUniformsiv", "program not linked");
11096 return error::kNoError
;
11098 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformsiv");
11099 glGetActiveUniformsiv(service_id
, count
, indices
, pname
, params
);
11100 GLenum error
= glGetError();
11101 if (error
== GL_NO_ERROR
) {
11102 result
->SetNumResults(count
);
11104 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformsiv", "");
11106 return error::kNoError
;
11109 error::Error
GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size
,
11110 const void* cmd_data
) {
11111 const gles2::cmds::GetActiveAttrib
& c
=
11112 *static_cast<const gles2::cmds::GetActiveAttrib
*>(cmd_data
);
11113 GLuint program_id
= c
.program
;
11114 GLuint index
= c
.index
;
11115 uint32 name_bucket_id
= c
.name_bucket_id
;
11116 typedef cmds::GetActiveAttrib::Result Result
;
11117 Result
* result
= GetSharedMemoryAs
<Result
*>(
11118 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
11120 return error::kOutOfBounds
;
11122 // Check that the client initialized the result.
11123 if (result
->success
!= 0) {
11124 return error::kInvalidArguments
;
11126 Program
* program
= GetProgramInfoNotShader(
11127 program_id
, "glGetActiveAttrib");
11129 return error::kNoError
;
11131 const Program::VertexAttrib
* attrib_info
=
11132 program
->GetAttribInfo(index
);
11133 if (!attrib_info
) {
11134 LOCAL_SET_GL_ERROR(
11135 GL_INVALID_VALUE
, "glGetActiveAttrib", "index out of range");
11136 return error::kNoError
;
11138 result
->success
= 1; // true.
11139 result
->size
= attrib_info
->size
;
11140 result
->type
= attrib_info
->type
;
11141 Bucket
* bucket
= CreateBucket(name_bucket_id
);
11142 bucket
->SetFromString(attrib_info
->name
.c_str());
11143 return error::kNoError
;
11146 error::Error
GLES2DecoderImpl::HandleShaderBinary(uint32 immediate_data_size
,
11147 const void* cmd_data
) {
11148 #if 1 // No binary shader support.
11149 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glShaderBinary", "not supported");
11150 return error::kNoError
;
11152 GLsizei n
= static_cast<GLsizei
>(c
.n
);
11154 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "n < 0");
11155 return error::kNoError
;
11157 GLsizei length
= static_cast<GLsizei
>(c
.length
);
11159 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "length < 0");
11160 return error::kNoError
;
11163 if (!SafeMultiplyUint32(n
, sizeof(GLuint
), &data_size
)) {
11164 return error::kOutOfBounds
;
11166 const GLuint
* shaders
= GetSharedMemoryAs
<const GLuint
*>(
11167 c
.shaders_shm_id
, c
.shaders_shm_offset
, data_size
);
11168 GLenum binaryformat
= static_cast<GLenum
>(c
.binaryformat
);
11169 const void* binary
= GetSharedMemoryAs
<const void*>(
11170 c
.binary_shm_id
, c
.binary_shm_offset
, length
);
11171 if (shaders
== NULL
|| binary
== NULL
) {
11172 return error::kOutOfBounds
;
11174 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
11175 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11176 Shader
* shader
= GetShader(shaders
[ii
]);
11178 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "unknown shader");
11179 return error::kNoError
;
11181 service_ids
[ii
] = shader
->service_id();
11183 // TODO(gman): call glShaderBinary
11184 return error::kNoError
;
11188 void GLES2DecoderImpl::DoSwapBuffers() {
11189 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
11191 int this_frame_number
= frame_number_
++;
11192 // TRACE_EVENT for gpu tests:
11193 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
11194 TRACE_EVENT_SCOPE_THREAD
,
11195 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
11196 "width", (is_offscreen
? offscreen_size_
.width() :
11197 surface_
->GetSize().width()));
11198 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
11199 "offscreen", is_offscreen
,
11200 "frame", this_frame_number
);
11202 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
11205 ScopedGPUTrace
scoped_gpu_trace(gpu_tracer_
.get(), kTraceDecoder
,
11206 "GLES2Decoder", "SwapBuffer");
11209 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
11212 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
11213 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
11214 is_offscreen
? offscreen_size_
: surface_
->GetSize());
11217 // If offscreen then don't actually SwapBuffers to the display. Just copy
11218 // the rendered frame to another frame buffer.
11219 if (is_offscreen
) {
11220 TRACE_EVENT2("gpu", "Offscreen",
11221 "width", offscreen_size_
.width(), "height", offscreen_size_
.height());
11222 if (offscreen_size_
!= offscreen_saved_color_texture_
->size()) {
11223 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
11224 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
11226 if (workarounds().needs_offscreen_buffer_workaround
) {
11227 offscreen_saved_frame_buffer_
->Create();
11231 // Allocate the offscreen saved color texture.
11232 DCHECK(offscreen_saved_color_format_
);
11233 offscreen_saved_color_texture_
->AllocateStorage(
11234 offscreen_size_
, offscreen_saved_color_format_
, false);
11236 offscreen_saved_frame_buffer_
->AttachRenderTexture(
11237 offscreen_saved_color_texture_
.get());
11238 if (offscreen_size_
.width() != 0 && offscreen_size_
.height() != 0) {
11239 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
11240 GL_FRAMEBUFFER_COMPLETE
) {
11241 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
11242 << "because offscreen saved FBO was incomplete.";
11243 MarkContextLost(error::kUnknown
);
11244 group_
->LoseContexts(error::kUnknown
);
11248 // Clear the offscreen color texture.
11249 // TODO(piman): Is this still necessary?
11251 ScopedFrameBufferBinder
binder(this,
11252 offscreen_saved_frame_buffer_
->id());
11253 glClearColor(0, 0, 0, 0);
11254 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
11255 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
11256 glClear(GL_COLOR_BUFFER_BIT
);
11257 RestoreClearState();
11261 UpdateParentTextureInfo();
11264 if (offscreen_size_
.width() == 0 || offscreen_size_
.height() == 0)
11266 ScopedGLErrorSuppressor
suppressor(
11267 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
11269 if (IsOffscreenBufferMultisampled()) {
11270 // For multisampled buffers, resolve the frame buffer.
11271 ScopedResolvedFrameBufferBinder
binder(this, true, false);
11273 ScopedFrameBufferBinder
binder(this,
11274 offscreen_target_frame_buffer_
->id());
11276 if (offscreen_target_buffer_preserved_
) {
11277 // Copy the target frame buffer to the saved offscreen texture.
11278 offscreen_saved_color_texture_
->Copy(
11279 offscreen_saved_color_texture_
->size(),
11280 offscreen_saved_color_format_
);
11282 // Flip the textures in the parent context via the texture manager.
11283 if (!!offscreen_saved_color_texture_info_
.get())
11284 offscreen_saved_color_texture_info_
->texture()->
11285 SetServiceId(offscreen_target_color_texture_
->id());
11287 offscreen_saved_color_texture_
.swap(offscreen_target_color_texture_
);
11288 offscreen_target_frame_buffer_
->AttachRenderTexture(
11289 offscreen_target_color_texture_
.get());
11292 // Ensure the side effects of the copy are visible to the parent
11293 // context. There is no need to do this for ANGLE because it uses a
11294 // single D3D device for all contexts.
11295 if (!feature_info_
->gl_version_info().is_angle
)
11299 if (surface_
->SwapBuffers() == gfx::SwapResult::SWAP_FAILED
) {
11300 LOG(ERROR
) << "Context lost because SwapBuffers failed.";
11301 if (!CheckResetStatus()) {
11302 MarkContextLost(error::kUnknown
);
11303 group_
->LoseContexts(error::kUnknown
);
11308 // This may be a slow command. Exit command processing to allow for
11309 // context preemption and GPU watchdog checks.
11310 ExitCommandProcessingEarly();
11313 void GLES2DecoderImpl::DoSwapInterval(int interval
) {
11314 context_
->SetSwapInterval(interval
);
11317 error::Error
GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
11318 uint32 immediate_data_size
,
11319 const void* cmd_data
) {
11320 const gles2::cmds::EnableFeatureCHROMIUM
& c
=
11321 *static_cast<const gles2::cmds::EnableFeatureCHROMIUM
*>(cmd_data
);
11322 Bucket
* bucket
= GetBucket(c
.bucket_id
);
11323 if (!bucket
|| bucket
->size() == 0) {
11324 return error::kInvalidArguments
;
11326 typedef cmds::EnableFeatureCHROMIUM::Result Result
;
11327 Result
* result
= GetSharedMemoryAs
<Result
*>(
11328 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
11330 return error::kOutOfBounds
;
11332 // Check that the client initialized the result.
11333 if (*result
!= 0) {
11334 return error::kInvalidArguments
;
11336 std::string feature_str
;
11337 if (!bucket
->GetAsString(&feature_str
)) {
11338 return error::kInvalidArguments
;
11341 // TODO(gman): make this some kind of table to function pointer thingy.
11342 if (feature_str
.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
11343 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
11344 } else if (feature_str
.compare("pepper3d_support_fixed_attribs") == 0) {
11345 buffer_manager()->set_allow_fixed_attribs(true);
11346 // TODO(gman): decide how to remove the need for this const_cast.
11347 // I could make validators_ non const but that seems bad as this is the only
11348 // place it is needed. I could make some special friend class of validators
11349 // just to allow this to set them. That seems silly. I could refactor this
11350 // code to use the extension mechanism or the initialization attributes to
11351 // turn this feature on. Given that the only real point of this is to make
11352 // the conformance tests pass and given that there is lots of real work that
11353 // needs to be done it seems like refactoring for one to one of those
11354 // methods is a very low priority.
11355 const_cast<Validators
*>(validators_
)->vertex_attrib_type
.AddValue(GL_FIXED
);
11357 return error::kNoError
;
11360 *result
= 1; // true.
11361 return error::kNoError
;
11364 error::Error
GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
11365 uint32 immediate_data_size
,
11366 const void* cmd_data
) {
11367 const gles2::cmds::GetRequestableExtensionsCHROMIUM
& c
=
11368 *static_cast<const gles2::cmds::GetRequestableExtensionsCHROMIUM
*>(
11370 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
11371 scoped_refptr
<FeatureInfo
> info(new FeatureInfo());
11372 info
->Initialize(disallowed_features_
);
11373 bucket
->SetFromString(info
->extensions().c_str());
11374 return error::kNoError
;
11377 error::Error
GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
11378 uint32 immediate_data_size
,
11379 const void* cmd_data
) {
11380 const gles2::cmds::RequestExtensionCHROMIUM
& c
=
11381 *static_cast<const gles2::cmds::RequestExtensionCHROMIUM
*>(cmd_data
);
11382 Bucket
* bucket
= GetBucket(c
.bucket_id
);
11383 if (!bucket
|| bucket
->size() == 0) {
11384 return error::kInvalidArguments
;
11386 std::string feature_str
;
11387 if (!bucket
->GetAsString(&feature_str
)) {
11388 return error::kInvalidArguments
;
11391 bool desire_standard_derivatives
= false;
11392 bool desire_frag_depth
= false;
11393 bool desire_draw_buffers
= false;
11394 bool desire_shader_texture_lod
= false;
11395 if (IsWebGLContext()) {
11396 desire_standard_derivatives
=
11397 feature_str
.find("GL_OES_standard_derivatives") != std::string::npos
;
11398 desire_frag_depth
=
11399 feature_str
.find("GL_EXT_frag_depth") != std::string::npos
;
11400 desire_draw_buffers
=
11401 feature_str
.find("GL_EXT_draw_buffers") != std::string::npos
;
11402 desire_shader_texture_lod
=
11403 feature_str
.find("GL_EXT_shader_texture_lod") != std::string::npos
;
11406 if (desire_standard_derivatives
!= derivatives_explicitly_enabled_
||
11407 desire_frag_depth
!= frag_depth_explicitly_enabled_
||
11408 desire_draw_buffers
!= draw_buffers_explicitly_enabled_
||
11409 desire_shader_texture_lod
!= shader_texture_lod_explicitly_enabled_
) {
11410 derivatives_explicitly_enabled_
|= desire_standard_derivatives
;
11411 frag_depth_explicitly_enabled_
|= desire_frag_depth
;
11412 draw_buffers_explicitly_enabled_
|= desire_draw_buffers
;
11413 shader_texture_lod_explicitly_enabled_
|= desire_shader_texture_lod
;
11414 InitializeShaderTranslator();
11417 UpdateCapabilities();
11419 return error::kNoError
;
11422 error::Error
GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
11423 uint32 immediate_data_size
,
11424 const void* cmd_data
) {
11425 const gles2::cmds::GetProgramInfoCHROMIUM
& c
=
11426 *static_cast<const gles2::cmds::GetProgramInfoCHROMIUM
*>(cmd_data
);
11427 GLuint program_id
= static_cast<GLuint
>(c
.program
);
11428 uint32 bucket_id
= c
.bucket_id
;
11429 Bucket
* bucket
= CreateBucket(bucket_id
);
11430 bucket
->SetSize(sizeof(ProgramInfoHeader
)); // in case we fail.
11431 Program
* program
= NULL
;
11432 program
= GetProgram(program_id
);
11433 if (!program
|| !program
->IsValid()) {
11434 return error::kNoError
;
11436 program
->GetProgramInfo(program_manager(), bucket
);
11437 return error::kNoError
;
11440 error::Error
GLES2DecoderImpl::HandleGetUniformBlocksCHROMIUM(
11441 uint32 immediate_data_size
, const void* cmd_data
) {
11442 if (!unsafe_es3_apis_enabled())
11443 return error::kUnknownCommand
;
11444 const gles2::cmds::GetUniformBlocksCHROMIUM
& c
=
11445 *static_cast<const gles2::cmds::GetUniformBlocksCHROMIUM
*>(cmd_data
);
11446 GLuint program_id
= static_cast<GLuint
>(c
.program
);
11447 uint32 bucket_id
= c
.bucket_id
;
11448 Bucket
* bucket
= CreateBucket(bucket_id
);
11449 bucket
->SetSize(sizeof(UniformBlocksHeader
)); // in case we fail.
11450 Program
* program
= NULL
;
11451 program
= GetProgram(program_id
);
11452 if (!program
|| !program
->IsValid()) {
11453 return error::kNoError
;
11455 program
->GetUniformBlocks(bucket
);
11456 return error::kNoError
;
11459 error::Error
GLES2DecoderImpl::HandleGetUniformsES3CHROMIUM(
11460 uint32 immediate_data_size
, const void* cmd_data
) {
11461 if (!unsafe_es3_apis_enabled())
11462 return error::kUnknownCommand
;
11463 const gles2::cmds::GetUniformsES3CHROMIUM
& c
=
11464 *static_cast<const gles2::cmds::GetUniformsES3CHROMIUM
*>(cmd_data
);
11465 GLuint program_id
= static_cast<GLuint
>(c
.program
);
11466 uint32 bucket_id
= c
.bucket_id
;
11467 Bucket
* bucket
= CreateBucket(bucket_id
);
11468 bucket
->SetSize(sizeof(UniformsES3Header
)); // in case we fail.
11469 Program
* program
= NULL
;
11470 program
= GetProgram(program_id
);
11471 if (!program
|| !program
->IsValid()) {
11472 return error::kNoError
;
11474 program
->GetUniformsES3(bucket
);
11475 return error::kNoError
;
11478 error::Error
GLES2DecoderImpl::HandleGetTransformFeedbackVarying(
11479 uint32 immediate_data_size
,
11480 const void* cmd_data
) {
11481 if (!unsafe_es3_apis_enabled())
11482 return error::kUnknownCommand
;
11483 const gles2::cmds::GetTransformFeedbackVarying
& c
=
11484 *static_cast<const gles2::cmds::GetTransformFeedbackVarying
*>(cmd_data
);
11485 GLuint program_id
= c
.program
;
11486 GLuint index
= c
.index
;
11487 uint32 name_bucket_id
= c
.name_bucket_id
;
11488 typedef cmds::GetTransformFeedbackVarying::Result Result
;
11489 Result
* result
= GetSharedMemoryAs
<Result
*>(
11490 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
11492 return error::kOutOfBounds
;
11494 // Check that the client initialized the result.
11495 if (result
->success
!= 0) {
11496 return error::kInvalidArguments
;
11498 Program
* program
= GetProgramInfoNotShader(
11499 program_id
, "glGetTransformFeedbackVarying");
11501 return error::kNoError
;
11503 GLuint service_id
= program
->service_id();
11504 GLint link_status
= GL_FALSE
;
11505 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
11506 if (link_status
!= GL_TRUE
) {
11507 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11508 "glGetTransformFeedbackVarying", "program not linked");
11509 return error::kNoError
;
11511 GLint max_length
= 0;
11513 service_id
, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH
, &max_length
);
11514 max_length
= std::max(1, max_length
);
11515 std::vector
<char> buffer(max_length
);
11516 GLsizei length
= 0;
11519 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetTransformFeedbackVarying");
11520 glGetTransformFeedbackVarying(
11521 service_id
, index
, max_length
, &length
, &size
, &type
, &buffer
[0]);
11522 GLenum error
= glGetError();
11523 if (error
!= GL_NO_ERROR
) {
11524 LOCAL_SET_GL_ERROR(error
, "glGetTransformFeedbackVarying", "");
11525 return error::kNoError
;
11527 result
->success
= 1; // true.
11528 result
->size
= static_cast<int32_t>(size
);
11529 result
->type
= static_cast<uint32_t>(type
);
11530 Bucket
* bucket
= CreateBucket(name_bucket_id
);
11531 DCHECK(length
>= 0 && length
< max_length
);
11532 buffer
[length
] = '\0'; // Just to be safe.
11533 bucket
->SetFromString(&buffer
[0]);
11534 return error::kNoError
;
11537 error::Error
GLES2DecoderImpl::HandleGetTransformFeedbackVaryingsCHROMIUM(
11538 uint32 immediate_data_size
, const void* cmd_data
) {
11539 if (!unsafe_es3_apis_enabled())
11540 return error::kUnknownCommand
;
11541 const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM
& c
=
11542 *static_cast<const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM
*>(
11544 GLuint program_id
= static_cast<GLuint
>(c
.program
);
11545 uint32 bucket_id
= c
.bucket_id
;
11546 Bucket
* bucket
= CreateBucket(bucket_id
);
11547 bucket
->SetSize(sizeof(TransformFeedbackVaryingsHeader
)); // in case we fail.
11548 Program
* program
= NULL
;
11549 program
= GetProgram(program_id
);
11550 if (!program
|| !program
->IsValid()) {
11551 return error::kNoError
;
11553 program
->GetTransformFeedbackVaryings(bucket
);
11554 return error::kNoError
;
11557 error::ContextLostReason
GLES2DecoderImpl::GetContextLostReason() {
11558 return context_lost_reason_
;
11561 error::ContextLostReason
GLES2DecoderImpl::GetContextLostReasonFromResetStatus(
11562 GLenum reset_status
) const {
11563 switch (reset_status
) {
11565 // TODO(kbr): improve the precision of the error code in this case.
11566 // Consider delegating to context for error code if MakeCurrent fails.
11567 return error::kUnknown
;
11568 case GL_GUILTY_CONTEXT_RESET_ARB
:
11569 return error::kGuilty
;
11570 case GL_INNOCENT_CONTEXT_RESET_ARB
:
11571 return error::kInnocent
;
11572 case GL_UNKNOWN_CONTEXT_RESET_ARB
:
11573 return error::kUnknown
;
11577 return error::kUnknown
;
11580 bool GLES2DecoderImpl::WasContextLost() const {
11581 return context_was_lost_
;
11584 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() const {
11585 return WasContextLost() && reset_by_robustness_extension_
;
11588 void GLES2DecoderImpl::MarkContextLost(error::ContextLostReason reason
) {
11589 // Only lose the context once.
11590 if (WasContextLost())
11593 // Don't make GL calls in here, the context might not be current.
11594 context_lost_reason_
= reason
;
11595 current_decoder_error_
= error::kLostContext
;
11596 context_was_lost_
= true;
11599 bool GLES2DecoderImpl::CheckResetStatus() {
11600 DCHECK(!WasContextLost());
11601 DCHECK(context_
->IsCurrent(NULL
));
11603 if (IsRobustnessSupported()) {
11604 // If the reason for the call was a GL error, we can try to determine the
11605 // reset status more accurately.
11606 GLenum driver_status
= glGetGraphicsResetStatusARB();
11607 if (driver_status
== GL_NO_ERROR
)
11610 LOG(ERROR
) << (surface_
->IsOffscreen() ? "Offscreen" : "Onscreen")
11611 << " context lost via ARB/EXT_robustness. Reset status = "
11612 << GLES2Util::GetStringEnum(driver_status
);
11614 // Don't pretend we know which client was responsible.
11615 if (workarounds().use_virtualized_gl_contexts
)
11616 driver_status
= GL_UNKNOWN_CONTEXT_RESET_ARB
;
11618 switch (driver_status
) {
11619 case GL_GUILTY_CONTEXT_RESET_ARB
:
11620 MarkContextLost(error::kGuilty
);
11622 case GL_INNOCENT_CONTEXT_RESET_ARB
:
11623 MarkContextLost(error::kInnocent
);
11625 case GL_UNKNOWN_CONTEXT_RESET_ARB
:
11626 MarkContextLost(error::kUnknown
);
11632 reset_by_robustness_extension_
= true;
11638 error::Error
GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
11639 uint32 immediate_data_size
,
11640 const void* cmd_data
) {
11641 return error::kUnknownCommand
;
11644 error::Error
GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
11645 uint32 immediate_data_size
,
11646 const void* cmd_data
) {
11647 const gles2::cmds::WaitSyncPointCHROMIUM
& c
=
11648 *static_cast<const gles2::cmds::WaitSyncPointCHROMIUM
*>(cmd_data
);
11649 uint32 sync_point
= c
.sync_point
;
11650 if (wait_sync_point_callback_
.is_null())
11651 return error::kNoError
;
11653 return wait_sync_point_callback_
.Run(sync_point
) ?
11654 error::kNoError
: error::kDeferCommandUntilLater
;
11657 error::Error
GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
11658 uint32 immediate_data_size
,
11659 const void* cmd_data
) {
11660 if (surface_
->DeferDraws())
11661 return error::kDeferCommandUntilLater
;
11662 if (!surface_
->SetBackbufferAllocation(false))
11663 return error::kLostContext
;
11664 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
11665 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
11666 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
11667 return error::kNoError
;
11670 bool GLES2DecoderImpl::GenQueriesEXTHelper(
11671 GLsizei n
, const GLuint
* client_ids
) {
11672 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11673 if (query_manager_
->GetQuery(client_ids
[ii
])) {
11677 query_manager_
->GenQueries(n
, client_ids
);
11681 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
11682 GLsizei n
, const GLuint
* client_ids
) {
11683 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11684 query_manager_
->RemoveQuery(client_ids
[ii
]);
11688 bool GLES2DecoderImpl::ProcessPendingQueries(bool did_finish
) {
11689 if (query_manager_
.get() == NULL
) {
11692 if (!query_manager_
->ProcessPendingQueries(did_finish
)) {
11693 current_decoder_error_
= error::kOutOfBounds
;
11695 return query_manager_
->HavePendingQueries();
11698 // Note that if there are no pending readpixels right now,
11699 // this function will call the callback immediately.
11700 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback
) {
11701 if (features().use_async_readpixels
&& !pending_readpixel_fences_
.empty()) {
11702 pending_readpixel_fences_
.back()->callbacks
.push_back(callback
);
11708 void GLES2DecoderImpl::ProcessPendingReadPixels(bool did_finish
) {
11709 // Note: |did_finish| guarantees that the GPU has passed the fence but
11710 // we cannot assume that GLFence::HasCompleted() will return true yet as
11711 // that's not guaranteed by all GLFence implementations.
11712 while (!pending_readpixel_fences_
.empty() &&
11714 pending_readpixel_fences_
.front()->fence
->HasCompleted())) {
11715 std::vector
<base::Closure
> callbacks
=
11716 pending_readpixel_fences_
.front()->callbacks
;
11717 pending_readpixel_fences_
.pop();
11718 for (size_t i
= 0; i
< callbacks
.size(); i
++) {
11719 callbacks
[i
].Run();
11724 bool GLES2DecoderImpl::HasMoreIdleWork() {
11725 return !pending_readpixel_fences_
.empty() ||
11726 async_pixel_transfer_manager_
->NeedsProcessMorePendingTransfers();
11729 void GLES2DecoderImpl::PerformIdleWork() {
11730 ProcessPendingReadPixels(false);
11731 if (!async_pixel_transfer_manager_
->NeedsProcessMorePendingTransfers())
11733 async_pixel_transfer_manager_
->ProcessMorePendingTransfers();
11734 ProcessFinishedAsyncTransfers();
11737 error::Error
GLES2DecoderImpl::HandleBeginQueryEXT(uint32 immediate_data_size
,
11738 const void* cmd_data
) {
11739 const gles2::cmds::BeginQueryEXT
& c
=
11740 *static_cast<const gles2::cmds::BeginQueryEXT
*>(cmd_data
);
11741 GLenum target
= static_cast<GLenum
>(c
.target
);
11742 GLuint client_id
= static_cast<GLuint
>(c
.id
);
11743 int32 sync_shm_id
= static_cast<int32
>(c
.sync_data_shm_id
);
11744 uint32 sync_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
11747 case GL_COMMANDS_ISSUED_CHROMIUM
:
11748 case GL_LATENCY_QUERY_CHROMIUM
:
11749 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
:
11750 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM
:
11751 case GL_GET_ERROR_QUERY_CHROMIUM
:
11753 case GL_COMMANDS_COMPLETED_CHROMIUM
:
11754 if (!features().chromium_sync_query
) {
11755 LOCAL_SET_GL_ERROR(
11756 GL_INVALID_OPERATION
, "glBeginQueryEXT",
11757 "not enabled for commands completed queries");
11758 return error::kNoError
;
11761 case GL_SAMPLES_PASSED
:
11762 case GL_ANY_SAMPLES_PASSED
:
11763 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE
:
11764 if (!features().occlusion_query_boolean
) {
11765 LOCAL_SET_GL_ERROR(
11766 GL_INVALID_OPERATION
, "glBeginQueryEXT",
11767 "not enabled for occlusion queries");
11768 return error::kNoError
;
11771 case GL_TIME_ELAPSED
:
11772 if (!query_manager_
->GPUTimingAvailable()) {
11773 LOCAL_SET_GL_ERROR(
11774 GL_INVALID_OPERATION
, "glBeginQueryEXT",
11775 "not enabled for timing queries");
11776 return error::kNoError
;
11780 LOCAL_SET_GL_ERROR(
11781 GL_INVALID_ENUM
, "glBeginQueryEXT",
11782 "unknown query target");
11783 return error::kNoError
;
11786 if (query_manager_
->GetActiveQuery(target
)) {
11787 LOCAL_SET_GL_ERROR(
11788 GL_INVALID_OPERATION
, "glBeginQueryEXT", "query already in progress");
11789 return error::kNoError
;
11792 if (client_id
== 0) {
11793 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glBeginQueryEXT", "id is 0");
11794 return error::kNoError
;
11797 QueryManager::Query
* query
= query_manager_
->GetQuery(client_id
);
11799 if (!query_manager_
->IsValidQuery(client_id
)) {
11800 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11802 "id not made by glGenQueriesEXT");
11803 return error::kNoError
;
11805 query
= query_manager_
->CreateQuery(
11806 target
, client_id
, sync_shm_id
, sync_shm_offset
);
11809 if (query
->target() != target
) {
11810 LOCAL_SET_GL_ERROR(
11811 GL_INVALID_OPERATION
, "glBeginQueryEXT", "target does not match");
11812 return error::kNoError
;
11813 } else if (query
->shm_id() != sync_shm_id
||
11814 query
->shm_offset() != sync_shm_offset
) {
11815 DLOG(ERROR
) << "Shared memory used by query not the same as before";
11816 return error::kInvalidArguments
;
11819 if (!query_manager_
->BeginQuery(query
)) {
11820 return error::kOutOfBounds
;
11823 return error::kNoError
;
11826 error::Error
GLES2DecoderImpl::HandleEndQueryEXT(uint32 immediate_data_size
,
11827 const void* cmd_data
) {
11828 const gles2::cmds::EndQueryEXT
& c
=
11829 *static_cast<const gles2::cmds::EndQueryEXT
*>(cmd_data
);
11830 GLenum target
= static_cast<GLenum
>(c
.target
);
11831 uint32 submit_count
= static_cast<GLuint
>(c
.submit_count
);
11833 QueryManager::Query
* query
= query_manager_
->GetActiveQuery(target
);
11835 LOCAL_SET_GL_ERROR(
11836 GL_INVALID_OPERATION
, "glEndQueryEXT", "No active query");
11837 return error::kNoError
;
11840 if (!query_manager_
->EndQuery(query
, submit_count
)) {
11841 return error::kOutOfBounds
;
11844 query_manager_
->ProcessPendingTransferQueries();
11846 return error::kNoError
;
11849 error::Error
GLES2DecoderImpl::HandleQueryCounterEXT(uint32 immediate_data_size
,
11850 const void* cmd_data
) {
11851 const gles2::cmds::QueryCounterEXT
& c
=
11852 *static_cast<const gles2::cmds::QueryCounterEXT
*>(cmd_data
);
11853 GLuint client_id
= static_cast<GLuint
>(c
.id
);
11854 GLenum target
= static_cast<GLenum
>(c
.target
);
11855 int32 sync_shm_id
= static_cast<int32
>(c
.sync_data_shm_id
);
11856 uint32 sync_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
11857 uint32 submit_count
= static_cast<GLuint
>(c
.submit_count
);
11861 if (!query_manager_
->GPUTimingAvailable()) {
11862 LOCAL_SET_GL_ERROR(
11863 GL_INVALID_OPERATION
, "glQueryCounterEXT",
11864 "not enabled for timing queries");
11865 return error::kNoError
;
11869 LOCAL_SET_GL_ERROR(
11870 GL_INVALID_ENUM
, "glQueryCounterEXT",
11871 "unknown query target");
11872 return error::kNoError
;
11875 QueryManager::Query
* query
= query_manager_
->GetQuery(client_id
);
11877 if (!query_manager_
->IsValidQuery(client_id
)) {
11878 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11879 "glQueryCounterEXT",
11880 "id not made by glGenQueriesEXT");
11881 return error::kNoError
;
11883 query
= query_manager_
->CreateQuery(
11884 target
, client_id
, sync_shm_id
, sync_shm_offset
);
11886 if (!query_manager_
->QueryCounter(query
, submit_count
)) {
11887 return error::kOutOfBounds
;
11890 return error::kNoError
;
11893 error::Error
GLES2DecoderImpl::HandleSetDisjointValueSyncCHROMIUM(
11894 uint32 immediate_data_size
, const void* cmd_data
) {
11895 const gles2::cmds::SetDisjointValueSyncCHROMIUM
& c
=
11896 *static_cast<const gles2::cmds::SetDisjointValueSyncCHROMIUM
*>(cmd_data
);
11897 int32 sync_shm_id
= static_cast<int32
>(c
.sync_data_shm_id
);
11898 uint32 sync_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
11900 query_manager_
->SetDisjointSync(sync_shm_id
, sync_shm_offset
);
11901 return error::kNoError
;
11904 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
11905 GLsizei n
, const GLuint
* client_ids
) {
11906 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11907 if (GetVertexAttribManager(client_ids
[ii
])) {
11912 if (!features().native_vertex_array_object
) {
11914 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11915 CreateVertexAttribManager(client_ids
[ii
], 0, true);
11918 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
11920 glGenVertexArraysOES(n
, service_ids
.get());
11921 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11922 CreateVertexAttribManager(client_ids
[ii
], service_ids
[ii
], true);
11929 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
11930 GLsizei n
, const GLuint
* client_ids
) {
11931 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11932 VertexAttribManager
* vao
=
11933 GetVertexAttribManager(client_ids
[ii
]);
11934 if (vao
&& !vao
->IsDeleted()) {
11935 if (state_
.vertex_attrib_manager
.get() == vao
) {
11936 DoBindVertexArrayOES(0);
11938 RemoveVertexAttribManager(client_ids
[ii
]);
11943 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id
) {
11944 VertexAttribManager
* vao
= NULL
;
11945 if (client_id
!= 0) {
11946 vao
= GetVertexAttribManager(client_id
);
11948 // Unlike most Bind* methods, the spec explicitly states that VertexArray
11949 // only allows names that have been previously generated. As such, we do
11950 // not generate new names here.
11951 LOCAL_SET_GL_ERROR(
11952 GL_INVALID_OPERATION
,
11953 "glBindVertexArrayOES", "bad vertex array id.");
11954 current_decoder_error_
= error::kNoError
;
11958 vao
= state_
.default_vertex_attrib_manager
.get();
11961 // Only set the VAO state if it's changed
11962 if (state_
.vertex_attrib_manager
.get() != vao
) {
11963 state_
.vertex_attrib_manager
= vao
;
11964 if (!features().native_vertex_array_object
) {
11965 EmulateVertexArrayState();
11967 GLuint service_id
= vao
->service_id();
11968 glBindVertexArrayOES(service_id
);
11973 // Used when OES_vertex_array_object isn't natively supported
11974 void GLES2DecoderImpl::EmulateVertexArrayState() {
11975 // Setup the Vertex attribute state
11976 for (uint32 vv
= 0; vv
< group_
->max_vertex_attribs(); ++vv
) {
11977 RestoreStateForAttrib(vv
, true);
11980 // Setup the element buffer
11981 Buffer
* element_array_buffer
=
11982 state_
.vertex_attrib_manager
->element_array_buffer();
11983 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
11984 element_array_buffer
? element_array_buffer
->service_id() : 0);
11987 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id
) {
11988 const VertexAttribManager
* vao
=
11989 GetVertexAttribManager(client_id
);
11990 return vao
&& vao
->IsValid() && !vao
->IsDeleted();
11993 bool GLES2DecoderImpl::DoIsPathCHROMIUM(GLuint client_id
) {
11994 GLuint service_id
= 0;
11995 return path_manager()->GetPath(client_id
, &service_id
) &&
11996 glIsPathNV(service_id
) == GL_TRUE
;
11999 #if defined(OS_MACOSX)
12000 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id
) {
12001 TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.find(
12003 if (it
!= texture_to_io_surface_map_
.end()) {
12004 // Found a previous IOSurface bound to this texture; release it.
12005 IOSurfaceRef surface
= it
->second
;
12006 CFRelease(surface
);
12007 texture_to_io_surface_map_
.erase(it
);
12012 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
12013 GLenum target
, GLsizei width
, GLsizei height
,
12014 GLuint io_surface_id
, GLuint plane
) {
12015 #if defined(OS_MACOSX)
12016 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL
) {
12017 LOCAL_SET_GL_ERROR(
12018 GL_INVALID_OPERATION
,
12019 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
12023 if (target
!= GL_TEXTURE_RECTANGLE_ARB
) {
12024 // This might be supported in the future, and if we could require
12025 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
12026 // could delete a lot of code. For now, perform strict validation so we
12027 // know what's going on.
12028 LOCAL_SET_GL_ERROR(
12029 GL_INVALID_OPERATION
,
12030 "glTexImageIOSurface2DCHROMIUM",
12031 "requires TEXTURE_RECTANGLE_ARB target");
12035 // Default target might be conceptually valid, but disallow it to avoid
12037 TextureRef
* texture_ref
=
12038 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
12039 if (!texture_ref
) {
12040 LOCAL_SET_GL_ERROR(
12041 GL_INVALID_OPERATION
,
12042 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
12046 // Look up the new IOSurface. Note that because of asynchrony
12047 // between processes this might fail; during live resizing the
12048 // plugin process might allocate and release an IOSurface before
12049 // this process gets a chance to look it up. Hold on to any old
12050 // IOSurface in this case.
12051 IOSurfaceRef surface
= IOSurfaceLookup(io_surface_id
);
12053 LOCAL_SET_GL_ERROR(
12054 GL_INVALID_OPERATION
,
12055 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
12059 // Release any IOSurface previously bound to this texture.
12060 ReleaseIOSurfaceForTexture(texture_ref
->service_id());
12062 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
12063 texture_to_io_surface_map_
.insert(
12064 std::make_pair(texture_ref
->service_id(), surface
));
12066 CGLContextObj context
=
12067 static_cast<CGLContextObj
>(context_
->GetHandle());
12069 CGLError err
= CGLTexImageIOSurface2D(
12076 GL_UNSIGNED_INT_8_8_8_8_REV
,
12080 if (err
!= kCGLNoError
) {
12081 LOCAL_SET_GL_ERROR(
12082 GL_INVALID_OPERATION
,
12083 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
12087 texture_manager()->SetLevelInfo(
12088 texture_ref
, target
, 0, GL_RGBA
, width
, height
, 1, 0, GL_BGRA
,
12089 GL_UNSIGNED_INT_8_8_8_8_REV
, gfx::Rect(width
, height
));
12092 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12093 "glTexImageIOSurface2DCHROMIUM", "not supported.");
12097 static GLenum
ExtractFormatFromStorageFormat(GLenum internalformat
) {
12098 switch (internalformat
) {
12110 return GL_RED_INTEGER
;
12122 return GL_RG_INTEGER
;
12123 case GL_ATC_RGB_AMD
:
12124 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
12125 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
12126 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
12127 case GL_ETC1_RGB8_OES
:
12129 case GL_R11F_G11F_B10F
:
12131 case GL_RGB8_SNORM
:
12142 return GL_RGB_INTEGER
;
12143 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
12144 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
12145 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
:
12146 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
12147 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
12148 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
12149 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
12151 case GL_SRGB8_ALPHA8
:
12152 case GL_RGBA8_SNORM
:
12161 case GL_RGB10_A2UI
:
12166 return GL_RGBA_INTEGER
;
12167 case GL_DEPTH_COMPONENT16
:
12168 case GL_DEPTH_COMPONENT24
:
12169 case GL_DEPTH_COMPONENT32F
:
12170 return GL_DEPTH_COMPONENT
;
12171 case GL_DEPTH24_STENCIL8
:
12172 case GL_DEPTH32F_STENCIL8
:
12173 return GL_DEPTH_STENCIL
;
12174 case GL_LUMINANCE8_ALPHA8_EXT
:
12175 return GL_LUMINANCE_ALPHA
;
12176 case GL_LUMINANCE8_EXT
:
12177 return GL_LUMINANCE
;
12178 case GL_ALPHA8_EXT
:
12180 case GL_ALPHA32F_EXT
:
12182 case GL_LUMINANCE32F_EXT
:
12183 return GL_LUMINANCE
;
12184 case GL_LUMINANCE_ALPHA32F_EXT
:
12185 return GL_LUMINANCE_ALPHA
;
12186 case GL_ALPHA16F_EXT
:
12188 case GL_LUMINANCE16F_EXT
:
12189 return GL_LUMINANCE
;
12190 case GL_LUMINANCE_ALPHA16F_EXT
:
12191 return GL_LUMINANCE_ALPHA
;
12193 return GL_BGRA_EXT
;
12199 bool GLES2DecoderImpl::ValidateCopyTextureCHROMIUM(
12200 const char* function_name
,
12202 TextureRef
* source_texture_ref
,
12203 TextureRef
* dest_texture_ref
,
12204 GLenum dest_internal_format
) {
12205 if (!source_texture_ref
|| !dest_texture_ref
) {
12206 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown texture id");
12210 if (GL_TEXTURE_2D
!= target
) {
12211 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
12212 "invalid texture target");
12216 Texture
* source_texture
= source_texture_ref
->texture();
12217 Texture
* dest_texture
= dest_texture_ref
->texture();
12218 if (source_texture
== dest_texture
) {
12219 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
12220 "source and destination textures are the same");
12224 if (dest_texture
->target() != GL_TEXTURE_2D
||
12225 (source_texture
->target() != GL_TEXTURE_2D
&&
12226 source_texture
->target() != GL_TEXTURE_RECTANGLE_ARB
&&
12227 source_texture
->target() != GL_TEXTURE_EXTERNAL_OES
)) {
12228 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
12229 "invalid texture target binding");
12233 GLenum source_type
= 0;
12234 GLenum source_internal_format
= 0;
12235 source_texture
->GetLevelType(source_texture
->target(), 0, &source_type
,
12236 &source_internal_format
);
12238 // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
12239 // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
12240 // renderable on some platforms.
12241 bool valid_dest_format
= dest_internal_format
== GL_RGB
||
12242 dest_internal_format
== GL_RGBA
||
12243 dest_internal_format
== GL_BGRA_EXT
;
12244 bool valid_source_format
=
12245 source_internal_format
== GL_R8
|| source_internal_format
== GL_ALPHA
||
12246 source_internal_format
== GL_RGB
|| source_internal_format
== GL_RGBA
||
12247 source_internal_format
== GL_LUMINANCE
||
12248 source_internal_format
== GL_LUMINANCE_ALPHA
||
12249 source_internal_format
== GL_BGRA_EXT
;
12250 if (!valid_source_format
|| !valid_dest_format
) {
12251 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
12252 "invalid internal format");
12258 bool GLES2DecoderImpl::ValidateCompressedCopyTextureCHROMIUM(
12259 const char* function_name
,
12261 TextureRef
* source_texture_ref
,
12262 TextureRef
* dest_texture_ref
) {
12263 if (!source_texture_ref
|| !dest_texture_ref
) {
12264 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown texture id");
12268 if (GL_TEXTURE_2D
!= target
) {
12269 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
12270 "invalid texture target");
12274 Texture
* source_texture
= source_texture_ref
->texture();
12275 Texture
* dest_texture
= dest_texture_ref
->texture();
12276 if (source_texture
== dest_texture
) {
12277 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
12278 "source and destination textures are the same");
12282 if (dest_texture
->target() != GL_TEXTURE_2D
||
12283 (source_texture
->target() != GL_TEXTURE_2D
&&
12284 source_texture
->target() != GL_TEXTURE_RECTANGLE_ARB
&&
12285 source_texture
->target() != GL_TEXTURE_EXTERNAL_OES
)) {
12286 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
12287 "invalid texture target binding");
12291 GLenum source_type
= 0;
12292 GLenum source_internal_format
= 0;
12293 source_texture
->GetLevelType(source_texture
->target(), 0, &source_type
,
12294 &source_internal_format
);
12296 bool valid_format
=
12297 source_internal_format
== GL_ATC_RGB_AMD
||
12298 source_internal_format
== GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
||
12299 source_internal_format
== GL_COMPRESSED_RGB_S3TC_DXT1_EXT
||
12300 source_internal_format
== GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
||
12301 source_internal_format
== GL_ETC1_RGB8_OES
;
12303 if (!valid_format
) {
12304 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
12305 "invalid internal format");
12312 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
12316 GLenum internal_format
,
12318 GLboolean unpack_flip_y
,
12319 GLboolean unpack_premultiply_alpha
,
12320 GLboolean unpack_unmultiply_alpha
) {
12321 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
12323 TextureRef
* source_texture_ref
= GetTexture(source_id
);
12324 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
12325 Texture
* source_texture
= source_texture_ref
->texture();
12326 Texture
* dest_texture
= dest_texture_ref
->texture();
12327 int source_width
= 0;
12328 int source_height
= 0;
12329 gfx::GLImage
* image
=
12330 source_texture
->GetLevelImage(source_texture
->target(), 0);
12332 gfx::Size size
= image
->GetSize();
12333 source_width
= size
.width();
12334 source_height
= size
.height();
12335 if (source_width
<= 0 || source_height
<= 0) {
12336 LOCAL_SET_GL_ERROR(
12338 "glCopyTextureChromium", "invalid image size");
12342 if (!source_texture
->GetLevelSize(source_texture
->target(), 0,
12343 &source_width
, &source_height
, nullptr)) {
12344 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
12345 "glCopyTextureChromium",
12346 "source texture has no level 0");
12350 // Check that this type of texture is allowed.
12351 if (!texture_manager()->ValidForTarget(source_texture
->target(), 0,
12352 source_width
, source_height
, 1)) {
12353 LOCAL_SET_GL_ERROR(
12354 GL_INVALID_VALUE
, "glCopyTextureCHROMIUM", "Bad dimensions");
12359 GLenum source_type
= 0;
12360 GLenum source_internal_format
= 0;
12361 source_texture
->GetLevelType(
12362 source_texture
->target(), 0, &source_type
, &source_internal_format
);
12364 if (dest_texture
->IsImmutable()) {
12365 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCopyTextureCHROMIUM",
12366 "texture is immutable");
12370 if (!ValidateCopyTextureCHROMIUM("glCopyTextureCHROMIUM", target
,
12371 source_texture_ref
, dest_texture_ref
,
12372 internal_format
)) {
12376 // Clear the source texture if necessary.
12377 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref
,
12378 source_texture
->target(), 0)) {
12379 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTextureCHROMIUM",
12380 "dimensions too big");
12384 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12385 // needed because it takes 10s of milliseconds to initialize.
12386 if (!copy_texture_CHROMIUM_
.get()) {
12387 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12388 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
12389 copy_texture_CHROMIUM_
->Initialize(this);
12390 RestoreCurrentFramebufferBindings();
12391 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR
)
12395 GLenum dest_type_previous
= dest_type
;
12396 GLenum dest_internal_format
= internal_format
;
12397 int dest_width
= 0;
12398 int dest_height
= 0;
12399 bool dest_level_defined
= dest_texture
->GetLevelSize(
12400 GL_TEXTURE_2D
, 0, &dest_width
, &dest_height
, nullptr);
12402 if (dest_level_defined
) {
12403 dest_texture
->GetLevelType(GL_TEXTURE_2D
, 0, &dest_type_previous
,
12404 &dest_internal_format
);
12407 // Resize the destination texture to the dimensions of the source texture.
12408 if (!dest_level_defined
|| dest_width
!= source_width
||
12409 dest_height
!= source_height
||
12410 dest_internal_format
!= internal_format
||
12411 dest_type_previous
!= dest_type
) {
12412 // Ensure that the glTexImage2D succeeds.
12413 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12414 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
12415 glTexImage2D(GL_TEXTURE_2D
, 0, internal_format
, source_width
, source_height
,
12416 0, internal_format
, dest_type
, NULL
);
12417 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
12418 if (error
!= GL_NO_ERROR
) {
12419 RestoreCurrentTextureBindings(&state_
, GL_TEXTURE_2D
);
12423 texture_manager()->SetLevelInfo(
12424 dest_texture_ref
, GL_TEXTURE_2D
, 0, internal_format
, source_width
,
12425 source_height
, 1, 0, internal_format
, dest_type
,
12426 gfx::Rect(source_width
, source_height
));
12428 texture_manager()->SetLevelCleared(dest_texture_ref
, GL_TEXTURE_2D
, 0,
12432 ScopedModifyPixels
modify(dest_texture_ref
);
12434 // Try using GLImage::CopyTexSubImage when possible.
12435 bool unpack_premultiply_alpha_change
=
12436 (unpack_premultiply_alpha
^ unpack_unmultiply_alpha
) != 0;
12437 if (image
&& !unpack_flip_y
&& !unpack_premultiply_alpha_change
) {
12438 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
12439 if (image
->CopyTexSubImage(GL_TEXTURE_2D
, gfx::Point(0, 0),
12440 gfx::Rect(0, 0, source_width
, source_height
))) {
12445 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
12447 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
12448 // before presenting.
12449 if (source_texture
->target() == GL_TEXTURE_EXTERNAL_OES
) {
12450 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
12451 // instead of using kIdentityMatrix crbug.com/226218.
12452 copy_texture_CHROMIUM_
->DoCopyTextureWithTransform(
12453 this, source_texture
->target(), source_texture
->service_id(),
12454 dest_texture
->service_id(), source_width
, source_height
,
12455 unpack_flip_y
== GL_TRUE
,
12456 unpack_premultiply_alpha
== GL_TRUE
,
12457 unpack_unmultiply_alpha
== GL_TRUE
,
12460 copy_texture_CHROMIUM_
->DoCopyTexture(
12461 this, source_texture
->target(), source_texture
->service_id(),
12462 source_internal_format
, dest_texture
->service_id(), internal_format
,
12463 source_width
, source_height
,
12464 unpack_flip_y
== GL_TRUE
,
12465 unpack_premultiply_alpha
== GL_TRUE
,
12466 unpack_unmultiply_alpha
== GL_TRUE
);
12469 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
12472 void GLES2DecoderImpl::DoCopySubTextureCHROMIUM(
12482 GLboolean unpack_flip_y
,
12483 GLboolean unpack_premultiply_alpha
,
12484 GLboolean unpack_unmultiply_alpha
) {
12485 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopySubTextureCHROMIUM");
12487 TextureRef
* source_texture_ref
= GetTexture(source_id
);
12488 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
12489 Texture
* source_texture
= source_texture_ref
->texture();
12490 Texture
* dest_texture
= dest_texture_ref
->texture();
12491 int source_width
= 0;
12492 int source_height
= 0;
12493 gfx::GLImage
* image
=
12494 source_texture
->GetLevelImage(source_texture
->target(), 0);
12496 gfx::Size size
= image
->GetSize();
12497 source_width
= size
.width();
12498 source_height
= size
.height();
12499 if (source_width
<= 0 || source_height
<= 0) {
12500 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
12501 "invalid image size");
12505 if (!source_texture
->GetLevelSize(source_texture
->target(), 0,
12506 &source_width
, &source_height
, nullptr)) {
12507 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
12508 "source texture has no level 0");
12512 // Check that this type of texture is allowed.
12513 if (!texture_manager()->ValidForTarget(source_texture
->target(), 0,
12514 source_width
, source_height
, 1)) {
12515 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
12516 "source texture bad dimensions");
12521 GLenum source_type
= 0;
12522 GLenum source_internal_format
= 0;
12523 source_texture
->GetLevelType(source_texture
->target(), 0, &source_type
,
12524 &source_internal_format
);
12525 if (!source_texture
->ValidForTexture(source_texture
->target(), 0, x
, y
, 0,
12526 width
, height
, 1, source_type
)) {
12527 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
12528 "source texture bad dimensions.");
12532 GLenum dest_type
= 0;
12533 GLenum dest_internal_format
= 0;
12534 bool dest_level_defined
= dest_texture
->GetLevelType(
12535 dest_texture
->target(), 0, &dest_type
, &dest_internal_format
);
12536 if (!dest_level_defined
) {
12537 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCopySubTextureCHROMIUM",
12538 "destination texture is not defined");
12541 if (!dest_texture
->ValidForTexture(dest_texture
->target(), 0, xoffset
,
12542 yoffset
, 0, width
, height
, 1, dest_type
)) {
12543 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
12544 "destination texture bad dimensions.");
12548 if (!ValidateCopyTextureCHROMIUM("glCopySubTextureCHROMIUM", target
,
12549 source_texture_ref
, dest_texture_ref
,
12550 dest_internal_format
)) {
12554 // Clear the source texture if necessary.
12555 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref
,
12556 source_texture
->target(), 0)) {
12557 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopySubTextureCHROMIUM",
12558 "source texture dimensions too big");
12562 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12563 // needed because it takes 10s of milliseconds to initialize.
12564 if (!copy_texture_CHROMIUM_
.get()) {
12565 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopySubTextureCHROMIUM");
12566 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
12567 copy_texture_CHROMIUM_
->Initialize(this);
12568 RestoreCurrentFramebufferBindings();
12569 if (LOCAL_PEEK_GL_ERROR("glCopySubTextureCHROMIUM") != GL_NO_ERROR
)
12573 int dest_width
= 0;
12574 int dest_height
= 0;
12575 bool ok
= dest_texture
->GetLevelSize(
12576 GL_TEXTURE_2D
, 0, &dest_width
, &dest_height
, nullptr);
12578 if (xoffset
!= 0 || yoffset
!= 0 || width
!= dest_width
||
12579 height
!= dest_height
) {
12580 gfx::Rect cleared_rect
;
12581 if (CombineAdjacentRects(dest_texture
->GetLevelClearedRect(target
, 0),
12582 gfx::Rect(xoffset
, yoffset
, width
, height
),
12584 DCHECK_GE(cleared_rect
.size().GetArea(),
12585 dest_texture
->GetLevelClearedRect(target
, 0).size().GetArea());
12586 texture_manager()->SetLevelClearedRect(dest_texture_ref
, target
, 0,
12589 // Otherwise clear part of texture level that is not already cleared.
12590 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref
, target
,
12592 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopySubTextureCHROMIUM",
12593 "destination texture dimensions too big");
12598 texture_manager()->SetLevelCleared(dest_texture_ref
, GL_TEXTURE_2D
, 0,
12602 ScopedModifyPixels
modify(dest_texture_ref
);
12604 // Try using GLImage::CopyTexSubImage when possible.
12605 bool unpack_premultiply_alpha_change
=
12606 (unpack_premultiply_alpha
^ unpack_unmultiply_alpha
) != 0;
12607 if (image
&& !unpack_flip_y
&& !unpack_premultiply_alpha_change
) {
12608 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
12609 if (image
->CopyTexSubImage(GL_TEXTURE_2D
, gfx::Point(xoffset
, yoffset
),
12610 gfx::Rect(x
, y
, width
, height
))) {
12615 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
12617 // TODO(hkuang): get the StreamTexture transform matrix in GPU process.
12618 // crbug.com/226218.
12619 copy_texture_CHROMIUM_
->DoCopySubTexture(
12620 this, source_texture
->target(), source_texture
->service_id(),
12621 source_internal_format
, dest_texture
->service_id(), dest_internal_format
,
12622 xoffset
, yoffset
, x
, y
, width
, height
, dest_width
, dest_height
,
12623 source_width
, source_height
,
12624 unpack_flip_y
== GL_TRUE
,
12625 unpack_premultiply_alpha
== GL_TRUE
,
12626 unpack_unmultiply_alpha
== GL_TRUE
);
12628 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
12631 void GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM(GLenum target
,
12634 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM");
12636 TextureRef
* source_texture_ref
= GetTexture(source_id
);
12637 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
12638 Texture
* source_texture
= source_texture_ref
->texture();
12639 Texture
* dest_texture
= dest_texture_ref
->texture();
12640 int source_width
= 0;
12641 int source_height
= 0;
12642 gfx::GLImage
* image
=
12643 source_texture
->GetLevelImage(source_texture
->target(), 0);
12645 gfx::Size size
= image
->GetSize();
12646 source_width
= size
.width();
12647 source_height
= size
.height();
12648 if (source_width
<= 0 || source_height
<= 0) {
12649 LOCAL_SET_GL_ERROR(
12651 "glCompressedCopyTextureCHROMIUM", "invalid image size");
12655 if (!source_texture
->GetLevelSize(source_texture
->target(), 0,
12656 &source_width
, &source_height
, nullptr)) {
12657 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
12658 "glCompressedCopyTextureCHROMIUM",
12659 "source texture has no level 0");
12663 // Check that this type of texture is allowed.
12664 if (!texture_manager()->ValidForTarget(source_texture
->target(), 0,
12665 source_width
, source_height
, 1)) {
12666 LOCAL_SET_GL_ERROR(
12667 GL_INVALID_VALUE
, "glCompressedCopyTextureCHROMIUM",
12673 GLenum source_type
= 0;
12674 GLenum source_internal_format
= 0;
12675 source_texture
->GetLevelType(
12676 source_texture
->target(), 0, &source_type
, &source_internal_format
);
12678 if (dest_texture
->IsImmutable()) {
12679 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12680 "glCompressedCopyTextureCHROMIUM",
12681 "texture is immutable");
12685 if (!ValidateCompressedCopyTextureCHROMIUM(
12686 "glCompressedCopyTextureCHROMIUM",
12688 source_texture_ref
, dest_texture_ref
)) {
12692 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12693 // needed because it takes 10s of milliseconds to initialize.
12694 if (!copy_texture_CHROMIUM_
.get()) {
12695 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12696 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
12697 copy_texture_CHROMIUM_
->Initialize(this);
12698 RestoreCurrentFramebufferBindings();
12699 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR
)
12703 // Clear the source texture if necessary.
12704 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref
,
12705 source_texture
->target(), 0)) {
12706 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCompressedCopyTextureCHROMIUM",
12707 "dimensions too big");
12711 ScopedTextureBinder
binder(
12712 &state_
, dest_texture
->service_id(), GL_TEXTURE_2D
);
12714 ScopedModifyPixels
modify(dest_texture_ref
);
12716 // Try using GLImage::CopyTexImage when possible.
12718 GLenum dest_type
= 0;
12719 GLenum dest_internal_format
= 0;
12720 int dest_width
= 0;
12721 int dest_height
= 0;
12722 bool dest_level_defined
= dest_texture
->GetLevelSize(
12723 GL_TEXTURE_2D
, 0, &dest_width
, &dest_height
, nullptr);
12725 if (dest_level_defined
) {
12726 dest_texture
->GetLevelType(GL_TEXTURE_2D
, 0, &dest_type
,
12727 &dest_internal_format
);
12730 // Resize the destination texture to the dimensions of the source texture.
12731 if (!dest_level_defined
|| dest_width
!= source_width
||
12732 dest_height
!= source_height
||
12733 dest_internal_format
!= source_internal_format
) {
12734 GLsizei source_size
= 0;
12736 bool did_get_size
= GetCompressedTexSizeInBytes(
12737 "glCompressedCopyTextureCHROMIUM", source_width
, source_height
,
12738 1, source_internal_format
, &source_size
);
12739 DCHECK(did_get_size
);
12741 // Ensure that the glCompressedTexImage2D succeeds.
12742 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
12743 glCompressedTexImage2D(GL_TEXTURE_2D
, 0, source_internal_format
,
12744 source_width
, source_height
, 0, source_size
,
12746 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedCopyTextureCHROMIUM");
12747 if (error
!= GL_NO_ERROR
) {
12748 RestoreCurrentTextureBindings(&state_
, GL_TEXTURE_2D
);
12752 texture_manager()->SetLevelInfo(
12753 dest_texture_ref
, GL_TEXTURE_2D
, 0, source_internal_format
,
12754 source_width
, source_height
, 1, 0, source_internal_format
,
12755 source_type
, gfx::Rect(source_width
, source_height
));
12757 texture_manager()->SetLevelCleared(dest_texture_ref
, GL_TEXTURE_2D
, 0,
12761 if (image
->CopyTexSubImage(GL_TEXTURE_2D
, gfx::Point(0, 0),
12762 gfx::Rect(0, 0, source_width
, source_height
))) {
12769 "GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM, fallback");
12771 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
12773 // As a fallback, copy into a non-compressed GL_RGBA texture.
12774 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
12775 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, source_width
, source_height
,
12776 0, GL_RGBA
, GL_UNSIGNED_BYTE
, NULL
);
12777 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedCopyTextureCHROMIUM");
12778 if (error
!= GL_NO_ERROR
) {
12779 RestoreCurrentTextureBindings(&state_
, GL_TEXTURE_2D
);
12783 texture_manager()->SetLevelInfo(
12784 dest_texture_ref
, GL_TEXTURE_2D
, 0, GL_RGBA
, source_width
,
12785 source_height
, 1, 0, GL_RGBA
, GL_UNSIGNED_BYTE
,
12786 gfx::Rect(source_width
, source_height
));
12788 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
12789 // before presenting.
12790 if (source_texture
->target() == GL_TEXTURE_EXTERNAL_OES
) {
12791 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
12792 // instead of using kIdentityMatrix crbug.com/226218.
12793 copy_texture_CHROMIUM_
->DoCopyTextureWithTransform(
12794 this, source_texture
->target(), source_texture
->service_id(),
12795 dest_texture
->service_id(), source_width
, source_height
,
12796 false, false, false, kIdentityMatrix
);
12798 copy_texture_CHROMIUM_
->DoCopyTexture(
12799 this, source_texture
->target(), source_texture
->service_id(),
12800 source_internal_format
, dest_texture
->service_id(), GL_RGBA
,
12801 source_width
, source_height
, false, false, false);
12804 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
12807 static GLenum
ExtractTypeFromStorageFormat(GLenum internalformat
) {
12808 switch (internalformat
) {
12810 return GL_UNSIGNED_BYTE
;
12814 return GL_HALF_FLOAT
;
12818 return GL_UNSIGNED_BYTE
;
12822 return GL_UNSIGNED_SHORT
;
12826 return GL_UNSIGNED_INT
;
12830 return GL_UNSIGNED_BYTE
;
12834 return GL_HALF_FLOAT
;
12838 return GL_UNSIGNED_BYTE
;
12842 return GL_UNSIGNED_SHORT
;
12846 return GL_UNSIGNED_INT
;
12851 return GL_UNSIGNED_BYTE
;
12852 case GL_R11F_G11F_B10F
:
12853 return GL_UNSIGNED_INT_10F_11F_11F_REV
;
12855 return GL_UNSIGNED_SHORT_5_6_5
;
12856 case GL_RGB8_SNORM
:
12859 return GL_UNSIGNED_INT_5_9_9_9_REV
;
12861 return GL_HALF_FLOAT
;
12865 return GL_UNSIGNED_BYTE
;
12869 return GL_UNSIGNED_SHORT
;
12873 return GL_UNSIGNED_INT
;
12877 return GL_UNSIGNED_BYTE
;
12878 case GL_SRGB8_ALPHA8
:
12879 return GL_UNSIGNED_BYTE
;
12880 case GL_RGBA8_SNORM
:
12883 return GL_UNSIGNED_SHORT_4_4_4_4
;
12885 return GL_UNSIGNED_INT_2_10_10_10_REV
;
12887 return GL_UNSIGNED_SHORT_5_5_5_1
;
12889 return GL_HALF_FLOAT
;
12893 return GL_UNSIGNED_BYTE
;
12896 case GL_RGB10_A2UI
:
12897 return GL_UNSIGNED_INT_2_10_10_10_REV
;
12899 return GL_UNSIGNED_SHORT
;
12905 return GL_UNSIGNED_INT
;
12906 case GL_DEPTH_COMPONENT16
:
12907 return GL_UNSIGNED_SHORT
;
12908 case GL_DEPTH_COMPONENT24
:
12909 return GL_UNSIGNED_INT
;
12910 case GL_DEPTH_COMPONENT32F
:
12912 case GL_DEPTH24_STENCIL8
:
12913 return GL_UNSIGNED_INT_24_8
;
12914 case GL_DEPTH32F_STENCIL8
:
12915 return GL_FLOAT_32_UNSIGNED_INT_24_8_REV
;
12916 case GL_LUMINANCE8_ALPHA8_EXT
:
12917 return GL_UNSIGNED_BYTE
;
12918 case GL_LUMINANCE8_EXT
:
12919 return GL_UNSIGNED_BYTE
;
12920 case GL_ALPHA8_EXT
:
12921 return GL_UNSIGNED_BYTE
;
12922 case GL_ALPHA32F_EXT
:
12924 case GL_LUMINANCE32F_EXT
:
12926 case GL_LUMINANCE_ALPHA32F_EXT
:
12928 case GL_ALPHA16F_EXT
:
12929 return GL_HALF_FLOAT_OES
;
12930 case GL_LUMINANCE16F_EXT
:
12931 return GL_HALF_FLOAT_OES
;
12932 case GL_LUMINANCE_ALPHA16F_EXT
:
12933 return GL_HALF_FLOAT_OES
;
12935 return GL_UNSIGNED_BYTE
;
12941 void GLES2DecoderImpl::DoTexStorage2DEXT(
12944 GLenum internal_format
,
12947 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
12948 "width", width
, "height", height
);
12949 if (!texture_manager()->ValidForTarget(target
, 0, width
, height
, 1) ||
12950 TextureManager::ComputeMipMapCount(target
, width
, height
, 1) < levels
) {
12951 LOCAL_SET_GL_ERROR(
12952 GL_INVALID_VALUE
, "glTexStorage2DEXT", "dimensions out of range");
12955 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
12957 if (!texture_ref
) {
12958 LOCAL_SET_GL_ERROR(
12959 GL_INVALID_OPERATION
,
12960 "glTexStorage2DEXT", "unknown texture for target");
12963 Texture
* texture
= texture_ref
->texture();
12964 if (texture
->IsAttachedToFramebuffer()) {
12965 framebuffer_state_
.clear_state_dirty
= true;
12967 if (texture
->IsImmutable()) {
12968 LOCAL_SET_GL_ERROR(
12969 GL_INVALID_OPERATION
,
12970 "glTexStorage2DEXT", "texture is immutable");
12974 GLenum format
= ExtractFormatFromStorageFormat(internal_format
);
12975 GLenum type
= ExtractTypeFromStorageFormat(internal_format
);
12978 GLsizei level_width
= width
;
12979 GLsizei level_height
= height
;
12980 uint32 estimated_size
= 0;
12981 for (int ii
= 0; ii
< levels
; ++ii
) {
12982 uint32 level_size
= 0;
12983 if (!GLES2Util::ComputeImageDataSizes(
12984 level_width
, level_height
, 1, format
, type
, state_
.unpack_alignment
,
12985 &estimated_size
, NULL
, NULL
) ||
12986 !SafeAddUint32(estimated_size
, level_size
, &estimated_size
)) {
12987 LOCAL_SET_GL_ERROR(
12988 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "dimensions too large");
12991 level_width
= std::max(1, level_width
>> 1);
12992 level_height
= std::max(1, level_height
>> 1);
12994 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
12995 LOCAL_SET_GL_ERROR(
12996 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "out of memory");
13001 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
13002 glTexStorage2DEXT(target
, levels
, internal_format
, width
, height
);
13003 GLenum error
= LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
13004 if (error
== GL_NO_ERROR
) {
13005 GLsizei level_width
= width
;
13006 GLsizei level_height
= height
;
13008 GLenum cur_format
= feature_info_
->IsES3Enabled() ?
13009 internal_format
: format
;
13010 for (int ii
= 0; ii
< levels
; ++ii
) {
13011 if (target
== GL_TEXTURE_CUBE_MAP
) {
13012 for (int jj
= 0; jj
< 6; ++jj
) {
13013 GLenum face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ jj
;
13014 texture_manager()->SetLevelInfo(texture_ref
, face
, ii
, cur_format
,
13015 level_width
, level_height
, 1, 0,
13016 format
, type
, gfx::Rect());
13019 texture_manager()->SetLevelInfo(texture_ref
, target
, ii
, cur_format
,
13020 level_width
, level_height
, 1, 0,
13021 format
, type
, gfx::Rect());
13023 level_width
= std::max(1, level_width
>> 1);
13024 level_height
= std::max(1, level_height
>> 1);
13026 texture
->SetImmutable(true);
13030 error::Error
GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
13031 uint32 immediate_data_size
,
13032 const void* cmd_data
) {
13033 return error::kUnknownCommand
;
13036 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target
,
13037 const GLbyte
* data
) {
13038 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
13039 "context", logger_
.GetLogPrefix(),
13040 "mailbox[0]", static_cast<unsigned char>(data
[0]));
13042 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
13044 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref
, target
, data
);
13047 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id
,
13048 GLenum target
, const GLbyte
* data
) {
13049 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
13050 "context", logger_
.GetLogPrefix(),
13051 "mailbox[0]", static_cast<unsigned char>(data
[0]));
13053 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id
),
13057 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name
,
13058 TextureRef
* texture_ref
, GLenum target
, const GLbyte
* data
) {
13059 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
13060 DLOG_IF(ERROR
, !mailbox
.Verify()) << func_name
<< " was passed a "
13061 "mailbox that was not generated by "
13062 "GenMailboxCHROMIUM.";
13064 if (!texture_ref
) {
13065 LOCAL_SET_GL_ERROR(
13066 GL_INVALID_OPERATION
, func_name
.c_str(), "unknown texture for target");
13070 Texture
* produced
= texture_manager()->Produce(texture_ref
);
13072 LOCAL_SET_GL_ERROR(
13073 GL_INVALID_OPERATION
, func_name
.c_str(), "invalid texture");
13077 if (produced
->target() != target
) {
13078 LOCAL_SET_GL_ERROR(
13079 GL_INVALID_OPERATION
, func_name
.c_str(), "invalid target");
13083 group_
->mailbox_manager()->ProduceTexture(mailbox
, produced
);
13086 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target
,
13087 const GLbyte
* data
) {
13088 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
13089 "context", logger_
.GetLogPrefix(),
13090 "mailbox[0]", static_cast<unsigned char>(data
[0]));
13091 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
13092 DLOG_IF(ERROR
, !mailbox
.Verify()) << "ConsumeTextureCHROMIUM was passed a "
13093 "mailbox that was not generated by "
13094 "GenMailboxCHROMIUM.";
13096 scoped_refptr
<TextureRef
> texture_ref
=
13097 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
13098 if (!texture_ref
.get()) {
13099 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
13100 "glConsumeTextureCHROMIUM",
13101 "unknown texture for target");
13104 GLuint client_id
= texture_ref
->client_id();
13106 LOCAL_SET_GL_ERROR(
13107 GL_INVALID_OPERATION
,
13108 "glConsumeTextureCHROMIUM", "unknown texture for target");
13111 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(mailbox
);
13113 LOCAL_SET_GL_ERROR(
13114 GL_INVALID_OPERATION
,
13115 "glConsumeTextureCHROMIUM", "invalid mailbox name");
13118 if (texture
->target() != target
) {
13119 LOCAL_SET_GL_ERROR(
13120 GL_INVALID_OPERATION
,
13121 "glConsumeTextureCHROMIUM", "invalid target");
13125 DeleteTexturesHelper(1, &client_id
);
13126 texture_ref
= texture_manager()->Consume(client_id
, texture
);
13127 glBindTexture(target
, texture_ref
->service_id());
13129 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
13130 unit
.bind_target
= target
;
13132 case GL_TEXTURE_2D
:
13133 unit
.bound_texture_2d
= texture_ref
;
13135 case GL_TEXTURE_CUBE_MAP
:
13136 unit
.bound_texture_cube_map
= texture_ref
;
13138 case GL_TEXTURE_EXTERNAL_OES
:
13139 unit
.bound_texture_external_oes
= texture_ref
;
13141 case GL_TEXTURE_RECTANGLE_ARB
:
13142 unit
.bound_texture_rectangle_arb
= texture_ref
;
13145 NOTREACHED(); // Validation should prevent us getting here.
13150 void GLES2DecoderImpl::EnsureTextureForClientId(
13152 GLuint client_id
) {
13153 TextureRef
* texture_ref
= GetTexture(client_id
);
13154 if (!texture_ref
) {
13156 glGenTextures(1, &service_id
);
13157 DCHECK_NE(0u, service_id
);
13158 texture_ref
= CreateTexture(client_id
, service_id
);
13159 texture_manager()->SetTarget(texture_ref
, target
);
13160 glBindTexture(target
, service_id
);
13161 RestoreCurrentTextureBindings(&state_
, target
);
13165 // If CreateAndConsumeTexture fails we still need to ensure that the client_id
13166 // provided is associated with a service_id/TextureRef for consistency, even if
13167 // the resulting texture is incomplete.
13168 error::Error
GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
13169 uint32_t immediate_data_size
,
13170 const void* cmd_data
) {
13171 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate
& c
=
13173 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate
*>(
13175 GLenum target
= static_cast<GLenum
>(c
.target
);
13176 uint32_t data_size
;
13177 if (!ComputeDataSize(1, sizeof(GLbyte
), 64, &data_size
)) {
13178 return error::kOutOfBounds
;
13180 if (data_size
> immediate_data_size
) {
13181 return error::kOutOfBounds
;
13183 const GLbyte
* mailbox
=
13184 GetImmediateDataAs
<const GLbyte
*>(c
, data_size
, immediate_data_size
);
13185 if (!validators_
->texture_bind_target
.IsValid(target
)) {
13186 LOCAL_SET_GL_ERROR_INVALID_ENUM(
13187 "glCreateAndConsumeTextureCHROMIUM", target
, "target");
13188 return error::kNoError
;
13190 if (mailbox
== NULL
) {
13191 return error::kOutOfBounds
;
13193 uint32_t client_id
= c
.client_id
;
13194 DoCreateAndConsumeTextureCHROMIUM(target
, mailbox
, client_id
);
13195 return error::kNoError
;
13198 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target
,
13199 const GLbyte
* data
, GLuint client_id
) {
13200 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
13201 "context", logger_
.GetLogPrefix(),
13202 "mailbox[0]", static_cast<unsigned char>(data
[0]));
13203 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
13204 DLOG_IF(ERROR
, !mailbox
.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
13205 "passed a mailbox that was not "
13206 "generated by GenMailboxCHROMIUM.";
13208 TextureRef
* texture_ref
= GetTexture(client_id
);
13210 // No need to call EnsureTextureForClientId here, the client_id already has
13211 // an associated texture.
13212 LOCAL_SET_GL_ERROR(
13213 GL_INVALID_OPERATION
,
13214 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
13217 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(mailbox
);
13219 EnsureTextureForClientId(target
, client_id
);
13220 LOCAL_SET_GL_ERROR(
13221 GL_INVALID_OPERATION
,
13222 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
13226 if (texture
->target() != target
) {
13227 EnsureTextureForClientId(target
, client_id
);
13228 LOCAL_SET_GL_ERROR(
13229 GL_INVALID_OPERATION
,
13230 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
13234 texture_ref
= texture_manager()->Consume(client_id
, texture
);
13237 bool GLES2DecoderImpl::DoIsValuebufferCHROMIUM(GLuint client_id
) {
13238 const Valuebuffer
* valuebuffer
= GetValuebuffer(client_id
);
13239 return valuebuffer
&& valuebuffer
->IsValid();
13242 void GLES2DecoderImpl::DoBindValueBufferCHROMIUM(GLenum target
,
13243 GLuint client_id
) {
13244 Valuebuffer
* valuebuffer
= NULL
;
13245 if (client_id
!= 0) {
13246 valuebuffer
= GetValuebuffer(client_id
);
13247 if (!valuebuffer
) {
13248 if (!group_
->bind_generates_resource()) {
13249 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glBindValuebufferCHROMIUM",
13250 "id not generated by glBindValuebufferCHROMIUM");
13254 // It's a new id so make a valuebuffer for it.
13255 CreateValuebuffer(client_id
);
13256 valuebuffer
= GetValuebuffer(client_id
);
13258 valuebuffer
->MarkAsValid();
13260 state_
.bound_valuebuffer
= valuebuffer
;
13263 void GLES2DecoderImpl::DoSubscribeValueCHROMIUM(GLenum target
,
13264 GLenum subscription
) {
13265 if (!CheckCurrentValuebuffer("glSubscribeValueCHROMIUM")) {
13268 state_
.bound_valuebuffer
.get()->AddSubscription(subscription
);
13271 void GLES2DecoderImpl::DoPopulateSubscribedValuesCHROMIUM(GLenum target
) {
13272 if (!CheckCurrentValuebuffer("glPopulateSubscribedValuesCHROMIUM")) {
13275 valuebuffer_manager()->UpdateValuebufferState(state_
.bound_valuebuffer
.get());
13278 void GLES2DecoderImpl::DoUniformValueBufferCHROMIUM(GLint location
,
13280 GLenum subscription
) {
13281 if (!CheckCurrentValuebufferForSubscription(
13282 subscription
, "glPopulateSubscribedValuesCHROMIUM")) {
13285 if (!CheckSubscriptionTarget(location
, subscription
,
13286 "glPopulateSubscribedValuesCHROMIUM")) {
13289 const ValueState
* state
=
13290 state_
.bound_valuebuffer
.get()->GetState(subscription
);
13292 switch (subscription
) {
13293 case GL_MOUSE_POSITION_CHROMIUM
:
13294 DoUniform2iv(location
, 1, state
->int_value
);
13297 NOTREACHED() << "Unhandled uniform subscription target "
13304 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
13305 GLsizei length
, const GLchar
* marker
) {
13309 debug_marker_manager_
.SetMarker(
13310 length
? std::string(marker
, length
) : std::string(marker
));
13313 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
13314 GLsizei
/*length*/, const GLchar
* /*marker*/) {
13317 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
13320 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
13321 GLenum target
, GLint image_id
) {
13322 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
13324 if (target
== GL_TEXTURE_CUBE_MAP
) {
13325 LOCAL_SET_GL_ERROR(
13327 "glBindTexImage2DCHROMIUM", "invalid target");
13331 // Default target might be conceptually valid, but disallow it to avoid
13333 TextureRef
* texture_ref
=
13334 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
13335 if (!texture_ref
) {
13336 LOCAL_SET_GL_ERROR(
13337 GL_INVALID_OPERATION
,
13338 "glBindTexImage2DCHROMIUM", "no texture bound");
13342 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
13344 LOCAL_SET_GL_ERROR(
13345 GL_INVALID_OPERATION
,
13346 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
13351 ScopedGLErrorSuppressor
suppressor(
13352 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
13353 if (!gl_image
->BindTexImage(target
)) {
13354 LOCAL_SET_GL_ERROR(
13355 GL_INVALID_OPERATION
,
13356 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
13361 gfx::Size size
= gl_image
->GetSize();
13362 texture_manager()->SetLevelInfo(
13363 texture_ref
, target
, 0, gl_image
->GetInternalFormat(), size
.width(),
13364 size
.height(), 1, 0, gl_image
->GetInternalFormat(), GL_UNSIGNED_BYTE
,
13366 texture_manager()->SetLevelImage(texture_ref
, target
, 0, gl_image
);
13369 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
13370 GLenum target
, GLint image_id
) {
13371 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
13373 // Default target might be conceptually valid, but disallow it to avoid
13375 TextureRef
* texture_ref
=
13376 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
13377 if (!texture_ref
) {
13378 LOCAL_SET_GL_ERROR(
13379 GL_INVALID_OPERATION
,
13380 "glReleaseTexImage2DCHROMIUM", "no texture bound");
13384 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
13386 LOCAL_SET_GL_ERROR(
13387 GL_INVALID_OPERATION
,
13388 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
13392 // Do nothing when image is not currently bound.
13393 if (texture_ref
->texture()->GetLevelImage(target
, 0) != gl_image
)
13397 ScopedGLErrorSuppressor
suppressor(
13398 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
13399 gl_image
->ReleaseTexImage(target
);
13402 texture_manager()->SetLevelInfo(
13403 texture_ref
, target
, 0, gl_image
->GetInternalFormat(), 0, 0, 1, 0,
13404 gl_image
->GetInternalFormat(), GL_UNSIGNED_BYTE
, gfx::Rect());
13407 error::Error
GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
13408 uint32 immediate_data_size
,
13409 const void* cmd_data
) {
13410 const gles2::cmds::TraceBeginCHROMIUM
& c
=
13411 *static_cast<const gles2::cmds::TraceBeginCHROMIUM
*>(cmd_data
);
13412 Bucket
* category_bucket
= GetBucket(c
.category_bucket_id
);
13413 Bucket
* name_bucket
= GetBucket(c
.name_bucket_id
);
13414 if (!category_bucket
|| category_bucket
->size() == 0 ||
13415 !name_bucket
|| name_bucket
->size() == 0) {
13416 return error::kInvalidArguments
;
13419 std::string category_name
;
13420 std::string trace_name
;
13421 if (!category_bucket
->GetAsString(&category_name
) ||
13422 !name_bucket
->GetAsString(&trace_name
)) {
13423 return error::kInvalidArguments
;
13426 debug_marker_manager_
.PushGroup(trace_name
);
13427 if (!gpu_tracer_
->Begin(category_name
, trace_name
, kTraceCHROMIUM
)) {
13428 LOCAL_SET_GL_ERROR(
13429 GL_INVALID_OPERATION
,
13430 "glTraceBeginCHROMIUM", "unable to create begin trace");
13431 return error::kNoError
;
13433 return error::kNoError
;
13436 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
13437 debug_marker_manager_
.PopGroup();
13438 if (!gpu_tracer_
->End(kTraceCHROMIUM
)) {
13439 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
13440 "glTraceEndCHROMIUM", "no trace begin found");
13445 void GLES2DecoderImpl::DoDrawBuffersEXT(
13446 GLsizei count
, const GLenum
* bufs
) {
13447 if (count
> static_cast<GLsizei
>(group_
->max_draw_buffers())) {
13448 LOCAL_SET_GL_ERROR(
13450 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
13454 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
13456 for (GLsizei i
= 0; i
< count
; ++i
) {
13457 if (bufs
[i
] != static_cast<GLenum
>(GL_COLOR_ATTACHMENT0
+ i
) &&
13458 bufs
[i
] != GL_NONE
) {
13459 LOCAL_SET_GL_ERROR(
13460 GL_INVALID_OPERATION
,
13461 "glDrawBuffersEXT",
13462 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
13466 glDrawBuffersARB(count
, bufs
);
13467 framebuffer
->SetDrawBuffers(count
, bufs
);
13468 } else { // backbuffer
13470 (bufs
[0] != GL_BACK
&& bufs
[0] != GL_NONE
)) {
13471 LOCAL_SET_GL_ERROR(
13472 GL_INVALID_OPERATION
,
13473 "glDrawBuffersEXT",
13474 "more than one buffer or bufs not GL_NONE or GL_BACK");
13477 GLenum mapped_buf
= bufs
[0];
13478 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
13479 bufs
[0] == GL_BACK
) {
13480 mapped_buf
= GL_COLOR_ATTACHMENT0
;
13482 glDrawBuffersARB(count
, &mapped_buf
);
13483 back_buffer_draw_buffer_
= bufs
[0];
13487 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current
, GLenum other
) {
13488 MarkContextLost(GetContextLostReasonFromResetStatus(current
));
13489 group_
->LoseContexts(GetContextLostReasonFromResetStatus(other
));
13490 reset_by_robustness_extension_
= true;
13493 void GLES2DecoderImpl::DoFlushDriverCachesCHROMIUM(void) {
13494 // On Adreno Android devices we need to use a workaround to force caches to
13496 if (feature_info_
->workarounds().unbind_egl_context_to_flush_driver_caches
) {
13497 context_
->ReleaseCurrent(nullptr);
13498 context_
->MakeCurrent(surface_
.get());
13502 void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode
,
13503 const GLfloat
* matrix
) {
13504 DCHECK(matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
||
13505 matrix_mode
== GL_PATH_MODELVIEW_CHROMIUM
);
13506 if (!features().chromium_path_rendering
) {
13507 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
13508 "glMatrixLoadfCHROMIUM",
13509 "function not available");
13513 GLfloat
* target_matrix
= matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
13514 ? state_
.projection_matrix
13515 : state_
.modelview_matrix
;
13516 memcpy(target_matrix
, matrix
, sizeof(GLfloat
) * 16);
13517 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
13518 // since the values of the _NV and _CHROMIUM tokens match.
13519 glMatrixLoadfEXT(matrix_mode
, matrix
);
13522 void GLES2DecoderImpl::DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode
) {
13523 DCHECK(matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
||
13524 matrix_mode
== GL_PATH_MODELVIEW_CHROMIUM
);
13526 if (!features().chromium_path_rendering
) {
13527 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
13528 "glMatrixLoadIdentityCHROMIUM",
13529 "function not available");
13533 GLfloat
* target_matrix
= matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
13534 ? state_
.projection_matrix
13535 : state_
.modelview_matrix
;
13536 memcpy(target_matrix
, kIdentityMatrix
, sizeof(kIdentityMatrix
));
13537 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
13538 // since the values of the _NV and _CHROMIUM tokens match.
13539 glMatrixLoadIdentityEXT(matrix_mode
);
13542 bool GLES2DecoderImpl::ValidateAsyncTransfer(
13543 const char* function_name
,
13544 TextureRef
* texture_ref
,
13547 const void * data
) {
13548 // We only support async uploads to 2D textures for now.
13549 if (GL_TEXTURE_2D
!= target
) {
13550 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
13553 // We only support uploads to level zero for now.
13555 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "level != 0");
13558 // A transfer buffer must be bound, even for asyncTexImage2D.
13559 if (data
== NULL
) {
13560 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
, "buffer == 0");
13563 // We only support one async transfer in progress.
13564 if (!texture_ref
||
13565 async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
13566 LOCAL_SET_GL_ERROR(
13567 GL_INVALID_OPERATION
,
13568 function_name
, "transfer already in progress");
13574 base::Closure
GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
13575 uint32 async_upload_token
,
13576 uint32 sync_data_shm_id
,
13577 uint32 sync_data_shm_offset
) {
13578 scoped_refptr
<gpu::Buffer
> buffer
= GetSharedMemoryBuffer(sync_data_shm_id
);
13579 if (!buffer
.get() ||
13580 !buffer
->GetDataAddress(sync_data_shm_offset
, sizeof(AsyncUploadSync
)))
13581 return base::Closure();
13583 AsyncMemoryParams
mem_params(buffer
,
13584 sync_data_shm_offset
,
13585 sizeof(AsyncUploadSync
));
13587 scoped_refptr
<AsyncUploadTokenCompletionObserver
> observer(
13588 new AsyncUploadTokenCompletionObserver(async_upload_token
));
13591 &AsyncPixelTransferManager::AsyncNotifyCompletion
,
13592 base::Unretained(GetAsyncPixelTransferManager()),
13597 error::Error
GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
13598 uint32 immediate_data_size
,
13599 const void* cmd_data
) {
13600 const gles2::cmds::AsyncTexImage2DCHROMIUM
& c
=
13601 *static_cast<const gles2::cmds::AsyncTexImage2DCHROMIUM
*>(cmd_data
);
13602 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
13603 GLenum target
= static_cast<GLenum
>(c
.target
);
13604 GLint level
= static_cast<GLint
>(c
.level
);
13605 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
13606 GLsizei width
= static_cast<GLsizei
>(c
.width
);
13607 GLsizei height
= static_cast<GLsizei
>(c
.height
);
13608 GLint border
= static_cast<GLint
>(c
.border
);
13609 GLenum format
= static_cast<GLenum
>(c
.format
);
13610 GLenum type
= static_cast<GLenum
>(c
.type
);
13611 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
13612 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
13613 uint32 pixels_size
;
13614 uint32 async_upload_token
= static_cast<uint32
>(c
.async_upload_token
);
13615 uint32 sync_data_shm_id
= static_cast<uint32
>(c
.sync_data_shm_id
);
13616 uint32 sync_data_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
13618 base::ScopedClosureRunner scoped_completion_callback
;
13619 if (async_upload_token
) {
13620 base::Closure completion_closure
=
13621 AsyncUploadTokenCompletionClosure(async_upload_token
,
13623 sync_data_shm_offset
);
13624 if (completion_closure
.is_null())
13625 return error::kInvalidArguments
;
13627 scoped_completion_callback
.Reset(completion_closure
);
13630 // TODO(epenner): Move this and copies of this memory validation
13631 // into ValidateTexImage2D step.
13632 if (!GLES2Util::ComputeImageDataSizes(
13633 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
13635 return error::kOutOfBounds
;
13637 const void* pixels
= NULL
;
13638 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
13639 pixels
= GetSharedMemoryAs
<const void*>(
13640 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
13642 return error::kOutOfBounds
;
13646 TextureManager::DoTexImageArguments args
= {
13647 target
, level
, internal_format
, width
, height
, 1, border
, format
, type
,
13648 pixels
, pixels_size
, TextureManager::DoTexImageArguments::kTexImage2D
};
13649 TextureRef
* texture_ref
;
13650 // All the normal glTexSubImage2D validation.
13651 if (!texture_manager()->ValidateTexImage(
13652 &state_
, "glAsyncTexImage2DCHROMIUM", args
, &texture_ref
)) {
13653 return error::kNoError
;
13656 // Extra async validation.
13657 Texture
* texture
= texture_ref
->texture();
13658 if (!ValidateAsyncTransfer(
13659 "glAsyncTexImage2DCHROMIUM", texture_ref
, target
, level
, pixels
))
13660 return error::kNoError
;
13662 // Don't allow async redefinition of a textures.
13663 if (texture
->IsDefined()) {
13664 LOCAL_SET_GL_ERROR(
13665 GL_INVALID_OPERATION
,
13666 "glAsyncTexImage2DCHROMIUM", "already defined");
13667 return error::kNoError
;
13670 if (!EnsureGPUMemoryAvailable(pixels_size
)) {
13671 LOCAL_SET_GL_ERROR(
13672 GL_OUT_OF_MEMORY
, "glAsyncTexImage2DCHROMIUM", "out of memory");
13673 return error::kNoError
;
13676 // Setup the parameters.
13677 AsyncTexImage2DParams tex_params
= {
13678 target
, level
, static_cast<GLenum
>(internal_format
),
13679 width
, height
, border
, format
, type
};
13680 AsyncMemoryParams
mem_params(
13681 GetSharedMemoryBuffer(c
.pixels_shm_id
), c
.pixels_shm_offset
, pixels_size
);
13683 // Set up the async state if needed, and make the texture
13684 // immutable so the async state stays valid. The level info
13685 // is set up lazily when the transfer completes.
13686 AsyncPixelTransferDelegate
* delegate
=
13687 async_pixel_transfer_manager_
->CreatePixelTransferDelegate(texture_ref
,
13689 texture
->SetImmutable(true);
13691 delegate
->AsyncTexImage2D(
13694 base::Bind(&TextureManager::SetLevelInfoFromParams
,
13695 // The callback is only invoked if the transfer delegate still
13696 // exists, which implies through manager->texture_ref->state
13697 // ownership that both of these pointers are valid.
13698 base::Unretained(texture_manager()),
13699 base::Unretained(texture_ref
),
13701 return error::kNoError
;
13704 error::Error
GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
13705 uint32 immediate_data_size
,
13706 const void* cmd_data
) {
13707 const gles2::cmds::AsyncTexSubImage2DCHROMIUM
& c
=
13708 *static_cast<const gles2::cmds::AsyncTexSubImage2DCHROMIUM
*>(cmd_data
);
13709 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
13710 GLenum target
= static_cast<GLenum
>(c
.target
);
13711 GLint level
= static_cast<GLint
>(c
.level
);
13712 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
13713 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
13714 GLsizei width
= static_cast<GLsizei
>(c
.width
);
13715 GLsizei height
= static_cast<GLsizei
>(c
.height
);
13716 GLenum format
= static_cast<GLenum
>(c
.format
);
13717 GLenum type
= static_cast<GLenum
>(c
.type
);
13718 uint32 async_upload_token
= static_cast<uint32
>(c
.async_upload_token
);
13719 uint32 sync_data_shm_id
= static_cast<uint32
>(c
.sync_data_shm_id
);
13720 uint32 sync_data_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
13722 base::ScopedClosureRunner scoped_completion_callback
;
13723 if (async_upload_token
) {
13724 base::Closure completion_closure
=
13725 AsyncUploadTokenCompletionClosure(async_upload_token
,
13727 sync_data_shm_offset
);
13728 if (completion_closure
.is_null())
13729 return error::kInvalidArguments
;
13731 scoped_completion_callback
.Reset(completion_closure
);
13734 // TODO(epenner): Move this and copies of this memory validation
13735 // into ValidateTexSubImage2D step.
13737 if (!GLES2Util::ComputeImageDataSizes(
13738 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &data_size
,
13740 return error::kOutOfBounds
;
13742 const void* pixels
= GetSharedMemoryAs
<const void*>(
13743 c
.data_shm_id
, c
.data_shm_offset
, data_size
);
13745 // All the normal glTexSubImage2D validation.
13746 error::Error error
= error::kNoError
;
13747 if (!ValidateTexSubImage2D(&error
, "glAsyncTexSubImage2DCHROMIUM",
13748 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
)) {
13752 // Extra async validation.
13753 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
13755 Texture
* texture
= texture_ref
->texture();
13756 if (!ValidateAsyncTransfer(
13757 "glAsyncTexSubImage2DCHROMIUM", texture_ref
, target
, level
, pixels
))
13758 return error::kNoError
;
13760 // Guarantee async textures are always 'cleared' as follows:
13761 // - AsyncTexImage2D can not redefine an existing texture
13762 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
13763 // - AsyncTexSubImage2D clears synchronously if not already cleared.
13764 // - Textures become immutable after an async call.
13765 // This way we know in all cases that an async texture is always clear.
13766 if (!texture
->SafeToRenderFrom()) {
13767 if (!texture_manager()->ClearTextureLevel(this, texture_ref
,
13769 LOCAL_SET_GL_ERROR(
13771 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
13772 return error::kNoError
;
13776 // Setup the parameters.
13777 AsyncTexSubImage2DParams tex_params
= {target
, level
, xoffset
, yoffset
,
13778 width
, height
, format
, type
};
13779 AsyncMemoryParams
mem_params(
13780 GetSharedMemoryBuffer(c
.data_shm_id
), c
.data_shm_offset
, data_size
);
13781 AsyncPixelTransferDelegate
* delegate
=
13782 async_pixel_transfer_manager_
->GetPixelTransferDelegate(texture_ref
);
13784 // TODO(epenner): We may want to enforce exclusive use
13785 // of async APIs in which case this should become an error,
13786 // (the texture should have been async defined).
13787 AsyncTexImage2DParams define_params
= {target
, level
,
13789 texture
->GetLevelSize(
13790 target
, level
, &define_params
.width
, &define_params
.height
, nullptr);
13791 texture
->GetLevelType(
13792 target
, level
, &define_params
.type
, &define_params
.internal_format
);
13793 // Set up the async state if needed, and make the texture
13794 // immutable so the async state stays valid.
13795 delegate
= async_pixel_transfer_manager_
->CreatePixelTransferDelegate(
13796 texture_ref
, define_params
);
13797 texture
->SetImmutable(true);
13800 delegate
->AsyncTexSubImage2D(tex_params
, mem_params
);
13801 return error::kNoError
;
13804 error::Error
GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
13805 uint32 immediate_data_size
,
13806 const void* cmd_data
) {
13807 const gles2::cmds::WaitAsyncTexImage2DCHROMIUM
& c
=
13808 *static_cast<const gles2::cmds::WaitAsyncTexImage2DCHROMIUM
*>(cmd_data
);
13809 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
13810 GLenum target
= static_cast<GLenum
>(c
.target
);
13812 if (GL_TEXTURE_2D
!= target
) {
13813 LOCAL_SET_GL_ERROR(
13814 GL_INVALID_ENUM
, "glWaitAsyncTexImage2DCHROMIUM", "target");
13815 return error::kNoError
;
13817 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
13819 if (!texture_ref
) {
13820 LOCAL_SET_GL_ERROR(
13821 GL_INVALID_OPERATION
,
13822 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
13823 return error::kNoError
;
13825 AsyncPixelTransferDelegate
* delegate
=
13826 async_pixel_transfer_manager_
->GetPixelTransferDelegate(texture_ref
);
13828 LOCAL_SET_GL_ERROR(
13829 GL_INVALID_OPERATION
,
13830 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
13831 return error::kNoError
;
13833 delegate
->WaitForTransferCompletion();
13834 ProcessFinishedAsyncTransfers();
13835 return error::kNoError
;
13838 error::Error
GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
13839 uint32 immediate_data_size
,
13840 const void* data
) {
13841 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
13843 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
13844 ProcessFinishedAsyncTransfers();
13845 return error::kNoError
;
13848 error::Error
GLES2DecoderImpl::HandleUniformBlockBinding(
13849 uint32_t immediate_data_size
, const void* cmd_data
) {
13850 if (!unsafe_es3_apis_enabled())
13851 return error::kUnknownCommand
;
13852 const gles2::cmds::UniformBlockBinding
& c
=
13853 *static_cast<const gles2::cmds::UniformBlockBinding
*>(cmd_data
);
13854 GLuint client_id
= c
.program
;
13855 GLuint index
= static_cast<GLuint
>(c
.index
);
13856 GLuint binding
= static_cast<GLuint
>(c
.binding
);
13857 Program
* program
= GetProgramInfoNotShader(
13858 client_id
, "glUniformBlockBinding");
13860 return error::kNoError
;
13862 GLuint service_id
= program
->service_id();
13863 glUniformBlockBinding(service_id
, index
, binding
);
13864 return error::kNoError
;
13867 error::Error
GLES2DecoderImpl::HandleClientWaitSync(
13868 uint32_t immediate_data_size
, const void* cmd_data
) {
13869 if (!unsafe_es3_apis_enabled())
13870 return error::kUnknownCommand
;
13871 const gles2::cmds::ClientWaitSync
& c
=
13872 *static_cast<const gles2::cmds::ClientWaitSync
*>(cmd_data
);
13873 GLuint sync
= static_cast<GLuint
>(c
.sync
);
13874 GLbitfield flags
= static_cast<GLbitfield
>(c
.flags
);
13875 GLuint64 timeout
= GLES2Util::MapTwoUint32ToUint64(c
.timeout_0
, c
.timeout_1
);
13876 typedef cmds::ClientWaitSync::Result Result
;
13877 Result
* result_dst
= GetSharedMemoryAs
<Result
*>(
13878 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result_dst
));
13880 return error::kOutOfBounds
;
13882 if (*result_dst
!= GL_WAIT_FAILED
) {
13883 return error::kInvalidArguments
;
13885 GLsync service_sync
= 0;
13886 if (!group_
->GetSyncServiceId(sync
, &service_sync
)) {
13887 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "ClientWaitSync", "invalid sync");
13888 return error::kNoError
;
13890 *result_dst
= glClientWaitSync(service_sync
, flags
, timeout
);
13891 return error::kNoError
;
13894 error::Error
GLES2DecoderImpl::HandleWaitSync(
13895 uint32_t immediate_data_size
, const void* cmd_data
) {
13896 if (!unsafe_es3_apis_enabled())
13897 return error::kUnknownCommand
;
13898 const gles2::cmds::WaitSync
& c
=
13899 *static_cast<const gles2::cmds::WaitSync
*>(cmd_data
);
13900 GLuint sync
= static_cast<GLuint
>(c
.sync
);
13901 GLbitfield flags
= static_cast<GLbitfield
>(c
.flags
);
13902 GLuint64 timeout
= GLES2Util::MapTwoUint32ToUint64(c
.timeout_0
, c
.timeout_1
);
13903 GLsync service_sync
= 0;
13904 if (!group_
->GetSyncServiceId(sync
, &service_sync
)) {
13905 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "WaitSync", "invalid sync");
13906 return error::kNoError
;
13908 glWaitSync(service_sync
, flags
, timeout
);
13909 return error::kNoError
;
13912 error::Error
GLES2DecoderImpl::HandleGetInternalformativ(
13913 uint32_t immediate_data_size
, const void* cmd_data
) {
13914 if (!unsafe_es3_apis_enabled())
13915 return error::kUnknownCommand
;
13916 const gles2::cmds::GetInternalformativ
& c
=
13917 *static_cast<const gles2::cmds::GetInternalformativ
*>(cmd_data
);
13918 GLenum target
= static_cast<GLenum
>(c
.target
);
13919 GLenum format
= static_cast<GLenum
>(c
.format
);
13920 GLenum pname
= static_cast<GLenum
>(c
.pname
);
13921 if (!validators_
->render_buffer_target
.IsValid(target
)) {
13922 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", target
, "target");
13923 return error::kNoError
;
13925 if (!validators_
->render_buffer_format
.IsValid(format
)) {
13926 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", format
, "format");
13927 return error::kNoError
;
13929 if (!validators_
->internal_format_parameter
.IsValid(pname
)) {
13930 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", pname
, "pname");
13931 return error::kNoError
;
13933 typedef cmds::GetInternalformativ::Result Result
;
13934 GLsizei num_values
= 0;
13936 case GL_NUM_SAMPLE_COUNTS
:
13942 glGetInternalformativ(target
, format
, GL_NUM_SAMPLE_COUNTS
, 1, &value
);
13943 num_values
= static_cast<GLsizei
>(value
);
13950 Result
* result
= GetSharedMemoryAs
<Result
*>(
13951 c
.params_shm_id
, c
.params_shm_offset
, Result::ComputeSize(num_values
));
13952 GLint
* params
= result
? result
->GetData() : NULL
;
13953 if (params
== NULL
) {
13954 return error::kOutOfBounds
;
13956 // Check that the client initialized the result.
13957 if (result
->size
!= 0) {
13958 return error::kInvalidArguments
;
13960 glGetInternalformativ(target
, format
, pname
, num_values
, params
);
13961 result
->SetNumResults(num_values
);
13962 return error::kNoError
;
13965 error::Error
GLES2DecoderImpl::HandleMapBufferRange(
13966 uint32_t immediate_data_size
, const void* cmd_data
) {
13967 if (!unsafe_es3_apis_enabled()) {
13968 return error::kUnknownCommand
;
13970 const gles2::cmds::MapBufferRange
& c
=
13971 *static_cast<const gles2::cmds::MapBufferRange
*>(cmd_data
);
13972 GLenum target
= static_cast<GLenum
>(c
.target
);
13973 GLbitfield access
= static_cast<GLbitfield
>(c
.access
);
13974 GLintptr offset
= static_cast<GLintptr
>(c
.offset
);
13975 GLsizeiptr size
= static_cast<GLsizeiptr
>(c
.size
);
13977 typedef cmds::MapBufferRange::Result Result
;
13978 Result
* result
= GetSharedMemoryAs
<Result
*>(
13979 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
13981 return error::kOutOfBounds
;
13983 if (*result
!= 0) {
13985 return error::kInvalidArguments
;
13988 GetSharedMemoryAs
<int8_t*>(c
.data_shm_id
, c
.data_shm_offset
, size
);
13990 return error::kOutOfBounds
;
13993 GLbitfield mask
= GL_MAP_INVALIDATE_BUFFER_BIT
;
13994 if ((access
& mask
) == mask
) {
13995 // TODO(zmo): To be on the safe side, always map
13996 // GL_MAP_INVALIDATE_BUFFER_BIT to GL_MAP_INVALIDATE_RANGE_BIT.
13997 access
= (access
& ~GL_MAP_INVALIDATE_BUFFER_BIT
);
13998 access
= (access
| GL_MAP_INVALIDATE_RANGE_BIT
);
14000 // TODO(zmo): Always filter out GL_MAP_UNSYNCHRONIZED_BIT to get rid of
14001 // undefined behaviors.
14002 mask
= GL_MAP_READ_BIT
| GL_MAP_UNSYNCHRONIZED_BIT
;
14003 if ((access
& mask
) == mask
) {
14004 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "MapBufferRange",
14005 "incompatible access bits");
14006 return error::kNoError
;
14008 access
= (access
& ~GL_MAP_UNSYNCHRONIZED_BIT
);
14009 if ((access
& GL_MAP_WRITE_BIT
) == GL_MAP_WRITE_BIT
&&
14010 (access
& GL_MAP_INVALIDATE_RANGE_BIT
) == 0) {
14011 access
= (access
| GL_MAP_READ_BIT
);
14013 void* ptr
= glMapBufferRange(target
, offset
, size
, access
);
14014 if (ptr
== nullptr) {
14015 return error::kNoError
;
14017 Buffer
* buffer
= buffer_manager()->GetBufferInfoForTarget(&state_
, target
);
14019 buffer
->SetMappedRange(offset
, size
, access
, ptr
,
14020 GetSharedMemoryBuffer(c
.data_shm_id
));
14021 if ((access
& GL_MAP_INVALIDATE_RANGE_BIT
) == 0) {
14022 memcpy(mem
, ptr
, size
);
14025 return error::kNoError
;
14028 error::Error
GLES2DecoderImpl::HandleUnmapBuffer(
14029 uint32_t immediate_data_size
, const void* cmd_data
) {
14030 if (!unsafe_es3_apis_enabled()) {
14031 return error::kUnknownCommand
;
14033 const gles2::cmds::UnmapBuffer
& c
=
14034 *static_cast<const gles2::cmds::UnmapBuffer
*>(cmd_data
);
14035 GLenum target
= static_cast<GLenum
>(c
.target
);
14037 Buffer
* buffer
= buffer_manager()->GetBufferInfoForTarget(&state_
, target
);
14039 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "UnmapBuffer", "no buffer bound");
14040 return error::kNoError
;
14042 const Buffer::MappedRange
* mapped_range
= buffer
->GetMappedRange();
14043 if (!mapped_range
) {
14044 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "UnmapBuffer",
14045 "buffer is unmapped");
14046 return error::kNoError
;
14048 if ((mapped_range
->access
& GL_MAP_WRITE_BIT
) == 0 ||
14049 (mapped_range
->access
& GL_MAP_FLUSH_EXPLICIT_BIT
) ==
14050 GL_MAP_FLUSH_EXPLICIT_BIT
) {
14051 // If we don't need to write back, or explict flush is required, no copying
14054 void* mem
= mapped_range
->GetShmPointer();
14056 return error::kOutOfBounds
;
14058 DCHECK(mapped_range
->pointer
);
14059 memcpy(mapped_range
->pointer
, mem
, mapped_range
->size
);
14061 buffer
->RemoveMappedRange();
14062 GLboolean rt
= glUnmapBuffer(target
);
14063 if (rt
== GL_FALSE
) {
14064 // At this point, we have already done the necessary validation, so
14065 // GL_FALSE indicates data corruption.
14066 // TODO(zmo): We could redo the map / copy data / unmap to recover, but
14067 // the second unmap could still return GL_FALSE. For now, we simply lose
14068 // the contexts in the share group.
14069 LOG(ERROR
) << "glUnmapBuffer unexpectedly returned GL_FALSE";
14070 // Need to lose current context before broadcasting!
14071 MarkContextLost(error::kGuilty
);
14072 group_
->LoseContexts(error::kInnocent
);
14073 return error::kLostContext
;
14075 return error::kNoError
;
14078 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
14079 TextureRef
* texture_ref
) {
14080 Texture
* texture
= texture_ref
->texture();
14081 DoDidUseTexImageIfNeeded(texture
, texture
->target());
14084 // Note that GL_LOST_CONTEXT is specific to GLES.
14085 // For desktop GL we have to query the reset status proactively.
14086 void GLES2DecoderImpl::OnContextLostError() {
14087 if (!WasContextLost()) {
14088 // Need to lose current context before broadcasting!
14089 CheckResetStatus();
14090 group_
->LoseContexts(error::kUnknown
);
14091 reset_by_robustness_extension_
= true;
14095 void GLES2DecoderImpl::OnOutOfMemoryError() {
14096 if (lose_context_when_out_of_memory_
&& !WasContextLost()) {
14097 error::ContextLostReason other
= error::kOutOfMemory
;
14098 if (CheckResetStatus()) {
14099 other
= error::kUnknown
;
14101 // Need to lose current context before broadcasting!
14102 MarkContextLost(error::kOutOfMemory
);
14104 group_
->LoseContexts(other
);
14108 error::Error
GLES2DecoderImpl::HandleGenPathsCHROMIUM(
14109 uint32 immediate_data_size
,
14110 const void* cmd_data
) {
14111 static const char kFunctionName
[] = "glGenPathsCHROMIUM";
14112 const gles2::cmds::GenPathsCHROMIUM
& c
=
14113 *static_cast<const gles2::cmds::GenPathsCHROMIUM
*>(cmd_data
);
14114 if (!features().chromium_path_rendering
) {
14115 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14116 "function not available");
14117 return error::kNoError
;
14120 GLsizei range
= static_cast<GLsizei
>(c
.range
);
14122 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "range < 0");
14123 return error::kNoError
;
14126 GLuint first_client_id
= static_cast<GLuint
>(c
.first_client_id
);
14127 if (first_client_id
== 0)
14128 return error::kInvalidArguments
;
14131 return error::kNoError
;
14133 if (!GenPathsCHROMIUMHelper(first_client_id
, range
))
14134 return error::kInvalidArguments
;
14136 return error::kNoError
;
14138 error::Error
GLES2DecoderImpl::HandleDeletePathsCHROMIUM(
14139 uint32_t immediate_data_size
,
14140 const void* cmd_data
) {
14141 static const char kFunctionName
[] = "glDeletePathsCHROMIUM";
14142 const gles2::cmds::DeletePathsCHROMIUM
& c
=
14143 *static_cast<const gles2::cmds::DeletePathsCHROMIUM
*>(cmd_data
);
14144 if (!features().chromium_path_rendering
) {
14145 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14146 "function not available");
14147 return error::kNoError
;
14150 GLsizei range
= static_cast<GLsizei
>(c
.range
);
14152 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "range < 0");
14153 return error::kNoError
;
14157 return error::kNoError
;
14159 GLuint first_client_id
= c
.first_client_id
;
14160 // first_client_id can be 0, because non-existing path ids are skipped.
14162 if (!DeletePathsCHROMIUMHelper(first_client_id
, range
))
14163 return error::kInvalidArguments
;
14165 return error::kNoError
;
14168 error::Error
GLES2DecoderImpl::HandlePathCommandsCHROMIUM(
14169 uint32 immediate_data_size
,
14170 const void* cmd_data
) {
14171 static const char kFunctionName
[] = "glPathCommandsCHROMIUM";
14172 const gles2::cmds::PathCommandsCHROMIUM
& c
=
14173 *static_cast<const gles2::cmds::PathCommandsCHROMIUM
*>(cmd_data
);
14174 if (!features().chromium_path_rendering
) {
14175 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14176 "function not available");
14177 return error::kNoError
;
14180 GLuint service_id
= 0;
14181 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
)) {
14182 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14183 "invalid path name");
14184 return error::kNoError
;
14187 GLsizei num_commands
= static_cast<GLsizei
>(c
.numCommands
);
14188 if (num_commands
< 0) {
14189 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "numCommands < 0");
14190 return error::kNoError
;
14193 GLsizei num_coords
= static_cast<uint32
>(c
.numCoords
);
14194 if (num_coords
< 0) {
14195 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "numCoords < 0");
14196 return error::kNoError
;
14199 GLenum coord_type
= static_cast<uint32
>(c
.coordType
);
14200 if (!validators_
->path_coord_type
.IsValid(static_cast<GLint
>(coord_type
))) {
14201 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM
, kFunctionName
, "invalid coordType");
14202 return error::kNoError
;
14205 const GLubyte
* commands
= NULL
;
14206 base::CheckedNumeric
<GLsizei
> num_coords_expected
= 0;
14208 if (num_commands
> 0) {
14209 uint32 commands_shm_id
= static_cast<uint32
>(c
.commands_shm_id
);
14210 uint32 commands_shm_offset
= static_cast<uint32
>(c
.commands_shm_offset
);
14211 if (commands_shm_id
!= 0 || commands_shm_offset
!= 0)
14212 commands
= GetSharedMemoryAs
<const GLubyte
*>(
14213 commands_shm_id
, commands_shm_offset
, num_commands
);
14216 return error::kOutOfBounds
;
14218 for (GLsizei i
= 0; i
< num_commands
; ++i
) {
14219 switch (commands
[i
]) {
14220 case GL_CLOSE_PATH_CHROMIUM
:
14221 // Close has no coords.
14223 case GL_MOVE_TO_CHROMIUM
:
14225 case GL_LINE_TO_CHROMIUM
:
14226 num_coords_expected
+= 2;
14228 case GL_QUADRATIC_CURVE_TO_CHROMIUM
:
14229 num_coords_expected
+= 4;
14231 case GL_CUBIC_CURVE_TO_CHROMIUM
:
14232 num_coords_expected
+= 6;
14234 case GL_CONIC_CURVE_TO_CHROMIUM
:
14235 num_coords_expected
+= 5;
14238 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM
, kFunctionName
, "invalid command");
14239 return error::kNoError
;
14244 if (!num_coords_expected
.IsValid() ||
14245 num_coords
!= num_coords_expected
.ValueOrDie()) {
14246 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14247 "numCoords does not match commands");
14248 return error::kNoError
;
14251 const void* coords
= NULL
;
14253 if (num_coords
> 0) {
14254 uint32 coords_size
= 0;
14255 uint32 coord_type_size
=
14256 GLES2Util::GetGLTypeSizeForPathCoordType(coord_type
);
14257 if (!SafeMultiplyUint32(num_coords
, coord_type_size
, &coords_size
))
14258 return error::kOutOfBounds
;
14260 uint32 coords_shm_id
= static_cast<uint32
>(c
.coords_shm_id
);
14261 uint32 coords_shm_offset
= static_cast<uint32
>(c
.coords_shm_offset
);
14262 if (coords_shm_id
!= 0 || coords_shm_offset
!= 0)
14263 coords
= GetSharedMemoryAs
<const void*>(coords_shm_id
, coords_shm_offset
,
14267 return error::kOutOfBounds
;
14270 glPathCommandsNV(service_id
, num_commands
, commands
, num_coords
, coord_type
,
14273 return error::kNoError
;
14276 error::Error
GLES2DecoderImpl::HandlePathParameterfCHROMIUM(
14277 uint32 immediate_data_size
,
14278 const void* cmd_data
) {
14279 static const char kFunctionName
[] = "glPathParameterfCHROMIUM";
14280 const gles2::cmds::PathParameterfCHROMIUM
& c
=
14281 *static_cast<const gles2::cmds::PathParameterfCHROMIUM
*>(cmd_data
);
14282 if (!features().chromium_path_rendering
) {
14283 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14284 "function not available");
14285 return error::kNoError
;
14287 GLuint service_id
= 0;
14288 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
)) {
14289 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14290 "invalid path name");
14291 return error::kNoError
;
14294 GLenum pname
= static_cast<GLenum
>(c
.pname
);
14295 GLfloat value
= static_cast<GLfloat
>(c
.value
);
14296 bool hasValueError
= false;
14299 case GL_PATH_STROKE_WIDTH_CHROMIUM
:
14300 case GL_PATH_MITER_LIMIT_CHROMIUM
:
14301 hasValueError
= std::isnan(value
) || !std::isfinite(value
) || value
< 0;
14303 case GL_PATH_STROKE_BOUND_CHROMIUM
:
14304 value
= std::max(std::min(1.0f
, value
), 0.0f
);
14306 case GL_PATH_END_CAPS_CHROMIUM
:
14307 hasValueError
= !validators_
->path_parameter_cap_values
.IsValid(
14308 static_cast<GLint
>(value
));
14310 case GL_PATH_JOIN_STYLE_CHROMIUM
:
14311 hasValueError
= !validators_
->path_parameter_join_values
.IsValid(
14312 static_cast<GLint
>(value
));
14315 DCHECK(!validators_
->path_parameter
.IsValid(pname
));
14316 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, pname
, "pname");
14317 return error::kNoError
;
14319 DCHECK(validators_
->path_parameter
.IsValid(pname
));
14321 if (hasValueError
) {
14322 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "value not correct");
14323 return error::kNoError
;
14326 glPathParameterfNV(service_id
, pname
, value
);
14327 return error::kNoError
;
14330 error::Error
GLES2DecoderImpl::HandlePathParameteriCHROMIUM(
14331 uint32 immediate_data_size
,
14332 const void* cmd_data
) {
14333 static const char kFunctionName
[] = "glPathParameteriCHROMIUM";
14334 const gles2::cmds::PathParameteriCHROMIUM
& c
=
14335 *static_cast<const gles2::cmds::PathParameteriCHROMIUM
*>(cmd_data
);
14336 if (!features().chromium_path_rendering
) {
14337 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14338 "function not available");
14339 return error::kNoError
;
14341 GLuint service_id
= 0;
14342 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
)) {
14343 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14344 "invalid path name");
14345 return error::kNoError
;
14348 GLenum pname
= static_cast<GLenum
>(c
.pname
);
14349 GLint value
= static_cast<GLint
>(c
.value
);
14350 bool hasValueError
= false;
14353 case GL_PATH_STROKE_WIDTH_CHROMIUM
:
14354 case GL_PATH_MITER_LIMIT_CHROMIUM
:
14355 hasValueError
= value
< 0;
14357 case GL_PATH_STROKE_BOUND_CHROMIUM
:
14358 value
= std::max(std::min(1, value
), 0);
14360 case GL_PATH_END_CAPS_CHROMIUM
:
14361 hasValueError
= !validators_
->path_parameter_cap_values
.IsValid(value
);
14363 case GL_PATH_JOIN_STYLE_CHROMIUM
:
14364 hasValueError
= !validators_
->path_parameter_join_values
.IsValid(value
);
14367 DCHECK(!validators_
->path_parameter
.IsValid(pname
));
14368 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, pname
, "pname");
14369 return error::kNoError
;
14371 DCHECK(validators_
->path_parameter
.IsValid(pname
));
14373 if (hasValueError
) {
14374 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "value not correct");
14375 return error::kNoError
;
14378 glPathParameteriNV(service_id
, pname
, value
);
14379 return error::kNoError
;
14382 error::Error
GLES2DecoderImpl::HandleStencilFillPathCHROMIUM(
14383 uint32 immediate_data_size
,
14384 const void* cmd_data
) {
14385 static const char kFunctionName
[] = "glStencilFillPathCHROMIUM";
14386 const gles2::cmds::StencilFillPathCHROMIUM
& c
=
14387 *static_cast<const gles2::cmds::StencilFillPathCHROMIUM
*>(cmd_data
);
14388 if (!features().chromium_path_rendering
) {
14389 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14390 "function not available");
14391 return error::kNoError
;
14393 GLenum fill_mode
= static_cast<GLenum
>(c
.fillMode
);
14394 if (!validators_
->path_fill_mode
.IsValid(fill_mode
)) {
14395 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, fill_mode
, "fillMode");
14396 return error::kNoError
;
14398 GLuint mask
= static_cast<GLuint
>(c
.mask
);
14399 if ((fill_mode
== GL_COUNT_UP_CHROMIUM
||
14400 fill_mode
== GL_COUNT_DOWN_CHROMIUM
) &&
14401 GLES2Util::IsNPOT(mask
+ 1)) {
14402 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
,
14403 "mask + 1 is not power of two");
14404 return error::kNoError
;
14406 GLuint service_id
= 0;
14407 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
)) {
14408 // "If /path/ does not name an existing path object, the command does
14409 // nothing (and no error is generated)."
14410 // This holds for other rendering functions, too.
14411 return error::kNoError
;
14414 glStencilFillPathNV(service_id
, fill_mode
, mask
);
14415 return error::kNoError
;
14418 error::Error
GLES2DecoderImpl::HandleStencilStrokePathCHROMIUM(
14419 uint32 immediate_data_size
,
14420 const void* cmd_data
) {
14421 static const char kFunctionName
[] = "glStencilStrokePathCHROMIUM";
14422 const gles2::cmds::StencilStrokePathCHROMIUM
& c
=
14423 *static_cast<const gles2::cmds::StencilStrokePathCHROMIUM
*>(cmd_data
);
14424 if (!features().chromium_path_rendering
) {
14425 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14426 "function not available");
14427 return error::kNoError
;
14429 GLuint service_id
= 0;
14430 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
)) {
14431 return error::kNoError
;
14433 GLint reference
= static_cast<GLint
>(c
.reference
);
14434 GLuint mask
= static_cast<GLuint
>(c
.mask
);
14436 glStencilStrokePathNV(service_id
, reference
, mask
);
14437 return error::kNoError
;
14440 error::Error
GLES2DecoderImpl::HandleCoverFillPathCHROMIUM(
14441 uint32 immediate_data_size
,
14442 const void* cmd_data
) {
14443 static const char kFunctionName
[] = "glCoverFillPathCHROMIUM";
14444 const gles2::cmds::CoverFillPathCHROMIUM
& c
=
14445 *static_cast<const gles2::cmds::CoverFillPathCHROMIUM
*>(cmd_data
);
14446 if (!features().chromium_path_rendering
) {
14447 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14448 "function not available");
14449 return error::kNoError
;
14451 GLenum cover_mode
= static_cast<GLenum
>(c
.coverMode
);
14452 if (!validators_
->path_cover_mode
.IsValid(cover_mode
)) {
14453 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, cover_mode
, "coverMode");
14454 return error::kNoError
;
14456 GLuint service_id
= 0;
14457 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
))
14458 return error::kNoError
;
14461 glCoverFillPathNV(service_id
, cover_mode
);
14462 return error::kNoError
;
14465 error::Error
GLES2DecoderImpl::HandleCoverStrokePathCHROMIUM(
14466 uint32 immediate_data_size
,
14467 const void* cmd_data
) {
14468 static const char kFunctionName
[] = "glCoverStrokePathCHROMIUM";
14469 const gles2::cmds::CoverStrokePathCHROMIUM
& c
=
14470 *static_cast<const gles2::cmds::CoverStrokePathCHROMIUM
*>(cmd_data
);
14471 if (!features().chromium_path_rendering
) {
14472 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14473 "function not available");
14474 return error::kNoError
;
14476 GLenum cover_mode
= static_cast<GLenum
>(c
.coverMode
);
14477 if (!validators_
->path_cover_mode
.IsValid(cover_mode
)) {
14478 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, cover_mode
, "coverMode");
14479 return error::kNoError
;
14481 GLuint service_id
= 0;
14482 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
))
14483 return error::kNoError
;
14486 glCoverStrokePathNV(service_id
, cover_mode
);
14487 return error::kNoError
;
14490 error::Error
GLES2DecoderImpl::HandleStencilThenCoverFillPathCHROMIUM(
14491 uint32 immediate_data_size
,
14492 const void* cmd_data
) {
14493 static const char kFunctionName
[] = "glStencilThenCoverFillPathCHROMIUM";
14494 const gles2::cmds::StencilThenCoverFillPathCHROMIUM
& c
=
14495 *static_cast<const gles2::cmds::StencilThenCoverFillPathCHROMIUM
*>(
14497 if (!features().chromium_path_rendering
) {
14498 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14499 "function not available");
14500 return error::kNoError
;
14502 GLenum fill_mode
= static_cast<GLenum
>(c
.fillMode
);
14503 if (!validators_
->path_fill_mode
.IsValid(fill_mode
)) {
14504 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, fill_mode
, "fillMode");
14505 return error::kNoError
;
14507 GLuint mask
= static_cast<GLuint
>(c
.mask
);
14508 if ((fill_mode
== GL_COUNT_UP_CHROMIUM
||
14509 fill_mode
== GL_COUNT_DOWN_CHROMIUM
) &&
14510 GLES2Util::IsNPOT(mask
+ 1)) {
14511 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
,
14512 "mask + 1 is not power of two");
14513 return error::kNoError
;
14515 GLenum cover_mode
= static_cast<GLenum
>(c
.coverMode
);
14516 if (!validators_
->path_cover_mode
.IsValid(cover_mode
)) {
14517 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, cover_mode
, "coverMode");
14518 return error::kNoError
;
14520 GLuint service_id
= 0;
14521 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
))
14522 return error::kNoError
;
14525 glStencilThenCoverFillPathNV(service_id
, fill_mode
, mask
, cover_mode
);
14526 return error::kNoError
;
14529 error::Error
GLES2DecoderImpl::HandleStencilThenCoverStrokePathCHROMIUM(
14530 uint32 immediate_data_size
,
14531 const void* cmd_data
) {
14532 static const char kFunctionName
[] = "glStencilThenCoverStrokePathCHROMIUM";
14533 const gles2::cmds::StencilThenCoverStrokePathCHROMIUM
& c
=
14534 *static_cast<const gles2::cmds::StencilThenCoverStrokePathCHROMIUM
*>(
14536 if (!features().chromium_path_rendering
) {
14537 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14538 "function not available");
14539 return error::kNoError
;
14541 GLenum cover_mode
= static_cast<GLenum
>(c
.coverMode
);
14542 if (!validators_
->path_cover_mode
.IsValid(cover_mode
)) {
14543 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, cover_mode
, "coverMode");
14544 return error::kNoError
;
14546 GLuint service_id
= 0;
14547 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
))
14548 return error::kNoError
;
14550 GLint reference
= static_cast<GLint
>(c
.reference
);
14551 GLuint mask
= static_cast<GLuint
>(c
.mask
);
14553 glStencilThenCoverStrokePathNV(service_id
, reference
, mask
, cover_mode
);
14554 return error::kNoError
;
14557 // Include the auto-generated part of this file. We split this because it means
14558 // we can easily edit the non-auto generated parts right here in this file
14559 // instead of having to edit some template or the code generator.
14560 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
14562 } // namespace gles2