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 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
735 // check with all attached and enabled color attachments.
736 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers
);
737 bool BoundFramebufferHasDepthAttachment();
738 bool BoundFramebufferHasStencilAttachment();
740 error::ContextLostReason
GetContextLostReason() override
;
742 // Overridden from FramebufferManager::TextureDetachObserver:
743 void OnTextureRefDetachedFromFramebuffer(TextureRef
* texture
) override
;
745 // Overriden from ErrorStateClient.
746 void OnContextLostError() override
;
747 void OnOutOfMemoryError() override
;
749 // Ensure Renderbuffer corresponding to last DoBindRenderbuffer() is bound.
750 void EnsureRenderbufferBound();
752 // Helpers to facilitate calling into compatible extensions.
753 static void RenderbufferStorageMultisampleHelper(
754 const FeatureInfo
* feature_info
,
757 GLenum internal_format
,
761 void BlitFramebufferHelper(GLint srcX0
,
773 friend class ScopedFrameBufferBinder
;
774 friend class ScopedResolvedFrameBufferBinder
;
775 friend class BackFramebuffer
;
777 // Initialize or re-initialize the shader translator.
778 bool InitializeShaderTranslator();
780 void UpdateCapabilities();
782 // Helpers for the glGen and glDelete functions.
783 bool GenTexturesHelper(GLsizei n
, const GLuint
* client_ids
);
784 void DeleteTexturesHelper(GLsizei n
, const GLuint
* client_ids
);
785 bool GenBuffersHelper(GLsizei n
, const GLuint
* client_ids
);
786 void DeleteBuffersHelper(GLsizei n
, const GLuint
* client_ids
);
787 bool GenFramebuffersHelper(GLsizei n
, const GLuint
* client_ids
);
788 void DeleteFramebuffersHelper(GLsizei n
, const GLuint
* client_ids
);
789 bool GenRenderbuffersHelper(GLsizei n
, const GLuint
* client_ids
);
790 void DeleteRenderbuffersHelper(GLsizei n
, const GLuint
* client_ids
);
791 bool GenValuebuffersCHROMIUMHelper(GLsizei n
, const GLuint
* client_ids
);
792 void DeleteValuebuffersCHROMIUMHelper(GLsizei n
, const GLuint
* client_ids
);
793 bool GenQueriesEXTHelper(GLsizei n
, const GLuint
* client_ids
);
794 void DeleteQueriesEXTHelper(GLsizei n
, const GLuint
* client_ids
);
795 bool GenVertexArraysOESHelper(GLsizei n
, const GLuint
* client_ids
);
796 void DeleteVertexArraysOESHelper(GLsizei n
, const GLuint
* client_ids
);
797 bool GenPathsCHROMIUMHelper(GLuint first_client_id
, GLsizei range
);
798 bool DeletePathsCHROMIUMHelper(GLuint first_client_id
, GLsizei range
);
800 // Helper for async upload token completion notification callback.
801 base::Closure
AsyncUploadTokenCompletionClosure(uint32 async_upload_token
,
802 uint32 sync_data_shm_id
,
803 uint32 sync_data_shm_offset
);
808 void OnFboChanged() const;
809 void OnUseFramebuffer() const;
811 error::ContextLostReason
GetContextLostReasonFromResetStatus(
812 GLenum reset_status
) const;
814 // TODO(gman): Cache these pointers?
815 BufferManager
* buffer_manager() {
816 return group_
->buffer_manager();
819 RenderbufferManager
* renderbuffer_manager() {
820 return group_
->renderbuffer_manager();
823 FramebufferManager
* framebuffer_manager() {
824 return group_
->framebuffer_manager();
827 ValuebufferManager
* valuebuffer_manager() {
828 return group_
->valuebuffer_manager();
831 PathManager
* path_manager() { return group_
->path_manager(); }
833 ProgramManager
* program_manager() {
834 return group_
->program_manager();
837 ShaderManager
* shader_manager() {
838 return group_
->shader_manager();
841 ShaderTranslatorCache
* shader_translator_cache() {
842 return group_
->shader_translator_cache();
845 const TextureManager
* texture_manager() const {
846 return group_
->texture_manager();
849 TextureManager
* texture_manager() {
850 return group_
->texture_manager();
853 MailboxManager
* mailbox_manager() {
854 return group_
->mailbox_manager();
857 ImageManager
* image_manager() { return image_manager_
.get(); }
859 VertexArrayManager
* vertex_array_manager() {
860 return vertex_array_manager_
.get();
863 MemoryTracker
* memory_tracker() {
864 return group_
->memory_tracker();
867 bool EnsureGPUMemoryAvailable(size_t estimated_size
) {
868 MemoryTracker
* tracker
= memory_tracker();
870 return tracker
->EnsureGPUMemoryAvailable(estimated_size
);
875 bool IsWebGLContext() const {
876 return webgl_version_
== 1 || webgl_version_
== 2;
879 bool IsOffscreenBufferMultisampled() const {
880 return offscreen_target_samples_
> 1;
883 // Creates a Texture for the given texture.
884 TextureRef
* CreateTexture(
885 GLuint client_id
, GLuint service_id
) {
886 return texture_manager()->CreateTexture(client_id
, service_id
);
889 // Gets the texture info for the given texture. Returns NULL if none exists.
890 TextureRef
* GetTexture(GLuint client_id
) const {
891 return texture_manager()->GetTexture(client_id
);
894 // Deletes the texture info for the given texture.
895 void RemoveTexture(GLuint client_id
) {
896 texture_manager()->RemoveTexture(client_id
);
899 // Get the size (in pixels) of the currently bound frame buffer (either FBO
900 // or regular back buffer).
901 gfx::Size
GetBoundReadFrameBufferSize();
903 // Get the format of the currently bound frame buffer (either FBO or regular
905 GLenum
GetBoundReadFrameBufferTextureType();
906 GLenum
GetBoundReadFrameBufferInternalFormat();
907 GLenum
GetBoundDrawFrameBufferInternalFormat();
909 // Wrapper for CompressedTexImage2D commands.
910 error::Error
DoCompressedTexImage2D(
913 GLenum internal_format
,
920 // Wrapper for CompressedTexImage3D commands.
921 error::Error
DoCompressedTexImage3D(
924 GLenum internal_format
,
932 // Wrapper for CompressedTexSubImage2D.
933 void DoCompressedTexSubImage2D(
944 // Wrapper for CompressedTexSubImage3D.
945 void DoCompressedTexSubImage3D(
958 // Wrapper for CopyTexImage2D.
959 void DoCopyTexImage2D(
962 GLenum internal_format
,
969 // Wrapper for SwapBuffers.
970 void DoSwapBuffers();
972 // Wrapper for SwapInterval.
973 void DoSwapInterval(int interval
);
975 // Wrapper for CopyTexSubImage2D.
976 void DoCopyTexSubImage2D(
986 // Validation for TexSubImage2D.
987 bool ValidateTexSubImage2D(
989 const char* function_name
,
1000 // Wrapper for TexSubImage2D.
1001 error::Error
DoTexSubImage2D(
1012 // Wrapper for TexSubImage3D.
1013 error::Error
DoTexSubImage3D(
1026 // Extra validation for async tex(Sub)Image2D.
1027 bool ValidateAsyncTransfer(
1028 const char* function_name
,
1029 TextureRef
* texture_ref
,
1034 // Wrapper for TexImageIOSurface2DCHROMIUM.
1035 void DoTexImageIOSurface2DCHROMIUM(
1039 GLuint io_surface_id
,
1042 void DoCopyTextureCHROMIUM(GLenum target
,
1045 GLenum internal_format
,
1047 GLboolean unpack_flip_y
,
1048 GLboolean unpack_premultiply_alpha
,
1049 GLboolean unpack_unmultiply_alpha
);
1051 void DoCopySubTextureCHROMIUM(GLenum target
,
1060 GLboolean unpack_flip_y
,
1061 GLboolean unpack_premultiply_alpha
,
1062 GLboolean unpack_unmultiply_alpha
);
1064 void DoCompressedCopyTextureCHROMIUM(GLenum target
,
1068 // Wrapper for TexStorage2DEXT.
1069 void DoTexStorage2DEXT(
1072 GLenum internal_format
,
1076 void DoProduceTextureCHROMIUM(GLenum target
, const GLbyte
* key
);
1077 void DoProduceTextureDirectCHROMIUM(GLuint texture
, GLenum target
,
1079 void ProduceTextureRef(std::string func_name
, TextureRef
* texture_ref
,
1080 GLenum target
, const GLbyte
* data
);
1082 void EnsureTextureForClientId(GLenum target
, GLuint client_id
);
1083 void DoConsumeTextureCHROMIUM(GLenum target
, const GLbyte
* key
);
1084 void DoCreateAndConsumeTextureCHROMIUM(GLenum target
, const GLbyte
* key
,
1087 bool DoIsValuebufferCHROMIUM(GLuint client_id
);
1088 void DoBindValueBufferCHROMIUM(GLenum target
, GLuint valuebuffer
);
1089 void DoSubscribeValueCHROMIUM(GLenum target
, GLenum subscription
);
1090 void DoPopulateSubscribedValuesCHROMIUM(GLenum target
);
1091 void DoUniformValueBufferCHROMIUM(GLint location
,
1093 GLenum subscription
);
1095 void DoBindTexImage2DCHROMIUM(
1098 void DoReleaseTexImage2DCHROMIUM(
1102 void DoTraceEndCHROMIUM(void);
1104 void DoDrawBuffersEXT(GLsizei count
, const GLenum
* bufs
);
1106 void DoLoseContextCHROMIUM(GLenum current
, GLenum other
);
1108 void DoFlushDriverCachesCHROMIUM(void);
1110 void DoMatrixLoadfCHROMIUM(GLenum matrix_mode
, const GLfloat
* matrix
);
1111 void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode
);
1113 // Creates a Program for the given program.
1114 Program
* CreateProgram(
1115 GLuint client_id
, GLuint service_id
) {
1116 return program_manager()->CreateProgram(client_id
, service_id
);
1119 // Gets the program info for the given program. Returns NULL if none exists.
1120 Program
* GetProgram(GLuint client_id
) {
1121 return program_manager()->GetProgram(client_id
);
1125 void LogClientServiceMapping(
1126 const char* /* function_name */,
1127 GLuint
/* client_id */,
1128 GLuint
/* service_id */) {
1130 template<typename T
>
1131 void LogClientServiceForInfo(
1132 T
* /* info */, GLuint
/* client_id */, const char* /* function_name */) {
1135 void LogClientServiceMapping(
1136 const char* function_name
, GLuint client_id
, GLuint service_id
) {
1137 if (service_logging_
) {
1138 VLOG(1) << "[" << logger_
.GetLogPrefix() << "] " << function_name
1139 << ": client_id = " << client_id
1140 << ", service_id = " << service_id
;
1143 template<typename T
>
1144 void LogClientServiceForInfo(
1145 T
* info
, GLuint client_id
, const char* function_name
) {
1147 LogClientServiceMapping(function_name
, client_id
, info
->service_id());
1152 // Gets the program info for the given program. If it's not a program
1153 // generates a GL error. Returns NULL if not program.
1154 Program
* GetProgramInfoNotShader(
1155 GLuint client_id
, const char* function_name
) {
1156 Program
* program
= GetProgram(client_id
);
1158 if (GetShader(client_id
)) {
1160 GL_INVALID_OPERATION
, function_name
, "shader passed for program");
1162 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown program");
1165 LogClientServiceForInfo(program
, client_id
, function_name
);
1170 // Creates a Shader for the given shader.
1171 Shader
* CreateShader(
1174 GLenum shader_type
) {
1175 return shader_manager()->CreateShader(
1176 client_id
, service_id
, shader_type
);
1179 // Gets the shader info for the given shader. Returns NULL if none exists.
1180 Shader
* GetShader(GLuint client_id
) {
1181 return shader_manager()->GetShader(client_id
);
1184 // Gets the shader info for the given shader. If it's not a shader generates a
1185 // GL error. Returns NULL if not shader.
1186 Shader
* GetShaderInfoNotProgram(
1187 GLuint client_id
, const char* function_name
) {
1188 Shader
* shader
= GetShader(client_id
);
1190 if (GetProgram(client_id
)) {
1192 GL_INVALID_OPERATION
, function_name
, "program passed for shader");
1195 GL_INVALID_VALUE
, function_name
, "unknown shader");
1198 LogClientServiceForInfo(shader
, client_id
, function_name
);
1202 // Creates a buffer info for the given buffer.
1203 void CreateBuffer(GLuint client_id
, GLuint service_id
) {
1204 return buffer_manager()->CreateBuffer(client_id
, service_id
);
1207 // Gets the buffer info for the given buffer.
1208 Buffer
* GetBuffer(GLuint client_id
) {
1209 Buffer
* buffer
= buffer_manager()->GetBuffer(client_id
);
1213 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1214 // on glDeleteBuffers so we can make sure the user does not try to render
1215 // with deleted buffers.
1216 void RemoveBuffer(GLuint client_id
);
1218 // Creates a framebuffer info for the given framebuffer.
1219 void CreateFramebuffer(GLuint client_id
, GLuint service_id
) {
1220 return framebuffer_manager()->CreateFramebuffer(client_id
, service_id
);
1223 // Gets the framebuffer info for the given framebuffer.
1224 Framebuffer
* GetFramebuffer(GLuint client_id
) {
1225 return framebuffer_manager()->GetFramebuffer(client_id
);
1228 // Removes the framebuffer info for the given framebuffer.
1229 void RemoveFramebuffer(GLuint client_id
) {
1230 framebuffer_manager()->RemoveFramebuffer(client_id
);
1233 // Creates a renderbuffer info for the given renderbuffer.
1234 void CreateRenderbuffer(GLuint client_id
, GLuint service_id
) {
1235 return renderbuffer_manager()->CreateRenderbuffer(
1236 client_id
, service_id
);
1239 // Gets the renderbuffer info for the given renderbuffer.
1240 Renderbuffer
* GetRenderbuffer(GLuint client_id
) {
1241 return renderbuffer_manager()->GetRenderbuffer(client_id
);
1244 // Removes the renderbuffer info for the given renderbuffer.
1245 void RemoveRenderbuffer(GLuint client_id
) {
1246 renderbuffer_manager()->RemoveRenderbuffer(client_id
);
1249 // Creates a valuebuffer info for the given valuebuffer.
1250 void CreateValuebuffer(GLuint client_id
) {
1251 return valuebuffer_manager()->CreateValuebuffer(client_id
);
1254 // Gets the valuebuffer info for a given valuebuffer.
1255 Valuebuffer
* GetValuebuffer(GLuint client_id
) {
1256 return valuebuffer_manager()->GetValuebuffer(client_id
);
1259 // Removes the valuebuffer info for the given valuebuffer.
1260 void RemoveValuebuffer(GLuint client_id
) {
1261 valuebuffer_manager()->RemoveValuebuffer(client_id
);
1264 // Gets the vertex attrib manager for the given vertex array.
1265 VertexAttribManager
* GetVertexAttribManager(GLuint client_id
) {
1266 VertexAttribManager
* info
=
1267 vertex_array_manager()->GetVertexAttribManager(client_id
);
1271 // Removes the vertex attrib manager for the given vertex array.
1272 void RemoveVertexAttribManager(GLuint client_id
) {
1273 vertex_array_manager()->RemoveVertexAttribManager(client_id
);
1276 // Creates a vertex attrib manager for the given vertex array.
1277 scoped_refptr
<VertexAttribManager
> CreateVertexAttribManager(
1280 bool client_visible
) {
1281 return vertex_array_manager()->CreateVertexAttribManager(
1282 client_id
, service_id
, group_
->max_vertex_attribs(), client_visible
);
1285 void DoBindAttribLocation(GLuint client_id
, GLuint index
, const char* name
);
1286 void DoBindUniformLocationCHROMIUM(
1287 GLuint client_id
, GLint location
, const char* name
);
1289 error::Error
GetAttribLocationHelper(
1290 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1291 const std::string
& name_str
);
1293 error::Error
GetUniformLocationHelper(
1294 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1295 const std::string
& name_str
);
1297 error::Error
GetFragDataLocationHelper(
1298 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1299 const std::string
& name_str
);
1301 // Wrapper for glShaderSource.
1302 void DoShaderSource(
1303 GLuint client_id
, GLsizei count
, const char** data
, const GLint
* length
);
1305 // Wrapper for glTransformFeedbackVaryings.
1306 void DoTransformFeedbackVaryings(
1307 GLuint client_program_id
, GLsizei count
, const char* const* varyings
,
1308 GLenum buffer_mode
);
1310 // Clear any textures used by the current program.
1311 bool ClearUnclearedTextures();
1313 // Clears any uncleared attachments attached to the given frame buffer.
1314 // Returns false if there was a generated GL error.
1315 void ClearUnclearedAttachments(GLenum target
, Framebuffer
* framebuffer
);
1317 // overridden from GLES2Decoder
1318 bool ClearLevel(Texture
* texture
,
1326 int height
) override
;
1328 // Restore all GL state that affects clearing.
1329 void RestoreClearState();
1331 // Remembers the state of some capabilities.
1332 // Returns: true if glEnable/glDisable should actually be called.
1333 bool SetCapabilityState(GLenum cap
, bool enabled
);
1335 // Check that the currently bound framebuffers are valid.
1336 // Generates GL error if not.
1337 bool CheckBoundFramebuffersValid(const char* func_name
);
1339 // Check that the currently bound read framebuffer has a color image
1340 // attached. Generates GL error if not.
1341 bool CheckBoundReadFramebufferColorAttachment(const char* func_name
);
1343 // Check that the currently bound read framebuffer's color image
1344 // isn't the target texture of the glCopyTex{Sub}Image2D.
1345 bool FormsTextureCopyingFeedbackLoop(TextureRef
* texture
, GLint level
);
1347 // Check if a framebuffer meets our requirements.
1348 bool CheckFramebufferValid(
1349 Framebuffer
* framebuffer
,
1351 const char* func_name
);
1353 // Check if the current valuebuffer exists and is valid. If not generates
1354 // the appropriate GL error. Returns true if the current valuebuffer is in
1356 bool CheckCurrentValuebuffer(const char* function_name
);
1358 // Check if the current valuebuffer exists and is valiud and that the
1359 // value buffer is actually subscribed to the given subscription
1360 bool CheckCurrentValuebufferForSubscription(GLenum subscription
,
1361 const char* function_name
);
1363 // Check if the location can be used for the given subscription target. If not
1364 // generates the appropriate GL error. Returns true if the location is usable
1365 bool CheckSubscriptionTarget(GLint location
,
1366 GLenum subscription
,
1367 const char* function_name
);
1369 // Checks if the current program exists and is valid. If not generates the
1370 // appropriate GL error. Returns true if the current program is in a usable
1372 bool CheckCurrentProgram(const char* function_name
);
1374 // Checks if the current program exists and is valid and that location is not
1375 // -1. If the current program is not valid generates the appropriate GL
1376 // error. Returns true if the current program is in a usable state and
1377 // location is not -1.
1378 bool CheckCurrentProgramForUniform(GLint location
, const char* function_name
);
1380 // Checks if the current program samples a texture that is also the color
1381 // image of the current bound framebuffer, i.e., the source and destination
1382 // of the draw operation are the same.
1383 bool CheckDrawingFeedbackLoops();
1385 // Checks if |api_type| is valid for the given uniform
1386 // If the api type is not valid generates the appropriate GL
1387 // error. Returns true if |api_type| is valid for the uniform
1388 bool CheckUniformForApiType(const Program::UniformInfo
* info
,
1389 const char* function_name
,
1390 Program::UniformApiType api_type
);
1392 // Gets the type of a uniform for a location in the current program. Sets GL
1393 // errors if the current program is not valid. Returns true if the current
1394 // program is valid and the location exists. Adjusts count so it
1395 // does not overflow the uniform.
1396 bool PrepForSetUniformByLocation(GLint fake_location
,
1397 const char* function_name
,
1398 Program::UniformApiType api_type
,
1399 GLint
* real_location
,
1403 // Gets the service id for any simulated backbuffer fbo.
1404 GLuint
GetBackbufferServiceId() const;
1406 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1407 bool GetHelper(GLenum pname
, GLint
* params
, GLsizei
* num_written
);
1409 // Helper for glGetVertexAttrib
1410 void GetVertexAttribHelper(
1411 const VertexAttrib
* attrib
, GLenum pname
, GLint
* param
);
1413 // Wrapper for glActiveTexture
1414 void DoActiveTexture(GLenum texture_unit
);
1416 // Wrapper for glAttachShader
1417 void DoAttachShader(GLuint client_program_id
, GLint client_shader_id
);
1419 // Wrapper for glBindBuffer since we need to track the current targets.
1420 void DoBindBuffer(GLenum target
, GLuint buffer
);
1422 // Wrapper for glBindFramebuffer since we need to track the current targets.
1423 void DoBindFramebuffer(GLenum target
, GLuint framebuffer
);
1425 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1426 void DoBindRenderbuffer(GLenum target
, GLuint renderbuffer
);
1428 // Wrapper for glBindTexture since we need to track the current targets.
1429 void DoBindTexture(GLenum target
, GLuint texture
);
1431 // Wrapper for glBindVertexArrayOES
1432 void DoBindVertexArrayOES(GLuint array
);
1433 void EmulateVertexArrayState();
1435 // Wrapper for glBlitFramebufferCHROMIUM.
1436 void DoBlitFramebufferCHROMIUM(
1437 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
1438 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
1439 GLbitfield mask
, GLenum filter
);
1441 // Wrapper for glBufferSubData.
1442 void DoBufferSubData(
1443 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
);
1445 // Wrapper for glCheckFramebufferStatus
1446 GLenum
DoCheckFramebufferStatus(GLenum target
);
1448 // Wrapper for glClear
1449 error::Error
DoClear(GLbitfield mask
);
1451 // Wrappers for various state.
1452 void DoDepthRangef(GLclampf znear
, GLclampf zfar
);
1453 void DoSampleCoverage(GLclampf value
, GLboolean invert
);
1455 // Wrapper for glCompileShader.
1456 void DoCompileShader(GLuint shader
);
1458 // Wrapper for glDetachShader
1459 void DoDetachShader(GLuint client_program_id
, GLint client_shader_id
);
1461 // Wrapper for glDisable
1462 void DoDisable(GLenum cap
);
1464 // Wrapper for glDisableVertexAttribArray.
1465 void DoDisableVertexAttribArray(GLuint index
);
1467 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1469 void DoDiscardFramebufferEXT(GLenum target
,
1470 GLsizei numAttachments
,
1471 const GLenum
* attachments
);
1473 // Wrapper for glEnable
1474 void DoEnable(GLenum cap
);
1476 // Wrapper for glEnableVertexAttribArray.
1477 void DoEnableVertexAttribArray(GLuint index
);
1479 // Wrapper for glFinish.
1482 // Wrapper for glFlush.
1485 // Wrapper for glFramebufferRenderbufffer.
1486 void DoFramebufferRenderbuffer(
1487 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
1488 GLuint renderbuffer
);
1490 // Wrapper for glFramebufferTexture2D.
1491 void DoFramebufferTexture2D(
1492 GLenum target
, GLenum attachment
, GLenum textarget
, GLuint texture
,
1495 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1496 void DoFramebufferTexture2DMultisample(
1497 GLenum target
, GLenum attachment
, GLenum textarget
,
1498 GLuint texture
, GLint level
, GLsizei samples
);
1500 // Common implementation for both DoFramebufferTexture2D wrappers.
1501 void DoFramebufferTexture2DCommon(const char* name
,
1502 GLenum target
, GLenum attachment
, GLenum textarget
,
1503 GLuint texture
, GLint level
, GLsizei samples
);
1505 // Wrapper for glFramebufferTextureLayer.
1506 void DoFramebufferTextureLayer(
1507 GLenum target
, GLenum attachment
, GLuint texture
, GLint level
,
1510 // Wrapper for glGenerateMipmap
1511 void DoGenerateMipmap(GLenum target
);
1513 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1514 // to account for different pname values defined in different extension
1516 GLenum
AdjustGetPname(GLenum pname
);
1518 // Wrapper for DoGetBooleanv.
1519 void DoGetBooleanv(GLenum pname
, GLboolean
* params
);
1521 // Wrapper for DoGetFloatv.
1522 void DoGetFloatv(GLenum pname
, GLfloat
* params
);
1524 // Wrapper for glGetFramebufferAttachmentParameteriv.
1525 void DoGetFramebufferAttachmentParameteriv(
1526 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
);
1528 // Wrapper for glGetInteger64v.
1529 void DoGetInteger64v(GLenum pname
, GLint64
* params
);
1531 // Wrapper for glGetIntegerv.
1532 void DoGetIntegerv(GLenum pname
, GLint
* params
);
1534 // Gets the max value in a range in a buffer.
1535 GLuint
DoGetMaxValueInBufferCHROMIUM(
1536 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
);
1538 // Wrapper for glGetBufferParameteri64v.
1539 void DoGetBufferParameteri64v(
1540 GLenum target
, GLenum pname
, GLint64
* params
);
1542 // Wrapper for glGetBufferParameteriv.
1543 void DoGetBufferParameteriv(
1544 GLenum target
, GLenum pname
, GLint
* params
);
1546 // Wrapper for glGetProgramiv.
1547 void DoGetProgramiv(
1548 GLuint program_id
, GLenum pname
, GLint
* params
);
1550 // Wrapper for glRenderbufferParameteriv.
1551 void DoGetRenderbufferParameteriv(
1552 GLenum target
, GLenum pname
, GLint
* params
);
1554 // Wrapper for glGetShaderiv
1555 void DoGetShaderiv(GLuint shader
, GLenum pname
, GLint
* params
);
1557 // Wrappers for glGetTexParameter.
1558 void DoGetTexParameterfv(GLenum target
, GLenum pname
, GLfloat
* params
);
1559 void DoGetTexParameteriv(GLenum target
, GLenum pname
, GLint
* params
);
1560 void InitTextureMaxAnisotropyIfNeeded(GLenum target
, GLenum pname
);
1562 // Wrappers for glGetVertexAttrib.
1563 template <typename T
>
1564 void DoGetVertexAttribImpl(GLuint index
, GLenum pname
, T
* params
);
1565 void DoGetVertexAttribfv(GLuint index
, GLenum pname
, GLfloat
* params
);
1566 void DoGetVertexAttribiv(GLuint index
, GLenum pname
, GLint
* params
);
1567 void DoGetVertexAttribIiv(GLuint index
, GLenum pname
, GLint
* params
);
1568 void DoGetVertexAttribIuiv(GLuint index
, GLenum pname
, GLuint
* params
);
1570 // Wrappers for glIsXXX functions.
1571 bool DoIsEnabled(GLenum cap
);
1572 bool DoIsBuffer(GLuint client_id
);
1573 bool DoIsFramebuffer(GLuint client_id
);
1574 bool DoIsProgram(GLuint client_id
);
1575 bool DoIsRenderbuffer(GLuint client_id
);
1576 bool DoIsShader(GLuint client_id
);
1577 bool DoIsTexture(GLuint client_id
);
1578 bool DoIsVertexArrayOES(GLuint client_id
);
1579 bool DoIsPathCHROMIUM(GLuint client_id
);
1581 // Wrapper for glLinkProgram
1582 void DoLinkProgram(GLuint program
);
1584 // Wrapper for glReadBuffer
1585 void DoReadBuffer(GLenum src
);
1587 // Wrapper for glRenderbufferStorage.
1588 void DoRenderbufferStorage(
1589 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
);
1591 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1592 void DoRenderbufferStorageMultisampleCHROMIUM(
1593 GLenum target
, GLsizei samples
, GLenum internalformat
,
1594 GLsizei width
, GLsizei height
);
1596 // Handler for glRenderbufferStorageMultisampleEXT
1597 // (multisampled_render_to_texture).
1598 void DoRenderbufferStorageMultisampleEXT(
1599 GLenum target
, GLsizei samples
, GLenum internalformat
,
1600 GLsizei width
, GLsizei height
);
1602 // Common validation for multisample extensions.
1603 bool ValidateRenderbufferStorageMultisample(GLsizei samples
,
1604 GLenum internalformat
,
1608 // Verifies that the currently bound multisample renderbuffer is valid
1609 // Very slow! Only done on platforms with driver bugs that return invalid
1610 // buffers under memory pressure
1611 bool VerifyMultisampleRenderbufferIntegrity(
1612 GLuint renderbuffer
, GLenum format
);
1614 // Wrapper for glReleaseShaderCompiler.
1615 void DoReleaseShaderCompiler() { }
1617 // Wrappers for glSamplerParameter*v functions.
1618 void DoSamplerParameterfv(
1619 GLuint sampler
, GLenum pname
, const GLfloat
* params
);
1620 void DoSamplerParameteriv(GLuint sampler
, GLenum pname
, const GLint
* params
);
1622 // Wrappers for glTexParameter functions.
1623 void DoTexParameterf(GLenum target
, GLenum pname
, GLfloat param
);
1624 void DoTexParameteri(GLenum target
, GLenum pname
, GLint param
);
1625 void DoTexParameterfv(GLenum target
, GLenum pname
, const GLfloat
* params
);
1626 void DoTexParameteriv(GLenum target
, GLenum pname
, const GLint
* params
);
1628 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1629 // spec only these 2 functions can be used to set sampler uniforms.
1630 void DoUniform1i(GLint fake_location
, GLint v0
);
1631 void DoUniform1iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1632 void DoUniform2iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1633 void DoUniform3iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1634 void DoUniform4iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1636 // Wrappers for glUniformfv because some drivers don't correctly accept
1638 void DoUniform1fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1639 void DoUniform2fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1640 void DoUniform3fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1641 void DoUniform4fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1643 void DoUniformMatrix2fv(
1644 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1645 const GLfloat
* value
);
1646 void DoUniformMatrix3fv(
1647 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1648 const GLfloat
* value
);
1649 void DoUniformMatrix4fv(
1650 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1651 const GLfloat
* value
);
1653 template <typename T
>
1654 bool SetVertexAttribValue(
1655 const char* function_name
, GLuint index
, const T
* value
);
1657 // Wrappers for glVertexAttrib??
1658 void DoVertexAttrib1f(GLuint index
, GLfloat v0
);
1659 void DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
);
1660 void DoVertexAttrib3f(GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
);
1661 void DoVertexAttrib4f(
1662 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
);
1663 void DoVertexAttrib1fv(GLuint index
, const GLfloat
* v
);
1664 void DoVertexAttrib2fv(GLuint index
, const GLfloat
* v
);
1665 void DoVertexAttrib3fv(GLuint index
, const GLfloat
* v
);
1666 void DoVertexAttrib4fv(GLuint index
, const GLfloat
* v
);
1667 void DoVertexAttribI4i(GLuint index
, GLint v0
, GLint v1
, GLint v2
, GLint v3
);
1668 void DoVertexAttribI4iv(GLuint index
, const GLint
* v
);
1669 void DoVertexAttribI4ui(
1670 GLuint index
, GLuint v0
, GLuint v1
, GLuint v2
, GLuint v3
);
1671 void DoVertexAttribI4uiv(GLuint index
, const GLuint
* v
);
1673 // Wrapper for glViewport
1674 void DoViewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
1676 // Wrapper for glUseProgram
1677 void DoUseProgram(GLuint program
);
1679 // Wrapper for glValidateProgram.
1680 void DoValidateProgram(GLuint program_client_id
);
1682 void DoInsertEventMarkerEXT(GLsizei length
, const GLchar
* marker
);
1683 void DoPushGroupMarkerEXT(GLsizei length
, const GLchar
* group
);
1684 void DoPopGroupMarkerEXT(void);
1686 // Gets the number of values that will be returned by glGetXXX. Returns
1687 // false if pname is unknown.
1688 bool GetNumValuesReturnedForGLGet(GLenum pname
, GLsizei
* num_values
);
1690 // Checks if the current program and vertex attributes are valid for drawing.
1692 const char* function_name
, GLuint max_vertex_accessed
, bool instanced
,
1695 // Returns true if successful, simulated will be true if attrib0 was
1697 bool SimulateAttrib0(
1698 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
);
1699 void RestoreStateForAttrib(GLuint attrib
, bool restore_array_binding
);
1701 // If an image is bound to texture, this will call Will/DidUseTexImage
1703 void DoWillUseTexImageIfNeeded(Texture
* texture
, GLenum textarget
);
1704 void DoDidUseTexImageIfNeeded(Texture
* texture
, GLenum textarget
);
1706 // Returns false if textures were replaced.
1707 bool PrepareTexturesForRender();
1708 void RestoreStateForTextures();
1710 // Returns true if GL_FIXED attribs were simulated.
1711 bool SimulateFixedAttribs(
1712 const char* function_name
,
1713 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
);
1714 void RestoreStateForSimulatedFixedAttribs();
1716 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1717 // cases (primcount is always 1 for non-instanced).
1718 error::Error
DoDrawArrays(
1719 const char* function_name
,
1720 bool instanced
, GLenum mode
, GLint first
, GLsizei count
,
1722 error::Error
DoDrawElements(
1723 const char* function_name
,
1724 bool instanced
, GLenum mode
, GLsizei count
, GLenum type
,
1725 int32 offset
, GLsizei primcount
);
1727 GLenum
GetBindTargetForSamplerType(GLenum type
) {
1728 DCHECK(type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_CUBE
||
1729 type
== GL_SAMPLER_EXTERNAL_OES
|| type
== GL_SAMPLER_2D_RECT_ARB
);
1732 return GL_TEXTURE_2D
;
1733 case GL_SAMPLER_CUBE
:
1734 return GL_TEXTURE_CUBE_MAP
;
1735 case GL_SAMPLER_EXTERNAL_OES
:
1736 return GL_TEXTURE_EXTERNAL_OES
;
1737 case GL_SAMPLER_2D_RECT_ARB
:
1738 return GL_TEXTURE_RECTANGLE_ARB
;
1745 // Gets the framebuffer info for a particular target.
1746 Framebuffer
* GetFramebufferInfoForTarget(GLenum target
) {
1747 Framebuffer
* framebuffer
= NULL
;
1749 case GL_FRAMEBUFFER
:
1750 case GL_DRAW_FRAMEBUFFER_EXT
:
1751 framebuffer
= framebuffer_state_
.bound_draw_framebuffer
.get();
1753 case GL_READ_FRAMEBUFFER_EXT
:
1754 framebuffer
= framebuffer_state_
.bound_read_framebuffer
.get();
1763 Renderbuffer
* GetRenderbufferInfoForTarget(
1765 Renderbuffer
* renderbuffer
= NULL
;
1767 case GL_RENDERBUFFER
:
1768 renderbuffer
= state_
.bound_renderbuffer
.get();
1774 return renderbuffer
;
1777 // Validates the program and location for a glGetUniform call and returns
1778 // a SizeResult setup to receive the result. Returns true if glGetUniform
1779 // should be called.
1781 bool GetUniformSetup(GLuint program
,
1782 GLint fake_location
,
1785 error::Error
* error
,
1786 GLint
* real_location
,
1788 SizedResult
<T
>** result
,
1789 GLenum
* result_type
,
1790 GLsizei
* result_size
);
1792 bool WasContextLost() const override
;
1793 bool WasContextLostByRobustnessExtension() const override
;
1794 void MarkContextLost(error::ContextLostReason reason
) override
;
1795 bool CheckResetStatus();
1797 #if defined(OS_MACOSX)
1798 void ReleaseIOSurfaceForTexture(GLuint texture_id
);
1801 bool GetCompressedTexSizeInBytes(
1802 const char* function_name
, GLsizei width
, GLsizei height
, GLsizei depth
,
1803 GLenum format
, GLsizei
* size_in_bytes
);
1805 bool ValidateCompressedTexDimensions(
1806 const char* function_name
, GLenum target
, GLint level
,
1807 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
);
1808 bool ValidateCompressedTexFuncData(
1809 const char* function_name
, GLsizei width
, GLsizei height
, GLsizei depth
,
1810 GLenum format
, GLsizei size
);
1811 bool ValidateCompressedTexSubDimensions(
1812 const char* function_name
,
1813 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
1814 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
,
1816 bool ValidateCopyTextureCHROMIUM(const char* function_name
,
1818 TextureRef
* source_texture_ref
,
1819 TextureRef
* dest_texture_ref
,
1820 GLenum dest_internal_format
);
1821 bool ValidateCompressedCopyTextureCHROMIUM(const char* function_name
,
1823 TextureRef
* source_texture_ref
,
1824 TextureRef
* dest_texture_ref
);
1826 void RenderWarning(const char* filename
, int line
, const std::string
& msg
);
1827 void PerformanceWarning(
1828 const char* filename
, int line
, const std::string
& msg
);
1830 const FeatureInfo::FeatureFlags
& features() const {
1831 return feature_info_
->feature_flags();
1834 const FeatureInfo::Workarounds
& workarounds() const {
1835 return feature_info_
->workarounds();
1838 bool ShouldDeferDraws() {
1839 return !offscreen_target_frame_buffer_
.get() &&
1840 framebuffer_state_
.bound_draw_framebuffer
.get() == NULL
&&
1841 surface_
->DeferDraws();
1844 bool ShouldDeferReads() {
1845 return !offscreen_target_frame_buffer_
.get() &&
1846 framebuffer_state_
.bound_read_framebuffer
.get() == NULL
&&
1847 surface_
->DeferDraws();
1850 bool IsRobustnessSupported() {
1851 return has_robustness_extension_
&&
1852 context_
->WasAllocatedUsingRobustnessExtension();
1855 error::Error
WillAccessBoundFramebufferForDraw() {
1856 if (ShouldDeferDraws())
1857 return error::kDeferCommandUntilLater
;
1858 if (!offscreen_target_frame_buffer_
.get() &&
1859 !framebuffer_state_
.bound_draw_framebuffer
.get() &&
1860 !surface_
->SetBackbufferAllocation(true))
1861 return error::kLostContext
;
1862 return error::kNoError
;
1865 error::Error
WillAccessBoundFramebufferForRead() {
1866 if (ShouldDeferReads())
1867 return error::kDeferCommandUntilLater
;
1868 if (!offscreen_target_frame_buffer_
.get() &&
1869 !framebuffer_state_
.bound_read_framebuffer
.get() &&
1870 !surface_
->SetBackbufferAllocation(true))
1871 return error::kLostContext
;
1872 return error::kNoError
;
1875 // Set remaining commands to process to 0 to force DoCommands to return
1876 // and allow context preemption and GPU watchdog checks in GpuScheduler().
1877 void ExitCommandProcessingEarly() { commands_to_process_
= 0; }
1879 void ProcessPendingReadPixels(bool did_finish
);
1880 void FinishReadPixels(const cmds::ReadPixels
& c
, GLuint buffer
);
1882 // Generate a member function prototype for each command in an automated and
1884 #define GLES2_CMD_OP(name) \
1885 Error Handle##name(uint32 immediate_data_size, const void* data);
1887 GLES2_COMMAND_LIST(GLES2_CMD_OP
)
1891 // The GL context this decoder renders to on behalf of the client.
1892 scoped_refptr
<gfx::GLSurface
> surface_
;
1893 scoped_refptr
<gfx::GLContext
> context_
;
1895 // The ContextGroup for this decoder uses to track resources.
1896 scoped_refptr
<ContextGroup
> group_
;
1898 DebugMarkerManager debug_marker_manager_
;
1901 // All the state for this context.
1902 ContextState state_
;
1904 // Current width and height of the offscreen frame buffer.
1905 gfx::Size offscreen_size_
;
1907 // Util to help with GL.
1910 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1911 GLuint attrib_0_buffer_id_
;
1913 // The value currently in attrib_0.
1914 Vec4 attrib_0_value_
;
1916 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1917 bool attrib_0_buffer_matches_value_
;
1919 // The size of attrib 0.
1920 GLsizei attrib_0_size_
;
1922 // The buffer used to simulate GL_FIXED attribs.
1923 GLuint fixed_attrib_buffer_id_
;
1925 // The size of fiixed attrib buffer.
1926 GLsizei fixed_attrib_buffer_size_
;
1928 // The offscreen frame buffer that the client renders to. With EGL, the
1929 // depth and stencil buffers are separate. With regular GL there is a single
1930 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1931 // offscreen_target_stencil_render_buffer_ is unused.
1932 scoped_ptr
<BackFramebuffer
> offscreen_target_frame_buffer_
;
1933 scoped_ptr
<BackTexture
> offscreen_target_color_texture_
;
1934 scoped_ptr
<BackRenderbuffer
> offscreen_target_color_render_buffer_
;
1935 scoped_ptr
<BackRenderbuffer
> offscreen_target_depth_render_buffer_
;
1936 scoped_ptr
<BackRenderbuffer
> offscreen_target_stencil_render_buffer_
;
1937 GLenum offscreen_target_color_format_
;
1938 GLenum offscreen_target_depth_format_
;
1939 GLenum offscreen_target_stencil_format_
;
1940 GLsizei offscreen_target_samples_
;
1941 GLboolean offscreen_target_buffer_preserved_
;
1943 // The copy that is saved when SwapBuffers is called.
1944 scoped_ptr
<BackFramebuffer
> offscreen_saved_frame_buffer_
;
1945 scoped_ptr
<BackTexture
> offscreen_saved_color_texture_
;
1946 scoped_refptr
<TextureRef
>
1947 offscreen_saved_color_texture_info_
;
1949 // The copy that is used as the destination for multi-sample resolves.
1950 scoped_ptr
<BackFramebuffer
> offscreen_resolved_frame_buffer_
;
1951 scoped_ptr
<BackTexture
> offscreen_resolved_color_texture_
;
1952 GLenum offscreen_saved_color_format_
;
1954 scoped_ptr
<QueryManager
> query_manager_
;
1956 scoped_ptr
<VertexArrayManager
> vertex_array_manager_
;
1958 scoped_ptr
<ImageManager
> image_manager_
;
1960 base::Callback
<void(gfx::Size
, float)> resize_callback_
;
1962 WaitSyncPointCallback wait_sync_point_callback_
;
1964 ShaderCacheCallback shader_cache_callback_
;
1966 scoped_ptr
<AsyncPixelTransferManager
> async_pixel_transfer_manager_
;
1968 // The format of the back buffer_
1969 GLenum back_buffer_color_format_
;
1970 bool back_buffer_has_depth_
;
1971 bool back_buffer_has_stencil_
;
1972 // This tracks read buffer for both offscreen/onscreen backbuffer cases.
1973 // TODO(zmo): when ES3 APIs are exposed to Nacl, make sure read_buffer_
1974 // setting is set correctly when SwapBuffers().
1975 GLenum back_buffer_read_buffer_
;
1979 // Backbuffer attachments that are currently undefined.
1980 uint32 backbuffer_needs_clear_bits_
;
1982 // The current decoder error communicates the decoder error through command
1983 // processing functions that do not return the error value. Should be set only
1984 // if not returning an error.
1985 error::Error current_decoder_error_
;
1987 bool use_shader_translator_
;
1988 scoped_refptr
<ShaderTranslatorInterface
> vertex_translator_
;
1989 scoped_refptr
<ShaderTranslatorInterface
> fragment_translator_
;
1991 DisallowedFeatures disallowed_features_
;
1993 // Cached from ContextGroup
1994 const Validators
* validators_
;
1995 scoped_refptr
<FeatureInfo
> feature_info_
;
1999 // Number of commands remaining to be processed in DoCommands().
2000 int commands_to_process_
;
2002 bool has_robustness_extension_
;
2003 error::ContextLostReason context_lost_reason_
;
2004 bool context_was_lost_
;
2005 bool reset_by_robustness_extension_
;
2006 bool supports_post_sub_buffer_
;
2008 // Indicates whether this is a context for WebGL1, WebGL2, or others.
2012 unsigned webgl_version_
;
2014 // These flags are used to override the state of the shared feature_info_
2015 // member. Because the same FeatureInfo instance may be shared among many
2016 // contexts, the assumptions on the availablity of extensions in WebGL
2017 // contexts may be broken. These flags override the shared state to preserve
2019 bool derivatives_explicitly_enabled_
;
2020 bool frag_depth_explicitly_enabled_
;
2021 bool draw_buffers_explicitly_enabled_
;
2022 bool shader_texture_lod_explicitly_enabled_
;
2024 bool compile_shader_always_succeeds_
;
2026 // An optional behaviour to lose the context and group when OOM.
2027 bool lose_context_when_out_of_memory_
;
2030 bool service_logging_
;
2032 #if defined(OS_MACOSX)
2033 typedef std::map
<GLuint
, IOSurfaceRef
> TextureToIOSurfaceMap
;
2034 TextureToIOSurfaceMap texture_to_io_surface_map_
;
2037 scoped_ptr
<CopyTextureCHROMIUMResourceManager
> copy_texture_CHROMIUM_
;
2038 scoped_ptr
<ClearFramebufferResourceManager
> clear_framebuffer_blit_
;
2040 // Cached values of the currently assigned viewport dimensions.
2041 GLsizei viewport_max_width_
;
2042 GLsizei viewport_max_height_
;
2044 // Command buffer stats.
2045 base::TimeDelta total_processing_commands_time_
;
2047 // States related to each manager.
2048 DecoderTextureState texture_state_
;
2049 DecoderFramebufferState framebuffer_state_
;
2051 scoped_ptr
<GPUTracer
> gpu_tracer_
;
2052 scoped_ptr
<GPUStateTracer
> gpu_state_tracer_
;
2053 const unsigned char* cb_command_trace_category_
;
2054 const unsigned char* gpu_decoder_category_
;
2055 int gpu_trace_level_
;
2056 bool gpu_trace_commands_
;
2057 bool gpu_debug_commands_
;
2059 std::queue
<linked_ptr
<FenceCallback
> > pending_readpixel_fences_
;
2061 // Used to validate multisample renderbuffers if needed
2062 GLuint validation_texture_
;
2063 GLuint validation_fbo_multisample_
;
2064 GLuint validation_fbo_
;
2066 typedef gpu::gles2::GLES2Decoder::Error (GLES2DecoderImpl::*CmdHandler
)(
2067 uint32 immediate_data_size
,
2070 // A struct to hold info about each command.
2071 struct CommandInfo
{
2072 CmdHandler cmd_handler
;
2073 uint8 arg_flags
; // How to handle the arguments for this command
2074 uint8 cmd_flags
; // How to handle this command
2075 uint16 arg_count
; // How many arguments are expected for this command.
2078 // A table of CommandInfo for all the commands.
2079 static const CommandInfo command_info
[kNumCommands
- kStartPoint
];
2081 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl
);
2084 const GLES2DecoderImpl::CommandInfo
GLES2DecoderImpl::command_info
[] = {
2085 #define GLES2_CMD_OP(name) \
2087 &GLES2DecoderImpl::Handle##name, cmds::name::kArgFlags, \
2088 cmds::name::cmd_flags, \
2089 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, \
2092 GLES2_COMMAND_LIST(GLES2_CMD_OP
)
2096 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
2097 const char* function_name
, ErrorState
* error_state
)
2098 : function_name_(function_name
),
2099 error_state_(error_state
) {
2100 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_
, function_name_
);
2103 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
2104 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_
, function_name_
);
2107 static void RestoreCurrentTextureBindings(ContextState
* state
, GLenum target
) {
2108 TextureUnit
& info
= state
->texture_units
[0];
2110 scoped_refptr
<TextureRef
> texture_ref
;
2113 texture_ref
= info
.bound_texture_2d
;
2115 case GL_TEXTURE_CUBE_MAP
:
2116 texture_ref
= info
.bound_texture_cube_map
;
2118 case GL_TEXTURE_EXTERNAL_OES
:
2119 texture_ref
= info
.bound_texture_external_oes
;
2121 case GL_TEXTURE_RECTANGLE_ARB
:
2122 texture_ref
= info
.bound_texture_rectangle_arb
;
2128 if (texture_ref
.get()) {
2129 last_id
= texture_ref
->service_id();
2134 glBindTexture(target
, last_id
);
2135 glActiveTexture(GL_TEXTURE0
+ state
->active_texture_unit
);
2138 ScopedTextureBinder::ScopedTextureBinder(ContextState
* state
,
2143 ScopedGLErrorSuppressor
suppressor(
2144 "ScopedTextureBinder::ctor", state_
->GetErrorState());
2146 // TODO(apatrick): Check if there are any other states that need to be reset
2147 // before binding a new texture.
2148 glActiveTexture(GL_TEXTURE0
);
2149 glBindTexture(target
, id
);
2152 ScopedTextureBinder::~ScopedTextureBinder() {
2153 ScopedGLErrorSuppressor
suppressor(
2154 "ScopedTextureBinder::dtor", state_
->GetErrorState());
2155 RestoreCurrentTextureBindings(state_
, target_
);
2158 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState
* state
,
2161 ScopedGLErrorSuppressor
suppressor(
2162 "ScopedRenderBufferBinder::ctor", state_
->GetErrorState());
2163 glBindRenderbufferEXT(GL_RENDERBUFFER
, id
);
2166 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
2167 ScopedGLErrorSuppressor
suppressor(
2168 "ScopedRenderBufferBinder::dtor", state_
->GetErrorState());
2169 state_
->RestoreRenderbufferBindings();
2172 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl
* decoder
,
2174 : decoder_(decoder
) {
2175 ScopedGLErrorSuppressor
suppressor(
2176 "ScopedFrameBufferBinder::ctor", decoder_
->GetErrorState());
2177 glBindFramebufferEXT(GL_FRAMEBUFFER
, id
);
2178 decoder
->OnFboChanged();
2181 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
2182 ScopedGLErrorSuppressor
suppressor(
2183 "ScopedFrameBufferBinder::dtor", decoder_
->GetErrorState());
2184 decoder_
->RestoreCurrentFramebufferBindings();
2187 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
2188 GLES2DecoderImpl
* decoder
, bool enforce_internal_framebuffer
, bool internal
)
2189 : decoder_(decoder
) {
2190 resolve_and_bind_
= (
2191 decoder_
->offscreen_target_frame_buffer_
.get() &&
2192 decoder_
->IsOffscreenBufferMultisampled() &&
2193 (!decoder_
->framebuffer_state_
.bound_read_framebuffer
.get() ||
2194 enforce_internal_framebuffer
));
2195 if (!resolve_and_bind_
)
2198 ScopedGLErrorSuppressor
suppressor(
2199 "ScopedResolvedFrameBufferBinder::ctor", decoder_
->GetErrorState());
2200 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
,
2201 decoder_
->offscreen_target_frame_buffer_
->id());
2204 if (!decoder_
->offscreen_resolved_frame_buffer_
.get()) {
2205 decoder_
->offscreen_resolved_frame_buffer_
.reset(
2206 new BackFramebuffer(decoder_
));
2207 decoder_
->offscreen_resolved_frame_buffer_
->Create();
2208 decoder_
->offscreen_resolved_color_texture_
.reset(
2209 new BackTexture(decoder
->memory_tracker(), &decoder
->state_
));
2210 decoder_
->offscreen_resolved_color_texture_
->Create();
2212 DCHECK(decoder_
->offscreen_saved_color_format_
);
2213 decoder_
->offscreen_resolved_color_texture_
->AllocateStorage(
2214 decoder_
->offscreen_size_
, decoder_
->offscreen_saved_color_format_
,
2216 decoder_
->offscreen_resolved_frame_buffer_
->AttachRenderTexture(
2217 decoder_
->offscreen_resolved_color_texture_
.get());
2218 if (decoder_
->offscreen_resolved_frame_buffer_
->CheckStatus() !=
2219 GL_FRAMEBUFFER_COMPLETE
) {
2220 LOG(ERROR
) << "ScopedResolvedFrameBufferBinder failed "
2221 << "because offscreen resolved FBO was incomplete.";
2225 targetid
= decoder_
->offscreen_resolved_frame_buffer_
->id();
2227 targetid
= decoder_
->offscreen_saved_frame_buffer_
->id();
2229 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, targetid
);
2230 const int width
= decoder_
->offscreen_size_
.width();
2231 const int height
= decoder_
->offscreen_size_
.height();
2232 decoder
->state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
2233 decoder
->BlitFramebufferHelper(0,
2241 GL_COLOR_BUFFER_BIT
,
2243 glBindFramebufferEXT(GL_FRAMEBUFFER
, targetid
);
2246 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
2247 if (!resolve_and_bind_
)
2250 ScopedGLErrorSuppressor
suppressor(
2251 "ScopedResolvedFrameBufferBinder::dtor", decoder_
->GetErrorState());
2252 decoder_
->RestoreCurrentFramebufferBindings();
2253 if (decoder_
->state_
.enable_flags
.scissor_test
) {
2254 decoder_
->state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
2258 BackTexture::BackTexture(
2259 MemoryTracker
* memory_tracker
,
2260 ContextState
* state
)
2261 : memory_tracker_(memory_tracker
, MemoryTracker::kUnmanaged
),
2263 bytes_allocated_(0),
2267 BackTexture::~BackTexture() {
2268 // This does not destroy the render texture because that would require that
2269 // the associated GL context was current. Just check that it was explicitly
2274 void BackTexture::Create() {
2275 ScopedGLErrorSuppressor
suppressor("BackTexture::Create",
2276 state_
->GetErrorState());
2278 glGenTextures(1, &id_
);
2279 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2280 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
2281 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
2282 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
2283 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
2285 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
2286 // never called on an offscreen context, no data will ever be uploaded to the
2287 // saved offscreen color texture (it is deferred until to when SwapBuffers
2288 // is called). My idea is that some nvidia drivers might have a bug where
2289 // deleting a texture that has never been populated might cause a
2292 GL_TEXTURE_2D
, 0, GL_RGBA
, 16, 16, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, NULL
);
2294 bytes_allocated_
= 16u * 16u * 4u;
2295 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2298 bool BackTexture::AllocateStorage(
2299 const gfx::Size
& size
, GLenum format
, bool zero
) {
2301 ScopedGLErrorSuppressor
suppressor("BackTexture::AllocateStorage",
2302 state_
->GetErrorState());
2303 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2304 uint32 image_size
= 0;
2305 GLES2Util::ComputeImageDataSizes(
2306 size
.width(), size
.height(), 1, format
, GL_UNSIGNED_BYTE
, 8, &image_size
,
2309 if (!memory_tracker_
.EnsureGPUMemoryAvailable(image_size
)) {
2313 scoped_ptr
<char[]> zero_data
;
2315 zero_data
.reset(new char[image_size
]);
2316 memset(zero_data
.get(), 0, image_size
);
2319 glTexImage2D(GL_TEXTURE_2D
,
2331 bool success
= glGetError() == GL_NO_ERROR
;
2333 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2334 bytes_allocated_
= image_size
;
2335 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2340 void BackTexture::Copy(const gfx::Size
& size
, GLenum format
) {
2342 ScopedGLErrorSuppressor
suppressor("BackTexture::Copy",
2343 state_
->GetErrorState());
2344 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2345 glCopyTexImage2D(GL_TEXTURE_2D
,
2354 void BackTexture::Destroy() {
2356 ScopedGLErrorSuppressor
suppressor("BackTexture::Destroy",
2357 state_
->GetErrorState());
2358 glDeleteTextures(1, &id_
);
2361 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2362 bytes_allocated_
= 0;
2365 void BackTexture::Invalidate() {
2369 BackRenderbuffer::BackRenderbuffer(
2370 RenderbufferManager
* renderbuffer_manager
,
2371 MemoryTracker
* memory_tracker
,
2372 ContextState
* state
)
2373 : renderbuffer_manager_(renderbuffer_manager
),
2374 memory_tracker_(memory_tracker
, MemoryTracker::kUnmanaged
),
2376 bytes_allocated_(0),
2380 BackRenderbuffer::~BackRenderbuffer() {
2381 // This does not destroy the render buffer because that would require that
2382 // the associated GL context was current. Just check that it was explicitly
2387 void BackRenderbuffer::Create() {
2388 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Create",
2389 state_
->GetErrorState());
2391 glGenRenderbuffersEXT(1, &id_
);
2394 bool BackRenderbuffer::AllocateStorage(const FeatureInfo
* feature_info
,
2395 const gfx::Size
& size
,
2398 ScopedGLErrorSuppressor
suppressor(
2399 "BackRenderbuffer::AllocateStorage", state_
->GetErrorState());
2400 ScopedRenderBufferBinder
binder(state_
, id_
);
2402 uint32 estimated_size
= 0;
2403 if (!renderbuffer_manager_
->ComputeEstimatedRenderbufferSize(
2404 size
.width(), size
.height(), samples
, format
, &estimated_size
)) {
2408 if (!memory_tracker_
.EnsureGPUMemoryAvailable(estimated_size
)) {
2413 glRenderbufferStorageEXT(GL_RENDERBUFFER
,
2418 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info
,
2425 bool success
= glGetError() == GL_NO_ERROR
;
2427 // Mark the previously allocated bytes as free.
2428 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2429 bytes_allocated_
= estimated_size
;
2430 // Track the newly allocated bytes.
2431 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2436 void BackRenderbuffer::Destroy() {
2438 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Destroy",
2439 state_
->GetErrorState());
2440 glDeleteRenderbuffersEXT(1, &id_
);
2443 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2444 bytes_allocated_
= 0;
2447 void BackRenderbuffer::Invalidate() {
2451 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl
* decoder
)
2452 : decoder_(decoder
),
2456 BackFramebuffer::~BackFramebuffer() {
2457 // This does not destroy the frame buffer because that would require that
2458 // the associated GL context was current. Just check that it was explicitly
2463 void BackFramebuffer::Create() {
2464 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Create",
2465 decoder_
->GetErrorState());
2467 glGenFramebuffersEXT(1, &id_
);
2470 void BackFramebuffer::AttachRenderTexture(BackTexture
* texture
) {
2472 ScopedGLErrorSuppressor
suppressor(
2473 "BackFramebuffer::AttachRenderTexture", decoder_
->GetErrorState());
2474 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2475 GLuint attach_id
= texture
? texture
->id() : 0;
2476 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
,
2477 GL_COLOR_ATTACHMENT0
,
2483 void BackFramebuffer::AttachRenderBuffer(GLenum target
,
2484 BackRenderbuffer
* render_buffer
) {
2486 ScopedGLErrorSuppressor
suppressor(
2487 "BackFramebuffer::AttachRenderBuffer", decoder_
->GetErrorState());
2488 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2489 GLuint attach_id
= render_buffer
? render_buffer
->id() : 0;
2490 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
,
2496 void BackFramebuffer::Destroy() {
2498 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Destroy",
2499 decoder_
->GetErrorState());
2500 glDeleteFramebuffersEXT(1, &id_
);
2505 void BackFramebuffer::Invalidate() {
2509 GLenum
BackFramebuffer::CheckStatus() {
2511 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::CheckStatus",
2512 decoder_
->GetErrorState());
2513 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2514 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER
);
2517 GLES2Decoder
* GLES2Decoder::Create(ContextGroup
* group
) {
2518 return new GLES2DecoderImpl(group
);
2521 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup
* group
)
2524 logger_(&debug_marker_manager_
),
2525 state_(group_
->feature_info(), this, &logger_
),
2526 attrib_0_buffer_id_(0),
2527 attrib_0_buffer_matches_value_(true),
2529 fixed_attrib_buffer_id_(0),
2530 fixed_attrib_buffer_size_(0),
2531 offscreen_target_color_format_(0),
2532 offscreen_target_depth_format_(0),
2533 offscreen_target_stencil_format_(0),
2534 offscreen_target_samples_(0),
2535 offscreen_target_buffer_preserved_(true),
2536 offscreen_saved_color_format_(0),
2537 back_buffer_color_format_(0),
2538 back_buffer_has_depth_(false),
2539 back_buffer_has_stencil_(false),
2540 back_buffer_read_buffer_(GL_BACK
),
2541 surfaceless_(false),
2542 backbuffer_needs_clear_bits_(0),
2543 current_decoder_error_(error::kNoError
),
2544 use_shader_translator_(true),
2545 validators_(group_
->feature_info()->validators()),
2546 feature_info_(group_
->feature_info()),
2548 has_robustness_extension_(false),
2549 context_lost_reason_(error::kUnknown
),
2550 context_was_lost_(false),
2551 reset_by_robustness_extension_(false),
2552 supports_post_sub_buffer_(false),
2554 derivatives_explicitly_enabled_(false),
2555 frag_depth_explicitly_enabled_(false),
2556 draw_buffers_explicitly_enabled_(false),
2557 shader_texture_lod_explicitly_enabled_(false),
2558 compile_shader_always_succeeds_(false),
2559 lose_context_when_out_of_memory_(false),
2560 service_logging_(base::CommandLine::ForCurrentProcess()->HasSwitch(
2561 switches::kEnableGPUServiceLoggingGPU
)),
2562 viewport_max_width_(0),
2563 viewport_max_height_(0),
2564 texture_state_(group_
->feature_info()
2566 .texsubimage_faster_than_teximage
),
2567 cb_command_trace_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2568 TRACE_DISABLED_BY_DEFAULT("cb_command"))),
2569 gpu_decoder_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2570 TRACE_DISABLED_BY_DEFAULT("gpu_decoder"))),
2571 gpu_trace_level_(2),
2572 gpu_trace_commands_(false),
2573 gpu_debug_commands_(false),
2574 validation_texture_(0),
2575 validation_fbo_multisample_(0),
2576 validation_fbo_(0) {
2579 // The shader translator is used for WebGL even when running on EGL
2580 // because additional restrictions are needed (like only enabling
2581 // GL_OES_standard_derivatives on demand). It is used for the unit
2582 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2583 // the empty string to CompileShader and this is not a valid shader.
2584 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL
||
2585 base::CommandLine::ForCurrentProcess()->HasSwitch(
2586 switches::kDisableGLSLTranslator
)) {
2587 use_shader_translator_
= false;
2591 GLES2DecoderImpl::~GLES2DecoderImpl() {
2594 bool GLES2DecoderImpl::Initialize(
2595 const scoped_refptr
<gfx::GLSurface
>& surface
,
2596 const scoped_refptr
<gfx::GLContext
>& context
,
2598 const gfx::Size
& offscreen_size
,
2599 const DisallowedFeatures
& disallowed_features
,
2600 const std::vector
<int32
>& attribs
) {
2601 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2602 DCHECK(context
->IsCurrent(surface
.get()));
2603 DCHECK(!context_
.get());
2604 DCHECK(!offscreen
|| !offscreen_size
.IsEmpty());
2606 ContextCreationAttribHelper attrib_parser
;
2607 if (!attrib_parser
.Parse(attribs
))
2609 webgl_version_
= attrib_parser
.webgl_version
;
2611 surfaceless_
= surface
->IsSurfaceless() && !offscreen
;
2614 gpu_state_tracer_
= GPUStateTracer::Create(&state_
);
2616 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2617 switches::kEnableGPUDebugging
)) {
2621 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2622 switches::kEnableGPUCommandLogging
)) {
2623 set_log_commands(true);
2626 compile_shader_always_succeeds_
=
2627 base::CommandLine::ForCurrentProcess()->HasSwitch(
2628 switches::kCompileShaderAlwaysSucceeds
);
2630 // Take ownership of the context and surface. The surface can be replaced with
2635 // Create GPU Tracer for timing values.
2636 gpu_tracer_
.reset(new GPUTracer(this));
2638 if (feature_info_
->workarounds().disable_timestamp_queries
) {
2639 // Forcing time elapsed query for any GPU Timing Client forces it for all
2640 // clients in the context.
2641 GetGLContext()->CreateGPUTimingClient()->ForceTimeElapsedQuery();
2644 // Save the loseContextWhenOutOfMemory context creation attribute.
2645 lose_context_when_out_of_memory_
=
2646 attrib_parser
.lose_context_when_out_of_memory
;
2648 // If the failIfMajorPerformanceCaveat context creation attribute was true
2649 // and we are using a software renderer, fail.
2650 if (attrib_parser
.fail_if_major_perf_caveat
&&
2651 feature_info_
->feature_flags().is_swiftshader
) {
2652 group_
= NULL
; // Must not destroy ContextGroup if it is not initialized.
2657 disallowed_features_
= disallowed_features
;
2658 if (webgl_version_
== 1) {
2659 disallowed_features_
.npot_support
= true;
2662 if (!group_
->Initialize(this,
2663 ContextGroup::GetContextType(webgl_version_
),
2664 disallowed_features_
)) {
2665 group_
= NULL
; // Must not destroy ContextGroup if it is not initialized.
2671 if (webgl_version_
== 2) {
2672 if (!feature_info_
->IsES3Capable()) {
2673 LOG(ERROR
) << "Underlying driver does not support ES3.";
2677 feature_info_
->EnableES3Validators();
2678 set_unsafe_es3_apis_enabled(true);
2681 state_
.attrib_values
.resize(group_
->max_vertex_attribs());
2682 vertex_array_manager_
.reset(new VertexArrayManager());
2684 GLuint default_vertex_attrib_service_id
= 0;
2685 if (features().native_vertex_array_object
) {
2686 glGenVertexArraysOES(1, &default_vertex_attrib_service_id
);
2687 glBindVertexArrayOES(default_vertex_attrib_service_id
);
2690 state_
.default_vertex_attrib_manager
=
2691 CreateVertexAttribManager(0, default_vertex_attrib_service_id
, false);
2693 state_
.default_vertex_attrib_manager
->Initialize(
2694 group_
->max_vertex_attribs(),
2695 feature_info_
->workarounds().init_vertex_attributes
);
2697 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2698 DoBindVertexArrayOES(0);
2700 query_manager_
.reset(new QueryManager(this, feature_info_
.get()));
2702 image_manager_
.reset(new ImageManager
);
2704 util_
.set_num_compressed_texture_formats(
2705 validators_
->compressed_texture_format
.GetValues().size());
2707 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
2708 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2709 // OpenGL ES 2.0 does not have this issue.
2710 glEnableVertexAttribArray(0);
2712 glGenBuffersARB(1, &attrib_0_buffer_id_
);
2713 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
2714 glVertexAttribPointer(0, 1, GL_FLOAT
, GL_FALSE
, 0, NULL
);
2715 glBindBuffer(GL_ARRAY_BUFFER
, 0);
2716 glGenBuffersARB(1, &fixed_attrib_buffer_id_
);
2718 state_
.texture_units
.resize(group_
->max_texture_units());
2719 for (uint32 tt
= 0; tt
< state_
.texture_units
.size(); ++tt
) {
2720 glActiveTexture(GL_TEXTURE0
+ tt
);
2721 // We want the last bind to be 2D.
2723 if (features().oes_egl_image_external
) {
2724 ref
= texture_manager()->GetDefaultTextureInfo(
2725 GL_TEXTURE_EXTERNAL_OES
);
2726 state_
.texture_units
[tt
].bound_texture_external_oes
= ref
;
2727 glBindTexture(GL_TEXTURE_EXTERNAL_OES
, ref
? ref
->service_id() : 0);
2729 if (features().arb_texture_rectangle
) {
2730 ref
= texture_manager()->GetDefaultTextureInfo(
2731 GL_TEXTURE_RECTANGLE_ARB
);
2732 state_
.texture_units
[tt
].bound_texture_rectangle_arb
= ref
;
2733 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, ref
? ref
->service_id() : 0);
2735 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP
);
2736 state_
.texture_units
[tt
].bound_texture_cube_map
= ref
;
2737 glBindTexture(GL_TEXTURE_CUBE_MAP
, ref
? ref
->service_id() : 0);
2738 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D
);
2739 state_
.texture_units
[tt
].bound_texture_2d
= ref
;
2740 glBindTexture(GL_TEXTURE_2D
, ref
? ref
->service_id() : 0);
2742 glActiveTexture(GL_TEXTURE0
);
2745 // cache ALPHA_BITS result for re-use with clear behaviour
2746 GLint alpha_bits
= 0;
2749 if (attrib_parser
.samples
> 0 && attrib_parser
.sample_buffers
> 0 &&
2750 features().chromium_framebuffer_multisample
) {
2751 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2752 // max_sample_count must be initialized to a sane value. If
2753 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2754 GLint max_sample_count
= 1;
2755 glGetIntegerv(GL_MAX_SAMPLES_EXT
, &max_sample_count
);
2756 offscreen_target_samples_
= std::min(attrib_parser
.samples
,
2759 offscreen_target_samples_
= 1;
2761 offscreen_target_buffer_preserved_
= attrib_parser
.buffer_preserved
;
2763 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
2764 const bool rgb8_supported
=
2765 context_
->HasExtension("GL_OES_rgb8_rgba8");
2766 // The only available default render buffer formats in GLES2 have very
2767 // little precision. Don't enable multisampling unless 8-bit render
2768 // buffer formats are available--instead fall back to 8-bit textures.
2769 if (rgb8_supported
&& offscreen_target_samples_
> 1) {
2770 offscreen_target_color_format_
= attrib_parser
.alpha_size
> 0 ?
2773 offscreen_target_samples_
= 1;
2774 offscreen_target_color_format_
=
2775 attrib_parser
.alpha_size
> 0 || workarounds().disable_gl_rgb_format
2780 // ANGLE only supports packed depth/stencil formats, so use it if it is
2782 const bool depth24_stencil8_supported
=
2783 feature_info_
->feature_flags().packed_depth24_stencil8
;
2784 VLOG(1) << "GL_OES_packed_depth_stencil "
2785 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2786 if ((attrib_parser
.depth_size
> 0 || attrib_parser
.stencil_size
> 0) &&
2787 depth24_stencil8_supported
) {
2788 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2789 offscreen_target_stencil_format_
= 0;
2791 // It may be the case that this depth/stencil combination is not
2792 // supported, but this will be checked later by CheckFramebufferStatus.
2793 offscreen_target_depth_format_
= attrib_parser
.depth_size
> 0 ?
2794 GL_DEPTH_COMPONENT16
: 0;
2795 offscreen_target_stencil_format_
= attrib_parser
.stencil_size
> 0 ?
2796 GL_STENCIL_INDEX8
: 0;
2799 offscreen_target_color_format_
=
2800 attrib_parser
.alpha_size
> 0 || workarounds().disable_gl_rgb_format
2804 // If depth is requested at all, use the packed depth stencil format if
2805 // it's available, as some desktop GL drivers don't support any non-packed
2806 // formats for depth attachments.
2807 const bool depth24_stencil8_supported
=
2808 feature_info_
->feature_flags().packed_depth24_stencil8
;
2809 VLOG(1) << "GL_EXT_packed_depth_stencil "
2810 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2812 if ((attrib_parser
.depth_size
> 0 || attrib_parser
.stencil_size
> 0) &&
2813 depth24_stencil8_supported
) {
2814 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2815 offscreen_target_stencil_format_
= 0;
2817 offscreen_target_depth_format_
= attrib_parser
.depth_size
> 0 ?
2818 GL_DEPTH_COMPONENT
: 0;
2819 offscreen_target_stencil_format_
= attrib_parser
.stencil_size
> 0 ?
2820 GL_STENCIL_INDEX
: 0;
2824 offscreen_saved_color_format_
=
2825 attrib_parser
.alpha_size
> 0 || workarounds().disable_gl_rgb_format
2829 // Create the target frame buffer. This is the one that the client renders
2831 offscreen_target_frame_buffer_
.reset(new BackFramebuffer(this));
2832 offscreen_target_frame_buffer_
->Create();
2833 // Due to GLES2 format limitations, either the color texture (for
2834 // non-multisampling) or the color render buffer (for multisampling) will be
2835 // attached to the offscreen frame buffer. The render buffer has more
2836 // limited formats available to it, but the texture can't do multisampling.
2837 if (IsOffscreenBufferMultisampled()) {
2838 offscreen_target_color_render_buffer_
.reset(new BackRenderbuffer(
2839 renderbuffer_manager(), memory_tracker(), &state_
));
2840 offscreen_target_color_render_buffer_
->Create();
2842 offscreen_target_color_texture_
.reset(new BackTexture(
2843 memory_tracker(), &state_
));
2844 offscreen_target_color_texture_
->Create();
2846 offscreen_target_depth_render_buffer_
.reset(new BackRenderbuffer(
2847 renderbuffer_manager(), memory_tracker(), &state_
));
2848 offscreen_target_depth_render_buffer_
->Create();
2849 offscreen_target_stencil_render_buffer_
.reset(new BackRenderbuffer(
2850 renderbuffer_manager(), memory_tracker(), &state_
));
2851 offscreen_target_stencil_render_buffer_
->Create();
2853 // Create the saved offscreen texture. The target frame buffer is copied
2854 // here when SwapBuffers is called.
2855 offscreen_saved_frame_buffer_
.reset(new BackFramebuffer(this));
2856 offscreen_saved_frame_buffer_
->Create();
2858 offscreen_saved_color_texture_
.reset(new BackTexture(
2859 memory_tracker(), &state_
));
2860 offscreen_saved_color_texture_
->Create();
2862 // Allocate the render buffers at their initial size and check the status
2863 // of the frame buffers is okay.
2864 if (!ResizeOffscreenFrameBuffer(offscreen_size
)) {
2865 LOG(ERROR
) << "Could not allocate offscreen buffer storage.";
2870 state_
.viewport_width
= offscreen_size
.width();
2871 state_
.viewport_height
= offscreen_size
.height();
2873 // Allocate the offscreen saved color texture.
2874 DCHECK(offscreen_saved_color_format_
);
2875 offscreen_saved_color_texture_
->AllocateStorage(
2876 gfx::Size(1, 1), offscreen_saved_color_format_
, true);
2878 offscreen_saved_frame_buffer_
->AttachRenderTexture(
2879 offscreen_saved_color_texture_
.get());
2880 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
2881 GL_FRAMEBUFFER_COMPLETE
) {
2882 LOG(ERROR
) << "Offscreen saved FBO was incomplete.";
2887 // Bind to the new default frame buffer (the offscreen target frame buffer).
2888 // This should now be associated with ID zero.
2889 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
2891 glBindFramebufferEXT(GL_FRAMEBUFFER
, GetBackbufferServiceId());
2892 // These are NOT if the back buffer has these proprorties. They are
2893 // if we want the command buffer to enforce them regardless of what
2894 // the real backbuffer is assuming the real back buffer gives us more than
2895 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2896 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2897 // can't do anything about that.
2899 if (!surfaceless_
) {
2900 GLint depth_bits
= 0;
2901 GLint stencil_bits
= 0;
2903 bool default_fb
= (GetBackbufferServiceId() == 0);
2905 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
2906 glGetFramebufferAttachmentParameterivEXT(
2908 default_fb
? GL_BACK_LEFT
: GL_COLOR_ATTACHMENT0
,
2909 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE
, &alpha_bits
);
2910 glGetFramebufferAttachmentParameterivEXT(
2912 default_fb
? GL_DEPTH
: GL_DEPTH_ATTACHMENT
,
2913 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE
, &depth_bits
);
2914 glGetFramebufferAttachmentParameterivEXT(
2916 default_fb
? GL_STENCIL
: GL_STENCIL_ATTACHMENT
,
2917 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE
, &stencil_bits
);
2919 glGetIntegerv(GL_ALPHA_BITS
, &alpha_bits
);
2920 glGetIntegerv(GL_DEPTH_BITS
, &depth_bits
);
2921 glGetIntegerv(GL_STENCIL_BITS
, &stencil_bits
);
2924 // This checks if the user requested RGBA and we have RGBA then RGBA. If
2925 // the user requested RGB then RGB. If the user did not specify a
2926 // preference than use whatever we were given. Same for DEPTH and STENCIL.
2927 back_buffer_color_format_
=
2928 (attrib_parser
.alpha_size
!= 0 && alpha_bits
> 0) ? GL_RGBA
: GL_RGB
;
2929 back_buffer_has_depth_
= attrib_parser
.depth_size
!= 0 && depth_bits
> 0;
2930 back_buffer_has_stencil_
=
2931 attrib_parser
.stencil_size
!= 0 && stencil_bits
> 0;
2934 state_
.viewport_width
= surface
->GetSize().width();
2935 state_
.viewport_height
= surface
->GetSize().height();
2938 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2939 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2940 // isn't well documented; it was discovered in the Khronos OpenGL ES
2941 // mailing list archives. It also implicitly enables the desktop GL
2942 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2943 // variable in fragment shaders.
2944 if (!feature_info_
->gl_version_info().BehavesLikeGLES()) {
2945 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE
);
2946 glEnable(GL_POINT_SPRITE
);
2949 has_robustness_extension_
=
2950 context
->HasExtension("GL_ARB_robustness") ||
2951 context
->HasExtension("GL_KHR_robustness") ||
2952 context
->HasExtension("GL_EXT_robustness");
2954 if (!InitializeShaderTranslator()) {
2958 GLint viewport_params
[4] = { 0 };
2959 glGetIntegerv(GL_MAX_VIEWPORT_DIMS
, viewport_params
);
2960 viewport_max_width_
= viewport_params
[0];
2961 viewport_max_height_
= viewport_params
[1];
2963 state_
.scissor_width
= state_
.viewport_width
;
2964 state_
.scissor_height
= state_
.viewport_height
;
2966 // Set all the default state because some GL drivers get it wrong.
2967 state_
.InitCapabilities(NULL
);
2968 state_
.InitState(NULL
);
2969 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
2971 DoBindBuffer(GL_ARRAY_BUFFER
, 0);
2972 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
2973 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
2974 DoBindRenderbuffer(GL_RENDERBUFFER
, 0);
2975 DoBindValueBufferCHROMIUM(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM
, 0);
2977 bool call_gl_clear
= !surfaceless_
;
2978 #if defined(OS_ANDROID)
2979 // Temporary workaround for Android WebView because this clear ignores the
2980 // clip and corrupts that external UI of the App. Not calling glClear is ok
2981 // because the system already clears the buffer before each draw. Proper
2982 // fix might be setting the scissor clip properly before initialize. See
2983 // crbug.com/259023 for details.
2984 call_gl_clear
= surface_
->GetHandle();
2986 if (call_gl_clear
) {
2987 // On configs where we report no alpha, if the underlying surface has
2988 // alpha, clear the surface alpha to 1.0 to be correct on ReadPixels/etc.
2989 bool clear_alpha
= back_buffer_color_format_
== GL_RGB
&& alpha_bits
> 0;
2991 glClearColor(0.0f
, 0.0f
, 0.0f
, 1.0f
);
2994 // Clear the backbuffer.
2995 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
2997 // Restore alpha clear value if we changed it.
2999 glClearColor(0.0f
, 0.0f
, 0.0f
, 0.0f
);
3003 supports_post_sub_buffer_
= surface
->SupportsPostSubBuffer();
3004 if (feature_info_
->workarounds()
3005 .disable_post_sub_buffers_for_onscreen_surfaces
&&
3006 !surface
->IsOffscreen())
3007 supports_post_sub_buffer_
= false;
3009 if (feature_info_
->workarounds().reverse_point_sprite_coord_origin
) {
3010 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN
, GL_LOWER_LEFT
);
3013 if (feature_info_
->workarounds().unbind_fbo_on_context_switch
) {
3014 context_
->SetUnbindFboOnMakeCurrent();
3017 // Only compositor contexts are known to use only the subset of GL
3018 // that can be safely migrated between the iGPU and the dGPU. Mark
3019 // those contexts as safe to forcibly transition between the GPUs.
3020 // http://crbug.com/180876, http://crbug.com/227228
3022 context_
->SetSafeToForceGpuSwitch();
3024 async_pixel_transfer_manager_
.reset(
3025 AsyncPixelTransferManager::Create(context
.get()));
3026 async_pixel_transfer_manager_
->Initialize(texture_manager());
3028 if (workarounds().gl_clear_broken
) {
3029 DCHECK(!clear_framebuffer_blit_
.get());
3030 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glClearWorkaroundInit");
3031 clear_framebuffer_blit_
.reset(new ClearFramebufferResourceManager(this));
3032 if (LOCAL_PEEK_GL_ERROR("glClearWorkaroundInit") != GL_NO_ERROR
)
3036 framebuffer_manager()->AddObserver(this);
3041 Capabilities
GLES2DecoderImpl::GetCapabilities() {
3042 DCHECK(initialized());
3044 caps
.VisitPrecisions([](GLenum shader
, GLenum type
,
3045 Capabilities::ShaderPrecision
* shader_precision
) {
3046 GLint range
[2] = {0, 0};
3047 GLint precision
= 0;
3048 GetShaderPrecisionFormatImpl(shader
, type
, range
, &precision
);
3049 shader_precision
->min_range
= range
[0];
3050 shader_precision
->max_range
= range
[1];
3051 shader_precision
->precision
= precision
;
3053 DoGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
,
3054 &caps
.max_combined_texture_image_units
);
3055 DoGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE
, &caps
.max_cube_map_texture_size
);
3056 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS
,
3057 &caps
.max_fragment_uniform_vectors
);
3058 DoGetIntegerv(GL_MAX_RENDERBUFFER_SIZE
, &caps
.max_renderbuffer_size
);
3059 DoGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS
, &caps
.max_texture_image_units
);
3060 DoGetIntegerv(GL_MAX_TEXTURE_SIZE
, &caps
.max_texture_size
);
3061 DoGetIntegerv(GL_MAX_VARYING_VECTORS
, &caps
.max_varying_vectors
);
3062 DoGetIntegerv(GL_MAX_VERTEX_ATTRIBS
, &caps
.max_vertex_attribs
);
3063 DoGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS
,
3064 &caps
.max_vertex_texture_image_units
);
3065 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS
,
3066 &caps
.max_vertex_uniform_vectors
);
3067 DoGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS
,
3068 &caps
.num_compressed_texture_formats
);
3069 DoGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS
, &caps
.num_shader_binary_formats
);
3070 DoGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM
,
3071 &caps
.bind_generates_resource_chromium
);
3072 if (unsafe_es3_apis_enabled()) {
3073 // TODO(zmo): Note that some parameter values could be more than 32-bit,
3074 // but for now we clamp them to 32-bit max.
3075 DoGetIntegerv(GL_MAX_3D_TEXTURE_SIZE
, &caps
.max_3d_texture_size
);
3076 DoGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS
, &caps
.max_array_texture_layers
);
3077 DoGetIntegerv(GL_MAX_COLOR_ATTACHMENTS
, &caps
.max_color_attachments
);
3078 DoGetInteger64v(GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS
,
3079 &caps
.max_combined_fragment_uniform_components
);
3080 DoGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS
,
3081 &caps
.max_combined_uniform_blocks
);
3082 DoGetInteger64v(GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS
,
3083 &caps
.max_combined_vertex_uniform_components
);
3084 DoGetIntegerv(GL_MAX_DRAW_BUFFERS
, &caps
.max_draw_buffers
);
3085 DoGetInteger64v(GL_MAX_ELEMENT_INDEX
, &caps
.max_element_index
);
3086 DoGetIntegerv(GL_MAX_ELEMENTS_INDICES
, &caps
.max_elements_indices
);
3087 DoGetIntegerv(GL_MAX_ELEMENTS_VERTICES
, &caps
.max_elements_vertices
);
3088 DoGetIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS
,
3089 &caps
.max_fragment_input_components
);
3090 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS
,
3091 &caps
.max_fragment_uniform_blocks
);
3092 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS
,
3093 &caps
.max_fragment_uniform_components
);
3094 DoGetIntegerv(GL_MAX_PROGRAM_TEXEL_OFFSET
,
3095 &caps
.max_program_texel_offset
);
3096 DoGetInteger64v(GL_MAX_SERVER_WAIT_TIMEOUT
, &caps
.max_server_wait_timeout
);
3097 // Work around Linux NVIDIA driver bug where GL_TIMEOUT_IGNORED is
3099 if (caps
.max_server_wait_timeout
< 0)
3100 caps
.max_server_wait_timeout
= 0;
3101 DoGetFloatv(GL_MAX_TEXTURE_LOD_BIAS
, &caps
.max_texture_lod_bias
);
3102 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS
,
3103 &caps
.max_transform_feedback_interleaved_components
);
3104 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS
,
3105 &caps
.max_transform_feedback_separate_attribs
);
3106 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS
,
3107 &caps
.max_transform_feedback_separate_components
);
3108 DoGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE
, &caps
.max_uniform_block_size
);
3109 DoGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS
,
3110 &caps
.max_uniform_buffer_bindings
);
3111 DoGetIntegerv(GL_MAX_VARYING_COMPONENTS
, &caps
.max_varying_components
);
3112 DoGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS
,
3113 &caps
.max_vertex_output_components
);
3114 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS
,
3115 &caps
.max_vertex_uniform_blocks
);
3116 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS
,
3117 &caps
.max_vertex_uniform_components
);
3118 DoGetIntegerv(GL_MIN_PROGRAM_TEXEL_OFFSET
, &caps
.min_program_texel_offset
);
3119 DoGetIntegerv(GL_NUM_EXTENSIONS
, &caps
.num_extensions
);
3120 DoGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS
,
3121 &caps
.num_program_binary_formats
);
3122 DoGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
,
3123 &caps
.uniform_buffer_offset_alignment
);
3124 // TODO(zmo): once we switch to MANGLE, we should query version numbers.
3125 caps
.major_version
= 3;
3126 caps
.minor_version
= 0;
3128 if (feature_info_
->feature_flags().multisampled_render_to_texture
||
3129 feature_info_
->feature_flags().chromium_framebuffer_multisample
||
3130 unsafe_es3_apis_enabled()) {
3131 DoGetIntegerv(GL_MAX_SAMPLES
, &caps
.max_samples
);
3134 caps
.egl_image_external
=
3135 feature_info_
->feature_flags().oes_egl_image_external
;
3136 caps
.texture_format_atc
=
3137 feature_info_
->feature_flags().ext_texture_format_atc
;
3138 caps
.texture_format_bgra8888
=
3139 feature_info_
->feature_flags().ext_texture_format_bgra8888
;
3140 caps
.texture_format_dxt1
=
3141 feature_info_
->feature_flags().ext_texture_format_dxt1
;
3142 caps
.texture_format_dxt5
=
3143 feature_info_
->feature_flags().ext_texture_format_dxt5
;
3144 caps
.texture_format_etc1
=
3145 feature_info_
->feature_flags().oes_compressed_etc1_rgb8_texture
;
3146 caps
.texture_format_etc1_npot
=
3147 caps
.texture_format_etc1
&& !workarounds().etc1_power_of_two_only
;
3148 caps
.texture_rectangle
= feature_info_
->feature_flags().arb_texture_rectangle
;
3149 caps
.texture_usage
= feature_info_
->feature_flags().angle_texture_usage
;
3150 caps
.texture_storage
= feature_info_
->feature_flags().ext_texture_storage
;
3151 caps
.discard_framebuffer
=
3152 feature_info_
->feature_flags().ext_discard_framebuffer
;
3153 caps
.sync_query
= feature_info_
->feature_flags().chromium_sync_query
;
3155 #if defined(OS_MACOSX)
3156 // This is unconditionally true on mac, no need to test for it at runtime.
3157 caps
.iosurface
= true;
3160 caps
.post_sub_buffer
= supports_post_sub_buffer_
;
3162 caps
.surfaceless
= surfaceless_
;
3164 caps
.blend_equation_advanced
=
3165 feature_info_
->feature_flags().blend_equation_advanced
;
3166 caps
.blend_equation_advanced_coherent
=
3167 feature_info_
->feature_flags().blend_equation_advanced_coherent
;
3168 caps
.texture_rg
= feature_info_
->feature_flags().ext_texture_rg
;
3169 caps
.max_copy_texture_chromium_size
=
3170 feature_info_
->workarounds().max_copy_texture_chromium_size
;
3171 caps
.render_buffer_format_bgra8888
=
3172 feature_info_
->feature_flags().ext_render_buffer_format_bgra8888
;
3173 caps
.occlusion_query_boolean
=
3174 feature_info_
->feature_flags().occlusion_query_boolean
;
3175 caps
.timer_queries
=
3176 query_manager_
->GPUTimingAvailable();
3180 void GLES2DecoderImpl::UpdateCapabilities() {
3181 util_
.set_num_compressed_texture_formats(
3182 validators_
->compressed_texture_format
.GetValues().size());
3183 util_
.set_num_shader_binary_formats(
3184 validators_
->shader_binary_format
.GetValues().size());
3187 bool GLES2DecoderImpl::InitializeShaderTranslator() {
3188 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
3190 if (!use_shader_translator_
) {
3193 ShBuiltInResources resources
;
3194 ShInitBuiltInResources(&resources
);
3195 resources
.MaxVertexAttribs
= group_
->max_vertex_attribs();
3196 resources
.MaxVertexUniformVectors
=
3197 group_
->max_vertex_uniform_vectors();
3198 resources
.MaxVaryingVectors
= group_
->max_varying_vectors();
3199 resources
.MaxVertexTextureImageUnits
=
3200 group_
->max_vertex_texture_image_units();
3201 resources
.MaxCombinedTextureImageUnits
= group_
->max_texture_units();
3202 resources
.MaxTextureImageUnits
= group_
->max_texture_image_units();
3203 resources
.MaxFragmentUniformVectors
=
3204 group_
->max_fragment_uniform_vectors();
3205 resources
.MaxDrawBuffers
= group_
->max_draw_buffers();
3206 resources
.MaxExpressionComplexity
= 256;
3207 resources
.MaxCallStackDepth
= 256;
3209 GLint range
[2] = { 0, 0 };
3210 GLint precision
= 0;
3211 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER
, GL_HIGH_FLOAT
,
3213 resources
.FragmentPrecisionHigh
=
3214 PrecisionMeetsSpecForHighpFloat(range
[0], range
[1], precision
);
3216 if (IsWebGLContext()) {
3217 resources
.OES_standard_derivatives
= derivatives_explicitly_enabled_
;
3218 resources
.EXT_frag_depth
= frag_depth_explicitly_enabled_
;
3219 resources
.EXT_draw_buffers
= draw_buffers_explicitly_enabled_
;
3220 if (!draw_buffers_explicitly_enabled_
)
3221 resources
.MaxDrawBuffers
= 1;
3222 resources
.EXT_shader_texture_lod
= shader_texture_lod_explicitly_enabled_
;
3223 resources
.NV_draw_buffers
=
3224 draw_buffers_explicitly_enabled_
&& features().nv_draw_buffers
;
3226 resources
.OES_standard_derivatives
=
3227 features().oes_standard_derivatives
? 1 : 0;
3228 resources
.ARB_texture_rectangle
=
3229 features().arb_texture_rectangle
? 1 : 0;
3230 resources
.OES_EGL_image_external
=
3231 features().oes_egl_image_external
? 1 : 0;
3232 resources
.EXT_draw_buffers
=
3233 features().ext_draw_buffers
? 1 : 0;
3234 resources
.EXT_frag_depth
=
3235 features().ext_frag_depth
? 1 : 0;
3236 resources
.EXT_shader_texture_lod
=
3237 features().ext_shader_texture_lod
? 1 : 0;
3238 resources
.NV_draw_buffers
=
3239 features().nv_draw_buffers
? 1 : 0;
3242 ShShaderSpec shader_spec
;
3243 if (IsWebGLContext()) {
3244 shader_spec
= webgl_version_
== 2 ? SH_WEBGL2_SPEC
: SH_WEBGL_SPEC
;
3246 shader_spec
= unsafe_es3_apis_enabled() ? SH_GLES3_SPEC
: SH_GLES2_SPEC
;
3249 if ((shader_spec
== SH_WEBGL_SPEC
|| shader_spec
== SH_WEBGL2_SPEC
) &&
3250 features().enable_shader_name_hashing
)
3251 resources
.HashFunction
= &CityHash64
;
3253 resources
.HashFunction
= NULL
;
3254 ShaderTranslatorInterface::GlslImplementationType implementation_type
=
3255 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
?
3256 ShaderTranslatorInterface::kGlslES
: ShaderTranslatorInterface::kGlsl
;
3257 int driver_bug_workarounds
= 0;
3258 if (workarounds().needs_glsl_built_in_function_emulation
)
3259 driver_bug_workarounds
|= SH_EMULATE_BUILT_IN_FUNCTIONS
;
3260 if (workarounds().init_gl_position_in_vertex_shader
)
3261 driver_bug_workarounds
|= SH_INIT_GL_POSITION
;
3262 if (workarounds().unfold_short_circuit_as_ternary_operation
)
3263 driver_bug_workarounds
|= SH_UNFOLD_SHORT_CIRCUIT
;
3264 if (workarounds().init_varyings_without_static_use
)
3265 driver_bug_workarounds
|= SH_INIT_VARYINGS_WITHOUT_STATIC_USE
;
3266 if (workarounds().unroll_for_loop_with_sampler_array_index
)
3267 driver_bug_workarounds
|= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX
;
3268 if (workarounds().scalarize_vec_and_mat_constructor_args
)
3269 driver_bug_workarounds
|= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS
;
3270 if (workarounds().regenerate_struct_names
)
3271 driver_bug_workarounds
|= SH_REGENERATE_STRUCT_NAMES
;
3272 if (workarounds().remove_pow_with_constant_exponent
)
3273 driver_bug_workarounds
|= SH_REMOVE_POW_WITH_CONSTANT_EXPONENT
;
3275 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
3276 switches::kEmulateShaderPrecision
))
3277 resources
.WEBGL_debug_shader_precision
= true;
3279 vertex_translator_
= shader_translator_cache()->GetTranslator(
3283 implementation_type
,
3284 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
3285 if (!vertex_translator_
.get()) {
3286 LOG(ERROR
) << "Could not initialize vertex shader translator.";
3291 fragment_translator_
= shader_translator_cache()->GetTranslator(
3295 implementation_type
,
3296 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
3297 if (!fragment_translator_
.get()) {
3298 LOG(ERROR
) << "Could not initialize fragment shader translator.";
3305 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n
, const GLuint
* client_ids
) {
3306 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3307 if (GetBuffer(client_ids
[ii
])) {
3311 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3312 glGenBuffersARB(n
, service_ids
.get());
3313 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3314 CreateBuffer(client_ids
[ii
], service_ids
[ii
]);
3319 bool GLES2DecoderImpl::GenFramebuffersHelper(
3320 GLsizei n
, const GLuint
* client_ids
) {
3321 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3322 if (GetFramebuffer(client_ids
[ii
])) {
3326 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3327 glGenFramebuffersEXT(n
, service_ids
.get());
3328 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3329 CreateFramebuffer(client_ids
[ii
], service_ids
[ii
]);
3334 bool GLES2DecoderImpl::GenRenderbuffersHelper(
3335 GLsizei n
, const GLuint
* client_ids
) {
3336 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3337 if (GetRenderbuffer(client_ids
[ii
])) {
3341 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3342 glGenRenderbuffersEXT(n
, service_ids
.get());
3343 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3344 CreateRenderbuffer(client_ids
[ii
], service_ids
[ii
]);
3349 bool GLES2DecoderImpl::GenValuebuffersCHROMIUMHelper(GLsizei n
,
3350 const GLuint
* client_ids
) {
3351 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3352 if (GetValuebuffer(client_ids
[ii
])) {
3356 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3357 CreateValuebuffer(client_ids
[ii
]);
3362 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n
, const GLuint
* client_ids
) {
3363 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3364 if (GetTexture(client_ids
[ii
])) {
3368 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3369 glGenTextures(n
, service_ids
.get());
3370 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3371 CreateTexture(client_ids
[ii
], service_ids
[ii
]);
3376 bool GLES2DecoderImpl::GenPathsCHROMIUMHelper(GLuint first_client_id
,
3378 GLuint last_client_id
;
3379 if (!SafeAddUint32(first_client_id
, range
- 1, &last_client_id
))
3382 if (path_manager()->HasPathsInRange(first_client_id
, last_client_id
))
3385 GLuint first_service_id
= glGenPathsNV(range
);
3386 if (first_service_id
== 0) {
3387 // We have to fail the connection here, because client has already
3388 // succeeded in allocating the ids. This happens if we allocate
3389 // the whole path id space (two allocations of 0x7FFFFFFF paths, for
3393 // GenPathsNV does not wrap.
3394 DCHECK(first_service_id
+ range
- 1 >= first_service_id
);
3396 path_manager()->CreatePathRange(first_client_id
, last_client_id
,
3402 bool GLES2DecoderImpl::DeletePathsCHROMIUMHelper(GLuint first_client_id
,
3404 GLuint last_client_id
;
3405 if (!SafeAddUint32(first_client_id
, range
- 1, &last_client_id
))
3408 path_manager()->RemovePaths(first_client_id
, last_client_id
);
3412 void GLES2DecoderImpl::DeleteBuffersHelper(
3413 GLsizei n
, const GLuint
* client_ids
) {
3414 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3415 Buffer
* buffer
= GetBuffer(client_ids
[ii
]);
3416 if (buffer
&& !buffer
->IsDeleted()) {
3417 buffer
->RemoveMappedRange();
3418 state_
.RemoveBoundBuffer(buffer
);
3419 RemoveBuffer(client_ids
[ii
]);
3424 void GLES2DecoderImpl::DeleteFramebuffersHelper(
3425 GLsizei n
, const GLuint
* client_ids
) {
3426 bool supports_separate_framebuffer_binds
=
3427 features().chromium_framebuffer_multisample
;
3429 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3430 Framebuffer
* framebuffer
=
3431 GetFramebuffer(client_ids
[ii
]);
3432 if (framebuffer
&& !framebuffer
->IsDeleted()) {
3433 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
3434 GLenum target
= supports_separate_framebuffer_binds
?
3435 GL_DRAW_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
3437 // Unbind attachments on FBO before deletion.
3438 if (workarounds().unbind_attachments_on_bound_render_fbo_delete
)
3439 framebuffer
->DoUnbindGLAttachmentsForWorkaround(target
);
3441 glBindFramebufferEXT(target
, GetBackbufferServiceId());
3442 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
3443 framebuffer_state_
.clear_state_dirty
= true;
3445 if (framebuffer
== framebuffer_state_
.bound_read_framebuffer
.get()) {
3446 framebuffer_state_
.bound_read_framebuffer
= NULL
;
3447 GLenum target
= supports_separate_framebuffer_binds
?
3448 GL_READ_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
3449 glBindFramebufferEXT(target
, GetBackbufferServiceId());
3452 RemoveFramebuffer(client_ids
[ii
]);
3457 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
3458 GLsizei n
, const GLuint
* client_ids
) {
3459 bool supports_separate_framebuffer_binds
=
3460 features().chromium_framebuffer_multisample
;
3461 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3462 Renderbuffer
* renderbuffer
=
3463 GetRenderbuffer(client_ids
[ii
]);
3464 if (renderbuffer
&& !renderbuffer
->IsDeleted()) {
3465 if (state_
.bound_renderbuffer
.get() == renderbuffer
) {
3466 state_
.bound_renderbuffer
= NULL
;
3468 // Unbind from current framebuffers.
3469 if (supports_separate_framebuffer_binds
) {
3470 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
3471 framebuffer_state_
.bound_read_framebuffer
3472 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT
, renderbuffer
);
3474 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3475 framebuffer_state_
.bound_draw_framebuffer
3476 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT
, renderbuffer
);
3479 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3480 framebuffer_state_
.bound_draw_framebuffer
3481 ->UnbindRenderbuffer(GL_FRAMEBUFFER
, renderbuffer
);
3484 framebuffer_state_
.clear_state_dirty
= true;
3485 RemoveRenderbuffer(client_ids
[ii
]);
3490 void GLES2DecoderImpl::DeleteValuebuffersCHROMIUMHelper(
3492 const GLuint
* client_ids
) {
3493 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3494 Valuebuffer
* valuebuffer
= GetValuebuffer(client_ids
[ii
]);
3496 if (state_
.bound_valuebuffer
.get() == valuebuffer
) {
3497 state_
.bound_valuebuffer
= NULL
;
3499 RemoveValuebuffer(client_ids
[ii
]);
3504 void GLES2DecoderImpl::DeleteTexturesHelper(
3505 GLsizei n
, const GLuint
* client_ids
) {
3506 bool supports_separate_framebuffer_binds
=
3507 features().chromium_framebuffer_multisample
;
3508 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3509 TextureRef
* texture_ref
= GetTexture(client_ids
[ii
]);
3511 Texture
* texture
= texture_ref
->texture();
3512 if (texture
->IsAttachedToFramebuffer()) {
3513 framebuffer_state_
.clear_state_dirty
= true;
3515 // Unbind texture_ref from texture_ref units.
3516 for (size_t jj
= 0; jj
< state_
.texture_units
.size(); ++jj
) {
3517 state_
.texture_units
[jj
].Unbind(texture_ref
);
3519 // Unbind from current framebuffers.
3520 if (supports_separate_framebuffer_binds
) {
3521 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
3522 framebuffer_state_
.bound_read_framebuffer
3523 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT
, texture_ref
);
3525 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3526 framebuffer_state_
.bound_draw_framebuffer
3527 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT
, texture_ref
);
3530 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3531 framebuffer_state_
.bound_draw_framebuffer
3532 ->UnbindTexture(GL_FRAMEBUFFER
, texture_ref
);
3535 #if defined(OS_MACOSX)
3536 GLuint service_id
= texture
->service_id();
3537 if (texture
->target() == GL_TEXTURE_RECTANGLE_ARB
) {
3538 ReleaseIOSurfaceForTexture(service_id
);
3541 RemoveTexture(client_ids
[ii
]);
3546 // } // anonymous namespace
3548 bool GLES2DecoderImpl::MakeCurrent() {
3549 if (!context_
.get())
3552 if (WasContextLost()) {
3553 LOG(ERROR
) << " GLES2DecoderImpl: Trying to make lost context current.";
3557 if (!context_
->MakeCurrent(surface_
.get())) {
3558 LOG(ERROR
) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3559 MarkContextLost(error::kMakeCurrentFailed
);
3560 group_
->LoseContexts(error::kUnknown
);
3564 if (CheckResetStatus()) {
3566 << " GLES2DecoderImpl: Context reset detected after MakeCurrent.";
3567 group_
->LoseContexts(error::kUnknown
);
3571 ProcessFinishedAsyncTransfers();
3573 // Rebind the FBO if it was unbound by the context.
3574 if (workarounds().unbind_fbo_on_context_switch
)
3575 RestoreFramebufferBindings();
3577 framebuffer_state_
.clear_state_dirty
= true;
3582 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3583 ProcessPendingReadPixels(false);
3584 if (engine() && query_manager_
.get())
3585 query_manager_
->ProcessPendingTransferQueries();
3587 // TODO(epenner): Is there a better place to do this?
3588 // This needs to occur before we execute any batch of commands
3589 // from the client, as the client may have recieved an async
3590 // completion while issuing those commands.
3591 // "DidFlushStart" would be ideal if we had such a callback.
3592 async_pixel_transfer_manager_
->BindCompletedAsyncTransfers();
3595 static void RebindCurrentFramebuffer(
3597 Framebuffer
* framebuffer
,
3598 GLuint back_buffer_service_id
) {
3599 GLuint framebuffer_id
= framebuffer
? framebuffer
->service_id() : 0;
3601 if (framebuffer_id
== 0) {
3602 framebuffer_id
= back_buffer_service_id
;
3605 glBindFramebufferEXT(target
, framebuffer_id
);
3608 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3609 framebuffer_state_
.clear_state_dirty
= true;
3611 if (!features().chromium_framebuffer_multisample
) {
3612 RebindCurrentFramebuffer(
3614 framebuffer_state_
.bound_draw_framebuffer
.get(),
3615 GetBackbufferServiceId());
3617 RebindCurrentFramebuffer(
3618 GL_READ_FRAMEBUFFER_EXT
,
3619 framebuffer_state_
.bound_read_framebuffer
.get(),
3620 GetBackbufferServiceId());
3621 RebindCurrentFramebuffer(
3622 GL_DRAW_FRAMEBUFFER_EXT
,
3623 framebuffer_state_
.bound_draw_framebuffer
.get(),
3624 GetBackbufferServiceId());
3629 bool GLES2DecoderImpl::CheckFramebufferValid(
3630 Framebuffer
* framebuffer
,
3631 GLenum target
, const char* func_name
) {
3635 if (backbuffer_needs_clear_bits_
) {
3636 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3637 offscreen_target_color_format_
) & 0x0008) != 0 ? 0 : 1.f
);
3638 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
3640 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
3641 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
3643 state_
.SetDeviceDepthMask(GL_TRUE
);
3644 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
3645 bool reset_draw_buffer
= false;
3646 if ((backbuffer_needs_clear_bits_
& GL_COLOR_BUFFER_BIT
) != 0 &&
3647 group_
->draw_buffer() == GL_NONE
) {
3648 reset_draw_buffer
= true;
3649 GLenum buf
= GL_BACK
;
3650 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3651 buf
= GL_COLOR_ATTACHMENT0
;
3652 glDrawBuffersARB(1, &buf
);
3654 glClear(backbuffer_needs_clear_bits_
);
3655 if (reset_draw_buffer
) {
3656 GLenum buf
= GL_NONE
;
3657 glDrawBuffersARB(1, &buf
);
3659 backbuffer_needs_clear_bits_
= 0;
3660 RestoreClearState();
3665 if (framebuffer_manager()->IsComplete(framebuffer
)) {
3669 GLenum completeness
= framebuffer
->IsPossiblyComplete();
3670 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
3672 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
, "framebuffer incomplete");
3676 // Are all the attachments cleared?
3677 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3678 texture_manager()->HaveUnclearedMips()) {
3679 if (!framebuffer
->IsCleared()) {
3680 // Can we clear them?
3681 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3682 GL_FRAMEBUFFER_COMPLETE
) {
3684 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3685 "framebuffer incomplete (clear)");
3688 ClearUnclearedAttachments(target
, framebuffer
);
3692 if (!framebuffer_manager()->IsComplete(framebuffer
)) {
3693 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3694 GL_FRAMEBUFFER_COMPLETE
) {
3696 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3697 "framebuffer incomplete (check)");
3700 framebuffer_manager()->MarkAsComplete(framebuffer
);
3703 // NOTE: At this point we don't know if the framebuffer is complete but
3704 // we DO know that everything that needs to be cleared has been cleared.
3708 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name
) {
3709 if (!features().chromium_framebuffer_multisample
) {
3710 bool valid
= CheckFramebufferValid(
3711 framebuffer_state_
.bound_draw_framebuffer
.get(), GL_FRAMEBUFFER_EXT
,
3719 return CheckFramebufferValid(framebuffer_state_
.bound_draw_framebuffer
.get(),
3720 GL_DRAW_FRAMEBUFFER_EXT
,
3722 CheckFramebufferValid(framebuffer_state_
.bound_read_framebuffer
.get(),
3723 GL_READ_FRAMEBUFFER_EXT
,
3727 bool GLES2DecoderImpl::CheckBoundReadFramebufferColorAttachment(
3728 const char* func_name
) {
3729 Framebuffer
* framebuffer
= features().chromium_framebuffer_multisample
?
3730 framebuffer_state_
.bound_read_framebuffer
.get() :
3731 framebuffer_state_
.bound_draw_framebuffer
.get();
3734 if (framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
) == NULL
) {
3736 GL_INVALID_OPERATION
, func_name
, "no color image attached");
3742 bool GLES2DecoderImpl::FormsTextureCopyingFeedbackLoop(
3743 TextureRef
* texture
, GLint level
) {
3744 Framebuffer
* framebuffer
= features().chromium_framebuffer_multisample
?
3745 framebuffer_state_
.bound_read_framebuffer
.get() :
3746 framebuffer_state_
.bound_draw_framebuffer
.get();
3749 const Framebuffer::Attachment
* attachment
= framebuffer
->GetAttachment(
3750 GL_COLOR_ATTACHMENT0
);
3753 return attachment
->FormsFeedbackLoop(texture
, level
);
3756 gfx::Size
GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3757 Framebuffer
* framebuffer
=
3758 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3759 if (framebuffer
!= NULL
) {
3760 const Framebuffer::Attachment
* attachment
=
3761 framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
);
3763 return gfx::Size(attachment
->width(), attachment
->height());
3765 return gfx::Size(0, 0);
3766 } else if (offscreen_target_frame_buffer_
.get()) {
3767 return offscreen_size_
;
3769 return surface_
->GetSize();
3773 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3774 Framebuffer
* framebuffer
=
3775 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3776 if (framebuffer
!= NULL
) {
3777 return framebuffer
->GetColorAttachmentTextureType();
3779 return GL_UNSIGNED_BYTE
;
3783 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3784 Framebuffer
* framebuffer
=
3785 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3786 if (framebuffer
!= NULL
) {
3787 return framebuffer
->GetColorAttachmentFormat();
3788 } else if (offscreen_target_frame_buffer_
.get()) {
3789 return offscreen_target_color_format_
;
3791 return back_buffer_color_format_
;
3795 GLenum
GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3796 Framebuffer
* framebuffer
=
3797 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
3798 if (framebuffer
!= NULL
) {
3799 return framebuffer
->GetColorAttachmentFormat();
3800 } else if (offscreen_target_frame_buffer_
.get()) {
3801 return offscreen_target_color_format_
;
3803 return back_buffer_color_format_
;
3807 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3808 if (!offscreen_saved_color_texture_info_
.get())
3810 GLenum target
= offscreen_saved_color_texture_info_
->texture()->target();
3811 glBindTexture(target
, offscreen_saved_color_texture_info_
->service_id());
3812 texture_manager()->SetLevelInfo(
3813 offscreen_saved_color_texture_info_
.get(), GL_TEXTURE_2D
,
3815 GL_RGBA
, offscreen_size_
.width(), offscreen_size_
.height(),
3818 GL_RGBA
, GL_UNSIGNED_BYTE
, gfx::Rect(offscreen_size_
));
3819 texture_manager()->SetParameteri(
3820 "UpdateParentTextureInfo",
3822 offscreen_saved_color_texture_info_
.get(),
3823 GL_TEXTURE_MAG_FILTER
,
3825 texture_manager()->SetParameteri(
3826 "UpdateParentTextureInfo",
3828 offscreen_saved_color_texture_info_
.get(),
3829 GL_TEXTURE_MIN_FILTER
,
3831 texture_manager()->SetParameteri(
3832 "UpdateParentTextureInfo",
3834 offscreen_saved_color_texture_info_
.get(),
3837 texture_manager()->SetParameteri(
3838 "UpdateParentTextureInfo",
3840 offscreen_saved_color_texture_info_
.get(),
3843 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
3845 glBindTexture(target
, texture_ref
? texture_ref
->service_id() : 0);
3848 void GLES2DecoderImpl::SetResizeCallback(
3849 const base::Callback
<void(gfx::Size
, float)>& callback
) {
3850 resize_callback_
= callback
;
3853 Logger
* GLES2DecoderImpl::GetLogger() {
3857 void GLES2DecoderImpl::BeginDecoding() {
3858 gpu_tracer_
->BeginDecoding();
3859 gpu_trace_commands_
= gpu_tracer_
->IsTracing() && *gpu_decoder_category_
;
3860 gpu_debug_commands_
= log_commands() || debug() || gpu_trace_commands_
||
3861 (*cb_command_trace_category_
!= 0);
3862 query_manager_
->ProcessFrameBeginUpdates();
3865 void GLES2DecoderImpl::EndDecoding() {
3866 gpu_tracer_
->EndDecoding();
3869 ErrorState
* GLES2DecoderImpl::GetErrorState() {
3870 return state_
.GetErrorState();
3873 void GLES2DecoderImpl::SetShaderCacheCallback(
3874 const ShaderCacheCallback
& callback
) {
3875 shader_cache_callback_
= callback
;
3878 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3879 const WaitSyncPointCallback
& callback
) {
3880 wait_sync_point_callback_
= callback
;
3883 AsyncPixelTransferManager
*
3884 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3885 return async_pixel_transfer_manager_
.get();
3888 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3889 async_pixel_transfer_manager_
.reset();
3892 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3893 AsyncPixelTransferManager
* manager
) {
3894 async_pixel_transfer_manager_
= make_scoped_ptr(manager
);
3897 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id
,
3898 uint32
* service_texture_id
) {
3899 TextureRef
* texture_ref
= texture_manager()->GetTexture(client_texture_id
);
3901 *service_texture_id
= texture_ref
->service_id();
3907 uint32
GLES2DecoderImpl::GetTextureUploadCount() {
3908 return texture_state_
.texture_upload_count
+
3909 async_pixel_transfer_manager_
->GetTextureUploadCount();
3912 base::TimeDelta
GLES2DecoderImpl::GetTotalTextureUploadTime() {
3913 return texture_state_
.total_texture_upload_time
+
3914 async_pixel_transfer_manager_
->GetTotalTextureUploadTime();
3917 base::TimeDelta
GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3918 return total_processing_commands_time_
;
3921 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time
) {
3922 total_processing_commands_time_
+= time
;
3925 void GLES2DecoderImpl::Destroy(bool have_context
) {
3929 DCHECK(!have_context
|| context_
->IsCurrent(NULL
));
3931 // Unbind everything.
3932 state_
.vertex_attrib_manager
= NULL
;
3933 state_
.default_vertex_attrib_manager
= NULL
;
3934 state_
.texture_units
.clear();
3935 state_
.bound_array_buffer
= NULL
;
3936 state_
.bound_copy_read_buffer
= NULL
;
3937 state_
.bound_copy_write_buffer
= NULL
;
3938 state_
.bound_pixel_pack_buffer
= NULL
;
3939 state_
.bound_pixel_unpack_buffer
= NULL
;
3940 state_
.bound_transform_feedback_buffer
= NULL
;
3941 state_
.bound_uniform_buffer
= NULL
;
3942 framebuffer_state_
.bound_read_framebuffer
= NULL
;
3943 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
3944 state_
.bound_renderbuffer
= NULL
;
3945 state_
.bound_valuebuffer
= NULL
;
3947 if (offscreen_saved_color_texture_info_
.get()) {
3948 DCHECK(offscreen_target_color_texture_
);
3949 DCHECK_EQ(offscreen_saved_color_texture_info_
->service_id(),
3950 offscreen_saved_color_texture_
->id());
3951 offscreen_saved_color_texture_
->Invalidate();
3952 offscreen_saved_color_texture_info_
= NULL
;
3955 if (copy_texture_CHROMIUM_
.get()) {
3956 copy_texture_CHROMIUM_
->Destroy();
3957 copy_texture_CHROMIUM_
.reset();
3960 clear_framebuffer_blit_
.reset();
3962 if (state_
.current_program
.get()) {
3963 program_manager()->UnuseProgram(shader_manager(),
3964 state_
.current_program
.get());
3967 if (attrib_0_buffer_id_
) {
3968 glDeleteBuffersARB(1, &attrib_0_buffer_id_
);
3970 if (fixed_attrib_buffer_id_
) {
3971 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_
);
3974 if (validation_texture_
) {
3975 glDeleteTextures(1, &validation_texture_
);
3976 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_
);
3977 glDeleteFramebuffersEXT(1, &validation_fbo_
);
3980 if (offscreen_target_frame_buffer_
.get())
3981 offscreen_target_frame_buffer_
->Destroy();
3982 if (offscreen_target_color_texture_
.get())
3983 offscreen_target_color_texture_
->Destroy();
3984 if (offscreen_target_color_render_buffer_
.get())
3985 offscreen_target_color_render_buffer_
->Destroy();
3986 if (offscreen_target_depth_render_buffer_
.get())
3987 offscreen_target_depth_render_buffer_
->Destroy();
3988 if (offscreen_target_stencil_render_buffer_
.get())
3989 offscreen_target_stencil_render_buffer_
->Destroy();
3990 if (offscreen_saved_frame_buffer_
.get())
3991 offscreen_saved_frame_buffer_
->Destroy();
3992 if (offscreen_saved_color_texture_
.get())
3993 offscreen_saved_color_texture_
->Destroy();
3994 if (offscreen_resolved_frame_buffer_
.get())
3995 offscreen_resolved_frame_buffer_
->Destroy();
3996 if (offscreen_resolved_color_texture_
.get())
3997 offscreen_resolved_color_texture_
->Destroy();
3999 if (offscreen_target_frame_buffer_
.get())
4000 offscreen_target_frame_buffer_
->Invalidate();
4001 if (offscreen_target_color_texture_
.get())
4002 offscreen_target_color_texture_
->Invalidate();
4003 if (offscreen_target_color_render_buffer_
.get())
4004 offscreen_target_color_render_buffer_
->Invalidate();
4005 if (offscreen_target_depth_render_buffer_
.get())
4006 offscreen_target_depth_render_buffer_
->Invalidate();
4007 if (offscreen_target_stencil_render_buffer_
.get())
4008 offscreen_target_stencil_render_buffer_
->Invalidate();
4009 if (offscreen_saved_frame_buffer_
.get())
4010 offscreen_saved_frame_buffer_
->Invalidate();
4011 if (offscreen_saved_color_texture_
.get())
4012 offscreen_saved_color_texture_
->Invalidate();
4013 if (offscreen_resolved_frame_buffer_
.get())
4014 offscreen_resolved_frame_buffer_
->Invalidate();
4015 if (offscreen_resolved_color_texture_
.get())
4016 offscreen_resolved_color_texture_
->Invalidate();
4019 // Current program must be cleared after calling ProgramManager::UnuseProgram.
4020 // Otherwise, we can leak objects. http://crbug.com/258772.
4021 // state_.current_program must be reset before group_ is reset because
4022 // the later deletes the ProgramManager object that referred by
4023 // state_.current_program object.
4024 state_
.current_program
= NULL
;
4026 copy_texture_CHROMIUM_
.reset();
4027 clear_framebuffer_blit_
.reset();
4029 if (query_manager_
.get()) {
4030 query_manager_
->Destroy(have_context
);
4031 query_manager_
.reset();
4034 if (vertex_array_manager_
.get()) {
4035 vertex_array_manager_
->Destroy(have_context
);
4036 vertex_array_manager_
.reset();
4039 if (image_manager_
.get()) {
4040 image_manager_
->Destroy(have_context
);
4041 image_manager_
.reset();
4044 offscreen_target_frame_buffer_
.reset();
4045 offscreen_target_color_texture_
.reset();
4046 offscreen_target_color_render_buffer_
.reset();
4047 offscreen_target_depth_render_buffer_
.reset();
4048 offscreen_target_stencil_render_buffer_
.reset();
4049 offscreen_saved_frame_buffer_
.reset();
4050 offscreen_saved_color_texture_
.reset();
4051 offscreen_resolved_frame_buffer_
.reset();
4052 offscreen_resolved_color_texture_
.reset();
4054 // Need to release these before releasing |group_| which may own the
4055 // ShaderTranslatorCache.
4056 fragment_translator_
= NULL
;
4057 vertex_translator_
= NULL
;
4059 // Should destroy the transfer manager before the texture manager held
4060 // by the context group.
4061 async_pixel_transfer_manager_
.reset();
4063 // Destroy the GPU Tracer which may own some in process GPU Timings.
4065 gpu_tracer_
->Destroy(have_context
);
4066 gpu_tracer_
.reset();
4070 framebuffer_manager()->RemoveObserver(this);
4071 group_
->Destroy(this, have_context
);
4075 if (context_
.get()) {
4076 context_
->ReleaseCurrent(NULL
);
4080 #if defined(OS_MACOSX)
4081 for (TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.begin();
4082 it
!= texture_to_io_surface_map_
.end(); ++it
) {
4083 CFRelease(it
->second
);
4085 texture_to_io_surface_map_
.clear();
4089 void GLES2DecoderImpl::SetSurface(
4090 const scoped_refptr
<gfx::GLSurface
>& surface
) {
4091 DCHECK(context_
->IsCurrent(NULL
));
4092 DCHECK(surface_
.get());
4094 RestoreCurrentFramebufferBindings();
4097 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox
& mailbox
) {
4098 if (!offscreen_saved_color_texture_
.get()) {
4099 LOG(ERROR
) << "Called ProduceFrontBuffer on a non-offscreen context";
4102 if (!offscreen_saved_color_texture_info_
.get()) {
4103 GLuint service_id
= offscreen_saved_color_texture_
->id();
4104 offscreen_saved_color_texture_info_
= TextureRef::Create(
4105 texture_manager(), 0, service_id
);
4106 texture_manager()->SetTarget(offscreen_saved_color_texture_info_
.get(),
4108 UpdateParentTextureInfo();
4110 mailbox_manager()->ProduceTexture(
4111 mailbox
, offscreen_saved_color_texture_info_
->texture());
4114 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size
& size
) {
4115 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
4116 if (!is_offscreen
) {
4117 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
4118 << " with an onscreen framebuffer.";
4122 if (offscreen_size_
== size
)
4125 offscreen_size_
= size
;
4126 int w
= offscreen_size_
.width();
4127 int h
= offscreen_size_
.height();
4128 if (w
< 0 || h
< 0 || h
>= (INT_MAX
/ 4) / (w
? w
: 1)) {
4129 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4130 << "to allocate storage due to excessive dimensions.";
4134 // Reallocate the offscreen target buffers.
4135 DCHECK(offscreen_target_color_format_
);
4136 if (IsOffscreenBufferMultisampled()) {
4137 if (!offscreen_target_color_render_buffer_
->AllocateStorage(
4138 feature_info_
.get(),
4140 offscreen_target_color_format_
,
4141 offscreen_target_samples_
)) {
4142 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4143 << "to allocate storage for offscreen target color buffer.";
4147 if (!offscreen_target_color_texture_
->AllocateStorage(
4148 offscreen_size_
, offscreen_target_color_format_
, false)) {
4149 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4150 << "to allocate storage for offscreen target color texture.";
4154 if (offscreen_target_depth_format_
&&
4155 !offscreen_target_depth_render_buffer_
->AllocateStorage(
4156 feature_info_
.get(),
4158 offscreen_target_depth_format_
,
4159 offscreen_target_samples_
)) {
4160 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4161 << "to allocate storage for offscreen target depth buffer.";
4164 if (offscreen_target_stencil_format_
&&
4165 !offscreen_target_stencil_render_buffer_
->AllocateStorage(
4166 feature_info_
.get(),
4168 offscreen_target_stencil_format_
,
4169 offscreen_target_samples_
)) {
4170 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4171 << "to allocate storage for offscreen target stencil buffer.";
4175 // Attach the offscreen target buffers to the target frame buffer.
4176 if (IsOffscreenBufferMultisampled()) {
4177 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4178 GL_COLOR_ATTACHMENT0
,
4179 offscreen_target_color_render_buffer_
.get());
4181 offscreen_target_frame_buffer_
->AttachRenderTexture(
4182 offscreen_target_color_texture_
.get());
4184 if (offscreen_target_depth_format_
) {
4185 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4186 GL_DEPTH_ATTACHMENT
,
4187 offscreen_target_depth_render_buffer_
.get());
4189 const bool packed_depth_stencil
=
4190 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
4191 if (packed_depth_stencil
) {
4192 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4193 GL_STENCIL_ATTACHMENT
,
4194 offscreen_target_depth_render_buffer_
.get());
4195 } else if (offscreen_target_stencil_format_
) {
4196 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4197 GL_STENCIL_ATTACHMENT
,
4198 offscreen_target_stencil_render_buffer_
.get());
4201 if (offscreen_target_frame_buffer_
->CheckStatus() !=
4202 GL_FRAMEBUFFER_COMPLETE
) {
4203 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4204 << "because offscreen FBO was incomplete.";
4208 // Clear the target frame buffer.
4210 ScopedFrameBufferBinder
binder(this, offscreen_target_frame_buffer_
->id());
4211 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
4212 offscreen_target_color_format_
) & 0x0008) != 0 ? 0 : 1.f
);
4213 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
4215 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
4216 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
4218 state_
.SetDeviceDepthMask(GL_TRUE
);
4219 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
4220 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
4221 RestoreClearState();
4224 // Destroy the offscreen resolved framebuffers.
4225 if (offscreen_resolved_frame_buffer_
.get())
4226 offscreen_resolved_frame_buffer_
->Destroy();
4227 if (offscreen_resolved_color_texture_
.get())
4228 offscreen_resolved_color_texture_
->Destroy();
4229 offscreen_resolved_color_texture_
.reset();
4230 offscreen_resolved_frame_buffer_
.reset();
4235 error::Error
GLES2DecoderImpl::HandleResizeCHROMIUM(uint32 immediate_data_size
,
4236 const void* cmd_data
) {
4237 const gles2::cmds::ResizeCHROMIUM
& c
=
4238 *static_cast<const gles2::cmds::ResizeCHROMIUM
*>(cmd_data
);
4239 if (!offscreen_target_frame_buffer_
.get() && surface_
->DeferDraws())
4240 return error::kDeferCommandUntilLater
;
4242 GLuint width
= static_cast<GLuint
>(c
.width
);
4243 GLuint height
= static_cast<GLuint
>(c
.height
);
4244 GLfloat scale_factor
= c
.scale_factor
;
4245 TRACE_EVENT2("gpu", "glResizeChromium", "width", width
, "height", height
);
4247 width
= std::max(1U, width
);
4248 height
= std::max(1U, height
);
4250 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
4251 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
4252 // Make sure that we are done drawing to the back buffer before resizing.
4255 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
4257 if (!ResizeOffscreenFrameBuffer(gfx::Size(width
, height
))) {
4258 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because "
4259 << "ResizeOffscreenFrameBuffer failed.";
4260 return error::kLostContext
;
4264 if (!resize_callback_
.is_null()) {
4265 resize_callback_
.Run(gfx::Size(width
, height
), scale_factor
);
4266 DCHECK(context_
->IsCurrent(surface_
.get()));
4267 if (!context_
->IsCurrent(surface_
.get())) {
4268 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because context no longer "
4269 << "current after resize callback.";
4270 return error::kLostContext
;
4274 return error::kNoError
;
4277 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id
) const {
4278 if (command_id
> kStartPoint
&& command_id
< kNumCommands
) {
4279 return gles2::GetCommandName(static_cast<CommandId
>(command_id
));
4281 return GetCommonCommandName(static_cast<cmd::CommandId
>(command_id
));
4284 // Decode a command, and call the corresponding GL functions.
4285 // NOTE: DoCommand() is slower than calling DoCommands() on larger batches
4286 // of commands at once, and is now only used for tests that need to track
4287 // individual commands.
4288 error::Error
GLES2DecoderImpl::DoCommand(unsigned int command
,
4289 unsigned int arg_count
,
4290 const void* cmd_data
) {
4291 return DoCommands(1, cmd_data
, arg_count
+ 1, 0);
4294 // Decode multiple commands, and call the corresponding GL functions.
4295 // NOTE: 'buffer' is a pointer to the command buffer. As such, it could be
4296 // changed by a (malicious) client at any time, so if validation has to happen,
4297 // it should operate on a copy of them.
4298 // NOTE: This is duplicating code from AsyncAPIInterface::DoCommands() in the
4299 // interest of performance in this critical execution loop.
4300 template <bool DebugImpl
>
4301 error::Error
GLES2DecoderImpl::DoCommandsImpl(unsigned int num_commands
,
4304 int* entries_processed
) {
4305 commands_to_process_
= num_commands
;
4306 error::Error result
= error::kNoError
;
4307 const CommandBufferEntry
* cmd_data
=
4308 static_cast<const CommandBufferEntry
*>(buffer
);
4309 int process_pos
= 0;
4310 unsigned int command
= 0;
4312 while (process_pos
< num_entries
&& result
== error::kNoError
&&
4313 commands_to_process_
--) {
4314 const unsigned int size
= cmd_data
->value_header
.size
;
4315 command
= cmd_data
->value_header
.command
;
4318 result
= error::kInvalidSize
;
4322 if (static_cast<int>(size
) + process_pos
> num_entries
) {
4323 result
= error::kOutOfBounds
;
4328 TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4329 GetCommandName(command
));
4331 if (log_commands()) {
4332 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "]"
4333 << "cmd: " << GetCommandName(command
);
4337 const unsigned int arg_count
= size
- 1;
4338 unsigned int command_index
= command
- kStartPoint
- 1;
4339 if (command_index
< arraysize(command_info
)) {
4340 const CommandInfo
& info
= command_info
[command_index
];
4341 unsigned int info_arg_count
= static_cast<unsigned int>(info
.arg_count
);
4342 if ((info
.arg_flags
== cmd::kFixed
&& arg_count
== info_arg_count
) ||
4343 (info
.arg_flags
== cmd::kAtLeastN
&& arg_count
>= info_arg_count
)) {
4344 bool doing_gpu_trace
= false;
4345 if (DebugImpl
&& gpu_trace_commands_
) {
4346 if (CMD_FLAG_GET_TRACE_LEVEL(info
.cmd_flags
) <= gpu_trace_level_
) {
4347 doing_gpu_trace
= true;
4348 gpu_tracer_
->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_decoder"),
4349 GetCommandName(command
),
4354 uint32 immediate_data_size
= (arg_count
- info_arg_count
) *
4355 sizeof(CommandBufferEntry
); // NOLINT
4357 result
= (this->*info
.cmd_handler
)(immediate_data_size
, cmd_data
);
4359 if (DebugImpl
&& doing_gpu_trace
)
4360 gpu_tracer_
->End(kTraceDecoder
);
4362 if (DebugImpl
&& debug()) {
4364 while ((error
= glGetError()) != GL_NO_ERROR
) {
4365 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "] "
4366 << "GL ERROR: " << GLES2Util::GetStringEnum(error
)
4367 << " : " << GetCommandName(command
);
4368 LOCAL_SET_GL_ERROR(error
, "DoCommand", "GL error from driver");
4372 result
= error::kInvalidArguments
;
4375 result
= DoCommonCommand(command
, arg_count
, cmd_data
);
4379 TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4380 GetCommandName(command
));
4383 if (result
== error::kNoError
&&
4384 current_decoder_error_
!= error::kNoError
) {
4385 result
= current_decoder_error_
;
4386 current_decoder_error_
= error::kNoError
;
4389 if (result
!= error::kDeferCommandUntilLater
) {
4390 process_pos
+= size
;
4395 if (entries_processed
)
4396 *entries_processed
= process_pos
;
4398 if (error::IsError(result
)) {
4399 LOG(ERROR
) << "Error: " << result
<< " for Command "
4400 << GetCommandName(command
);
4406 error::Error
GLES2DecoderImpl::DoCommands(unsigned int num_commands
,
4409 int* entries_processed
) {
4410 if (gpu_debug_commands_
) {
4411 return DoCommandsImpl
<true>(
4412 num_commands
, buffer
, num_entries
, entries_processed
);
4414 return DoCommandsImpl
<false>(
4415 num_commands
, buffer
, num_entries
, entries_processed
);
4419 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id
) {
4420 buffer_manager()->RemoveBuffer(client_id
);
4423 void GLES2DecoderImpl::DoFinish() {
4425 ProcessPendingReadPixels(true);
4426 ProcessPendingQueries(true);
4429 void GLES2DecoderImpl::DoFlush() {
4431 ProcessPendingQueries(false);
4434 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit
) {
4435 GLuint texture_index
= texture_unit
- GL_TEXTURE0
;
4436 if (texture_index
>= state_
.texture_units
.size()) {
4437 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4438 "glActiveTexture", texture_unit
, "texture_unit");
4441 state_
.active_texture_unit
= texture_index
;
4442 glActiveTexture(texture_unit
);
4445 void GLES2DecoderImpl::DoBindBuffer(GLenum target
, GLuint client_id
) {
4446 Buffer
* buffer
= NULL
;
4447 GLuint service_id
= 0;
4448 if (client_id
!= 0) {
4449 buffer
= GetBuffer(client_id
);
4451 if (!group_
->bind_generates_resource()) {
4452 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4454 "id not generated by glGenBuffers");
4458 // It's a new id so make a buffer buffer for it.
4459 glGenBuffersARB(1, &service_id
);
4460 CreateBuffer(client_id
, service_id
);
4461 buffer
= GetBuffer(client_id
);
4464 LogClientServiceForInfo(buffer
, client_id
, "glBindBuffer");
4466 if (!buffer_manager()->SetTarget(buffer
, target
)) {
4468 GL_INVALID_OPERATION
,
4469 "glBindBuffer", "buffer bound to more than 1 target");
4472 service_id
= buffer
->service_id();
4474 state_
.SetBoundBuffer(target
, buffer
);
4475 glBindBuffer(target
, service_id
);
4478 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
4479 bool all_draw_buffers
) {
4480 Framebuffer
* framebuffer
=
4481 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4482 if (!all_draw_buffers
|| !framebuffer
) {
4483 return (GLES2Util::GetChannelsForFormat(
4484 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
4486 return framebuffer
->HasAlphaMRT();
4489 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
4490 Framebuffer
* framebuffer
=
4491 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4493 return framebuffer
->HasDepthAttachment();
4495 if (offscreen_target_frame_buffer_
.get()) {
4496 return offscreen_target_depth_format_
!= 0;
4498 return back_buffer_has_depth_
;
4501 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
4502 Framebuffer
* framebuffer
=
4503 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4505 return framebuffer
->HasStencilAttachment();
4507 if (offscreen_target_frame_buffer_
.get()) {
4508 return offscreen_target_stencil_format_
!= 0 ||
4509 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
4511 return back_buffer_has_stencil_
;
4514 void GLES2DecoderImpl::ApplyDirtyState() {
4515 if (framebuffer_state_
.clear_state_dirty
) {
4516 bool have_alpha
= BoundFramebufferHasColorAttachmentWithAlpha(true);
4517 state_
.SetDeviceColorMask(state_
.color_mask_red
,
4518 state_
.color_mask_green
,
4519 state_
.color_mask_blue
,
4520 state_
.color_mask_alpha
&& have_alpha
);
4522 bool have_depth
= BoundFramebufferHasDepthAttachment();
4523 state_
.SetDeviceDepthMask(state_
.depth_mask
&& have_depth
);
4525 bool have_stencil
= BoundFramebufferHasStencilAttachment();
4526 state_
.SetDeviceStencilMaskSeparate(
4527 GL_FRONT
, have_stencil
? state_
.stencil_front_writemask
: 0);
4528 state_
.SetDeviceStencilMaskSeparate(
4529 GL_BACK
, have_stencil
? state_
.stencil_back_writemask
: 0);
4531 state_
.SetDeviceCapabilityState(
4532 GL_DEPTH_TEST
, state_
.enable_flags
.depth_test
&& have_depth
);
4533 state_
.SetDeviceCapabilityState(
4534 GL_STENCIL_TEST
, state_
.enable_flags
.stencil_test
&& have_stencil
);
4535 framebuffer_state_
.clear_state_dirty
= false;
4539 GLuint
GLES2DecoderImpl::GetBackbufferServiceId() const {
4540 return (offscreen_target_frame_buffer_
.get())
4541 ? offscreen_target_frame_buffer_
->id()
4542 : (surface_
.get() ? surface_
->GetBackingFrameBufferObject() : 0);
4545 void GLES2DecoderImpl::RestoreState(const ContextState
* prev_state
) {
4546 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
4547 "context", logger_
.GetLogPrefix());
4548 // Restore the Framebuffer first because of bugs in Intel drivers.
4549 // Intel drivers incorrectly clip the viewport settings to
4550 // the size of the current framebuffer object.
4551 RestoreFramebufferBindings();
4552 state_
.RestoreState(prev_state
);
4555 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
4557 framebuffer_state_
.bound_draw_framebuffer
.get()
4558 ? framebuffer_state_
.bound_draw_framebuffer
->service_id()
4559 : GetBackbufferServiceId();
4560 if (!features().chromium_framebuffer_multisample
) {
4561 glBindFramebufferEXT(GL_FRAMEBUFFER
, service_id
);
4563 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, service_id
);
4564 service_id
= framebuffer_state_
.bound_read_framebuffer
.get()
4565 ? framebuffer_state_
.bound_read_framebuffer
->service_id()
4566 : GetBackbufferServiceId();
4567 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, service_id
);
4572 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
4573 state_
.RestoreRenderbufferBindings();
4576 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id
) const {
4577 Texture
* texture
= texture_manager()->GetTextureForServiceId(service_id
);
4579 GLenum target
= texture
->target();
4580 glBindTexture(target
, service_id
);
4582 target
, GL_TEXTURE_WRAP_S
, texture
->wrap_s());
4584 target
, GL_TEXTURE_WRAP_T
, texture
->wrap_t());
4586 target
, GL_TEXTURE_MIN_FILTER
, texture
->min_filter());
4588 target
, GL_TEXTURE_MAG_FILTER
, texture
->mag_filter());
4589 RestoreTextureUnitBindings(state_
.active_texture_unit
);
4593 void GLES2DecoderImpl::ClearAllAttributes() const {
4594 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
4596 if (feature_info_
->feature_flags().native_vertex_array_object
)
4597 glBindVertexArrayOES(0);
4599 for (uint32 i
= 0; i
< group_
->max_vertex_attribs(); ++i
) {
4600 if (i
!= 0) // Never disable attribute 0
4601 glDisableVertexAttribArray(i
);
4602 if (features().angle_instanced_arrays
)
4603 glVertexAttribDivisorANGLE(i
, 0);
4607 void GLES2DecoderImpl::RestoreAllAttributes() const {
4608 state_
.RestoreVertexAttribs();
4611 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore
) {
4612 state_
.SetIgnoreCachedStateForTest(ignore
);
4615 void GLES2DecoderImpl::OnFboChanged() const {
4616 if (workarounds().restore_scissor_on_fbo_change
)
4617 state_
.fbo_binding_for_scissor_workaround_dirty
= true;
4619 if (workarounds().gl_begin_gl_end_on_fbo_change_to_backbuffer
) {
4620 GLint bound_fbo_unsigned
= -1;
4621 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT
, &bound_fbo_unsigned
);
4622 GLuint bound_fbo
= static_cast<GLuint
>(bound_fbo_unsigned
);
4623 if (surface_
&& surface_
->GetBackingFrameBufferObject() == bound_fbo
)
4624 surface_
->NotifyWasBound();
4628 // Called after the FBO is checked for completeness.
4629 void GLES2DecoderImpl::OnUseFramebuffer() const {
4630 if (state_
.fbo_binding_for_scissor_workaround_dirty
) {
4631 state_
.fbo_binding_for_scissor_workaround_dirty
= false;
4632 // The driver forgets the correct scissor when modifying the FBO binding.
4633 glScissor(state_
.scissor_x
,
4635 state_
.scissor_width
,
4636 state_
.scissor_height
);
4638 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
4639 // it's unclear how this bug works.
4644 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target
, GLuint client_id
) {
4645 Framebuffer
* framebuffer
= NULL
;
4646 GLuint service_id
= 0;
4647 if (client_id
!= 0) {
4648 framebuffer
= GetFramebuffer(client_id
);
4650 if (!group_
->bind_generates_resource()) {
4651 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4652 "glBindFramebuffer",
4653 "id not generated by glGenFramebuffers");
4657 // It's a new id so make a framebuffer framebuffer for it.
4658 glGenFramebuffersEXT(1, &service_id
);
4659 CreateFramebuffer(client_id
, service_id
);
4660 framebuffer
= GetFramebuffer(client_id
);
4662 service_id
= framebuffer
->service_id();
4664 framebuffer
->MarkAsValid();
4666 LogClientServiceForInfo(framebuffer
, client_id
, "glBindFramebuffer");
4668 if (target
== GL_FRAMEBUFFER
|| target
== GL_DRAW_FRAMEBUFFER_EXT
) {
4669 framebuffer_state_
.bound_draw_framebuffer
= framebuffer
;
4672 // vmiura: This looks like dup code
4673 if (target
== GL_FRAMEBUFFER
|| target
== GL_READ_FRAMEBUFFER_EXT
) {
4674 framebuffer_state_
.bound_read_framebuffer
= framebuffer
;
4677 framebuffer_state_
.clear_state_dirty
= true;
4679 // If we are rendering to the backbuffer get the FBO id for any simulated
4681 if (framebuffer
== NULL
) {
4682 service_id
= GetBackbufferServiceId();
4685 glBindFramebufferEXT(target
, service_id
);
4689 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target
, GLuint client_id
) {
4690 Renderbuffer
* renderbuffer
= NULL
;
4691 GLuint service_id
= 0;
4692 if (client_id
!= 0) {
4693 renderbuffer
= GetRenderbuffer(client_id
);
4694 if (!renderbuffer
) {
4695 if (!group_
->bind_generates_resource()) {
4696 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4697 "glBindRenderbuffer",
4698 "id not generated by glGenRenderbuffers");
4702 // It's a new id so make a renderbuffer for it.
4703 glGenRenderbuffersEXT(1, &service_id
);
4704 CreateRenderbuffer(client_id
, service_id
);
4705 renderbuffer
= GetRenderbuffer(client_id
);
4707 service_id
= renderbuffer
->service_id();
4709 renderbuffer
->MarkAsValid();
4711 LogClientServiceForInfo(renderbuffer
, client_id
, "glBindRenderbuffer");
4712 state_
.bound_renderbuffer
= renderbuffer
;
4713 state_
.bound_renderbuffer_valid
= true;
4714 glBindRenderbufferEXT(GL_RENDERBUFFER
, service_id
);
4717 void GLES2DecoderImpl::DoBindTexture(GLenum target
, GLuint client_id
) {
4718 TextureRef
* texture_ref
= NULL
;
4719 GLuint service_id
= 0;
4720 if (client_id
!= 0) {
4721 texture_ref
= GetTexture(client_id
);
4723 if (!group_
->bind_generates_resource()) {
4724 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4726 "id not generated by glGenTextures");
4730 // It's a new id so make a texture texture for it.
4731 glGenTextures(1, &service_id
);
4732 DCHECK_NE(0u, service_id
);
4733 CreateTexture(client_id
, service_id
);
4734 texture_ref
= GetTexture(client_id
);
4737 texture_ref
= texture_manager()->GetDefaultTextureInfo(target
);
4740 // Check the texture exists
4742 Texture
* texture
= texture_ref
->texture();
4743 // Check that we are not trying to bind it to a different target.
4744 if (texture
->target() != 0 && texture
->target() != target
) {
4745 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4747 "texture bound to more than 1 target.");
4750 LogClientServiceForInfo(texture
, client_id
, "glBindTexture");
4751 if (texture
->target() == 0) {
4752 texture_manager()->SetTarget(texture_ref
, target
);
4754 glBindTexture(target
, texture
->service_id());
4756 glBindTexture(target
, 0);
4759 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4760 unit
.bind_target
= target
;
4763 unit
.bound_texture_2d
= texture_ref
;
4765 case GL_TEXTURE_CUBE_MAP
:
4766 unit
.bound_texture_cube_map
= texture_ref
;
4768 case GL_TEXTURE_EXTERNAL_OES
:
4769 unit
.bound_texture_external_oes
= texture_ref
;
4771 case GL_TEXTURE_RECTANGLE_ARB
:
4772 unit
.bound_texture_rectangle_arb
= texture_ref
;
4775 unit
.bound_texture_3d
= texture_ref
;
4777 case GL_TEXTURE_2D_ARRAY
:
4778 unit
.bound_texture_2d_array
= texture_ref
;
4781 NOTREACHED(); // Validation should prevent us getting here.
4786 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index
) {
4787 if (state_
.vertex_attrib_manager
->Enable(index
, false)) {
4789 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
4790 glDisableVertexAttribArray(index
);
4795 "glDisableVertexAttribArray", "index out of range");
4799 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target
,
4800 GLsizei numAttachments
,
4801 const GLenum
* attachments
) {
4802 if (workarounds().disable_discard_framebuffer
)
4805 Framebuffer
* framebuffer
=
4806 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
4808 // Validates the attachments. If one of them fails
4809 // the whole command fails.
4810 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4812 !validators_
->attachment
.IsValid(attachments
[i
])) ||
4814 !validators_
->backbuffer_attachment
.IsValid(attachments
[i
]))) {
4815 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4816 "glDiscardFramebufferEXT", attachments
[i
], "attachments");
4821 // Marks each one of them as not cleared
4822 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4824 framebuffer
->MarkAttachmentAsCleared(renderbuffer_manager(),
4829 switch (attachments
[i
]) {
4831 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
4834 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
4835 case GL_STENCIL_EXT
:
4836 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
4845 // If the default framebuffer is bound but we are still rendering to an
4846 // FBO, translate attachment names that refer to default framebuffer
4847 // channels to corresponding framebuffer attachments.
4848 scoped_ptr
<GLenum
[]> translated_attachments(new GLenum
[numAttachments
]);
4849 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4850 GLenum attachment
= attachments
[i
];
4851 if (!framebuffer
&& GetBackbufferServiceId()) {
4852 switch (attachment
) {
4854 attachment
= GL_COLOR_ATTACHMENT0
;
4857 attachment
= GL_DEPTH_ATTACHMENT
;
4859 case GL_STENCIL_EXT
:
4860 attachment
= GL_STENCIL_ATTACHMENT
;
4867 translated_attachments
[i
] = attachment
;
4870 ScopedRenderTo
do_render(framebuffer
);
4871 if (feature_info_
->gl_version_info().is_es3
) {
4872 glInvalidateFramebuffer(
4873 target
, numAttachments
, translated_attachments
.get());
4875 glDiscardFramebufferEXT(
4876 target
, numAttachments
, translated_attachments
.get());
4880 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index
) {
4881 if (state_
.vertex_attrib_manager
->Enable(index
, true)) {
4882 glEnableVertexAttribArray(index
);
4885 GL_INVALID_VALUE
, "glEnableVertexAttribArray", "index out of range");
4889 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target
) {
4890 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
4893 !texture_manager()->CanGenerateMipmaps(texture_ref
)) {
4895 GL_INVALID_OPERATION
, "glGenerateMipmap", "Can not generate mips");
4899 if (target
== GL_TEXTURE_CUBE_MAP
) {
4900 for (int i
= 0; i
< 6; ++i
) {
4901 GLenum face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ i
;
4902 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, face
, 0)) {
4904 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
4909 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
, 0)) {
4911 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
4916 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4917 // Workaround for Mac driver bug. In the large scheme of things setting
4918 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4919 // hit so there's probably no need to make this conditional. The bug appears
4920 // to be that if the filtering mode is set to something that doesn't require
4921 // mipmaps for rendering, or is never set to something other than the default,
4922 // then glGenerateMipmap misbehaves.
4923 if (workarounds().set_texture_filter_before_generating_mipmap
) {
4924 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST_MIPMAP_NEAREST
);
4926 glGenerateMipmapEXT(target
);
4927 if (workarounds().set_texture_filter_before_generating_mipmap
) {
4928 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
,
4929 texture_ref
->texture()->min_filter());
4931 GLenum error
= LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4932 if (error
== GL_NO_ERROR
) {
4933 texture_manager()->MarkMipmapsGenerated(texture_ref
);
4937 bool GLES2DecoderImpl::GetHelper(
4938 GLenum pname
, GLint
* params
, GLsizei
* num_written
) {
4939 DCHECK(num_written
);
4940 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
4942 case GL_IMPLEMENTATION_COLOR_READ_FORMAT
:
4944 // Return the GL implementation's preferred format and (see below type)
4945 // if we have the GL extension that exposes this. This allows the GPU
4946 // client to use the implementation's preferred format for glReadPixels
4947 // for optimisation.
4949 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4950 // case when requested on integer/floating point buffers but which is
4951 // acceptable on GLES2 and with the GL_OES_read_format extension.
4953 // Therefore if an error occurs we swallow the error and use the
4954 // internal implementation.
4956 if (context_
->HasExtension("GL_OES_read_format")) {
4957 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
4959 glGetIntegerv(pname
, params
);
4960 if (glGetError() == GL_NO_ERROR
)
4963 *params
= GLES2Util::GetPreferredGLReadPixelsFormat(
4964 GetBoundReadFrameBufferInternalFormat());
4967 case GL_IMPLEMENTATION_COLOR_READ_TYPE
:
4970 if (context_
->HasExtension("GL_OES_read_format")) {
4971 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
4973 glGetIntegerv(pname
, params
);
4974 if (glGetError() == GL_NO_ERROR
)
4977 *params
= GLES2Util::GetPreferredGLReadPixelsType(
4978 GetBoundReadFrameBufferInternalFormat(),
4979 GetBoundReadFrameBufferTextureType());
4982 case GL_MAX_FRAGMENT_UNIFORM_VECTORS
:
4985 *params
= group_
->max_fragment_uniform_vectors();
4988 case GL_MAX_VARYING_VECTORS
:
4991 *params
= group_
->max_varying_vectors();
4994 case GL_MAX_VERTEX_UNIFORM_VECTORS
:
4997 *params
= group_
->max_vertex_uniform_vectors();
5002 if (unsafe_es3_apis_enabled()) {
5004 case GL_MAX_VARYING_COMPONENTS
: {
5005 if (feature_info_
->gl_version_info().is_es
) {
5006 // We can just delegate this query to the driver.
5010 // GL_MAX_VARYING_COMPONENTS is deprecated in the desktop
5011 // OpenGL core profile, so for simplicity, just compute it
5012 // from GL_MAX_VARYING_VECTORS on non-OpenGL ES
5014 GLint max_varying_vectors
= 0;
5015 glGetIntegerv(GL_MAX_VARYING_VECTORS
, &max_varying_vectors
);
5018 *params
= max_varying_vectors
* 4;
5022 case GL_READ_BUFFER
:
5025 Framebuffer
* framebuffer
=
5026 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER
);
5029 read_buffer
= framebuffer
->read_buffer();
5031 read_buffer
= back_buffer_read_buffer_
;
5033 *params
= static_cast<GLint
>(read_buffer
);
5039 case GL_MAX_VIEWPORT_DIMS
:
5040 if (offscreen_target_frame_buffer_
.get()) {
5043 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
5044 params
[1] = renderbuffer_manager()->max_renderbuffer_size();
5049 case GL_MAX_SAMPLES
:
5052 params
[0] = renderbuffer_manager()->max_samples();
5055 case GL_MAX_RENDERBUFFER_SIZE
:
5058 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
5061 case GL_MAX_TEXTURE_SIZE
:
5064 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D
);
5067 case GL_MAX_CUBE_MAP_TEXTURE_SIZE
:
5070 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP
);
5073 case GL_MAX_COLOR_ATTACHMENTS_EXT
:
5076 params
[0] = group_
->max_color_attachments();
5079 case GL_MAX_DRAW_BUFFERS_ARB
:
5082 params
[0] = group_
->max_draw_buffers();
5089 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
5090 Framebuffer
* framebuffer
=
5091 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5093 glGetFramebufferAttachmentParameterivEXT(
5094 GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
5095 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE
, &v
);
5097 v
= (back_buffer_color_format_
== GL_RGBA
? 8 : 0);
5100 glGetIntegerv(GL_ALPHA_BITS
, &v
);
5103 BoundFramebufferHasColorAttachmentWithAlpha(false) ? v
: 0;
5110 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
5111 Framebuffer
* framebuffer
=
5112 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5114 glGetFramebufferAttachmentParameterivEXT(
5115 GL_FRAMEBUFFER
, GL_DEPTH_ATTACHMENT
,
5116 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE
, &v
);
5118 v
= (back_buffer_has_depth_
? 24 : 0);
5121 glGetIntegerv(GL_DEPTH_BITS
, &v
);
5123 params
[0] = BoundFramebufferHasDepthAttachment() ? v
: 0;
5132 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
5133 Framebuffer
* framebuffer
=
5134 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5136 GLenum framebuffer_enum
= 0;
5139 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE
;
5142 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE
;
5145 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE
;
5148 glGetFramebufferAttachmentParameterivEXT(
5149 GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
, framebuffer_enum
, &v
);
5154 glGetIntegerv(pname
, &v
);
5159 case GL_STENCIL_BITS
:
5163 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
5164 Framebuffer
* framebuffer
=
5165 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5167 glGetFramebufferAttachmentParameterivEXT(
5168 GL_FRAMEBUFFER
, GL_STENCIL_ATTACHMENT
,
5169 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE
, &v
);
5171 v
= (back_buffer_has_stencil_
? 8 : 0);
5174 glGetIntegerv(GL_STENCIL_BITS
, &v
);
5176 params
[0] = BoundFramebufferHasStencilAttachment() ? v
: 0;
5179 case GL_COMPRESSED_TEXTURE_FORMATS
:
5180 *num_written
= validators_
->compressed_texture_format
.GetValues().size();
5182 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
5183 params
[ii
] = validators_
->compressed_texture_format
.GetValues()[ii
];
5187 case GL_NUM_COMPRESSED_TEXTURE_FORMATS
:
5190 *params
= validators_
->compressed_texture_format
.GetValues().size();
5193 case GL_NUM_SHADER_BINARY_FORMATS
:
5196 *params
= validators_
->shader_binary_format
.GetValues().size();
5199 case GL_SHADER_BINARY_FORMATS
:
5200 *num_written
= validators_
->shader_binary_format
.GetValues().size();
5202 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
5203 params
[ii
] = validators_
->shader_binary_format
.GetValues()[ii
];
5207 case GL_SHADER_COMPILER
:
5213 case GL_ARRAY_BUFFER_BINDING
:
5216 *params
= GetClientId(
5217 buffer_manager(), state_
.bound_array_buffer
.get());
5220 case GL_ELEMENT_ARRAY_BUFFER_BINDING
:
5223 *params
= GetClientId(
5225 state_
.vertex_attrib_manager
->element_array_buffer());
5228 case GL_COPY_READ_BUFFER_BINDING
:
5231 *params
= GetClientId(
5232 buffer_manager(), state_
.bound_copy_read_buffer
.get());
5235 case GL_COPY_WRITE_BUFFER_BINDING
:
5238 *params
= GetClientId(
5239 buffer_manager(), state_
.bound_copy_write_buffer
.get());
5242 case GL_PIXEL_PACK_BUFFER_BINDING
:
5245 *params
= GetClientId(
5246 buffer_manager(), state_
.bound_pixel_pack_buffer
.get());
5249 case GL_PIXEL_UNPACK_BUFFER_BINDING
:
5252 *params
= GetClientId(
5253 buffer_manager(), state_
.bound_pixel_unpack_buffer
.get());
5256 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING
:
5259 *params
= GetClientId(
5260 buffer_manager(), state_
.bound_transform_feedback_buffer
.get());
5263 case GL_UNIFORM_BUFFER_BINDING
:
5266 *params
= GetClientId(
5267 buffer_manager(), state_
.bound_uniform_buffer
.get());
5270 case GL_FRAMEBUFFER_BINDING
:
5271 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
5274 *params
= GetClientId(
5275 framebuffer_manager(),
5276 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
));
5279 case GL_READ_FRAMEBUFFER_BINDING_EXT
:
5282 *params
= GetClientId(
5283 framebuffer_manager(),
5284 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
));
5287 case GL_RENDERBUFFER_BINDING
:
5290 Renderbuffer
* renderbuffer
=
5291 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5293 *params
= renderbuffer
->client_id();
5299 case GL_CURRENT_PROGRAM
:
5302 *params
= GetClientId(program_manager(), state_
.current_program
.get());
5305 case GL_VERTEX_ARRAY_BINDING_OES
:
5308 if (state_
.vertex_attrib_manager
.get() !=
5309 state_
.default_vertex_attrib_manager
.get()) {
5310 GLuint client_id
= 0;
5311 vertex_array_manager_
->GetClientId(
5312 state_
.vertex_attrib_manager
->service_id(), &client_id
);
5313 *params
= client_id
;
5319 case GL_TEXTURE_BINDING_2D
:
5322 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5323 if (unit
.bound_texture_2d
.get()) {
5324 *params
= unit
.bound_texture_2d
->client_id();
5330 case GL_TEXTURE_BINDING_CUBE_MAP
:
5333 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5334 if (unit
.bound_texture_cube_map
.get()) {
5335 *params
= unit
.bound_texture_cube_map
->client_id();
5341 case GL_TEXTURE_BINDING_EXTERNAL_OES
:
5344 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5345 if (unit
.bound_texture_external_oes
.get()) {
5346 *params
= unit
.bound_texture_external_oes
->client_id();
5352 case GL_TEXTURE_BINDING_RECTANGLE_ARB
:
5355 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5356 if (unit
.bound_texture_rectangle_arb
.get()) {
5357 *params
= unit
.bound_texture_rectangle_arb
->client_id();
5363 case GL_BIND_GENERATES_RESOURCE_CHROMIUM
:
5366 params
[0] = group_
->bind_generates_resource() ? 1 : 0;
5370 if (pname
>= GL_DRAW_BUFFER0_ARB
&&
5371 pname
< GL_DRAW_BUFFER0_ARB
+ group_
->max_draw_buffers()) {
5374 Framebuffer
* framebuffer
=
5375 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
5377 params
[0] = framebuffer
->GetDrawBuffer(pname
);
5378 } else { // backbuffer
5379 if (pname
== GL_DRAW_BUFFER0_ARB
)
5380 params
[0] = group_
->draw_buffer();
5382 params
[0] = GL_NONE
;
5387 *num_written
= util_
.GLGetNumValuesReturned(pname
);
5392 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
5393 GLenum pname
, GLsizei
* num_values
) {
5394 if (state_
.GetStateAsGLint(pname
, NULL
, num_values
)) {
5397 return GetHelper(pname
, NULL
, num_values
);
5400 GLenum
GLES2DecoderImpl::AdjustGetPname(GLenum pname
) {
5401 if (GL_MAX_SAMPLES
== pname
&&
5402 features().use_img_for_multisampled_render_to_texture
) {
5403 return GL_MAX_SAMPLES_IMG
;
5408 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname
, GLboolean
* params
) {
5410 GLsizei num_written
= 0;
5411 if (GetNumValuesReturnedForGLGet(pname
, &num_written
)) {
5412 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
5413 if (!state_
.GetStateAsGLint(pname
, values
.get(), &num_written
)) {
5414 GetHelper(pname
, values
.get(), &num_written
);
5416 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
5417 params
[ii
] = static_cast<GLboolean
>(values
[ii
]);
5420 pname
= AdjustGetPname(pname
);
5421 glGetBooleanv(pname
, params
);
5425 void GLES2DecoderImpl::DoGetFloatv(GLenum pname
, GLfloat
* params
) {
5427 GLsizei num_written
= 0;
5428 if (!state_
.GetStateAsGLfloat(pname
, params
, &num_written
)) {
5429 if (GetHelper(pname
, NULL
, &num_written
)) {
5430 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
5431 GetHelper(pname
, values
.get(), &num_written
);
5432 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
5433 params
[ii
] = static_cast<GLfloat
>(values
[ii
]);
5436 pname
= AdjustGetPname(pname
);
5437 glGetFloatv(pname
, params
);
5442 void GLES2DecoderImpl::DoGetInteger64v(GLenum pname
, GLint64
* params
) {
5444 if (unsafe_es3_apis_enabled()) {
5446 case GL_MAX_ELEMENT_INDEX
: {
5447 if (feature_info_
->gl_version_info().IsAtLeastGLES(3, 0) ||
5448 feature_info_
->gl_version_info().IsAtLeastGL(4, 3)) {
5449 glGetInteger64v(GL_MAX_ELEMENT_INDEX
, params
);
5451 // Assume that desktop GL implementations can generally support
5454 *params
= std::numeric_limits
<unsigned int>::max();
5461 pname
= AdjustGetPname(pname
);
5462 glGetInteger64v(pname
, params
);
5465 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname
, GLint
* params
) {
5467 GLsizei num_written
;
5468 if (!state_
.GetStateAsGLint(pname
, params
, &num_written
) &&
5469 !GetHelper(pname
, params
, &num_written
)) {
5470 pname
= AdjustGetPname(pname
);
5471 glGetIntegerv(pname
, params
);
5475 void GLES2DecoderImpl::DoGetProgramiv(
5476 GLuint program_id
, GLenum pname
, GLint
* params
) {
5477 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetProgramiv");
5481 program
->GetProgramiv(pname
, params
);
5484 void GLES2DecoderImpl::DoGetBufferParameteri64v(
5485 GLenum target
, GLenum pname
, GLint64
* params
) {
5486 // Just delegate it. Some validation is actually done before this.
5487 buffer_manager()->ValidateAndDoGetBufferParameteri64v(
5488 &state_
, target
, pname
, params
);
5491 void GLES2DecoderImpl::DoGetBufferParameteriv(
5492 GLenum target
, GLenum pname
, GLint
* params
) {
5493 // Just delegate it. Some validation is actually done before this.
5494 buffer_manager()->ValidateAndDoGetBufferParameteriv(
5495 &state_
, target
, pname
, params
);
5498 void GLES2DecoderImpl::DoBindAttribLocation(
5499 GLuint program_id
, GLuint index
, const char* name
) {
5500 if (!StringIsValidForGLES(name
)) {
5502 GL_INVALID_VALUE
, "glBindAttribLocation", "Invalid character");
5505 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
5507 GL_INVALID_OPERATION
, "glBindAttribLocation", "reserved prefix");
5510 if (index
>= group_
->max_vertex_attribs()) {
5512 GL_INVALID_VALUE
, "glBindAttribLocation", "index out of range");
5515 Program
* program
= GetProgramInfoNotShader(
5516 program_id
, "glBindAttribLocation");
5520 // At this point, the program's shaders may not be translated yet,
5521 // therefore, we may not find the hashed attribute name.
5522 // glBindAttribLocation call with original name is useless.
5523 // So instead, we should simply cache the binding, and then call
5524 // Program::ExecuteBindAttribLocationCalls() right before link.
5525 program
->SetAttribLocationBinding(name
, static_cast<GLint
>(index
));
5526 // TODO(zmo): Get rid of the following glBindAttribLocation call.
5527 glBindAttribLocation(program
->service_id(), index
, name
);
5530 error::Error
GLES2DecoderImpl::HandleBindAttribLocationBucket(
5531 uint32 immediate_data_size
,
5532 const void* cmd_data
) {
5533 const gles2::cmds::BindAttribLocationBucket
& c
=
5534 *static_cast<const gles2::cmds::BindAttribLocationBucket
*>(cmd_data
);
5535 GLuint program
= static_cast<GLuint
>(c
.program
);
5536 GLuint index
= static_cast<GLuint
>(c
.index
);
5537 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
5538 if (!bucket
|| bucket
->size() == 0) {
5539 return error::kInvalidArguments
;
5541 std::string name_str
;
5542 if (!bucket
->GetAsString(&name_str
)) {
5543 return error::kInvalidArguments
;
5545 DoBindAttribLocation(program
, index
, name_str
.c_str());
5546 return error::kNoError
;
5549 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
5550 GLuint program_id
, GLint location
, const char* name
) {
5551 if (!StringIsValidForGLES(name
)) {
5554 "glBindUniformLocationCHROMIUM", "Invalid character");
5557 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
5559 GL_INVALID_OPERATION
,
5560 "glBindUniformLocationCHROMIUM", "reserved prefix");
5563 if (location
< 0 || static_cast<uint32
>(location
) >=
5564 (group_
->max_fragment_uniform_vectors() +
5565 group_
->max_vertex_uniform_vectors()) * 4) {
5568 "glBindUniformLocationCHROMIUM", "location out of range");
5571 Program
* program
= GetProgramInfoNotShader(
5572 program_id
, "glBindUniformLocationCHROMIUM");
5576 if (!program
->SetUniformLocationBinding(name
, location
)) {
5579 "glBindUniformLocationCHROMIUM", "location out of range");
5583 error::Error
GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
5584 uint32 immediate_data_size
,
5585 const void* cmd_data
) {
5586 const gles2::cmds::BindUniformLocationCHROMIUMBucket
& c
=
5587 *static_cast<const gles2::cmds::BindUniformLocationCHROMIUMBucket
*>(
5589 GLuint program
= static_cast<GLuint
>(c
.program
);
5590 GLint location
= static_cast<GLint
>(c
.location
);
5591 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
5592 if (!bucket
|| bucket
->size() == 0) {
5593 return error::kInvalidArguments
;
5595 std::string name_str
;
5596 if (!bucket
->GetAsString(&name_str
)) {
5597 return error::kInvalidArguments
;
5599 DoBindUniformLocationCHROMIUM(program
, location
, name_str
.c_str());
5600 return error::kNoError
;
5603 error::Error
GLES2DecoderImpl::HandleDeleteShader(uint32 immediate_data_size
,
5604 const void* cmd_data
) {
5605 const gles2::cmds::DeleteShader
& c
=
5606 *static_cast<const gles2::cmds::DeleteShader
*>(cmd_data
);
5607 GLuint client_id
= c
.shader
;
5609 Shader
* shader
= GetShader(client_id
);
5611 if (!shader
->IsDeleted()) {
5612 shader_manager()->Delete(shader
);
5615 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glDeleteShader", "unknown shader");
5618 return error::kNoError
;
5621 error::Error
GLES2DecoderImpl::HandleDeleteProgram(uint32 immediate_data_size
,
5622 const void* cmd_data
) {
5623 const gles2::cmds::DeleteProgram
& c
=
5624 *static_cast<const gles2::cmds::DeleteProgram
*>(cmd_data
);
5625 GLuint client_id
= c
.program
;
5627 Program
* program
= GetProgram(client_id
);
5629 if (!program
->IsDeleted()) {
5630 program_manager()->MarkAsDeleted(shader_manager(), program
);
5634 GL_INVALID_VALUE
, "glDeleteProgram", "unknown program");
5637 return error::kNoError
;
5640 error::Error
GLES2DecoderImpl::DoClear(GLbitfield mask
) {
5641 DCHECK(!ShouldDeferDraws());
5642 if (CheckBoundFramebuffersValid("glClear")) {
5644 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
5645 if (workarounds().gl_clear_broken
) {
5646 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::ClearWorkaround",
5648 if (!BoundFramebufferHasDepthAttachment())
5649 mask
&= ~GL_DEPTH_BUFFER_BIT
;
5650 if (!BoundFramebufferHasStencilAttachment())
5651 mask
&= ~GL_STENCIL_BUFFER_BIT
;
5652 clear_framebuffer_blit_
->ClearFramebuffer(
5653 this, GetBoundReadFrameBufferSize(), mask
, state_
.color_clear_red
,
5654 state_
.color_clear_green
, state_
.color_clear_blue
,
5655 state_
.color_clear_alpha
, state_
.depth_clear
, state_
.stencil_clear
);
5656 return error::kNoError
;
5660 return error::kNoError
;
5663 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
5664 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
5665 GLuint client_renderbuffer_id
) {
5666 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5669 GL_INVALID_OPERATION
,
5670 "glFramebufferRenderbuffer", "no framebuffer bound");
5673 GLuint service_id
= 0;
5674 Renderbuffer
* renderbuffer
= NULL
;
5675 if (client_renderbuffer_id
) {
5676 renderbuffer
= GetRenderbuffer(client_renderbuffer_id
);
5677 if (!renderbuffer
) {
5679 GL_INVALID_OPERATION
,
5680 "glFramebufferRenderbuffer", "unknown renderbuffer");
5683 service_id
= renderbuffer
->service_id();
5685 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
5686 glFramebufferRenderbufferEXT(
5687 target
, attachment
, renderbuffertarget
, service_id
);
5688 GLenum error
= LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
5689 if (error
== GL_NO_ERROR
) {
5690 framebuffer
->AttachRenderbuffer(attachment
, renderbuffer
);
5692 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
5693 framebuffer_state_
.clear_state_dirty
= true;
5698 void GLES2DecoderImpl::DoDisable(GLenum cap
) {
5699 if (SetCapabilityState(cap
, false)) {
5704 void GLES2DecoderImpl::DoEnable(GLenum cap
) {
5705 if (SetCapabilityState(cap
, true)) {
5710 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear
, GLclampf zfar
) {
5711 state_
.z_near
= std::min(1.0f
, std::max(0.0f
, znear
));
5712 state_
.z_far
= std::min(1.0f
, std::max(0.0f
, zfar
));
5713 glDepthRange(znear
, zfar
);
5716 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value
, GLboolean invert
) {
5717 state_
.sample_coverage_value
= std::min(1.0f
, std::max(0.0f
, value
));
5718 state_
.sample_coverage_invert
= (invert
!= 0);
5719 glSampleCoverage(state_
.sample_coverage_value
, invert
);
5722 // Assumes framebuffer is complete.
5723 void GLES2DecoderImpl::ClearUnclearedAttachments(
5724 GLenum target
, Framebuffer
* framebuffer
) {
5725 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
5726 // bind this to the DRAW point, clear then bind back to READ
5727 // TODO(gman): I don't think there is any guarantee that an FBO that
5728 // is complete on the READ attachment will be complete as a DRAW
5730 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, 0);
5731 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, framebuffer
->service_id());
5733 GLbitfield clear_bits
= 0;
5734 if (framebuffer
->HasUnclearedColorAttachments()) {
5737 (GLES2Util::GetChannelsForFormat(
5738 framebuffer
->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f
:
5740 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
5741 clear_bits
|= GL_COLOR_BUFFER_BIT
;
5742 if (feature_info_
->feature_flags().ext_draw_buffers
)
5743 framebuffer
->PrepareDrawBuffersForClear();
5746 if (framebuffer
->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT
) ||
5747 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
5749 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
5750 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
5751 clear_bits
|= GL_STENCIL_BUFFER_BIT
;
5754 if (framebuffer
->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT
) ||
5755 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
5757 state_
.SetDeviceDepthMask(GL_TRUE
);
5758 clear_bits
|= GL_DEPTH_BUFFER_BIT
;
5761 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5762 glClear(clear_bits
);
5764 if ((clear_bits
& GL_COLOR_BUFFER_BIT
) != 0 &&
5765 feature_info_
->feature_flags().ext_draw_buffers
)
5766 framebuffer
->RestoreDrawBuffersAfterClear();
5768 framebuffer_manager()->MarkAttachmentsAsCleared(
5769 framebuffer
, renderbuffer_manager(), texture_manager());
5771 RestoreClearState();
5773 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
5774 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, framebuffer
->service_id());
5775 Framebuffer
* draw_framebuffer
=
5776 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5777 GLuint service_id
= draw_framebuffer
? draw_framebuffer
->service_id() :
5778 GetBackbufferServiceId();
5779 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, service_id
);
5783 void GLES2DecoderImpl::RestoreClearState() {
5784 framebuffer_state_
.clear_state_dirty
= true;
5786 state_
.color_clear_red
, state_
.color_clear_green
, state_
.color_clear_blue
,
5787 state_
.color_clear_alpha
);
5788 glClearStencil(state_
.stencil_clear
);
5789 glClearDepth(state_
.depth_clear
);
5790 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
,
5791 state_
.enable_flags
.scissor_test
);
5792 glScissor(state_
.scissor_x
, state_
.scissor_y
, state_
.scissor_width
,
5793 state_
.scissor_height
);
5796 GLenum
GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target
) {
5797 Framebuffer
* framebuffer
=
5798 GetFramebufferInfoForTarget(target
);
5800 return GL_FRAMEBUFFER_COMPLETE
;
5802 GLenum completeness
= framebuffer
->IsPossiblyComplete();
5803 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
5804 return completeness
;
5806 return framebuffer
->GetStatus(texture_manager(), target
);
5809 void GLES2DecoderImpl::DoFramebufferTexture2D(
5810 GLenum target
, GLenum attachment
, GLenum textarget
,
5811 GLuint client_texture_id
, GLint level
) {
5812 DoFramebufferTexture2DCommon(
5813 "glFramebufferTexture2D", target
, attachment
,
5814 textarget
, client_texture_id
, level
, 0);
5817 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5818 GLenum target
, GLenum attachment
, GLenum textarget
,
5819 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
5820 DoFramebufferTexture2DCommon(
5821 "glFramebufferTexture2DMultisample", target
, attachment
,
5822 textarget
, client_texture_id
, level
, samples
);
5825 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5826 const char* name
, GLenum target
, GLenum attachment
, GLenum textarget
,
5827 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
5828 if (samples
> renderbuffer_manager()->max_samples()) {
5831 "glFramebufferTexture2DMultisample", "samples too large");
5834 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5837 GL_INVALID_OPERATION
,
5838 name
, "no framebuffer bound.");
5841 GLuint service_id
= 0;
5842 TextureRef
* texture_ref
= NULL
;
5843 if (client_texture_id
) {
5844 texture_ref
= GetTexture(client_texture_id
);
5847 GL_INVALID_OPERATION
,
5848 name
, "unknown texture_ref");
5851 service_id
= texture_ref
->service_id();
5854 if (!texture_manager()->ValidForTarget(textarget
, level
, 0, 0, 1)) {
5857 name
, "level out of range");
5862 DoWillUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
5864 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name
);
5866 glFramebufferTexture2DEXT(target
, attachment
, textarget
, service_id
, level
);
5868 if (features().use_img_for_multisampled_render_to_texture
) {
5869 glFramebufferTexture2DMultisampleIMG(target
, attachment
, textarget
,
5870 service_id
, level
, samples
);
5872 glFramebufferTexture2DMultisampleEXT(target
, attachment
, textarget
,
5873 service_id
, level
, samples
);
5876 GLenum error
= LOCAL_PEEK_GL_ERROR(name
);
5877 if (error
== GL_NO_ERROR
) {
5878 framebuffer
->AttachTexture(attachment
, texture_ref
, textarget
, level
,
5881 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
5882 framebuffer_state_
.clear_state_dirty
= true;
5886 DoDidUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
5891 void GLES2DecoderImpl::DoFramebufferTextureLayer(
5892 GLenum target
, GLenum attachment
, GLuint client_texture_id
,
5893 GLint level
, GLint layer
) {
5894 // TODO(zmo): Unsafe ES3 API, missing states update.
5895 GLuint service_id
= 0;
5896 TextureRef
* texture_ref
= NULL
;
5897 if (client_texture_id
) {
5898 texture_ref
= GetTexture(client_texture_id
);
5901 GL_INVALID_OPERATION
,
5902 "glFramebufferTextureLayer", "unknown texture_ref");
5905 service_id
= texture_ref
->service_id();
5907 glFramebufferTextureLayer(target
, attachment
, service_id
, level
, layer
);
5910 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5911 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
) {
5912 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5915 GL_INVALID_OPERATION
,
5916 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5919 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME
) {
5920 const Framebuffer::Attachment
* attachment_object
=
5921 framebuffer
->GetAttachment(attachment
);
5922 *params
= attachment_object
? attachment_object
->object_name() : 0;
5924 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT
&&
5925 features().use_img_for_multisampled_render_to_texture
) {
5926 pname
= GL_TEXTURE_SAMPLES_IMG
;
5928 glGetFramebufferAttachmentParameterivEXT(target
, attachment
, pname
, params
);
5932 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5933 GLenum target
, GLenum pname
, GLint
* params
) {
5934 Renderbuffer
* renderbuffer
=
5935 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5936 if (!renderbuffer
) {
5938 GL_INVALID_OPERATION
,
5939 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5943 EnsureRenderbufferBound();
5945 case GL_RENDERBUFFER_INTERNAL_FORMAT
:
5946 *params
= renderbuffer
->internal_format();
5948 case GL_RENDERBUFFER_WIDTH
:
5949 *params
= renderbuffer
->width();
5951 case GL_RENDERBUFFER_HEIGHT
:
5952 *params
= renderbuffer
->height();
5954 case GL_RENDERBUFFER_SAMPLES_EXT
:
5955 if (features().use_img_for_multisampled_render_to_texture
) {
5956 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_IMG
,
5959 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_EXT
,
5963 glGetRenderbufferParameterivEXT(target
, pname
, params
);
5968 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5969 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
5970 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
5971 GLbitfield mask
, GLenum filter
) {
5972 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5974 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5978 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5979 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
5980 BlitFramebufferHelper(
5981 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5982 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
,
5983 state_
.enable_flags
.scissor_test
);
5986 void GLES2DecoderImpl::EnsureRenderbufferBound() {
5987 if (!state_
.bound_renderbuffer_valid
) {
5988 state_
.bound_renderbuffer_valid
= true;
5989 glBindRenderbufferEXT(GL_RENDERBUFFER
,
5990 state_
.bound_renderbuffer
.get()
5991 ? state_
.bound_renderbuffer
->service_id()
5996 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
5997 const FeatureInfo
* feature_info
,
6000 GLenum internal_format
,
6003 // TODO(sievers): This could be resolved at the GL binding level, but the
6004 // binding process is currently a bit too 'brute force'.
6005 if (feature_info
->gl_version_info().is_angle
) {
6006 glRenderbufferStorageMultisampleANGLE(
6007 target
, samples
, internal_format
, width
, height
);
6008 } else if (feature_info
->feature_flags().use_core_framebuffer_multisample
) {
6009 glRenderbufferStorageMultisample(
6010 target
, samples
, internal_format
, width
, height
);
6012 glRenderbufferStorageMultisampleEXT(
6013 target
, samples
, internal_format
, width
, height
);
6017 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0
,
6027 // TODO(sievers): This could be resolved at the GL binding level, but the
6028 // binding process is currently a bit too 'brute force'.
6029 if (feature_info_
->gl_version_info().is_angle
) {
6030 glBlitFramebufferANGLE(
6031 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
6032 } else if (feature_info_
->feature_flags().use_core_framebuffer_multisample
) {
6034 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
6036 glBlitFramebufferEXT(
6037 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
6041 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
6043 GLenum internalformat
,
6046 if (samples
> renderbuffer_manager()->max_samples()) {
6049 "glRenderbufferStorageMultisample", "samples too large");
6053 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
6054 height
> renderbuffer_manager()->max_renderbuffer_size()) {
6057 "glRenderbufferStorageMultisample", "dimensions too large");
6061 uint32 estimated_size
= 0;
6062 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6063 width
, height
, samples
, internalformat
, &estimated_size
)) {
6066 "glRenderbufferStorageMultisample", "dimensions too large");
6070 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
6073 "glRenderbufferStorageMultisample", "out of memory");
6080 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
6081 GLenum target
, GLsizei samples
, GLenum internalformat
,
6082 GLsizei width
, GLsizei height
) {
6083 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
6084 if (!renderbuffer
) {
6085 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
6086 "glRenderbufferStorageMultisampleCHROMIUM",
6087 "no renderbuffer bound");
6091 if (!ValidateRenderbufferStorageMultisample(
6092 samples
, internalformat
, width
, height
)) {
6096 EnsureRenderbufferBound();
6097 GLenum impl_format
=
6098 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6100 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
6101 "glRenderbufferStorageMultisampleCHROMIUM");
6102 RenderbufferStorageMultisampleHelper(
6103 feature_info_
.get(), target
, samples
, impl_format
, width
, height
);
6105 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
6106 if (error
== GL_NO_ERROR
) {
6107 if (workarounds().validate_multisample_buffer_allocation
) {
6108 if (!VerifyMultisampleRenderbufferIntegrity(
6109 renderbuffer
->service_id(), impl_format
)) {
6112 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
6117 // TODO(gman): If renderbuffers tracked which framebuffers they were
6118 // attached to we could just mark those framebuffers as not complete.
6119 framebuffer_manager()->IncFramebufferStateChangeCount();
6120 renderbuffer_manager()->SetInfo(
6121 renderbuffer
, samples
, internalformat
, width
, height
);
6125 // This is the handler for multisampled_render_to_texture extensions.
6126 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
6127 GLenum target
, GLsizei samples
, GLenum internalformat
,
6128 GLsizei width
, GLsizei height
) {
6129 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
6130 if (!renderbuffer
) {
6131 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
6132 "glRenderbufferStorageMultisampleEXT",
6133 "no renderbuffer bound");
6137 if (!ValidateRenderbufferStorageMultisample(
6138 samples
, internalformat
, width
, height
)) {
6142 EnsureRenderbufferBound();
6143 GLenum impl_format
=
6144 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6146 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
6147 if (features().use_img_for_multisampled_render_to_texture
) {
6148 glRenderbufferStorageMultisampleIMG(
6149 target
, samples
, impl_format
, width
, height
);
6151 glRenderbufferStorageMultisampleEXT(
6152 target
, samples
, impl_format
, width
, height
);
6154 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
6155 if (error
== GL_NO_ERROR
) {
6156 // TODO(gman): If renderbuffers tracked which framebuffers they were
6157 // attached to we could just mark those framebuffers as not complete.
6158 framebuffer_manager()->IncFramebufferStateChangeCount();
6159 renderbuffer_manager()->SetInfo(
6160 renderbuffer
, samples
, internalformat
, width
, height
);
6164 // This function validates the allocation of a multisampled renderbuffer
6165 // by clearing it to a key color, blitting the contents to a texture, and
6166 // reading back the color to ensure it matches the key.
6167 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
6168 GLuint renderbuffer
, GLenum format
) {
6170 // Only validate color buffers.
6171 // These formats have been selected because they are very common or are known
6172 // to be used by the WebGL backbuffer. If problems are observed with other
6173 // color formats they can be added here.
6184 GLint draw_framebuffer
, read_framebuffer
;
6186 // Cache framebuffer and texture bindings.
6187 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING
, &draw_framebuffer
);
6188 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING
, &read_framebuffer
);
6190 if (!validation_texture_
) {
6191 GLint bound_texture
;
6192 glGetIntegerv(GL_TEXTURE_BINDING_2D
, &bound_texture
);
6194 // Create additional resources needed for the verification.
6195 glGenTextures(1, &validation_texture_
);
6196 glGenFramebuffersEXT(1, &validation_fbo_multisample_
);
6197 glGenFramebuffersEXT(1, &validation_fbo_
);
6199 // Texture only needs to be 1x1.
6200 glBindTexture(GL_TEXTURE_2D
, validation_texture_
);
6201 // TODO(erikchen): When Chrome on Mac is linked against an OSX 10.9+ SDK, a
6202 // multisample will fail if the color format of the source and destination
6203 // do not match. Here, we assume that the source is GL_RGBA, and make the
6204 // destination GL_RGBA. http://crbug.com/484203
6205 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, 1, 1, 0, GL_RGBA
,
6206 GL_UNSIGNED_BYTE
, NULL
);
6208 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
6209 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
6210 GL_TEXTURE_2D
, validation_texture_
, 0);
6212 glBindTexture(GL_TEXTURE_2D
, bound_texture
);
6215 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
6216 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
6217 GL_RENDERBUFFER
, renderbuffer
);
6219 // Cache current state and reset it to the values we require.
6220 GLboolean scissor_enabled
= false;
6221 glGetBooleanv(GL_SCISSOR_TEST
, &scissor_enabled
);
6222 if (scissor_enabled
)
6223 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
6225 GLboolean color_mask
[4] = {GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
};
6226 glGetBooleanv(GL_COLOR_WRITEMASK
, color_mask
);
6227 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
6229 GLfloat clear_color
[4] = {0.0f
, 0.0f
, 0.0f
, 0.0f
};
6230 glGetFloatv(GL_COLOR_CLEAR_VALUE
, clear_color
);
6231 glClearColor(1.0f
, 0.0f
, 1.0f
, 1.0f
);
6233 // Clear the buffer to the desired key color.
6234 glClear(GL_COLOR_BUFFER_BIT
);
6236 // Blit from the multisample buffer to a standard texture.
6237 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, validation_fbo_multisample_
);
6238 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, validation_fbo_
);
6240 BlitFramebufferHelper(
6241 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
6243 // Read a pixel from the buffer.
6244 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
6246 unsigned char pixel
[3] = {0, 0, 0};
6247 glReadPixels(0, 0, 1, 1, GL_RGB
, GL_UNSIGNED_BYTE
, &pixel
);
6249 // Detach the renderbuffer.
6250 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
6251 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
6252 GL_RENDERBUFFER
, 0);
6254 // Restore cached state.
6255 if (scissor_enabled
)
6256 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
6258 state_
.SetDeviceColorMask(
6259 color_mask
[0], color_mask
[1], color_mask
[2], color_mask
[3]);
6260 glClearColor(clear_color
[0], clear_color
[1], clear_color
[2], clear_color
[3]);
6261 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, draw_framebuffer
);
6262 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, read_framebuffer
);
6264 // Return true if the pixel matched the desired key color.
6265 return (pixel
[0] == 0xFF &&
6270 void GLES2DecoderImpl::DoRenderbufferStorage(
6271 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
) {
6272 Renderbuffer
* renderbuffer
=
6273 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
6274 if (!renderbuffer
) {
6276 GL_INVALID_OPERATION
,
6277 "glRenderbufferStorage", "no renderbuffer bound");
6281 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
6282 height
> renderbuffer_manager()->max_renderbuffer_size()) {
6284 GL_INVALID_VALUE
, "glRenderbufferStorage", "dimensions too large");
6288 uint32 estimated_size
= 0;
6289 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6290 width
, height
, 1, internalformat
, &estimated_size
)) {
6292 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "dimensions too large");
6296 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
6298 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "out of memory");
6302 EnsureRenderbufferBound();
6303 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
6304 glRenderbufferStorageEXT(
6306 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6310 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
6311 if (error
== GL_NO_ERROR
) {
6312 // TODO(gman): If tetxures tracked which framebuffers they were attached to
6313 // we could just mark those framebuffers as not complete.
6314 framebuffer_manager()->IncFramebufferStateChangeCount();
6315 renderbuffer_manager()->SetInfo(
6316 renderbuffer
, 1, internalformat
, width
, height
);
6320 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id
) {
6321 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
6322 SCOPED_UMA_HISTOGRAM_TIMER("GPU.DoLinkProgramTime");
6323 Program
* program
= GetProgramInfoNotShader(
6324 program_id
, "glLinkProgram");
6329 LogClientServiceForInfo(program
, program_id
, "glLinkProgram");
6330 if (program
->Link(shader_manager(),
6331 workarounds().count_all_in_varyings_packing
?
6332 Program::kCountAll
: Program::kCountOnlyStaticallyUsed
,
6333 shader_cache_callback_
)) {
6334 if (program
== state_
.current_program
.get()) {
6335 if (workarounds().use_current_program_after_successful_link
)
6336 glUseProgram(program
->service_id());
6337 if (workarounds().clear_uniforms_before_first_program_use
)
6338 program_manager()->ClearUniforms(program
);
6342 // LinkProgram can be very slow. Exit command processing to allow for
6343 // context preemption and GPU watchdog checks.
6344 ExitCommandProcessingEarly();
6347 void GLES2DecoderImpl::DoReadBuffer(GLenum src
) {
6354 GLenum upper_limit
= static_cast<GLenum
>(
6355 group_
->max_color_attachments() + GL_COLOR_ATTACHMENT0
);
6356 if (src
< GL_COLOR_ATTACHMENT0
|| src
>= upper_limit
) {
6358 GL_INVALID_ENUM
, "glReadBuffer", "invalid enum for src");
6365 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER
);
6367 if (src
== GL_BACK
) {
6369 GL_INVALID_ENUM
, "glReadBuffer",
6370 "invalid src for a named framebuffer");
6373 framebuffer
->set_read_buffer(src
);
6375 if (src
!= GL_NONE
&& src
!= GL_BACK
) {
6377 GL_INVALID_ENUM
, "glReadBuffer",
6378 "invalid src for the default framebuffer");
6381 back_buffer_read_buffer_
= src
;
6382 if (GetBackbufferServiceId() && src
== GL_BACK
)
6383 src
= GL_COLOR_ATTACHMENT0
;
6388 void GLES2DecoderImpl::DoSamplerParameterfv(
6389 GLuint sampler
, GLenum pname
, const GLfloat
* params
) {
6391 glSamplerParameterf(sampler
, pname
, params
[0]);
6394 void GLES2DecoderImpl::DoSamplerParameteriv(
6395 GLuint sampler
, GLenum pname
, const GLint
* params
) {
6397 glSamplerParameteri(sampler
, pname
, params
[0]);
6400 void GLES2DecoderImpl::DoTexParameterf(
6401 GLenum target
, GLenum pname
, GLfloat param
) {
6402 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6405 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterf", "unknown texture");
6409 texture_manager()->SetParameterf(
6410 "glTexParameterf", GetErrorState(), texture
, pname
, param
);
6413 void GLES2DecoderImpl::DoTexParameteri(
6414 GLenum target
, GLenum pname
, GLint param
) {
6415 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6418 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameteri", "unknown texture");
6422 texture_manager()->SetParameteri(
6423 "glTexParameteri", GetErrorState(), texture
, pname
, param
);
6426 void GLES2DecoderImpl::DoTexParameterfv(
6427 GLenum target
, GLenum pname
, const GLfloat
* params
) {
6428 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6431 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterfv", "unknown texture");
6435 texture_manager()->SetParameterf(
6436 "glTexParameterfv", GetErrorState(), texture
, pname
, *params
);
6439 void GLES2DecoderImpl::DoTexParameteriv(
6440 GLenum target
, GLenum pname
, const GLint
* params
) {
6441 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6445 GL_INVALID_VALUE
, "glTexParameteriv", "unknown texture");
6449 texture_manager()->SetParameteri(
6450 "glTexParameteriv", GetErrorState(), texture
, pname
, *params
);
6453 bool GLES2DecoderImpl::CheckCurrentValuebuffer(const char* function_name
) {
6454 if (!state_
.bound_valuebuffer
.get()) {
6455 // There is no valuebuffer bound
6456 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6457 "no valuebuffer in use");
6463 bool GLES2DecoderImpl::CheckCurrentValuebufferForSubscription(
6464 GLenum subscription
,
6465 const char* function_name
) {
6466 if (!CheckCurrentValuebuffer(function_name
)) {
6469 if (!state_
.bound_valuebuffer
.get()->IsSubscribed(subscription
)) {
6470 // The valuebuffer is not subscribed to the target
6471 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6472 "valuebuffer is not subscribed");
6478 bool GLES2DecoderImpl::CheckSubscriptionTarget(GLint location
,
6479 GLenum subscription
,
6480 const char* function_name
) {
6481 if (!CheckCurrentProgramForUniform(location
, function_name
)) {
6484 GLint real_location
= -1;
6485 GLint array_index
= -1;
6486 const Program::UniformInfo
* info
=
6487 state_
.current_program
->GetUniformInfoByFakeLocation(
6488 location
, &real_location
, &array_index
);
6490 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
, "unknown location");
6493 if ((ValuebufferManager::ApiTypeForSubscriptionTarget(subscription
) &
6494 info
->accepts_api_type
) == 0) {
6495 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6496 "wrong type for subscription");
6502 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name
) {
6503 if (!state_
.current_program
.get()) {
6504 // The program does not exist.
6506 GL_INVALID_OPERATION
, function_name
, "no program in use");
6509 if (!state_
.current_program
->InUse()) {
6511 GL_INVALID_OPERATION
, function_name
, "program not linked");
6517 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
6518 GLint location
, const char* function_name
) {
6519 if (!CheckCurrentProgram(function_name
)) {
6522 return location
!= -1;
6525 bool GLES2DecoderImpl::CheckDrawingFeedbackLoops() {
6526 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
6529 const Framebuffer::Attachment
* attachment
=
6530 framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
);
6534 DCHECK(state_
.current_program
.get());
6535 const Program::SamplerIndices
& sampler_indices
=
6536 state_
.current_program
->sampler_indices();
6537 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6538 const Program::UniformInfo
* uniform_info
=
6539 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6540 DCHECK(uniform_info
);
6541 if (uniform_info
->type
!= GL_SAMPLER_2D
)
6543 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6544 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6545 if (texture_unit_index
>= state_
.texture_units
.size())
6547 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6548 TextureRef
* texture_ref
=
6549 texture_unit
.GetInfoForSamplerType(GL_SAMPLER_2D
).get();
6550 if (attachment
->IsTexture(texture_ref
))
6557 bool GLES2DecoderImpl::CheckUniformForApiType(
6558 const Program::UniformInfo
* info
,
6559 const char* function_name
,
6560 Program::UniformApiType api_type
) {
6562 if ((api_type
& info
->accepts_api_type
) == 0) {
6563 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6564 "wrong uniform function for type");
6570 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
6571 GLint fake_location
,
6572 const char* function_name
,
6573 Program::UniformApiType api_type
,
6574 GLint
* real_location
,
6579 DCHECK(real_location
);
6581 if (!CheckCurrentProgramForUniform(fake_location
, function_name
)) {
6584 GLint array_index
= -1;
6585 const Program::UniformInfo
* info
=
6586 state_
.current_program
->GetUniformInfoByFakeLocation(
6587 fake_location
, real_location
, &array_index
);
6590 GL_INVALID_OPERATION
, function_name
, "unknown location");
6593 if (!CheckUniformForApiType(info
, function_name
, api_type
)) {
6596 if (*count
> 1 && !info
->is_array
) {
6598 GL_INVALID_OPERATION
, function_name
, "count > 1 for non-array");
6601 *count
= std::min(info
->size
- array_index
, *count
);
6609 void GLES2DecoderImpl::DoUniform1i(GLint fake_location
, GLint v0
) {
6612 GLint real_location
= -1;
6613 if (!PrepForSetUniformByLocation(fake_location
,
6615 Program::kUniform1i
,
6621 if (!state_
.current_program
->SetSamplers(
6622 state_
.texture_units
.size(), fake_location
, 1, &v0
)) {
6624 GL_INVALID_VALUE
, "glUniform1i", "texture unit out of range");
6627 glUniform1i(real_location
, v0
);
6630 void GLES2DecoderImpl::DoUniform1iv(
6631 GLint fake_location
, GLsizei count
, const GLint
*value
) {
6633 GLint real_location
= -1;
6634 if (!PrepForSetUniformByLocation(fake_location
,
6636 Program::kUniform1i
,
6642 if (type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_2D_RECT_ARB
||
6643 type
== GL_SAMPLER_CUBE
|| type
== GL_SAMPLER_EXTERNAL_OES
) {
6644 if (!state_
.current_program
->SetSamplers(
6645 state_
.texture_units
.size(), fake_location
, count
, value
)) {
6647 GL_INVALID_VALUE
, "glUniform1iv", "texture unit out of range");
6651 glUniform1iv(real_location
, count
, value
);
6654 void GLES2DecoderImpl::DoUniform1fv(
6655 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6657 GLint real_location
= -1;
6658 if (!PrepForSetUniformByLocation(fake_location
,
6660 Program::kUniform1f
,
6666 if (type
== GL_BOOL
) {
6667 scoped_ptr
<GLint
[]> temp(new GLint
[count
]);
6668 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
6669 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6671 DoUniform1iv(real_location
, count
, temp
.get());
6673 glUniform1fv(real_location
, count
, value
);
6677 void GLES2DecoderImpl::DoUniform2fv(
6678 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6680 GLint real_location
= -1;
6681 if (!PrepForSetUniformByLocation(fake_location
,
6683 Program::kUniform2f
,
6689 if (type
== GL_BOOL_VEC2
) {
6690 GLsizei num_values
= count
* 2;
6691 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6692 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6693 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6695 glUniform2iv(real_location
, count
, temp
.get());
6697 glUniform2fv(real_location
, count
, value
);
6701 void GLES2DecoderImpl::DoUniform3fv(
6702 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6704 GLint real_location
= -1;
6705 if (!PrepForSetUniformByLocation(fake_location
,
6707 Program::kUniform3f
,
6713 if (type
== GL_BOOL_VEC3
) {
6714 GLsizei num_values
= count
* 3;
6715 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6716 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6717 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6719 glUniform3iv(real_location
, count
, temp
.get());
6721 glUniform3fv(real_location
, count
, value
);
6725 void GLES2DecoderImpl::DoUniform4fv(
6726 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6728 GLint real_location
= -1;
6729 if (!PrepForSetUniformByLocation(fake_location
,
6731 Program::kUniform4f
,
6737 if (type
== GL_BOOL_VEC4
) {
6738 GLsizei num_values
= count
* 4;
6739 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6740 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6741 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6743 glUniform4iv(real_location
, count
, temp
.get());
6745 glUniform4fv(real_location
, count
, value
);
6749 void GLES2DecoderImpl::DoUniform2iv(
6750 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6752 GLint real_location
= -1;
6753 if (!PrepForSetUniformByLocation(fake_location
,
6755 Program::kUniform2i
,
6761 glUniform2iv(real_location
, count
, value
);
6764 void GLES2DecoderImpl::DoUniform3iv(
6765 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6767 GLint real_location
= -1;
6768 if (!PrepForSetUniformByLocation(fake_location
,
6770 Program::kUniform3i
,
6776 glUniform3iv(real_location
, count
, value
);
6779 void GLES2DecoderImpl::DoUniform4iv(
6780 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6782 GLint real_location
= -1;
6783 if (!PrepForSetUniformByLocation(fake_location
,
6785 Program::kUniform4i
,
6791 glUniform4iv(real_location
, count
, value
);
6794 void GLES2DecoderImpl::DoUniformMatrix2fv(
6795 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6796 const GLfloat
* value
) {
6798 GLint real_location
= -1;
6799 if (!PrepForSetUniformByLocation(fake_location
,
6800 "glUniformMatrix2fv",
6801 Program::kUniformMatrix2f
,
6807 glUniformMatrix2fv(real_location
, count
, transpose
, value
);
6810 void GLES2DecoderImpl::DoUniformMatrix3fv(
6811 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6812 const GLfloat
* value
) {
6814 GLint real_location
= -1;
6815 if (!PrepForSetUniformByLocation(fake_location
,
6816 "glUniformMatrix3fv",
6817 Program::kUniformMatrix3f
,
6823 glUniformMatrix3fv(real_location
, count
, transpose
, value
);
6826 void GLES2DecoderImpl::DoUniformMatrix4fv(
6827 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6828 const GLfloat
* value
) {
6830 GLint real_location
= -1;
6831 if (!PrepForSetUniformByLocation(fake_location
,
6832 "glUniformMatrix4fv",
6833 Program::kUniformMatrix4f
,
6839 glUniformMatrix4fv(real_location
, count
, transpose
, value
);
6842 void GLES2DecoderImpl::DoUseProgram(GLuint program_id
) {
6843 GLuint service_id
= 0;
6844 Program
* program
= NULL
;
6846 program
= GetProgramInfoNotShader(program_id
, "glUseProgram");
6850 if (!program
->IsValid()) {
6851 // Program was not linked successfully. (ie, glLinkProgram)
6853 GL_INVALID_OPERATION
, "glUseProgram", "program not linked");
6856 service_id
= program
->service_id();
6858 if (state_
.current_program
.get()) {
6859 program_manager()->UnuseProgram(shader_manager(),
6860 state_
.current_program
.get());
6862 state_
.current_program
= program
;
6863 LogClientServiceMapping("glUseProgram", program_id
, service_id
);
6864 glUseProgram(service_id
);
6865 if (state_
.current_program
.get()) {
6866 program_manager()->UseProgram(state_
.current_program
.get());
6867 if (workarounds().clear_uniforms_before_first_program_use
)
6868 program_manager()->ClearUniforms(program
);
6872 void GLES2DecoderImpl::RenderWarning(
6873 const char* filename
, int line
, const std::string
& msg
) {
6874 logger_
.LogMessage(filename
, line
, std::string("RENDER WARNING: ") + msg
);
6877 void GLES2DecoderImpl::PerformanceWarning(
6878 const char* filename
, int line
, const std::string
& msg
) {
6879 logger_
.LogMessage(filename
, line
,
6880 std::string("PERFORMANCE WARNING: ") + msg
);
6883 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
6884 Texture
* texture
, GLenum textarget
) {
6885 // Image is already in use if texture is attached to a framebuffer.
6886 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
6887 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6889 ScopedGLErrorSuppressor
suppressor(
6890 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
6892 glBindTexture(textarget
, texture
->service_id());
6893 image
->WillUseTexImage();
6894 RestoreCurrentTextureBindings(&state_
, textarget
);
6899 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6900 Texture
* texture
, GLenum textarget
) {
6901 // Image is still in use if texture is attached to a framebuffer.
6902 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
6903 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6905 ScopedGLErrorSuppressor
suppressor(
6906 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6908 glBindTexture(textarget
, texture
->service_id());
6909 image
->DidUseTexImage();
6910 RestoreCurrentTextureBindings(&state_
, textarget
);
6915 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6916 DCHECK(state_
.current_program
.get());
6917 if (!texture_manager()->HaveUnrenderableTextures() &&
6918 !texture_manager()->HaveImages()) {
6922 bool textures_set
= false;
6923 const Program::SamplerIndices
& sampler_indices
=
6924 state_
.current_program
->sampler_indices();
6925 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6926 const Program::UniformInfo
* uniform_info
=
6927 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6928 DCHECK(uniform_info
);
6929 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6930 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6931 if (texture_unit_index
< state_
.texture_units
.size()) {
6932 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6933 TextureRef
* texture_ref
=
6934 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6935 GLenum textarget
= GetBindTargetForSamplerType(uniform_info
->type
);
6936 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
6937 textures_set
= true;
6938 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6941 texture_manager()->black_texture_id(uniform_info
->type
));
6943 LOCAL_RENDER_WARNING(
6944 std::string("there is no texture bound to the unit ") +
6945 base::IntToString(texture_unit_index
));
6947 LOCAL_RENDER_WARNING(
6948 std::string("texture bound to texture unit ") +
6949 base::IntToString(texture_unit_index
) +
6950 " is not renderable. It maybe non-power-of-2 and have"
6951 " incompatible texture filtering.");
6956 if (textarget
!= GL_TEXTURE_CUBE_MAP
) {
6957 Texture
* texture
= texture_ref
->texture();
6958 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6959 if (image
&& !texture
->IsAttachedToFramebuffer()) {
6960 ScopedGLErrorSuppressor
suppressor(
6961 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6962 textures_set
= true;
6963 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6964 image
->WillUseTexImage();
6969 // else: should this be an error?
6972 return !textures_set
;
6975 void GLES2DecoderImpl::RestoreStateForTextures() {
6976 DCHECK(state_
.current_program
.get());
6977 const Program::SamplerIndices
& sampler_indices
=
6978 state_
.current_program
->sampler_indices();
6979 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6980 const Program::UniformInfo
* uniform_info
=
6981 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6982 DCHECK(uniform_info
);
6983 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6984 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6985 if (texture_unit_index
< state_
.texture_units
.size()) {
6986 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6987 TextureRef
* texture_ref
=
6988 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6989 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
6990 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6991 // Get the texture_ref info that was previously bound here.
6992 texture_ref
= texture_unit
.bind_target
== GL_TEXTURE_2D
6993 ? texture_unit
.bound_texture_2d
.get()
6994 : texture_unit
.bound_texture_cube_map
.get();
6995 glBindTexture(texture_unit
.bind_target
,
6996 texture_ref
? texture_ref
->service_id() : 0);
7000 if (texture_unit
.bind_target
!= GL_TEXTURE_CUBE_MAP
) {
7001 Texture
* texture
= texture_ref
->texture();
7002 gfx::GLImage
* image
=
7003 texture
->GetLevelImage(texture_unit
.bind_target
, 0);
7004 if (image
&& !texture
->IsAttachedToFramebuffer()) {
7005 ScopedGLErrorSuppressor
suppressor(
7006 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
7007 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
7008 image
->DidUseTexImage();
7015 // Set the active texture back to whatever the user had it as.
7016 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
7019 bool GLES2DecoderImpl::ClearUnclearedTextures() {
7020 // Only check if there are some uncleared textures.
7021 if (!texture_manager()->HaveUnsafeTextures()) {
7025 // 1: Check all textures we are about to render with.
7026 if (state_
.current_program
.get()) {
7027 const Program::SamplerIndices
& sampler_indices
=
7028 state_
.current_program
->sampler_indices();
7029 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
7030 const Program::UniformInfo
* uniform_info
=
7031 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
7032 DCHECK(uniform_info
);
7033 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
7034 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
7035 if (texture_unit_index
< state_
.texture_units
.size()) {
7036 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
7037 TextureRef
* texture_ref
=
7038 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
7039 if (texture_ref
&& !texture_ref
->texture()->SafeToRenderFrom()) {
7040 if (!texture_manager()->ClearRenderableLevels(this, texture_ref
)) {
7051 bool GLES2DecoderImpl::IsDrawValid(
7052 const char* function_name
, GLuint max_vertex_accessed
, bool instanced
,
7053 GLsizei primcount
) {
7054 DCHECK(instanced
|| primcount
== 1);
7056 // NOTE: We specifically do not check current_program->IsValid() because
7057 // it could never be invalid since glUseProgram would have failed. While
7058 // glLinkProgram could later mark the program as invalid the previous
7059 // valid program will still function if it is still the current program.
7060 if (!state_
.current_program
.get()) {
7061 // The program does not exist.
7062 // But GL says no ERROR.
7063 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
7067 if (CheckDrawingFeedbackLoops()) {
7069 GL_INVALID_OPERATION
, function_name
,
7070 "Source and destination textures of the draw are the same.");
7074 return state_
.vertex_attrib_manager
7075 ->ValidateBindings(function_name
,
7077 feature_info_
.get(),
7078 state_
.current_program
.get(),
7079 max_vertex_accessed
,
7084 bool GLES2DecoderImpl::SimulateAttrib0(
7085 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
) {
7089 if (feature_info_
->gl_version_info().BehavesLikeGLES())
7092 const VertexAttrib
* attrib
=
7093 state_
.vertex_attrib_manager
->GetVertexAttrib(0);
7094 // If it's enabled or it's not used then we don't need to do anything.
7095 bool attrib_0_used
=
7096 state_
.current_program
->GetAttribInfoByLocation(0) != NULL
;
7097 if (attrib
->enabled() && attrib_0_used
) {
7101 // Make a buffer with a single repeated vec4 value enough to
7102 // simulate the constant value that is supposed to be here.
7103 // This is required to emulate GLES2 on GL.
7104 GLuint num_vertices
= max_vertex_accessed
+ 1;
7105 uint32 size_needed
= 0;
7107 if (num_vertices
== 0 ||
7108 !SafeMultiplyUint32(num_vertices
, sizeof(Vec4f
), &size_needed
) ||
7109 size_needed
> 0x7FFFFFFFU
) {
7110 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
7114 LOCAL_PERFORMANCE_WARNING(
7115 "Attribute 0 is disabled. This has signficant performance penalty");
7117 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
7118 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
7120 bool new_buffer
= static_cast<GLsizei
>(size_needed
) > attrib_0_size_
;
7122 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
7123 GLenum error
= glGetError();
7124 if (error
!= GL_NO_ERROR
) {
7126 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
7131 const Vec4
& value
= state_
.attrib_values
[0];
7134 (!attrib_0_buffer_matches_value_
|| !value
.Equal(attrib_0_value_
)))){
7135 // TODO(zmo): This is not 100% correct because we might lose data when
7136 // casting to float type, but it is a corner case and once we migrate to
7137 // core profiles on desktop GL, it is no longer relevant.
7138 Vec4f
fvalue(value
);
7139 std::vector
<Vec4f
> temp(num_vertices
, fvalue
);
7140 glBufferSubData(GL_ARRAY_BUFFER
, 0, size_needed
, &temp
[0].v
[0]);
7141 attrib_0_buffer_matches_value_
= true;
7142 attrib_0_value_
= value
;
7143 attrib_0_size_
= size_needed
;
7146 glVertexAttribPointer(0, 4, GL_FLOAT
, GL_FALSE
, 0, NULL
);
7148 if (attrib
->divisor())
7149 glVertexAttribDivisorANGLE(0, 0);
7155 void GLES2DecoderImpl::RestoreStateForAttrib(
7156 GLuint attrib_index
, bool restore_array_binding
) {
7157 const VertexAttrib
* attrib
=
7158 state_
.vertex_attrib_manager
->GetVertexAttrib(attrib_index
);
7159 if (restore_array_binding
) {
7160 const void* ptr
= reinterpret_cast<const void*>(attrib
->offset());
7161 Buffer
* buffer
= attrib
->buffer();
7162 glBindBuffer(GL_ARRAY_BUFFER
, buffer
? buffer
->service_id() : 0);
7163 glVertexAttribPointer(
7164 attrib_index
, attrib
->size(), attrib
->type(), attrib
->normalized(),
7165 attrib
->gl_stride(), ptr
);
7167 if (attrib
->divisor())
7168 glVertexAttribDivisorANGLE(attrib_index
, attrib
->divisor());
7170 GL_ARRAY_BUFFER
, state_
.bound_array_buffer
.get() ?
7171 state_
.bound_array_buffer
->service_id() : 0);
7173 // Never touch vertex attribute 0's state (in particular, never
7174 // disable it) when running on desktop GL because it will never be
7176 if (attrib_index
!= 0 ||
7177 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
7178 if (attrib
->enabled()) {
7179 glEnableVertexAttribArray(attrib_index
);
7181 glDisableVertexAttribArray(attrib_index
);
7186 bool GLES2DecoderImpl::SimulateFixedAttribs(
7187 const char* function_name
,
7188 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
) {
7191 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
)
7194 if (!state_
.vertex_attrib_manager
->HaveFixedAttribs()) {
7198 LOCAL_PERFORMANCE_WARNING(
7199 "GL_FIXED attributes have a signficant performance penalty");
7201 // NOTE: we could be smart and try to check if a buffer is used
7202 // twice in 2 different attribs, find the overlapping parts and therefore
7203 // duplicate the minimum amount of data but this whole code path is not meant
7204 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
7205 // tests so we just add to the buffer attrib used.
7207 GLuint elements_needed
= 0;
7208 const VertexAttribManager::VertexAttribList
& enabled_attribs
=
7209 state_
.vertex_attrib_manager
->GetEnabledVertexAttribs();
7210 for (VertexAttribManager::VertexAttribList::const_iterator it
=
7211 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
7212 const VertexAttrib
* attrib
= *it
;
7213 const Program::VertexAttrib
* attrib_info
=
7214 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
7215 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
7216 max_vertex_accessed
);
7217 GLuint num_vertices
= max_accessed
+ 1;
7218 if (num_vertices
== 0) {
7220 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
7224 attrib
->CanAccess(max_accessed
) &&
7225 attrib
->type() == GL_FIXED
) {
7226 uint32 elements_used
= 0;
7227 if (!SafeMultiplyUint32(num_vertices
, attrib
->size(), &elements_used
) ||
7228 !SafeAddUint32(elements_needed
, elements_used
, &elements_needed
)) {
7230 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
7236 const uint32 kSizeOfFloat
= sizeof(float); // NOLINT
7237 uint32 size_needed
= 0;
7238 if (!SafeMultiplyUint32(elements_needed
, kSizeOfFloat
, &size_needed
) ||
7239 size_needed
> 0x7FFFFFFFU
) {
7241 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
7245 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
7247 glBindBuffer(GL_ARRAY_BUFFER
, fixed_attrib_buffer_id_
);
7248 if (static_cast<GLsizei
>(size_needed
) > fixed_attrib_buffer_size_
) {
7249 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
7250 GLenum error
= glGetError();
7251 if (error
!= GL_NO_ERROR
) {
7253 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
7258 // Copy the elements and convert to float
7259 GLintptr offset
= 0;
7260 for (VertexAttribManager::VertexAttribList::const_iterator it
=
7261 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
7262 const VertexAttrib
* attrib
= *it
;
7263 const Program::VertexAttrib
* attrib_info
=
7264 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
7265 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
7266 max_vertex_accessed
);
7267 GLuint num_vertices
= max_accessed
+ 1;
7268 if (num_vertices
== 0) {
7270 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
7274 attrib
->CanAccess(max_accessed
) &&
7275 attrib
->type() == GL_FIXED
) {
7276 int num_elements
= attrib
->size() * num_vertices
;
7277 const int src_size
= num_elements
* sizeof(int32
);
7278 const int dst_size
= num_elements
* sizeof(float);
7279 scoped_ptr
<float[]> data(new float[num_elements
]);
7280 const int32
* src
= reinterpret_cast<const int32
*>(
7281 attrib
->buffer()->GetRange(attrib
->offset(), src_size
));
7282 const int32
* end
= src
+ num_elements
;
7283 float* dst
= data
.get();
7284 while (src
!= end
) {
7285 *dst
++ = static_cast<float>(*src
++) / 65536.0f
;
7287 glBufferSubData(GL_ARRAY_BUFFER
, offset
, dst_size
, data
.get());
7288 glVertexAttribPointer(
7289 attrib
->index(), attrib
->size(), GL_FLOAT
, false, 0,
7290 reinterpret_cast<GLvoid
*>(offset
));
7298 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
7299 // There's no need to call glVertexAttribPointer because we shadow all the
7300 // settings and passing GL_FIXED to it will not work.
7303 state_
.bound_array_buffer
.get() ? state_
.bound_array_buffer
->service_id()
7307 error::Error
GLES2DecoderImpl::DoDrawArrays(
7308 const char* function_name
,
7313 GLsizei primcount
) {
7314 error::Error error
= WillAccessBoundFramebufferForDraw();
7315 if (error
!= error::kNoError
)
7317 if (!validators_
->draw_mode
.IsValid(mode
)) {
7318 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
7319 return error::kNoError
;
7322 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
7323 return error::kNoError
;
7325 if (primcount
< 0) {
7326 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
7327 return error::kNoError
;
7329 if (!CheckBoundFramebuffersValid(function_name
)) {
7330 return error::kNoError
;
7332 // We have to check this here because the prototype for glDrawArrays
7333 // is GLint not GLsizei.
7335 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "first < 0");
7336 return error::kNoError
;
7339 if (count
== 0 || primcount
== 0) {
7340 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
7341 return error::kNoError
;
7344 GLuint max_vertex_accessed
= first
+ count
- 1;
7345 if (IsDrawValid(function_name
, max_vertex_accessed
, instanced
, primcount
)) {
7346 if (!ClearUnclearedTextures()) {
7347 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
7348 return error::kNoError
;
7350 bool simulated_attrib_0
= false;
7351 if (!SimulateAttrib0(
7352 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
7353 return error::kNoError
;
7355 bool simulated_fixed_attribs
= false;
7356 if (SimulateFixedAttribs(
7357 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
7359 bool textures_set
= !PrepareTexturesForRender();
7361 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
7363 glDrawArrays(mode
, first
, count
);
7365 glDrawArraysInstancedANGLE(mode
, first
, count
, primcount
);
7368 RestoreStateForTextures();
7370 if (simulated_fixed_attribs
) {
7371 RestoreStateForSimulatedFixedAttribs();
7374 if (simulated_attrib_0
) {
7375 // We don't have to restore attrib 0 generic data at the end of this
7376 // function even if it is simulated. This is because we will simulate
7377 // it in each draw call, and attrib 0 generic data queries use cached
7378 // values instead of passing down to the underlying driver.
7379 RestoreStateForAttrib(0, false);
7382 return error::kNoError
;
7385 error::Error
GLES2DecoderImpl::HandleDrawArrays(uint32 immediate_data_size
,
7386 const void* cmd_data
) {
7387 // TODO(zmo): crbug.com/481184
7388 // On Desktop GL with versions lower than 4.3, we need to emulate
7389 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7390 const cmds::DrawArrays
& c
= *static_cast<const cmds::DrawArrays
*>(cmd_data
);
7391 return DoDrawArrays("glDrawArrays",
7393 static_cast<GLenum
>(c
.mode
),
7394 static_cast<GLint
>(c
.first
),
7395 static_cast<GLsizei
>(c
.count
),
7399 error::Error
GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
7400 uint32 immediate_data_size
,
7401 const void* cmd_data
) {
7402 const gles2::cmds::DrawArraysInstancedANGLE
& c
=
7403 *static_cast<const gles2::cmds::DrawArraysInstancedANGLE
*>(cmd_data
);
7404 if (!features().angle_instanced_arrays
) {
7406 GL_INVALID_OPERATION
,
7407 "glDrawArraysInstancedANGLE", "function not available");
7408 return error::kNoError
;
7410 return DoDrawArrays("glDrawArraysIntancedANGLE",
7412 static_cast<GLenum
>(c
.mode
),
7413 static_cast<GLint
>(c
.first
),
7414 static_cast<GLsizei
>(c
.count
),
7415 static_cast<GLsizei
>(c
.primcount
));
7418 error::Error
GLES2DecoderImpl::DoDrawElements(
7419 const char* function_name
,
7425 GLsizei primcount
) {
7426 error::Error error
= WillAccessBoundFramebufferForDraw();
7427 if (error
!= error::kNoError
)
7429 if (!state_
.vertex_attrib_manager
->element_array_buffer()) {
7431 GL_INVALID_OPERATION
, function_name
, "No element array buffer bound");
7432 return error::kNoError
;
7436 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
7437 return error::kNoError
;
7440 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "offset < 0");
7441 return error::kNoError
;
7443 if (!validators_
->draw_mode
.IsValid(mode
)) {
7444 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
7445 return error::kNoError
;
7447 if (!validators_
->index_type
.IsValid(type
)) {
7448 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, type
, "type");
7449 return error::kNoError
;
7451 if (primcount
< 0) {
7452 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
7453 return error::kNoError
;
7456 if (!CheckBoundFramebuffersValid(function_name
)) {
7457 return error::kNoError
;
7460 if (count
== 0 || primcount
== 0) {
7461 return error::kNoError
;
7464 GLuint max_vertex_accessed
;
7465 Buffer
* element_array_buffer
=
7466 state_
.vertex_attrib_manager
->element_array_buffer();
7468 if (!element_array_buffer
->GetMaxValueForRange(
7469 offset
, count
, type
, &max_vertex_accessed
)) {
7471 GL_INVALID_OPERATION
, function_name
, "range out of bounds for buffer");
7472 return error::kNoError
;
7475 if (IsDrawValid(function_name
, max_vertex_accessed
, instanced
, primcount
)) {
7476 if (!ClearUnclearedTextures()) {
7477 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
7478 return error::kNoError
;
7480 bool simulated_attrib_0
= false;
7481 if (!SimulateAttrib0(
7482 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
7483 return error::kNoError
;
7485 bool simulated_fixed_attribs
= false;
7486 if (SimulateFixedAttribs(
7487 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
7489 bool textures_set
= !PrepareTexturesForRender();
7491 // TODO(gman): Refactor to hide these details in BufferManager or
7492 // VertexAttribManager.
7493 const GLvoid
* indices
= reinterpret_cast<const GLvoid
*>(offset
);
7494 bool used_client_side_array
= false;
7495 if (element_array_buffer
->IsClientSideArray()) {
7496 used_client_side_array
= true;
7497 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
7498 indices
= element_array_buffer
->GetRange(offset
, 0);
7501 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
7503 glDrawElements(mode
, count
, type
, indices
);
7505 glDrawElementsInstancedANGLE(mode
, count
, type
, indices
, primcount
);
7508 if (used_client_side_array
) {
7509 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
7510 element_array_buffer
->service_id());
7514 RestoreStateForTextures();
7516 if (simulated_fixed_attribs
) {
7517 RestoreStateForSimulatedFixedAttribs();
7520 if (simulated_attrib_0
) {
7521 // We don't have to restore attrib 0 generic data at the end of this
7522 // function even if it is simulated. This is because we will simulate
7523 // it in each draw call, and attrib 0 generic data queries use cached
7524 // values instead of passing down to the underlying driver.
7525 RestoreStateForAttrib(0, false);
7528 return error::kNoError
;
7531 error::Error
GLES2DecoderImpl::HandleDrawElements(uint32 immediate_data_size
,
7532 const void* cmd_data
) {
7533 // TODO(zmo): crbug.com/481184
7534 // On Desktop GL with versions lower than 4.3, we need to emulate
7535 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7536 const gles2::cmds::DrawElements
& c
=
7537 *static_cast<const gles2::cmds::DrawElements
*>(cmd_data
);
7538 return DoDrawElements("glDrawElements",
7540 static_cast<GLenum
>(c
.mode
),
7541 static_cast<GLsizei
>(c
.count
),
7542 static_cast<GLenum
>(c
.type
),
7543 static_cast<int32
>(c
.index_offset
),
7547 error::Error
GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
7548 uint32 immediate_data_size
,
7549 const void* cmd_data
) {
7550 const gles2::cmds::DrawElementsInstancedANGLE
& c
=
7551 *static_cast<const gles2::cmds::DrawElementsInstancedANGLE
*>(cmd_data
);
7552 if (!features().angle_instanced_arrays
) {
7554 GL_INVALID_OPERATION
,
7555 "glDrawElementsInstancedANGLE", "function not available");
7556 return error::kNoError
;
7558 return DoDrawElements("glDrawElementsInstancedANGLE",
7560 static_cast<GLenum
>(c
.mode
),
7561 static_cast<GLsizei
>(c
.count
),
7562 static_cast<GLenum
>(c
.type
),
7563 static_cast<int32
>(c
.index_offset
),
7564 static_cast<GLsizei
>(c
.primcount
));
7567 GLuint
GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
7568 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
7569 GLuint max_vertex_accessed
= 0;
7570 Buffer
* buffer
= GetBuffer(buffer_id
);
7572 // TODO(gman): Should this be a GL error or a command buffer error?
7574 GL_INVALID_VALUE
, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
7576 if (!buffer
->GetMaxValueForRange(
7577 offset
, count
, type
, &max_vertex_accessed
)) {
7578 // TODO(gman): Should this be a GL error or a command buffer error?
7580 GL_INVALID_OPERATION
,
7581 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
7584 return max_vertex_accessed
;
7587 void GLES2DecoderImpl::DoShaderSource(
7588 GLuint client_id
, GLsizei count
, const char** data
, const GLint
* length
) {
7590 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
7591 if (length
&& length
[ii
] > 0)
7592 str
.append(data
[ii
], length
[ii
]);
7594 str
.append(data
[ii
]);
7596 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glShaderSource");
7600 // Note: We don't actually call glShaderSource here. We wait until
7601 // we actually compile the shader.
7602 shader
->set_source(str
);
7605 void GLES2DecoderImpl::DoTransformFeedbackVaryings(
7606 GLuint client_program_id
, GLsizei count
, const char* const* varyings
,
7607 GLenum buffer_mode
) {
7608 Program
* program
= GetProgramInfoNotShader(
7609 client_program_id
, "glTransformFeedbackVaryings");
7613 program
->TransformFeedbackVaryings(count
, varyings
, buffer_mode
);
7614 glTransformFeedbackVaryings(
7615 program
->service_id(), count
, varyings
, buffer_mode
);
7618 void GLES2DecoderImpl::DoCompileShader(GLuint client_id
) {
7619 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
7620 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glCompileShader");
7625 scoped_refptr
<ShaderTranslatorInterface
> translator
;
7626 if (use_shader_translator_
) {
7627 translator
= shader
->shader_type() == GL_VERTEX_SHADER
?
7628 vertex_translator_
: fragment_translator_
;
7631 const Shader::TranslatedShaderSourceType source_type
=
7632 feature_info_
->feature_flags().angle_translated_shader_source
?
7633 Shader::kANGLE
: Shader::kGL
;
7634 shader
->RequestCompile(translator
, source_type
);
7637 void GLES2DecoderImpl::DoGetShaderiv(
7638 GLuint shader_id
, GLenum pname
, GLint
* params
) {
7639 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderiv");
7644 // Compile now for statuses that require it.
7646 case GL_COMPILE_STATUS
:
7647 case GL_INFO_LOG_LENGTH
:
7648 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE
:
7649 shader
->DoCompile();
7657 case GL_SHADER_SOURCE_LENGTH
:
7658 *params
= shader
->source().size();
7662 case GL_COMPILE_STATUS
:
7663 *params
= compile_shader_always_succeeds_
? true : shader
->valid();
7665 case GL_INFO_LOG_LENGTH
:
7666 *params
= shader
->log_info().size();
7670 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE
:
7671 *params
= shader
->translated_source().size();
7678 glGetShaderiv(shader
->service_id(), pname
, params
);
7681 error::Error
GLES2DecoderImpl::HandleGetShaderSource(uint32 immediate_data_size
,
7682 const void* cmd_data
) {
7683 const gles2::cmds::GetShaderSource
& c
=
7684 *static_cast<const gles2::cmds::GetShaderSource
*>(cmd_data
);
7685 GLuint shader_id
= c
.shader
;
7686 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7687 Bucket
* bucket
= CreateBucket(bucket_id
);
7688 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderSource");
7689 if (!shader
|| shader
->source().empty()) {
7691 return error::kNoError
;
7693 bucket
->SetFromString(shader
->source().c_str());
7694 return error::kNoError
;
7697 error::Error
GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
7698 uint32 immediate_data_size
,
7699 const void* cmd_data
) {
7700 const gles2::cmds::GetTranslatedShaderSourceANGLE
& c
=
7701 *static_cast<const gles2::cmds::GetTranslatedShaderSourceANGLE
*>(
7703 GLuint shader_id
= c
.shader
;
7704 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7705 Bucket
* bucket
= CreateBucket(bucket_id
);
7706 Shader
* shader
= GetShaderInfoNotProgram(
7707 shader_id
, "glGetTranslatedShaderSourceANGLE");
7710 return error::kNoError
;
7713 // Make sure translator has been utilized in compile.
7714 shader
->DoCompile();
7716 bucket
->SetFromString(shader
->translated_source().c_str());
7717 return error::kNoError
;
7720 error::Error
GLES2DecoderImpl::HandleGetProgramInfoLog(
7721 uint32 immediate_data_size
,
7722 const void* cmd_data
) {
7723 const gles2::cmds::GetProgramInfoLog
& c
=
7724 *static_cast<const gles2::cmds::GetProgramInfoLog
*>(cmd_data
);
7725 GLuint program_id
= c
.program
;
7726 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7727 Bucket
* bucket
= CreateBucket(bucket_id
);
7728 Program
* program
= GetProgramInfoNotShader(
7729 program_id
, "glGetProgramInfoLog");
7730 if (!program
|| !program
->log_info()) {
7731 bucket
->SetFromString("");
7732 return error::kNoError
;
7734 bucket
->SetFromString(program
->log_info()->c_str());
7735 return error::kNoError
;
7738 error::Error
GLES2DecoderImpl::HandleGetShaderInfoLog(
7739 uint32 immediate_data_size
,
7740 const void* cmd_data
) {
7741 const gles2::cmds::GetShaderInfoLog
& c
=
7742 *static_cast<const gles2::cmds::GetShaderInfoLog
*>(cmd_data
);
7743 GLuint shader_id
= c
.shader
;
7744 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7745 Bucket
* bucket
= CreateBucket(bucket_id
);
7746 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderInfoLog");
7748 bucket
->SetFromString("");
7749 return error::kNoError
;
7752 // Shader must be compiled in order to get the info log.
7753 shader
->DoCompile();
7755 bucket
->SetFromString(shader
->log_info().c_str());
7756 return error::kNoError
;
7759 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap
) {
7760 return state_
.GetEnabled(cap
);
7763 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id
) {
7764 const Buffer
* buffer
= GetBuffer(client_id
);
7765 return buffer
&& buffer
->IsValid() && !buffer
->IsDeleted();
7768 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id
) {
7769 const Framebuffer
* framebuffer
=
7770 GetFramebuffer(client_id
);
7771 return framebuffer
&& framebuffer
->IsValid() && !framebuffer
->IsDeleted();
7774 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id
) {
7775 // IsProgram is true for programs as soon as they are created, until they are
7776 // deleted and no longer in use.
7777 const Program
* program
= GetProgram(client_id
);
7778 return program
!= NULL
&& !program
->IsDeleted();
7781 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id
) {
7782 const Renderbuffer
* renderbuffer
=
7783 GetRenderbuffer(client_id
);
7784 return renderbuffer
&& renderbuffer
->IsValid() && !renderbuffer
->IsDeleted();
7787 bool GLES2DecoderImpl::DoIsShader(GLuint client_id
) {
7788 // IsShader is true for shaders as soon as they are created, until they
7789 // are deleted and not attached to any programs.
7790 const Shader
* shader
= GetShader(client_id
);
7791 return shader
!= NULL
&& !shader
->IsDeleted();
7794 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id
) {
7795 const TextureRef
* texture_ref
= GetTexture(client_id
);
7796 return texture_ref
&& texture_ref
->texture()->IsValid();
7799 void GLES2DecoderImpl::DoAttachShader(
7800 GLuint program_client_id
, GLint shader_client_id
) {
7801 Program
* program
= GetProgramInfoNotShader(
7802 program_client_id
, "glAttachShader");
7806 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glAttachShader");
7810 if (!program
->AttachShader(shader_manager(), shader
)) {
7812 GL_INVALID_OPERATION
,
7814 "can not attach more than one shader of the same type.");
7817 glAttachShader(program
->service_id(), shader
->service_id());
7820 void GLES2DecoderImpl::DoDetachShader(
7821 GLuint program_client_id
, GLint shader_client_id
) {
7822 Program
* program
= GetProgramInfoNotShader(
7823 program_client_id
, "glDetachShader");
7827 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glDetachShader");
7831 if (!program
->DetachShader(shader_manager(), shader
)) {
7833 GL_INVALID_OPERATION
,
7834 "glDetachShader", "shader not attached to program");
7837 glDetachShader(program
->service_id(), shader
->service_id());
7840 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id
) {
7841 Program
* program
= GetProgramInfoNotShader(
7842 program_client_id
, "glValidateProgram");
7846 program
->Validate();
7849 void GLES2DecoderImpl::GetVertexAttribHelper(
7850 const VertexAttrib
* attrib
, GLenum pname
, GLint
* params
) {
7852 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
:
7854 Buffer
* buffer
= attrib
->buffer();
7855 if (buffer
&& !buffer
->IsDeleted()) {
7857 buffer_manager()->GetClientId(buffer
->service_id(), &client_id
);
7858 *params
= client_id
;
7862 case GL_VERTEX_ATTRIB_ARRAY_ENABLED
:
7863 *params
= attrib
->enabled();
7865 case GL_VERTEX_ATTRIB_ARRAY_SIZE
:
7866 *params
= attrib
->size();
7868 case GL_VERTEX_ATTRIB_ARRAY_STRIDE
:
7869 *params
= attrib
->gl_stride();
7871 case GL_VERTEX_ATTRIB_ARRAY_TYPE
:
7872 *params
= attrib
->type();
7874 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED
:
7875 *params
= attrib
->normalized();
7877 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR
:
7878 *params
= attrib
->divisor();
7880 case GL_VERTEX_ATTRIB_ARRAY_INTEGER
:
7881 *params
= attrib
->integer();
7889 void GLES2DecoderImpl::DoGetTexParameterfv(
7890 GLenum target
, GLenum pname
, GLfloat
* params
) {
7891 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
7892 glGetTexParameterfv(target
, pname
, params
);
7895 void GLES2DecoderImpl::DoGetTexParameteriv(
7896 GLenum target
, GLenum pname
, GLint
* params
) {
7897 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
7898 glGetTexParameteriv(target
, pname
, params
);
7901 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
7902 GLenum target
, GLenum pname
) {
7903 if (!workarounds().init_texture_max_anisotropy
)
7905 if (pname
!= GL_TEXTURE_MAX_ANISOTROPY_EXT
||
7906 !validators_
->texture_parameter
.IsValid(pname
)) {
7910 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
7914 GL_INVALID_OPERATION
,
7915 "glGetTexParamter{fi}v", "unknown texture for target");
7918 Texture
* texture
= texture_ref
->texture();
7919 texture
->InitTextureMaxAnisotropyIfNeeded(target
);
7922 template <typename T
>
7923 void GLES2DecoderImpl::DoGetVertexAttribImpl(
7924 GLuint index
, GLenum pname
, T
* params
) {
7925 VertexAttrib
* attrib
= state_
.vertex_attrib_manager
->GetVertexAttrib(index
);
7928 GL_INVALID_VALUE
, "glGetVertexAttrib", "index out of range");
7932 case GL_CURRENT_VERTEX_ATTRIB
:
7933 state_
.attrib_values
[index
].GetValues(params
);
7937 GetVertexAttribHelper(attrib
, pname
, &value
);
7938 *params
= static_cast<T
>(value
);
7944 void GLES2DecoderImpl::DoGetVertexAttribfv(
7945 GLuint index
, GLenum pname
, GLfloat
* params
) {
7946 DoGetVertexAttribImpl
<GLfloat
>(index
, pname
, params
);
7949 void GLES2DecoderImpl::DoGetVertexAttribiv(
7950 GLuint index
, GLenum pname
, GLint
* params
) {
7951 DoGetVertexAttribImpl
<GLint
>(index
, pname
, params
);
7954 void GLES2DecoderImpl::DoGetVertexAttribIiv(
7955 GLuint index
, GLenum pname
, GLint
* params
) {
7956 DoGetVertexAttribImpl
<GLint
>(index
, pname
, params
);
7959 void GLES2DecoderImpl::DoGetVertexAttribIuiv(
7960 GLuint index
, GLenum pname
, GLuint
* params
) {
7961 DoGetVertexAttribImpl
<GLuint
>(index
, pname
, params
);
7964 template <typename T
>
7965 bool GLES2DecoderImpl::SetVertexAttribValue(
7966 const char* function_name
, GLuint index
, const T
* value
) {
7967 if (index
>= state_
.attrib_values
.size()) {
7968 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "index out of range");
7971 state_
.attrib_values
[index
].SetValues(value
);
7975 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index
, GLfloat v0
) {
7976 GLfloat v
[4] = { v0
, 0.0f
, 0.0f
, 1.0f
, };
7977 if (SetVertexAttribValue("glVertexAttrib1f", index
, v
)) {
7978 glVertexAttrib1f(index
, v0
);
7982 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
) {
7983 GLfloat v
[4] = { v0
, v1
, 0.0f
, 1.0f
, };
7984 if (SetVertexAttribValue("glVertexAttrib2f", index
, v
)) {
7985 glVertexAttrib2f(index
, v0
, v1
);
7989 void GLES2DecoderImpl::DoVertexAttrib3f(
7990 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
) {
7991 GLfloat v
[4] = { v0
, v1
, v2
, 1.0f
, };
7992 if (SetVertexAttribValue("glVertexAttrib3f", index
, v
)) {
7993 glVertexAttrib3f(index
, v0
, v1
, v2
);
7997 void GLES2DecoderImpl::DoVertexAttrib4f(
7998 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
) {
7999 GLfloat v
[4] = { v0
, v1
, v2
, v3
, };
8000 if (SetVertexAttribValue("glVertexAttrib4f", index
, v
)) {
8001 glVertexAttrib4f(index
, v0
, v1
, v2
, v3
);
8005 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index
, const GLfloat
* v
) {
8006 GLfloat t
[4] = { v
[0], 0.0f
, 0.0f
, 1.0f
, };
8007 if (SetVertexAttribValue("glVertexAttrib1fv", index
, t
)) {
8008 glVertexAttrib1fv(index
, v
);
8012 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index
, const GLfloat
* v
) {
8013 GLfloat t
[4] = { v
[0], v
[1], 0.0f
, 1.0f
, };
8014 if (SetVertexAttribValue("glVertexAttrib2fv", index
, t
)) {
8015 glVertexAttrib2fv(index
, v
);
8019 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index
, const GLfloat
* v
) {
8020 GLfloat t
[4] = { v
[0], v
[1], v
[2], 1.0f
, };
8021 if (SetVertexAttribValue("glVertexAttrib3fv", index
, t
)) {
8022 glVertexAttrib3fv(index
, v
);
8026 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index
, const GLfloat
* v
) {
8027 if (SetVertexAttribValue("glVertexAttrib4fv", index
, v
)) {
8028 glVertexAttrib4fv(index
, v
);
8032 void GLES2DecoderImpl::DoVertexAttribI4i(
8033 GLuint index
, GLint v0
, GLint v1
, GLint v2
, GLint v3
) {
8034 GLint v
[4] = { v0
, v1
, v2
, v3
};
8035 if (SetVertexAttribValue("glVertexAttribI4i", index
, v
)) {
8036 glVertexAttribI4i(index
, v0
, v1
, v2
, v3
);
8040 void GLES2DecoderImpl::DoVertexAttribI4iv(GLuint index
, const GLint
* v
) {
8041 if (SetVertexAttribValue("glVertexAttribI4iv", index
, v
)) {
8042 glVertexAttribI4iv(index
, v
);
8046 void GLES2DecoderImpl::DoVertexAttribI4ui(
8047 GLuint index
, GLuint v0
, GLuint v1
, GLuint v2
, GLuint v3
) {
8048 GLuint v
[4] = { v0
, v1
, v2
, v3
};
8049 if (SetVertexAttribValue("glVertexAttribI4ui", index
, v
)) {
8050 glVertexAttribI4ui(index
, v0
, v1
, v2
, v3
);
8054 void GLES2DecoderImpl::DoVertexAttribI4uiv(GLuint index
, const GLuint
* v
) {
8055 if (SetVertexAttribValue("glVertexAttribI4uiv", index
, v
)) {
8056 glVertexAttribI4uiv(index
, v
);
8060 error::Error
GLES2DecoderImpl::HandleVertexAttribIPointer(
8061 uint32 immediate_data_size
,
8062 const void* cmd_data
) {
8063 if (!unsafe_es3_apis_enabled())
8064 return error::kUnknownCommand
;
8065 const gles2::cmds::VertexAttribIPointer
& c
=
8066 *static_cast<const gles2::cmds::VertexAttribIPointer
*>(cmd_data
);
8068 if (!state_
.bound_array_buffer
.get() ||
8069 state_
.bound_array_buffer
->IsDeleted()) {
8070 if (state_
.vertex_attrib_manager
.get() ==
8071 state_
.default_vertex_attrib_manager
.get()) {
8073 GL_INVALID_VALUE
, "glVertexAttribIPointer", "no array buffer bound");
8074 return error::kNoError
;
8075 } else if (c
.offset
!= 0) {
8078 "glVertexAttribIPointer", "client side arrays are not allowed");
8079 return error::kNoError
;
8083 GLuint indx
= c
.indx
;
8084 GLint size
= c
.size
;
8085 GLenum type
= c
.type
;
8086 GLsizei stride
= c
.stride
;
8087 GLsizei offset
= c
.offset
;
8088 const void* ptr
= reinterpret_cast<const void*>(offset
);
8089 if (!validators_
->vertex_attrib_i_type
.IsValid(type
)) {
8090 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribIPointer", type
, "type");
8091 return error::kNoError
;
8093 if (!validators_
->vertex_attrib_size
.IsValid(size
)) {
8095 GL_INVALID_VALUE
, "glVertexAttribIPointer", "size GL_INVALID_VALUE");
8096 return error::kNoError
;
8098 if (indx
>= group_
->max_vertex_attribs()) {
8100 GL_INVALID_VALUE
, "glVertexAttribIPointer", "index out of range");
8101 return error::kNoError
;
8105 GL_INVALID_VALUE
, "glVertexAttribIPointer", "stride < 0");
8106 return error::kNoError
;
8110 GL_INVALID_VALUE
, "glVertexAttribIPointer", "stride > 255");
8111 return error::kNoError
;
8115 GL_INVALID_VALUE
, "glVertexAttribIPointer", "offset < 0");
8116 return error::kNoError
;
8118 GLsizei component_size
=
8119 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type
);
8120 // component_size must be a power of two to use & as optimized modulo.
8121 DCHECK(GLES2Util::IsPOT(component_size
));
8122 if (offset
& (component_size
- 1)) {
8124 GL_INVALID_OPERATION
,
8125 "glVertexAttribIPointer", "offset not valid for type");
8126 return error::kNoError
;
8128 if (stride
& (component_size
- 1)) {
8130 GL_INVALID_OPERATION
,
8131 "glVertexAttribIPointer", "stride not valid for type");
8132 return error::kNoError
;
8134 state_
.vertex_attrib_manager
8135 ->SetAttribInfo(indx
,
8136 state_
.bound_array_buffer
.get(),
8141 stride
!= 0 ? stride
: component_size
* size
,
8144 glVertexAttribIPointer(indx
, size
, type
, stride
, ptr
);
8145 return error::kNoError
;
8148 error::Error
GLES2DecoderImpl::HandleVertexAttribPointer(
8149 uint32 immediate_data_size
,
8150 const void* cmd_data
) {
8151 const gles2::cmds::VertexAttribPointer
& c
=
8152 *static_cast<const gles2::cmds::VertexAttribPointer
*>(cmd_data
);
8154 if (!state_
.bound_array_buffer
.get() ||
8155 state_
.bound_array_buffer
->IsDeleted()) {
8156 if (state_
.vertex_attrib_manager
.get() ==
8157 state_
.default_vertex_attrib_manager
.get()) {
8159 GL_INVALID_VALUE
, "glVertexAttribPointer", "no array buffer bound");
8160 return error::kNoError
;
8161 } else if (c
.offset
!= 0) {
8164 "glVertexAttribPointer", "client side arrays are not allowed");
8165 return error::kNoError
;
8169 GLuint indx
= c
.indx
;
8170 GLint size
= c
.size
;
8171 GLenum type
= c
.type
;
8172 GLboolean normalized
= static_cast<GLboolean
>(c
.normalized
);
8173 GLsizei stride
= c
.stride
;
8174 GLsizei offset
= c
.offset
;
8175 const void* ptr
= reinterpret_cast<const void*>(offset
);
8176 if (!validators_
->vertex_attrib_type
.IsValid(type
)) {
8177 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type
, "type");
8178 return error::kNoError
;
8180 if (!validators_
->vertex_attrib_size
.IsValid(size
)) {
8182 GL_INVALID_VALUE
, "glVertexAttribPointer", "size GL_INVALID_VALUE");
8183 return error::kNoError
;
8185 if (indx
>= group_
->max_vertex_attribs()) {
8187 GL_INVALID_VALUE
, "glVertexAttribPointer", "index out of range");
8188 return error::kNoError
;
8192 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride < 0");
8193 return error::kNoError
;
8197 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride > 255");
8198 return error::kNoError
;
8202 GL_INVALID_VALUE
, "glVertexAttribPointer", "offset < 0");
8203 return error::kNoError
;
8205 GLsizei component_size
=
8206 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type
);
8207 // component_size must be a power of two to use & as optimized modulo.
8208 DCHECK(GLES2Util::IsPOT(component_size
));
8209 if (offset
& (component_size
- 1)) {
8211 GL_INVALID_OPERATION
,
8212 "glVertexAttribPointer", "offset not valid for type");
8213 return error::kNoError
;
8215 if (stride
& (component_size
- 1)) {
8217 GL_INVALID_OPERATION
,
8218 "glVertexAttribPointer", "stride not valid for type");
8219 return error::kNoError
;
8221 state_
.vertex_attrib_manager
8222 ->SetAttribInfo(indx
,
8223 state_
.bound_array_buffer
.get(),
8228 stride
!= 0 ? stride
: component_size
* size
,
8231 // We support GL_FIXED natively on EGL/GLES2 implementations
8232 if (type
!= GL_FIXED
|| feature_info_
->gl_version_info().is_es
) {
8233 glVertexAttribPointer(indx
, size
, type
, normalized
, stride
, ptr
);
8235 return error::kNoError
;
8238 void GLES2DecoderImpl::DoViewport(GLint x
, GLint y
, GLsizei width
,
8240 state_
.viewport_x
= x
;
8241 state_
.viewport_y
= y
;
8242 state_
.viewport_width
= std::min(width
, viewport_max_width_
);
8243 state_
.viewport_height
= std::min(height
, viewport_max_height_
);
8244 glViewport(x
, y
, width
, height
);
8247 error::Error
GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
8248 uint32 immediate_data_size
,
8249 const void* cmd_data
) {
8250 const gles2::cmds::VertexAttribDivisorANGLE
& c
=
8251 *static_cast<const gles2::cmds::VertexAttribDivisorANGLE
*>(cmd_data
);
8252 if (!features().angle_instanced_arrays
) {
8254 GL_INVALID_OPERATION
,
8255 "glVertexAttribDivisorANGLE", "function not available");
8256 return error::kNoError
;
8258 GLuint index
= c
.index
;
8259 GLuint divisor
= c
.divisor
;
8260 if (index
>= group_
->max_vertex_attribs()) {
8263 "glVertexAttribDivisorANGLE", "index out of range");
8264 return error::kNoError
;
8267 state_
.vertex_attrib_manager
->SetDivisor(
8270 glVertexAttribDivisorANGLE(index
, divisor
);
8271 return error::kNoError
;
8274 template <typename pixel_data_type
>
8275 static void WriteAlphaData(
8276 void* pixels
, uint32 row_count
, uint32 channel_count
,
8277 uint32 alpha_channel_index
, uint32 unpadded_row_size
,
8278 uint32 padded_row_size
, pixel_data_type alpha_value
) {
8279 DCHECK_GT(channel_count
, 0U);
8280 DCHECK_EQ(unpadded_row_size
% sizeof(pixel_data_type
), 0U);
8281 uint32 unpadded_row_size_in_elements
=
8282 unpadded_row_size
/ sizeof(pixel_data_type
);
8283 DCHECK_EQ(padded_row_size
% sizeof(pixel_data_type
), 0U);
8284 uint32 padded_row_size_in_elements
=
8285 padded_row_size
/ sizeof(pixel_data_type
);
8286 pixel_data_type
* dst
=
8287 static_cast<pixel_data_type
*>(pixels
) + alpha_channel_index
;
8288 for (uint32 yy
= 0; yy
< row_count
; ++yy
) {
8289 pixel_data_type
* end
= dst
+ unpadded_row_size_in_elements
;
8290 for (pixel_data_type
* d
= dst
; d
< end
; d
+= channel_count
) {
8293 dst
+= padded_row_size_in_elements
;
8297 void GLES2DecoderImpl::FinishReadPixels(
8298 const cmds::ReadPixels
& c
,
8300 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
8301 GLsizei width
= c
.width
;
8302 GLsizei height
= c
.height
;
8303 GLenum format
= c
.format
;
8304 GLenum type
= c
.type
;
8305 typedef cmds::ReadPixels::Result Result
;
8307 Result
* result
= NULL
;
8308 if (c
.result_shm_id
!= 0) {
8309 result
= GetSharedMemoryAs
<Result
*>(
8310 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
8313 glDeleteBuffersARB(1, &buffer
);
8318 GLES2Util::ComputeImageDataSizes(
8319 width
, height
, 1, format
, type
, state_
.pack_alignment
, &pixels_size
,
8321 void* pixels
= GetSharedMemoryAs
<void*>(
8322 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
8325 glDeleteBuffersARB(1, &buffer
);
8331 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
8333 if (features().map_buffer_range
) {
8334 data
= glMapBufferRange(
8335 GL_PIXEL_PACK_BUFFER_ARB
, 0, pixels_size
, GL_MAP_READ_BIT
);
8337 data
= glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB
, GL_READ_ONLY
);
8340 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glMapBuffer",
8341 "Unable to map memory for readback.");
8344 memcpy(pixels
, data
, pixels_size
);
8345 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
8346 // have to restore the state.
8347 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB
);
8348 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
8349 glDeleteBuffersARB(1, &buffer
);
8352 if (result
!= NULL
) {
8356 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
8357 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
8358 if ((channels_exist
& 0x0008) == 0 &&
8359 workarounds().clear_alpha_in_readpixels
) {
8360 // Set the alpha to 255 because some drivers are buggy in this regard.
8363 uint32 unpadded_row_size
;
8364 uint32 padded_row_size
;
8365 if (!GLES2Util::ComputeImageDataSizes(
8366 width
, 2, 1, format
, type
, state_
.pack_alignment
, &temp_size
,
8367 &unpadded_row_size
, &padded_row_size
)) {
8371 uint32 channel_count
= 0;
8372 uint32 alpha_channel
= 0;
8385 if (channel_count
> 0) {
8387 case GL_UNSIGNED_BYTE
:
8388 WriteAlphaData
<uint8
>(
8389 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
8390 padded_row_size
, 0xFF);
8393 WriteAlphaData
<float>(
8394 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
8395 padded_row_size
, 1.0f
);
8398 WriteAlphaData
<uint16
>(
8399 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
8400 padded_row_size
, 0x3C00);
8407 error::Error
GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size
,
8408 const void* cmd_data
) {
8409 const gles2::cmds::ReadPixels
& c
=
8410 *static_cast<const gles2::cmds::ReadPixels
*>(cmd_data
);
8411 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
8412 error::Error fbo_error
= WillAccessBoundFramebufferForRead();
8413 if (fbo_error
!= error::kNoError
)
8417 GLsizei width
= c
.width
;
8418 GLsizei height
= c
.height
;
8419 GLenum format
= c
.format
;
8420 GLenum type
= c
.type
;
8421 GLboolean async
= static_cast<GLboolean
>(c
.async
);
8422 if (width
< 0 || height
< 0) {
8423 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glReadPixels", "dimensions < 0");
8424 return error::kNoError
;
8426 typedef cmds::ReadPixels::Result Result
;
8428 if (!GLES2Util::ComputeImageDataSizes(
8429 width
, height
, 1, format
, type
, state_
.pack_alignment
, &pixels_size
,
8431 return error::kOutOfBounds
;
8433 void* pixels
= GetSharedMemoryAs
<void*>(
8434 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
8436 return error::kOutOfBounds
;
8438 Result
* result
= NULL
;
8439 if (c
.result_shm_id
!= 0) {
8440 result
= GetSharedMemoryAs
<Result
*>(
8441 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
8443 return error::kOutOfBounds
;
8447 if (!validators_
->read_pixel_format
.IsValid(format
)) {
8448 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format
, "format");
8449 return error::kNoError
;
8451 if (!validators_
->read_pixel_type
.IsValid(type
)) {
8452 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type
, "type");
8453 return error::kNoError
;
8455 if ((format
!= GL_RGBA
&& format
!= GL_BGRA_EXT
&& format
!= GL_RGB
&&
8456 format
!= GL_ALPHA
) || type
!= GL_UNSIGNED_BYTE
) {
8457 // format and type are acceptable enums but not guaranteed to be supported
8458 // for this framebuffer. Have to ask gl if they are valid.
8459 GLint preferred_format
= 0;
8460 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT
, &preferred_format
);
8461 GLint preferred_type
= 0;
8462 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE
, &preferred_type
);
8463 if (format
!= static_cast<GLenum
>(preferred_format
) ||
8464 type
!= static_cast<GLenum
>(preferred_type
)) {
8466 GL_INVALID_OPERATION
, "glReadPixels", "format and type incompatible "
8467 "with the current read framebuffer");
8468 return error::kNoError
;
8471 if (width
== 0 || height
== 0) {
8472 return error::kNoError
;
8475 // Get the size of the current fbo or backbuffer.
8476 gfx::Size max_size
= GetBoundReadFrameBufferSize();
8480 if (!SafeAddInt32(x
, width
, &max_x
) || !SafeAddInt32(y
, height
, &max_y
)) {
8482 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
8483 return error::kNoError
;
8486 if (!CheckBoundReadFramebufferColorAttachment("glReadPixels")) {
8487 return error::kNoError
;
8490 if (!CheckBoundFramebuffersValid("glReadPixels")) {
8491 return error::kNoError
;
8494 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
8496 ScopedResolvedFrameBufferBinder
binder(this, false, true);
8498 if (x
< 0 || y
< 0 || max_x
> max_size
.width() || max_y
> max_size
.height()) {
8499 // The user requested an out of range area. Get the results 1 line
8502 uint32 unpadded_row_size
;
8503 uint32 padded_row_size
;
8504 if (!GLES2Util::ComputeImageDataSizes(
8505 width
, 2, 1, format
, type
, state_
.pack_alignment
, &temp_size
,
8506 &unpadded_row_size
, &padded_row_size
)) {
8508 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
8509 return error::kNoError
;
8512 GLint dest_x_offset
= std::max(-x
, 0);
8513 uint32 dest_row_offset
;
8514 if (!GLES2Util::ComputeImageDataSizes(
8515 dest_x_offset
, 1, 1, format
, type
, state_
.pack_alignment
,
8516 &dest_row_offset
, NULL
, NULL
)) {
8518 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
8519 return error::kNoError
;
8522 // Copy each row into the larger dest rect.
8523 int8
* dst
= static_cast<int8
*>(pixels
);
8524 GLint read_x
= std::max(0, x
);
8525 GLint read_end_x
= std::max(0, std::min(max_size
.width(), max_x
));
8526 GLint read_width
= read_end_x
- read_x
;
8527 for (GLint yy
= 0; yy
< height
; ++yy
) {
8531 memset(dst
, 0, unpadded_row_size
);
8533 // If the row is in range, copy it.
8534 if (ry
>= 0 && ry
< max_size
.height() && read_width
> 0) {
8536 read_x
, ry
, read_width
, 1, format
, type
, dst
+ dest_row_offset
);
8538 dst
+= padded_row_size
;
8541 if (async
&& features().use_async_readpixels
) {
8543 glGenBuffersARB(1, &buffer
);
8544 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
8545 // For ANGLE client version 2, GL_STREAM_READ is not available.
8546 const GLenum usage_hint
= feature_info_
->gl_version_info().is_angle
?
8547 GL_STATIC_DRAW
: GL_STREAM_READ
;
8548 glBufferData(GL_PIXEL_PACK_BUFFER_ARB
, pixels_size
, NULL
, usage_hint
);
8549 GLenum error
= glGetError();
8550 if (error
== GL_NO_ERROR
) {
8551 glReadPixels(x
, y
, width
, height
, format
, type
, 0);
8552 pending_readpixel_fences_
.push(linked_ptr
<FenceCallback
>(
8553 new FenceCallback()));
8554 WaitForReadPixels(base::Bind(
8555 &GLES2DecoderImpl::FinishReadPixels
,
8556 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
8557 <GLES2DecoderImpl
>(this),
8559 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
8560 return error::kNoError
;
8562 // On error, unbind pack buffer and fall through to sync readpixels
8563 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
8564 glDeleteBuffersARB(1, &buffer
);
8567 glReadPixels(x
, y
, width
, height
, format
, type
, pixels
);
8569 GLenum error
= LOCAL_PEEK_GL_ERROR("glReadPixels");
8570 if (error
== GL_NO_ERROR
) {
8571 if (result
!= NULL
) {
8574 FinishReadPixels(c
, 0);
8577 return error::kNoError
;
8580 error::Error
GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size
,
8581 const void* cmd_data
) {
8582 const gles2::cmds::PixelStorei
& c
=
8583 *static_cast<const gles2::cmds::PixelStorei
*>(cmd_data
);
8584 GLenum pname
= c
.pname
;
8585 GLenum param
= c
.param
;
8586 if (!validators_
->pixel_store
.IsValid(pname
)) {
8587 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname
, "pname");
8588 return error::kNoError
;
8591 case GL_PACK_ALIGNMENT
:
8592 case GL_UNPACK_ALIGNMENT
:
8593 if (!validators_
->pixel_store_alignment
.IsValid(param
)) {
8595 GL_INVALID_VALUE
, "glPixelStorei", "param GL_INVALID_VALUE");
8596 return error::kNoError
;
8602 glPixelStorei(pname
, param
);
8604 case GL_PACK_ALIGNMENT
:
8605 state_
.pack_alignment
= param
;
8607 case GL_PACK_REVERSE_ROW_ORDER_ANGLE
:
8608 state_
.pack_reverse_row_order
= (param
!= 0);
8610 case GL_UNPACK_ALIGNMENT
:
8611 state_
.unpack_alignment
= param
;
8614 // Validation should have prevented us from getting here.
8618 return error::kNoError
;
8621 error::Error
GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
8622 uint32 immediate_data_size
,
8623 const void* cmd_data
) {
8624 const gles2::cmds::PostSubBufferCHROMIUM
& c
=
8625 *static_cast<const gles2::cmds::PostSubBufferCHROMIUM
*>(cmd_data
);
8626 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
8628 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
8630 if (!supports_post_sub_buffer_
) {
8632 GL_INVALID_OPERATION
,
8633 "glPostSubBufferCHROMIUM", "command not supported by surface");
8634 return error::kNoError
;
8637 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
8640 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
8641 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
8642 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
8643 is_offscreen
? offscreen_size_
: surface_
->GetSize());
8645 if (surface_
->PostSubBuffer(c
.x
, c
.y
, c
.width
, c
.height
) !=
8646 gfx::SwapResult::SWAP_FAILED
) {
8647 return error::kNoError
;
8649 LOG(ERROR
) << "Context lost because PostSubBuffer failed.";
8650 return error::kLostContext
;
8654 error::Error
GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
8655 uint32 immediate_data_size
,
8656 const void* cmd_data
) {
8657 const gles2::cmds::ScheduleOverlayPlaneCHROMIUM
& c
=
8658 *static_cast<const gles2::cmds::ScheduleOverlayPlaneCHROMIUM
*>(cmd_data
);
8659 TextureRef
* ref
= texture_manager()->GetTexture(c
.overlay_texture_id
);
8661 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
8662 "glScheduleOverlayPlaneCHROMIUM",
8664 return error::kNoError
;
8666 gfx::GLImage
* image
=
8667 ref
->texture()->GetLevelImage(ref
->texture()->target(), 0);
8669 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
8670 "glScheduleOverlayPlaneCHROMIUM",
8671 "unsupported texture format");
8672 return error::kNoError
;
8674 gfx::OverlayTransform transform
= GetGFXOverlayTransform(c
.plane_transform
);
8675 if (transform
== gfx::OVERLAY_TRANSFORM_INVALID
) {
8676 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM
,
8677 "glScheduleOverlayPlaneCHROMIUM",
8678 "invalid transform enum");
8679 return error::kNoError
;
8681 if (!surface_
->ScheduleOverlayPlane(
8685 gfx::Rect(c
.bounds_x
, c
.bounds_y
, c
.bounds_width
, c
.bounds_height
),
8686 gfx::RectF(c
.uv_x
, c
.uv_y
, c
.uv_width
, c
.uv_height
))) {
8687 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
8688 "glScheduleOverlayPlaneCHROMIUM",
8689 "failed to schedule overlay");
8691 return error::kNoError
;
8694 error::Error
GLES2DecoderImpl::GetAttribLocationHelper(
8695 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8696 const std::string
& name_str
) {
8697 if (!StringIsValidForGLES(name_str
.c_str())) {
8699 GL_INVALID_VALUE
, "glGetAttribLocation", "Invalid character");
8700 return error::kNoError
;
8702 Program
* program
= GetProgramInfoNotShader(
8703 client_id
, "glGetAttribLocation");
8705 return error::kNoError
;
8707 if (!program
->IsValid()) {
8709 GL_INVALID_OPERATION
, "glGetAttribLocation", "program not linked");
8710 return error::kNoError
;
8712 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8713 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8715 return error::kOutOfBounds
;
8717 // Require the client to init this incase the context is lost and we are no
8718 // longer executing commands.
8719 if (*location
!= -1) {
8720 return error::kGenericError
;
8722 *location
= program
->GetAttribLocation(name_str
);
8723 return error::kNoError
;
8726 error::Error
GLES2DecoderImpl::HandleGetAttribLocation(
8727 uint32 immediate_data_size
,
8728 const void* cmd_data
) {
8729 const gles2::cmds::GetAttribLocation
& c
=
8730 *static_cast<const gles2::cmds::GetAttribLocation
*>(cmd_data
);
8731 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8733 return error::kInvalidArguments
;
8735 std::string name_str
;
8736 if (!bucket
->GetAsString(&name_str
)) {
8737 return error::kInvalidArguments
;
8739 return GetAttribLocationHelper(
8740 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8743 error::Error
GLES2DecoderImpl::GetUniformLocationHelper(
8744 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8745 const std::string
& name_str
) {
8746 if (!StringIsValidForGLES(name_str
.c_str())) {
8748 GL_INVALID_VALUE
, "glGetUniformLocation", "Invalid character");
8749 return error::kNoError
;
8751 Program
* program
= GetProgramInfoNotShader(
8752 client_id
, "glGetUniformLocation");
8754 return error::kNoError
;
8756 if (!program
->IsValid()) {
8758 GL_INVALID_OPERATION
, "glGetUniformLocation", "program not linked");
8759 return error::kNoError
;
8761 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8762 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8764 return error::kOutOfBounds
;
8766 // Require the client to init this incase the context is lost an we are no
8767 // longer executing commands.
8768 if (*location
!= -1) {
8769 return error::kGenericError
;
8771 *location
= program
->GetUniformFakeLocation(name_str
);
8772 return error::kNoError
;
8775 error::Error
GLES2DecoderImpl::HandleGetUniformLocation(
8776 uint32 immediate_data_size
,
8777 const void* cmd_data
) {
8778 const gles2::cmds::GetUniformLocation
& c
=
8779 *static_cast<const gles2::cmds::GetUniformLocation
*>(cmd_data
);
8780 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8782 return error::kInvalidArguments
;
8784 std::string name_str
;
8785 if (!bucket
->GetAsString(&name_str
)) {
8786 return error::kInvalidArguments
;
8788 return GetUniformLocationHelper(
8789 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8792 error::Error
GLES2DecoderImpl::HandleGetUniformIndices(
8793 uint32 immediate_data_size
,
8794 const void* cmd_data
) {
8795 if (!unsafe_es3_apis_enabled())
8796 return error::kUnknownCommand
;
8797 const gles2::cmds::GetUniformIndices
& c
=
8798 *static_cast<const gles2::cmds::GetUniformIndices
*>(cmd_data
);
8799 Bucket
* bucket
= GetBucket(c
.names_bucket_id
);
8801 return error::kInvalidArguments
;
8804 std::vector
<char*> names
;
8805 std::vector
<GLint
> len
;
8806 if (!bucket
->GetAsStrings(&count
, &names
, &len
) || count
<= 0) {
8807 return error::kInvalidArguments
;
8809 typedef cmds::GetUniformIndices::Result Result
;
8810 Result
* result
= GetSharedMemoryAs
<Result
*>(
8811 c
.indices_shm_id
, c
.indices_shm_offset
,
8812 Result::ComputeSize(static_cast<size_t>(count
)));
8813 GLuint
* indices
= result
? result
->GetData() : NULL
;
8814 if (indices
== NULL
) {
8815 return error::kOutOfBounds
;
8817 // Check that the client initialized the result.
8818 if (result
->size
!= 0) {
8819 return error::kInvalidArguments
;
8821 Program
* program
= GetProgramInfoNotShader(c
.program
, "glGetUniformIndices");
8823 return error::kNoError
;
8825 GLuint service_id
= program
->service_id();
8826 GLint link_status
= GL_FALSE
;
8827 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
8828 if (link_status
!= GL_TRUE
) {
8829 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
8830 "glGetUniformIndices", "program not linked");
8831 return error::kNoError
;
8833 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetUniformIndices");
8834 glGetUniformIndices(service_id
, count
, &names
[0], indices
);
8835 GLenum error
= glGetError();
8836 if (error
== GL_NO_ERROR
) {
8837 result
->SetNumResults(count
);
8839 LOCAL_SET_GL_ERROR(error
, "GetUniformIndices", "");
8841 return error::kNoError
;
8844 error::Error
GLES2DecoderImpl::GetFragDataLocationHelper(
8845 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8846 const std::string
& name_str
) {
8847 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8848 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8850 return error::kOutOfBounds
;
8852 // Require the client to init this incase the context is lost and we are no
8853 // longer executing commands.
8854 if (*location
!= -1) {
8855 return error::kGenericError
;
8857 Program
* program
= GetProgramInfoNotShader(
8858 client_id
, "glGetFragDataLocation");
8860 return error::kNoError
;
8862 *location
= glGetFragDataLocation(program
->service_id(), name_str
.c_str());
8863 return error::kNoError
;
8866 error::Error
GLES2DecoderImpl::HandleGetFragDataLocation(
8867 uint32 immediate_data_size
,
8868 const void* cmd_data
) {
8869 if (!unsafe_es3_apis_enabled())
8870 return error::kUnknownCommand
;
8871 const gles2::cmds::GetFragDataLocation
& c
=
8872 *static_cast<const gles2::cmds::GetFragDataLocation
*>(cmd_data
);
8873 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8875 return error::kInvalidArguments
;
8877 std::string name_str
;
8878 if (!bucket
->GetAsString(&name_str
)) {
8879 return error::kInvalidArguments
;
8881 return GetFragDataLocationHelper(
8882 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8885 error::Error
GLES2DecoderImpl::HandleGetUniformBlockIndex(
8886 uint32 immediate_data_size
, const void* cmd_data
) {
8887 if (!unsafe_es3_apis_enabled())
8888 return error::kUnknownCommand
;
8889 const gles2::cmds::GetUniformBlockIndex
& c
=
8890 *static_cast<const gles2::cmds::GetUniformBlockIndex
*>(cmd_data
);
8891 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8893 return error::kInvalidArguments
;
8895 std::string name_str
;
8896 if (!bucket
->GetAsString(&name_str
)) {
8897 return error::kInvalidArguments
;
8899 GLuint
* index
= GetSharedMemoryAs
<GLuint
*>(
8900 c
.index_shm_id
, c
.index_shm_offset
, sizeof(GLuint
));
8902 return error::kOutOfBounds
;
8904 // Require the client to init this in case the context is lost and we are no
8905 // longer executing commands.
8906 if (*index
!= GL_INVALID_INDEX
) {
8907 return error::kGenericError
;
8909 Program
* program
= GetProgramInfoNotShader(
8910 c
.program
, "glGetUniformBlockIndex");
8912 return error::kNoError
;
8914 *index
= glGetUniformBlockIndex(program
->service_id(), name_str
.c_str());
8915 return error::kNoError
;
8918 error::Error
GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size
,
8919 const void* cmd_data
) {
8920 const gles2::cmds::GetString
& c
=
8921 *static_cast<const gles2::cmds::GetString
*>(cmd_data
);
8922 GLenum name
= static_cast<GLenum
>(c
.name
);
8923 if (!validators_
->string_type
.IsValid(name
)) {
8924 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name
, "name");
8925 return error::kNoError
;
8928 const char* str
= nullptr;
8929 std::string extensions
;
8932 if (unsafe_es3_apis_enabled())
8933 str
= "OpenGL ES 3.0 Chromium";
8935 str
= "OpenGL ES 2.0 Chromium";
8937 case GL_SHADING_LANGUAGE_VERSION
:
8938 if (unsafe_es3_apis_enabled())
8939 str
= "OpenGL ES GLSL ES 3.0 Chromium";
8941 str
= "OpenGL ES GLSL ES 1.0 Chromium";
8945 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
8946 // They are used by WEBGL_debug_renderer_info.
8947 if (!IsWebGLContext())
8950 str
= reinterpret_cast<const char*>(glGetString(name
));
8954 // For WebGL contexts, strip out the OES derivatives and
8955 // EXT frag depth extensions if they have not been enabled.
8956 if (IsWebGLContext()) {
8957 extensions
= feature_info_
->extensions();
8958 if (!derivatives_explicitly_enabled_
) {
8959 size_t offset
= extensions
.find(kOESDerivativeExtension
);
8960 if (std::string::npos
!= offset
) {
8961 extensions
.replace(offset
, arraysize(kOESDerivativeExtension
),
8965 if (!frag_depth_explicitly_enabled_
) {
8966 size_t offset
= extensions
.find(kEXTFragDepthExtension
);
8967 if (std::string::npos
!= offset
) {
8968 extensions
.replace(offset
, arraysize(kEXTFragDepthExtension
),
8972 if (!draw_buffers_explicitly_enabled_
) {
8973 size_t offset
= extensions
.find(kEXTDrawBuffersExtension
);
8974 if (std::string::npos
!= offset
) {
8975 extensions
.replace(offset
, arraysize(kEXTDrawBuffersExtension
),
8979 if (!shader_texture_lod_explicitly_enabled_
) {
8980 size_t offset
= extensions
.find(kEXTShaderTextureLodExtension
);
8981 if (std::string::npos
!= offset
) {
8982 extensions
.replace(offset
,
8983 arraysize(kEXTShaderTextureLodExtension
),
8988 extensions
= feature_info_
->extensions().c_str();
8990 if (supports_post_sub_buffer_
)
8991 extensions
+= " GL_CHROMIUM_post_sub_buffer";
8992 str
= extensions
.c_str();
8996 str
= reinterpret_cast<const char*>(glGetString(name
));
8999 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
9000 bucket
->SetFromString(str
);
9001 return error::kNoError
;
9004 error::Error
GLES2DecoderImpl::HandleBufferData(uint32 immediate_data_size
,
9005 const void* cmd_data
) {
9006 const gles2::cmds::BufferData
& c
=
9007 *static_cast<const gles2::cmds::BufferData
*>(cmd_data
);
9008 GLenum target
= static_cast<GLenum
>(c
.target
);
9009 GLsizeiptr size
= static_cast<GLsizeiptr
>(c
.size
);
9010 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
9011 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
9012 GLenum usage
= static_cast<GLenum
>(c
.usage
);
9013 const void* data
= NULL
;
9014 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
9015 data
= GetSharedMemoryAs
<const void*>(data_shm_id
, data_shm_offset
, size
);
9017 return error::kOutOfBounds
;
9020 buffer_manager()->ValidateAndDoBufferData(&state_
, target
, size
, data
, usage
);
9021 return error::kNoError
;
9024 void GLES2DecoderImpl::DoBufferSubData(
9025 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
) {
9026 // Just delegate it. Some validation is actually done before this.
9027 buffer_manager()->ValidateAndDoBufferSubData(
9028 &state_
, target
, offset
, size
, data
);
9031 bool GLES2DecoderImpl::ClearLevel(Texture
* texture
,
9040 uint32 channels
= GLES2Util::GetChannelsForFormat(format
);
9041 if ((feature_info_
->feature_flags().angle_depth_texture
||
9042 feature_info_
->IsES3Enabled())
9043 && (channels
& GLES2Util::kDepth
) != 0) {
9044 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
9045 // on depth formats.
9047 glGenFramebuffersEXT(1, &fb
);
9048 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb
);
9050 bool have_stencil
= (channels
& GLES2Util::kStencil
) != 0;
9051 GLenum attachment
= have_stencil
? GL_DEPTH_STENCIL_ATTACHMENT
:
9052 GL_DEPTH_ATTACHMENT
;
9054 glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT
, attachment
, target
,
9055 texture
->service_id(), level
);
9056 // ANGLE promises a depth only attachment ok.
9057 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT
) !=
9058 GL_FRAMEBUFFER_COMPLETE
) {
9062 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
9063 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
9065 state_
.SetDeviceDepthMask(GL_TRUE
);
9066 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
9067 glScissor(xoffset
, yoffset
, width
, height
);
9068 glClear(GL_DEPTH_BUFFER_BIT
| (have_stencil
? GL_STENCIL_BUFFER_BIT
: 0));
9070 RestoreClearState();
9072 glDeleteFramebuffersEXT(1, &fb
);
9073 Framebuffer
* framebuffer
=
9074 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
9075 GLuint fb_service_id
=
9076 framebuffer
? framebuffer
->service_id() : GetBackbufferServiceId();
9077 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb_service_id
);
9081 static const uint32 kMaxZeroSize
= 1024 * 1024 * 4;
9084 uint32 padded_row_size
;
9085 if (!GLES2Util::ComputeImageDataSizes(
9086 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &size
,
9087 NULL
, &padded_row_size
)) {
9091 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size
);
9095 if (size
> kMaxZeroSize
) {
9096 if (kMaxZeroSize
< padded_row_size
) {
9097 // That'd be an awfully large texture.
9100 // We should never have a large total size with a zero row size.
9101 DCHECK_GT(padded_row_size
, 0U);
9102 tile_height
= kMaxZeroSize
/ padded_row_size
;
9103 if (!GLES2Util::ComputeImageDataSizes(
9104 width
, tile_height
, 1, format
, type
, state_
.unpack_alignment
, &size
,
9109 tile_height
= height
;
9112 // Assumes the size has already been checked.
9113 scoped_ptr
<char[]> zero(new char[size
]);
9114 memset(zero
.get(), 0, size
);
9115 glBindTexture(texture
->target(), texture
->service_id());
9118 while (y
< height
) {
9119 GLint h
= y
+ tile_height
> height
? height
- y
: tile_height
;
9120 glTexSubImage2D(target
, level
, xoffset
, yoffset
+ y
, width
, h
, format
, type
,
9124 TextureRef
* bound_texture
=
9125 texture_manager()->GetTextureInfoForTarget(&state_
, texture
->target());
9126 glBindTexture(texture
->target(),
9127 bound_texture
? bound_texture
->service_id() : 0);
9133 const int kS3TCBlockWidth
= 4;
9134 const int kS3TCBlockHeight
= 4;
9135 const int kS3TCDXT1BlockSize
= 8;
9136 const int kS3TCDXT3AndDXT5BlockSize
= 16;
9137 const int kEACAndETC2BlockSize
= 4;
9139 bool IsValidDXTSize(GLint level
, GLsizei size
) {
9140 return (size
== 1) ||
9141 (size
== 2) || !(size
% kS3TCBlockWidth
);
9144 bool IsValidPVRTCSize(GLint level
, GLsizei size
) {
9145 return GLES2Util::IsPOT(size
);
9148 } // anonymous namespace.
9150 bool GLES2DecoderImpl::GetCompressedTexSizeInBytes(
9151 const char* function_name
, GLsizei width
, GLsizei height
, GLsizei depth
,
9152 GLenum format
, GLsizei
* size_in_bytes
) {
9153 base::CheckedNumeric
<GLsizei
> bytes_required(0);
9156 case GL_ATC_RGB_AMD
:
9157 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
9158 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
9159 case GL_ETC1_RGB8_OES
:
9161 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
9163 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
9164 bytes_required
*= kS3TCDXT1BlockSize
;
9166 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
9167 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
9168 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
9169 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
9171 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
9173 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
9174 bytes_required
*= kS3TCDXT3AndDXT5BlockSize
;
9176 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
9177 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
9178 bytes_required
= std::max(width
, 8);
9179 bytes_required
*= std::max(height
, 8);
9180 bytes_required
*= 4;
9181 bytes_required
+= 7;
9182 bytes_required
/= 8;
9184 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
9185 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
:
9186 bytes_required
= std::max(width
, 16);
9187 bytes_required
*= std::max(height
, 8);
9188 bytes_required
*= 2;
9189 bytes_required
+= 7;
9190 bytes_required
/= 8;
9194 case GL_COMPRESSED_R11_EAC
:
9195 case GL_COMPRESSED_SIGNED_R11_EAC
:
9196 case GL_COMPRESSED_RGB8_ETC2
:
9197 case GL_COMPRESSED_SRGB8_ETC2
:
9198 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9199 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9201 (width
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9203 (height
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9204 bytes_required
*= 8;
9205 bytes_required
*= depth
;
9207 case GL_COMPRESSED_RG11_EAC
:
9208 case GL_COMPRESSED_SIGNED_RG11_EAC
:
9209 case GL_COMPRESSED_RGBA8_ETC2_EAC
:
9210 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
:
9212 (width
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9214 (height
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9215 bytes_required
*= 16;
9216 bytes_required
*= depth
;
9219 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, format
, "format");
9223 if (!bytes_required
.IsValid()) {
9224 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "invalid size");
9228 *size_in_bytes
= bytes_required
.ValueOrDefault(0);
9232 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
9233 const char* function_name
, GLsizei width
, GLsizei height
, GLsizei depth
,
9234 GLenum format
, GLsizei size
) {
9235 GLsizei bytes_required
= 0;
9236 if (!GetCompressedTexSizeInBytes(
9237 function_name
, width
, height
, depth
, format
, &bytes_required
)) {
9241 if (size
!= bytes_required
) {
9243 GL_INVALID_VALUE
, function_name
, "size is not correct for dimensions");
9250 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
9251 const char* function_name
, GLenum target
, GLint level
,
9252 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
) {
9254 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
9255 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
9256 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
9257 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
9258 DCHECK_EQ(1, depth
); // 2D formats.
9259 if (!IsValidDXTSize(level
, width
) || !IsValidDXTSize(level
, height
)) {
9261 GL_INVALID_OPERATION
, function_name
,
9262 "width or height invalid for level");
9266 case GL_ATC_RGB_AMD
:
9267 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
9268 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
9269 case GL_ETC1_RGB8_OES
:
9270 DCHECK_EQ(1, depth
); // 2D formats.
9271 if (width
<= 0 || height
<= 0) {
9273 GL_INVALID_OPERATION
, function_name
,
9274 "width or height invalid for level");
9278 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
9279 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
9280 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
9281 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
:
9282 DCHECK_EQ(1, depth
); // 2D formats.
9283 if (!IsValidPVRTCSize(level
, width
) ||
9284 !IsValidPVRTCSize(level
, height
)) {
9286 GL_INVALID_OPERATION
, function_name
,
9287 "width or height invalid for level");
9293 case GL_COMPRESSED_R11_EAC
:
9294 case GL_COMPRESSED_SIGNED_R11_EAC
:
9295 case GL_COMPRESSED_RG11_EAC
:
9296 case GL_COMPRESSED_SIGNED_RG11_EAC
:
9297 case GL_COMPRESSED_RGB8_ETC2
:
9298 case GL_COMPRESSED_SRGB8_ETC2
:
9299 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9300 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9301 case GL_COMPRESSED_RGBA8_ETC2_EAC
:
9302 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
:
9303 if (width
<= 0 || height
<= 0 || depth
<= 0) {
9305 GL_INVALID_OPERATION
, function_name
,
9306 "width, height, or depth invalid");
9309 if (target
== GL_TEXTURE_3D
) {
9311 GL_INVALID_OPERATION
, function_name
,
9312 "target invalid for format");
9321 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
9322 const char* function_name
,
9323 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
9324 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
,
9326 if (xoffset
< 0 || yoffset
< 0 || zoffset
< 0) {
9328 GL_INVALID_VALUE
, function_name
, "x/y/z offset < 0");
9333 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
9334 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
9335 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
9336 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
: {
9337 const int kBlockWidth
= 4;
9338 const int kBlockHeight
= 4;
9339 if ((xoffset
% kBlockWidth
) || (yoffset
% kBlockHeight
)) {
9341 GL_INVALID_OPERATION
, function_name
,
9342 "xoffset or yoffset not multiple of 4");
9345 GLsizei tex_width
= 0;
9346 GLsizei tex_height
= 0;
9347 if (!texture
->GetLevelSize(target
, level
,
9348 &tex_width
, &tex_height
, nullptr) ||
9349 width
- xoffset
> tex_width
||
9350 height
- yoffset
> tex_height
) {
9352 GL_INVALID_OPERATION
, function_name
, "dimensions out of range");
9355 return ValidateCompressedTexDimensions(
9356 function_name
, target
, level
, width
, height
, 1, format
);
9358 case GL_ATC_RGB_AMD
:
9359 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
9360 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
: {
9362 GL_INVALID_OPERATION
, function_name
,
9363 "not supported for ATC textures");
9366 case GL_ETC1_RGB8_OES
: {
9368 GL_INVALID_OPERATION
, function_name
,
9369 "not supported for ECT1_RGB8_OES textures");
9372 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
9373 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
9374 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
9375 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
: {
9376 if ((xoffset
!= 0) || (yoffset
!= 0)) {
9378 GL_INVALID_OPERATION
, function_name
,
9379 "xoffset and yoffset must be zero");
9382 GLsizei tex_width
= 0;
9383 GLsizei tex_height
= 0;
9384 if (!texture
->GetLevelSize(target
, level
,
9385 &tex_width
, &tex_height
, nullptr) ||
9386 width
!= tex_width
||
9387 height
!= tex_height
) {
9389 GL_INVALID_OPERATION
, function_name
,
9390 "dimensions must match existing texture level dimensions");
9393 return ValidateCompressedTexDimensions(
9394 function_name
, target
, level
, width
, height
, 1, format
);
9398 case GL_COMPRESSED_R11_EAC
:
9399 case GL_COMPRESSED_SIGNED_R11_EAC
:
9400 case GL_COMPRESSED_RG11_EAC
:
9401 case GL_COMPRESSED_SIGNED_RG11_EAC
:
9402 case GL_COMPRESSED_RGB8_ETC2
:
9403 case GL_COMPRESSED_SRGB8_ETC2
:
9404 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9405 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9406 case GL_COMPRESSED_RGBA8_ETC2_EAC
:
9407 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
:
9409 const int kBlockSize
= 4;
9410 GLsizei tex_width
, tex_height
;
9411 if (target
== GL_TEXTURE_3D
||
9412 !texture
->GetLevelSize(target
, level
,
9413 &tex_width
, &tex_height
, nullptr) ||
9414 (xoffset
% kBlockSize
) || (yoffset
% kBlockSize
) ||
9415 ((width
% kBlockSize
) && xoffset
+ width
!= tex_width
) ||
9416 ((height
% kBlockSize
) && yoffset
+ height
!= tex_height
)) {
9418 GL_INVALID_OPERATION
, function_name
,
9419 "dimensions must match existing texture level dimensions");
9429 error::Error
GLES2DecoderImpl::DoCompressedTexImage2D(
9432 GLenum internal_format
,
9438 if (!validators_
->texture_target
.IsValid(target
)) {
9439 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9440 "glCompressedTexImage2D", target
, "target");
9441 return error::kNoError
;
9443 if (!validators_
->compressed_texture_format
.IsValid(
9445 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9446 "glCompressedTexImage2D", internal_format
, "internal_format");
9447 return error::kNoError
;
9449 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
9453 "glCompressedTexImage2D", "dimensions out of range");
9454 return error::kNoError
;
9456 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9461 "glCompressedTexImage2D", "unknown texture target");
9462 return error::kNoError
;
9464 Texture
* texture
= texture_ref
->texture();
9465 if (texture
->IsImmutable()) {
9467 GL_INVALID_OPERATION
,
9468 "glCompressedTexImage2D", "texture is immutable");
9469 return error::kNoError
;
9472 if (!ValidateCompressedTexDimensions("glCompressedTexImage2D", target
, level
,
9473 width
, height
, 1, internal_format
) ||
9474 !ValidateCompressedTexFuncData("glCompressedTexImage2D", width
, height
,
9475 1, internal_format
, image_size
)) {
9476 return error::kNoError
;
9479 if (!EnsureGPUMemoryAvailable(image_size
)) {
9481 GL_OUT_OF_MEMORY
, "glCompressedTexImage2D", "out of memory");
9482 return error::kNoError
;
9485 if (texture
->IsAttachedToFramebuffer()) {
9486 framebuffer_state_
.clear_state_dirty
= true;
9489 scoped_ptr
<int8
[]> zero
;
9491 zero
.reset(new int8
[image_size
]);
9492 memset(zero
.get(), 0, image_size
);
9495 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
9496 glCompressedTexImage2D(
9497 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
9498 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
9499 if (error
== GL_NO_ERROR
) {
9500 texture_manager()->SetLevelInfo(texture_ref
, target
, level
, internal_format
,
9501 width
, height
, 1, border
, 0, 0,
9502 gfx::Rect(width
, height
));
9505 // This may be a slow command. Exit command processing to allow for
9506 // context preemption and GPU watchdog checks.
9507 ExitCommandProcessingEarly();
9508 return error::kNoError
;
9511 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2D(
9512 uint32 immediate_data_size
,
9513 const void* cmd_data
) {
9514 const gles2::cmds::CompressedTexImage2D
& c
=
9515 *static_cast<const gles2::cmds::CompressedTexImage2D
*>(cmd_data
);
9516 GLenum target
= static_cast<GLenum
>(c
.target
);
9517 GLint level
= static_cast<GLint
>(c
.level
);
9518 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9519 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9520 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9521 GLint border
= static_cast<GLint
>(c
.border
);
9522 GLsizei image_size
= static_cast<GLsizei
>(c
.imageSize
);
9523 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
9524 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
9525 const void* data
= NULL
;
9526 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
9527 data
= GetSharedMemoryAs
<const void*>(
9528 data_shm_id
, data_shm_offset
, image_size
);
9530 return error::kOutOfBounds
;
9533 return DoCompressedTexImage2D(
9534 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
9537 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
9538 uint32 immediate_data_size
,
9539 const void* cmd_data
) {
9540 const gles2::cmds::CompressedTexImage2DBucket
& c
=
9541 *static_cast<const gles2::cmds::CompressedTexImage2DBucket
*>(cmd_data
);
9542 GLenum target
= static_cast<GLenum
>(c
.target
);
9543 GLint level
= static_cast<GLint
>(c
.level
);
9544 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9545 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9546 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9547 GLint border
= static_cast<GLint
>(c
.border
);
9548 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9550 return error::kInvalidArguments
;
9552 uint32 data_size
= bucket
->size();
9553 GLsizei imageSize
= data_size
;
9554 const void* data
= bucket
->GetData(0, data_size
);
9556 return error::kInvalidArguments
;
9558 return DoCompressedTexImage2D(
9559 target
, level
, internal_format
, width
, height
, border
,
9563 error::Error
GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
9564 uint32 immediate_data_size
,
9565 const void* cmd_data
) {
9566 const gles2::cmds::CompressedTexSubImage2DBucket
& c
=
9567 *static_cast<const gles2::cmds::CompressedTexSubImage2DBucket
*>(cmd_data
);
9568 GLenum target
= static_cast<GLenum
>(c
.target
);
9569 GLint level
= static_cast<GLint
>(c
.level
);
9570 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
9571 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
9572 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9573 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9574 GLenum format
= static_cast<GLenum
>(c
.format
);
9575 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9577 return error::kInvalidArguments
;
9579 uint32 data_size
= bucket
->size();
9580 GLsizei imageSize
= data_size
;
9581 const void* data
= bucket
->GetData(0, data_size
);
9583 return error::kInvalidArguments
;
9585 if (!validators_
->texture_target
.IsValid(target
)) {
9587 GL_INVALID_ENUM
, "glCompressedTexSubImage2D", "target");
9588 return error::kNoError
;
9590 if (!validators_
->compressed_texture_format
.IsValid(format
)) {
9591 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9592 "glCompressedTexSubImage2D", format
, "format");
9593 return error::kNoError
;
9597 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "width < 0");
9598 return error::kNoError
;
9602 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "height < 0");
9603 return error::kNoError
;
9605 if (imageSize
< 0) {
9607 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "imageSize < 0");
9608 return error::kNoError
;
9610 DoCompressedTexSubImage2D(
9611 target
, level
, xoffset
, yoffset
, width
, height
, format
, imageSize
, data
);
9612 return error::kNoError
;
9615 error::Error
GLES2DecoderImpl::DoCompressedTexImage3D(
9618 GLenum internal_format
,
9625 if (!validators_
->texture_3_d_target
.IsValid(target
)) {
9626 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9627 "glCompressedTexImage3D", target
, "target");
9628 return error::kNoError
;
9630 if (!validators_
->compressed_texture_format
.IsValid(
9632 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9633 "glCompressedTexImage3D", internal_format
, "internal_format");
9634 return error::kNoError
;
9636 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, depth
) ||
9640 "glCompressedTexImage3D", "dimensions out of range");
9641 return error::kNoError
;
9643 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9648 "glCompressedTexImage3D", "unknown texture target");
9649 return error::kNoError
;
9651 Texture
* texture
= texture_ref
->texture();
9652 if (texture
->IsImmutable()) {
9654 GL_INVALID_OPERATION
,
9655 "glCompressedTexImage3D", "texture is immutable");
9656 return error::kNoError
;
9659 if (!ValidateCompressedTexDimensions("glCompressedTexImage3D", target
, level
,
9660 width
, height
, depth
, internal_format
) ||
9661 !ValidateCompressedTexFuncData("glCompressedTexImage3D", width
, height
,
9662 depth
, internal_format
, image_size
)) {
9663 return error::kNoError
;
9666 if (!EnsureGPUMemoryAvailable(image_size
)) {
9668 GL_OUT_OF_MEMORY
, "glCompressedTexImage3D", "out of memory");
9669 return error::kNoError
;
9672 if (texture
->IsAttachedToFramebuffer()) {
9673 framebuffer_state_
.clear_state_dirty
= true;
9676 scoped_ptr
<int8
[]> zero
;
9678 zero
.reset(new int8
[image_size
]);
9679 memset(zero
.get(), 0, image_size
);
9682 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage3D");
9683 glCompressedTexImage3D(target
, level
, internal_format
, width
, height
, depth
,
9684 border
, image_size
, data
);
9685 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedTexImage3D");
9686 if (error
== GL_NO_ERROR
) {
9687 texture_manager()->SetLevelInfo(texture_ref
, target
, level
, internal_format
,
9688 width
, height
, depth
, border
, 0, 0,
9689 gfx::Rect(width
, height
));
9692 // This may be a slow command. Exit command processing to allow for
9693 // context preemption and GPU watchdog checks.
9694 ExitCommandProcessingEarly();
9695 return error::kNoError
;
9698 error::Error
GLES2DecoderImpl::HandleCompressedTexImage3D(
9699 uint32 immediate_data_size
, const void* cmd_data
) {
9700 if (!unsafe_es3_apis_enabled())
9701 return error::kUnknownCommand
;
9703 const gles2::cmds::CompressedTexImage3D
& c
=
9704 *static_cast<const gles2::cmds::CompressedTexImage3D
*>(cmd_data
);
9705 GLenum target
= static_cast<GLenum
>(c
.target
);
9706 GLint level
= static_cast<GLint
>(c
.level
);
9707 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9708 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9709 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9710 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9711 GLint border
= static_cast<GLint
>(c
.border
);
9712 GLsizei image_size
= static_cast<GLsizei
>(c
.imageSize
);
9713 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
9714 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
9715 const void* data
= NULL
;
9716 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
9717 data
= GetSharedMemoryAs
<const void*>(
9718 data_shm_id
, data_shm_offset
, image_size
);
9720 return error::kOutOfBounds
;
9723 return DoCompressedTexImage3D(target
, level
, internal_format
, width
, height
,
9724 depth
, border
, image_size
, data
);
9727 error::Error
GLES2DecoderImpl::HandleCompressedTexImage3DBucket(
9728 uint32 immediate_data_size
, const void* cmd_data
) {
9729 if (!unsafe_es3_apis_enabled())
9730 return error::kUnknownCommand
;
9732 const gles2::cmds::CompressedTexImage3DBucket
& c
=
9733 *static_cast<const gles2::cmds::CompressedTexImage3DBucket
*>(cmd_data
);
9734 GLenum target
= static_cast<GLenum
>(c
.target
);
9735 GLint level
= static_cast<GLint
>(c
.level
);
9736 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9737 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9738 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9739 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9740 GLint border
= static_cast<GLint
>(c
.border
);
9741 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9743 return error::kInvalidArguments
;
9745 uint32 data_size
= bucket
->size();
9746 GLsizei imageSize
= data_size
;
9747 const void* data
= bucket
->GetData(0, data_size
);
9749 return error::kInvalidArguments
;
9751 return DoCompressedTexImage3D(target
, level
, internal_format
, width
, height
,
9752 depth
, border
, imageSize
, data
);
9755 void GLES2DecoderImpl::DoCompressedTexSubImage3D(
9756 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
9757 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
,
9758 GLsizei image_size
, const void* data
) {
9759 if (!validators_
->texture_3_d_target
.IsValid(target
)) {
9761 GL_INVALID_ENUM
, "glCompressedTexSubImage3D", "target");
9764 if (!validators_
->compressed_texture_format
.IsValid(format
)) {
9765 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9766 "glCompressedTexSubImage3D", format
, "format");
9769 if (width
< 0 || height
< 0 || depth
< 0) {
9771 GL_INVALID_VALUE
, "glCompressedTexSubImage3D", "size < 0");
9774 if (image_size
< 0) {
9776 GL_INVALID_VALUE
, "glCompressedTexSubImage3D", "imageSize < 0");
9779 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9782 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCompressedTexSubImage3D",
9783 "unknown texture for target");
9786 Texture
* texture
= texture_ref
->texture();
9787 GLenum type
= 0, internal_format
= 0;
9788 if (!texture
->GetLevelType(target
, level
, &type
, &internal_format
)) {
9789 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCompressedTexSubImage3D",
9790 "level does not exist");
9793 if (internal_format
!= format
) {
9794 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCompressedTexSubImage3D",
9795 "format does not match internal format");
9798 if (!texture
->ValidForTexture(target
, level
, xoffset
, yoffset
, zoffset
,
9799 width
, height
, depth
, type
)) {
9800 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCompressedTexSubImage3D",
9804 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage3D",
9805 width
, height
, depth
, format
,
9807 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage3D",
9808 target
, level
, xoffset
, yoffset
,
9809 zoffset
, width
, height
, depth
,
9814 // Note: There is no need to deal with texture cleared tracking here
9815 // because the validation above means you can only get here if the level
9816 // is already a matching compressed format and in that case
9817 // CompressedTexImage3D already cleared the texture.
9818 glCompressedTexSubImage3D(
9819 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
, format
,
9822 // This may be a slow command. Exit command processing to allow for
9823 // context preemption and GPU watchdog checks.
9824 ExitCommandProcessingEarly();
9827 error::Error
GLES2DecoderImpl::HandleCompressedTexSubImage3DBucket(
9828 uint32 immediate_data_size
, const void* cmd_data
) {
9829 if (!unsafe_es3_apis_enabled())
9830 return error::kUnknownCommand
;
9831 const gles2::cmds::CompressedTexSubImage3DBucket
& c
=
9832 *static_cast<const gles2::cmds::CompressedTexSubImage3DBucket
*>(cmd_data
);
9833 GLenum target
= static_cast<GLenum
>(c
.target
);
9834 GLint level
= static_cast<GLint
>(c
.level
);
9835 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
9836 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
9837 GLint zoffset
= static_cast<GLint
>(c
.zoffset
);
9838 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9839 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9840 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9841 GLenum format
= static_cast<GLenum
>(c
.format
);
9842 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9844 return error::kInvalidArguments
;
9846 uint32 data_size
= bucket
->size();
9847 GLsizei image_size
= data_size
;
9848 const void* data
= bucket
->GetData(0, data_size
);
9850 return error::kInvalidArguments
;
9852 DoCompressedTexSubImage3D(
9853 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
, format
,
9855 return error::kNoError
;
9858 error::Error
GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size
,
9859 const void* cmd_data
) {
9860 const gles2::cmds::TexImage2D
& c
=
9861 *static_cast<const gles2::cmds::TexImage2D
*>(cmd_data
);
9862 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
9863 "width", c
.width
, "height", c
.height
);
9864 // Set as failed for now, but if it successed, this will be set to not failed.
9865 texture_state_
.tex_image_failed
= true;
9866 GLenum target
= static_cast<GLenum
>(c
.target
);
9867 GLint level
= static_cast<GLint
>(c
.level
);
9868 // TODO(kloveless): Change TexImage2D command to use unsigned integer
9869 // for internalformat.
9870 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9871 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9872 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9873 GLint border
= static_cast<GLint
>(c
.border
);
9874 GLenum format
= static_cast<GLenum
>(c
.format
);
9875 GLenum type
= static_cast<GLenum
>(c
.type
);
9876 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
9877 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
9879 if (!GLES2Util::ComputeImageDataSizes(
9880 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
9882 return error::kOutOfBounds
;
9884 const void* pixels
= NULL
;
9885 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
9886 pixels
= GetSharedMemoryAs
<const void*>(
9887 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
9889 return error::kOutOfBounds
;
9893 // For testing only. Allows us to stress the ability to respond to OOM errors.
9894 if (workarounds().simulate_out_of_memory_on_large_textures
&&
9895 (width
* height
>= 4096 * 4096)) {
9898 "glTexImage2D", "synthetic out of memory");
9899 return error::kNoError
;
9902 TextureManager::DoTexImageArguments args
= {
9903 target
, level
, internal_format
, width
, height
, 1, border
, format
, type
,
9904 pixels
, pixels_size
, TextureManager::DoTexImageArguments::kTexImage2D
};
9905 texture_manager()->ValidateAndDoTexImage(
9906 &texture_state_
, &state_
, &framebuffer_state_
, "glTexImage2D", args
);
9908 // This may be a slow command. Exit command processing to allow for
9909 // context preemption and GPU watchdog checks.
9910 ExitCommandProcessingEarly();
9911 return error::kNoError
;
9914 error::Error
GLES2DecoderImpl::HandleTexImage3D(uint32 immediate_data_size
,
9915 const void* cmd_data
) {
9916 if (!unsafe_es3_apis_enabled())
9917 return error::kUnknownCommand
;
9919 const gles2::cmds::TexImage3D
& c
=
9920 *static_cast<const gles2::cmds::TexImage3D
*>(cmd_data
);
9921 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage3D",
9922 "widthXheight", c
.width
* c
.height
, "depth", c
.depth
);
9923 // Set as failed for now, but if it successed, this will be set to not failed.
9924 texture_state_
.tex_image_failed
= true;
9925 GLenum target
= static_cast<GLenum
>(c
.target
);
9926 GLint level
= static_cast<GLint
>(c
.level
);
9927 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9928 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9929 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9930 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9931 GLint border
= static_cast<GLint
>(c
.border
);
9932 GLenum format
= static_cast<GLenum
>(c
.format
);
9933 GLenum type
= static_cast<GLenum
>(c
.type
);
9934 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
9935 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
9937 if (!GLES2Util::ComputeImageDataSizes(
9938 width
, height
, depth
, format
, type
, state_
.unpack_alignment
, &pixels_size
,
9940 return error::kOutOfBounds
;
9942 const void* pixels
= NULL
;
9943 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
9944 pixels
= GetSharedMemoryAs
<const void*>(
9945 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
9947 return error::kOutOfBounds
;
9951 // For testing only. Allows us to stress the ability to respond to OOM errors.
9952 if (workarounds().simulate_out_of_memory_on_large_textures
&&
9953 (width
* height
* depth
>= 4096 * 4096)) {
9956 "glTexImage3D", "synthetic out of memory");
9957 return error::kNoError
;
9960 TextureManager::DoTexImageArguments args
= {
9961 target
, level
, internal_format
, width
, height
, depth
, border
, format
, type
,
9962 pixels
, pixels_size
, TextureManager::DoTexImageArguments::kTexImage3D
};
9963 texture_manager()->ValidateAndDoTexImage(
9964 &texture_state_
, &state_
, &framebuffer_state_
, "glTexImage3D", args
);
9966 // This may be a slow command. Exit command processing to allow for
9967 // context preemption and GPU watchdog checks.
9968 ExitCommandProcessingEarly();
9969 return error::kNoError
;
9972 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
9981 const void * data
) {
9982 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9986 GL_INVALID_OPERATION
,
9987 "glCompressedTexSubImage2D", "unknown texture for target");
9990 Texture
* texture
= texture_ref
->texture();
9992 GLenum internal_format
= 0;
9993 if (!texture
->GetLevelType(target
, level
, &type
, &internal_format
)) {
9995 GL_INVALID_OPERATION
,
9996 "glCompressedTexSubImage2D", "level does not exist.");
9999 if (internal_format
!= format
) {
10000 LOCAL_SET_GL_ERROR(
10001 GL_INVALID_OPERATION
,
10002 "glCompressedTexSubImage2D", "format does not match internal format.");
10005 if (!texture
->ValidForTexture(target
, level
, xoffset
, yoffset
, 0, width
,
10006 height
, 1, type
)) {
10007 LOCAL_SET_GL_ERROR(
10008 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "bad dimensions.");
10012 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage2D",
10013 width
, height
, 1, format
, image_size
) ||
10014 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage2D",
10015 target
, level
, xoffset
, yoffset
, 0,
10016 width
, height
, 1, format
, texture
)) {
10021 // Note: There is no need to deal with texture cleared tracking here
10022 // because the validation above means you can only get here if the level
10023 // is already a matching compressed format and in that case
10024 // CompressedTexImage2D already cleared the texture.
10025 glCompressedTexSubImage2D(
10026 target
, level
, xoffset
, yoffset
, width
, height
, format
, image_size
, data
);
10028 // This may be a slow command. Exit command processing to allow for
10029 // context preemption and GPU watchdog checks.
10030 ExitCommandProcessingEarly();
10034 GLint start
, GLint range
, GLint sourceRange
,
10035 GLint
* out_start
, GLint
* out_range
) {
10042 GLint end
= start
+ range
;
10043 if (end
> sourceRange
) {
10044 range
-= end
- sourceRange
;
10046 *out_start
= start
;
10047 *out_range
= range
;
10050 void GLES2DecoderImpl::DoCopyTexImage2D(
10053 GLenum internal_format
,
10059 DCHECK(!ShouldDeferReads());
10060 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10062 if (!texture_ref
) {
10063 LOCAL_SET_GL_ERROR(
10064 GL_INVALID_OPERATION
,
10065 "glCopyTexImage2D", "unknown texture for target");
10068 Texture
* texture
= texture_ref
->texture();
10069 if (texture
->IsImmutable()) {
10070 LOCAL_SET_GL_ERROR(
10071 GL_INVALID_OPERATION
, "glCopyTexImage2D", "texture is immutable");
10074 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
10076 LOCAL_SET_GL_ERROR(
10077 GL_INVALID_VALUE
, "glCopyTexImage2D", "dimensions out of range");
10080 if (!texture_manager()->ValidateFormatAndTypeCombination(
10081 state_
.GetErrorState(), "glCopyTexImage2D", internal_format
,
10082 GL_UNSIGNED_BYTE
)) {
10086 // Check we have compatible formats.
10087 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
10088 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
10089 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(internal_format
);
10091 if ((channels_needed
& channels_exist
) != channels_needed
) {
10092 LOCAL_SET_GL_ERROR(
10093 GL_INVALID_OPERATION
, "glCopyTexImage2D", "incompatible format");
10097 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
10098 LOCAL_SET_GL_ERROR(
10099 GL_INVALID_OPERATION
,
10100 "glCopyTexImage2D", "can not be used with depth or stencil textures");
10104 uint32 estimated_size
= 0;
10105 if (!GLES2Util::ComputeImageDataSizes(
10106 width
, height
, 1, internal_format
, GL_UNSIGNED_BYTE
,
10107 state_
.unpack_alignment
, &estimated_size
, NULL
, NULL
)) {
10108 LOCAL_SET_GL_ERROR(
10109 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too large");
10113 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
10114 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "out of memory");
10118 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexImage2D")) {
10122 if (FormsTextureCopyingFeedbackLoop(texture_ref
, level
)) {
10123 LOCAL_SET_GL_ERROR(
10124 GL_INVALID_OPERATION
,
10125 "glCopyTexImage2D", "source and destination textures are the same");
10129 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
10133 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
10134 ScopedResolvedFrameBufferBinder
binder(this, false, true);
10135 gfx::Size size
= GetBoundReadFrameBufferSize();
10137 if (texture
->IsAttachedToFramebuffer()) {
10138 framebuffer_state_
.clear_state_dirty
= true;
10141 // Clip to size to source dimensions
10144 GLint copyWidth
= 0;
10145 GLint copyHeight
= 0;
10146 Clip(x
, width
, size
.width(), ©X
, ©Width
);
10147 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
10151 copyWidth
!= width
||
10152 copyHeight
!= height
) {
10153 // some part was clipped so clear the rect.
10154 uint32 pixels_size
= 0;
10155 if (!GLES2Util::ComputeImageDataSizes(
10156 width
, height
, 1, internal_format
, GL_UNSIGNED_BYTE
,
10157 state_
.unpack_alignment
, &pixels_size
, NULL
, NULL
)) {
10158 LOCAL_SET_GL_ERROR(
10159 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too big");
10162 scoped_ptr
<char[]> zero(new char[pixels_size
]);
10163 memset(zero
.get(), 0, pixels_size
);
10164 ScopedModifyPixels
modify(texture_ref
);
10165 glTexImage2D(target
, level
, internal_format
, width
, height
, border
,
10166 internal_format
, GL_UNSIGNED_BYTE
, zero
.get());
10167 if (copyHeight
> 0 && copyWidth
> 0) {
10168 GLint dx
= copyX
- x
;
10169 GLint dy
= copyY
- y
;
10172 glCopyTexSubImage2D(target
, level
,
10173 destX
, destY
, copyX
, copyY
,
10174 copyWidth
, copyHeight
);
10177 ScopedModifyPixels
modify(texture_ref
);
10178 glCopyTexImage2D(target
, level
, internal_format
,
10179 copyX
, copyY
, copyWidth
, copyHeight
, border
);
10181 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
10182 if (error
== GL_NO_ERROR
) {
10183 texture_manager()->SetLevelInfo(texture_ref
, target
, level
, internal_format
,
10184 width
, height
, 1, border
, internal_format
,
10185 GL_UNSIGNED_BYTE
, gfx::Rect(width
, height
));
10188 // This may be a slow command. Exit command processing to allow for
10189 // context preemption and GPU watchdog checks.
10190 ExitCommandProcessingEarly();
10193 void GLES2DecoderImpl::DoCopyTexSubImage2D(
10202 DCHECK(!ShouldDeferReads());
10203 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10205 if (!texture_ref
) {
10206 LOCAL_SET_GL_ERROR(
10207 GL_INVALID_OPERATION
,
10208 "glCopyTexSubImage2D", "unknown texture for target");
10211 Texture
* texture
= texture_ref
->texture();
10214 if (!texture
->GetLevelType(target
, level
, &type
, &format
) ||
10215 !texture
->ValidForTexture(
10216 target
, level
, xoffset
, yoffset
, 0, width
, height
, 1, type
)) {
10217 LOCAL_SET_GL_ERROR(
10218 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "bad dimensions.");
10221 if (async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
10222 LOCAL_SET_GL_ERROR(
10223 GL_INVALID_OPERATION
,
10224 "glCopyTexSubImage2D", "async upload pending for texture");
10228 // Check we have compatible formats.
10229 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
10230 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
10231 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(format
);
10233 if (!channels_needed
||
10234 (channels_needed
& channels_exist
) != channels_needed
) {
10235 LOCAL_SET_GL_ERROR(
10236 GL_INVALID_OPERATION
, "glCopyTexSubImage2D", "incompatible format");
10240 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
10241 LOCAL_SET_GL_ERROR(
10242 GL_INVALID_OPERATION
,
10243 "glCopySubImage2D", "can not be used with depth or stencil textures");
10247 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexSubImage2D")) {
10251 if (FormsTextureCopyingFeedbackLoop(texture_ref
, level
)) {
10252 LOCAL_SET_GL_ERROR(
10253 GL_INVALID_OPERATION
,
10254 "glCopyTexSubImage2D", "source and destination textures are the same");
10258 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
10262 ScopedResolvedFrameBufferBinder
binder(this, false, true);
10263 gfx::Size size
= GetBoundReadFrameBufferSize();
10266 GLint copyWidth
= 0;
10267 GLint copyHeight
= 0;
10268 Clip(x
, width
, size
.width(), ©X
, ©Width
);
10269 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
10271 if (xoffset
!= 0 || yoffset
!= 0 || width
!= size
.width() ||
10272 height
!= size
.height()) {
10273 gfx::Rect cleared_rect
;
10274 if (CombineAdjacentRects(texture
->GetLevelClearedRect(target
, level
),
10275 gfx::Rect(xoffset
, yoffset
, width
, height
),
10277 DCHECK_GE(cleared_rect
.size().GetArea(),
10278 texture
->GetLevelClearedRect(target
, level
).size().GetArea());
10279 texture_manager()->SetLevelClearedRect(texture_ref
, target
, level
,
10282 // Otherwise clear part of texture level that is not already cleared.
10283 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
,
10285 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D",
10286 "dimensions too big");
10291 // Write all pixels in below.
10292 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
10297 copyWidth
!= width
||
10298 copyHeight
!= height
) {
10299 // some part was clipped so clear the sub rect.
10300 uint32 pixels_size
= 0;
10301 if (!GLES2Util::ComputeImageDataSizes(
10302 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
10304 LOCAL_SET_GL_ERROR(
10305 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "dimensions too large");
10308 scoped_ptr
<char[]> zero(new char[pixels_size
]);
10309 memset(zero
.get(), 0, pixels_size
);
10310 ScopedModifyPixels
modify(texture_ref
);
10312 target
, level
, xoffset
, yoffset
, width
, height
,
10313 format
, type
, zero
.get());
10316 if (copyHeight
> 0 && copyWidth
> 0) {
10317 GLint dx
= copyX
- x
;
10318 GLint dy
= copyY
- y
;
10319 GLint destX
= xoffset
+ dx
;
10320 GLint destY
= yoffset
+ dy
;
10321 ScopedModifyPixels
modify(texture_ref
);
10322 glCopyTexSubImage2D(target
, level
,
10323 destX
, destY
, copyX
, copyY
,
10324 copyWidth
, copyHeight
);
10327 // This may be a slow command. Exit command processing to allow for
10328 // context preemption and GPU watchdog checks.
10329 ExitCommandProcessingEarly();
10332 bool GLES2DecoderImpl::ValidateTexSubImage2D(
10333 error::Error
* error
,
10334 const char* function_name
,
10343 const void * data
) {
10344 (*error
) = error::kNoError
;
10345 if (!validators_
->texture_target
.IsValid(target
)) {
10346 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
10350 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "width < 0");
10354 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "height < 0");
10357 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10359 if (!texture_ref
) {
10360 LOCAL_SET_GL_ERROR(
10361 GL_INVALID_OPERATION
,
10362 function_name
, "unknown texture for target");
10365 Texture
* texture
= texture_ref
->texture();
10366 GLenum current_type
= 0;
10367 GLenum internal_format
= 0;
10368 if (!texture
->GetLevelType(target
, level
, ¤t_type
, &internal_format
)) {
10369 LOCAL_SET_GL_ERROR(
10370 GL_INVALID_OPERATION
, function_name
, "level does not exist.");
10373 if (!texture_manager()->ValidateTextureParameters(state_
.GetErrorState(),
10374 function_name
, format
, type
, internal_format
, level
)) {
10377 if (type
!= current_type
) {
10378 LOCAL_SET_GL_ERROR(
10379 GL_INVALID_OPERATION
,
10380 function_name
, "type does not match type of texture.");
10383 if (async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
10384 LOCAL_SET_GL_ERROR(
10385 GL_INVALID_OPERATION
,
10386 function_name
, "async upload pending for texture");
10389 if (!texture
->ValidForTexture(
10390 target
, level
, xoffset
, yoffset
, 0, width
, height
, 1, type
)) {
10391 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "bad dimensions.");
10394 if ((GLES2Util::GetChannelsForFormat(format
) &
10395 (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0
10396 && !feature_info_
->IsES3Enabled()) {
10397 LOCAL_SET_GL_ERROR(
10398 GL_INVALID_OPERATION
,
10399 function_name
, "can not supply data for depth or stencil textures");
10402 if (data
== NULL
) {
10403 (*error
) = error::kOutOfBounds
;
10409 error::Error
GLES2DecoderImpl::DoTexSubImage2D(
10418 const void * data
) {
10419 error::Error error
= error::kNoError
;
10420 if (!ValidateTexSubImage2D(&error
, "glTexSubImage2D", target
, level
,
10421 xoffset
, yoffset
, width
, height
, format
, type
, data
)) {
10424 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10426 Texture
* texture
= texture_ref
->texture();
10427 GLsizei tex_width
= 0;
10428 GLsizei tex_height
= 0;
10429 bool ok
= texture
->GetLevelSize(
10430 target
, level
, &tex_width
, &tex_height
, nullptr);
10432 if (xoffset
!= 0 || yoffset
!= 0 ||
10433 width
!= tex_width
|| height
!= tex_height
) {
10434 gfx::Rect cleared_rect
;
10435 if (CombineAdjacentRects(texture
->GetLevelClearedRect(target
, level
),
10436 gfx::Rect(xoffset
, yoffset
, width
, height
),
10438 DCHECK_GE(cleared_rect
.size().GetArea(),
10439 texture
->GetLevelClearedRect(target
, level
).size().GetArea());
10440 texture_manager()->SetLevelClearedRect(texture_ref
, target
, level
,
10443 // Otherwise clear part of texture level that is not already cleared.
10444 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
,
10446 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glTexSubImage2D",
10447 "dimensions too big");
10448 return error::kNoError
;
10451 ScopedTextureUploadTimer
timer(&texture_state_
);
10453 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
10454 return error::kNoError
;
10457 if (!texture_state_
.texsubimage_faster_than_teximage
&&
10458 !texture
->IsImmutable() &&
10459 !texture
->HasImages()) {
10460 ScopedTextureUploadTimer
timer(&texture_state_
);
10461 GLenum internal_format
;
10463 texture
->GetLevelType(target
, level
, &tex_type
, &internal_format
);
10464 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
10467 target
, level
, internal_format
, width
, height
, 0, format
, type
, data
);
10469 ScopedTextureUploadTimer
timer(&texture_state_
);
10471 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
10473 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
10475 // This may be a slow command. Exit command processing to allow for
10476 // context preemption and GPU watchdog checks.
10477 ExitCommandProcessingEarly();
10478 return error::kNoError
;
10481 error::Error
GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size
,
10482 const void* cmd_data
) {
10483 const gles2::cmds::TexSubImage2D
& c
=
10484 *static_cast<const gles2::cmds::TexSubImage2D
*>(cmd_data
);
10485 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
10486 "width", c
.width
, "height", c
.height
);
10487 GLboolean internal
= static_cast<GLboolean
>(c
.internal
);
10488 if (internal
== GL_TRUE
&& texture_state_
.tex_image_failed
)
10489 return error::kNoError
;
10491 GLenum target
= static_cast<GLenum
>(c
.target
);
10492 GLint level
= static_cast<GLint
>(c
.level
);
10493 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
10494 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
10495 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10496 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10497 GLenum format
= static_cast<GLenum
>(c
.format
);
10498 GLenum type
= static_cast<GLenum
>(c
.type
);
10500 if (!GLES2Util::ComputeImageDataSizes(
10501 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &data_size
,
10503 return error::kOutOfBounds
;
10505 const void* pixels
= GetSharedMemoryAs
<const void*>(
10506 c
.pixels_shm_id
, c
.pixels_shm_offset
, data_size
);
10507 return DoTexSubImage2D(
10508 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
);
10511 error::Error
GLES2DecoderImpl::DoTexSubImage3D(
10522 const void * data
) {
10523 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10525 if (!texture_ref
) {
10526 LOCAL_SET_GL_ERROR(
10527 GL_INVALID_ENUM
, "glTexSubImage3D", "invalid target");
10530 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexSubImage3D");
10531 ScopedTextureUploadTimer
timer(&texture_state_
);
10532 glTexSubImage3D(target
, level
, xoffset
, yoffset
, zoffset
, width
, height
,
10533 depth
, format
, type
, data
);
10534 GLenum error
= LOCAL_PEEK_GL_ERROR("glTexSubImage3D");
10535 if (error
== GL_NO_ERROR
) {
10536 // TODO(zmo): This is not 100% correct because only part of the level
10537 // image is cleared.
10538 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
10541 // This may be a slow command. Exit command processing to allow for
10542 // context preemption and GPU watchdog checks.
10543 ExitCommandProcessingEarly();
10544 return error::kNoError
;
10547 error::Error
GLES2DecoderImpl::HandleTexSubImage3D(uint32 immediate_data_size
,
10548 const void* cmd_data
) {
10549 if (!unsafe_es3_apis_enabled())
10550 return error::kUnknownCommand
;
10552 const gles2::cmds::TexSubImage3D
& c
=
10553 *static_cast<const gles2::cmds::TexSubImage3D
*>(cmd_data
);
10554 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage3D",
10555 "widthXheight", c
.width
* c
.height
, "depth", c
.depth
);
10556 GLboolean internal
= static_cast<GLboolean
>(c
.internal
);
10557 if (internal
== GL_TRUE
&& texture_state_
.tex_image_failed
)
10558 return error::kNoError
;
10560 GLenum target
= static_cast<GLenum
>(c
.target
);
10561 GLint level
= static_cast<GLint
>(c
.level
);
10562 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
10563 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
10564 GLint zoffset
= static_cast<GLint
>(c
.zoffset
);
10565 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10566 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10567 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
10568 GLenum format
= static_cast<GLenum
>(c
.format
);
10569 GLenum type
= static_cast<GLenum
>(c
.type
);
10571 if (!GLES2Util::ComputeImageDataSizes(
10572 width
, height
, depth
, format
, type
, state_
.unpack_alignment
, &data_size
,
10574 return error::kOutOfBounds
;
10576 const void* pixels
= GetSharedMemoryAs
<const void*>(
10577 c
.pixels_shm_id
, c
.pixels_shm_offset
, data_size
);
10578 return DoTexSubImage3D(target
, level
, xoffset
, yoffset
, zoffset
, width
,
10579 height
, depth
, format
, type
, pixels
);
10582 error::Error
GLES2DecoderImpl::HandleGetVertexAttribPointerv(
10583 uint32 immediate_data_size
,
10584 const void* cmd_data
) {
10585 const gles2::cmds::GetVertexAttribPointerv
& c
=
10586 *static_cast<const gles2::cmds::GetVertexAttribPointerv
*>(cmd_data
);
10587 GLuint index
= static_cast<GLuint
>(c
.index
);
10588 GLenum pname
= static_cast<GLenum
>(c
.pname
);
10589 typedef cmds::GetVertexAttribPointerv::Result Result
;
10590 Result
* result
= GetSharedMemoryAs
<Result
*>(
10591 c
.pointer_shm_id
, c
.pointer_shm_offset
, Result::ComputeSize(1));
10593 return error::kOutOfBounds
;
10595 // Check that the client initialized the result.
10596 if (result
->size
!= 0) {
10597 return error::kInvalidArguments
;
10599 if (!validators_
->vertex_pointer
.IsValid(pname
)) {
10600 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10601 "glGetVertexAttribPointerv", pname
, "pname");
10602 return error::kNoError
;
10604 if (index
>= group_
->max_vertex_attribs()) {
10605 LOCAL_SET_GL_ERROR(
10606 GL_INVALID_VALUE
, "glGetVertexAttribPointerv", "index out of range.");
10607 return error::kNoError
;
10609 result
->SetNumResults(1);
10610 *result
->GetData() =
10611 state_
.vertex_attrib_manager
->GetVertexAttrib(index
)->offset();
10612 return error::kNoError
;
10616 bool GLES2DecoderImpl::GetUniformSetup(GLuint program_id
,
10617 GLint fake_location
,
10620 error::Error
* error
,
10621 GLint
* real_location
,
10622 GLuint
* service_id
,
10623 SizedResult
<T
>** result_pointer
,
10624 GLenum
* result_type
,
10625 GLsizei
* result_size
) {
10627 DCHECK(service_id
);
10628 DCHECK(result_pointer
);
10629 DCHECK(result_type
);
10630 DCHECK(result_size
);
10631 DCHECK(real_location
);
10632 *error
= error::kNoError
;
10633 // Make sure we have enough room for the result on failure.
10634 SizedResult
<T
>* result
;
10635 result
= GetSharedMemoryAs
<SizedResult
<T
>*>(
10636 shm_id
, shm_offset
, SizedResult
<T
>::ComputeSize(0));
10638 *error
= error::kOutOfBounds
;
10641 *result_pointer
= result
;
10642 // Set the result size to 0 so the client does not have to check for success.
10643 result
->SetNumResults(0);
10644 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetUniform");
10648 if (!program
->IsValid()) {
10649 // Program was not linked successfully. (ie, glLinkProgram)
10650 LOCAL_SET_GL_ERROR(
10651 GL_INVALID_OPERATION
, "glGetUniform", "program not linked");
10654 *service_id
= program
->service_id();
10655 GLint array_index
= -1;
10656 const Program::UniformInfo
* uniform_info
=
10657 program
->GetUniformInfoByFakeLocation(
10658 fake_location
, real_location
, &array_index
);
10659 if (!uniform_info
) {
10660 // No such location.
10661 LOCAL_SET_GL_ERROR(
10662 GL_INVALID_OPERATION
, "glGetUniform", "unknown location");
10665 GLenum type
= uniform_info
->type
;
10666 uint32 num_elements
= GLES2Util::GetElementCountForUniformType(type
);
10667 if (num_elements
== 0) {
10668 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glGetUniform", "unknown type");
10671 result
= GetSharedMemoryAs
<SizedResult
<T
>*>(
10672 shm_id
, shm_offset
, SizedResult
<T
>::ComputeSize(num_elements
));
10674 *error
= error::kOutOfBounds
;
10677 result
->SetNumResults(num_elements
);
10678 *result_size
= num_elements
* sizeof(T
);
10679 *result_type
= type
;
10683 error::Error
GLES2DecoderImpl::HandleGetUniformiv(uint32 immediate_data_size
,
10684 const void* cmd_data
) {
10685 const gles2::cmds::GetUniformiv
& c
=
10686 *static_cast<const gles2::cmds::GetUniformiv
*>(cmd_data
);
10687 GLuint program
= c
.program
;
10688 GLint fake_location
= c
.location
;
10690 GLenum result_type
;
10691 GLsizei result_size
;
10692 GLint real_location
= -1;
10694 cmds::GetUniformiv::Result
* result
;
10695 if (GetUniformSetup
<GLint
>(program
, fake_location
, c
.params_shm_id
,
10696 c
.params_shm_offset
, &error
, &real_location
,
10697 &service_id
, &result
, &result_type
,
10700 service_id
, real_location
, result
->GetData());
10705 error::Error
GLES2DecoderImpl::HandleGetUniformuiv(uint32 immediate_data_size
,
10706 const void* cmd_data
) {
10707 if (!unsafe_es3_apis_enabled())
10708 return error::kUnknownCommand
;
10710 const gles2::cmds::GetUniformuiv
& c
=
10711 *static_cast<const gles2::cmds::GetUniformuiv
*>(cmd_data
);
10712 GLuint program
= c
.program
;
10713 GLint fake_location
= c
.location
;
10715 GLenum result_type
;
10716 GLsizei result_size
;
10717 GLint real_location
= -1;
10719 cmds::GetUniformuiv::Result
* result
;
10720 if (GetUniformSetup
<GLuint
>(program
, fake_location
, c
.params_shm_id
,
10721 c
.params_shm_offset
, &error
, &real_location
,
10722 &service_id
, &result
, &result_type
,
10725 service_id
, real_location
, result
->GetData());
10730 error::Error
GLES2DecoderImpl::HandleGetUniformfv(uint32 immediate_data_size
,
10731 const void* cmd_data
) {
10732 const gles2::cmds::GetUniformfv
& c
=
10733 *static_cast<const gles2::cmds::GetUniformfv
*>(cmd_data
);
10734 GLuint program
= c
.program
;
10735 GLint fake_location
= c
.location
;
10737 GLint real_location
= -1;
10739 cmds::GetUniformfv::Result
* result
;
10740 GLenum result_type
;
10741 GLsizei result_size
;
10742 if (GetUniformSetup
<GLfloat
>(program
, fake_location
, c
.params_shm_id
,
10743 c
.params_shm_offset
, &error
, &real_location
,
10744 &service_id
, &result
, &result_type
,
10746 if (result_type
== GL_BOOL
|| result_type
== GL_BOOL_VEC2
||
10747 result_type
== GL_BOOL_VEC3
|| result_type
== GL_BOOL_VEC4
) {
10748 GLsizei num_values
= result_size
/ sizeof(GLfloat
);
10749 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
10750 glGetUniformiv(service_id
, real_location
, temp
.get());
10751 GLfloat
* dst
= result
->GetData();
10752 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
10753 dst
[ii
] = (temp
[ii
] != 0);
10756 glGetUniformfv(service_id
, real_location
, result
->GetData());
10762 error::Error
GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
10763 uint32 immediate_data_size
,
10764 const void* cmd_data
) {
10765 const gles2::cmds::GetShaderPrecisionFormat
& c
=
10766 *static_cast<const gles2::cmds::GetShaderPrecisionFormat
*>(cmd_data
);
10767 GLenum shader_type
= static_cast<GLenum
>(c
.shadertype
);
10768 GLenum precision_type
= static_cast<GLenum
>(c
.precisiontype
);
10769 typedef cmds::GetShaderPrecisionFormat::Result Result
;
10770 Result
* result
= GetSharedMemoryAs
<Result
*>(
10771 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10773 return error::kOutOfBounds
;
10775 // Check that the client initialized the result.
10776 if (result
->success
!= 0) {
10777 return error::kInvalidArguments
;
10779 if (!validators_
->shader_type
.IsValid(shader_type
)) {
10780 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10781 "glGetShaderPrecisionFormat", shader_type
, "shader_type");
10782 return error::kNoError
;
10784 if (!validators_
->shader_precision
.IsValid(precision_type
)) {
10785 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10786 "glGetShaderPrecisionFormat", precision_type
, "precision_type");
10787 return error::kNoError
;
10790 result
->success
= 1; // true
10792 GLint range
[2] = { 0, 0 };
10793 GLint precision
= 0;
10794 GetShaderPrecisionFormatImpl(shader_type
, precision_type
, range
, &precision
);
10796 result
->min_range
= range
[0];
10797 result
->max_range
= range
[1];
10798 result
->precision
= precision
;
10800 return error::kNoError
;
10803 error::Error
GLES2DecoderImpl::HandleGetAttachedShaders(
10804 uint32 immediate_data_size
,
10805 const void* cmd_data
) {
10806 const gles2::cmds::GetAttachedShaders
& c
=
10807 *static_cast<const gles2::cmds::GetAttachedShaders
*>(cmd_data
);
10808 uint32 result_size
= c
.result_size
;
10809 GLuint program_id
= static_cast<GLuint
>(c
.program
);
10810 Program
* program
= GetProgramInfoNotShader(
10811 program_id
, "glGetAttachedShaders");
10813 return error::kNoError
;
10815 typedef cmds::GetAttachedShaders::Result Result
;
10816 uint32 max_count
= Result::ComputeMaxResults(result_size
);
10817 Result
* result
= GetSharedMemoryAs
<Result
*>(
10818 c
.result_shm_id
, c
.result_shm_offset
, Result::ComputeSize(max_count
));
10820 return error::kOutOfBounds
;
10822 // Check that the client initialized the result.
10823 if (result
->size
!= 0) {
10824 return error::kInvalidArguments
;
10827 glGetAttachedShaders(
10828 program
->service_id(), max_count
, &count
, result
->GetData());
10829 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
10830 if (!shader_manager()->GetClientId(result
->GetData()[ii
],
10831 &result
->GetData()[ii
])) {
10833 return error::kGenericError
;
10836 result
->SetNumResults(count
);
10837 return error::kNoError
;
10840 error::Error
GLES2DecoderImpl::HandleGetActiveUniform(
10841 uint32 immediate_data_size
,
10842 const void* cmd_data
) {
10843 const gles2::cmds::GetActiveUniform
& c
=
10844 *static_cast<const gles2::cmds::GetActiveUniform
*>(cmd_data
);
10845 GLuint program_id
= c
.program
;
10846 GLuint index
= c
.index
;
10847 uint32 name_bucket_id
= c
.name_bucket_id
;
10848 typedef cmds::GetActiveUniform::Result Result
;
10849 Result
* result
= GetSharedMemoryAs
<Result
*>(
10850 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10852 return error::kOutOfBounds
;
10854 // Check that the client initialized the result.
10855 if (result
->success
!= 0) {
10856 return error::kInvalidArguments
;
10858 Program
* program
= GetProgramInfoNotShader(
10859 program_id
, "glGetActiveUniform");
10861 return error::kNoError
;
10863 const Program::UniformInfo
* uniform_info
=
10864 program
->GetUniformInfo(index
);
10865 if (!uniform_info
) {
10866 LOCAL_SET_GL_ERROR(
10867 GL_INVALID_VALUE
, "glGetActiveUniform", "index out of range");
10868 return error::kNoError
;
10870 result
->success
= 1; // true.
10871 result
->size
= uniform_info
->size
;
10872 result
->type
= uniform_info
->type
;
10873 Bucket
* bucket
= CreateBucket(name_bucket_id
);
10874 bucket
->SetFromString(uniform_info
->name
.c_str());
10875 return error::kNoError
;
10878 error::Error
GLES2DecoderImpl::HandleGetActiveUniformBlockiv(
10879 uint32 immediate_data_size
, const void* cmd_data
) {
10880 if (!unsafe_es3_apis_enabled())
10881 return error::kUnknownCommand
;
10882 const gles2::cmds::GetActiveUniformBlockiv
& c
=
10883 *static_cast<const gles2::cmds::GetActiveUniformBlockiv
*>(cmd_data
);
10884 GLuint program_id
= c
.program
;
10885 GLuint index
= static_cast<GLuint
>(c
.index
);
10886 GLenum pname
= static_cast<GLenum
>(c
.pname
);
10887 Program
* program
= GetProgramInfoNotShader(
10888 program_id
, "glGetActiveUniformBlockiv");
10890 return error::kNoError
;
10892 GLuint service_id
= program
->service_id();
10893 GLint link_status
= GL_FALSE
;
10894 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
10895 if (link_status
!= GL_TRUE
) {
10896 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10897 "glGetActiveActiveUniformBlockiv", "program not linked");
10898 return error::kNoError
;
10900 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformBlockiv");
10901 GLsizei num_values
= 1;
10902 if (pname
== GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES
) {
10904 glGetActiveUniformBlockiv(
10905 service_id
, index
, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS
, &num
);
10906 GLenum error
= glGetError();
10907 if (error
!= GL_NO_ERROR
) {
10908 // Assume this will the same error if calling with pname.
10909 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformBlockiv", "");
10910 return error::kNoError
;
10912 num_values
= static_cast<GLsizei
>(num
);
10914 typedef cmds::GetActiveUniformBlockiv::Result Result
;
10915 Result
* result
= GetSharedMemoryAs
<Result
*>(
10916 c
.params_shm_id
, c
.params_shm_offset
, Result::ComputeSize(num_values
));
10917 GLint
* params
= result
? result
->GetData() : NULL
;
10918 if (params
== NULL
) {
10919 return error::kOutOfBounds
;
10921 // Check that the client initialized the result.
10922 if (result
->size
!= 0) {
10923 return error::kInvalidArguments
;
10925 glGetActiveUniformBlockiv(service_id
, index
, pname
, params
);
10926 GLenum error
= glGetError();
10927 if (error
== GL_NO_ERROR
) {
10928 result
->SetNumResults(num_values
);
10930 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformBlockiv", "");
10932 return error::kNoError
;
10935 error::Error
GLES2DecoderImpl::HandleGetActiveUniformBlockName(
10936 uint32 immediate_data_size
, const void* cmd_data
) {
10937 if (!unsafe_es3_apis_enabled())
10938 return error::kUnknownCommand
;
10939 const gles2::cmds::GetActiveUniformBlockName
& c
=
10940 *static_cast<const gles2::cmds::GetActiveUniformBlockName
*>(cmd_data
);
10941 GLuint program_id
= c
.program
;
10942 GLuint index
= c
.index
;
10943 uint32 name_bucket_id
= c
.name_bucket_id
;
10944 typedef cmds::GetActiveUniformBlockName::Result Result
;
10945 Result
* result
= GetSharedMemoryAs
<Result
*>(
10946 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10948 return error::kOutOfBounds
;
10950 // Check that the client initialized the result.
10951 if (*result
!= 0) {
10952 return error::kInvalidArguments
;
10954 Program
* program
= GetProgramInfoNotShader(
10955 program_id
, "glGetActiveUniformBlockName");
10957 return error::kNoError
;
10959 GLuint service_id
= program
->service_id();
10960 GLint link_status
= GL_FALSE
;
10961 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
10962 if (link_status
!= GL_TRUE
) {
10963 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10964 "glGetActiveActiveUniformBlockName", "program not linked");
10965 return error::kNoError
;
10967 GLint max_length
= 0;
10969 service_id
, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH
, &max_length
);
10970 // Increase one so &buffer[0] is always valid.
10971 GLsizei buf_size
= static_cast<GLsizei
>(max_length
) + 1;
10972 std::vector
<char> buffer(buf_size
);
10973 GLsizei length
= 0;
10974 glGetActiveUniformBlockName(
10975 service_id
, index
, buf_size
, &length
, &buffer
[0]);
10978 return error::kNoError
;
10981 Bucket
* bucket
= CreateBucket(name_bucket_id
);
10982 DCHECK_GT(buf_size
, length
);
10983 DCHECK_EQ(0, buffer
[length
]);
10984 bucket
->SetFromString(&buffer
[0]);
10985 return error::kNoError
;
10988 error::Error
GLES2DecoderImpl::HandleGetActiveUniformsiv(
10989 uint32 immediate_data_size
, const void* cmd_data
) {
10990 if (!unsafe_es3_apis_enabled())
10991 return error::kUnknownCommand
;
10992 const gles2::cmds::GetActiveUniformsiv
& c
=
10993 *static_cast<const gles2::cmds::GetActiveUniformsiv
*>(cmd_data
);
10994 GLuint program_id
= c
.program
;
10995 GLenum pname
= static_cast<GLenum
>(c
.pname
);
10996 Bucket
* bucket
= GetBucket(c
.indices_bucket_id
);
10998 return error::kInvalidArguments
;
11000 GLsizei count
= static_cast<GLsizei
>(bucket
->size() / sizeof(GLuint
));
11001 const GLuint
* indices
= bucket
->GetDataAs
<const GLuint
*>(0, bucket
->size());
11002 typedef cmds::GetActiveUniformsiv::Result Result
;
11003 Result
* result
= GetSharedMemoryAs
<Result
*>(
11004 c
.params_shm_id
, c
.params_shm_offset
, Result::ComputeSize(count
));
11005 GLint
* params
= result
? result
->GetData() : NULL
;
11006 if (params
== NULL
) {
11007 return error::kOutOfBounds
;
11009 // Check that the client initialized the result.
11010 if (result
->size
!= 0) {
11011 return error::kInvalidArguments
;
11013 Program
* program
= GetProgramInfoNotShader(
11014 program_id
, "glGetActiveUniformsiv");
11016 return error::kNoError
;
11018 GLuint service_id
= program
->service_id();
11019 GLint link_status
= GL_FALSE
;
11020 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
11021 if (link_status
!= GL_TRUE
) {
11022 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11023 "glGetActiveUniformsiv", "program not linked");
11024 return error::kNoError
;
11026 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformsiv");
11027 glGetActiveUniformsiv(service_id
, count
, indices
, pname
, params
);
11028 GLenum error
= glGetError();
11029 if (error
== GL_NO_ERROR
) {
11030 result
->SetNumResults(count
);
11032 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformsiv", "");
11034 return error::kNoError
;
11037 error::Error
GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size
,
11038 const void* cmd_data
) {
11039 const gles2::cmds::GetActiveAttrib
& c
=
11040 *static_cast<const gles2::cmds::GetActiveAttrib
*>(cmd_data
);
11041 GLuint program_id
= c
.program
;
11042 GLuint index
= c
.index
;
11043 uint32 name_bucket_id
= c
.name_bucket_id
;
11044 typedef cmds::GetActiveAttrib::Result Result
;
11045 Result
* result
= GetSharedMemoryAs
<Result
*>(
11046 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
11048 return error::kOutOfBounds
;
11050 // Check that the client initialized the result.
11051 if (result
->success
!= 0) {
11052 return error::kInvalidArguments
;
11054 Program
* program
= GetProgramInfoNotShader(
11055 program_id
, "glGetActiveAttrib");
11057 return error::kNoError
;
11059 const Program::VertexAttrib
* attrib_info
=
11060 program
->GetAttribInfo(index
);
11061 if (!attrib_info
) {
11062 LOCAL_SET_GL_ERROR(
11063 GL_INVALID_VALUE
, "glGetActiveAttrib", "index out of range");
11064 return error::kNoError
;
11066 result
->success
= 1; // true.
11067 result
->size
= attrib_info
->size
;
11068 result
->type
= attrib_info
->type
;
11069 Bucket
* bucket
= CreateBucket(name_bucket_id
);
11070 bucket
->SetFromString(attrib_info
->name
.c_str());
11071 return error::kNoError
;
11074 error::Error
GLES2DecoderImpl::HandleShaderBinary(uint32 immediate_data_size
,
11075 const void* cmd_data
) {
11076 #if 1 // No binary shader support.
11077 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glShaderBinary", "not supported");
11078 return error::kNoError
;
11080 GLsizei n
= static_cast<GLsizei
>(c
.n
);
11082 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "n < 0");
11083 return error::kNoError
;
11085 GLsizei length
= static_cast<GLsizei
>(c
.length
);
11087 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "length < 0");
11088 return error::kNoError
;
11091 if (!SafeMultiplyUint32(n
, sizeof(GLuint
), &data_size
)) {
11092 return error::kOutOfBounds
;
11094 const GLuint
* shaders
= GetSharedMemoryAs
<const GLuint
*>(
11095 c
.shaders_shm_id
, c
.shaders_shm_offset
, data_size
);
11096 GLenum binaryformat
= static_cast<GLenum
>(c
.binaryformat
);
11097 const void* binary
= GetSharedMemoryAs
<const void*>(
11098 c
.binary_shm_id
, c
.binary_shm_offset
, length
);
11099 if (shaders
== NULL
|| binary
== NULL
) {
11100 return error::kOutOfBounds
;
11102 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
11103 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11104 Shader
* shader
= GetShader(shaders
[ii
]);
11106 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "unknown shader");
11107 return error::kNoError
;
11109 service_ids
[ii
] = shader
->service_id();
11111 // TODO(gman): call glShaderBinary
11112 return error::kNoError
;
11116 void GLES2DecoderImpl::DoSwapBuffers() {
11117 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
11119 int this_frame_number
= frame_number_
++;
11120 // TRACE_EVENT for gpu tests:
11121 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
11122 TRACE_EVENT_SCOPE_THREAD
,
11123 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
11124 "width", (is_offscreen
? offscreen_size_
.width() :
11125 surface_
->GetSize().width()));
11126 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
11127 "offscreen", is_offscreen
,
11128 "frame", this_frame_number
);
11130 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
11133 ScopedGPUTrace
scoped_gpu_trace(gpu_tracer_
.get(), kTraceDecoder
,
11134 "GLES2Decoder", "SwapBuffer");
11137 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
11140 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
11141 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
11142 is_offscreen
? offscreen_size_
: surface_
->GetSize());
11145 // If offscreen then don't actually SwapBuffers to the display. Just copy
11146 // the rendered frame to another frame buffer.
11147 if (is_offscreen
) {
11148 TRACE_EVENT2("gpu", "Offscreen",
11149 "width", offscreen_size_
.width(), "height", offscreen_size_
.height());
11150 if (offscreen_size_
!= offscreen_saved_color_texture_
->size()) {
11151 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
11152 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
11154 if (workarounds().needs_offscreen_buffer_workaround
) {
11155 offscreen_saved_frame_buffer_
->Create();
11159 // Allocate the offscreen saved color texture.
11160 DCHECK(offscreen_saved_color_format_
);
11161 offscreen_saved_color_texture_
->AllocateStorage(
11162 offscreen_size_
, offscreen_saved_color_format_
, false);
11164 offscreen_saved_frame_buffer_
->AttachRenderTexture(
11165 offscreen_saved_color_texture_
.get());
11166 if (offscreen_size_
.width() != 0 && offscreen_size_
.height() != 0) {
11167 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
11168 GL_FRAMEBUFFER_COMPLETE
) {
11169 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
11170 << "because offscreen saved FBO was incomplete.";
11171 MarkContextLost(error::kUnknown
);
11172 group_
->LoseContexts(error::kUnknown
);
11176 // Clear the offscreen color texture.
11177 // TODO(piman): Is this still necessary?
11179 ScopedFrameBufferBinder
binder(this,
11180 offscreen_saved_frame_buffer_
->id());
11181 glClearColor(0, 0, 0, 0);
11182 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
11183 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
11184 glClear(GL_COLOR_BUFFER_BIT
);
11185 RestoreClearState();
11189 UpdateParentTextureInfo();
11192 if (offscreen_size_
.width() == 0 || offscreen_size_
.height() == 0)
11194 ScopedGLErrorSuppressor
suppressor(
11195 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
11197 if (IsOffscreenBufferMultisampled()) {
11198 // For multisampled buffers, resolve the frame buffer.
11199 ScopedResolvedFrameBufferBinder
binder(this, true, false);
11201 ScopedFrameBufferBinder
binder(this,
11202 offscreen_target_frame_buffer_
->id());
11204 if (offscreen_target_buffer_preserved_
) {
11205 // Copy the target frame buffer to the saved offscreen texture.
11206 offscreen_saved_color_texture_
->Copy(
11207 offscreen_saved_color_texture_
->size(),
11208 offscreen_saved_color_format_
);
11210 // Flip the textures in the parent context via the texture manager.
11211 if (!!offscreen_saved_color_texture_info_
.get())
11212 offscreen_saved_color_texture_info_
->texture()->
11213 SetServiceId(offscreen_target_color_texture_
->id());
11215 offscreen_saved_color_texture_
.swap(offscreen_target_color_texture_
);
11216 offscreen_target_frame_buffer_
->AttachRenderTexture(
11217 offscreen_target_color_texture_
.get());
11220 // Ensure the side effects of the copy are visible to the parent
11221 // context. There is no need to do this for ANGLE because it uses a
11222 // single D3D device for all contexts.
11223 if (!feature_info_
->gl_version_info().is_angle
)
11227 if (surface_
->SwapBuffers() == gfx::SwapResult::SWAP_FAILED
) {
11228 LOG(ERROR
) << "Context lost because SwapBuffers failed.";
11229 if (!CheckResetStatus()) {
11230 MarkContextLost(error::kUnknown
);
11231 group_
->LoseContexts(error::kUnknown
);
11236 // This may be a slow command. Exit command processing to allow for
11237 // context preemption and GPU watchdog checks.
11238 ExitCommandProcessingEarly();
11241 void GLES2DecoderImpl::DoSwapInterval(int interval
) {
11242 context_
->SetSwapInterval(interval
);
11245 error::Error
GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
11246 uint32 immediate_data_size
,
11247 const void* cmd_data
) {
11248 const gles2::cmds::EnableFeatureCHROMIUM
& c
=
11249 *static_cast<const gles2::cmds::EnableFeatureCHROMIUM
*>(cmd_data
);
11250 Bucket
* bucket
= GetBucket(c
.bucket_id
);
11251 if (!bucket
|| bucket
->size() == 0) {
11252 return error::kInvalidArguments
;
11254 typedef cmds::EnableFeatureCHROMIUM::Result Result
;
11255 Result
* result
= GetSharedMemoryAs
<Result
*>(
11256 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
11258 return error::kOutOfBounds
;
11260 // Check that the client initialized the result.
11261 if (*result
!= 0) {
11262 return error::kInvalidArguments
;
11264 std::string feature_str
;
11265 if (!bucket
->GetAsString(&feature_str
)) {
11266 return error::kInvalidArguments
;
11269 // TODO(gman): make this some kind of table to function pointer thingy.
11270 if (feature_str
.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
11271 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
11272 } else if (feature_str
.compare("pepper3d_support_fixed_attribs") == 0) {
11273 buffer_manager()->set_allow_fixed_attribs(true);
11274 // TODO(gman): decide how to remove the need for this const_cast.
11275 // I could make validators_ non const but that seems bad as this is the only
11276 // place it is needed. I could make some special friend class of validators
11277 // just to allow this to set them. That seems silly. I could refactor this
11278 // code to use the extension mechanism or the initialization attributes to
11279 // turn this feature on. Given that the only real point of this is to make
11280 // the conformance tests pass and given that there is lots of real work that
11281 // needs to be done it seems like refactoring for one to one of those
11282 // methods is a very low priority.
11283 const_cast<Validators
*>(validators_
)->vertex_attrib_type
.AddValue(GL_FIXED
);
11285 return error::kNoError
;
11288 *result
= 1; // true.
11289 return error::kNoError
;
11292 error::Error
GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
11293 uint32 immediate_data_size
,
11294 const void* cmd_data
) {
11295 const gles2::cmds::GetRequestableExtensionsCHROMIUM
& c
=
11296 *static_cast<const gles2::cmds::GetRequestableExtensionsCHROMIUM
*>(
11298 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
11299 scoped_refptr
<FeatureInfo
> info(new FeatureInfo());
11300 info
->Initialize(disallowed_features_
);
11301 bucket
->SetFromString(info
->extensions().c_str());
11302 return error::kNoError
;
11305 error::Error
GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
11306 uint32 immediate_data_size
,
11307 const void* cmd_data
) {
11308 const gles2::cmds::RequestExtensionCHROMIUM
& c
=
11309 *static_cast<const gles2::cmds::RequestExtensionCHROMIUM
*>(cmd_data
);
11310 Bucket
* bucket
= GetBucket(c
.bucket_id
);
11311 if (!bucket
|| bucket
->size() == 0) {
11312 return error::kInvalidArguments
;
11314 std::string feature_str
;
11315 if (!bucket
->GetAsString(&feature_str
)) {
11316 return error::kInvalidArguments
;
11319 bool desire_standard_derivatives
= false;
11320 bool desire_frag_depth
= false;
11321 bool desire_draw_buffers
= false;
11322 bool desire_shader_texture_lod
= false;
11323 if (IsWebGLContext()) {
11324 desire_standard_derivatives
=
11325 feature_str
.find("GL_OES_standard_derivatives") != std::string::npos
;
11326 desire_frag_depth
=
11327 feature_str
.find("GL_EXT_frag_depth") != std::string::npos
;
11328 desire_draw_buffers
=
11329 feature_str
.find("GL_EXT_draw_buffers") != std::string::npos
;
11330 desire_shader_texture_lod
=
11331 feature_str
.find("GL_EXT_shader_texture_lod") != std::string::npos
;
11334 if (desire_standard_derivatives
!= derivatives_explicitly_enabled_
||
11335 desire_frag_depth
!= frag_depth_explicitly_enabled_
||
11336 desire_draw_buffers
!= draw_buffers_explicitly_enabled_
||
11337 desire_shader_texture_lod
!= shader_texture_lod_explicitly_enabled_
) {
11338 derivatives_explicitly_enabled_
|= desire_standard_derivatives
;
11339 frag_depth_explicitly_enabled_
|= desire_frag_depth
;
11340 draw_buffers_explicitly_enabled_
|= desire_draw_buffers
;
11341 shader_texture_lod_explicitly_enabled_
|= desire_shader_texture_lod
;
11342 InitializeShaderTranslator();
11345 UpdateCapabilities();
11347 return error::kNoError
;
11350 error::Error
GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
11351 uint32 immediate_data_size
,
11352 const void* cmd_data
) {
11353 const gles2::cmds::GetProgramInfoCHROMIUM
& c
=
11354 *static_cast<const gles2::cmds::GetProgramInfoCHROMIUM
*>(cmd_data
);
11355 GLuint program_id
= static_cast<GLuint
>(c
.program
);
11356 uint32 bucket_id
= c
.bucket_id
;
11357 Bucket
* bucket
= CreateBucket(bucket_id
);
11358 bucket
->SetSize(sizeof(ProgramInfoHeader
)); // in case we fail.
11359 Program
* program
= NULL
;
11360 program
= GetProgram(program_id
);
11361 if (!program
|| !program
->IsValid()) {
11362 return error::kNoError
;
11364 program
->GetProgramInfo(program_manager(), bucket
);
11365 return error::kNoError
;
11368 error::Error
GLES2DecoderImpl::HandleGetUniformBlocksCHROMIUM(
11369 uint32 immediate_data_size
, const void* cmd_data
) {
11370 if (!unsafe_es3_apis_enabled())
11371 return error::kUnknownCommand
;
11372 const gles2::cmds::GetUniformBlocksCHROMIUM
& c
=
11373 *static_cast<const gles2::cmds::GetUniformBlocksCHROMIUM
*>(cmd_data
);
11374 GLuint program_id
= static_cast<GLuint
>(c
.program
);
11375 uint32 bucket_id
= c
.bucket_id
;
11376 Bucket
* bucket
= CreateBucket(bucket_id
);
11377 bucket
->SetSize(sizeof(UniformBlocksHeader
)); // in case we fail.
11378 Program
* program
= NULL
;
11379 program
= GetProgram(program_id
);
11380 if (!program
|| !program
->IsValid()) {
11381 return error::kNoError
;
11383 program
->GetUniformBlocks(bucket
);
11384 return error::kNoError
;
11387 error::Error
GLES2DecoderImpl::HandleGetUniformsES3CHROMIUM(
11388 uint32 immediate_data_size
, const void* cmd_data
) {
11389 if (!unsafe_es3_apis_enabled())
11390 return error::kUnknownCommand
;
11391 const gles2::cmds::GetUniformsES3CHROMIUM
& c
=
11392 *static_cast<const gles2::cmds::GetUniformsES3CHROMIUM
*>(cmd_data
);
11393 GLuint program_id
= static_cast<GLuint
>(c
.program
);
11394 uint32 bucket_id
= c
.bucket_id
;
11395 Bucket
* bucket
= CreateBucket(bucket_id
);
11396 bucket
->SetSize(sizeof(UniformsES3Header
)); // in case we fail.
11397 Program
* program
= NULL
;
11398 program
= GetProgram(program_id
);
11399 if (!program
|| !program
->IsValid()) {
11400 return error::kNoError
;
11402 program
->GetUniformsES3(bucket
);
11403 return error::kNoError
;
11406 error::Error
GLES2DecoderImpl::HandleGetTransformFeedbackVarying(
11407 uint32 immediate_data_size
,
11408 const void* cmd_data
) {
11409 if (!unsafe_es3_apis_enabled())
11410 return error::kUnknownCommand
;
11411 const gles2::cmds::GetTransformFeedbackVarying
& c
=
11412 *static_cast<const gles2::cmds::GetTransformFeedbackVarying
*>(cmd_data
);
11413 GLuint program_id
= c
.program
;
11414 GLuint index
= c
.index
;
11415 uint32 name_bucket_id
= c
.name_bucket_id
;
11416 typedef cmds::GetTransformFeedbackVarying::Result Result
;
11417 Result
* result
= GetSharedMemoryAs
<Result
*>(
11418 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
11420 return error::kOutOfBounds
;
11422 // Check that the client initialized the result.
11423 if (result
->success
!= 0) {
11424 return error::kInvalidArguments
;
11426 Program
* program
= GetProgramInfoNotShader(
11427 program_id
, "glGetTransformFeedbackVarying");
11429 return error::kNoError
;
11431 GLuint service_id
= program
->service_id();
11432 GLint link_status
= GL_FALSE
;
11433 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
11434 if (link_status
!= GL_TRUE
) {
11435 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11436 "glGetTransformFeedbackVarying", "program not linked");
11437 return error::kNoError
;
11439 GLint max_length
= 0;
11441 service_id
, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH
, &max_length
);
11442 max_length
= std::max(1, max_length
);
11443 std::vector
<char> buffer(max_length
);
11444 GLsizei length
= 0;
11447 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetTransformFeedbackVarying");
11448 glGetTransformFeedbackVarying(
11449 service_id
, index
, max_length
, &length
, &size
, &type
, &buffer
[0]);
11450 GLenum error
= glGetError();
11451 if (error
!= GL_NO_ERROR
) {
11452 LOCAL_SET_GL_ERROR(error
, "glGetTransformFeedbackVarying", "");
11453 return error::kNoError
;
11455 result
->success
= 1; // true.
11456 result
->size
= static_cast<int32_t>(size
);
11457 result
->type
= static_cast<uint32_t>(type
);
11458 Bucket
* bucket
= CreateBucket(name_bucket_id
);
11459 DCHECK(length
>= 0 && length
< max_length
);
11460 buffer
[length
] = '\0'; // Just to be safe.
11461 bucket
->SetFromString(&buffer
[0]);
11462 return error::kNoError
;
11465 error::Error
GLES2DecoderImpl::HandleGetTransformFeedbackVaryingsCHROMIUM(
11466 uint32 immediate_data_size
, const void* cmd_data
) {
11467 if (!unsafe_es3_apis_enabled())
11468 return error::kUnknownCommand
;
11469 const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM
& c
=
11470 *static_cast<const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM
*>(
11472 GLuint program_id
= static_cast<GLuint
>(c
.program
);
11473 uint32 bucket_id
= c
.bucket_id
;
11474 Bucket
* bucket
= CreateBucket(bucket_id
);
11475 bucket
->SetSize(sizeof(TransformFeedbackVaryingsHeader
)); // in case we fail.
11476 Program
* program
= NULL
;
11477 program
= GetProgram(program_id
);
11478 if (!program
|| !program
->IsValid()) {
11479 return error::kNoError
;
11481 program
->GetTransformFeedbackVaryings(bucket
);
11482 return error::kNoError
;
11485 error::ContextLostReason
GLES2DecoderImpl::GetContextLostReason() {
11486 return context_lost_reason_
;
11489 error::ContextLostReason
GLES2DecoderImpl::GetContextLostReasonFromResetStatus(
11490 GLenum reset_status
) const {
11491 switch (reset_status
) {
11493 // TODO(kbr): improve the precision of the error code in this case.
11494 // Consider delegating to context for error code if MakeCurrent fails.
11495 return error::kUnknown
;
11496 case GL_GUILTY_CONTEXT_RESET_ARB
:
11497 return error::kGuilty
;
11498 case GL_INNOCENT_CONTEXT_RESET_ARB
:
11499 return error::kInnocent
;
11500 case GL_UNKNOWN_CONTEXT_RESET_ARB
:
11501 return error::kUnknown
;
11505 return error::kUnknown
;
11508 bool GLES2DecoderImpl::WasContextLost() const {
11509 return context_was_lost_
;
11512 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() const {
11513 return WasContextLost() && reset_by_robustness_extension_
;
11516 void GLES2DecoderImpl::MarkContextLost(error::ContextLostReason reason
) {
11517 // Only lose the context once.
11518 if (WasContextLost())
11521 // Don't make GL calls in here, the context might not be current.
11522 context_lost_reason_
= reason
;
11523 current_decoder_error_
= error::kLostContext
;
11524 context_was_lost_
= true;
11527 bool GLES2DecoderImpl::CheckResetStatus() {
11528 DCHECK(!WasContextLost());
11529 DCHECK(context_
->IsCurrent(NULL
));
11531 if (IsRobustnessSupported()) {
11532 // If the reason for the call was a GL error, we can try to determine the
11533 // reset status more accurately.
11534 GLenum driver_status
= glGetGraphicsResetStatusARB();
11535 if (driver_status
== GL_NO_ERROR
)
11538 LOG(ERROR
) << (surface_
->IsOffscreen() ? "Offscreen" : "Onscreen")
11539 << " context lost via ARB/EXT_robustness. Reset status = "
11540 << GLES2Util::GetStringEnum(driver_status
);
11542 // Don't pretend we know which client was responsible.
11543 if (workarounds().use_virtualized_gl_contexts
)
11544 driver_status
= GL_UNKNOWN_CONTEXT_RESET_ARB
;
11546 switch (driver_status
) {
11547 case GL_GUILTY_CONTEXT_RESET_ARB
:
11548 MarkContextLost(error::kGuilty
);
11550 case GL_INNOCENT_CONTEXT_RESET_ARB
:
11551 MarkContextLost(error::kInnocent
);
11553 case GL_UNKNOWN_CONTEXT_RESET_ARB
:
11554 MarkContextLost(error::kUnknown
);
11560 reset_by_robustness_extension_
= true;
11566 error::Error
GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
11567 uint32 immediate_data_size
,
11568 const void* cmd_data
) {
11569 return error::kUnknownCommand
;
11572 error::Error
GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
11573 uint32 immediate_data_size
,
11574 const void* cmd_data
) {
11575 const gles2::cmds::WaitSyncPointCHROMIUM
& c
=
11576 *static_cast<const gles2::cmds::WaitSyncPointCHROMIUM
*>(cmd_data
);
11577 uint32 sync_point
= c
.sync_point
;
11578 if (wait_sync_point_callback_
.is_null())
11579 return error::kNoError
;
11581 return wait_sync_point_callback_
.Run(sync_point
) ?
11582 error::kNoError
: error::kDeferCommandUntilLater
;
11585 error::Error
GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
11586 uint32 immediate_data_size
,
11587 const void* cmd_data
) {
11588 if (surface_
->DeferDraws())
11589 return error::kDeferCommandUntilLater
;
11590 if (!surface_
->SetBackbufferAllocation(false))
11591 return error::kLostContext
;
11592 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
11593 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
11594 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
11595 return error::kNoError
;
11598 bool GLES2DecoderImpl::GenQueriesEXTHelper(
11599 GLsizei n
, const GLuint
* client_ids
) {
11600 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11601 if (query_manager_
->GetQuery(client_ids
[ii
])) {
11605 query_manager_
->GenQueries(n
, client_ids
);
11609 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
11610 GLsizei n
, const GLuint
* client_ids
) {
11611 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11612 query_manager_
->RemoveQuery(client_ids
[ii
]);
11616 bool GLES2DecoderImpl::ProcessPendingQueries(bool did_finish
) {
11617 if (query_manager_
.get() == NULL
) {
11620 if (!query_manager_
->ProcessPendingQueries(did_finish
)) {
11621 current_decoder_error_
= error::kOutOfBounds
;
11623 return query_manager_
->HavePendingQueries();
11626 // Note that if there are no pending readpixels right now,
11627 // this function will call the callback immediately.
11628 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback
) {
11629 if (features().use_async_readpixels
&& !pending_readpixel_fences_
.empty()) {
11630 pending_readpixel_fences_
.back()->callbacks
.push_back(callback
);
11636 void GLES2DecoderImpl::ProcessPendingReadPixels(bool did_finish
) {
11637 // Note: |did_finish| guarantees that the GPU has passed the fence but
11638 // we cannot assume that GLFence::HasCompleted() will return true yet as
11639 // that's not guaranteed by all GLFence implementations.
11640 while (!pending_readpixel_fences_
.empty() &&
11642 pending_readpixel_fences_
.front()->fence
->HasCompleted())) {
11643 std::vector
<base::Closure
> callbacks
=
11644 pending_readpixel_fences_
.front()->callbacks
;
11645 pending_readpixel_fences_
.pop();
11646 for (size_t i
= 0; i
< callbacks
.size(); i
++) {
11647 callbacks
[i
].Run();
11652 bool GLES2DecoderImpl::HasMoreIdleWork() {
11653 return !pending_readpixel_fences_
.empty() ||
11654 async_pixel_transfer_manager_
->NeedsProcessMorePendingTransfers();
11657 void GLES2DecoderImpl::PerformIdleWork() {
11658 ProcessPendingReadPixels(false);
11659 if (!async_pixel_transfer_manager_
->NeedsProcessMorePendingTransfers())
11661 async_pixel_transfer_manager_
->ProcessMorePendingTransfers();
11662 ProcessFinishedAsyncTransfers();
11665 error::Error
GLES2DecoderImpl::HandleBeginQueryEXT(uint32 immediate_data_size
,
11666 const void* cmd_data
) {
11667 const gles2::cmds::BeginQueryEXT
& c
=
11668 *static_cast<const gles2::cmds::BeginQueryEXT
*>(cmd_data
);
11669 GLenum target
= static_cast<GLenum
>(c
.target
);
11670 GLuint client_id
= static_cast<GLuint
>(c
.id
);
11671 int32 sync_shm_id
= static_cast<int32
>(c
.sync_data_shm_id
);
11672 uint32 sync_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
11675 case GL_COMMANDS_ISSUED_CHROMIUM
:
11676 case GL_LATENCY_QUERY_CHROMIUM
:
11677 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
:
11678 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM
:
11679 case GL_GET_ERROR_QUERY_CHROMIUM
:
11681 case GL_COMMANDS_COMPLETED_CHROMIUM
:
11682 if (!features().chromium_sync_query
) {
11683 LOCAL_SET_GL_ERROR(
11684 GL_INVALID_OPERATION
, "glBeginQueryEXT",
11685 "not enabled for commands completed queries");
11686 return error::kNoError
;
11689 case GL_SAMPLES_PASSED
:
11690 case GL_ANY_SAMPLES_PASSED
:
11691 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE
:
11692 if (!features().occlusion_query_boolean
) {
11693 LOCAL_SET_GL_ERROR(
11694 GL_INVALID_OPERATION
, "glBeginQueryEXT",
11695 "not enabled for occlusion queries");
11696 return error::kNoError
;
11699 case GL_TIME_ELAPSED
:
11700 if (!query_manager_
->GPUTimingAvailable()) {
11701 LOCAL_SET_GL_ERROR(
11702 GL_INVALID_OPERATION
, "glBeginQueryEXT",
11703 "not enabled for timing queries");
11704 return error::kNoError
;
11708 LOCAL_SET_GL_ERROR(
11709 GL_INVALID_ENUM
, "glBeginQueryEXT",
11710 "unknown query target");
11711 return error::kNoError
;
11714 if (query_manager_
->GetActiveQuery(target
)) {
11715 LOCAL_SET_GL_ERROR(
11716 GL_INVALID_OPERATION
, "glBeginQueryEXT", "query already in progress");
11717 return error::kNoError
;
11720 if (client_id
== 0) {
11721 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glBeginQueryEXT", "id is 0");
11722 return error::kNoError
;
11725 QueryManager::Query
* query
= query_manager_
->GetQuery(client_id
);
11727 if (!query_manager_
->IsValidQuery(client_id
)) {
11728 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11730 "id not made by glGenQueriesEXT");
11731 return error::kNoError
;
11733 query
= query_manager_
->CreateQuery(
11734 target
, client_id
, sync_shm_id
, sync_shm_offset
);
11737 if (query
->target() != target
) {
11738 LOCAL_SET_GL_ERROR(
11739 GL_INVALID_OPERATION
, "glBeginQueryEXT", "target does not match");
11740 return error::kNoError
;
11741 } else if (query
->shm_id() != sync_shm_id
||
11742 query
->shm_offset() != sync_shm_offset
) {
11743 DLOG(ERROR
) << "Shared memory used by query not the same as before";
11744 return error::kInvalidArguments
;
11747 if (!query_manager_
->BeginQuery(query
)) {
11748 return error::kOutOfBounds
;
11751 return error::kNoError
;
11754 error::Error
GLES2DecoderImpl::HandleEndQueryEXT(uint32 immediate_data_size
,
11755 const void* cmd_data
) {
11756 const gles2::cmds::EndQueryEXT
& c
=
11757 *static_cast<const gles2::cmds::EndQueryEXT
*>(cmd_data
);
11758 GLenum target
= static_cast<GLenum
>(c
.target
);
11759 uint32 submit_count
= static_cast<GLuint
>(c
.submit_count
);
11761 QueryManager::Query
* query
= query_manager_
->GetActiveQuery(target
);
11763 LOCAL_SET_GL_ERROR(
11764 GL_INVALID_OPERATION
, "glEndQueryEXT", "No active query");
11765 return error::kNoError
;
11768 if (!query_manager_
->EndQuery(query
, submit_count
)) {
11769 return error::kOutOfBounds
;
11772 query_manager_
->ProcessPendingTransferQueries();
11774 return error::kNoError
;
11777 error::Error
GLES2DecoderImpl::HandleQueryCounterEXT(uint32 immediate_data_size
,
11778 const void* cmd_data
) {
11779 const gles2::cmds::QueryCounterEXT
& c
=
11780 *static_cast<const gles2::cmds::QueryCounterEXT
*>(cmd_data
);
11781 GLuint client_id
= static_cast<GLuint
>(c
.id
);
11782 GLenum target
= static_cast<GLenum
>(c
.target
);
11783 int32 sync_shm_id
= static_cast<int32
>(c
.sync_data_shm_id
);
11784 uint32 sync_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
11785 uint32 submit_count
= static_cast<GLuint
>(c
.submit_count
);
11789 if (!query_manager_
->GPUTimingAvailable()) {
11790 LOCAL_SET_GL_ERROR(
11791 GL_INVALID_OPERATION
, "glQueryCounterEXT",
11792 "not enabled for timing queries");
11793 return error::kNoError
;
11797 LOCAL_SET_GL_ERROR(
11798 GL_INVALID_ENUM
, "glQueryCounterEXT",
11799 "unknown query target");
11800 return error::kNoError
;
11803 QueryManager::Query
* query
= query_manager_
->GetQuery(client_id
);
11805 if (!query_manager_
->IsValidQuery(client_id
)) {
11806 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11807 "glQueryCounterEXT",
11808 "id not made by glGenQueriesEXT");
11809 return error::kNoError
;
11811 query
= query_manager_
->CreateQuery(
11812 target
, client_id
, sync_shm_id
, sync_shm_offset
);
11814 if (!query_manager_
->QueryCounter(query
, submit_count
)) {
11815 return error::kOutOfBounds
;
11818 return error::kNoError
;
11821 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
11822 GLsizei n
, const GLuint
* client_ids
) {
11823 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11824 if (GetVertexAttribManager(client_ids
[ii
])) {
11829 if (!features().native_vertex_array_object
) {
11831 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11832 CreateVertexAttribManager(client_ids
[ii
], 0, true);
11835 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
11837 glGenVertexArraysOES(n
, service_ids
.get());
11838 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11839 CreateVertexAttribManager(client_ids
[ii
], service_ids
[ii
], true);
11846 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
11847 GLsizei n
, const GLuint
* client_ids
) {
11848 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11849 VertexAttribManager
* vao
=
11850 GetVertexAttribManager(client_ids
[ii
]);
11851 if (vao
&& !vao
->IsDeleted()) {
11852 if (state_
.vertex_attrib_manager
.get() == vao
) {
11853 DoBindVertexArrayOES(0);
11855 RemoveVertexAttribManager(client_ids
[ii
]);
11860 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id
) {
11861 VertexAttribManager
* vao
= NULL
;
11862 if (client_id
!= 0) {
11863 vao
= GetVertexAttribManager(client_id
);
11865 // Unlike most Bind* methods, the spec explicitly states that VertexArray
11866 // only allows names that have been previously generated. As such, we do
11867 // not generate new names here.
11868 LOCAL_SET_GL_ERROR(
11869 GL_INVALID_OPERATION
,
11870 "glBindVertexArrayOES", "bad vertex array id.");
11871 current_decoder_error_
= error::kNoError
;
11875 vao
= state_
.default_vertex_attrib_manager
.get();
11878 // Only set the VAO state if it's changed
11879 if (state_
.vertex_attrib_manager
.get() != vao
) {
11880 state_
.vertex_attrib_manager
= vao
;
11881 if (!features().native_vertex_array_object
) {
11882 EmulateVertexArrayState();
11884 GLuint service_id
= vao
->service_id();
11885 glBindVertexArrayOES(service_id
);
11890 // Used when OES_vertex_array_object isn't natively supported
11891 void GLES2DecoderImpl::EmulateVertexArrayState() {
11892 // Setup the Vertex attribute state
11893 for (uint32 vv
= 0; vv
< group_
->max_vertex_attribs(); ++vv
) {
11894 RestoreStateForAttrib(vv
, true);
11897 // Setup the element buffer
11898 Buffer
* element_array_buffer
=
11899 state_
.vertex_attrib_manager
->element_array_buffer();
11900 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
11901 element_array_buffer
? element_array_buffer
->service_id() : 0);
11904 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id
) {
11905 const VertexAttribManager
* vao
=
11906 GetVertexAttribManager(client_id
);
11907 return vao
&& vao
->IsValid() && !vao
->IsDeleted();
11910 bool GLES2DecoderImpl::DoIsPathCHROMIUM(GLuint client_id
) {
11911 GLuint service_id
= 0;
11912 return path_manager()->GetPath(client_id
, &service_id
) &&
11913 glIsPathNV(service_id
) == GL_TRUE
;
11916 #if defined(OS_MACOSX)
11917 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id
) {
11918 TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.find(
11920 if (it
!= texture_to_io_surface_map_
.end()) {
11921 // Found a previous IOSurface bound to this texture; release it.
11922 IOSurfaceRef surface
= it
->second
;
11923 CFRelease(surface
);
11924 texture_to_io_surface_map_
.erase(it
);
11929 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
11930 GLenum target
, GLsizei width
, GLsizei height
,
11931 GLuint io_surface_id
, GLuint plane
) {
11932 #if defined(OS_MACOSX)
11933 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL
) {
11934 LOCAL_SET_GL_ERROR(
11935 GL_INVALID_OPERATION
,
11936 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
11940 if (target
!= GL_TEXTURE_RECTANGLE_ARB
) {
11941 // This might be supported in the future, and if we could require
11942 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
11943 // could delete a lot of code. For now, perform strict validation so we
11944 // know what's going on.
11945 LOCAL_SET_GL_ERROR(
11946 GL_INVALID_OPERATION
,
11947 "glTexImageIOSurface2DCHROMIUM",
11948 "requires TEXTURE_RECTANGLE_ARB target");
11952 // Default target might be conceptually valid, but disallow it to avoid
11954 TextureRef
* texture_ref
=
11955 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
11956 if (!texture_ref
) {
11957 LOCAL_SET_GL_ERROR(
11958 GL_INVALID_OPERATION
,
11959 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
11963 // Look up the new IOSurface. Note that because of asynchrony
11964 // between processes this might fail; during live resizing the
11965 // plugin process might allocate and release an IOSurface before
11966 // this process gets a chance to look it up. Hold on to any old
11967 // IOSurface in this case.
11968 IOSurfaceRef surface
= IOSurfaceLookup(io_surface_id
);
11970 LOCAL_SET_GL_ERROR(
11971 GL_INVALID_OPERATION
,
11972 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
11976 // Release any IOSurface previously bound to this texture.
11977 ReleaseIOSurfaceForTexture(texture_ref
->service_id());
11979 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
11980 texture_to_io_surface_map_
.insert(
11981 std::make_pair(texture_ref
->service_id(), surface
));
11983 CGLContextObj context
=
11984 static_cast<CGLContextObj
>(context_
->GetHandle());
11986 CGLError err
= CGLTexImageIOSurface2D(
11993 GL_UNSIGNED_INT_8_8_8_8_REV
,
11997 if (err
!= kCGLNoError
) {
11998 LOCAL_SET_GL_ERROR(
11999 GL_INVALID_OPERATION
,
12000 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
12004 texture_manager()->SetLevelInfo(
12005 texture_ref
, target
, 0, GL_RGBA
, width
, height
, 1, 0, GL_BGRA
,
12006 GL_UNSIGNED_INT_8_8_8_8_REV
, gfx::Rect(width
, height
));
12009 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12010 "glTexImageIOSurface2DCHROMIUM", "not supported.");
12014 static GLenum
ExtractFormatFromStorageFormat(GLenum internalformat
) {
12015 switch (internalformat
) {
12027 return GL_RED_INTEGER
;
12039 return GL_RG_INTEGER
;
12040 case GL_ATC_RGB_AMD
:
12041 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
12042 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
12043 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
12044 case GL_ETC1_RGB8_OES
:
12046 case GL_R11F_G11F_B10F
:
12048 case GL_RGB8_SNORM
:
12059 return GL_RGB_INTEGER
;
12060 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
12061 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
12062 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
:
12063 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
12064 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
12065 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
12066 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
12068 case GL_SRGB8_ALPHA8
:
12069 case GL_RGBA8_SNORM
:
12078 case GL_RGB10_A2UI
:
12083 return GL_RGBA_INTEGER
;
12084 case GL_DEPTH_COMPONENT16
:
12085 case GL_DEPTH_COMPONENT24
:
12086 case GL_DEPTH_COMPONENT32F
:
12087 return GL_DEPTH_COMPONENT
;
12088 case GL_DEPTH24_STENCIL8
:
12089 case GL_DEPTH32F_STENCIL8
:
12090 return GL_DEPTH_STENCIL
;
12091 case GL_LUMINANCE8_ALPHA8_EXT
:
12092 return GL_LUMINANCE_ALPHA
;
12093 case GL_LUMINANCE8_EXT
:
12094 return GL_LUMINANCE
;
12095 case GL_ALPHA8_EXT
:
12097 case GL_ALPHA32F_EXT
:
12099 case GL_LUMINANCE32F_EXT
:
12100 return GL_LUMINANCE
;
12101 case GL_LUMINANCE_ALPHA32F_EXT
:
12102 return GL_LUMINANCE_ALPHA
;
12103 case GL_ALPHA16F_EXT
:
12105 case GL_LUMINANCE16F_EXT
:
12106 return GL_LUMINANCE
;
12107 case GL_LUMINANCE_ALPHA16F_EXT
:
12108 return GL_LUMINANCE_ALPHA
;
12110 return GL_BGRA_EXT
;
12116 bool GLES2DecoderImpl::ValidateCopyTextureCHROMIUM(
12117 const char* function_name
,
12119 TextureRef
* source_texture_ref
,
12120 TextureRef
* dest_texture_ref
,
12121 GLenum dest_internal_format
) {
12122 if (!source_texture_ref
|| !dest_texture_ref
) {
12123 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown texture id");
12127 if (GL_TEXTURE_2D
!= target
) {
12128 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
12129 "invalid texture target");
12133 Texture
* source_texture
= source_texture_ref
->texture();
12134 Texture
* dest_texture
= dest_texture_ref
->texture();
12135 if (source_texture
== dest_texture
) {
12136 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
12137 "source and destination textures are the same");
12141 if (dest_texture
->target() != GL_TEXTURE_2D
||
12142 (source_texture
->target() != GL_TEXTURE_2D
&&
12143 source_texture
->target() != GL_TEXTURE_RECTANGLE_ARB
&&
12144 source_texture
->target() != GL_TEXTURE_EXTERNAL_OES
)) {
12145 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
12146 "invalid texture target binding");
12150 GLenum source_type
= 0;
12151 GLenum source_internal_format
= 0;
12152 source_texture
->GetLevelType(source_texture
->target(), 0, &source_type
,
12153 &source_internal_format
);
12155 // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
12156 // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
12157 // renderable on some platforms.
12158 bool valid_dest_format
= dest_internal_format
== GL_RGB
||
12159 dest_internal_format
== GL_RGBA
||
12160 dest_internal_format
== GL_BGRA_EXT
;
12161 bool valid_source_format
=
12162 source_internal_format
== GL_R8
|| source_internal_format
== GL_ALPHA
||
12163 source_internal_format
== GL_RGB
|| source_internal_format
== GL_RGBA
||
12164 source_internal_format
== GL_LUMINANCE
||
12165 source_internal_format
== GL_LUMINANCE_ALPHA
||
12166 source_internal_format
== GL_BGRA_EXT
;
12167 if (!valid_source_format
|| !valid_dest_format
) {
12168 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
12169 "invalid internal format");
12175 bool GLES2DecoderImpl::ValidateCompressedCopyTextureCHROMIUM(
12176 const char* function_name
,
12178 TextureRef
* source_texture_ref
,
12179 TextureRef
* dest_texture_ref
) {
12180 if (!source_texture_ref
|| !dest_texture_ref
) {
12181 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown texture id");
12185 if (GL_TEXTURE_2D
!= target
) {
12186 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
12187 "invalid texture target");
12191 Texture
* source_texture
= source_texture_ref
->texture();
12192 Texture
* dest_texture
= dest_texture_ref
->texture();
12193 if (source_texture
== dest_texture
) {
12194 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
12195 "source and destination textures are the same");
12199 if (dest_texture
->target() != GL_TEXTURE_2D
||
12200 (source_texture
->target() != GL_TEXTURE_2D
&&
12201 source_texture
->target() != GL_TEXTURE_RECTANGLE_ARB
&&
12202 source_texture
->target() != GL_TEXTURE_EXTERNAL_OES
)) {
12203 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
12204 "invalid texture target binding");
12208 GLenum source_type
= 0;
12209 GLenum source_internal_format
= 0;
12210 source_texture
->GetLevelType(source_texture
->target(), 0, &source_type
,
12211 &source_internal_format
);
12213 bool valid_format
=
12214 source_internal_format
== GL_ATC_RGB_AMD
||
12215 source_internal_format
== GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
||
12216 source_internal_format
== GL_COMPRESSED_RGB_S3TC_DXT1_EXT
||
12217 source_internal_format
== GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
||
12218 source_internal_format
== GL_ETC1_RGB8_OES
;
12220 if (!valid_format
) {
12221 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
12222 "invalid internal format");
12229 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
12233 GLenum internal_format
,
12235 GLboolean unpack_flip_y
,
12236 GLboolean unpack_premultiply_alpha
,
12237 GLboolean unpack_unmultiply_alpha
) {
12238 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
12240 TextureRef
* source_texture_ref
= GetTexture(source_id
);
12241 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
12242 Texture
* source_texture
= source_texture_ref
->texture();
12243 Texture
* dest_texture
= dest_texture_ref
->texture();
12244 int source_width
= 0;
12245 int source_height
= 0;
12246 gfx::GLImage
* image
=
12247 source_texture
->GetLevelImage(source_texture
->target(), 0);
12249 gfx::Size size
= image
->GetSize();
12250 source_width
= size
.width();
12251 source_height
= size
.height();
12252 if (source_width
<= 0 || source_height
<= 0) {
12253 LOCAL_SET_GL_ERROR(
12255 "glCopyTextureChromium", "invalid image size");
12259 if (!source_texture
->GetLevelSize(source_texture
->target(), 0,
12260 &source_width
, &source_height
, nullptr)) {
12261 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
12262 "glCopyTextureChromium",
12263 "source texture has no level 0");
12267 // Check that this type of texture is allowed.
12268 if (!texture_manager()->ValidForTarget(source_texture
->target(), 0,
12269 source_width
, source_height
, 1)) {
12270 LOCAL_SET_GL_ERROR(
12271 GL_INVALID_VALUE
, "glCopyTextureCHROMIUM", "Bad dimensions");
12276 GLenum source_type
= 0;
12277 GLenum source_internal_format
= 0;
12278 source_texture
->GetLevelType(
12279 source_texture
->target(), 0, &source_type
, &source_internal_format
);
12281 if (dest_texture
->IsImmutable()) {
12282 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCopyTextureCHROMIUM",
12283 "texture is immutable");
12287 if (!ValidateCopyTextureCHROMIUM("glCopyTextureCHROMIUM", target
,
12288 source_texture_ref
, dest_texture_ref
,
12289 internal_format
)) {
12293 // Clear the source texture if necessary.
12294 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref
,
12295 source_texture
->target(), 0)) {
12296 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTextureCHROMIUM",
12297 "dimensions too big");
12301 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12302 // needed because it takes 10s of milliseconds to initialize.
12303 if (!copy_texture_CHROMIUM_
.get()) {
12304 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12305 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
12306 copy_texture_CHROMIUM_
->Initialize(this);
12307 RestoreCurrentFramebufferBindings();
12308 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR
)
12312 GLenum dest_type_previous
= dest_type
;
12313 GLenum dest_internal_format
= internal_format
;
12314 int dest_width
= 0;
12315 int dest_height
= 0;
12316 bool dest_level_defined
= dest_texture
->GetLevelSize(
12317 GL_TEXTURE_2D
, 0, &dest_width
, &dest_height
, nullptr);
12319 if (dest_level_defined
) {
12320 dest_texture
->GetLevelType(GL_TEXTURE_2D
, 0, &dest_type_previous
,
12321 &dest_internal_format
);
12324 // Resize the destination texture to the dimensions of the source texture.
12325 if (!dest_level_defined
|| dest_width
!= source_width
||
12326 dest_height
!= source_height
||
12327 dest_internal_format
!= internal_format
||
12328 dest_type_previous
!= dest_type
) {
12329 // Ensure that the glTexImage2D succeeds.
12330 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12331 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
12332 glTexImage2D(GL_TEXTURE_2D
, 0, internal_format
, source_width
, source_height
,
12333 0, internal_format
, dest_type
, NULL
);
12334 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
12335 if (error
!= GL_NO_ERROR
) {
12336 RestoreCurrentTextureBindings(&state_
, GL_TEXTURE_2D
);
12340 texture_manager()->SetLevelInfo(
12341 dest_texture_ref
, GL_TEXTURE_2D
, 0, internal_format
, source_width
,
12342 source_height
, 1, 0, internal_format
, dest_type
,
12343 gfx::Rect(source_width
, source_height
));
12345 texture_manager()->SetLevelCleared(dest_texture_ref
, GL_TEXTURE_2D
, 0,
12349 ScopedModifyPixels
modify(dest_texture_ref
);
12351 // Try using GLImage::CopyTexSubImage when possible.
12352 bool unpack_premultiply_alpha_change
=
12353 (unpack_premultiply_alpha
^ unpack_unmultiply_alpha
) != 0;
12354 if (image
&& !unpack_flip_y
&& !unpack_premultiply_alpha_change
) {
12355 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
12356 if (image
->CopyTexSubImage(GL_TEXTURE_2D
, gfx::Point(0, 0),
12357 gfx::Rect(0, 0, source_width
, source_height
))) {
12362 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
12364 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
12365 // before presenting.
12366 if (source_texture
->target() == GL_TEXTURE_EXTERNAL_OES
) {
12367 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
12368 // instead of using kIdentityMatrix crbug.com/226218.
12369 copy_texture_CHROMIUM_
->DoCopyTextureWithTransform(
12370 this, source_texture
->target(), source_texture
->service_id(),
12371 dest_texture
->service_id(), source_width
, source_height
,
12372 unpack_flip_y
== GL_TRUE
,
12373 unpack_premultiply_alpha
== GL_TRUE
,
12374 unpack_unmultiply_alpha
== GL_TRUE
,
12377 copy_texture_CHROMIUM_
->DoCopyTexture(
12378 this, source_texture
->target(), source_texture
->service_id(),
12379 source_internal_format
, dest_texture
->service_id(), internal_format
,
12380 source_width
, source_height
,
12381 unpack_flip_y
== GL_TRUE
,
12382 unpack_premultiply_alpha
== GL_TRUE
,
12383 unpack_unmultiply_alpha
== GL_TRUE
);
12386 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
12389 void GLES2DecoderImpl::DoCopySubTextureCHROMIUM(
12399 GLboolean unpack_flip_y
,
12400 GLboolean unpack_premultiply_alpha
,
12401 GLboolean unpack_unmultiply_alpha
) {
12402 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopySubTextureCHROMIUM");
12404 TextureRef
* source_texture_ref
= GetTexture(source_id
);
12405 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
12406 Texture
* source_texture
= source_texture_ref
->texture();
12407 Texture
* dest_texture
= dest_texture_ref
->texture();
12408 int source_width
= 0;
12409 int source_height
= 0;
12410 gfx::GLImage
* image
=
12411 source_texture
->GetLevelImage(source_texture
->target(), 0);
12413 gfx::Size size
= image
->GetSize();
12414 source_width
= size
.width();
12415 source_height
= size
.height();
12416 if (source_width
<= 0 || source_height
<= 0) {
12417 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
12418 "invalid image size");
12422 if (!source_texture
->GetLevelSize(source_texture
->target(), 0,
12423 &source_width
, &source_height
, nullptr)) {
12424 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
12425 "source texture has no level 0");
12429 // Check that this type of texture is allowed.
12430 if (!texture_manager()->ValidForTarget(source_texture
->target(), 0,
12431 source_width
, source_height
, 1)) {
12432 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
12433 "source texture bad dimensions");
12438 GLenum source_type
= 0;
12439 GLenum source_internal_format
= 0;
12440 source_texture
->GetLevelType(source_texture
->target(), 0, &source_type
,
12441 &source_internal_format
);
12442 if (!source_texture
->ValidForTexture(source_texture
->target(), 0, x
, y
, 0,
12443 width
, height
, 1, source_type
)) {
12444 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
12445 "source texture bad dimensions.");
12449 GLenum dest_type
= 0;
12450 GLenum dest_internal_format
= 0;
12451 bool dest_level_defined
= dest_texture
->GetLevelType(
12452 dest_texture
->target(), 0, &dest_type
, &dest_internal_format
);
12453 if (!dest_level_defined
) {
12454 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCopySubTextureCHROMIUM",
12455 "destination texture is not defined");
12458 if (!dest_texture
->ValidForTexture(dest_texture
->target(), 0, xoffset
,
12459 yoffset
, 0, width
, height
, 1, dest_type
)) {
12460 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
12461 "destination texture bad dimensions.");
12465 if (!ValidateCopyTextureCHROMIUM("glCopySubTextureCHROMIUM", target
,
12466 source_texture_ref
, dest_texture_ref
,
12467 dest_internal_format
)) {
12471 // Clear the source texture if necessary.
12472 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref
,
12473 source_texture
->target(), 0)) {
12474 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopySubTextureCHROMIUM",
12475 "source texture dimensions too big");
12479 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12480 // needed because it takes 10s of milliseconds to initialize.
12481 if (!copy_texture_CHROMIUM_
.get()) {
12482 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopySubTextureCHROMIUM");
12483 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
12484 copy_texture_CHROMIUM_
->Initialize(this);
12485 RestoreCurrentFramebufferBindings();
12486 if (LOCAL_PEEK_GL_ERROR("glCopySubTextureCHROMIUM") != GL_NO_ERROR
)
12490 int dest_width
= 0;
12491 int dest_height
= 0;
12492 bool ok
= dest_texture
->GetLevelSize(
12493 GL_TEXTURE_2D
, 0, &dest_width
, &dest_height
, nullptr);
12495 if (xoffset
!= 0 || yoffset
!= 0 || width
!= dest_width
||
12496 height
!= dest_height
) {
12497 gfx::Rect cleared_rect
;
12498 if (CombineAdjacentRects(dest_texture
->GetLevelClearedRect(target
, 0),
12499 gfx::Rect(xoffset
, yoffset
, width
, height
),
12501 DCHECK_GE(cleared_rect
.size().GetArea(),
12502 dest_texture
->GetLevelClearedRect(target
, 0).size().GetArea());
12503 texture_manager()->SetLevelClearedRect(dest_texture_ref
, target
, 0,
12506 // Otherwise clear part of texture level that is not already cleared.
12507 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref
, target
,
12509 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopySubTextureCHROMIUM",
12510 "destination texture dimensions too big");
12515 texture_manager()->SetLevelCleared(dest_texture_ref
, GL_TEXTURE_2D
, 0,
12519 ScopedModifyPixels
modify(dest_texture_ref
);
12521 // Try using GLImage::CopyTexSubImage when possible.
12522 bool unpack_premultiply_alpha_change
=
12523 (unpack_premultiply_alpha
^ unpack_unmultiply_alpha
) != 0;
12524 if (image
&& !unpack_flip_y
&& !unpack_premultiply_alpha_change
) {
12525 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
12526 if (image
->CopyTexSubImage(GL_TEXTURE_2D
, gfx::Point(xoffset
, yoffset
),
12527 gfx::Rect(x
, y
, width
, height
))) {
12532 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
12534 // TODO(hkuang): get the StreamTexture transform matrix in GPU process.
12535 // crbug.com/226218.
12536 copy_texture_CHROMIUM_
->DoCopySubTexture(
12537 this, source_texture
->target(), source_texture
->service_id(),
12538 source_internal_format
, dest_texture
->service_id(), dest_internal_format
,
12539 xoffset
, yoffset
, x
, y
, width
, height
, dest_width
, dest_height
,
12540 source_width
, source_height
,
12541 unpack_flip_y
== GL_TRUE
,
12542 unpack_premultiply_alpha
== GL_TRUE
,
12543 unpack_unmultiply_alpha
== GL_TRUE
);
12545 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
12548 void GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM(GLenum target
,
12551 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM");
12553 TextureRef
* source_texture_ref
= GetTexture(source_id
);
12554 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
12555 Texture
* source_texture
= source_texture_ref
->texture();
12556 Texture
* dest_texture
= dest_texture_ref
->texture();
12557 int source_width
= 0;
12558 int source_height
= 0;
12559 gfx::GLImage
* image
=
12560 source_texture
->GetLevelImage(source_texture
->target(), 0);
12562 gfx::Size size
= image
->GetSize();
12563 source_width
= size
.width();
12564 source_height
= size
.height();
12565 if (source_width
<= 0 || source_height
<= 0) {
12566 LOCAL_SET_GL_ERROR(
12568 "glCompressedCopyTextureCHROMIUM", "invalid image size");
12572 if (!source_texture
->GetLevelSize(source_texture
->target(), 0,
12573 &source_width
, &source_height
, nullptr)) {
12574 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
12575 "glCompressedCopyTextureCHROMIUM",
12576 "source texture has no level 0");
12580 // Check that this type of texture is allowed.
12581 if (!texture_manager()->ValidForTarget(source_texture
->target(), 0,
12582 source_width
, source_height
, 1)) {
12583 LOCAL_SET_GL_ERROR(
12584 GL_INVALID_VALUE
, "glCompressedCopyTextureCHROMIUM",
12590 GLenum source_type
= 0;
12591 GLenum source_internal_format
= 0;
12592 source_texture
->GetLevelType(
12593 source_texture
->target(), 0, &source_type
, &source_internal_format
);
12595 if (dest_texture
->IsImmutable()) {
12596 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12597 "glCompressedCopyTextureCHROMIUM",
12598 "texture is immutable");
12602 if (!ValidateCompressedCopyTextureCHROMIUM(
12603 "glCompressedCopyTextureCHROMIUM",
12605 source_texture_ref
, dest_texture_ref
)) {
12609 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12610 // needed because it takes 10s of milliseconds to initialize.
12611 if (!copy_texture_CHROMIUM_
.get()) {
12612 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12613 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
12614 copy_texture_CHROMIUM_
->Initialize(this);
12615 RestoreCurrentFramebufferBindings();
12616 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR
)
12620 // Clear the source texture if necessary.
12621 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref
,
12622 source_texture
->target(), 0)) {
12623 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCompressedCopyTextureCHROMIUM",
12624 "dimensions too big");
12628 ScopedTextureBinder
binder(
12629 &state_
, dest_texture
->service_id(), GL_TEXTURE_2D
);
12631 ScopedModifyPixels
modify(dest_texture_ref
);
12633 // Try using GLImage::CopyTexImage when possible.
12635 GLenum dest_type
= 0;
12636 GLenum dest_internal_format
= 0;
12637 int dest_width
= 0;
12638 int dest_height
= 0;
12639 bool dest_level_defined
= dest_texture
->GetLevelSize(
12640 GL_TEXTURE_2D
, 0, &dest_width
, &dest_height
, nullptr);
12642 if (dest_level_defined
) {
12643 dest_texture
->GetLevelType(GL_TEXTURE_2D
, 0, &dest_type
,
12644 &dest_internal_format
);
12647 // Resize the destination texture to the dimensions of the source texture.
12648 if (!dest_level_defined
|| dest_width
!= source_width
||
12649 dest_height
!= source_height
||
12650 dest_internal_format
!= source_internal_format
) {
12651 GLsizei source_size
= 0;
12653 bool did_get_size
= GetCompressedTexSizeInBytes(
12654 "glCompressedCopyTextureCHROMIUM", source_width
, source_height
,
12655 1, source_internal_format
, &source_size
);
12656 DCHECK(did_get_size
);
12658 // Ensure that the glCompressedTexImage2D succeeds.
12659 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
12660 glCompressedTexImage2D(GL_TEXTURE_2D
, 0, source_internal_format
,
12661 source_width
, source_height
, 0, source_size
,
12663 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedCopyTextureCHROMIUM");
12664 if (error
!= GL_NO_ERROR
) {
12665 RestoreCurrentTextureBindings(&state_
, GL_TEXTURE_2D
);
12669 texture_manager()->SetLevelInfo(
12670 dest_texture_ref
, GL_TEXTURE_2D
, 0, source_internal_format
,
12671 source_width
, source_height
, 1, 0, source_internal_format
,
12672 source_type
, gfx::Rect(source_width
, source_height
));
12674 texture_manager()->SetLevelCleared(dest_texture_ref
, GL_TEXTURE_2D
, 0,
12678 if (image
->CopyTexSubImage(GL_TEXTURE_2D
, gfx::Point(0, 0),
12679 gfx::Rect(0, 0, source_width
, source_height
))) {
12686 "GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM, fallback");
12688 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
12690 // As a fallback, copy into a non-compressed GL_RGBA texture.
12691 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
12692 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, source_width
, source_height
,
12693 0, GL_RGBA
, GL_UNSIGNED_BYTE
, NULL
);
12694 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedCopyTextureCHROMIUM");
12695 if (error
!= GL_NO_ERROR
) {
12696 RestoreCurrentTextureBindings(&state_
, GL_TEXTURE_2D
);
12700 texture_manager()->SetLevelInfo(
12701 dest_texture_ref
, GL_TEXTURE_2D
, 0, GL_RGBA
, source_width
,
12702 source_height
, 1, 0, GL_RGBA
, GL_UNSIGNED_BYTE
,
12703 gfx::Rect(source_width
, source_height
));
12705 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
12706 // before presenting.
12707 if (source_texture
->target() == GL_TEXTURE_EXTERNAL_OES
) {
12708 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
12709 // instead of using kIdentityMatrix crbug.com/226218.
12710 copy_texture_CHROMIUM_
->DoCopyTextureWithTransform(
12711 this, source_texture
->target(), source_texture
->service_id(),
12712 dest_texture
->service_id(), source_width
, source_height
,
12713 false, false, false, kIdentityMatrix
);
12715 copy_texture_CHROMIUM_
->DoCopyTexture(
12716 this, source_texture
->target(), source_texture
->service_id(),
12717 source_internal_format
, dest_texture
->service_id(), GL_RGBA
,
12718 source_width
, source_height
, false, false, false);
12721 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
12724 static GLenum
ExtractTypeFromStorageFormat(GLenum internalformat
) {
12725 switch (internalformat
) {
12727 return GL_UNSIGNED_BYTE
;
12731 return GL_HALF_FLOAT
;
12735 return GL_UNSIGNED_BYTE
;
12739 return GL_UNSIGNED_SHORT
;
12743 return GL_UNSIGNED_INT
;
12747 return GL_UNSIGNED_BYTE
;
12751 return GL_HALF_FLOAT
;
12755 return GL_UNSIGNED_BYTE
;
12759 return GL_UNSIGNED_SHORT
;
12763 return GL_UNSIGNED_INT
;
12768 return GL_UNSIGNED_BYTE
;
12769 case GL_R11F_G11F_B10F
:
12770 return GL_UNSIGNED_INT_10F_11F_11F_REV
;
12772 return GL_UNSIGNED_SHORT_5_6_5
;
12773 case GL_RGB8_SNORM
:
12776 return GL_UNSIGNED_INT_5_9_9_9_REV
;
12778 return GL_HALF_FLOAT
;
12782 return GL_UNSIGNED_BYTE
;
12786 return GL_UNSIGNED_SHORT
;
12790 return GL_UNSIGNED_INT
;
12794 return GL_UNSIGNED_BYTE
;
12795 case GL_SRGB8_ALPHA8
:
12796 return GL_UNSIGNED_BYTE
;
12797 case GL_RGBA8_SNORM
:
12800 return GL_UNSIGNED_SHORT_4_4_4_4
;
12802 return GL_UNSIGNED_INT_2_10_10_10_REV
;
12804 return GL_UNSIGNED_SHORT_5_5_5_1
;
12806 return GL_HALF_FLOAT
;
12810 return GL_UNSIGNED_BYTE
;
12813 case GL_RGB10_A2UI
:
12814 return GL_UNSIGNED_INT_2_10_10_10_REV
;
12816 return GL_UNSIGNED_SHORT
;
12822 return GL_UNSIGNED_INT
;
12823 case GL_DEPTH_COMPONENT16
:
12824 return GL_UNSIGNED_SHORT
;
12825 case GL_DEPTH_COMPONENT24
:
12826 return GL_UNSIGNED_INT
;
12827 case GL_DEPTH_COMPONENT32F
:
12829 case GL_DEPTH24_STENCIL8
:
12830 return GL_UNSIGNED_INT_24_8
;
12831 case GL_DEPTH32F_STENCIL8
:
12832 return GL_FLOAT_32_UNSIGNED_INT_24_8_REV
;
12833 case GL_LUMINANCE8_ALPHA8_EXT
:
12834 return GL_UNSIGNED_BYTE
;
12835 case GL_LUMINANCE8_EXT
:
12836 return GL_UNSIGNED_BYTE
;
12837 case GL_ALPHA8_EXT
:
12838 return GL_UNSIGNED_BYTE
;
12839 case GL_ALPHA32F_EXT
:
12841 case GL_LUMINANCE32F_EXT
:
12843 case GL_LUMINANCE_ALPHA32F_EXT
:
12845 case GL_ALPHA16F_EXT
:
12846 return GL_HALF_FLOAT_OES
;
12847 case GL_LUMINANCE16F_EXT
:
12848 return GL_HALF_FLOAT_OES
;
12849 case GL_LUMINANCE_ALPHA16F_EXT
:
12850 return GL_HALF_FLOAT_OES
;
12852 return GL_UNSIGNED_BYTE
;
12858 void GLES2DecoderImpl::DoTexStorage2DEXT(
12861 GLenum internal_format
,
12864 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
12865 "width", width
, "height", height
);
12866 if (!texture_manager()->ValidForTarget(target
, 0, width
, height
, 1) ||
12867 TextureManager::ComputeMipMapCount(target
, width
, height
, 1) < levels
) {
12868 LOCAL_SET_GL_ERROR(
12869 GL_INVALID_VALUE
, "glTexStorage2DEXT", "dimensions out of range");
12872 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
12874 if (!texture_ref
) {
12875 LOCAL_SET_GL_ERROR(
12876 GL_INVALID_OPERATION
,
12877 "glTexStorage2DEXT", "unknown texture for target");
12880 Texture
* texture
= texture_ref
->texture();
12881 if (texture
->IsAttachedToFramebuffer()) {
12882 framebuffer_state_
.clear_state_dirty
= true;
12884 if (texture
->IsImmutable()) {
12885 LOCAL_SET_GL_ERROR(
12886 GL_INVALID_OPERATION
,
12887 "glTexStorage2DEXT", "texture is immutable");
12891 GLenum format
= ExtractFormatFromStorageFormat(internal_format
);
12892 GLenum type
= ExtractTypeFromStorageFormat(internal_format
);
12895 GLsizei level_width
= width
;
12896 GLsizei level_height
= height
;
12897 uint32 estimated_size
= 0;
12898 for (int ii
= 0; ii
< levels
; ++ii
) {
12899 uint32 level_size
= 0;
12900 if (!GLES2Util::ComputeImageDataSizes(
12901 level_width
, level_height
, 1, format
, type
, state_
.unpack_alignment
,
12902 &estimated_size
, NULL
, NULL
) ||
12903 !SafeAddUint32(estimated_size
, level_size
, &estimated_size
)) {
12904 LOCAL_SET_GL_ERROR(
12905 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "dimensions too large");
12908 level_width
= std::max(1, level_width
>> 1);
12909 level_height
= std::max(1, level_height
>> 1);
12911 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
12912 LOCAL_SET_GL_ERROR(
12913 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "out of memory");
12918 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
12919 glTexStorage2DEXT(target
, levels
, internal_format
, width
, height
);
12920 GLenum error
= LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
12921 if (error
== GL_NO_ERROR
) {
12922 GLsizei level_width
= width
;
12923 GLsizei level_height
= height
;
12925 GLenum cur_format
= feature_info_
->IsES3Enabled() ?
12926 internal_format
: format
;
12927 for (int ii
= 0; ii
< levels
; ++ii
) {
12928 if (target
== GL_TEXTURE_CUBE_MAP
) {
12929 for (int jj
= 0; jj
< 6; ++jj
) {
12930 GLenum face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ jj
;
12931 texture_manager()->SetLevelInfo(texture_ref
, face
, ii
, cur_format
,
12932 level_width
, level_height
, 1, 0,
12933 format
, type
, gfx::Rect());
12936 texture_manager()->SetLevelInfo(texture_ref
, target
, ii
, cur_format
,
12937 level_width
, level_height
, 1, 0,
12938 format
, type
, gfx::Rect());
12940 level_width
= std::max(1, level_width
>> 1);
12941 level_height
= std::max(1, level_height
>> 1);
12943 texture
->SetImmutable(true);
12947 error::Error
GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
12948 uint32 immediate_data_size
,
12949 const void* cmd_data
) {
12950 return error::kUnknownCommand
;
12953 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target
,
12954 const GLbyte
* data
) {
12955 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
12956 "context", logger_
.GetLogPrefix(),
12957 "mailbox[0]", static_cast<unsigned char>(data
[0]));
12959 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
12961 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref
, target
, data
);
12964 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id
,
12965 GLenum target
, const GLbyte
* data
) {
12966 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
12967 "context", logger_
.GetLogPrefix(),
12968 "mailbox[0]", static_cast<unsigned char>(data
[0]));
12970 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id
),
12974 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name
,
12975 TextureRef
* texture_ref
, GLenum target
, const GLbyte
* data
) {
12976 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
12977 DLOG_IF(ERROR
, !mailbox
.Verify()) << func_name
<< " was passed a "
12978 "mailbox that was not generated by "
12979 "GenMailboxCHROMIUM.";
12981 if (!texture_ref
) {
12982 LOCAL_SET_GL_ERROR(
12983 GL_INVALID_OPERATION
, func_name
.c_str(), "unknown texture for target");
12987 Texture
* produced
= texture_manager()->Produce(texture_ref
);
12989 LOCAL_SET_GL_ERROR(
12990 GL_INVALID_OPERATION
, func_name
.c_str(), "invalid texture");
12994 if (produced
->target() != target
) {
12995 LOCAL_SET_GL_ERROR(
12996 GL_INVALID_OPERATION
, func_name
.c_str(), "invalid target");
13000 group_
->mailbox_manager()->ProduceTexture(mailbox
, produced
);
13003 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target
,
13004 const GLbyte
* data
) {
13005 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
13006 "context", logger_
.GetLogPrefix(),
13007 "mailbox[0]", static_cast<unsigned char>(data
[0]));
13008 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
13009 DLOG_IF(ERROR
, !mailbox
.Verify()) << "ConsumeTextureCHROMIUM was passed a "
13010 "mailbox that was not generated by "
13011 "GenMailboxCHROMIUM.";
13013 scoped_refptr
<TextureRef
> texture_ref
=
13014 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
13015 if (!texture_ref
.get()) {
13016 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
13017 "glConsumeTextureCHROMIUM",
13018 "unknown texture for target");
13021 GLuint client_id
= texture_ref
->client_id();
13023 LOCAL_SET_GL_ERROR(
13024 GL_INVALID_OPERATION
,
13025 "glConsumeTextureCHROMIUM", "unknown texture for target");
13028 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(mailbox
);
13030 LOCAL_SET_GL_ERROR(
13031 GL_INVALID_OPERATION
,
13032 "glConsumeTextureCHROMIUM", "invalid mailbox name");
13035 if (texture
->target() != target
) {
13036 LOCAL_SET_GL_ERROR(
13037 GL_INVALID_OPERATION
,
13038 "glConsumeTextureCHROMIUM", "invalid target");
13042 DeleteTexturesHelper(1, &client_id
);
13043 texture_ref
= texture_manager()->Consume(client_id
, texture
);
13044 glBindTexture(target
, texture_ref
->service_id());
13046 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
13047 unit
.bind_target
= target
;
13049 case GL_TEXTURE_2D
:
13050 unit
.bound_texture_2d
= texture_ref
;
13052 case GL_TEXTURE_CUBE_MAP
:
13053 unit
.bound_texture_cube_map
= texture_ref
;
13055 case GL_TEXTURE_EXTERNAL_OES
:
13056 unit
.bound_texture_external_oes
= texture_ref
;
13058 case GL_TEXTURE_RECTANGLE_ARB
:
13059 unit
.bound_texture_rectangle_arb
= texture_ref
;
13062 NOTREACHED(); // Validation should prevent us getting here.
13067 void GLES2DecoderImpl::EnsureTextureForClientId(
13069 GLuint client_id
) {
13070 TextureRef
* texture_ref
= GetTexture(client_id
);
13071 if (!texture_ref
) {
13073 glGenTextures(1, &service_id
);
13074 DCHECK_NE(0u, service_id
);
13075 texture_ref
= CreateTexture(client_id
, service_id
);
13076 texture_manager()->SetTarget(texture_ref
, target
);
13077 glBindTexture(target
, service_id
);
13078 RestoreCurrentTextureBindings(&state_
, target
);
13082 // If CreateAndConsumeTexture fails we still need to ensure that the client_id
13083 // provided is associated with a service_id/TextureRef for consistency, even if
13084 // the resulting texture is incomplete.
13085 error::Error
GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
13086 uint32_t immediate_data_size
,
13087 const void* cmd_data
) {
13088 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate
& c
=
13090 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate
*>(
13092 GLenum target
= static_cast<GLenum
>(c
.target
);
13093 uint32_t data_size
;
13094 if (!ComputeDataSize(1, sizeof(GLbyte
), 64, &data_size
)) {
13095 return error::kOutOfBounds
;
13097 if (data_size
> immediate_data_size
) {
13098 return error::kOutOfBounds
;
13100 const GLbyte
* mailbox
=
13101 GetImmediateDataAs
<const GLbyte
*>(c
, data_size
, immediate_data_size
);
13102 if (!validators_
->texture_bind_target
.IsValid(target
)) {
13103 LOCAL_SET_GL_ERROR_INVALID_ENUM(
13104 "glCreateAndConsumeTextureCHROMIUM", target
, "target");
13105 return error::kNoError
;
13107 if (mailbox
== NULL
) {
13108 return error::kOutOfBounds
;
13110 uint32_t client_id
= c
.client_id
;
13111 DoCreateAndConsumeTextureCHROMIUM(target
, mailbox
, client_id
);
13112 return error::kNoError
;
13115 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target
,
13116 const GLbyte
* data
, GLuint client_id
) {
13117 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
13118 "context", logger_
.GetLogPrefix(),
13119 "mailbox[0]", static_cast<unsigned char>(data
[0]));
13120 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
13121 DLOG_IF(ERROR
, !mailbox
.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
13122 "passed a mailbox that was not "
13123 "generated by GenMailboxCHROMIUM.";
13125 TextureRef
* texture_ref
= GetTexture(client_id
);
13127 // No need to call EnsureTextureForClientId here, the client_id already has
13128 // an associated texture.
13129 LOCAL_SET_GL_ERROR(
13130 GL_INVALID_OPERATION
,
13131 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
13134 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(mailbox
);
13136 EnsureTextureForClientId(target
, client_id
);
13137 LOCAL_SET_GL_ERROR(
13138 GL_INVALID_OPERATION
,
13139 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
13143 if (texture
->target() != target
) {
13144 EnsureTextureForClientId(target
, client_id
);
13145 LOCAL_SET_GL_ERROR(
13146 GL_INVALID_OPERATION
,
13147 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
13151 texture_ref
= texture_manager()->Consume(client_id
, texture
);
13154 bool GLES2DecoderImpl::DoIsValuebufferCHROMIUM(GLuint client_id
) {
13155 const Valuebuffer
* valuebuffer
= GetValuebuffer(client_id
);
13156 return valuebuffer
&& valuebuffer
->IsValid();
13159 void GLES2DecoderImpl::DoBindValueBufferCHROMIUM(GLenum target
,
13160 GLuint client_id
) {
13161 Valuebuffer
* valuebuffer
= NULL
;
13162 if (client_id
!= 0) {
13163 valuebuffer
= GetValuebuffer(client_id
);
13164 if (!valuebuffer
) {
13165 if (!group_
->bind_generates_resource()) {
13166 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glBindValuebufferCHROMIUM",
13167 "id not generated by glBindValuebufferCHROMIUM");
13171 // It's a new id so make a valuebuffer for it.
13172 CreateValuebuffer(client_id
);
13173 valuebuffer
= GetValuebuffer(client_id
);
13175 valuebuffer
->MarkAsValid();
13177 state_
.bound_valuebuffer
= valuebuffer
;
13180 void GLES2DecoderImpl::DoSubscribeValueCHROMIUM(GLenum target
,
13181 GLenum subscription
) {
13182 if (!CheckCurrentValuebuffer("glSubscribeValueCHROMIUM")) {
13185 state_
.bound_valuebuffer
.get()->AddSubscription(subscription
);
13188 void GLES2DecoderImpl::DoPopulateSubscribedValuesCHROMIUM(GLenum target
) {
13189 if (!CheckCurrentValuebuffer("glPopulateSubscribedValuesCHROMIUM")) {
13192 valuebuffer_manager()->UpdateValuebufferState(state_
.bound_valuebuffer
.get());
13195 void GLES2DecoderImpl::DoUniformValueBufferCHROMIUM(GLint location
,
13197 GLenum subscription
) {
13198 if (!CheckCurrentValuebufferForSubscription(
13199 subscription
, "glPopulateSubscribedValuesCHROMIUM")) {
13202 if (!CheckSubscriptionTarget(location
, subscription
,
13203 "glPopulateSubscribedValuesCHROMIUM")) {
13206 const ValueState
* state
=
13207 state_
.bound_valuebuffer
.get()->GetState(subscription
);
13209 switch (subscription
) {
13210 case GL_MOUSE_POSITION_CHROMIUM
:
13211 DoUniform2iv(location
, 1, state
->int_value
);
13214 NOTREACHED() << "Unhandled uniform subscription target "
13221 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
13222 GLsizei length
, const GLchar
* marker
) {
13226 debug_marker_manager_
.SetMarker(
13227 length
? std::string(marker
, length
) : std::string(marker
));
13230 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
13231 GLsizei
/*length*/, const GLchar
* /*marker*/) {
13234 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
13237 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
13238 GLenum target
, GLint image_id
) {
13239 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
13241 if (target
== GL_TEXTURE_CUBE_MAP
) {
13242 LOCAL_SET_GL_ERROR(
13244 "glBindTexImage2DCHROMIUM", "invalid target");
13248 // Default target might be conceptually valid, but disallow it to avoid
13250 TextureRef
* texture_ref
=
13251 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
13252 if (!texture_ref
) {
13253 LOCAL_SET_GL_ERROR(
13254 GL_INVALID_OPERATION
,
13255 "glBindTexImage2DCHROMIUM", "no texture bound");
13259 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
13261 LOCAL_SET_GL_ERROR(
13262 GL_INVALID_OPERATION
,
13263 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
13268 ScopedGLErrorSuppressor
suppressor(
13269 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
13270 if (!gl_image
->BindTexImage(target
)) {
13271 LOCAL_SET_GL_ERROR(
13272 GL_INVALID_OPERATION
,
13273 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
13278 gfx::Size size
= gl_image
->GetSize();
13279 texture_manager()->SetLevelInfo(
13280 texture_ref
, target
, 0, gl_image
->GetInternalFormat(), size
.width(),
13281 size
.height(), 1, 0, gl_image
->GetInternalFormat(), GL_UNSIGNED_BYTE
,
13283 texture_manager()->SetLevelImage(texture_ref
, target
, 0, gl_image
);
13286 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
13287 GLenum target
, GLint image_id
) {
13288 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
13290 // Default target might be conceptually valid, but disallow it to avoid
13292 TextureRef
* texture_ref
=
13293 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
13294 if (!texture_ref
) {
13295 LOCAL_SET_GL_ERROR(
13296 GL_INVALID_OPERATION
,
13297 "glReleaseTexImage2DCHROMIUM", "no texture bound");
13301 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
13303 LOCAL_SET_GL_ERROR(
13304 GL_INVALID_OPERATION
,
13305 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
13309 // Do nothing when image is not currently bound.
13310 if (texture_ref
->texture()->GetLevelImage(target
, 0) != gl_image
)
13314 ScopedGLErrorSuppressor
suppressor(
13315 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
13316 gl_image
->ReleaseTexImage(target
);
13319 texture_manager()->SetLevelInfo(
13320 texture_ref
, target
, 0, gl_image
->GetInternalFormat(), 0, 0, 1, 0,
13321 gl_image
->GetInternalFormat(), GL_UNSIGNED_BYTE
, gfx::Rect());
13324 error::Error
GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
13325 uint32 immediate_data_size
,
13326 const void* cmd_data
) {
13327 const gles2::cmds::TraceBeginCHROMIUM
& c
=
13328 *static_cast<const gles2::cmds::TraceBeginCHROMIUM
*>(cmd_data
);
13329 Bucket
* category_bucket
= GetBucket(c
.category_bucket_id
);
13330 Bucket
* name_bucket
= GetBucket(c
.name_bucket_id
);
13331 if (!category_bucket
|| category_bucket
->size() == 0 ||
13332 !name_bucket
|| name_bucket
->size() == 0) {
13333 return error::kInvalidArguments
;
13336 std::string category_name
;
13337 std::string trace_name
;
13338 if (!category_bucket
->GetAsString(&category_name
) ||
13339 !name_bucket
->GetAsString(&trace_name
)) {
13340 return error::kInvalidArguments
;
13343 debug_marker_manager_
.PushGroup(trace_name
);
13344 if (!gpu_tracer_
->Begin(category_name
, trace_name
, kTraceCHROMIUM
)) {
13345 LOCAL_SET_GL_ERROR(
13346 GL_INVALID_OPERATION
,
13347 "glTraceBeginCHROMIUM", "unable to create begin trace");
13348 return error::kNoError
;
13350 return error::kNoError
;
13353 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
13354 debug_marker_manager_
.PopGroup();
13355 if (!gpu_tracer_
->End(kTraceCHROMIUM
)) {
13356 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
13357 "glTraceEndCHROMIUM", "no trace begin found");
13362 void GLES2DecoderImpl::DoDrawBuffersEXT(
13363 GLsizei count
, const GLenum
* bufs
) {
13364 if (count
> static_cast<GLsizei
>(group_
->max_draw_buffers())) {
13365 LOCAL_SET_GL_ERROR(
13367 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
13371 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
13373 for (GLsizei i
= 0; i
< count
; ++i
) {
13374 if (bufs
[i
] != static_cast<GLenum
>(GL_COLOR_ATTACHMENT0
+ i
) &&
13375 bufs
[i
] != GL_NONE
) {
13376 LOCAL_SET_GL_ERROR(
13377 GL_INVALID_OPERATION
,
13378 "glDrawBuffersEXT",
13379 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
13383 glDrawBuffersARB(count
, bufs
);
13384 framebuffer
->SetDrawBuffers(count
, bufs
);
13385 } else { // backbuffer
13387 (bufs
[0] != GL_BACK
&& bufs
[0] != GL_NONE
)) {
13388 LOCAL_SET_GL_ERROR(
13389 GL_INVALID_OPERATION
,
13390 "glDrawBuffersEXT",
13391 "more than one buffer or bufs not GL_NONE or GL_BACK");
13394 GLenum mapped_buf
= bufs
[0];
13395 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
13396 bufs
[0] == GL_BACK
) {
13397 mapped_buf
= GL_COLOR_ATTACHMENT0
;
13399 glDrawBuffersARB(count
, &mapped_buf
);
13400 group_
->set_draw_buffer(bufs
[0]);
13404 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current
, GLenum other
) {
13405 MarkContextLost(GetContextLostReasonFromResetStatus(current
));
13406 group_
->LoseContexts(GetContextLostReasonFromResetStatus(other
));
13407 reset_by_robustness_extension_
= true;
13410 void GLES2DecoderImpl::DoFlushDriverCachesCHROMIUM(void) {
13411 // On Adreno Android devices we need to use a workaround to force caches to
13413 if (feature_info_
->workarounds().unbind_egl_context_to_flush_driver_caches
) {
13414 context_
->ReleaseCurrent(nullptr);
13415 context_
->MakeCurrent(surface_
.get());
13419 void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode
,
13420 const GLfloat
* matrix
) {
13421 DCHECK(matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
||
13422 matrix_mode
== GL_PATH_MODELVIEW_CHROMIUM
);
13423 if (!features().chromium_path_rendering
) {
13424 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
13425 "glMatrixLoadfCHROMIUM",
13426 "function not available");
13430 GLfloat
* target_matrix
= matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
13431 ? state_
.projection_matrix
13432 : state_
.modelview_matrix
;
13433 memcpy(target_matrix
, matrix
, sizeof(GLfloat
) * 16);
13434 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
13435 // since the values of the _NV and _CHROMIUM tokens match.
13436 glMatrixLoadfEXT(matrix_mode
, matrix
);
13439 void GLES2DecoderImpl::DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode
) {
13440 DCHECK(matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
||
13441 matrix_mode
== GL_PATH_MODELVIEW_CHROMIUM
);
13443 if (!features().chromium_path_rendering
) {
13444 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
13445 "glMatrixLoadIdentityCHROMIUM",
13446 "function not available");
13450 GLfloat
* target_matrix
= matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
13451 ? state_
.projection_matrix
13452 : state_
.modelview_matrix
;
13453 memcpy(target_matrix
, kIdentityMatrix
, sizeof(kIdentityMatrix
));
13454 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
13455 // since the values of the _NV and _CHROMIUM tokens match.
13456 glMatrixLoadIdentityEXT(matrix_mode
);
13459 bool GLES2DecoderImpl::ValidateAsyncTransfer(
13460 const char* function_name
,
13461 TextureRef
* texture_ref
,
13464 const void * data
) {
13465 // We only support async uploads to 2D textures for now.
13466 if (GL_TEXTURE_2D
!= target
) {
13467 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
13470 // We only support uploads to level zero for now.
13472 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "level != 0");
13475 // A transfer buffer must be bound, even for asyncTexImage2D.
13476 if (data
== NULL
) {
13477 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
, "buffer == 0");
13480 // We only support one async transfer in progress.
13481 if (!texture_ref
||
13482 async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
13483 LOCAL_SET_GL_ERROR(
13484 GL_INVALID_OPERATION
,
13485 function_name
, "transfer already in progress");
13491 base::Closure
GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
13492 uint32 async_upload_token
,
13493 uint32 sync_data_shm_id
,
13494 uint32 sync_data_shm_offset
) {
13495 scoped_refptr
<gpu::Buffer
> buffer
= GetSharedMemoryBuffer(sync_data_shm_id
);
13496 if (!buffer
.get() ||
13497 !buffer
->GetDataAddress(sync_data_shm_offset
, sizeof(AsyncUploadSync
)))
13498 return base::Closure();
13500 AsyncMemoryParams
mem_params(buffer
,
13501 sync_data_shm_offset
,
13502 sizeof(AsyncUploadSync
));
13504 scoped_refptr
<AsyncUploadTokenCompletionObserver
> observer(
13505 new AsyncUploadTokenCompletionObserver(async_upload_token
));
13508 &AsyncPixelTransferManager::AsyncNotifyCompletion
,
13509 base::Unretained(GetAsyncPixelTransferManager()),
13514 error::Error
GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
13515 uint32 immediate_data_size
,
13516 const void* cmd_data
) {
13517 const gles2::cmds::AsyncTexImage2DCHROMIUM
& c
=
13518 *static_cast<const gles2::cmds::AsyncTexImage2DCHROMIUM
*>(cmd_data
);
13519 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
13520 GLenum target
= static_cast<GLenum
>(c
.target
);
13521 GLint level
= static_cast<GLint
>(c
.level
);
13522 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
13523 GLsizei width
= static_cast<GLsizei
>(c
.width
);
13524 GLsizei height
= static_cast<GLsizei
>(c
.height
);
13525 GLint border
= static_cast<GLint
>(c
.border
);
13526 GLenum format
= static_cast<GLenum
>(c
.format
);
13527 GLenum type
= static_cast<GLenum
>(c
.type
);
13528 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
13529 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
13530 uint32 pixels_size
;
13531 uint32 async_upload_token
= static_cast<uint32
>(c
.async_upload_token
);
13532 uint32 sync_data_shm_id
= static_cast<uint32
>(c
.sync_data_shm_id
);
13533 uint32 sync_data_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
13535 base::ScopedClosureRunner scoped_completion_callback
;
13536 if (async_upload_token
) {
13537 base::Closure completion_closure
=
13538 AsyncUploadTokenCompletionClosure(async_upload_token
,
13540 sync_data_shm_offset
);
13541 if (completion_closure
.is_null())
13542 return error::kInvalidArguments
;
13544 scoped_completion_callback
.Reset(completion_closure
);
13547 // TODO(epenner): Move this and copies of this memory validation
13548 // into ValidateTexImage2D step.
13549 if (!GLES2Util::ComputeImageDataSizes(
13550 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
13552 return error::kOutOfBounds
;
13554 const void* pixels
= NULL
;
13555 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
13556 pixels
= GetSharedMemoryAs
<const void*>(
13557 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
13559 return error::kOutOfBounds
;
13563 TextureManager::DoTexImageArguments args
= {
13564 target
, level
, internal_format
, width
, height
, 1, border
, format
, type
,
13565 pixels
, pixels_size
, TextureManager::DoTexImageArguments::kTexImage2D
};
13566 TextureRef
* texture_ref
;
13567 // All the normal glTexSubImage2D validation.
13568 if (!texture_manager()->ValidateTexImage(
13569 &state_
, "glAsyncTexImage2DCHROMIUM", args
, &texture_ref
)) {
13570 return error::kNoError
;
13573 // Extra async validation.
13574 Texture
* texture
= texture_ref
->texture();
13575 if (!ValidateAsyncTransfer(
13576 "glAsyncTexImage2DCHROMIUM", texture_ref
, target
, level
, pixels
))
13577 return error::kNoError
;
13579 // Don't allow async redefinition of a textures.
13580 if (texture
->IsDefined()) {
13581 LOCAL_SET_GL_ERROR(
13582 GL_INVALID_OPERATION
,
13583 "glAsyncTexImage2DCHROMIUM", "already defined");
13584 return error::kNoError
;
13587 if (!EnsureGPUMemoryAvailable(pixels_size
)) {
13588 LOCAL_SET_GL_ERROR(
13589 GL_OUT_OF_MEMORY
, "glAsyncTexImage2DCHROMIUM", "out of memory");
13590 return error::kNoError
;
13593 // Setup the parameters.
13594 AsyncTexImage2DParams tex_params
= {
13595 target
, level
, static_cast<GLenum
>(internal_format
),
13596 width
, height
, border
, format
, type
};
13597 AsyncMemoryParams
mem_params(
13598 GetSharedMemoryBuffer(c
.pixels_shm_id
), c
.pixels_shm_offset
, pixels_size
);
13600 // Set up the async state if needed, and make the texture
13601 // immutable so the async state stays valid. The level info
13602 // is set up lazily when the transfer completes.
13603 AsyncPixelTransferDelegate
* delegate
=
13604 async_pixel_transfer_manager_
->CreatePixelTransferDelegate(texture_ref
,
13606 texture
->SetImmutable(true);
13608 delegate
->AsyncTexImage2D(
13611 base::Bind(&TextureManager::SetLevelInfoFromParams
,
13612 // The callback is only invoked if the transfer delegate still
13613 // exists, which implies through manager->texture_ref->state
13614 // ownership that both of these pointers are valid.
13615 base::Unretained(texture_manager()),
13616 base::Unretained(texture_ref
),
13618 return error::kNoError
;
13621 error::Error
GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
13622 uint32 immediate_data_size
,
13623 const void* cmd_data
) {
13624 const gles2::cmds::AsyncTexSubImage2DCHROMIUM
& c
=
13625 *static_cast<const gles2::cmds::AsyncTexSubImage2DCHROMIUM
*>(cmd_data
);
13626 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
13627 GLenum target
= static_cast<GLenum
>(c
.target
);
13628 GLint level
= static_cast<GLint
>(c
.level
);
13629 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
13630 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
13631 GLsizei width
= static_cast<GLsizei
>(c
.width
);
13632 GLsizei height
= static_cast<GLsizei
>(c
.height
);
13633 GLenum format
= static_cast<GLenum
>(c
.format
);
13634 GLenum type
= static_cast<GLenum
>(c
.type
);
13635 uint32 async_upload_token
= static_cast<uint32
>(c
.async_upload_token
);
13636 uint32 sync_data_shm_id
= static_cast<uint32
>(c
.sync_data_shm_id
);
13637 uint32 sync_data_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
13639 base::ScopedClosureRunner scoped_completion_callback
;
13640 if (async_upload_token
) {
13641 base::Closure completion_closure
=
13642 AsyncUploadTokenCompletionClosure(async_upload_token
,
13644 sync_data_shm_offset
);
13645 if (completion_closure
.is_null())
13646 return error::kInvalidArguments
;
13648 scoped_completion_callback
.Reset(completion_closure
);
13651 // TODO(epenner): Move this and copies of this memory validation
13652 // into ValidateTexSubImage2D step.
13654 if (!GLES2Util::ComputeImageDataSizes(
13655 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &data_size
,
13657 return error::kOutOfBounds
;
13659 const void* pixels
= GetSharedMemoryAs
<const void*>(
13660 c
.data_shm_id
, c
.data_shm_offset
, data_size
);
13662 // All the normal glTexSubImage2D validation.
13663 error::Error error
= error::kNoError
;
13664 if (!ValidateTexSubImage2D(&error
, "glAsyncTexSubImage2DCHROMIUM",
13665 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
)) {
13669 // Extra async validation.
13670 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
13672 Texture
* texture
= texture_ref
->texture();
13673 if (!ValidateAsyncTransfer(
13674 "glAsyncTexSubImage2DCHROMIUM", texture_ref
, target
, level
, pixels
))
13675 return error::kNoError
;
13677 // Guarantee async textures are always 'cleared' as follows:
13678 // - AsyncTexImage2D can not redefine an existing texture
13679 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
13680 // - AsyncTexSubImage2D clears synchronously if not already cleared.
13681 // - Textures become immutable after an async call.
13682 // This way we know in all cases that an async texture is always clear.
13683 if (!texture
->SafeToRenderFrom()) {
13684 if (!texture_manager()->ClearTextureLevel(this, texture_ref
,
13686 LOCAL_SET_GL_ERROR(
13688 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
13689 return error::kNoError
;
13693 // Setup the parameters.
13694 AsyncTexSubImage2DParams tex_params
= {target
, level
, xoffset
, yoffset
,
13695 width
, height
, format
, type
};
13696 AsyncMemoryParams
mem_params(
13697 GetSharedMemoryBuffer(c
.data_shm_id
), c
.data_shm_offset
, data_size
);
13698 AsyncPixelTransferDelegate
* delegate
=
13699 async_pixel_transfer_manager_
->GetPixelTransferDelegate(texture_ref
);
13701 // TODO(epenner): We may want to enforce exclusive use
13702 // of async APIs in which case this should become an error,
13703 // (the texture should have been async defined).
13704 AsyncTexImage2DParams define_params
= {target
, level
,
13706 texture
->GetLevelSize(
13707 target
, level
, &define_params
.width
, &define_params
.height
, nullptr);
13708 texture
->GetLevelType(
13709 target
, level
, &define_params
.type
, &define_params
.internal_format
);
13710 // Set up the async state if needed, and make the texture
13711 // immutable so the async state stays valid.
13712 delegate
= async_pixel_transfer_manager_
->CreatePixelTransferDelegate(
13713 texture_ref
, define_params
);
13714 texture
->SetImmutable(true);
13717 delegate
->AsyncTexSubImage2D(tex_params
, mem_params
);
13718 return error::kNoError
;
13721 error::Error
GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
13722 uint32 immediate_data_size
,
13723 const void* cmd_data
) {
13724 const gles2::cmds::WaitAsyncTexImage2DCHROMIUM
& c
=
13725 *static_cast<const gles2::cmds::WaitAsyncTexImage2DCHROMIUM
*>(cmd_data
);
13726 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
13727 GLenum target
= static_cast<GLenum
>(c
.target
);
13729 if (GL_TEXTURE_2D
!= target
) {
13730 LOCAL_SET_GL_ERROR(
13731 GL_INVALID_ENUM
, "glWaitAsyncTexImage2DCHROMIUM", "target");
13732 return error::kNoError
;
13734 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
13736 if (!texture_ref
) {
13737 LOCAL_SET_GL_ERROR(
13738 GL_INVALID_OPERATION
,
13739 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
13740 return error::kNoError
;
13742 AsyncPixelTransferDelegate
* delegate
=
13743 async_pixel_transfer_manager_
->GetPixelTransferDelegate(texture_ref
);
13745 LOCAL_SET_GL_ERROR(
13746 GL_INVALID_OPERATION
,
13747 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
13748 return error::kNoError
;
13750 delegate
->WaitForTransferCompletion();
13751 ProcessFinishedAsyncTransfers();
13752 return error::kNoError
;
13755 error::Error
GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
13756 uint32 immediate_data_size
,
13757 const void* data
) {
13758 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
13760 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
13761 ProcessFinishedAsyncTransfers();
13762 return error::kNoError
;
13765 error::Error
GLES2DecoderImpl::HandleUniformBlockBinding(
13766 uint32_t immediate_data_size
, const void* cmd_data
) {
13767 if (!unsafe_es3_apis_enabled())
13768 return error::kUnknownCommand
;
13769 const gles2::cmds::UniformBlockBinding
& c
=
13770 *static_cast<const gles2::cmds::UniformBlockBinding
*>(cmd_data
);
13771 GLuint client_id
= c
.program
;
13772 GLuint index
= static_cast<GLuint
>(c
.index
);
13773 GLuint binding
= static_cast<GLuint
>(c
.binding
);
13774 Program
* program
= GetProgramInfoNotShader(
13775 client_id
, "glUniformBlockBinding");
13777 return error::kNoError
;
13779 GLuint service_id
= program
->service_id();
13780 glUniformBlockBinding(service_id
, index
, binding
);
13781 return error::kNoError
;
13784 error::Error
GLES2DecoderImpl::HandleClientWaitSync(
13785 uint32_t immediate_data_size
, const void* cmd_data
) {
13786 if (!unsafe_es3_apis_enabled())
13787 return error::kUnknownCommand
;
13788 const gles2::cmds::ClientWaitSync
& c
=
13789 *static_cast<const gles2::cmds::ClientWaitSync
*>(cmd_data
);
13790 GLuint sync
= static_cast<GLuint
>(c
.sync
);
13791 GLbitfield flags
= static_cast<GLbitfield
>(c
.flags
);
13792 GLuint64 timeout
= GLES2Util::MapTwoUint32ToUint64(c
.timeout_0
, c
.timeout_1
);
13793 typedef cmds::ClientWaitSync::Result Result
;
13794 Result
* result_dst
= GetSharedMemoryAs
<Result
*>(
13795 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result_dst
));
13797 return error::kOutOfBounds
;
13799 if (*result_dst
!= GL_WAIT_FAILED
) {
13800 return error::kInvalidArguments
;
13802 GLsync service_sync
= 0;
13803 if (!group_
->GetSyncServiceId(sync
, &service_sync
)) {
13804 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "ClientWaitSync", "invalid sync");
13805 return error::kNoError
;
13807 *result_dst
= glClientWaitSync(service_sync
, flags
, timeout
);
13808 return error::kNoError
;
13811 error::Error
GLES2DecoderImpl::HandleWaitSync(
13812 uint32_t immediate_data_size
, const void* cmd_data
) {
13813 if (!unsafe_es3_apis_enabled())
13814 return error::kUnknownCommand
;
13815 const gles2::cmds::WaitSync
& c
=
13816 *static_cast<const gles2::cmds::WaitSync
*>(cmd_data
);
13817 GLuint sync
= static_cast<GLuint
>(c
.sync
);
13818 GLbitfield flags
= static_cast<GLbitfield
>(c
.flags
);
13819 GLuint64 timeout
= GLES2Util::MapTwoUint32ToUint64(c
.timeout_0
, c
.timeout_1
);
13820 GLsync service_sync
= 0;
13821 if (!group_
->GetSyncServiceId(sync
, &service_sync
)) {
13822 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "WaitSync", "invalid sync");
13823 return error::kNoError
;
13825 glWaitSync(service_sync
, flags
, timeout
);
13826 return error::kNoError
;
13829 error::Error
GLES2DecoderImpl::HandleGetInternalformativ(
13830 uint32_t immediate_data_size
, const void* cmd_data
) {
13831 if (!unsafe_es3_apis_enabled())
13832 return error::kUnknownCommand
;
13833 const gles2::cmds::GetInternalformativ
& c
=
13834 *static_cast<const gles2::cmds::GetInternalformativ
*>(cmd_data
);
13835 GLenum target
= static_cast<GLenum
>(c
.target
);
13836 GLenum format
= static_cast<GLenum
>(c
.format
);
13837 GLenum pname
= static_cast<GLenum
>(c
.pname
);
13838 if (!validators_
->render_buffer_target
.IsValid(target
)) {
13839 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", target
, "target");
13840 return error::kNoError
;
13842 if (!validators_
->render_buffer_format
.IsValid(format
)) {
13843 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", format
, "format");
13844 return error::kNoError
;
13846 if (!validators_
->internal_format_parameter
.IsValid(pname
)) {
13847 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", pname
, "pname");
13848 return error::kNoError
;
13850 typedef cmds::GetInternalformativ::Result Result
;
13851 GLsizei num_values
= 0;
13853 case GL_NUM_SAMPLE_COUNTS
:
13859 glGetInternalformativ(target
, format
, GL_NUM_SAMPLE_COUNTS
, 1, &value
);
13860 num_values
= static_cast<GLsizei
>(value
);
13867 Result
* result
= GetSharedMemoryAs
<Result
*>(
13868 c
.params_shm_id
, c
.params_shm_offset
, Result::ComputeSize(num_values
));
13869 GLint
* params
= result
? result
->GetData() : NULL
;
13870 if (params
== NULL
) {
13871 return error::kOutOfBounds
;
13873 // Check that the client initialized the result.
13874 if (result
->size
!= 0) {
13875 return error::kInvalidArguments
;
13877 glGetInternalformativ(target
, format
, pname
, num_values
, params
);
13878 result
->SetNumResults(num_values
);
13879 return error::kNoError
;
13882 error::Error
GLES2DecoderImpl::HandleMapBufferRange(
13883 uint32_t immediate_data_size
, const void* cmd_data
) {
13884 if (!unsafe_es3_apis_enabled()) {
13885 return error::kUnknownCommand
;
13887 const gles2::cmds::MapBufferRange
& c
=
13888 *static_cast<const gles2::cmds::MapBufferRange
*>(cmd_data
);
13889 GLenum target
= static_cast<GLenum
>(c
.target
);
13890 GLbitfield access
= static_cast<GLbitfield
>(c
.access
);
13891 GLintptr offset
= static_cast<GLintptr
>(c
.offset
);
13892 GLsizeiptr size
= static_cast<GLsizeiptr
>(c
.size
);
13894 typedef cmds::MapBufferRange::Result Result
;
13895 Result
* result
= GetSharedMemoryAs
<Result
*>(
13896 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
13898 return error::kOutOfBounds
;
13900 if (*result
!= 0) {
13902 return error::kInvalidArguments
;
13905 GetSharedMemoryAs
<int8_t*>(c
.data_shm_id
, c
.data_shm_offset
, size
);
13907 return error::kOutOfBounds
;
13910 GLbitfield mask
= GL_MAP_INVALIDATE_BUFFER_BIT
;
13911 if ((access
& mask
) == mask
) {
13912 // TODO(zmo): To be on the safe side, always map
13913 // GL_MAP_INVALIDATE_BUFFER_BIT to GL_MAP_INVALIDATE_RANGE_BIT.
13914 access
= (access
& ~GL_MAP_INVALIDATE_BUFFER_BIT
);
13915 access
= (access
| GL_MAP_INVALIDATE_RANGE_BIT
);
13917 // TODO(zmo): Always filter out GL_MAP_UNSYNCHRONIZED_BIT to get rid of
13918 // undefined behaviors.
13919 mask
= GL_MAP_READ_BIT
| GL_MAP_UNSYNCHRONIZED_BIT
;
13920 if ((access
& mask
) == mask
) {
13921 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "MapBufferRange",
13922 "incompatible access bits");
13923 return error::kNoError
;
13925 access
= (access
& ~GL_MAP_UNSYNCHRONIZED_BIT
);
13926 if ((access
& GL_MAP_WRITE_BIT
) == GL_MAP_WRITE_BIT
&&
13927 (access
& GL_MAP_INVALIDATE_RANGE_BIT
) == 0) {
13928 access
= (access
| GL_MAP_READ_BIT
);
13930 void* ptr
= glMapBufferRange(target
, offset
, size
, access
);
13931 if (ptr
== nullptr) {
13932 return error::kNoError
;
13934 Buffer
* buffer
= buffer_manager()->GetBufferInfoForTarget(&state_
, target
);
13936 buffer
->SetMappedRange(offset
, size
, access
, ptr
,
13937 GetSharedMemoryBuffer(c
.data_shm_id
));
13938 if ((access
& GL_MAP_INVALIDATE_RANGE_BIT
) == 0) {
13939 memcpy(mem
, ptr
, size
);
13942 return error::kNoError
;
13945 error::Error
GLES2DecoderImpl::HandleUnmapBuffer(
13946 uint32_t immediate_data_size
, const void* cmd_data
) {
13947 if (!unsafe_es3_apis_enabled()) {
13948 return error::kUnknownCommand
;
13950 const gles2::cmds::UnmapBuffer
& c
=
13951 *static_cast<const gles2::cmds::UnmapBuffer
*>(cmd_data
);
13952 GLenum target
= static_cast<GLenum
>(c
.target
);
13954 Buffer
* buffer
= buffer_manager()->GetBufferInfoForTarget(&state_
, target
);
13956 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "UnmapBuffer", "no buffer bound");
13957 return error::kNoError
;
13959 const Buffer::MappedRange
* mapped_range
= buffer
->GetMappedRange();
13960 if (!mapped_range
) {
13961 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "UnmapBuffer",
13962 "buffer is unmapped");
13963 return error::kNoError
;
13965 if ((mapped_range
->access
& GL_MAP_WRITE_BIT
) == 0 ||
13966 (mapped_range
->access
& GL_MAP_FLUSH_EXPLICIT_BIT
) ==
13967 GL_MAP_FLUSH_EXPLICIT_BIT
) {
13968 // If we don't need to write back, or explict flush is required, no copying
13971 void* mem
= mapped_range
->GetShmPointer();
13973 return error::kOutOfBounds
;
13975 DCHECK(mapped_range
->pointer
);
13976 memcpy(mapped_range
->pointer
, mem
, mapped_range
->size
);
13978 buffer
->RemoveMappedRange();
13979 GLboolean rt
= glUnmapBuffer(target
);
13980 if (rt
== GL_FALSE
) {
13981 // At this point, we have already done the necessary validation, so
13982 // GL_FALSE indicates data corruption.
13983 // TODO(zmo): We could redo the map / copy data / unmap to recover, but
13984 // the second unmap could still return GL_FALSE. For now, we simply lose
13985 // the contexts in the share group.
13986 LOG(ERROR
) << "glUnmapBuffer unexpectedly returned GL_FALSE";
13987 // Need to lose current context before broadcasting!
13988 MarkContextLost(error::kGuilty
);
13989 group_
->LoseContexts(error::kInnocent
);
13990 return error::kLostContext
;
13992 return error::kNoError
;
13995 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
13996 TextureRef
* texture_ref
) {
13997 Texture
* texture
= texture_ref
->texture();
13998 DoDidUseTexImageIfNeeded(texture
, texture
->target());
14001 // Note that GL_LOST_CONTEXT is specific to GLES.
14002 // For desktop GL we have to query the reset status proactively.
14003 void GLES2DecoderImpl::OnContextLostError() {
14004 if (!WasContextLost()) {
14005 // Need to lose current context before broadcasting!
14006 CheckResetStatus();
14007 group_
->LoseContexts(error::kUnknown
);
14008 reset_by_robustness_extension_
= true;
14012 void GLES2DecoderImpl::OnOutOfMemoryError() {
14013 if (lose_context_when_out_of_memory_
&& !WasContextLost()) {
14014 error::ContextLostReason other
= error::kOutOfMemory
;
14015 if (CheckResetStatus()) {
14016 other
= error::kUnknown
;
14018 // Need to lose current context before broadcasting!
14019 MarkContextLost(error::kOutOfMemory
);
14021 group_
->LoseContexts(other
);
14025 error::Error
GLES2DecoderImpl::HandleGenPathsCHROMIUM(
14026 uint32 immediate_data_size
,
14027 const void* cmd_data
) {
14028 static const char kFunctionName
[] = "glGenPathsCHROMIUM";
14029 const gles2::cmds::GenPathsCHROMIUM
& c
=
14030 *static_cast<const gles2::cmds::GenPathsCHROMIUM
*>(cmd_data
);
14031 if (!features().chromium_path_rendering
) {
14032 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14033 "function not available");
14034 return error::kNoError
;
14037 GLsizei range
= static_cast<GLsizei
>(c
.range
);
14039 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "range < 0");
14040 return error::kNoError
;
14043 GLuint first_client_id
= static_cast<GLuint
>(c
.first_client_id
);
14044 if (first_client_id
== 0)
14045 return error::kInvalidArguments
;
14048 return error::kNoError
;
14050 if (!GenPathsCHROMIUMHelper(first_client_id
, range
))
14051 return error::kInvalidArguments
;
14053 return error::kNoError
;
14055 error::Error
GLES2DecoderImpl::HandleDeletePathsCHROMIUM(
14056 uint32_t immediate_data_size
,
14057 const void* cmd_data
) {
14058 static const char kFunctionName
[] = "glDeletePathsCHROMIUM";
14059 const gles2::cmds::DeletePathsCHROMIUM
& c
=
14060 *static_cast<const gles2::cmds::DeletePathsCHROMIUM
*>(cmd_data
);
14061 if (!features().chromium_path_rendering
) {
14062 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14063 "function not available");
14064 return error::kNoError
;
14067 GLsizei range
= static_cast<GLsizei
>(c
.range
);
14069 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "range < 0");
14070 return error::kNoError
;
14074 return error::kNoError
;
14076 GLuint first_client_id
= c
.first_client_id
;
14077 // first_client_id can be 0, because non-existing path ids are skipped.
14079 if (!DeletePathsCHROMIUMHelper(first_client_id
, range
))
14080 return error::kInvalidArguments
;
14082 return error::kNoError
;
14085 error::Error
GLES2DecoderImpl::HandlePathCommandsCHROMIUM(
14086 uint32 immediate_data_size
,
14087 const void* cmd_data
) {
14088 static const char kFunctionName
[] = "glPathCommandsCHROMIUM";
14089 const gles2::cmds::PathCommandsCHROMIUM
& c
=
14090 *static_cast<const gles2::cmds::PathCommandsCHROMIUM
*>(cmd_data
);
14091 if (!features().chromium_path_rendering
) {
14092 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14093 "function not available");
14094 return error::kNoError
;
14097 GLuint service_id
= 0;
14098 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
)) {
14099 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14100 "invalid path name");
14101 return error::kNoError
;
14104 GLsizei num_commands
= static_cast<GLsizei
>(c
.numCommands
);
14105 if (num_commands
< 0) {
14106 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "numCommands < 0");
14107 return error::kNoError
;
14110 GLsizei num_coords
= static_cast<uint32
>(c
.numCoords
);
14111 if (num_coords
< 0) {
14112 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "numCoords < 0");
14113 return error::kNoError
;
14116 GLenum coord_type
= static_cast<uint32
>(c
.coordType
);
14117 if (!validators_
->path_coord_type
.IsValid(static_cast<GLint
>(coord_type
))) {
14118 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM
, kFunctionName
, "invalid coordType");
14119 return error::kNoError
;
14122 const GLubyte
* commands
= NULL
;
14123 base::CheckedNumeric
<GLsizei
> num_coords_expected
= 0;
14125 if (num_commands
> 0) {
14126 uint32 commands_shm_id
= static_cast<uint32
>(c
.commands_shm_id
);
14127 uint32 commands_shm_offset
= static_cast<uint32
>(c
.commands_shm_offset
);
14128 if (commands_shm_id
!= 0 || commands_shm_offset
!= 0)
14129 commands
= GetSharedMemoryAs
<const GLubyte
*>(
14130 commands_shm_id
, commands_shm_offset
, num_commands
);
14133 return error::kOutOfBounds
;
14135 for (GLsizei i
= 0; i
< num_commands
; ++i
) {
14136 switch (commands
[i
]) {
14137 case GL_CLOSE_PATH_CHROMIUM
:
14138 // Close has no coords.
14140 case GL_MOVE_TO_CHROMIUM
:
14142 case GL_LINE_TO_CHROMIUM
:
14143 num_coords_expected
+= 2;
14145 case GL_QUADRATIC_CURVE_TO_CHROMIUM
:
14146 num_coords_expected
+= 4;
14148 case GL_CUBIC_CURVE_TO_CHROMIUM
:
14149 num_coords_expected
+= 6;
14151 case GL_CONIC_CURVE_TO_CHROMIUM
:
14152 num_coords_expected
+= 5;
14155 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM
, kFunctionName
, "invalid command");
14156 return error::kNoError
;
14161 if (!num_coords_expected
.IsValid() ||
14162 num_coords
!= num_coords_expected
.ValueOrDie()) {
14163 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14164 "numCoords does not match commands");
14165 return error::kNoError
;
14168 const void* coords
= NULL
;
14170 if (num_coords
> 0) {
14171 uint32 coords_size
= 0;
14172 uint32 coord_type_size
=
14173 GLES2Util::GetGLTypeSizeForPathCoordType(coord_type
);
14174 if (!SafeMultiplyUint32(num_coords
, coord_type_size
, &coords_size
))
14175 return error::kOutOfBounds
;
14177 uint32 coords_shm_id
= static_cast<uint32
>(c
.coords_shm_id
);
14178 uint32 coords_shm_offset
= static_cast<uint32
>(c
.coords_shm_offset
);
14179 if (coords_shm_id
!= 0 || coords_shm_offset
!= 0)
14180 coords
= GetSharedMemoryAs
<const void*>(coords_shm_id
, coords_shm_offset
,
14184 return error::kOutOfBounds
;
14187 glPathCommandsNV(service_id
, num_commands
, commands
, num_coords
, coord_type
,
14190 return error::kNoError
;
14193 error::Error
GLES2DecoderImpl::HandlePathParameterfCHROMIUM(
14194 uint32 immediate_data_size
,
14195 const void* cmd_data
) {
14196 static const char kFunctionName
[] = "glPathParameterfCHROMIUM";
14197 const gles2::cmds::PathParameterfCHROMIUM
& c
=
14198 *static_cast<const gles2::cmds::PathParameterfCHROMIUM
*>(cmd_data
);
14199 if (!features().chromium_path_rendering
) {
14200 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14201 "function not available");
14202 return error::kNoError
;
14204 GLuint service_id
= 0;
14205 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
)) {
14206 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14207 "invalid path name");
14208 return error::kNoError
;
14211 GLenum pname
= static_cast<GLenum
>(c
.pname
);
14212 GLfloat value
= static_cast<GLfloat
>(c
.value
);
14213 bool hasValueError
= false;
14216 case GL_PATH_STROKE_WIDTH_CHROMIUM
:
14217 case GL_PATH_MITER_LIMIT_CHROMIUM
:
14218 hasValueError
= std::isnan(value
) || !std::isfinite(value
) || value
< 0;
14220 case GL_PATH_STROKE_BOUND_CHROMIUM
:
14221 value
= std::max(std::min(1.0f
, value
), 0.0f
);
14223 case GL_PATH_END_CAPS_CHROMIUM
:
14224 hasValueError
= !validators_
->path_parameter_cap_values
.IsValid(
14225 static_cast<GLint
>(value
));
14227 case GL_PATH_JOIN_STYLE_CHROMIUM
:
14228 hasValueError
= !validators_
->path_parameter_join_values
.IsValid(
14229 static_cast<GLint
>(value
));
14232 DCHECK(!validators_
->path_parameter
.IsValid(pname
));
14233 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, pname
, "pname");
14234 return error::kNoError
;
14236 DCHECK(validators_
->path_parameter
.IsValid(pname
));
14238 if (hasValueError
) {
14239 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "value not correct");
14240 return error::kNoError
;
14243 glPathParameterfNV(service_id
, pname
, value
);
14244 return error::kNoError
;
14247 error::Error
GLES2DecoderImpl::HandlePathParameteriCHROMIUM(
14248 uint32 immediate_data_size
,
14249 const void* cmd_data
) {
14250 static const char kFunctionName
[] = "glPathParameteriCHROMIUM";
14251 const gles2::cmds::PathParameteriCHROMIUM
& c
=
14252 *static_cast<const gles2::cmds::PathParameteriCHROMIUM
*>(cmd_data
);
14253 if (!features().chromium_path_rendering
) {
14254 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14255 "function not available");
14256 return error::kNoError
;
14258 GLuint service_id
= 0;
14259 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
)) {
14260 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14261 "invalid path name");
14262 return error::kNoError
;
14265 GLenum pname
= static_cast<GLenum
>(c
.pname
);
14266 GLint value
= static_cast<GLint
>(c
.value
);
14267 bool hasValueError
= false;
14270 case GL_PATH_STROKE_WIDTH_CHROMIUM
:
14271 case GL_PATH_MITER_LIMIT_CHROMIUM
:
14272 hasValueError
= value
< 0;
14274 case GL_PATH_STROKE_BOUND_CHROMIUM
:
14275 value
= std::max(std::min(1, value
), 0);
14277 case GL_PATH_END_CAPS_CHROMIUM
:
14278 hasValueError
= !validators_
->path_parameter_cap_values
.IsValid(value
);
14280 case GL_PATH_JOIN_STYLE_CHROMIUM
:
14281 hasValueError
= !validators_
->path_parameter_join_values
.IsValid(value
);
14284 DCHECK(!validators_
->path_parameter
.IsValid(pname
));
14285 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, pname
, "pname");
14286 return error::kNoError
;
14288 DCHECK(validators_
->path_parameter
.IsValid(pname
));
14290 if (hasValueError
) {
14291 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "value not correct");
14292 return error::kNoError
;
14295 glPathParameteriNV(service_id
, pname
, value
);
14296 return error::kNoError
;
14299 error::Error
GLES2DecoderImpl::HandleStencilFillPathCHROMIUM(
14300 uint32 immediate_data_size
,
14301 const void* cmd_data
) {
14302 static const char kFunctionName
[] = "glStencilFillPathCHROMIUM";
14303 const gles2::cmds::StencilFillPathCHROMIUM
& c
=
14304 *static_cast<const gles2::cmds::StencilFillPathCHROMIUM
*>(cmd_data
);
14305 if (!features().chromium_path_rendering
) {
14306 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14307 "function not available");
14308 return error::kNoError
;
14310 GLenum fill_mode
= static_cast<GLenum
>(c
.fillMode
);
14311 if (!validators_
->path_fill_mode
.IsValid(fill_mode
)) {
14312 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, fill_mode
, "fillMode");
14313 return error::kNoError
;
14315 GLuint mask
= static_cast<GLuint
>(c
.mask
);
14316 if ((fill_mode
== GL_COUNT_UP_CHROMIUM
||
14317 fill_mode
== GL_COUNT_DOWN_CHROMIUM
) &&
14318 GLES2Util::IsNPOT(mask
+ 1)) {
14319 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
,
14320 "mask + 1 is not power of two");
14321 return error::kNoError
;
14323 GLuint service_id
= 0;
14324 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
)) {
14325 // "If /path/ does not name an existing path object, the command does
14326 // nothing (and no error is generated)."
14327 // This holds for other rendering functions, too.
14328 return error::kNoError
;
14331 glStencilFillPathNV(service_id
, fill_mode
, mask
);
14332 return error::kNoError
;
14335 error::Error
GLES2DecoderImpl::HandleStencilStrokePathCHROMIUM(
14336 uint32 immediate_data_size
,
14337 const void* cmd_data
) {
14338 static const char kFunctionName
[] = "glStencilStrokePathCHROMIUM";
14339 const gles2::cmds::StencilStrokePathCHROMIUM
& c
=
14340 *static_cast<const gles2::cmds::StencilStrokePathCHROMIUM
*>(cmd_data
);
14341 if (!features().chromium_path_rendering
) {
14342 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14343 "function not available");
14344 return error::kNoError
;
14346 GLuint service_id
= 0;
14347 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
)) {
14348 return error::kNoError
;
14350 GLint reference
= static_cast<GLint
>(c
.reference
);
14351 GLuint mask
= static_cast<GLuint
>(c
.mask
);
14353 glStencilStrokePathNV(service_id
, reference
, mask
);
14354 return error::kNoError
;
14357 error::Error
GLES2DecoderImpl::HandleCoverFillPathCHROMIUM(
14358 uint32 immediate_data_size
,
14359 const void* cmd_data
) {
14360 static const char kFunctionName
[] = "glCoverFillPathCHROMIUM";
14361 const gles2::cmds::CoverFillPathCHROMIUM
& c
=
14362 *static_cast<const gles2::cmds::CoverFillPathCHROMIUM
*>(cmd_data
);
14363 if (!features().chromium_path_rendering
) {
14364 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14365 "function not available");
14366 return error::kNoError
;
14368 GLenum cover_mode
= static_cast<GLenum
>(c
.coverMode
);
14369 if (!validators_
->path_cover_mode
.IsValid(cover_mode
)) {
14370 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, cover_mode
, "coverMode");
14371 return error::kNoError
;
14373 GLuint service_id
= 0;
14374 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
))
14375 return error::kNoError
;
14378 glCoverFillPathNV(service_id
, cover_mode
);
14379 return error::kNoError
;
14382 error::Error
GLES2DecoderImpl::HandleCoverStrokePathCHROMIUM(
14383 uint32 immediate_data_size
,
14384 const void* cmd_data
) {
14385 static const char kFunctionName
[] = "glCoverStrokePathCHROMIUM";
14386 const gles2::cmds::CoverStrokePathCHROMIUM
& c
=
14387 *static_cast<const gles2::cmds::CoverStrokePathCHROMIUM
*>(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 cover_mode
= static_cast<GLenum
>(c
.coverMode
);
14394 if (!validators_
->path_cover_mode
.IsValid(cover_mode
)) {
14395 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, cover_mode
, "coverMode");
14396 return error::kNoError
;
14398 GLuint service_id
= 0;
14399 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
))
14400 return error::kNoError
;
14403 glCoverStrokePathNV(service_id
, cover_mode
);
14404 return error::kNoError
;
14407 error::Error
GLES2DecoderImpl::HandleStencilThenCoverFillPathCHROMIUM(
14408 uint32 immediate_data_size
,
14409 const void* cmd_data
) {
14410 static const char kFunctionName
[] = "glStencilThenCoverFillPathCHROMIUM";
14411 const gles2::cmds::StencilThenCoverFillPathCHROMIUM
& c
=
14412 *static_cast<const gles2::cmds::StencilThenCoverFillPathCHROMIUM
*>(
14414 if (!features().chromium_path_rendering
) {
14415 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14416 "function not available");
14417 return error::kNoError
;
14419 GLenum fill_mode
= static_cast<GLenum
>(c
.fillMode
);
14420 if (!validators_
->path_fill_mode
.IsValid(fill_mode
)) {
14421 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, fill_mode
, "fillMode");
14422 return error::kNoError
;
14424 GLuint mask
= static_cast<GLuint
>(c
.mask
);
14425 if ((fill_mode
== GL_COUNT_UP_CHROMIUM
||
14426 fill_mode
== GL_COUNT_DOWN_CHROMIUM
) &&
14427 GLES2Util::IsNPOT(mask
+ 1)) {
14428 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
,
14429 "mask + 1 is not power of two");
14430 return error::kNoError
;
14432 GLenum cover_mode
= static_cast<GLenum
>(c
.coverMode
);
14433 if (!validators_
->path_cover_mode
.IsValid(cover_mode
)) {
14434 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, cover_mode
, "coverMode");
14435 return error::kNoError
;
14437 GLuint service_id
= 0;
14438 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
))
14439 return error::kNoError
;
14442 glStencilThenCoverFillPathNV(service_id
, fill_mode
, mask
, cover_mode
);
14443 return error::kNoError
;
14446 error::Error
GLES2DecoderImpl::HandleStencilThenCoverStrokePathCHROMIUM(
14447 uint32 immediate_data_size
,
14448 const void* cmd_data
) {
14449 static const char kFunctionName
[] = "glStencilThenCoverStrokePathCHROMIUM";
14450 const gles2::cmds::StencilThenCoverStrokePathCHROMIUM
& c
=
14451 *static_cast<const gles2::cmds::StencilThenCoverStrokePathCHROMIUM
*>(
14453 if (!features().chromium_path_rendering
) {
14454 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14455 "function not available");
14456 return error::kNoError
;
14458 GLenum cover_mode
= static_cast<GLenum
>(c
.coverMode
);
14459 if (!validators_
->path_cover_mode
.IsValid(cover_mode
)) {
14460 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, cover_mode
, "coverMode");
14461 return error::kNoError
;
14463 GLuint service_id
= 0;
14464 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
))
14465 return error::kNoError
;
14467 GLint reference
= static_cast<GLint
>(c
.reference
);
14468 GLuint mask
= static_cast<GLuint
>(c
.mask
);
14470 glStencilThenCoverStrokePathNV(service_id
, reference
, mask
, cover_mode
);
14471 return error::kNoError
;
14474 // Include the auto-generated part of this file. We split this because it means
14475 // we can easily edit the non-auto generated parts right here in this file
14476 // instead of having to edit some template or the code generator.
14477 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
14479 } // namespace gles2