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/numerics/safe_math.h"
22 #include "base/strings/string_number_conversions.h"
23 #include "base/trace_event/trace_event.h"
24 #include "base/trace_event/trace_event_synthetic_delay.h"
25 #include "build/build_config.h"
26 #define GLES2_GPU_SERVICE 1
27 #include "gpu/command_buffer/common/debug_marker_manager.h"
28 #include "gpu/command_buffer/common/gles2_cmd_format.h"
29 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
30 #include "gpu/command_buffer/common/mailbox.h"
31 #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
32 #include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
33 #include "gpu/command_buffer/service/buffer_manager.h"
34 #include "gpu/command_buffer/service/context_group.h"
35 #include "gpu/command_buffer/service/context_state.h"
36 #include "gpu/command_buffer/service/error_state.h"
37 #include "gpu/command_buffer/service/feature_info.h"
38 #include "gpu/command_buffer/service/framebuffer_manager.h"
39 #include "gpu/command_buffer/service/gl_utils.h"
40 #include "gpu/command_buffer/service/gles2_cmd_clear_framebuffer.h"
41 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
42 #include "gpu/command_buffer/service/gles2_cmd_validation.h"
43 #include "gpu/command_buffer/service/gpu_state_tracer.h"
44 #include "gpu/command_buffer/service/gpu_switches.h"
45 #include "gpu/command_buffer/service/gpu_tracer.h"
46 #include "gpu/command_buffer/service/image_manager.h"
47 #include "gpu/command_buffer/service/logger.h"
48 #include "gpu/command_buffer/service/mailbox_manager.h"
49 #include "gpu/command_buffer/service/memory_tracking.h"
50 #include "gpu/command_buffer/service/path_manager.h"
51 #include "gpu/command_buffer/service/program_manager.h"
52 #include "gpu/command_buffer/service/query_manager.h"
53 #include "gpu/command_buffer/service/renderbuffer_manager.h"
54 #include "gpu/command_buffer/service/shader_manager.h"
55 #include "gpu/command_buffer/service/shader_translator.h"
56 #include "gpu/command_buffer/service/texture_manager.h"
57 #include "gpu/command_buffer/service/valuebuffer_manager.h"
58 #include "gpu/command_buffer/service/vertex_array_manager.h"
59 #include "gpu/command_buffer/service/vertex_attrib_manager.h"
60 #include "third_party/smhasher/src/City.h"
61 #include "ui/gfx/geometry/point.h"
62 #include "ui/gfx/geometry/rect.h"
63 #include "ui/gfx/geometry/size.h"
64 #include "ui/gfx/overlay_transform.h"
65 #include "ui/gl/gl_bindings.h"
66 #include "ui/gl/gl_context.h"
67 #include "ui/gl/gl_fence.h"
68 #include "ui/gl/gl_image.h"
69 #include "ui/gl/gl_implementation.h"
70 #include "ui/gl/gl_surface.h"
71 #include "ui/gl/gpu_timing.h"
73 #if defined(OS_MACOSX)
74 #include <IOSurface/IOSurface.h>
75 // Note that this must be included after gl_bindings.h to avoid conflicts.
76 #include <OpenGL/CGLIOSurface.h>
84 const char kOESDerivativeExtension
[] = "GL_OES_standard_derivatives";
85 const char kEXTFragDepthExtension
[] = "GL_EXT_frag_depth";
86 const char kEXTDrawBuffersExtension
[] = "GL_EXT_draw_buffers";
87 const char kEXTShaderTextureLodExtension
[] = "GL_EXT_shader_texture_lod";
89 const GLfloat kIdentityMatrix
[16] = {1.0f
, 0.0f
, 0.0f
, 0.0f
,
90 0.0f
, 1.0f
, 0.0f
, 0.0f
,
91 0.0f
, 0.0f
, 1.0f
, 0.0f
,
92 0.0f
, 0.0f
, 0.0f
, 1.0f
};
94 bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin
,
97 return (rangeMin
>= 62) && (rangeMax
>= 62) && (precision
>= 16);
100 void GetShaderPrecisionFormatImpl(GLenum shader_type
,
101 GLenum precision_type
,
102 GLint
* range
, GLint
* precision
) {
103 switch (precision_type
) {
107 // These values are for a 32-bit twos-complement integer format.
113 case GL_MEDIUM_FLOAT
:
115 // These values are for an IEEE single-precision floating-point format.
125 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
&&
126 gfx::g_driver_gl
.fn
.glGetShaderPrecisionFormatFn
) {
127 // This function is sometimes defined even though it's really just
128 // a stub, so we need to set range and precision as if it weren't
129 // defined before calling it.
130 // On Mac OS with some GPUs, calling this generates a
131 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
133 glGetShaderPrecisionFormat(shader_type
, precision_type
,
136 // TODO(brianderson): Make the following official workarounds.
138 // Some drivers have bugs where they report the ranges as a negative number.
139 // Taking the absolute value here shouldn't hurt because negative numbers
140 // aren't expected anyway.
141 range
[0] = abs(range
[0]);
142 range
[1] = abs(range
[1]);
144 // If the driver reports a precision for highp float that isn't actually
145 // highp, don't pretend like it's supported because shader compilation will
147 if (precision_type
== GL_HIGH_FLOAT
&&
148 !PrecisionMeetsSpecForHighpFloat(range
[0], range
[1], *precision
)) {
156 gfx::OverlayTransform
GetGFXOverlayTransform(GLenum plane_transform
) {
157 switch (plane_transform
) {
158 case GL_OVERLAY_TRANSFORM_NONE_CHROMIUM
:
159 return gfx::OVERLAY_TRANSFORM_NONE
;
160 case GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM
:
161 return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL
;
162 case GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM
:
163 return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL
;
164 case GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM
:
165 return gfx::OVERLAY_TRANSFORM_ROTATE_90
;
166 case GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM
:
167 return gfx::OVERLAY_TRANSFORM_ROTATE_180
;
168 case GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM
:
169 return gfx::OVERLAY_TRANSFORM_ROTATE_270
;
171 return gfx::OVERLAY_TRANSFORM_INVALID
;
175 template <typename MANAGER_TYPE
, typename OBJECT_TYPE
>
176 GLuint
GetClientId(const MANAGER_TYPE
* manager
, const OBJECT_TYPE
* object
) {
178 GLuint client_id
= 0;
180 manager
->GetClientId(object
->service_id(), &client_id
);
186 explicit Vec4f(const Vec4
& data
) {
193 // Returns the union of |rect1| and |rect2| if one of the rectangles is empty,
194 // contains the other rectangle or shares an edge with the other rectangle.
195 bool CombineAdjacentRects(const gfx::Rect
& rect1
,
196 const gfx::Rect
& rect2
,
198 // Return |rect2| if |rect1| is empty or |rect2| contains |rect1|.
199 if (rect1
.IsEmpty() || rect2
.Contains(rect1
)) {
204 // Return |rect1| if |rect2| is empty or |rect1| contains |rect2|.
205 if (rect2
.IsEmpty() || rect1
.Contains(rect2
)) {
210 // Return the union of |rect1| and |rect2| if they share an edge.
211 if (rect1
.SharesEdgeWith(rect2
)) {
212 *result
= gfx::UnionRects(rect1
, rect2
);
216 // Return false if it's not possible to combine |rect1| and |rect2|.
222 class GLES2DecoderImpl
;
224 // Local versions of the SET_GL_ERROR macros
225 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
226 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
227 #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
228 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
229 function_name, value, label)
230 #define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
231 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
232 function_name, pname)
233 #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
234 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
236 #define LOCAL_PEEK_GL_ERROR(function_name) \
237 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
238 #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
239 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
240 #define LOCAL_PERFORMANCE_WARNING(msg) \
241 PerformanceWarning(__FILE__, __LINE__, msg)
242 #define LOCAL_RENDER_WARNING(msg) \
243 RenderWarning(__FILE__, __LINE__, msg)
245 // Check that certain assumptions the code makes are true. There are places in
246 // the code where shared memory is passed direclty to GL. Example, glUniformiv,
247 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
248 // a few others) are 32bits. If they are not 32bits the code will have to change
249 // to call those GL functions with service side memory and then copy the results
250 // to shared memory, converting the sizes.
251 static_assert(sizeof(GLint
) == sizeof(uint32
), // NOLINT
252 "GLint should be the same size as uint32");
253 static_assert(sizeof(GLsizei
) == sizeof(uint32
), // NOLINT
254 "GLsizei should be the same size as uint32");
255 static_assert(sizeof(GLfloat
) == sizeof(float), // NOLINT
256 "GLfloat should be the same size as float");
258 // TODO(kbr): the use of this anonymous namespace core dumps the
259 // linker on Mac OS X 10.6 when the symbol ordering file is used
262 // Returns the address of the first byte after a struct.
263 template <typename T
>
264 const void* AddressAfterStruct(const T
& pod
) {
265 return reinterpret_cast<const uint8
*>(&pod
) + sizeof(pod
);
268 // Returns the address of the frst byte after the struct or NULL if size >
269 // immediate_data_size.
270 template <typename RETURN_TYPE
, typename COMMAND_TYPE
>
271 RETURN_TYPE
GetImmediateDataAs(const COMMAND_TYPE
& pod
,
273 uint32 immediate_data_size
) {
274 return (size
<= immediate_data_size
) ?
275 static_cast<RETURN_TYPE
>(const_cast<void*>(AddressAfterStruct(pod
))) :
279 // Computes the data size for certain gl commands like glUniform.
280 bool ComputeDataSize(
283 unsigned int elements_per_unit
,
286 if (!SafeMultiplyUint32(count
, size
, &value
)) {
289 if (!SafeMultiplyUint32(value
, elements_per_unit
, &value
)) {
296 // Return true if a character belongs to the ASCII subset as defined in
297 // GLSL ES 1.0 spec section 3.1.
298 static bool CharacterIsValidForGLES(unsigned char c
) {
299 // Printing characters are valid except " $ ` @ \ ' DEL.
300 if (c
>= 32 && c
<= 126 &&
309 // Horizontal tab, line feed, vertical tab, form feed, carriage return
311 if (c
>= 9 && c
<= 13) {
318 static bool StringIsValidForGLES(const char* str
) {
319 for (; *str
; ++str
) {
320 if (!CharacterIsValidForGLES(*str
)) {
327 // This class prevents any GL errors that occur when it is in scope from
328 // being reported to the client.
329 class ScopedGLErrorSuppressor
{
331 explicit ScopedGLErrorSuppressor(
332 const char* function_name
, ErrorState
* error_state
);
333 ~ScopedGLErrorSuppressor();
335 const char* function_name_
;
336 ErrorState
* error_state_
;
337 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor
);
340 // Temporarily changes a decoder's bound texture and restore it when this
341 // object goes out of scope. Also temporarily switches to using active texture
342 // unit zero in case the client has changed that to something invalid.
343 class ScopedTextureBinder
{
345 explicit ScopedTextureBinder(ContextState
* state
, GLuint id
, GLenum target
);
346 ~ScopedTextureBinder();
349 ContextState
* state_
;
351 DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder
);
354 // Temporarily changes a decoder's bound render buffer and restore it when this
355 // object goes out of scope.
356 class ScopedRenderBufferBinder
{
358 explicit ScopedRenderBufferBinder(ContextState
* state
, GLuint id
);
359 ~ScopedRenderBufferBinder();
362 ContextState
* state_
;
363 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder
);
366 // Temporarily changes a decoder's bound frame buffer and restore it when this
367 // object goes out of scope.
368 class ScopedFrameBufferBinder
{
370 explicit ScopedFrameBufferBinder(GLES2DecoderImpl
* decoder
, GLuint id
);
371 ~ScopedFrameBufferBinder();
374 GLES2DecoderImpl
* decoder_
;
375 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder
);
378 // Temporarily changes a decoder's bound frame buffer to a resolved version of
379 // the multisampled offscreen render buffer if that buffer is multisampled, and,
380 // if it is bound or enforce_internal_framebuffer is true. If internal is
381 // true, the resolved framebuffer is not visible to the parent.
382 class ScopedResolvedFrameBufferBinder
{
384 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl
* decoder
,
385 bool enforce_internal_framebuffer
,
387 ~ScopedResolvedFrameBufferBinder();
390 GLES2DecoderImpl
* decoder_
;
391 bool resolve_and_bind_
;
392 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder
);
395 class ScopedModifyPixels
{
397 explicit ScopedModifyPixels(TextureRef
* ref
);
398 ~ScopedModifyPixels();
404 ScopedModifyPixels::ScopedModifyPixels(TextureRef
* ref
) : ref_(ref
) {
406 ref_
->texture()->OnWillModifyPixels();
409 ScopedModifyPixels::~ScopedModifyPixels() {
411 ref_
->texture()->OnDidModifyPixels();
414 class ScopedRenderTo
{
416 explicit ScopedRenderTo(Framebuffer
* framebuffer
);
420 const Framebuffer
* framebuffer_
;
423 ScopedRenderTo::ScopedRenderTo(Framebuffer
* framebuffer
)
424 : framebuffer_(framebuffer
) {
426 framebuffer_
->OnWillRenderTo();
429 ScopedRenderTo::~ScopedRenderTo() {
431 framebuffer_
->OnDidRenderTo();
434 // Encapsulates an OpenGL texture.
437 explicit BackTexture(MemoryTracker
* memory_tracker
, ContextState
* state
);
440 // Create a new render texture.
443 // Set the initial size and format of a render texture or resize it.
444 bool AllocateStorage(const gfx::Size
& size
, GLenum format
, bool zero
);
446 // Copy the contents of the currently bound frame buffer.
447 void Copy(const gfx::Size
& size
, GLenum format
);
449 // Destroy the render texture. This must be explicitly called before
450 // destroying this object.
453 // Invalidate the texture. This can be used when a context is lost and it is
454 // not possible to make it current in order to free the resource.
461 gfx::Size
size() const {
466 MemoryTypeTracker memory_tracker_
;
467 ContextState
* state_
;
468 size_t bytes_allocated_
;
471 DISALLOW_COPY_AND_ASSIGN(BackTexture
);
474 // Encapsulates an OpenGL render buffer of any format.
475 class BackRenderbuffer
{
477 explicit BackRenderbuffer(
478 RenderbufferManager
* renderbuffer_manager
,
479 MemoryTracker
* memory_tracker
,
480 ContextState
* state
);
483 // Create a new render buffer.
486 // Set the initial size and format of a render buffer or resize it.
487 bool AllocateStorage(const FeatureInfo
* feature_info
,
488 const gfx::Size
& size
,
492 // Destroy the render buffer. This must be explicitly called before destroying
496 // Invalidate the render buffer. This can be used when a context is lost and
497 // it is not possible to make it current in order to free the resource.
505 RenderbufferManager
* renderbuffer_manager_
;
506 MemoryTypeTracker memory_tracker_
;
507 ContextState
* state_
;
508 size_t bytes_allocated_
;
510 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer
);
513 // Encapsulates an OpenGL frame buffer.
514 class BackFramebuffer
{
516 explicit BackFramebuffer(GLES2DecoderImpl
* decoder
);
519 // Create a new frame buffer.
522 // Attach a color render buffer to a frame buffer.
523 void AttachRenderTexture(BackTexture
* texture
);
525 // Attach a render buffer to a frame buffer. Note that this unbinds any
526 // currently bound frame buffer.
527 void AttachRenderBuffer(GLenum target
, BackRenderbuffer
* render_buffer
);
529 // Destroy the frame buffer. This must be explicitly called before destroying
533 // Invalidate the frame buffer. This can be used when a context is lost and it
534 // is not possible to make it current in order to free the resource.
537 // See glCheckFramebufferStatusEXT.
538 GLenum
CheckStatus();
545 GLES2DecoderImpl
* decoder_
;
547 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer
);
550 struct FenceCallback
{
552 : fence(gfx::GLFence::Create()) {
555 std::vector
<base::Closure
> callbacks
;
556 scoped_ptr
<gfx::GLFence
> fence
;
559 class AsyncUploadTokenCompletionObserver
560 : public AsyncPixelTransferCompletionObserver
{
562 explicit AsyncUploadTokenCompletionObserver(uint32 async_upload_token
)
563 : async_upload_token_(async_upload_token
) {
566 void DidComplete(const AsyncMemoryParams
& mem_params
) override
{
567 DCHECK(mem_params
.buffer().get());
568 void* data
= mem_params
.GetDataAddress();
569 AsyncUploadSync
* sync
= static_cast<AsyncUploadSync
*>(data
);
570 sync
->SetAsyncUploadToken(async_upload_token_
);
574 ~AsyncUploadTokenCompletionObserver() override
{}
576 uint32 async_upload_token_
;
578 DISALLOW_COPY_AND_ASSIGN(AsyncUploadTokenCompletionObserver
);
581 // } // anonymous namespace.
584 const unsigned int GLES2Decoder::kDefaultStencilMask
=
585 static_cast<unsigned int>(-1);
587 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id
,
588 uint32
* service_texture_id
) {
592 GLES2Decoder::GLES2Decoder()
593 : initialized_(false),
595 log_commands_(false),
596 unsafe_es3_apis_enabled_(false) {
599 GLES2Decoder::~GLES2Decoder() {
602 void GLES2Decoder::BeginDecoding() {}
604 void GLES2Decoder::EndDecoding() {}
606 // This class implements GLES2Decoder so we don't have to expose all the GLES2
607 // cmd stuff to outside this class.
608 class GLES2DecoderImpl
: public GLES2Decoder
,
609 public FramebufferManager::TextureDetachObserver
,
610 public ErrorStateClient
{
612 explicit GLES2DecoderImpl(ContextGroup
* group
);
613 ~GLES2DecoderImpl() override
;
615 // Overridden from AsyncAPIInterface.
616 Error
DoCommand(unsigned int command
,
617 unsigned int arg_count
,
618 const void* args
) override
;
620 error::Error
DoCommands(unsigned int num_commands
,
623 int* entries_processed
) override
;
625 template <bool DebugImpl
>
626 error::Error
DoCommandsImpl(unsigned int num_commands
,
629 int* entries_processed
);
631 // Overridden from AsyncAPIInterface.
632 const char* GetCommandName(unsigned int command_id
) const override
;
634 // Overridden from GLES2Decoder.
635 bool Initialize(const scoped_refptr
<gfx::GLSurface
>& surface
,
636 const scoped_refptr
<gfx::GLContext
>& context
,
638 const gfx::Size
& offscreen_size
,
639 const DisallowedFeatures
& disallowed_features
,
640 const std::vector
<int32
>& attribs
) override
;
641 void Destroy(bool have_context
) override
;
642 void SetSurface(const scoped_refptr
<gfx::GLSurface
>& surface
) override
;
643 void ProduceFrontBuffer(const Mailbox
& mailbox
) override
;
644 bool ResizeOffscreenFrameBuffer(const gfx::Size
& size
) override
;
645 void UpdateParentTextureInfo();
646 bool MakeCurrent() override
;
647 GLES2Util
* GetGLES2Util() override
{ return &util_
; }
648 gfx::GLContext
* GetGLContext() override
{ return context_
.get(); }
649 ContextGroup
* GetContextGroup() override
{ return group_
.get(); }
650 Capabilities
GetCapabilities() override
;
651 void RestoreState(const ContextState
* prev_state
) override
;
653 void RestoreActiveTexture() const override
{ state_
.RestoreActiveTexture(); }
654 void RestoreAllTextureUnitBindings(
655 const ContextState
* prev_state
) const override
{
656 state_
.RestoreAllTextureUnitBindings(prev_state
);
658 void RestoreActiveTextureUnitBinding(unsigned int target
) const override
{
659 state_
.RestoreActiveTextureUnitBinding(target
);
661 void RestoreBufferBindings() const override
{
662 state_
.RestoreBufferBindings();
664 void RestoreGlobalState() const override
{ state_
.RestoreGlobalState(NULL
); }
665 void RestoreProgramBindings() const override
{
666 state_
.RestoreProgramBindings();
668 void RestoreTextureUnitBindings(unsigned unit
) const override
{
669 state_
.RestoreTextureUnitBindings(unit
, NULL
);
671 void RestoreFramebufferBindings() const override
;
672 void RestoreRenderbufferBindings() override
;
673 void RestoreTextureState(unsigned service_id
) const override
;
675 void ClearAllAttributes() const override
;
676 void RestoreAllAttributes() const override
;
678 QueryManager
* GetQueryManager() override
{ return query_manager_
.get(); }
679 VertexArrayManager
* GetVertexArrayManager() override
{
680 return vertex_array_manager_
.get();
682 ImageManager
* GetImageManager() override
{ return image_manager_
.get(); }
684 ValuebufferManager
* GetValuebufferManager() override
{
685 return valuebuffer_manager();
688 bool ProcessPendingQueries(bool did_finish
) override
;
690 bool HasMoreIdleWork() override
;
691 void PerformIdleWork() override
;
693 void WaitForReadPixels(base::Closure callback
) override
;
695 void SetResizeCallback(
696 const base::Callback
<void(gfx::Size
, float)>& callback
) override
;
698 Logger
* GetLogger() override
;
700 void BeginDecoding() override
;
701 void EndDecoding() override
;
703 ErrorState
* GetErrorState() override
;
704 const ContextState
* GetContextState() override
{ return &state_
; }
706 void SetShaderCacheCallback(const ShaderCacheCallback
& callback
) override
;
707 void SetWaitSyncPointCallback(const WaitSyncPointCallback
& callback
) override
;
709 AsyncPixelTransferManager
* GetAsyncPixelTransferManager() override
;
710 void ResetAsyncPixelTransferManagerForTest() override
;
711 void SetAsyncPixelTransferManagerForTest(
712 AsyncPixelTransferManager
* manager
) override
;
713 void SetIgnoreCachedStateForTest(bool ignore
) override
;
714 void ProcessFinishedAsyncTransfers();
716 bool GetServiceTextureId(uint32 client_texture_id
,
717 uint32
* service_texture_id
) override
;
719 uint32
GetTextureUploadCount() override
;
720 base::TimeDelta
GetTotalTextureUploadTime() override
;
721 base::TimeDelta
GetTotalProcessingCommandsTime() override
;
722 void AddProcessingCommandsTime(base::TimeDelta
) override
;
724 // Restores the current state to the user's settings.
725 void RestoreCurrentFramebufferBindings();
727 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
728 void ApplyDirtyState();
730 // These check the state of the currently bound framebuffer or the
731 // backbuffer if no framebuffer is bound.
732 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
733 // check with all attached and enabled color attachments.
734 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers
);
735 bool BoundFramebufferHasDepthAttachment();
736 bool BoundFramebufferHasStencilAttachment();
738 error::ContextLostReason
GetContextLostReason() override
;
740 // Overridden from FramebufferManager::TextureDetachObserver:
741 void OnTextureRefDetachedFromFramebuffer(TextureRef
* texture
) override
;
743 // Overriden from ErrorStateClient.
744 void OnContextLostError() override
;
745 void OnOutOfMemoryError() override
;
747 // Ensure Renderbuffer corresponding to last DoBindRenderbuffer() is bound.
748 void EnsureRenderbufferBound();
750 // Helpers to facilitate calling into compatible extensions.
751 static void RenderbufferStorageMultisampleHelper(
752 const FeatureInfo
* feature_info
,
755 GLenum internal_format
,
759 void BlitFramebufferHelper(GLint srcX0
,
771 friend class ScopedFrameBufferBinder
;
772 friend class ScopedResolvedFrameBufferBinder
;
773 friend class BackFramebuffer
;
775 // Initialize or re-initialize the shader translator.
776 bool InitializeShaderTranslator();
778 void UpdateCapabilities();
780 // Helpers for the glGen and glDelete functions.
781 bool GenTexturesHelper(GLsizei n
, const GLuint
* client_ids
);
782 void DeleteTexturesHelper(GLsizei n
, const GLuint
* client_ids
);
783 bool GenBuffersHelper(GLsizei n
, const GLuint
* client_ids
);
784 void DeleteBuffersHelper(GLsizei n
, const GLuint
* client_ids
);
785 bool GenFramebuffersHelper(GLsizei n
, const GLuint
* client_ids
);
786 void DeleteFramebuffersHelper(GLsizei n
, const GLuint
* client_ids
);
787 bool GenRenderbuffersHelper(GLsizei n
, const GLuint
* client_ids
);
788 void DeleteRenderbuffersHelper(GLsizei n
, const GLuint
* client_ids
);
789 bool GenValuebuffersCHROMIUMHelper(GLsizei n
, const GLuint
* client_ids
);
790 void DeleteValuebuffersCHROMIUMHelper(GLsizei n
, const GLuint
* client_ids
);
791 bool GenQueriesEXTHelper(GLsizei n
, const GLuint
* client_ids
);
792 void DeleteQueriesEXTHelper(GLsizei n
, const GLuint
* client_ids
);
793 bool GenVertexArraysOESHelper(GLsizei n
, const GLuint
* client_ids
);
794 void DeleteVertexArraysOESHelper(GLsizei n
, const GLuint
* client_ids
);
795 bool GenPathsCHROMIUMHelper(GLuint first_client_id
, GLsizei range
);
796 bool DeletePathsCHROMIUMHelper(GLuint first_client_id
, GLsizei range
);
798 // Helper for async upload token completion notification callback.
799 base::Closure
AsyncUploadTokenCompletionClosure(uint32 async_upload_token
,
800 uint32 sync_data_shm_id
,
801 uint32 sync_data_shm_offset
);
806 void OnFboChanged() const;
807 void OnUseFramebuffer() const;
809 error::ContextLostReason
GetContextLostReasonFromResetStatus(
810 GLenum reset_status
) const;
812 // TODO(gman): Cache these pointers?
813 BufferManager
* buffer_manager() {
814 return group_
->buffer_manager();
817 RenderbufferManager
* renderbuffer_manager() {
818 return group_
->renderbuffer_manager();
821 FramebufferManager
* framebuffer_manager() {
822 return group_
->framebuffer_manager();
825 ValuebufferManager
* valuebuffer_manager() {
826 return group_
->valuebuffer_manager();
829 PathManager
* path_manager() { return group_
->path_manager(); }
831 ProgramManager
* program_manager() {
832 return group_
->program_manager();
835 ShaderManager
* shader_manager() {
836 return group_
->shader_manager();
839 ShaderTranslatorCache
* shader_translator_cache() {
840 return group_
->shader_translator_cache();
843 const TextureManager
* texture_manager() const {
844 return group_
->texture_manager();
847 TextureManager
* texture_manager() {
848 return group_
->texture_manager();
851 MailboxManager
* mailbox_manager() {
852 return group_
->mailbox_manager();
855 ImageManager
* image_manager() { return image_manager_
.get(); }
857 VertexArrayManager
* vertex_array_manager() {
858 return vertex_array_manager_
.get();
861 MemoryTracker
* memory_tracker() {
862 return group_
->memory_tracker();
865 bool EnsureGPUMemoryAvailable(size_t estimated_size
) {
866 MemoryTracker
* tracker
= memory_tracker();
868 return tracker
->EnsureGPUMemoryAvailable(estimated_size
);
873 bool IsWebGLContext() const {
874 return webgl_version_
== 1 || webgl_version_
== 2;
877 bool IsOffscreenBufferMultisampled() const {
878 return offscreen_target_samples_
> 1;
881 // Creates a Texture for the given texture.
882 TextureRef
* CreateTexture(
883 GLuint client_id
, GLuint service_id
) {
884 return texture_manager()->CreateTexture(client_id
, service_id
);
887 // Gets the texture info for the given texture. Returns NULL if none exists.
888 TextureRef
* GetTexture(GLuint client_id
) const {
889 return texture_manager()->GetTexture(client_id
);
892 // Deletes the texture info for the given texture.
893 void RemoveTexture(GLuint client_id
) {
894 texture_manager()->RemoveTexture(client_id
);
897 // Get the size (in pixels) of the currently bound frame buffer (either FBO
898 // or regular back buffer).
899 gfx::Size
GetBoundReadFrameBufferSize();
901 // Get the format of the currently bound frame buffer (either FBO or regular
903 GLenum
GetBoundReadFrameBufferTextureType();
904 GLenum
GetBoundReadFrameBufferInternalFormat();
905 GLenum
GetBoundDrawFrameBufferInternalFormat();
907 // Wrapper for CompressedTexImage2D commands.
908 error::Error
DoCompressedTexImage2D(
911 GLenum internal_format
,
918 // Wrapper for CompressedTexImage3D commands.
919 error::Error
DoCompressedTexImage3D(
922 GLenum internal_format
,
930 // Wrapper for CompressedTexSubImage2D.
931 void DoCompressedTexSubImage2D(
942 // Wrapper for CompressedTexSubImage3D.
943 void DoCompressedTexSubImage3D(
956 // Wrapper for CopyTexImage2D.
957 void DoCopyTexImage2D(
960 GLenum internal_format
,
967 // Wrapper for SwapBuffers.
968 void DoSwapBuffers();
970 // Wrapper for SwapInterval.
971 void DoSwapInterval(int interval
);
973 // Wrapper for CopyTexSubImage2D.
974 void DoCopyTexSubImage2D(
984 // Validation for TexSubImage2D.
985 bool ValidateTexSubImage2D(
987 const char* function_name
,
998 // Wrapper for TexSubImage2D.
999 error::Error
DoTexSubImage2D(
1010 // Wrapper for TexSubImage3D.
1011 error::Error
DoTexSubImage3D(
1024 // Extra validation for async tex(Sub)Image2D.
1025 bool ValidateAsyncTransfer(
1026 const char* function_name
,
1027 TextureRef
* texture_ref
,
1032 // Wrapper for TexImageIOSurface2DCHROMIUM.
1033 void DoTexImageIOSurface2DCHROMIUM(
1037 GLuint io_surface_id
,
1040 void DoCopyTextureCHROMIUM(GLenum target
,
1043 GLenum internal_format
,
1045 GLboolean unpack_flip_y
,
1046 GLboolean unpack_premultiply_alpha
,
1047 GLboolean unpack_unmultiply_alpha
);
1049 void DoCopySubTextureCHROMIUM(GLenum target
,
1058 GLboolean unpack_flip_y
,
1059 GLboolean unpack_premultiply_alpha
,
1060 GLboolean unpack_unmultiply_alpha
);
1062 void DoCompressedCopyTextureCHROMIUM(GLenum target
,
1066 // Wrapper for TexStorage2DEXT.
1067 void DoTexStorage2DEXT(
1070 GLenum internal_format
,
1074 void DoProduceTextureCHROMIUM(GLenum target
, const GLbyte
* key
);
1075 void DoProduceTextureDirectCHROMIUM(GLuint texture
, GLenum target
,
1077 void ProduceTextureRef(std::string func_name
, TextureRef
* texture_ref
,
1078 GLenum target
, const GLbyte
* data
);
1080 void EnsureTextureForClientId(GLenum target
, GLuint client_id
);
1081 void DoConsumeTextureCHROMIUM(GLenum target
, const GLbyte
* key
);
1082 void DoCreateAndConsumeTextureCHROMIUM(GLenum target
, const GLbyte
* key
,
1085 bool DoIsValuebufferCHROMIUM(GLuint client_id
);
1086 void DoBindValueBufferCHROMIUM(GLenum target
, GLuint valuebuffer
);
1087 void DoSubscribeValueCHROMIUM(GLenum target
, GLenum subscription
);
1088 void DoPopulateSubscribedValuesCHROMIUM(GLenum target
);
1089 void DoUniformValueBufferCHROMIUM(GLint location
,
1091 GLenum subscription
);
1093 void DoBindTexImage2DCHROMIUM(
1096 void DoReleaseTexImage2DCHROMIUM(
1100 void DoTraceEndCHROMIUM(void);
1102 void DoDrawBuffersEXT(GLsizei count
, const GLenum
* bufs
);
1104 void DoLoseContextCHROMIUM(GLenum current
, GLenum other
);
1106 void DoFlushDriverCachesCHROMIUM(void);
1108 void DoMatrixLoadfCHROMIUM(GLenum matrix_mode
, const GLfloat
* matrix
);
1109 void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode
);
1111 // Creates a Program for the given program.
1112 Program
* CreateProgram(
1113 GLuint client_id
, GLuint service_id
) {
1114 return program_manager()->CreateProgram(client_id
, service_id
);
1117 // Gets the program info for the given program. Returns NULL if none exists.
1118 Program
* GetProgram(GLuint client_id
) {
1119 return program_manager()->GetProgram(client_id
);
1123 void LogClientServiceMapping(
1124 const char* /* function_name */,
1125 GLuint
/* client_id */,
1126 GLuint
/* service_id */) {
1128 template<typename T
>
1129 void LogClientServiceForInfo(
1130 T
* /* info */, GLuint
/* client_id */, const char* /* function_name */) {
1133 void LogClientServiceMapping(
1134 const char* function_name
, GLuint client_id
, GLuint service_id
) {
1135 if (service_logging_
) {
1136 VLOG(1) << "[" << logger_
.GetLogPrefix() << "] " << function_name
1137 << ": client_id = " << client_id
1138 << ", service_id = " << service_id
;
1141 template<typename T
>
1142 void LogClientServiceForInfo(
1143 T
* info
, GLuint client_id
, const char* function_name
) {
1145 LogClientServiceMapping(function_name
, client_id
, info
->service_id());
1150 // Gets the program info for the given program. If it's not a program
1151 // generates a GL error. Returns NULL if not program.
1152 Program
* GetProgramInfoNotShader(
1153 GLuint client_id
, const char* function_name
) {
1154 Program
* program
= GetProgram(client_id
);
1156 if (GetShader(client_id
)) {
1158 GL_INVALID_OPERATION
, function_name
, "shader passed for program");
1160 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown program");
1163 LogClientServiceForInfo(program
, client_id
, function_name
);
1168 // Creates a Shader for the given shader.
1169 Shader
* CreateShader(
1172 GLenum shader_type
) {
1173 return shader_manager()->CreateShader(
1174 client_id
, service_id
, shader_type
);
1177 // Gets the shader info for the given shader. Returns NULL if none exists.
1178 Shader
* GetShader(GLuint client_id
) {
1179 return shader_manager()->GetShader(client_id
);
1182 // Gets the shader info for the given shader. If it's not a shader generates a
1183 // GL error. Returns NULL if not shader.
1184 Shader
* GetShaderInfoNotProgram(
1185 GLuint client_id
, const char* function_name
) {
1186 Shader
* shader
= GetShader(client_id
);
1188 if (GetProgram(client_id
)) {
1190 GL_INVALID_OPERATION
, function_name
, "program passed for shader");
1193 GL_INVALID_VALUE
, function_name
, "unknown shader");
1196 LogClientServiceForInfo(shader
, client_id
, function_name
);
1200 // Creates a buffer info for the given buffer.
1201 void CreateBuffer(GLuint client_id
, GLuint service_id
) {
1202 return buffer_manager()->CreateBuffer(client_id
, service_id
);
1205 // Gets the buffer info for the given buffer.
1206 Buffer
* GetBuffer(GLuint client_id
) {
1207 Buffer
* buffer
= buffer_manager()->GetBuffer(client_id
);
1211 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1212 // on glDeleteBuffers so we can make sure the user does not try to render
1213 // with deleted buffers.
1214 void RemoveBuffer(GLuint client_id
);
1216 // Creates a framebuffer info for the given framebuffer.
1217 void CreateFramebuffer(GLuint client_id
, GLuint service_id
) {
1218 return framebuffer_manager()->CreateFramebuffer(client_id
, service_id
);
1221 // Gets the framebuffer info for the given framebuffer.
1222 Framebuffer
* GetFramebuffer(GLuint client_id
) {
1223 return framebuffer_manager()->GetFramebuffer(client_id
);
1226 // Removes the framebuffer info for the given framebuffer.
1227 void RemoveFramebuffer(GLuint client_id
) {
1228 framebuffer_manager()->RemoveFramebuffer(client_id
);
1231 // Creates a renderbuffer info for the given renderbuffer.
1232 void CreateRenderbuffer(GLuint client_id
, GLuint service_id
) {
1233 return renderbuffer_manager()->CreateRenderbuffer(
1234 client_id
, service_id
);
1237 // Gets the renderbuffer info for the given renderbuffer.
1238 Renderbuffer
* GetRenderbuffer(GLuint client_id
) {
1239 return renderbuffer_manager()->GetRenderbuffer(client_id
);
1242 // Removes the renderbuffer info for the given renderbuffer.
1243 void RemoveRenderbuffer(GLuint client_id
) {
1244 renderbuffer_manager()->RemoveRenderbuffer(client_id
);
1247 // Creates a valuebuffer info for the given valuebuffer.
1248 void CreateValuebuffer(GLuint client_id
) {
1249 return valuebuffer_manager()->CreateValuebuffer(client_id
);
1252 // Gets the valuebuffer info for a given valuebuffer.
1253 Valuebuffer
* GetValuebuffer(GLuint client_id
) {
1254 return valuebuffer_manager()->GetValuebuffer(client_id
);
1257 // Removes the valuebuffer info for the given valuebuffer.
1258 void RemoveValuebuffer(GLuint client_id
) {
1259 valuebuffer_manager()->RemoveValuebuffer(client_id
);
1262 // Gets the vertex attrib manager for the given vertex array.
1263 VertexAttribManager
* GetVertexAttribManager(GLuint client_id
) {
1264 VertexAttribManager
* info
=
1265 vertex_array_manager()->GetVertexAttribManager(client_id
);
1269 // Removes the vertex attrib manager for the given vertex array.
1270 void RemoveVertexAttribManager(GLuint client_id
) {
1271 vertex_array_manager()->RemoveVertexAttribManager(client_id
);
1274 // Creates a vertex attrib manager for the given vertex array.
1275 scoped_refptr
<VertexAttribManager
> CreateVertexAttribManager(
1278 bool client_visible
) {
1279 return vertex_array_manager()->CreateVertexAttribManager(
1280 client_id
, service_id
, group_
->max_vertex_attribs(), client_visible
);
1283 void DoBindAttribLocation(GLuint client_id
, GLuint index
, const char* name
);
1284 void DoBindUniformLocationCHROMIUM(
1285 GLuint client_id
, GLint location
, const char* name
);
1287 error::Error
GetAttribLocationHelper(
1288 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1289 const std::string
& name_str
);
1291 error::Error
GetUniformLocationHelper(
1292 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1293 const std::string
& name_str
);
1295 error::Error
GetFragDataLocationHelper(
1296 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1297 const std::string
& name_str
);
1299 // Wrapper for glShaderSource.
1300 void DoShaderSource(
1301 GLuint client_id
, GLsizei count
, const char** data
, const GLint
* length
);
1303 // Wrapper for glTransformFeedbackVaryings.
1304 void DoTransformFeedbackVaryings(
1305 GLuint client_program_id
, GLsizei count
, const char* const* varyings
,
1306 GLenum buffer_mode
);
1308 // Clear any textures used by the current program.
1309 bool ClearUnclearedTextures();
1311 // Clears any uncleared attachments attached to the given frame buffer.
1312 // Returns false if there was a generated GL error.
1313 void ClearUnclearedAttachments(GLenum target
, Framebuffer
* framebuffer
);
1315 // overridden from GLES2Decoder
1316 bool ClearLevel(Texture
* texture
,
1324 int height
) override
;
1326 // Restore all GL state that affects clearing.
1327 void RestoreClearState();
1329 // Remembers the state of some capabilities.
1330 // Returns: true if glEnable/glDisable should actually be called.
1331 bool SetCapabilityState(GLenum cap
, bool enabled
);
1333 // Check that the currently bound framebuffers are valid.
1334 // Generates GL error if not.
1335 bool CheckBoundFramebuffersValid(const char* func_name
);
1337 // Check that the currently bound read framebuffer has a color image
1338 // attached. Generates GL error if not.
1339 bool CheckBoundReadFramebufferColorAttachment(const char* func_name
);
1341 // Check that the currently bound read framebuffer's color image
1342 // isn't the target texture of the glCopyTex{Sub}Image2D.
1343 bool FormsTextureCopyingFeedbackLoop(TextureRef
* texture
, GLint level
);
1345 // Check if a framebuffer meets our requirements.
1346 bool CheckFramebufferValid(
1347 Framebuffer
* framebuffer
,
1349 const char* func_name
);
1351 // Check if the current valuebuffer exists and is valid. If not generates
1352 // the appropriate GL error. Returns true if the current valuebuffer is in
1354 bool CheckCurrentValuebuffer(const char* function_name
);
1356 // Check if the current valuebuffer exists and is valiud and that the
1357 // value buffer is actually subscribed to the given subscription
1358 bool CheckCurrentValuebufferForSubscription(GLenum subscription
,
1359 const char* function_name
);
1361 // Check if the location can be used for the given subscription target. If not
1362 // generates the appropriate GL error. Returns true if the location is usable
1363 bool CheckSubscriptionTarget(GLint location
,
1364 GLenum subscription
,
1365 const char* function_name
);
1367 // Checks if the current program exists and is valid. If not generates the
1368 // appropriate GL error. Returns true if the current program is in a usable
1370 bool CheckCurrentProgram(const char* function_name
);
1372 // Checks if the current program exists and is valid and that location is not
1373 // -1. If the current program is not valid generates the appropriate GL
1374 // error. Returns true if the current program is in a usable state and
1375 // location is not -1.
1376 bool CheckCurrentProgramForUniform(GLint location
, const char* function_name
);
1378 // Checks if the current program samples a texture that is also the color
1379 // image of the current bound framebuffer, i.e., the source and destination
1380 // of the draw operation are the same.
1381 bool CheckDrawingFeedbackLoops();
1383 // Checks if |api_type| is valid for the given uniform
1384 // If the api type is not valid generates the appropriate GL
1385 // error. Returns true if |api_type| is valid for the uniform
1386 bool CheckUniformForApiType(const Program::UniformInfo
* info
,
1387 const char* function_name
,
1388 Program::UniformApiType api_type
);
1390 // Gets the type of a uniform for a location in the current program. Sets GL
1391 // errors if the current program is not valid. Returns true if the current
1392 // program is valid and the location exists. Adjusts count so it
1393 // does not overflow the uniform.
1394 bool PrepForSetUniformByLocation(GLint fake_location
,
1395 const char* function_name
,
1396 Program::UniformApiType api_type
,
1397 GLint
* real_location
,
1401 // Gets the service id for any simulated backbuffer fbo.
1402 GLuint
GetBackbufferServiceId() const;
1404 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1405 bool GetHelper(GLenum pname
, GLint
* params
, GLsizei
* num_written
);
1407 // Helper for glGetVertexAttrib
1408 void GetVertexAttribHelper(
1409 const VertexAttrib
* attrib
, GLenum pname
, GLint
* param
);
1411 // Wrapper for glActiveTexture
1412 void DoActiveTexture(GLenum texture_unit
);
1414 // Wrapper for glAttachShader
1415 void DoAttachShader(GLuint client_program_id
, GLint client_shader_id
);
1417 // Wrapper for glBindBuffer since we need to track the current targets.
1418 void DoBindBuffer(GLenum target
, GLuint buffer
);
1420 // Wrapper for glBindFramebuffer since we need to track the current targets.
1421 void DoBindFramebuffer(GLenum target
, GLuint framebuffer
);
1423 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1424 void DoBindRenderbuffer(GLenum target
, GLuint renderbuffer
);
1426 // Wrapper for glBindTexture since we need to track the current targets.
1427 void DoBindTexture(GLenum target
, GLuint texture
);
1429 // Wrapper for glBindVertexArrayOES
1430 void DoBindVertexArrayOES(GLuint array
);
1431 void EmulateVertexArrayState();
1433 // Wrapper for glBlitFramebufferCHROMIUM.
1434 void DoBlitFramebufferCHROMIUM(
1435 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
1436 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
1437 GLbitfield mask
, GLenum filter
);
1439 // Wrapper for glBufferSubData.
1440 void DoBufferSubData(
1441 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
);
1443 // Wrapper for glCheckFramebufferStatus
1444 GLenum
DoCheckFramebufferStatus(GLenum target
);
1446 // Wrapper for glClear
1447 error::Error
DoClear(GLbitfield mask
);
1449 // Wrappers for various state.
1450 void DoDepthRangef(GLclampf znear
, GLclampf zfar
);
1451 void DoSampleCoverage(GLclampf value
, GLboolean invert
);
1453 // Wrapper for glCompileShader.
1454 void DoCompileShader(GLuint shader
);
1456 // Wrapper for glDetachShader
1457 void DoDetachShader(GLuint client_program_id
, GLint client_shader_id
);
1459 // Wrapper for glDisable
1460 void DoDisable(GLenum cap
);
1462 // Wrapper for glDisableVertexAttribArray.
1463 void DoDisableVertexAttribArray(GLuint index
);
1465 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1467 void DoDiscardFramebufferEXT(GLenum target
,
1468 GLsizei numAttachments
,
1469 const GLenum
* attachments
);
1471 // Wrapper for glEnable
1472 void DoEnable(GLenum cap
);
1474 // Wrapper for glEnableVertexAttribArray.
1475 void DoEnableVertexAttribArray(GLuint index
);
1477 // Wrapper for glFinish.
1480 // Wrapper for glFlush.
1483 // Wrapper for glFramebufferRenderbufffer.
1484 void DoFramebufferRenderbuffer(
1485 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
1486 GLuint renderbuffer
);
1488 // Wrapper for glFramebufferTexture2D.
1489 void DoFramebufferTexture2D(
1490 GLenum target
, GLenum attachment
, GLenum textarget
, GLuint texture
,
1493 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1494 void DoFramebufferTexture2DMultisample(
1495 GLenum target
, GLenum attachment
, GLenum textarget
,
1496 GLuint texture
, GLint level
, GLsizei samples
);
1498 // Common implementation for both DoFramebufferTexture2D wrappers.
1499 void DoFramebufferTexture2DCommon(const char* name
,
1500 GLenum target
, GLenum attachment
, GLenum textarget
,
1501 GLuint texture
, GLint level
, GLsizei samples
);
1503 // Wrapper for glFramebufferTextureLayer.
1504 void DoFramebufferTextureLayer(
1505 GLenum target
, GLenum attachment
, GLuint texture
, GLint level
,
1508 // Wrapper for glGenerateMipmap
1509 void DoGenerateMipmap(GLenum target
);
1511 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1512 // to account for different pname values defined in different extension
1514 GLenum
AdjustGetPname(GLenum pname
);
1516 // Wrapper for DoGetBooleanv.
1517 void DoGetBooleanv(GLenum pname
, GLboolean
* params
);
1519 // Wrapper for DoGetFloatv.
1520 void DoGetFloatv(GLenum pname
, GLfloat
* params
);
1522 // Wrapper for glGetFramebufferAttachmentParameteriv.
1523 void DoGetFramebufferAttachmentParameteriv(
1524 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
);
1526 // Wrapper for glGetInteger64v.
1527 void DoGetInteger64v(GLenum pname
, GLint64
* params
);
1529 // Wrapper for glGetIntegerv.
1530 void DoGetIntegerv(GLenum pname
, GLint
* params
);
1532 // Gets the max value in a range in a buffer.
1533 GLuint
DoGetMaxValueInBufferCHROMIUM(
1534 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
);
1536 // Wrapper for glGetBufferParameteriv.
1537 void DoGetBufferParameteriv(
1538 GLenum target
, GLenum pname
, GLint
* params
);
1540 // Wrapper for glGetProgramiv.
1541 void DoGetProgramiv(
1542 GLuint program_id
, GLenum pname
, GLint
* params
);
1544 // Wrapper for glRenderbufferParameteriv.
1545 void DoGetRenderbufferParameteriv(
1546 GLenum target
, GLenum pname
, GLint
* params
);
1548 // Wrapper for glGetShaderiv
1549 void DoGetShaderiv(GLuint shader
, GLenum pname
, GLint
* params
);
1551 // Wrappers for glGetTexParameter.
1552 void DoGetTexParameterfv(GLenum target
, GLenum pname
, GLfloat
* params
);
1553 void DoGetTexParameteriv(GLenum target
, GLenum pname
, GLint
* params
);
1554 void InitTextureMaxAnisotropyIfNeeded(GLenum target
, GLenum pname
);
1556 // Wrappers for glGetVertexAttrib.
1557 template <typename T
>
1558 void DoGetVertexAttribImpl(GLuint index
, GLenum pname
, T
* params
);
1559 void DoGetVertexAttribfv(GLuint index
, GLenum pname
, GLfloat
* params
);
1560 void DoGetVertexAttribiv(GLuint index
, GLenum pname
, GLint
* params
);
1561 void DoGetVertexAttribIiv(GLuint index
, GLenum pname
, GLint
* params
);
1562 void DoGetVertexAttribIuiv(GLuint index
, GLenum pname
, GLuint
* params
);
1564 // Wrappers for glIsXXX functions.
1565 bool DoIsEnabled(GLenum cap
);
1566 bool DoIsBuffer(GLuint client_id
);
1567 bool DoIsFramebuffer(GLuint client_id
);
1568 bool DoIsProgram(GLuint client_id
);
1569 bool DoIsRenderbuffer(GLuint client_id
);
1570 bool DoIsShader(GLuint client_id
);
1571 bool DoIsTexture(GLuint client_id
);
1572 bool DoIsVertexArrayOES(GLuint client_id
);
1573 bool DoIsPathCHROMIUM(GLuint client_id
);
1575 // Wrapper for glLinkProgram
1576 void DoLinkProgram(GLuint program
);
1578 // Wrapper for glRenderbufferStorage.
1579 void DoRenderbufferStorage(
1580 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
);
1582 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1583 void DoRenderbufferStorageMultisampleCHROMIUM(
1584 GLenum target
, GLsizei samples
, GLenum internalformat
,
1585 GLsizei width
, GLsizei height
);
1587 // Handler for glRenderbufferStorageMultisampleEXT
1588 // (multisampled_render_to_texture).
1589 void DoRenderbufferStorageMultisampleEXT(
1590 GLenum target
, GLsizei samples
, GLenum internalformat
,
1591 GLsizei width
, GLsizei height
);
1593 // Common validation for multisample extensions.
1594 bool ValidateRenderbufferStorageMultisample(GLsizei samples
,
1595 GLenum internalformat
,
1599 // Verifies that the currently bound multisample renderbuffer is valid
1600 // Very slow! Only done on platforms with driver bugs that return invalid
1601 // buffers under memory pressure
1602 bool VerifyMultisampleRenderbufferIntegrity(
1603 GLuint renderbuffer
, GLenum format
);
1605 // Wrapper for glReleaseShaderCompiler.
1606 void DoReleaseShaderCompiler() { }
1608 // Wrappers for glSamplerParameter*v functions.
1609 void DoSamplerParameterfv(
1610 GLuint sampler
, GLenum pname
, const GLfloat
* params
);
1611 void DoSamplerParameteriv(GLuint sampler
, GLenum pname
, const GLint
* params
);
1613 // Wrappers for glTexParameter functions.
1614 void DoTexParameterf(GLenum target
, GLenum pname
, GLfloat param
);
1615 void DoTexParameteri(GLenum target
, GLenum pname
, GLint param
);
1616 void DoTexParameterfv(GLenum target
, GLenum pname
, const GLfloat
* params
);
1617 void DoTexParameteriv(GLenum target
, GLenum pname
, const GLint
* params
);
1619 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1620 // spec only these 2 functions can be used to set sampler uniforms.
1621 void DoUniform1i(GLint fake_location
, GLint v0
);
1622 void DoUniform1iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1623 void DoUniform2iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1624 void DoUniform3iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1625 void DoUniform4iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1627 // Wrappers for glUniformfv because some drivers don't correctly accept
1629 void DoUniform1fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1630 void DoUniform2fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1631 void DoUniform3fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1632 void DoUniform4fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1634 void DoUniformMatrix2fv(
1635 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1636 const GLfloat
* value
);
1637 void DoUniformMatrix3fv(
1638 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1639 const GLfloat
* value
);
1640 void DoUniformMatrix4fv(
1641 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1642 const GLfloat
* value
);
1644 template <typename T
>
1645 bool SetVertexAttribValue(
1646 const char* function_name
, GLuint index
, const T
* value
);
1648 // Wrappers for glVertexAttrib??
1649 void DoVertexAttrib1f(GLuint index
, GLfloat v0
);
1650 void DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
);
1651 void DoVertexAttrib3f(GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
);
1652 void DoVertexAttrib4f(
1653 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
);
1654 void DoVertexAttrib1fv(GLuint index
, const GLfloat
* v
);
1655 void DoVertexAttrib2fv(GLuint index
, const GLfloat
* v
);
1656 void DoVertexAttrib3fv(GLuint index
, const GLfloat
* v
);
1657 void DoVertexAttrib4fv(GLuint index
, const GLfloat
* v
);
1658 void DoVertexAttribI4i(GLuint index
, GLint v0
, GLint v1
, GLint v2
, GLint v3
);
1659 void DoVertexAttribI4iv(GLuint index
, const GLint
* v
);
1660 void DoVertexAttribI4ui(
1661 GLuint index
, GLuint v0
, GLuint v1
, GLuint v2
, GLuint v3
);
1662 void DoVertexAttribI4uiv(GLuint index
, const GLuint
* v
);
1664 // Wrapper for glViewport
1665 void DoViewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
1667 // Wrapper for glUseProgram
1668 void DoUseProgram(GLuint program
);
1670 // Wrapper for glValidateProgram.
1671 void DoValidateProgram(GLuint program_client_id
);
1673 void DoInsertEventMarkerEXT(GLsizei length
, const GLchar
* marker
);
1674 void DoPushGroupMarkerEXT(GLsizei length
, const GLchar
* group
);
1675 void DoPopGroupMarkerEXT(void);
1677 // Gets the number of values that will be returned by glGetXXX. Returns
1678 // false if pname is unknown.
1679 bool GetNumValuesReturnedForGLGet(GLenum pname
, GLsizei
* num_values
);
1681 // Checks if the current program and vertex attributes are valid for drawing.
1683 const char* function_name
, GLuint max_vertex_accessed
, bool instanced
,
1686 // Returns true if successful, simulated will be true if attrib0 was
1688 bool SimulateAttrib0(
1689 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
);
1690 void RestoreStateForAttrib(GLuint attrib
, bool restore_array_binding
);
1692 // If an image is bound to texture, this will call Will/DidUseTexImage
1694 void DoWillUseTexImageIfNeeded(Texture
* texture
, GLenum textarget
);
1695 void DoDidUseTexImageIfNeeded(Texture
* texture
, GLenum textarget
);
1697 // Returns false if textures were replaced.
1698 bool PrepareTexturesForRender();
1699 void RestoreStateForTextures();
1701 // Returns true if GL_FIXED attribs were simulated.
1702 bool SimulateFixedAttribs(
1703 const char* function_name
,
1704 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
);
1705 void RestoreStateForSimulatedFixedAttribs();
1707 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1708 // cases (primcount is always 1 for non-instanced).
1709 error::Error
DoDrawArrays(
1710 const char* function_name
,
1711 bool instanced
, GLenum mode
, GLint first
, GLsizei count
,
1713 error::Error
DoDrawElements(
1714 const char* function_name
,
1715 bool instanced
, GLenum mode
, GLsizei count
, GLenum type
,
1716 int32 offset
, GLsizei primcount
);
1718 GLenum
GetBindTargetForSamplerType(GLenum type
) {
1719 DCHECK(type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_CUBE
||
1720 type
== GL_SAMPLER_EXTERNAL_OES
|| type
== GL_SAMPLER_2D_RECT_ARB
);
1723 return GL_TEXTURE_2D
;
1724 case GL_SAMPLER_CUBE
:
1725 return GL_TEXTURE_CUBE_MAP
;
1726 case GL_SAMPLER_EXTERNAL_OES
:
1727 return GL_TEXTURE_EXTERNAL_OES
;
1728 case GL_SAMPLER_2D_RECT_ARB
:
1729 return GL_TEXTURE_RECTANGLE_ARB
;
1736 // Gets the framebuffer info for a particular target.
1737 Framebuffer
* GetFramebufferInfoForTarget(GLenum target
) {
1738 Framebuffer
* framebuffer
= NULL
;
1740 case GL_FRAMEBUFFER
:
1741 case GL_DRAW_FRAMEBUFFER_EXT
:
1742 framebuffer
= framebuffer_state_
.bound_draw_framebuffer
.get();
1744 case GL_READ_FRAMEBUFFER_EXT
:
1745 framebuffer
= framebuffer_state_
.bound_read_framebuffer
.get();
1754 Renderbuffer
* GetRenderbufferInfoForTarget(
1756 Renderbuffer
* renderbuffer
= NULL
;
1758 case GL_RENDERBUFFER
:
1759 renderbuffer
= state_
.bound_renderbuffer
.get();
1765 return renderbuffer
;
1768 // Validates the program and location for a glGetUniform call and returns
1769 // a SizeResult setup to receive the result. Returns true if glGetUniform
1770 // should be called.
1772 bool GetUniformSetup(GLuint program
,
1773 GLint fake_location
,
1776 error::Error
* error
,
1777 GLint
* real_location
,
1779 SizedResult
<T
>** result
,
1780 GLenum
* result_type
,
1781 GLsizei
* result_size
);
1783 bool WasContextLost() const override
;
1784 bool WasContextLostByRobustnessExtension() const override
;
1785 void MarkContextLost(error::ContextLostReason reason
) override
;
1786 bool CheckResetStatus();
1788 #if defined(OS_MACOSX)
1789 void ReleaseIOSurfaceForTexture(GLuint texture_id
);
1792 bool GetCompressedTexSizeInBytes(
1793 const char* function_name
, GLsizei width
, GLsizei height
, GLsizei depth
,
1794 GLenum format
, GLsizei
* size_in_bytes
);
1796 bool ValidateCompressedTexDimensions(
1797 const char* function_name
, GLenum target
, GLint level
,
1798 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
);
1799 bool ValidateCompressedTexFuncData(
1800 const char* function_name
, GLsizei width
, GLsizei height
, GLsizei depth
,
1801 GLenum format
, GLsizei size
);
1802 bool ValidateCompressedTexSubDimensions(
1803 const char* function_name
,
1804 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
1805 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
,
1807 bool ValidateCopyTextureCHROMIUM(const char* function_name
,
1809 TextureRef
* source_texture_ref
,
1810 TextureRef
* dest_texture_ref
,
1811 GLenum dest_internal_format
);
1812 bool ValidateCompressedCopyTextureCHROMIUM(const char* function_name
,
1814 TextureRef
* source_texture_ref
,
1815 TextureRef
* dest_texture_ref
);
1817 void RenderWarning(const char* filename
, int line
, const std::string
& msg
);
1818 void PerformanceWarning(
1819 const char* filename
, int line
, const std::string
& msg
);
1821 const FeatureInfo::FeatureFlags
& features() const {
1822 return feature_info_
->feature_flags();
1825 const FeatureInfo::Workarounds
& workarounds() const {
1826 return feature_info_
->workarounds();
1829 bool ShouldDeferDraws() {
1830 return !offscreen_target_frame_buffer_
.get() &&
1831 framebuffer_state_
.bound_draw_framebuffer
.get() == NULL
&&
1832 surface_
->DeferDraws();
1835 bool ShouldDeferReads() {
1836 return !offscreen_target_frame_buffer_
.get() &&
1837 framebuffer_state_
.bound_read_framebuffer
.get() == NULL
&&
1838 surface_
->DeferDraws();
1841 bool IsRobustnessSupported() {
1842 return has_robustness_extension_
&&
1843 context_
->WasAllocatedUsingRobustnessExtension();
1846 error::Error
WillAccessBoundFramebufferForDraw() {
1847 if (ShouldDeferDraws())
1848 return error::kDeferCommandUntilLater
;
1849 if (!offscreen_target_frame_buffer_
.get() &&
1850 !framebuffer_state_
.bound_draw_framebuffer
.get() &&
1851 !surface_
->SetBackbufferAllocation(true))
1852 return error::kLostContext
;
1853 return error::kNoError
;
1856 error::Error
WillAccessBoundFramebufferForRead() {
1857 if (ShouldDeferReads())
1858 return error::kDeferCommandUntilLater
;
1859 if (!offscreen_target_frame_buffer_
.get() &&
1860 !framebuffer_state_
.bound_read_framebuffer
.get() &&
1861 !surface_
->SetBackbufferAllocation(true))
1862 return error::kLostContext
;
1863 return error::kNoError
;
1866 // Set remaining commands to process to 0 to force DoCommands to return
1867 // and allow context preemption and GPU watchdog checks in GpuScheduler().
1868 void ExitCommandProcessingEarly() { commands_to_process_
= 0; }
1870 void ProcessPendingReadPixels(bool did_finish
);
1871 void FinishReadPixels(const cmds::ReadPixels
& c
, GLuint buffer
);
1873 // Generate a member function prototype for each command in an automated and
1875 #define GLES2_CMD_OP(name) \
1876 Error Handle##name(uint32 immediate_data_size, const void* data);
1878 GLES2_COMMAND_LIST(GLES2_CMD_OP
)
1882 // The GL context this decoder renders to on behalf of the client.
1883 scoped_refptr
<gfx::GLSurface
> surface_
;
1884 scoped_refptr
<gfx::GLContext
> context_
;
1886 // The ContextGroup for this decoder uses to track resources.
1887 scoped_refptr
<ContextGroup
> group_
;
1889 DebugMarkerManager debug_marker_manager_
;
1892 // All the state for this context.
1893 ContextState state_
;
1895 // Current width and height of the offscreen frame buffer.
1896 gfx::Size offscreen_size_
;
1898 // Util to help with GL.
1901 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1902 GLuint attrib_0_buffer_id_
;
1904 // The value currently in attrib_0.
1905 Vec4 attrib_0_value_
;
1907 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1908 bool attrib_0_buffer_matches_value_
;
1910 // The size of attrib 0.
1911 GLsizei attrib_0_size_
;
1913 // The buffer used to simulate GL_FIXED attribs.
1914 GLuint fixed_attrib_buffer_id_
;
1916 // The size of fiixed attrib buffer.
1917 GLsizei fixed_attrib_buffer_size_
;
1919 // The offscreen frame buffer that the client renders to. With EGL, the
1920 // depth and stencil buffers are separate. With regular GL there is a single
1921 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1922 // offscreen_target_stencil_render_buffer_ is unused.
1923 scoped_ptr
<BackFramebuffer
> offscreen_target_frame_buffer_
;
1924 scoped_ptr
<BackTexture
> offscreen_target_color_texture_
;
1925 scoped_ptr
<BackRenderbuffer
> offscreen_target_color_render_buffer_
;
1926 scoped_ptr
<BackRenderbuffer
> offscreen_target_depth_render_buffer_
;
1927 scoped_ptr
<BackRenderbuffer
> offscreen_target_stencil_render_buffer_
;
1928 GLenum offscreen_target_color_format_
;
1929 GLenum offscreen_target_depth_format_
;
1930 GLenum offscreen_target_stencil_format_
;
1931 GLsizei offscreen_target_samples_
;
1932 GLboolean offscreen_target_buffer_preserved_
;
1934 // The copy that is saved when SwapBuffers is called.
1935 scoped_ptr
<BackFramebuffer
> offscreen_saved_frame_buffer_
;
1936 scoped_ptr
<BackTexture
> offscreen_saved_color_texture_
;
1937 scoped_refptr
<TextureRef
>
1938 offscreen_saved_color_texture_info_
;
1940 // The copy that is used as the destination for multi-sample resolves.
1941 scoped_ptr
<BackFramebuffer
> offscreen_resolved_frame_buffer_
;
1942 scoped_ptr
<BackTexture
> offscreen_resolved_color_texture_
;
1943 GLenum offscreen_saved_color_format_
;
1945 scoped_ptr
<QueryManager
> query_manager_
;
1947 scoped_ptr
<VertexArrayManager
> vertex_array_manager_
;
1949 scoped_ptr
<ImageManager
> image_manager_
;
1951 base::Callback
<void(gfx::Size
, float)> resize_callback_
;
1953 WaitSyncPointCallback wait_sync_point_callback_
;
1955 ShaderCacheCallback shader_cache_callback_
;
1957 scoped_ptr
<AsyncPixelTransferManager
> async_pixel_transfer_manager_
;
1959 // The format of the back buffer_
1960 GLenum back_buffer_color_format_
;
1961 bool back_buffer_has_depth_
;
1962 bool back_buffer_has_stencil_
;
1966 // Backbuffer attachments that are currently undefined.
1967 uint32 backbuffer_needs_clear_bits_
;
1969 // The current decoder error communicates the decoder error through command
1970 // processing functions that do not return the error value. Should be set only
1971 // if not returning an error.
1972 error::Error current_decoder_error_
;
1974 bool use_shader_translator_
;
1975 scoped_refptr
<ShaderTranslatorInterface
> vertex_translator_
;
1976 scoped_refptr
<ShaderTranslatorInterface
> fragment_translator_
;
1978 DisallowedFeatures disallowed_features_
;
1980 // Cached from ContextGroup
1981 const Validators
* validators_
;
1982 scoped_refptr
<FeatureInfo
> feature_info_
;
1986 // Number of commands remaining to be processed in DoCommands().
1987 int commands_to_process_
;
1989 bool has_robustness_extension_
;
1990 error::ContextLostReason context_lost_reason_
;
1991 bool context_was_lost_
;
1992 bool reset_by_robustness_extension_
;
1993 bool supports_post_sub_buffer_
;
1995 // Indicates whether this is a context for WebGL1, WebGL2, or others.
1999 unsigned webgl_version_
;
2001 // These flags are used to override the state of the shared feature_info_
2002 // member. Because the same FeatureInfo instance may be shared among many
2003 // contexts, the assumptions on the availablity of extensions in WebGL
2004 // contexts may be broken. These flags override the shared state to preserve
2006 bool derivatives_explicitly_enabled_
;
2007 bool frag_depth_explicitly_enabled_
;
2008 bool draw_buffers_explicitly_enabled_
;
2009 bool shader_texture_lod_explicitly_enabled_
;
2011 bool compile_shader_always_succeeds_
;
2013 // An optional behaviour to lose the context and group when OOM.
2014 bool lose_context_when_out_of_memory_
;
2017 bool service_logging_
;
2019 #if defined(OS_MACOSX)
2020 typedef std::map
<GLuint
, IOSurfaceRef
> TextureToIOSurfaceMap
;
2021 TextureToIOSurfaceMap texture_to_io_surface_map_
;
2024 scoped_ptr
<CopyTextureCHROMIUMResourceManager
> copy_texture_CHROMIUM_
;
2025 scoped_ptr
<ClearFramebufferResourceManager
> clear_framebuffer_blit_
;
2027 // Cached values of the currently assigned viewport dimensions.
2028 GLsizei viewport_max_width_
;
2029 GLsizei viewport_max_height_
;
2031 // Command buffer stats.
2032 base::TimeDelta total_processing_commands_time_
;
2034 // States related to each manager.
2035 DecoderTextureState texture_state_
;
2036 DecoderFramebufferState framebuffer_state_
;
2038 scoped_ptr
<GPUTracer
> gpu_tracer_
;
2039 scoped_ptr
<GPUStateTracer
> gpu_state_tracer_
;
2040 const unsigned char* cb_command_trace_category_
;
2041 const unsigned char* gpu_decoder_category_
;
2042 int gpu_trace_level_
;
2043 bool gpu_trace_commands_
;
2044 bool gpu_debug_commands_
;
2046 std::queue
<linked_ptr
<FenceCallback
> > pending_readpixel_fences_
;
2048 // Used to validate multisample renderbuffers if needed
2049 GLuint validation_texture_
;
2050 GLuint validation_fbo_multisample_
;
2051 GLuint validation_fbo_
;
2053 typedef gpu::gles2::GLES2Decoder::Error (GLES2DecoderImpl::*CmdHandler
)(
2054 uint32 immediate_data_size
,
2057 // A struct to hold info about each command.
2058 struct CommandInfo
{
2059 CmdHandler cmd_handler
;
2060 uint8 arg_flags
; // How to handle the arguments for this command
2061 uint8 cmd_flags
; // How to handle this command
2062 uint16 arg_count
; // How many arguments are expected for this command.
2065 // A table of CommandInfo for all the commands.
2066 static const CommandInfo command_info
[kNumCommands
- kStartPoint
];
2068 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl
);
2071 const GLES2DecoderImpl::CommandInfo
GLES2DecoderImpl::command_info
[] = {
2072 #define GLES2_CMD_OP(name) \
2074 &GLES2DecoderImpl::Handle##name, cmds::name::kArgFlags, \
2075 cmds::name::cmd_flags, \
2076 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, \
2079 GLES2_COMMAND_LIST(GLES2_CMD_OP
)
2083 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
2084 const char* function_name
, ErrorState
* error_state
)
2085 : function_name_(function_name
),
2086 error_state_(error_state
) {
2087 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_
, function_name_
);
2090 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
2091 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_
, function_name_
);
2094 static void RestoreCurrentTextureBindings(ContextState
* state
, GLenum target
) {
2095 TextureUnit
& info
= state
->texture_units
[0];
2097 scoped_refptr
<TextureRef
> texture_ref
;
2100 texture_ref
= info
.bound_texture_2d
;
2102 case GL_TEXTURE_CUBE_MAP
:
2103 texture_ref
= info
.bound_texture_cube_map
;
2105 case GL_TEXTURE_EXTERNAL_OES
:
2106 texture_ref
= info
.bound_texture_external_oes
;
2108 case GL_TEXTURE_RECTANGLE_ARB
:
2109 texture_ref
= info
.bound_texture_rectangle_arb
;
2115 if (texture_ref
.get()) {
2116 last_id
= texture_ref
->service_id();
2121 glBindTexture(target
, last_id
);
2122 glActiveTexture(GL_TEXTURE0
+ state
->active_texture_unit
);
2125 ScopedTextureBinder::ScopedTextureBinder(ContextState
* state
,
2130 ScopedGLErrorSuppressor
suppressor(
2131 "ScopedTextureBinder::ctor", state_
->GetErrorState());
2133 // TODO(apatrick): Check if there are any other states that need to be reset
2134 // before binding a new texture.
2135 glActiveTexture(GL_TEXTURE0
);
2136 glBindTexture(target
, id
);
2139 ScopedTextureBinder::~ScopedTextureBinder() {
2140 ScopedGLErrorSuppressor
suppressor(
2141 "ScopedTextureBinder::dtor", state_
->GetErrorState());
2142 RestoreCurrentTextureBindings(state_
, target_
);
2145 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState
* state
,
2148 ScopedGLErrorSuppressor
suppressor(
2149 "ScopedRenderBufferBinder::ctor", state_
->GetErrorState());
2150 glBindRenderbufferEXT(GL_RENDERBUFFER
, id
);
2153 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
2154 ScopedGLErrorSuppressor
suppressor(
2155 "ScopedRenderBufferBinder::dtor", state_
->GetErrorState());
2156 state_
->RestoreRenderbufferBindings();
2159 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl
* decoder
,
2161 : decoder_(decoder
) {
2162 ScopedGLErrorSuppressor
suppressor(
2163 "ScopedFrameBufferBinder::ctor", decoder_
->GetErrorState());
2164 glBindFramebufferEXT(GL_FRAMEBUFFER
, id
);
2165 decoder
->OnFboChanged();
2168 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
2169 ScopedGLErrorSuppressor
suppressor(
2170 "ScopedFrameBufferBinder::dtor", decoder_
->GetErrorState());
2171 decoder_
->RestoreCurrentFramebufferBindings();
2174 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
2175 GLES2DecoderImpl
* decoder
, bool enforce_internal_framebuffer
, bool internal
)
2176 : decoder_(decoder
) {
2177 resolve_and_bind_
= (
2178 decoder_
->offscreen_target_frame_buffer_
.get() &&
2179 decoder_
->IsOffscreenBufferMultisampled() &&
2180 (!decoder_
->framebuffer_state_
.bound_read_framebuffer
.get() ||
2181 enforce_internal_framebuffer
));
2182 if (!resolve_and_bind_
)
2185 ScopedGLErrorSuppressor
suppressor(
2186 "ScopedResolvedFrameBufferBinder::ctor", decoder_
->GetErrorState());
2187 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
,
2188 decoder_
->offscreen_target_frame_buffer_
->id());
2191 if (!decoder_
->offscreen_resolved_frame_buffer_
.get()) {
2192 decoder_
->offscreen_resolved_frame_buffer_
.reset(
2193 new BackFramebuffer(decoder_
));
2194 decoder_
->offscreen_resolved_frame_buffer_
->Create();
2195 decoder_
->offscreen_resolved_color_texture_
.reset(
2196 new BackTexture(decoder
->memory_tracker(), &decoder
->state_
));
2197 decoder_
->offscreen_resolved_color_texture_
->Create();
2199 DCHECK(decoder_
->offscreen_saved_color_format_
);
2200 decoder_
->offscreen_resolved_color_texture_
->AllocateStorage(
2201 decoder_
->offscreen_size_
, decoder_
->offscreen_saved_color_format_
,
2203 decoder_
->offscreen_resolved_frame_buffer_
->AttachRenderTexture(
2204 decoder_
->offscreen_resolved_color_texture_
.get());
2205 if (decoder_
->offscreen_resolved_frame_buffer_
->CheckStatus() !=
2206 GL_FRAMEBUFFER_COMPLETE
) {
2207 LOG(ERROR
) << "ScopedResolvedFrameBufferBinder failed "
2208 << "because offscreen resolved FBO was incomplete.";
2212 targetid
= decoder_
->offscreen_resolved_frame_buffer_
->id();
2214 targetid
= decoder_
->offscreen_saved_frame_buffer_
->id();
2216 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, targetid
);
2217 const int width
= decoder_
->offscreen_size_
.width();
2218 const int height
= decoder_
->offscreen_size_
.height();
2219 decoder
->state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
2220 decoder
->BlitFramebufferHelper(0,
2228 GL_COLOR_BUFFER_BIT
,
2230 glBindFramebufferEXT(GL_FRAMEBUFFER
, targetid
);
2233 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
2234 if (!resolve_and_bind_
)
2237 ScopedGLErrorSuppressor
suppressor(
2238 "ScopedResolvedFrameBufferBinder::dtor", decoder_
->GetErrorState());
2239 decoder_
->RestoreCurrentFramebufferBindings();
2240 if (decoder_
->state_
.enable_flags
.scissor_test
) {
2241 decoder_
->state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
2245 BackTexture::BackTexture(
2246 MemoryTracker
* memory_tracker
,
2247 ContextState
* state
)
2248 : memory_tracker_(memory_tracker
, MemoryTracker::kUnmanaged
),
2250 bytes_allocated_(0),
2254 BackTexture::~BackTexture() {
2255 // This does not destroy the render texture because that would require that
2256 // the associated GL context was current. Just check that it was explicitly
2261 void BackTexture::Create() {
2262 ScopedGLErrorSuppressor
suppressor("BackTexture::Create",
2263 state_
->GetErrorState());
2265 glGenTextures(1, &id_
);
2266 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2267 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
2268 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
2269 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
2270 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
2272 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
2273 // never called on an offscreen context, no data will ever be uploaded to the
2274 // saved offscreen color texture (it is deferred until to when SwapBuffers
2275 // is called). My idea is that some nvidia drivers might have a bug where
2276 // deleting a texture that has never been populated might cause a
2279 GL_TEXTURE_2D
, 0, GL_RGBA
, 16, 16, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, NULL
);
2281 bytes_allocated_
= 16u * 16u * 4u;
2282 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2285 bool BackTexture::AllocateStorage(
2286 const gfx::Size
& size
, GLenum format
, bool zero
) {
2288 ScopedGLErrorSuppressor
suppressor("BackTexture::AllocateStorage",
2289 state_
->GetErrorState());
2290 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2291 uint32 image_size
= 0;
2292 GLES2Util::ComputeImageDataSizes(
2293 size
.width(), size
.height(), 1, format
, GL_UNSIGNED_BYTE
, 8, &image_size
,
2296 if (!memory_tracker_
.EnsureGPUMemoryAvailable(image_size
)) {
2300 scoped_ptr
<char[]> zero_data
;
2302 zero_data
.reset(new char[image_size
]);
2303 memset(zero_data
.get(), 0, image_size
);
2306 glTexImage2D(GL_TEXTURE_2D
,
2318 bool success
= glGetError() == GL_NO_ERROR
;
2320 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2321 bytes_allocated_
= image_size
;
2322 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2327 void BackTexture::Copy(const gfx::Size
& size
, GLenum format
) {
2329 ScopedGLErrorSuppressor
suppressor("BackTexture::Copy",
2330 state_
->GetErrorState());
2331 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2332 glCopyTexImage2D(GL_TEXTURE_2D
,
2341 void BackTexture::Destroy() {
2343 ScopedGLErrorSuppressor
suppressor("BackTexture::Destroy",
2344 state_
->GetErrorState());
2345 glDeleteTextures(1, &id_
);
2348 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2349 bytes_allocated_
= 0;
2352 void BackTexture::Invalidate() {
2356 BackRenderbuffer::BackRenderbuffer(
2357 RenderbufferManager
* renderbuffer_manager
,
2358 MemoryTracker
* memory_tracker
,
2359 ContextState
* state
)
2360 : renderbuffer_manager_(renderbuffer_manager
),
2361 memory_tracker_(memory_tracker
, MemoryTracker::kUnmanaged
),
2363 bytes_allocated_(0),
2367 BackRenderbuffer::~BackRenderbuffer() {
2368 // This does not destroy the render buffer because that would require that
2369 // the associated GL context was current. Just check that it was explicitly
2374 void BackRenderbuffer::Create() {
2375 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Create",
2376 state_
->GetErrorState());
2378 glGenRenderbuffersEXT(1, &id_
);
2381 bool BackRenderbuffer::AllocateStorage(const FeatureInfo
* feature_info
,
2382 const gfx::Size
& size
,
2385 ScopedGLErrorSuppressor
suppressor(
2386 "BackRenderbuffer::AllocateStorage", state_
->GetErrorState());
2387 ScopedRenderBufferBinder
binder(state_
, id_
);
2389 uint32 estimated_size
= 0;
2390 if (!renderbuffer_manager_
->ComputeEstimatedRenderbufferSize(
2391 size
.width(), size
.height(), samples
, format
, &estimated_size
)) {
2395 if (!memory_tracker_
.EnsureGPUMemoryAvailable(estimated_size
)) {
2400 glRenderbufferStorageEXT(GL_RENDERBUFFER
,
2405 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info
,
2412 bool success
= glGetError() == GL_NO_ERROR
;
2414 // Mark the previously allocated bytes as free.
2415 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2416 bytes_allocated_
= estimated_size
;
2417 // Track the newly allocated bytes.
2418 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2423 void BackRenderbuffer::Destroy() {
2425 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Destroy",
2426 state_
->GetErrorState());
2427 glDeleteRenderbuffersEXT(1, &id_
);
2430 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2431 bytes_allocated_
= 0;
2434 void BackRenderbuffer::Invalidate() {
2438 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl
* decoder
)
2439 : decoder_(decoder
),
2443 BackFramebuffer::~BackFramebuffer() {
2444 // This does not destroy the frame buffer because that would require that
2445 // the associated GL context was current. Just check that it was explicitly
2450 void BackFramebuffer::Create() {
2451 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Create",
2452 decoder_
->GetErrorState());
2454 glGenFramebuffersEXT(1, &id_
);
2457 void BackFramebuffer::AttachRenderTexture(BackTexture
* texture
) {
2459 ScopedGLErrorSuppressor
suppressor(
2460 "BackFramebuffer::AttachRenderTexture", decoder_
->GetErrorState());
2461 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2462 GLuint attach_id
= texture
? texture
->id() : 0;
2463 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
,
2464 GL_COLOR_ATTACHMENT0
,
2470 void BackFramebuffer::AttachRenderBuffer(GLenum target
,
2471 BackRenderbuffer
* render_buffer
) {
2473 ScopedGLErrorSuppressor
suppressor(
2474 "BackFramebuffer::AttachRenderBuffer", decoder_
->GetErrorState());
2475 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2476 GLuint attach_id
= render_buffer
? render_buffer
->id() : 0;
2477 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
,
2483 void BackFramebuffer::Destroy() {
2485 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Destroy",
2486 decoder_
->GetErrorState());
2487 glDeleteFramebuffersEXT(1, &id_
);
2492 void BackFramebuffer::Invalidate() {
2496 GLenum
BackFramebuffer::CheckStatus() {
2498 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::CheckStatus",
2499 decoder_
->GetErrorState());
2500 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2501 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER
);
2504 GLES2Decoder
* GLES2Decoder::Create(ContextGroup
* group
) {
2505 return new GLES2DecoderImpl(group
);
2508 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup
* group
)
2511 logger_(&debug_marker_manager_
),
2512 state_(group_
->feature_info(), this, &logger_
),
2513 attrib_0_buffer_id_(0),
2514 attrib_0_buffer_matches_value_(true),
2516 fixed_attrib_buffer_id_(0),
2517 fixed_attrib_buffer_size_(0),
2518 offscreen_target_color_format_(0),
2519 offscreen_target_depth_format_(0),
2520 offscreen_target_stencil_format_(0),
2521 offscreen_target_samples_(0),
2522 offscreen_target_buffer_preserved_(true),
2523 offscreen_saved_color_format_(0),
2524 back_buffer_color_format_(0),
2525 back_buffer_has_depth_(false),
2526 back_buffer_has_stencil_(false),
2527 surfaceless_(false),
2528 backbuffer_needs_clear_bits_(0),
2529 current_decoder_error_(error::kNoError
),
2530 use_shader_translator_(true),
2531 validators_(group_
->feature_info()->validators()),
2532 feature_info_(group_
->feature_info()),
2534 has_robustness_extension_(false),
2535 context_lost_reason_(error::kUnknown
),
2536 context_was_lost_(false),
2537 reset_by_robustness_extension_(false),
2538 supports_post_sub_buffer_(false),
2540 derivatives_explicitly_enabled_(false),
2541 frag_depth_explicitly_enabled_(false),
2542 draw_buffers_explicitly_enabled_(false),
2543 shader_texture_lod_explicitly_enabled_(false),
2544 compile_shader_always_succeeds_(false),
2545 lose_context_when_out_of_memory_(false),
2546 service_logging_(base::CommandLine::ForCurrentProcess()->HasSwitch(
2547 switches::kEnableGPUServiceLoggingGPU
)),
2548 viewport_max_width_(0),
2549 viewport_max_height_(0),
2550 texture_state_(group_
->feature_info()
2552 .texsubimage_faster_than_teximage
),
2553 cb_command_trace_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2554 TRACE_DISABLED_BY_DEFAULT("cb_command"))),
2555 gpu_decoder_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2556 TRACE_DISABLED_BY_DEFAULT("gpu_decoder"))),
2557 gpu_trace_level_(2),
2558 gpu_trace_commands_(false),
2559 gpu_debug_commands_(false),
2560 validation_texture_(0),
2561 validation_fbo_multisample_(0),
2562 validation_fbo_(0) {
2565 // The shader translator is used for WebGL even when running on EGL
2566 // because additional restrictions are needed (like only enabling
2567 // GL_OES_standard_derivatives on demand). It is used for the unit
2568 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2569 // the empty string to CompileShader and this is not a valid shader.
2570 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL
||
2571 base::CommandLine::ForCurrentProcess()->HasSwitch(
2572 switches::kDisableGLSLTranslator
)) {
2573 use_shader_translator_
= false;
2577 GLES2DecoderImpl::~GLES2DecoderImpl() {
2580 bool GLES2DecoderImpl::Initialize(
2581 const scoped_refptr
<gfx::GLSurface
>& surface
,
2582 const scoped_refptr
<gfx::GLContext
>& context
,
2584 const gfx::Size
& offscreen_size
,
2585 const DisallowedFeatures
& disallowed_features
,
2586 const std::vector
<int32
>& attribs
) {
2587 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2588 DCHECK(context
->IsCurrent(surface
.get()));
2589 DCHECK(!context_
.get());
2590 DCHECK(!offscreen
|| !offscreen_size
.IsEmpty());
2592 ContextCreationAttribHelper attrib_parser
;
2593 if (!attrib_parser
.Parse(attribs
))
2595 webgl_version_
= attrib_parser
.webgl_version
;
2597 surfaceless_
= surface
->IsSurfaceless() && !offscreen
;
2600 gpu_state_tracer_
= GPUStateTracer::Create(&state_
);
2602 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2603 switches::kEnableGPUDebugging
)) {
2607 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2608 switches::kEnableGPUCommandLogging
)) {
2609 set_log_commands(true);
2612 compile_shader_always_succeeds_
=
2613 base::CommandLine::ForCurrentProcess()->HasSwitch(
2614 switches::kCompileShaderAlwaysSucceeds
);
2616 // Take ownership of the context and surface. The surface can be replaced with
2621 // Create GPU Tracer for timing values.
2622 gpu_tracer_
.reset(new GPUTracer(this));
2624 if (feature_info_
->workarounds().disable_timestamp_queries
) {
2625 // Forcing time elapsed query for any GPU Timing Client forces it for all
2626 // clients in the context.
2627 GetGLContext()->CreateGPUTimingClient()->ForceTimeElapsedQuery();
2630 // Save the loseContextWhenOutOfMemory context creation attribute.
2631 lose_context_when_out_of_memory_
=
2632 attrib_parser
.lose_context_when_out_of_memory
;
2634 // If the failIfMajorPerformanceCaveat context creation attribute was true
2635 // and we are using a software renderer, fail.
2636 if (attrib_parser
.fail_if_major_perf_caveat
&&
2637 feature_info_
->feature_flags().is_swiftshader
) {
2638 group_
= NULL
; // Must not destroy ContextGroup if it is not initialized.
2643 disallowed_features_
= disallowed_features
;
2644 if (webgl_version_
== 1) {
2645 disallowed_features_
.npot_support
= true;
2648 if (!group_
->Initialize(this,
2649 ContextGroup::GetContextType(webgl_version_
),
2650 disallowed_features_
)) {
2651 group_
= NULL
; // Must not destroy ContextGroup if it is not initialized.
2657 if (webgl_version_
== 2) {
2658 if (!feature_info_
->IsES3Capable()) {
2659 LOG(ERROR
) << "Underlying driver does not support ES3.";
2663 feature_info_
->EnableES3Validators();
2664 set_unsafe_es3_apis_enabled(true);
2667 state_
.attrib_values
.resize(group_
->max_vertex_attribs());
2668 vertex_array_manager_
.reset(new VertexArrayManager());
2670 GLuint default_vertex_attrib_service_id
= 0;
2671 if (features().native_vertex_array_object
) {
2672 glGenVertexArraysOES(1, &default_vertex_attrib_service_id
);
2673 glBindVertexArrayOES(default_vertex_attrib_service_id
);
2676 state_
.default_vertex_attrib_manager
=
2677 CreateVertexAttribManager(0, default_vertex_attrib_service_id
, false);
2679 state_
.default_vertex_attrib_manager
->Initialize(
2680 group_
->max_vertex_attribs(),
2681 feature_info_
->workarounds().init_vertex_attributes
);
2683 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2684 DoBindVertexArrayOES(0);
2686 query_manager_
.reset(new QueryManager(this, feature_info_
.get()));
2688 image_manager_
.reset(new ImageManager
);
2690 util_
.set_num_compressed_texture_formats(
2691 validators_
->compressed_texture_format
.GetValues().size());
2693 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
2694 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2695 // OpenGL ES 2.0 does not have this issue.
2696 glEnableVertexAttribArray(0);
2698 glGenBuffersARB(1, &attrib_0_buffer_id_
);
2699 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
2700 glVertexAttribPointer(0, 1, GL_FLOAT
, GL_FALSE
, 0, NULL
);
2701 glBindBuffer(GL_ARRAY_BUFFER
, 0);
2702 glGenBuffersARB(1, &fixed_attrib_buffer_id_
);
2704 state_
.texture_units
.resize(group_
->max_texture_units());
2705 for (uint32 tt
= 0; tt
< state_
.texture_units
.size(); ++tt
) {
2706 glActiveTexture(GL_TEXTURE0
+ tt
);
2707 // We want the last bind to be 2D.
2709 if (features().oes_egl_image_external
) {
2710 ref
= texture_manager()->GetDefaultTextureInfo(
2711 GL_TEXTURE_EXTERNAL_OES
);
2712 state_
.texture_units
[tt
].bound_texture_external_oes
= ref
;
2713 glBindTexture(GL_TEXTURE_EXTERNAL_OES
, ref
? ref
->service_id() : 0);
2715 if (features().arb_texture_rectangle
) {
2716 ref
= texture_manager()->GetDefaultTextureInfo(
2717 GL_TEXTURE_RECTANGLE_ARB
);
2718 state_
.texture_units
[tt
].bound_texture_rectangle_arb
= ref
;
2719 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, ref
? ref
->service_id() : 0);
2721 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP
);
2722 state_
.texture_units
[tt
].bound_texture_cube_map
= ref
;
2723 glBindTexture(GL_TEXTURE_CUBE_MAP
, ref
? ref
->service_id() : 0);
2724 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D
);
2725 state_
.texture_units
[tt
].bound_texture_2d
= ref
;
2726 glBindTexture(GL_TEXTURE_2D
, ref
? ref
->service_id() : 0);
2728 glActiveTexture(GL_TEXTURE0
);
2731 // cache ALPHA_BITS result for re-use with clear behaviour
2732 GLint alpha_bits
= 0;
2735 if (attrib_parser
.samples
> 0 && attrib_parser
.sample_buffers
> 0 &&
2736 features().chromium_framebuffer_multisample
) {
2737 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2738 // max_sample_count must be initialized to a sane value. If
2739 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2740 GLint max_sample_count
= 1;
2741 glGetIntegerv(GL_MAX_SAMPLES_EXT
, &max_sample_count
);
2742 offscreen_target_samples_
= std::min(attrib_parser
.samples
,
2745 offscreen_target_samples_
= 1;
2747 offscreen_target_buffer_preserved_
= attrib_parser
.buffer_preserved
;
2749 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
2750 const bool rgb8_supported
=
2751 context_
->HasExtension("GL_OES_rgb8_rgba8");
2752 // The only available default render buffer formats in GLES2 have very
2753 // little precision. Don't enable multisampling unless 8-bit render
2754 // buffer formats are available--instead fall back to 8-bit textures.
2755 if (rgb8_supported
&& offscreen_target_samples_
> 1) {
2756 offscreen_target_color_format_
= attrib_parser
.alpha_size
> 0 ?
2759 offscreen_target_samples_
= 1;
2760 offscreen_target_color_format_
=
2761 attrib_parser
.alpha_size
> 0 || workarounds().disable_gl_rgb_format
2766 // ANGLE only supports packed depth/stencil formats, so use it if it is
2768 const bool depth24_stencil8_supported
=
2769 feature_info_
->feature_flags().packed_depth24_stencil8
;
2770 VLOG(1) << "GL_OES_packed_depth_stencil "
2771 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2772 if ((attrib_parser
.depth_size
> 0 || attrib_parser
.stencil_size
> 0) &&
2773 depth24_stencil8_supported
) {
2774 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2775 offscreen_target_stencil_format_
= 0;
2777 // It may be the case that this depth/stencil combination is not
2778 // supported, but this will be checked later by CheckFramebufferStatus.
2779 offscreen_target_depth_format_
= attrib_parser
.depth_size
> 0 ?
2780 GL_DEPTH_COMPONENT16
: 0;
2781 offscreen_target_stencil_format_
= attrib_parser
.stencil_size
> 0 ?
2782 GL_STENCIL_INDEX8
: 0;
2785 offscreen_target_color_format_
=
2786 attrib_parser
.alpha_size
> 0 || workarounds().disable_gl_rgb_format
2790 // If depth is requested at all, use the packed depth stencil format if
2791 // it's available, as some desktop GL drivers don't support any non-packed
2792 // formats for depth attachments.
2793 const bool depth24_stencil8_supported
=
2794 feature_info_
->feature_flags().packed_depth24_stencil8
;
2795 VLOG(1) << "GL_EXT_packed_depth_stencil "
2796 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2798 if ((attrib_parser
.depth_size
> 0 || attrib_parser
.stencil_size
> 0) &&
2799 depth24_stencil8_supported
) {
2800 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2801 offscreen_target_stencil_format_
= 0;
2803 offscreen_target_depth_format_
= attrib_parser
.depth_size
> 0 ?
2804 GL_DEPTH_COMPONENT
: 0;
2805 offscreen_target_stencil_format_
= attrib_parser
.stencil_size
> 0 ?
2806 GL_STENCIL_INDEX
: 0;
2810 offscreen_saved_color_format_
=
2811 attrib_parser
.alpha_size
> 0 || workarounds().disable_gl_rgb_format
2815 // Create the target frame buffer. This is the one that the client renders
2817 offscreen_target_frame_buffer_
.reset(new BackFramebuffer(this));
2818 offscreen_target_frame_buffer_
->Create();
2819 // Due to GLES2 format limitations, either the color texture (for
2820 // non-multisampling) or the color render buffer (for multisampling) will be
2821 // attached to the offscreen frame buffer. The render buffer has more
2822 // limited formats available to it, but the texture can't do multisampling.
2823 if (IsOffscreenBufferMultisampled()) {
2824 offscreen_target_color_render_buffer_
.reset(new BackRenderbuffer(
2825 renderbuffer_manager(), memory_tracker(), &state_
));
2826 offscreen_target_color_render_buffer_
->Create();
2828 offscreen_target_color_texture_
.reset(new BackTexture(
2829 memory_tracker(), &state_
));
2830 offscreen_target_color_texture_
->Create();
2832 offscreen_target_depth_render_buffer_
.reset(new BackRenderbuffer(
2833 renderbuffer_manager(), memory_tracker(), &state_
));
2834 offscreen_target_depth_render_buffer_
->Create();
2835 offscreen_target_stencil_render_buffer_
.reset(new BackRenderbuffer(
2836 renderbuffer_manager(), memory_tracker(), &state_
));
2837 offscreen_target_stencil_render_buffer_
->Create();
2839 // Create the saved offscreen texture. The target frame buffer is copied
2840 // here when SwapBuffers is called.
2841 offscreen_saved_frame_buffer_
.reset(new BackFramebuffer(this));
2842 offscreen_saved_frame_buffer_
->Create();
2844 offscreen_saved_color_texture_
.reset(new BackTexture(
2845 memory_tracker(), &state_
));
2846 offscreen_saved_color_texture_
->Create();
2848 // Allocate the render buffers at their initial size and check the status
2849 // of the frame buffers is okay.
2850 if (!ResizeOffscreenFrameBuffer(offscreen_size
)) {
2851 LOG(ERROR
) << "Could not allocate offscreen buffer storage.";
2856 state_
.viewport_width
= offscreen_size
.width();
2857 state_
.viewport_height
= offscreen_size
.height();
2859 // Allocate the offscreen saved color texture.
2860 DCHECK(offscreen_saved_color_format_
);
2861 offscreen_saved_color_texture_
->AllocateStorage(
2862 gfx::Size(1, 1), offscreen_saved_color_format_
, true);
2864 offscreen_saved_frame_buffer_
->AttachRenderTexture(
2865 offscreen_saved_color_texture_
.get());
2866 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
2867 GL_FRAMEBUFFER_COMPLETE
) {
2868 LOG(ERROR
) << "Offscreen saved FBO was incomplete.";
2873 // Bind to the new default frame buffer (the offscreen target frame buffer).
2874 // This should now be associated with ID zero.
2875 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
2877 glBindFramebufferEXT(GL_FRAMEBUFFER
, GetBackbufferServiceId());
2878 // These are NOT if the back buffer has these proprorties. They are
2879 // if we want the command buffer to enforce them regardless of what
2880 // the real backbuffer is assuming the real back buffer gives us more than
2881 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2882 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2883 // can't do anything about that.
2885 if (!surfaceless_
) {
2886 GLint depth_bits
= 0;
2887 GLint stencil_bits
= 0;
2889 bool default_fb
= (GetBackbufferServiceId() == 0);
2891 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
2892 glGetFramebufferAttachmentParameterivEXT(
2894 default_fb
? GL_BACK_LEFT
: GL_COLOR_ATTACHMENT0
,
2895 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE
, &alpha_bits
);
2896 glGetFramebufferAttachmentParameterivEXT(
2898 default_fb
? GL_DEPTH
: GL_DEPTH_ATTACHMENT
,
2899 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE
, &depth_bits
);
2900 glGetFramebufferAttachmentParameterivEXT(
2902 default_fb
? GL_STENCIL
: GL_STENCIL_ATTACHMENT
,
2903 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE
, &stencil_bits
);
2905 glGetIntegerv(GL_ALPHA_BITS
, &alpha_bits
);
2906 glGetIntegerv(GL_DEPTH_BITS
, &depth_bits
);
2907 glGetIntegerv(GL_STENCIL_BITS
, &stencil_bits
);
2910 // This checks if the user requested RGBA and we have RGBA then RGBA. If
2911 // the user requested RGB then RGB. If the user did not specify a
2912 // preference than use whatever we were given. Same for DEPTH and STENCIL.
2913 back_buffer_color_format_
=
2914 (attrib_parser
.alpha_size
!= 0 && alpha_bits
> 0) ? GL_RGBA
: GL_RGB
;
2915 back_buffer_has_depth_
= attrib_parser
.depth_size
!= 0 && depth_bits
> 0;
2916 back_buffer_has_stencil_
=
2917 attrib_parser
.stencil_size
!= 0 && stencil_bits
> 0;
2920 state_
.viewport_width
= surface
->GetSize().width();
2921 state_
.viewport_height
= surface
->GetSize().height();
2924 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2925 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2926 // isn't well documented; it was discovered in the Khronos OpenGL ES
2927 // mailing list archives. It also implicitly enables the desktop GL
2928 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2929 // variable in fragment shaders.
2930 if (!feature_info_
->gl_version_info().BehavesLikeGLES()) {
2931 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE
);
2932 glEnable(GL_POINT_SPRITE
);
2935 has_robustness_extension_
=
2936 context
->HasExtension("GL_ARB_robustness") ||
2937 context
->HasExtension("GL_KHR_robustness") ||
2938 context
->HasExtension("GL_EXT_robustness");
2940 if (!InitializeShaderTranslator()) {
2944 GLint viewport_params
[4] = { 0 };
2945 glGetIntegerv(GL_MAX_VIEWPORT_DIMS
, viewport_params
);
2946 viewport_max_width_
= viewport_params
[0];
2947 viewport_max_height_
= viewport_params
[1];
2949 state_
.scissor_width
= state_
.viewport_width
;
2950 state_
.scissor_height
= state_
.viewport_height
;
2952 // Set all the default state because some GL drivers get it wrong.
2953 state_
.InitCapabilities(NULL
);
2954 state_
.InitState(NULL
);
2955 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
2957 DoBindBuffer(GL_ARRAY_BUFFER
, 0);
2958 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
2959 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
2960 DoBindRenderbuffer(GL_RENDERBUFFER
, 0);
2961 DoBindValueBufferCHROMIUM(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM
, 0);
2963 bool call_gl_clear
= !surfaceless_
;
2964 #if defined(OS_ANDROID)
2965 // Temporary workaround for Android WebView because this clear ignores the
2966 // clip and corrupts that external UI of the App. Not calling glClear is ok
2967 // because the system already clears the buffer before each draw. Proper
2968 // fix might be setting the scissor clip properly before initialize. See
2969 // crbug.com/259023 for details.
2970 call_gl_clear
= surface_
->GetHandle();
2972 if (call_gl_clear
) {
2973 // On configs where we report no alpha, if the underlying surface has
2974 // alpha, clear the surface alpha to 1.0 to be correct on ReadPixels/etc.
2975 bool clear_alpha
= back_buffer_color_format_
== GL_RGB
&& alpha_bits
> 0;
2977 glClearColor(0.0f
, 0.0f
, 0.0f
, 1.0f
);
2980 // Clear the backbuffer.
2981 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
2983 // Restore alpha clear value if we changed it.
2985 glClearColor(0.0f
, 0.0f
, 0.0f
, 0.0f
);
2989 supports_post_sub_buffer_
= surface
->SupportsPostSubBuffer();
2990 if (feature_info_
->workarounds()
2991 .disable_post_sub_buffers_for_onscreen_surfaces
&&
2992 !surface
->IsOffscreen())
2993 supports_post_sub_buffer_
= false;
2995 if (feature_info_
->workarounds().reverse_point_sprite_coord_origin
) {
2996 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN
, GL_LOWER_LEFT
);
2999 if (feature_info_
->workarounds().unbind_fbo_on_context_switch
) {
3000 context_
->SetUnbindFboOnMakeCurrent();
3003 // Only compositor contexts are known to use only the subset of GL
3004 // that can be safely migrated between the iGPU and the dGPU. Mark
3005 // those contexts as safe to forcibly transition between the GPUs.
3006 // http://crbug.com/180876, http://crbug.com/227228
3008 context_
->SetSafeToForceGpuSwitch();
3010 async_pixel_transfer_manager_
.reset(
3011 AsyncPixelTransferManager::Create(context
.get()));
3012 async_pixel_transfer_manager_
->Initialize(texture_manager());
3014 if (workarounds().gl_clear_broken
) {
3015 DCHECK(!clear_framebuffer_blit_
.get());
3016 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glClearWorkaroundInit");
3017 clear_framebuffer_blit_
.reset(new ClearFramebufferResourceManager(this));
3018 if (LOCAL_PEEK_GL_ERROR("glClearWorkaroundInit") != GL_NO_ERROR
)
3022 framebuffer_manager()->AddObserver(this);
3027 Capabilities
GLES2DecoderImpl::GetCapabilities() {
3028 DCHECK(initialized());
3030 caps
.VisitPrecisions([](GLenum shader
, GLenum type
,
3031 Capabilities::ShaderPrecision
* shader_precision
) {
3032 GLint range
[2] = {0, 0};
3033 GLint precision
= 0;
3034 GetShaderPrecisionFormatImpl(shader
, type
, range
, &precision
);
3035 shader_precision
->min_range
= range
[0];
3036 shader_precision
->max_range
= range
[1];
3037 shader_precision
->precision
= precision
;
3039 DoGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
,
3040 &caps
.max_combined_texture_image_units
);
3041 DoGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE
, &caps
.max_cube_map_texture_size
);
3042 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS
,
3043 &caps
.max_fragment_uniform_vectors
);
3044 DoGetIntegerv(GL_MAX_RENDERBUFFER_SIZE
, &caps
.max_renderbuffer_size
);
3045 DoGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS
, &caps
.max_texture_image_units
);
3046 DoGetIntegerv(GL_MAX_TEXTURE_SIZE
, &caps
.max_texture_size
);
3047 DoGetIntegerv(GL_MAX_VARYING_VECTORS
, &caps
.max_varying_vectors
);
3048 DoGetIntegerv(GL_MAX_VERTEX_ATTRIBS
, &caps
.max_vertex_attribs
);
3049 DoGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS
,
3050 &caps
.max_vertex_texture_image_units
);
3051 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS
,
3052 &caps
.max_vertex_uniform_vectors
);
3053 DoGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS
,
3054 &caps
.num_compressed_texture_formats
);
3055 DoGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS
, &caps
.num_shader_binary_formats
);
3056 DoGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM
,
3057 &caps
.bind_generates_resource_chromium
);
3058 if (unsafe_es3_apis_enabled()) {
3059 // TODO(zmo): Note that some parameter values could be more than 32-bit,
3060 // but for now we clamp them to 32-bit max.
3061 DoGetIntegerv(GL_MAX_3D_TEXTURE_SIZE
, &caps
.max_3d_texture_size
);
3062 DoGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS
, &caps
.max_array_texture_layers
);
3063 DoGetIntegerv(GL_MAX_COLOR_ATTACHMENTS
, &caps
.max_color_attachments
);
3064 DoGetInteger64v(GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS
,
3065 &caps
.max_combined_fragment_uniform_components
);
3066 DoGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS
,
3067 &caps
.max_combined_uniform_blocks
);
3068 DoGetInteger64v(GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS
,
3069 &caps
.max_combined_vertex_uniform_components
);
3070 DoGetIntegerv(GL_MAX_DRAW_BUFFERS
, &caps
.max_draw_buffers
);
3071 DoGetInteger64v(GL_MAX_ELEMENT_INDEX
, &caps
.max_element_index
);
3072 DoGetIntegerv(GL_MAX_ELEMENTS_INDICES
, &caps
.max_elements_indices
);
3073 DoGetIntegerv(GL_MAX_ELEMENTS_VERTICES
, &caps
.max_elements_vertices
);
3074 DoGetIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS
,
3075 &caps
.max_fragment_input_components
);
3076 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS
,
3077 &caps
.max_fragment_uniform_blocks
);
3078 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS
,
3079 &caps
.max_fragment_uniform_components
);
3080 DoGetIntegerv(GL_MAX_PROGRAM_TEXEL_OFFSET
,
3081 &caps
.max_program_texel_offset
);
3082 DoGetInteger64v(GL_MAX_SERVER_WAIT_TIMEOUT
, &caps
.max_server_wait_timeout
);
3083 // Work around Linux NVIDIA driver bug where GL_TIMEOUT_IGNORED is
3085 if (caps
.max_server_wait_timeout
< 0)
3086 caps
.max_server_wait_timeout
= 0;
3087 DoGetFloatv(GL_MAX_TEXTURE_LOD_BIAS
, &caps
.max_texture_lod_bias
);
3088 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS
,
3089 &caps
.max_transform_feedback_interleaved_components
);
3090 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS
,
3091 &caps
.max_transform_feedback_separate_attribs
);
3092 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS
,
3093 &caps
.max_transform_feedback_separate_components
);
3094 DoGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE
, &caps
.max_uniform_block_size
);
3095 DoGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS
,
3096 &caps
.max_uniform_buffer_bindings
);
3097 DoGetIntegerv(GL_MAX_VARYING_COMPONENTS
, &caps
.max_varying_components
);
3098 DoGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS
,
3099 &caps
.max_vertex_output_components
);
3100 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS
,
3101 &caps
.max_vertex_uniform_blocks
);
3102 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS
,
3103 &caps
.max_vertex_uniform_components
);
3104 DoGetIntegerv(GL_MIN_PROGRAM_TEXEL_OFFSET
, &caps
.min_program_texel_offset
);
3105 DoGetIntegerv(GL_NUM_EXTENSIONS
, &caps
.num_extensions
);
3106 DoGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS
,
3107 &caps
.num_program_binary_formats
);
3108 DoGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
,
3109 &caps
.uniform_buffer_offset_alignment
);
3110 // TODO(zmo): once we switch to MANGLE, we should query version numbers.
3111 caps
.major_version
= 3;
3112 caps
.minor_version
= 0;
3114 if (feature_info_
->feature_flags().multisampled_render_to_texture
||
3115 feature_info_
->feature_flags().chromium_framebuffer_multisample
||
3116 unsafe_es3_apis_enabled()) {
3117 DoGetIntegerv(GL_MAX_SAMPLES
, &caps
.max_samples
);
3120 caps
.egl_image_external
=
3121 feature_info_
->feature_flags().oes_egl_image_external
;
3122 caps
.texture_format_atc
=
3123 feature_info_
->feature_flags().ext_texture_format_atc
;
3124 caps
.texture_format_bgra8888
=
3125 feature_info_
->feature_flags().ext_texture_format_bgra8888
;
3126 caps
.texture_format_dxt1
=
3127 feature_info_
->feature_flags().ext_texture_format_dxt1
;
3128 caps
.texture_format_dxt5
=
3129 feature_info_
->feature_flags().ext_texture_format_dxt5
;
3130 caps
.texture_format_etc1
=
3131 feature_info_
->feature_flags().oes_compressed_etc1_rgb8_texture
;
3132 caps
.texture_format_etc1_npot
=
3133 caps
.texture_format_etc1
&& !workarounds().etc1_power_of_two_only
;
3134 caps
.texture_rectangle
= feature_info_
->feature_flags().arb_texture_rectangle
;
3135 caps
.texture_usage
= feature_info_
->feature_flags().angle_texture_usage
;
3136 caps
.texture_storage
= feature_info_
->feature_flags().ext_texture_storage
;
3137 caps
.discard_framebuffer
=
3138 feature_info_
->feature_flags().ext_discard_framebuffer
;
3139 caps
.sync_query
= feature_info_
->feature_flags().chromium_sync_query
;
3141 #if defined(OS_MACOSX)
3142 // This is unconditionally true on mac, no need to test for it at runtime.
3143 caps
.iosurface
= true;
3146 caps
.post_sub_buffer
= supports_post_sub_buffer_
;
3148 caps
.surfaceless
= surfaceless_
;
3150 caps
.blend_equation_advanced
=
3151 feature_info_
->feature_flags().blend_equation_advanced
;
3152 caps
.blend_equation_advanced_coherent
=
3153 feature_info_
->feature_flags().blend_equation_advanced_coherent
;
3154 caps
.texture_rg
= feature_info_
->feature_flags().ext_texture_rg
;
3155 caps
.max_copy_texture_chromium_size
=
3156 feature_info_
->workarounds().max_copy_texture_chromium_size
;
3157 caps
.render_buffer_format_bgra8888
=
3158 feature_info_
->feature_flags().ext_render_buffer_format_bgra8888
;
3159 caps
.occlusion_query_boolean
=
3160 feature_info_
->feature_flags().occlusion_query_boolean
;
3161 caps
.timer_queries
=
3162 query_manager_
->GPUTimingAvailable();
3166 void GLES2DecoderImpl::UpdateCapabilities() {
3167 util_
.set_num_compressed_texture_formats(
3168 validators_
->compressed_texture_format
.GetValues().size());
3169 util_
.set_num_shader_binary_formats(
3170 validators_
->shader_binary_format
.GetValues().size());
3173 bool GLES2DecoderImpl::InitializeShaderTranslator() {
3174 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
3176 if (!use_shader_translator_
) {
3179 ShBuiltInResources resources
;
3180 ShInitBuiltInResources(&resources
);
3181 resources
.MaxVertexAttribs
= group_
->max_vertex_attribs();
3182 resources
.MaxVertexUniformVectors
=
3183 group_
->max_vertex_uniform_vectors();
3184 resources
.MaxVaryingVectors
= group_
->max_varying_vectors();
3185 resources
.MaxVertexTextureImageUnits
=
3186 group_
->max_vertex_texture_image_units();
3187 resources
.MaxCombinedTextureImageUnits
= group_
->max_texture_units();
3188 resources
.MaxTextureImageUnits
= group_
->max_texture_image_units();
3189 resources
.MaxFragmentUniformVectors
=
3190 group_
->max_fragment_uniform_vectors();
3191 resources
.MaxDrawBuffers
= group_
->max_draw_buffers();
3192 resources
.MaxExpressionComplexity
= 256;
3193 resources
.MaxCallStackDepth
= 256;
3195 GLint range
[2] = { 0, 0 };
3196 GLint precision
= 0;
3197 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER
, GL_HIGH_FLOAT
,
3199 resources
.FragmentPrecisionHigh
=
3200 PrecisionMeetsSpecForHighpFloat(range
[0], range
[1], precision
);
3202 if (IsWebGLContext()) {
3203 resources
.OES_standard_derivatives
= derivatives_explicitly_enabled_
;
3204 resources
.EXT_frag_depth
= frag_depth_explicitly_enabled_
;
3205 resources
.EXT_draw_buffers
= draw_buffers_explicitly_enabled_
;
3206 if (!draw_buffers_explicitly_enabled_
)
3207 resources
.MaxDrawBuffers
= 1;
3208 resources
.EXT_shader_texture_lod
= shader_texture_lod_explicitly_enabled_
;
3209 resources
.NV_draw_buffers
=
3210 draw_buffers_explicitly_enabled_
&& features().nv_draw_buffers
;
3212 resources
.OES_standard_derivatives
=
3213 features().oes_standard_derivatives
? 1 : 0;
3214 resources
.ARB_texture_rectangle
=
3215 features().arb_texture_rectangle
? 1 : 0;
3216 resources
.OES_EGL_image_external
=
3217 features().oes_egl_image_external
? 1 : 0;
3218 resources
.EXT_draw_buffers
=
3219 features().ext_draw_buffers
? 1 : 0;
3220 resources
.EXT_frag_depth
=
3221 features().ext_frag_depth
? 1 : 0;
3222 resources
.EXT_shader_texture_lod
=
3223 features().ext_shader_texture_lod
? 1 : 0;
3224 resources
.NV_draw_buffers
=
3225 features().nv_draw_buffers
? 1 : 0;
3228 ShShaderSpec shader_spec
;
3229 if (IsWebGLContext()) {
3230 shader_spec
= webgl_version_
== 2 ? SH_WEBGL2_SPEC
: SH_WEBGL_SPEC
;
3232 shader_spec
= unsafe_es3_apis_enabled() ? SH_GLES3_SPEC
: SH_GLES2_SPEC
;
3235 if ((shader_spec
== SH_WEBGL_SPEC
|| shader_spec
== SH_WEBGL2_SPEC
) &&
3236 features().enable_shader_name_hashing
)
3237 resources
.HashFunction
= &CityHash64
;
3239 resources
.HashFunction
= NULL
;
3240 ShaderTranslatorInterface::GlslImplementationType implementation_type
=
3241 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
?
3242 ShaderTranslatorInterface::kGlslES
: ShaderTranslatorInterface::kGlsl
;
3243 int driver_bug_workarounds
= 0;
3244 if (workarounds().needs_glsl_built_in_function_emulation
)
3245 driver_bug_workarounds
|= SH_EMULATE_BUILT_IN_FUNCTIONS
;
3246 if (workarounds().init_gl_position_in_vertex_shader
)
3247 driver_bug_workarounds
|= SH_INIT_GL_POSITION
;
3248 if (workarounds().unfold_short_circuit_as_ternary_operation
)
3249 driver_bug_workarounds
|= SH_UNFOLD_SHORT_CIRCUIT
;
3250 if (workarounds().init_varyings_without_static_use
)
3251 driver_bug_workarounds
|= SH_INIT_VARYINGS_WITHOUT_STATIC_USE
;
3252 if (workarounds().unroll_for_loop_with_sampler_array_index
)
3253 driver_bug_workarounds
|= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX
;
3254 if (workarounds().scalarize_vec_and_mat_constructor_args
)
3255 driver_bug_workarounds
|= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS
;
3256 if (workarounds().regenerate_struct_names
)
3257 driver_bug_workarounds
|= SH_REGENERATE_STRUCT_NAMES
;
3258 if (workarounds().remove_pow_with_constant_exponent
)
3259 driver_bug_workarounds
|= SH_REMOVE_POW_WITH_CONSTANT_EXPONENT
;
3261 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
3262 switches::kEmulateShaderPrecision
))
3263 resources
.WEBGL_debug_shader_precision
= true;
3265 vertex_translator_
= shader_translator_cache()->GetTranslator(
3269 implementation_type
,
3270 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
3271 if (!vertex_translator_
.get()) {
3272 LOG(ERROR
) << "Could not initialize vertex shader translator.";
3277 fragment_translator_
= shader_translator_cache()->GetTranslator(
3281 implementation_type
,
3282 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
3283 if (!fragment_translator_
.get()) {
3284 LOG(ERROR
) << "Could not initialize fragment shader translator.";
3291 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n
, const GLuint
* client_ids
) {
3292 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3293 if (GetBuffer(client_ids
[ii
])) {
3297 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3298 glGenBuffersARB(n
, service_ids
.get());
3299 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3300 CreateBuffer(client_ids
[ii
], service_ids
[ii
]);
3305 bool GLES2DecoderImpl::GenFramebuffersHelper(
3306 GLsizei n
, const GLuint
* client_ids
) {
3307 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3308 if (GetFramebuffer(client_ids
[ii
])) {
3312 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3313 glGenFramebuffersEXT(n
, service_ids
.get());
3314 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3315 CreateFramebuffer(client_ids
[ii
], service_ids
[ii
]);
3320 bool GLES2DecoderImpl::GenRenderbuffersHelper(
3321 GLsizei n
, const GLuint
* client_ids
) {
3322 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3323 if (GetRenderbuffer(client_ids
[ii
])) {
3327 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3328 glGenRenderbuffersEXT(n
, service_ids
.get());
3329 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3330 CreateRenderbuffer(client_ids
[ii
], service_ids
[ii
]);
3335 bool GLES2DecoderImpl::GenValuebuffersCHROMIUMHelper(GLsizei n
,
3336 const GLuint
* client_ids
) {
3337 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3338 if (GetValuebuffer(client_ids
[ii
])) {
3342 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3343 CreateValuebuffer(client_ids
[ii
]);
3348 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n
, const GLuint
* client_ids
) {
3349 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3350 if (GetTexture(client_ids
[ii
])) {
3354 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3355 glGenTextures(n
, service_ids
.get());
3356 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3357 CreateTexture(client_ids
[ii
], service_ids
[ii
]);
3362 bool GLES2DecoderImpl::GenPathsCHROMIUMHelper(GLuint first_client_id
,
3364 GLuint last_client_id
;
3365 if (!SafeAddUint32(first_client_id
, range
- 1, &last_client_id
))
3368 if (path_manager()->HasPathsInRange(first_client_id
, last_client_id
))
3371 GLuint first_service_id
= glGenPathsNV(range
);
3372 if (first_service_id
== 0) {
3373 // We have to fail the connection here, because client has already
3374 // succeeded in allocating the ids. This happens if we allocate
3375 // the whole path id space (two allocations of 0x7FFFFFFF paths, for
3379 // GenPathsNV does not wrap.
3380 DCHECK(first_service_id
+ range
- 1 >= first_service_id
);
3382 path_manager()->CreatePathRange(first_client_id
, last_client_id
,
3388 bool GLES2DecoderImpl::DeletePathsCHROMIUMHelper(GLuint first_client_id
,
3390 GLuint last_client_id
;
3391 if (!SafeAddUint32(first_client_id
, range
- 1, &last_client_id
))
3394 path_manager()->RemovePaths(first_client_id
, last_client_id
);
3398 void GLES2DecoderImpl::DeleteBuffersHelper(
3399 GLsizei n
, const GLuint
* client_ids
) {
3400 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3401 Buffer
* buffer
= GetBuffer(client_ids
[ii
]);
3402 if (buffer
&& !buffer
->IsDeleted()) {
3403 buffer
->RemoveMappedRange();
3404 state_
.RemoveBoundBuffer(buffer
);
3405 RemoveBuffer(client_ids
[ii
]);
3410 void GLES2DecoderImpl::DeleteFramebuffersHelper(
3411 GLsizei n
, const GLuint
* client_ids
) {
3412 bool supports_separate_framebuffer_binds
=
3413 features().chromium_framebuffer_multisample
;
3415 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3416 Framebuffer
* framebuffer
=
3417 GetFramebuffer(client_ids
[ii
]);
3418 if (framebuffer
&& !framebuffer
->IsDeleted()) {
3419 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
3420 GLenum target
= supports_separate_framebuffer_binds
?
3421 GL_DRAW_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
3423 // Unbind attachments on FBO before deletion.
3424 if (workarounds().unbind_attachments_on_bound_render_fbo_delete
)
3425 framebuffer
->DoUnbindGLAttachmentsForWorkaround(target
);
3427 glBindFramebufferEXT(target
, GetBackbufferServiceId());
3428 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
3429 framebuffer_state_
.clear_state_dirty
= true;
3431 if (framebuffer
== framebuffer_state_
.bound_read_framebuffer
.get()) {
3432 framebuffer_state_
.bound_read_framebuffer
= NULL
;
3433 GLenum target
= supports_separate_framebuffer_binds
?
3434 GL_READ_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
3435 glBindFramebufferEXT(target
, GetBackbufferServiceId());
3438 RemoveFramebuffer(client_ids
[ii
]);
3443 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
3444 GLsizei n
, const GLuint
* client_ids
) {
3445 bool supports_separate_framebuffer_binds
=
3446 features().chromium_framebuffer_multisample
;
3447 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3448 Renderbuffer
* renderbuffer
=
3449 GetRenderbuffer(client_ids
[ii
]);
3450 if (renderbuffer
&& !renderbuffer
->IsDeleted()) {
3451 if (state_
.bound_renderbuffer
.get() == renderbuffer
) {
3452 state_
.bound_renderbuffer
= NULL
;
3454 // Unbind from current framebuffers.
3455 if (supports_separate_framebuffer_binds
) {
3456 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
3457 framebuffer_state_
.bound_read_framebuffer
3458 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT
, renderbuffer
);
3460 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3461 framebuffer_state_
.bound_draw_framebuffer
3462 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT
, renderbuffer
);
3465 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3466 framebuffer_state_
.bound_draw_framebuffer
3467 ->UnbindRenderbuffer(GL_FRAMEBUFFER
, renderbuffer
);
3470 framebuffer_state_
.clear_state_dirty
= true;
3471 RemoveRenderbuffer(client_ids
[ii
]);
3476 void GLES2DecoderImpl::DeleteValuebuffersCHROMIUMHelper(
3478 const GLuint
* client_ids
) {
3479 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3480 Valuebuffer
* valuebuffer
= GetValuebuffer(client_ids
[ii
]);
3482 if (state_
.bound_valuebuffer
.get() == valuebuffer
) {
3483 state_
.bound_valuebuffer
= NULL
;
3485 RemoveValuebuffer(client_ids
[ii
]);
3490 void GLES2DecoderImpl::DeleteTexturesHelper(
3491 GLsizei n
, const GLuint
* client_ids
) {
3492 bool supports_separate_framebuffer_binds
=
3493 features().chromium_framebuffer_multisample
;
3494 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3495 TextureRef
* texture_ref
= GetTexture(client_ids
[ii
]);
3497 Texture
* texture
= texture_ref
->texture();
3498 if (texture
->IsAttachedToFramebuffer()) {
3499 framebuffer_state_
.clear_state_dirty
= true;
3501 // Unbind texture_ref from texture_ref units.
3502 for (size_t jj
= 0; jj
< state_
.texture_units
.size(); ++jj
) {
3503 state_
.texture_units
[jj
].Unbind(texture_ref
);
3505 // Unbind from current framebuffers.
3506 if (supports_separate_framebuffer_binds
) {
3507 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
3508 framebuffer_state_
.bound_read_framebuffer
3509 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT
, texture_ref
);
3511 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3512 framebuffer_state_
.bound_draw_framebuffer
3513 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT
, texture_ref
);
3516 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3517 framebuffer_state_
.bound_draw_framebuffer
3518 ->UnbindTexture(GL_FRAMEBUFFER
, texture_ref
);
3521 #if defined(OS_MACOSX)
3522 GLuint service_id
= texture
->service_id();
3523 if (texture
->target() == GL_TEXTURE_RECTANGLE_ARB
) {
3524 ReleaseIOSurfaceForTexture(service_id
);
3527 RemoveTexture(client_ids
[ii
]);
3532 // } // anonymous namespace
3534 bool GLES2DecoderImpl::MakeCurrent() {
3535 if (!context_
.get())
3538 if (WasContextLost()) {
3539 LOG(ERROR
) << " GLES2DecoderImpl: Trying to make lost context current.";
3543 if (!context_
->MakeCurrent(surface_
.get())) {
3544 LOG(ERROR
) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3545 MarkContextLost(error::kMakeCurrentFailed
);
3546 group_
->LoseContexts(error::kUnknown
);
3550 if (CheckResetStatus()) {
3552 << " GLES2DecoderImpl: Context reset detected after MakeCurrent.";
3553 group_
->LoseContexts(error::kUnknown
);
3557 ProcessFinishedAsyncTransfers();
3559 // Rebind the FBO if it was unbound by the context.
3560 if (workarounds().unbind_fbo_on_context_switch
)
3561 RestoreFramebufferBindings();
3563 framebuffer_state_
.clear_state_dirty
= true;
3568 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3569 ProcessPendingReadPixels(false);
3570 if (engine() && query_manager_
.get())
3571 query_manager_
->ProcessPendingTransferQueries();
3573 // TODO(epenner): Is there a better place to do this?
3574 // This needs to occur before we execute any batch of commands
3575 // from the client, as the client may have recieved an async
3576 // completion while issuing those commands.
3577 // "DidFlushStart" would be ideal if we had such a callback.
3578 async_pixel_transfer_manager_
->BindCompletedAsyncTransfers();
3581 static void RebindCurrentFramebuffer(
3583 Framebuffer
* framebuffer
,
3584 GLuint back_buffer_service_id
) {
3585 GLuint framebuffer_id
= framebuffer
? framebuffer
->service_id() : 0;
3587 if (framebuffer_id
== 0) {
3588 framebuffer_id
= back_buffer_service_id
;
3591 glBindFramebufferEXT(target
, framebuffer_id
);
3594 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3595 framebuffer_state_
.clear_state_dirty
= true;
3597 if (!features().chromium_framebuffer_multisample
) {
3598 RebindCurrentFramebuffer(
3600 framebuffer_state_
.bound_draw_framebuffer
.get(),
3601 GetBackbufferServiceId());
3603 RebindCurrentFramebuffer(
3604 GL_READ_FRAMEBUFFER_EXT
,
3605 framebuffer_state_
.bound_read_framebuffer
.get(),
3606 GetBackbufferServiceId());
3607 RebindCurrentFramebuffer(
3608 GL_DRAW_FRAMEBUFFER_EXT
,
3609 framebuffer_state_
.bound_draw_framebuffer
.get(),
3610 GetBackbufferServiceId());
3615 bool GLES2DecoderImpl::CheckFramebufferValid(
3616 Framebuffer
* framebuffer
,
3617 GLenum target
, const char* func_name
) {
3621 if (backbuffer_needs_clear_bits_
) {
3622 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3623 offscreen_target_color_format_
) & 0x0008) != 0 ? 0 : 1.f
);
3624 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
3626 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
3627 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
3629 state_
.SetDeviceDepthMask(GL_TRUE
);
3630 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
3631 bool reset_draw_buffer
= false;
3632 if ((backbuffer_needs_clear_bits_
& GL_COLOR_BUFFER_BIT
) != 0 &&
3633 group_
->draw_buffer() == GL_NONE
) {
3634 reset_draw_buffer
= true;
3635 GLenum buf
= GL_BACK
;
3636 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3637 buf
= GL_COLOR_ATTACHMENT0
;
3638 glDrawBuffersARB(1, &buf
);
3640 glClear(backbuffer_needs_clear_bits_
);
3641 if (reset_draw_buffer
) {
3642 GLenum buf
= GL_NONE
;
3643 glDrawBuffersARB(1, &buf
);
3645 backbuffer_needs_clear_bits_
= 0;
3646 RestoreClearState();
3651 if (framebuffer_manager()->IsComplete(framebuffer
)) {
3655 GLenum completeness
= framebuffer
->IsPossiblyComplete();
3656 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
3658 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
, "framebuffer incomplete");
3662 // Are all the attachments cleared?
3663 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3664 texture_manager()->HaveUnclearedMips()) {
3665 if (!framebuffer
->IsCleared()) {
3666 // Can we clear them?
3667 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3668 GL_FRAMEBUFFER_COMPLETE
) {
3670 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3671 "framebuffer incomplete (clear)");
3674 ClearUnclearedAttachments(target
, framebuffer
);
3678 if (!framebuffer_manager()->IsComplete(framebuffer
)) {
3679 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3680 GL_FRAMEBUFFER_COMPLETE
) {
3682 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3683 "framebuffer incomplete (check)");
3686 framebuffer_manager()->MarkAsComplete(framebuffer
);
3689 // NOTE: At this point we don't know if the framebuffer is complete but
3690 // we DO know that everything that needs to be cleared has been cleared.
3694 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name
) {
3695 if (!features().chromium_framebuffer_multisample
) {
3696 bool valid
= CheckFramebufferValid(
3697 framebuffer_state_
.bound_draw_framebuffer
.get(), GL_FRAMEBUFFER_EXT
,
3705 return CheckFramebufferValid(framebuffer_state_
.bound_draw_framebuffer
.get(),
3706 GL_DRAW_FRAMEBUFFER_EXT
,
3708 CheckFramebufferValid(framebuffer_state_
.bound_read_framebuffer
.get(),
3709 GL_READ_FRAMEBUFFER_EXT
,
3713 bool GLES2DecoderImpl::CheckBoundReadFramebufferColorAttachment(
3714 const char* func_name
) {
3715 Framebuffer
* framebuffer
= features().chromium_framebuffer_multisample
?
3716 framebuffer_state_
.bound_read_framebuffer
.get() :
3717 framebuffer_state_
.bound_draw_framebuffer
.get();
3720 if (framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
) == NULL
) {
3722 GL_INVALID_OPERATION
, func_name
, "no color image attached");
3728 bool GLES2DecoderImpl::FormsTextureCopyingFeedbackLoop(
3729 TextureRef
* texture
, GLint level
) {
3730 Framebuffer
* framebuffer
= features().chromium_framebuffer_multisample
?
3731 framebuffer_state_
.bound_read_framebuffer
.get() :
3732 framebuffer_state_
.bound_draw_framebuffer
.get();
3735 const Framebuffer::Attachment
* attachment
= framebuffer
->GetAttachment(
3736 GL_COLOR_ATTACHMENT0
);
3739 return attachment
->FormsFeedbackLoop(texture
, level
);
3742 gfx::Size
GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3743 Framebuffer
* framebuffer
=
3744 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3745 if (framebuffer
!= NULL
) {
3746 const Framebuffer::Attachment
* attachment
=
3747 framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
);
3749 return gfx::Size(attachment
->width(), attachment
->height());
3751 return gfx::Size(0, 0);
3752 } else if (offscreen_target_frame_buffer_
.get()) {
3753 return offscreen_size_
;
3755 return surface_
->GetSize();
3759 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3760 Framebuffer
* framebuffer
=
3761 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3762 if (framebuffer
!= NULL
) {
3763 return framebuffer
->GetColorAttachmentTextureType();
3765 return GL_UNSIGNED_BYTE
;
3769 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3770 Framebuffer
* framebuffer
=
3771 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3772 if (framebuffer
!= NULL
) {
3773 return framebuffer
->GetColorAttachmentFormat();
3774 } else if (offscreen_target_frame_buffer_
.get()) {
3775 return offscreen_target_color_format_
;
3777 return back_buffer_color_format_
;
3781 GLenum
GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3782 Framebuffer
* framebuffer
=
3783 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
3784 if (framebuffer
!= NULL
) {
3785 return framebuffer
->GetColorAttachmentFormat();
3786 } else if (offscreen_target_frame_buffer_
.get()) {
3787 return offscreen_target_color_format_
;
3789 return back_buffer_color_format_
;
3793 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3794 if (!offscreen_saved_color_texture_info_
.get())
3796 GLenum target
= offscreen_saved_color_texture_info_
->texture()->target();
3797 glBindTexture(target
, offscreen_saved_color_texture_info_
->service_id());
3798 texture_manager()->SetLevelInfo(
3799 offscreen_saved_color_texture_info_
.get(), GL_TEXTURE_2D
,
3801 GL_RGBA
, offscreen_size_
.width(), offscreen_size_
.height(),
3804 GL_RGBA
, GL_UNSIGNED_BYTE
, gfx::Rect(offscreen_size_
));
3805 texture_manager()->SetParameteri(
3806 "UpdateParentTextureInfo",
3808 offscreen_saved_color_texture_info_
.get(),
3809 GL_TEXTURE_MAG_FILTER
,
3811 texture_manager()->SetParameteri(
3812 "UpdateParentTextureInfo",
3814 offscreen_saved_color_texture_info_
.get(),
3815 GL_TEXTURE_MIN_FILTER
,
3817 texture_manager()->SetParameteri(
3818 "UpdateParentTextureInfo",
3820 offscreen_saved_color_texture_info_
.get(),
3823 texture_manager()->SetParameteri(
3824 "UpdateParentTextureInfo",
3826 offscreen_saved_color_texture_info_
.get(),
3829 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
3831 glBindTexture(target
, texture_ref
? texture_ref
->service_id() : 0);
3834 void GLES2DecoderImpl::SetResizeCallback(
3835 const base::Callback
<void(gfx::Size
, float)>& callback
) {
3836 resize_callback_
= callback
;
3839 Logger
* GLES2DecoderImpl::GetLogger() {
3843 void GLES2DecoderImpl::BeginDecoding() {
3844 gpu_tracer_
->BeginDecoding();
3845 gpu_trace_commands_
= gpu_tracer_
->IsTracing() && *gpu_decoder_category_
;
3846 gpu_debug_commands_
= log_commands() || debug() || gpu_trace_commands_
||
3847 (*cb_command_trace_category_
!= 0);
3850 void GLES2DecoderImpl::EndDecoding() {
3851 gpu_tracer_
->EndDecoding();
3854 ErrorState
* GLES2DecoderImpl::GetErrorState() {
3855 return state_
.GetErrorState();
3858 void GLES2DecoderImpl::SetShaderCacheCallback(
3859 const ShaderCacheCallback
& callback
) {
3860 shader_cache_callback_
= callback
;
3863 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3864 const WaitSyncPointCallback
& callback
) {
3865 wait_sync_point_callback_
= callback
;
3868 AsyncPixelTransferManager
*
3869 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3870 return async_pixel_transfer_manager_
.get();
3873 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3874 async_pixel_transfer_manager_
.reset();
3877 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3878 AsyncPixelTransferManager
* manager
) {
3879 async_pixel_transfer_manager_
= make_scoped_ptr(manager
);
3882 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id
,
3883 uint32
* service_texture_id
) {
3884 TextureRef
* texture_ref
= texture_manager()->GetTexture(client_texture_id
);
3886 *service_texture_id
= texture_ref
->service_id();
3892 uint32
GLES2DecoderImpl::GetTextureUploadCount() {
3893 return texture_state_
.texture_upload_count
+
3894 async_pixel_transfer_manager_
->GetTextureUploadCount();
3897 base::TimeDelta
GLES2DecoderImpl::GetTotalTextureUploadTime() {
3898 return texture_state_
.total_texture_upload_time
+
3899 async_pixel_transfer_manager_
->GetTotalTextureUploadTime();
3902 base::TimeDelta
GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3903 return total_processing_commands_time_
;
3906 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time
) {
3907 total_processing_commands_time_
+= time
;
3910 void GLES2DecoderImpl::Destroy(bool have_context
) {
3914 DCHECK(!have_context
|| context_
->IsCurrent(NULL
));
3916 // Unbind everything.
3917 state_
.vertex_attrib_manager
= NULL
;
3918 state_
.default_vertex_attrib_manager
= NULL
;
3919 state_
.texture_units
.clear();
3920 state_
.bound_array_buffer
= NULL
;
3921 state_
.bound_copy_read_buffer
= NULL
;
3922 state_
.bound_copy_write_buffer
= NULL
;
3923 state_
.bound_pixel_pack_buffer
= NULL
;
3924 state_
.bound_pixel_unpack_buffer
= NULL
;
3925 state_
.bound_transform_feedback_buffer
= NULL
;
3926 state_
.bound_uniform_buffer
= NULL
;
3927 framebuffer_state_
.bound_read_framebuffer
= NULL
;
3928 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
3929 state_
.bound_renderbuffer
= NULL
;
3930 state_
.bound_valuebuffer
= NULL
;
3932 if (offscreen_saved_color_texture_info_
.get()) {
3933 DCHECK(offscreen_target_color_texture_
);
3934 DCHECK_EQ(offscreen_saved_color_texture_info_
->service_id(),
3935 offscreen_saved_color_texture_
->id());
3936 offscreen_saved_color_texture_
->Invalidate();
3937 offscreen_saved_color_texture_info_
= NULL
;
3940 if (copy_texture_CHROMIUM_
.get()) {
3941 copy_texture_CHROMIUM_
->Destroy();
3942 copy_texture_CHROMIUM_
.reset();
3945 clear_framebuffer_blit_
.reset();
3947 if (state_
.current_program
.get()) {
3948 program_manager()->UnuseProgram(shader_manager(),
3949 state_
.current_program
.get());
3952 if (attrib_0_buffer_id_
) {
3953 glDeleteBuffersARB(1, &attrib_0_buffer_id_
);
3955 if (fixed_attrib_buffer_id_
) {
3956 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_
);
3959 if (validation_texture_
) {
3960 glDeleteTextures(1, &validation_texture_
);
3961 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_
);
3962 glDeleteFramebuffersEXT(1, &validation_fbo_
);
3965 if (offscreen_target_frame_buffer_
.get())
3966 offscreen_target_frame_buffer_
->Destroy();
3967 if (offscreen_target_color_texture_
.get())
3968 offscreen_target_color_texture_
->Destroy();
3969 if (offscreen_target_color_render_buffer_
.get())
3970 offscreen_target_color_render_buffer_
->Destroy();
3971 if (offscreen_target_depth_render_buffer_
.get())
3972 offscreen_target_depth_render_buffer_
->Destroy();
3973 if (offscreen_target_stencil_render_buffer_
.get())
3974 offscreen_target_stencil_render_buffer_
->Destroy();
3975 if (offscreen_saved_frame_buffer_
.get())
3976 offscreen_saved_frame_buffer_
->Destroy();
3977 if (offscreen_saved_color_texture_
.get())
3978 offscreen_saved_color_texture_
->Destroy();
3979 if (offscreen_resolved_frame_buffer_
.get())
3980 offscreen_resolved_frame_buffer_
->Destroy();
3981 if (offscreen_resolved_color_texture_
.get())
3982 offscreen_resolved_color_texture_
->Destroy();
3984 if (offscreen_target_frame_buffer_
.get())
3985 offscreen_target_frame_buffer_
->Invalidate();
3986 if (offscreen_target_color_texture_
.get())
3987 offscreen_target_color_texture_
->Invalidate();
3988 if (offscreen_target_color_render_buffer_
.get())
3989 offscreen_target_color_render_buffer_
->Invalidate();
3990 if (offscreen_target_depth_render_buffer_
.get())
3991 offscreen_target_depth_render_buffer_
->Invalidate();
3992 if (offscreen_target_stencil_render_buffer_
.get())
3993 offscreen_target_stencil_render_buffer_
->Invalidate();
3994 if (offscreen_saved_frame_buffer_
.get())
3995 offscreen_saved_frame_buffer_
->Invalidate();
3996 if (offscreen_saved_color_texture_
.get())
3997 offscreen_saved_color_texture_
->Invalidate();
3998 if (offscreen_resolved_frame_buffer_
.get())
3999 offscreen_resolved_frame_buffer_
->Invalidate();
4000 if (offscreen_resolved_color_texture_
.get())
4001 offscreen_resolved_color_texture_
->Invalidate();
4004 // Current program must be cleared after calling ProgramManager::UnuseProgram.
4005 // Otherwise, we can leak objects. http://crbug.com/258772.
4006 // state_.current_program must be reset before group_ is reset because
4007 // the later deletes the ProgramManager object that referred by
4008 // state_.current_program object.
4009 state_
.current_program
= NULL
;
4011 copy_texture_CHROMIUM_
.reset();
4012 clear_framebuffer_blit_
.reset();
4014 if (query_manager_
.get()) {
4015 query_manager_
->Destroy(have_context
);
4016 query_manager_
.reset();
4019 if (vertex_array_manager_
.get()) {
4020 vertex_array_manager_
->Destroy(have_context
);
4021 vertex_array_manager_
.reset();
4024 if (image_manager_
.get()) {
4025 image_manager_
->Destroy(have_context
);
4026 image_manager_
.reset();
4029 offscreen_target_frame_buffer_
.reset();
4030 offscreen_target_color_texture_
.reset();
4031 offscreen_target_color_render_buffer_
.reset();
4032 offscreen_target_depth_render_buffer_
.reset();
4033 offscreen_target_stencil_render_buffer_
.reset();
4034 offscreen_saved_frame_buffer_
.reset();
4035 offscreen_saved_color_texture_
.reset();
4036 offscreen_resolved_frame_buffer_
.reset();
4037 offscreen_resolved_color_texture_
.reset();
4039 // Need to release these before releasing |group_| which may own the
4040 // ShaderTranslatorCache.
4041 fragment_translator_
= NULL
;
4042 vertex_translator_
= NULL
;
4044 // Should destroy the transfer manager before the texture manager held
4045 // by the context group.
4046 async_pixel_transfer_manager_
.reset();
4048 // Destroy the GPU Tracer which may own some in process GPU Timings.
4050 gpu_tracer_
->Destroy(have_context
);
4051 gpu_tracer_
.reset();
4055 framebuffer_manager()->RemoveObserver(this);
4056 group_
->Destroy(this, have_context
);
4060 if (context_
.get()) {
4061 context_
->ReleaseCurrent(NULL
);
4065 #if defined(OS_MACOSX)
4066 for (TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.begin();
4067 it
!= texture_to_io_surface_map_
.end(); ++it
) {
4068 CFRelease(it
->second
);
4070 texture_to_io_surface_map_
.clear();
4074 void GLES2DecoderImpl::SetSurface(
4075 const scoped_refptr
<gfx::GLSurface
>& surface
) {
4076 DCHECK(context_
->IsCurrent(NULL
));
4077 DCHECK(surface_
.get());
4079 RestoreCurrentFramebufferBindings();
4082 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox
& mailbox
) {
4083 if (!offscreen_saved_color_texture_
.get()) {
4084 LOG(ERROR
) << "Called ProduceFrontBuffer on a non-offscreen context";
4087 if (!offscreen_saved_color_texture_info_
.get()) {
4088 GLuint service_id
= offscreen_saved_color_texture_
->id();
4089 offscreen_saved_color_texture_info_
= TextureRef::Create(
4090 texture_manager(), 0, service_id
);
4091 texture_manager()->SetTarget(offscreen_saved_color_texture_info_
.get(),
4093 UpdateParentTextureInfo();
4095 mailbox_manager()->ProduceTexture(
4096 mailbox
, offscreen_saved_color_texture_info_
->texture());
4099 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size
& size
) {
4100 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
4101 if (!is_offscreen
) {
4102 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
4103 << " with an onscreen framebuffer.";
4107 if (offscreen_size_
== size
)
4110 offscreen_size_
= size
;
4111 int w
= offscreen_size_
.width();
4112 int h
= offscreen_size_
.height();
4113 if (w
< 0 || h
< 0 || h
>= (INT_MAX
/ 4) / (w
? w
: 1)) {
4114 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4115 << "to allocate storage due to excessive dimensions.";
4119 // Reallocate the offscreen target buffers.
4120 DCHECK(offscreen_target_color_format_
);
4121 if (IsOffscreenBufferMultisampled()) {
4122 if (!offscreen_target_color_render_buffer_
->AllocateStorage(
4123 feature_info_
.get(),
4125 offscreen_target_color_format_
,
4126 offscreen_target_samples_
)) {
4127 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4128 << "to allocate storage for offscreen target color buffer.";
4132 if (!offscreen_target_color_texture_
->AllocateStorage(
4133 offscreen_size_
, offscreen_target_color_format_
, false)) {
4134 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4135 << "to allocate storage for offscreen target color texture.";
4139 if (offscreen_target_depth_format_
&&
4140 !offscreen_target_depth_render_buffer_
->AllocateStorage(
4141 feature_info_
.get(),
4143 offscreen_target_depth_format_
,
4144 offscreen_target_samples_
)) {
4145 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4146 << "to allocate storage for offscreen target depth buffer.";
4149 if (offscreen_target_stencil_format_
&&
4150 !offscreen_target_stencil_render_buffer_
->AllocateStorage(
4151 feature_info_
.get(),
4153 offscreen_target_stencil_format_
,
4154 offscreen_target_samples_
)) {
4155 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4156 << "to allocate storage for offscreen target stencil buffer.";
4160 // Attach the offscreen target buffers to the target frame buffer.
4161 if (IsOffscreenBufferMultisampled()) {
4162 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4163 GL_COLOR_ATTACHMENT0
,
4164 offscreen_target_color_render_buffer_
.get());
4166 offscreen_target_frame_buffer_
->AttachRenderTexture(
4167 offscreen_target_color_texture_
.get());
4169 if (offscreen_target_depth_format_
) {
4170 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4171 GL_DEPTH_ATTACHMENT
,
4172 offscreen_target_depth_render_buffer_
.get());
4174 const bool packed_depth_stencil
=
4175 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
4176 if (packed_depth_stencil
) {
4177 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4178 GL_STENCIL_ATTACHMENT
,
4179 offscreen_target_depth_render_buffer_
.get());
4180 } else if (offscreen_target_stencil_format_
) {
4181 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4182 GL_STENCIL_ATTACHMENT
,
4183 offscreen_target_stencil_render_buffer_
.get());
4186 if (offscreen_target_frame_buffer_
->CheckStatus() !=
4187 GL_FRAMEBUFFER_COMPLETE
) {
4188 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4189 << "because offscreen FBO was incomplete.";
4193 // Clear the target frame buffer.
4195 ScopedFrameBufferBinder
binder(this, offscreen_target_frame_buffer_
->id());
4196 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
4197 offscreen_target_color_format_
) & 0x0008) != 0 ? 0 : 1.f
);
4198 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
4200 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
4201 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
4203 state_
.SetDeviceDepthMask(GL_TRUE
);
4204 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
4205 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
4206 RestoreClearState();
4209 // Destroy the offscreen resolved framebuffers.
4210 if (offscreen_resolved_frame_buffer_
.get())
4211 offscreen_resolved_frame_buffer_
->Destroy();
4212 if (offscreen_resolved_color_texture_
.get())
4213 offscreen_resolved_color_texture_
->Destroy();
4214 offscreen_resolved_color_texture_
.reset();
4215 offscreen_resolved_frame_buffer_
.reset();
4220 error::Error
GLES2DecoderImpl::HandleResizeCHROMIUM(uint32 immediate_data_size
,
4221 const void* cmd_data
) {
4222 const gles2::cmds::ResizeCHROMIUM
& c
=
4223 *static_cast<const gles2::cmds::ResizeCHROMIUM
*>(cmd_data
);
4224 if (!offscreen_target_frame_buffer_
.get() && surface_
->DeferDraws())
4225 return error::kDeferCommandUntilLater
;
4227 GLuint width
= static_cast<GLuint
>(c
.width
);
4228 GLuint height
= static_cast<GLuint
>(c
.height
);
4229 GLfloat scale_factor
= c
.scale_factor
;
4230 TRACE_EVENT2("gpu", "glResizeChromium", "width", width
, "height", height
);
4232 width
= std::max(1U, width
);
4233 height
= std::max(1U, height
);
4235 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
4236 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
4237 // Make sure that we are done drawing to the back buffer before resizing.
4240 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
4242 if (!ResizeOffscreenFrameBuffer(gfx::Size(width
, height
))) {
4243 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because "
4244 << "ResizeOffscreenFrameBuffer failed.";
4245 return error::kLostContext
;
4249 if (!resize_callback_
.is_null()) {
4250 resize_callback_
.Run(gfx::Size(width
, height
), scale_factor
);
4251 DCHECK(context_
->IsCurrent(surface_
.get()));
4252 if (!context_
->IsCurrent(surface_
.get())) {
4253 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because context no longer "
4254 << "current after resize callback.";
4255 return error::kLostContext
;
4259 return error::kNoError
;
4262 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id
) const {
4263 if (command_id
> kStartPoint
&& command_id
< kNumCommands
) {
4264 return gles2::GetCommandName(static_cast<CommandId
>(command_id
));
4266 return GetCommonCommandName(static_cast<cmd::CommandId
>(command_id
));
4269 // Decode a command, and call the corresponding GL functions.
4270 // NOTE: DoCommand() is slower than calling DoCommands() on larger batches
4271 // of commands at once, and is now only used for tests that need to track
4272 // individual commands.
4273 error::Error
GLES2DecoderImpl::DoCommand(unsigned int command
,
4274 unsigned int arg_count
,
4275 const void* cmd_data
) {
4276 return DoCommands(1, cmd_data
, arg_count
+ 1, 0);
4279 // Decode multiple commands, and call the corresponding GL functions.
4280 // NOTE: 'buffer' is a pointer to the command buffer. As such, it could be
4281 // changed by a (malicious) client at any time, so if validation has to happen,
4282 // it should operate on a copy of them.
4283 // NOTE: This is duplicating code from AsyncAPIInterface::DoCommands() in the
4284 // interest of performance in this critical execution loop.
4285 template <bool DebugImpl
>
4286 error::Error
GLES2DecoderImpl::DoCommandsImpl(unsigned int num_commands
,
4289 int* entries_processed
) {
4290 commands_to_process_
= num_commands
;
4291 error::Error result
= error::kNoError
;
4292 const CommandBufferEntry
* cmd_data
=
4293 static_cast<const CommandBufferEntry
*>(buffer
);
4294 int process_pos
= 0;
4295 unsigned int command
= 0;
4297 while (process_pos
< num_entries
&& result
== error::kNoError
&&
4298 commands_to_process_
--) {
4299 const unsigned int size
= cmd_data
->value_header
.size
;
4300 command
= cmd_data
->value_header
.command
;
4303 result
= error::kInvalidSize
;
4307 if (static_cast<int>(size
) + process_pos
> num_entries
) {
4308 result
= error::kOutOfBounds
;
4313 TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4314 GetCommandName(command
));
4316 if (log_commands()) {
4317 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "]"
4318 << "cmd: " << GetCommandName(command
);
4322 const unsigned int arg_count
= size
- 1;
4323 unsigned int command_index
= command
- kStartPoint
- 1;
4324 if (command_index
< arraysize(command_info
)) {
4325 const CommandInfo
& info
= command_info
[command_index
];
4326 unsigned int info_arg_count
= static_cast<unsigned int>(info
.arg_count
);
4327 if ((info
.arg_flags
== cmd::kFixed
&& arg_count
== info_arg_count
) ||
4328 (info
.arg_flags
== cmd::kAtLeastN
&& arg_count
>= info_arg_count
)) {
4329 bool doing_gpu_trace
= false;
4330 if (DebugImpl
&& gpu_trace_commands_
) {
4331 if (CMD_FLAG_GET_TRACE_LEVEL(info
.cmd_flags
) <= gpu_trace_level_
) {
4332 doing_gpu_trace
= true;
4333 gpu_tracer_
->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_decoder"),
4334 GetCommandName(command
),
4339 uint32 immediate_data_size
= (arg_count
- info_arg_count
) *
4340 sizeof(CommandBufferEntry
); // NOLINT
4342 result
= (this->*info
.cmd_handler
)(immediate_data_size
, cmd_data
);
4344 if (DebugImpl
&& doing_gpu_trace
)
4345 gpu_tracer_
->End(kTraceDecoder
);
4347 if (DebugImpl
&& debug()) {
4349 while ((error
= glGetError()) != GL_NO_ERROR
) {
4350 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "] "
4351 << "GL ERROR: " << GLES2Util::GetStringEnum(error
)
4352 << " : " << GetCommandName(command
);
4353 LOCAL_SET_GL_ERROR(error
, "DoCommand", "GL error from driver");
4357 result
= error::kInvalidArguments
;
4360 result
= DoCommonCommand(command
, arg_count
, cmd_data
);
4364 TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4365 GetCommandName(command
));
4368 if (result
== error::kNoError
&&
4369 current_decoder_error_
!= error::kNoError
) {
4370 result
= current_decoder_error_
;
4371 current_decoder_error_
= error::kNoError
;
4374 if (result
!= error::kDeferCommandUntilLater
) {
4375 process_pos
+= size
;
4380 if (entries_processed
)
4381 *entries_processed
= process_pos
;
4383 if (error::IsError(result
)) {
4384 LOG(ERROR
) << "Error: " << result
<< " for Command "
4385 << GetCommandName(command
);
4391 error::Error
GLES2DecoderImpl::DoCommands(unsigned int num_commands
,
4394 int* entries_processed
) {
4395 if (gpu_debug_commands_
) {
4396 return DoCommandsImpl
<true>(
4397 num_commands
, buffer
, num_entries
, entries_processed
);
4399 return DoCommandsImpl
<false>(
4400 num_commands
, buffer
, num_entries
, entries_processed
);
4404 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id
) {
4405 buffer_manager()->RemoveBuffer(client_id
);
4408 void GLES2DecoderImpl::DoFinish() {
4410 ProcessPendingReadPixels(true);
4411 ProcessPendingQueries(true);
4414 void GLES2DecoderImpl::DoFlush() {
4416 ProcessPendingQueries(false);
4419 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit
) {
4420 GLuint texture_index
= texture_unit
- GL_TEXTURE0
;
4421 if (texture_index
>= state_
.texture_units
.size()) {
4422 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4423 "glActiveTexture", texture_unit
, "texture_unit");
4426 state_
.active_texture_unit
= texture_index
;
4427 glActiveTexture(texture_unit
);
4430 void GLES2DecoderImpl::DoBindBuffer(GLenum target
, GLuint client_id
) {
4431 Buffer
* buffer
= NULL
;
4432 GLuint service_id
= 0;
4433 if (client_id
!= 0) {
4434 buffer
= GetBuffer(client_id
);
4436 if (!group_
->bind_generates_resource()) {
4437 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4439 "id not generated by glGenBuffers");
4443 // It's a new id so make a buffer buffer for it.
4444 glGenBuffersARB(1, &service_id
);
4445 CreateBuffer(client_id
, service_id
);
4446 buffer
= GetBuffer(client_id
);
4449 LogClientServiceForInfo(buffer
, client_id
, "glBindBuffer");
4451 if (!buffer_manager()->SetTarget(buffer
, target
)) {
4453 GL_INVALID_OPERATION
,
4454 "glBindBuffer", "buffer bound to more than 1 target");
4457 service_id
= buffer
->service_id();
4459 state_
.SetBoundBuffer(target
, buffer
);
4460 glBindBuffer(target
, service_id
);
4463 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
4464 bool all_draw_buffers
) {
4465 Framebuffer
* framebuffer
=
4466 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4467 if (!all_draw_buffers
|| !framebuffer
) {
4468 return (GLES2Util::GetChannelsForFormat(
4469 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
4471 return framebuffer
->HasAlphaMRT();
4474 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
4475 Framebuffer
* framebuffer
=
4476 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4478 return framebuffer
->HasDepthAttachment();
4480 if (offscreen_target_frame_buffer_
.get()) {
4481 return offscreen_target_depth_format_
!= 0;
4483 return back_buffer_has_depth_
;
4486 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
4487 Framebuffer
* framebuffer
=
4488 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4490 return framebuffer
->HasStencilAttachment();
4492 if (offscreen_target_frame_buffer_
.get()) {
4493 return offscreen_target_stencil_format_
!= 0 ||
4494 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
4496 return back_buffer_has_stencil_
;
4499 void GLES2DecoderImpl::ApplyDirtyState() {
4500 if (framebuffer_state_
.clear_state_dirty
) {
4501 bool have_alpha
= BoundFramebufferHasColorAttachmentWithAlpha(true);
4502 state_
.SetDeviceColorMask(state_
.color_mask_red
,
4503 state_
.color_mask_green
,
4504 state_
.color_mask_blue
,
4505 state_
.color_mask_alpha
&& have_alpha
);
4507 bool have_depth
= BoundFramebufferHasDepthAttachment();
4508 state_
.SetDeviceDepthMask(state_
.depth_mask
&& have_depth
);
4510 bool have_stencil
= BoundFramebufferHasStencilAttachment();
4511 state_
.SetDeviceStencilMaskSeparate(
4512 GL_FRONT
, have_stencil
? state_
.stencil_front_writemask
: 0);
4513 state_
.SetDeviceStencilMaskSeparate(
4514 GL_BACK
, have_stencil
? state_
.stencil_back_writemask
: 0);
4516 state_
.SetDeviceCapabilityState(
4517 GL_DEPTH_TEST
, state_
.enable_flags
.depth_test
&& have_depth
);
4518 state_
.SetDeviceCapabilityState(
4519 GL_STENCIL_TEST
, state_
.enable_flags
.stencil_test
&& have_stencil
);
4520 framebuffer_state_
.clear_state_dirty
= false;
4524 GLuint
GLES2DecoderImpl::GetBackbufferServiceId() const {
4525 return (offscreen_target_frame_buffer_
.get())
4526 ? offscreen_target_frame_buffer_
->id()
4527 : (surface_
.get() ? surface_
->GetBackingFrameBufferObject() : 0);
4530 void GLES2DecoderImpl::RestoreState(const ContextState
* prev_state
) {
4531 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
4532 "context", logger_
.GetLogPrefix());
4533 // Restore the Framebuffer first because of bugs in Intel drivers.
4534 // Intel drivers incorrectly clip the viewport settings to
4535 // the size of the current framebuffer object.
4536 RestoreFramebufferBindings();
4537 state_
.RestoreState(prev_state
);
4540 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
4542 framebuffer_state_
.bound_draw_framebuffer
.get()
4543 ? framebuffer_state_
.bound_draw_framebuffer
->service_id()
4544 : GetBackbufferServiceId();
4545 if (!features().chromium_framebuffer_multisample
) {
4546 glBindFramebufferEXT(GL_FRAMEBUFFER
, service_id
);
4548 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, service_id
);
4549 service_id
= framebuffer_state_
.bound_read_framebuffer
.get()
4550 ? framebuffer_state_
.bound_read_framebuffer
->service_id()
4551 : GetBackbufferServiceId();
4552 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, service_id
);
4557 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
4558 state_
.RestoreRenderbufferBindings();
4561 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id
) const {
4562 Texture
* texture
= texture_manager()->GetTextureForServiceId(service_id
);
4564 GLenum target
= texture
->target();
4565 glBindTexture(target
, service_id
);
4567 target
, GL_TEXTURE_WRAP_S
, texture
->wrap_s());
4569 target
, GL_TEXTURE_WRAP_T
, texture
->wrap_t());
4571 target
, GL_TEXTURE_MIN_FILTER
, texture
->min_filter());
4573 target
, GL_TEXTURE_MAG_FILTER
, texture
->mag_filter());
4574 RestoreTextureUnitBindings(state_
.active_texture_unit
);
4578 void GLES2DecoderImpl::ClearAllAttributes() const {
4579 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
4581 if (feature_info_
->feature_flags().native_vertex_array_object
)
4582 glBindVertexArrayOES(0);
4584 for (uint32 i
= 0; i
< group_
->max_vertex_attribs(); ++i
) {
4585 if (i
!= 0) // Never disable attribute 0
4586 glDisableVertexAttribArray(i
);
4587 if (features().angle_instanced_arrays
)
4588 glVertexAttribDivisorANGLE(i
, 0);
4592 void GLES2DecoderImpl::RestoreAllAttributes() const {
4593 state_
.RestoreVertexAttribs();
4596 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore
) {
4597 state_
.SetIgnoreCachedStateForTest(ignore
);
4600 void GLES2DecoderImpl::OnFboChanged() const {
4601 if (workarounds().restore_scissor_on_fbo_change
)
4602 state_
.fbo_binding_for_scissor_workaround_dirty
= true;
4604 if (workarounds().gl_begin_gl_end_on_fbo_change_to_backbuffer
) {
4605 GLint bound_fbo_unsigned
= -1;
4606 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT
, &bound_fbo_unsigned
);
4607 GLuint bound_fbo
= static_cast<GLuint
>(bound_fbo_unsigned
);
4608 if (surface_
&& surface_
->GetBackingFrameBufferObject() == bound_fbo
)
4609 surface_
->NotifyWasBound();
4613 // Called after the FBO is checked for completeness.
4614 void GLES2DecoderImpl::OnUseFramebuffer() const {
4615 if (state_
.fbo_binding_for_scissor_workaround_dirty
) {
4616 state_
.fbo_binding_for_scissor_workaround_dirty
= false;
4617 // The driver forgets the correct scissor when modifying the FBO binding.
4618 glScissor(state_
.scissor_x
,
4620 state_
.scissor_width
,
4621 state_
.scissor_height
);
4623 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
4624 // it's unclear how this bug works.
4629 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target
, GLuint client_id
) {
4630 Framebuffer
* framebuffer
= NULL
;
4631 GLuint service_id
= 0;
4632 if (client_id
!= 0) {
4633 framebuffer
= GetFramebuffer(client_id
);
4635 if (!group_
->bind_generates_resource()) {
4636 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4637 "glBindFramebuffer",
4638 "id not generated by glGenFramebuffers");
4642 // It's a new id so make a framebuffer framebuffer for it.
4643 glGenFramebuffersEXT(1, &service_id
);
4644 CreateFramebuffer(client_id
, service_id
);
4645 framebuffer
= GetFramebuffer(client_id
);
4647 service_id
= framebuffer
->service_id();
4649 framebuffer
->MarkAsValid();
4651 LogClientServiceForInfo(framebuffer
, client_id
, "glBindFramebuffer");
4653 if (target
== GL_FRAMEBUFFER
|| target
== GL_DRAW_FRAMEBUFFER_EXT
) {
4654 framebuffer_state_
.bound_draw_framebuffer
= framebuffer
;
4657 // vmiura: This looks like dup code
4658 if (target
== GL_FRAMEBUFFER
|| target
== GL_READ_FRAMEBUFFER_EXT
) {
4659 framebuffer_state_
.bound_read_framebuffer
= framebuffer
;
4662 framebuffer_state_
.clear_state_dirty
= true;
4664 // If we are rendering to the backbuffer get the FBO id for any simulated
4666 if (framebuffer
== NULL
) {
4667 service_id
= GetBackbufferServiceId();
4670 glBindFramebufferEXT(target
, service_id
);
4674 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target
, GLuint client_id
) {
4675 Renderbuffer
* renderbuffer
= NULL
;
4676 GLuint service_id
= 0;
4677 if (client_id
!= 0) {
4678 renderbuffer
= GetRenderbuffer(client_id
);
4679 if (!renderbuffer
) {
4680 if (!group_
->bind_generates_resource()) {
4681 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4682 "glBindRenderbuffer",
4683 "id not generated by glGenRenderbuffers");
4687 // It's a new id so make a renderbuffer for it.
4688 glGenRenderbuffersEXT(1, &service_id
);
4689 CreateRenderbuffer(client_id
, service_id
);
4690 renderbuffer
= GetRenderbuffer(client_id
);
4692 service_id
= renderbuffer
->service_id();
4694 renderbuffer
->MarkAsValid();
4696 LogClientServiceForInfo(renderbuffer
, client_id
, "glBindRenderbuffer");
4697 state_
.bound_renderbuffer
= renderbuffer
;
4698 state_
.bound_renderbuffer_valid
= true;
4699 glBindRenderbufferEXT(GL_RENDERBUFFER
, service_id
);
4702 void GLES2DecoderImpl::DoBindTexture(GLenum target
, GLuint client_id
) {
4703 TextureRef
* texture_ref
= NULL
;
4704 GLuint service_id
= 0;
4705 if (client_id
!= 0) {
4706 texture_ref
= GetTexture(client_id
);
4708 if (!group_
->bind_generates_resource()) {
4709 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4711 "id not generated by glGenTextures");
4715 // It's a new id so make a texture texture for it.
4716 glGenTextures(1, &service_id
);
4717 DCHECK_NE(0u, service_id
);
4718 CreateTexture(client_id
, service_id
);
4719 texture_ref
= GetTexture(client_id
);
4722 texture_ref
= texture_manager()->GetDefaultTextureInfo(target
);
4725 // Check the texture exists
4727 Texture
* texture
= texture_ref
->texture();
4728 // Check that we are not trying to bind it to a different target.
4729 if (texture
->target() != 0 && texture
->target() != target
) {
4730 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4732 "texture bound to more than 1 target.");
4735 LogClientServiceForInfo(texture
, client_id
, "glBindTexture");
4736 if (texture
->target() == 0) {
4737 texture_manager()->SetTarget(texture_ref
, target
);
4739 glBindTexture(target
, texture
->service_id());
4741 glBindTexture(target
, 0);
4744 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4745 unit
.bind_target
= target
;
4748 unit
.bound_texture_2d
= texture_ref
;
4750 case GL_TEXTURE_CUBE_MAP
:
4751 unit
.bound_texture_cube_map
= texture_ref
;
4753 case GL_TEXTURE_EXTERNAL_OES
:
4754 unit
.bound_texture_external_oes
= texture_ref
;
4756 case GL_TEXTURE_RECTANGLE_ARB
:
4757 unit
.bound_texture_rectangle_arb
= texture_ref
;
4760 unit
.bound_texture_3d
= texture_ref
;
4762 case GL_TEXTURE_2D_ARRAY
:
4763 unit
.bound_texture_2d_array
= texture_ref
;
4766 NOTREACHED(); // Validation should prevent us getting here.
4771 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index
) {
4772 if (state_
.vertex_attrib_manager
->Enable(index
, false)) {
4774 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
4775 glDisableVertexAttribArray(index
);
4780 "glDisableVertexAttribArray", "index out of range");
4784 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target
,
4785 GLsizei numAttachments
,
4786 const GLenum
* attachments
) {
4787 if (workarounds().disable_discard_framebuffer
)
4790 Framebuffer
* framebuffer
=
4791 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
4793 // Validates the attachments. If one of them fails
4794 // the whole command fails.
4795 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4797 !validators_
->attachment
.IsValid(attachments
[i
])) ||
4799 !validators_
->backbuffer_attachment
.IsValid(attachments
[i
]))) {
4800 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4801 "glDiscardFramebufferEXT", attachments
[i
], "attachments");
4806 // Marks each one of them as not cleared
4807 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4809 framebuffer
->MarkAttachmentAsCleared(renderbuffer_manager(),
4814 switch (attachments
[i
]) {
4816 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
4819 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
4820 case GL_STENCIL_EXT
:
4821 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
4830 // If the default framebuffer is bound but we are still rendering to an
4831 // FBO, translate attachment names that refer to default framebuffer
4832 // channels to corresponding framebuffer attachments.
4833 scoped_ptr
<GLenum
[]> translated_attachments(new GLenum
[numAttachments
]);
4834 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4835 GLenum attachment
= attachments
[i
];
4836 if (!framebuffer
&& GetBackbufferServiceId()) {
4837 switch (attachment
) {
4839 attachment
= GL_COLOR_ATTACHMENT0
;
4842 attachment
= GL_DEPTH_ATTACHMENT
;
4844 case GL_STENCIL_EXT
:
4845 attachment
= GL_STENCIL_ATTACHMENT
;
4852 translated_attachments
[i
] = attachment
;
4855 ScopedRenderTo
do_render(framebuffer
);
4856 if (feature_info_
->gl_version_info().is_es3
) {
4857 glInvalidateFramebuffer(
4858 target
, numAttachments
, translated_attachments
.get());
4860 glDiscardFramebufferEXT(
4861 target
, numAttachments
, translated_attachments
.get());
4865 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index
) {
4866 if (state_
.vertex_attrib_manager
->Enable(index
, true)) {
4867 glEnableVertexAttribArray(index
);
4870 GL_INVALID_VALUE
, "glEnableVertexAttribArray", "index out of range");
4874 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target
) {
4875 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
4878 !texture_manager()->CanGenerateMipmaps(texture_ref
)) {
4880 GL_INVALID_OPERATION
, "glGenerateMipmap", "Can not generate mips");
4884 if (target
== GL_TEXTURE_CUBE_MAP
) {
4885 for (int i
= 0; i
< 6; ++i
) {
4886 GLenum face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ i
;
4887 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, face
, 0)) {
4889 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
4894 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
, 0)) {
4896 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
4901 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4902 // Workaround for Mac driver bug. In the large scheme of things setting
4903 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4904 // hit so there's probably no need to make this conditional. The bug appears
4905 // to be that if the filtering mode is set to something that doesn't require
4906 // mipmaps for rendering, or is never set to something other than the default,
4907 // then glGenerateMipmap misbehaves.
4908 if (workarounds().set_texture_filter_before_generating_mipmap
) {
4909 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST_MIPMAP_NEAREST
);
4911 glGenerateMipmapEXT(target
);
4912 if (workarounds().set_texture_filter_before_generating_mipmap
) {
4913 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
,
4914 texture_ref
->texture()->min_filter());
4916 GLenum error
= LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4917 if (error
== GL_NO_ERROR
) {
4918 texture_manager()->MarkMipmapsGenerated(texture_ref
);
4922 bool GLES2DecoderImpl::GetHelper(
4923 GLenum pname
, GLint
* params
, GLsizei
* num_written
) {
4924 DCHECK(num_written
);
4925 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
4927 case GL_IMPLEMENTATION_COLOR_READ_FORMAT
:
4929 // Return the GL implementation's preferred format and (see below type)
4930 // if we have the GL extension that exposes this. This allows the GPU
4931 // client to use the implementation's preferred format for glReadPixels
4932 // for optimisation.
4934 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4935 // case when requested on integer/floating point buffers but which is
4936 // acceptable on GLES2 and with the GL_OES_read_format extension.
4938 // Therefore if an error occurs we swallow the error and use the
4939 // internal implementation.
4941 if (context_
->HasExtension("GL_OES_read_format")) {
4942 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
4944 glGetIntegerv(pname
, params
);
4945 if (glGetError() == GL_NO_ERROR
)
4948 *params
= GLES2Util::GetPreferredGLReadPixelsFormat(
4949 GetBoundReadFrameBufferInternalFormat());
4952 case GL_IMPLEMENTATION_COLOR_READ_TYPE
:
4955 if (context_
->HasExtension("GL_OES_read_format")) {
4956 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
4958 glGetIntegerv(pname
, params
);
4959 if (glGetError() == GL_NO_ERROR
)
4962 *params
= GLES2Util::GetPreferredGLReadPixelsType(
4963 GetBoundReadFrameBufferInternalFormat(),
4964 GetBoundReadFrameBufferTextureType());
4967 case GL_MAX_FRAGMENT_UNIFORM_VECTORS
:
4970 *params
= group_
->max_fragment_uniform_vectors();
4973 case GL_MAX_VARYING_VECTORS
:
4976 *params
= group_
->max_varying_vectors();
4979 case GL_MAX_VERTEX_UNIFORM_VECTORS
:
4982 *params
= group_
->max_vertex_uniform_vectors();
4987 if (unsafe_es3_apis_enabled()) {
4989 case GL_MAX_VARYING_COMPONENTS
: {
4990 if (feature_info_
->gl_version_info().is_es
) {
4991 // We can just delegate this query to the driver.
4995 // GL_MAX_VARYING_COMPONENTS is deprecated in the desktop
4996 // OpenGL core profile, so for simplicity, just compute it
4997 // from GL_MAX_VARYING_VECTORS on non-OpenGL ES
4999 GLint max_varying_vectors
= 0;
5000 glGetIntegerv(GL_MAX_VARYING_VECTORS
, &max_varying_vectors
);
5003 *params
= max_varying_vectors
* 4;
5010 case GL_MAX_VIEWPORT_DIMS
:
5011 if (offscreen_target_frame_buffer_
.get()) {
5014 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
5015 params
[1] = renderbuffer_manager()->max_renderbuffer_size();
5020 case GL_MAX_SAMPLES
:
5023 params
[0] = renderbuffer_manager()->max_samples();
5026 case GL_MAX_RENDERBUFFER_SIZE
:
5029 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
5032 case GL_MAX_TEXTURE_SIZE
:
5035 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D
);
5038 case GL_MAX_CUBE_MAP_TEXTURE_SIZE
:
5041 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP
);
5044 case GL_MAX_COLOR_ATTACHMENTS_EXT
:
5047 params
[0] = group_
->max_color_attachments();
5050 case GL_MAX_DRAW_BUFFERS_ARB
:
5053 params
[0] = group_
->max_draw_buffers();
5060 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
5061 Framebuffer
* framebuffer
=
5062 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5064 glGetFramebufferAttachmentParameterivEXT(
5065 GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
5066 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE
, &v
);
5068 v
= (back_buffer_color_format_
== GL_RGBA
? 8 : 0);
5071 glGetIntegerv(GL_ALPHA_BITS
, &v
);
5074 BoundFramebufferHasColorAttachmentWithAlpha(false) ? v
: 0;
5081 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
5082 Framebuffer
* framebuffer
=
5083 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5085 glGetFramebufferAttachmentParameterivEXT(
5086 GL_FRAMEBUFFER
, GL_DEPTH_ATTACHMENT
,
5087 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE
, &v
);
5089 v
= (back_buffer_has_depth_
? 24 : 0);
5092 glGetIntegerv(GL_DEPTH_BITS
, &v
);
5094 params
[0] = BoundFramebufferHasDepthAttachment() ? v
: 0;
5103 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
5104 Framebuffer
* framebuffer
=
5105 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5107 GLenum framebuffer_enum
= 0;
5110 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE
;
5113 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE
;
5116 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE
;
5119 glGetFramebufferAttachmentParameterivEXT(
5120 GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
, framebuffer_enum
, &v
);
5125 glGetIntegerv(pname
, &v
);
5130 case GL_STENCIL_BITS
:
5134 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
5135 Framebuffer
* framebuffer
=
5136 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5138 glGetFramebufferAttachmentParameterivEXT(
5139 GL_FRAMEBUFFER
, GL_STENCIL_ATTACHMENT
,
5140 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE
, &v
);
5142 v
= (back_buffer_has_stencil_
? 8 : 0);
5145 glGetIntegerv(GL_STENCIL_BITS
, &v
);
5147 params
[0] = BoundFramebufferHasStencilAttachment() ? v
: 0;
5150 case GL_COMPRESSED_TEXTURE_FORMATS
:
5151 *num_written
= validators_
->compressed_texture_format
.GetValues().size();
5153 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
5154 params
[ii
] = validators_
->compressed_texture_format
.GetValues()[ii
];
5158 case GL_NUM_COMPRESSED_TEXTURE_FORMATS
:
5161 *params
= validators_
->compressed_texture_format
.GetValues().size();
5164 case GL_NUM_SHADER_BINARY_FORMATS
:
5167 *params
= validators_
->shader_binary_format
.GetValues().size();
5170 case GL_SHADER_BINARY_FORMATS
:
5171 *num_written
= validators_
->shader_binary_format
.GetValues().size();
5173 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
5174 params
[ii
] = validators_
->shader_binary_format
.GetValues()[ii
];
5178 case GL_SHADER_COMPILER
:
5184 case GL_ARRAY_BUFFER_BINDING
:
5187 *params
= GetClientId(
5188 buffer_manager(), state_
.bound_array_buffer
.get());
5191 case GL_ELEMENT_ARRAY_BUFFER_BINDING
:
5194 *params
= GetClientId(
5196 state_
.vertex_attrib_manager
->element_array_buffer());
5199 case GL_COPY_READ_BUFFER_BINDING
:
5202 *params
= GetClientId(
5203 buffer_manager(), state_
.bound_copy_read_buffer
.get());
5206 case GL_COPY_WRITE_BUFFER_BINDING
:
5209 *params
= GetClientId(
5210 buffer_manager(), state_
.bound_copy_write_buffer
.get());
5213 case GL_PIXEL_PACK_BUFFER_BINDING
:
5216 *params
= GetClientId(
5217 buffer_manager(), state_
.bound_pixel_pack_buffer
.get());
5220 case GL_PIXEL_UNPACK_BUFFER_BINDING
:
5223 *params
= GetClientId(
5224 buffer_manager(), state_
.bound_pixel_unpack_buffer
.get());
5227 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING
:
5230 *params
= GetClientId(
5231 buffer_manager(), state_
.bound_transform_feedback_buffer
.get());
5234 case GL_UNIFORM_BUFFER_BINDING
:
5237 *params
= GetClientId(
5238 buffer_manager(), state_
.bound_uniform_buffer
.get());
5241 case GL_FRAMEBUFFER_BINDING
:
5242 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
5245 *params
= GetClientId(
5246 framebuffer_manager(),
5247 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
));
5250 case GL_READ_FRAMEBUFFER_BINDING_EXT
:
5253 *params
= GetClientId(
5254 framebuffer_manager(),
5255 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
));
5258 case GL_RENDERBUFFER_BINDING
:
5261 Renderbuffer
* renderbuffer
=
5262 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5264 *params
= renderbuffer
->client_id();
5270 case GL_CURRENT_PROGRAM
:
5273 *params
= GetClientId(program_manager(), state_
.current_program
.get());
5276 case GL_VERTEX_ARRAY_BINDING_OES
:
5279 if (state_
.vertex_attrib_manager
.get() !=
5280 state_
.default_vertex_attrib_manager
.get()) {
5281 GLuint client_id
= 0;
5282 vertex_array_manager_
->GetClientId(
5283 state_
.vertex_attrib_manager
->service_id(), &client_id
);
5284 *params
= client_id
;
5290 case GL_TEXTURE_BINDING_2D
:
5293 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5294 if (unit
.bound_texture_2d
.get()) {
5295 *params
= unit
.bound_texture_2d
->client_id();
5301 case GL_TEXTURE_BINDING_CUBE_MAP
:
5304 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5305 if (unit
.bound_texture_cube_map
.get()) {
5306 *params
= unit
.bound_texture_cube_map
->client_id();
5312 case GL_TEXTURE_BINDING_EXTERNAL_OES
:
5315 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5316 if (unit
.bound_texture_external_oes
.get()) {
5317 *params
= unit
.bound_texture_external_oes
->client_id();
5323 case GL_TEXTURE_BINDING_RECTANGLE_ARB
:
5326 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5327 if (unit
.bound_texture_rectangle_arb
.get()) {
5328 *params
= unit
.bound_texture_rectangle_arb
->client_id();
5334 case GL_BIND_GENERATES_RESOURCE_CHROMIUM
:
5337 params
[0] = group_
->bind_generates_resource() ? 1 : 0;
5341 if (pname
>= GL_DRAW_BUFFER0_ARB
&&
5342 pname
< GL_DRAW_BUFFER0_ARB
+ group_
->max_draw_buffers()) {
5345 Framebuffer
* framebuffer
=
5346 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
5348 params
[0] = framebuffer
->GetDrawBuffer(pname
);
5349 } else { // backbuffer
5350 if (pname
== GL_DRAW_BUFFER0_ARB
)
5351 params
[0] = group_
->draw_buffer();
5353 params
[0] = GL_NONE
;
5358 *num_written
= util_
.GLGetNumValuesReturned(pname
);
5363 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
5364 GLenum pname
, GLsizei
* num_values
) {
5365 if (state_
.GetStateAsGLint(pname
, NULL
, num_values
)) {
5368 return GetHelper(pname
, NULL
, num_values
);
5371 GLenum
GLES2DecoderImpl::AdjustGetPname(GLenum pname
) {
5372 if (GL_MAX_SAMPLES
== pname
&&
5373 features().use_img_for_multisampled_render_to_texture
) {
5374 return GL_MAX_SAMPLES_IMG
;
5379 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname
, GLboolean
* params
) {
5381 GLsizei num_written
= 0;
5382 if (GetNumValuesReturnedForGLGet(pname
, &num_written
)) {
5383 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
5384 if (!state_
.GetStateAsGLint(pname
, values
.get(), &num_written
)) {
5385 GetHelper(pname
, values
.get(), &num_written
);
5387 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
5388 params
[ii
] = static_cast<GLboolean
>(values
[ii
]);
5391 pname
= AdjustGetPname(pname
);
5392 glGetBooleanv(pname
, params
);
5396 void GLES2DecoderImpl::DoGetFloatv(GLenum pname
, GLfloat
* params
) {
5398 GLsizei num_written
= 0;
5399 if (!state_
.GetStateAsGLfloat(pname
, params
, &num_written
)) {
5400 if (GetHelper(pname
, NULL
, &num_written
)) {
5401 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
5402 GetHelper(pname
, values
.get(), &num_written
);
5403 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
5404 params
[ii
] = static_cast<GLfloat
>(values
[ii
]);
5407 pname
= AdjustGetPname(pname
);
5408 glGetFloatv(pname
, params
);
5413 void GLES2DecoderImpl::DoGetInteger64v(GLenum pname
, GLint64
* params
) {
5415 if (unsafe_es3_apis_enabled()) {
5417 case GL_MAX_ELEMENT_INDEX
: {
5418 if (feature_info_
->gl_version_info().IsAtLeastGLES(3, 0) ||
5419 feature_info_
->gl_version_info().IsAtLeastGL(4, 3)) {
5420 glGetInteger64v(GL_MAX_ELEMENT_INDEX
, params
);
5422 // Assume that desktop GL implementations can generally support
5425 *params
= std::numeric_limits
<unsigned int>::max();
5432 pname
= AdjustGetPname(pname
);
5433 glGetInteger64v(pname
, params
);
5436 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname
, GLint
* params
) {
5438 GLsizei num_written
;
5439 if (!state_
.GetStateAsGLint(pname
, params
, &num_written
) &&
5440 !GetHelper(pname
, params
, &num_written
)) {
5441 pname
= AdjustGetPname(pname
);
5442 glGetIntegerv(pname
, params
);
5446 void GLES2DecoderImpl::DoGetProgramiv(
5447 GLuint program_id
, GLenum pname
, GLint
* params
) {
5448 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetProgramiv");
5452 program
->GetProgramiv(pname
, params
);
5455 void GLES2DecoderImpl::DoGetBufferParameteriv(
5456 GLenum target
, GLenum pname
, GLint
* params
) {
5457 // Just delegate it. Some validation is actually done before this.
5458 buffer_manager()->ValidateAndDoGetBufferParameteriv(
5459 &state_
, target
, pname
, params
);
5462 void GLES2DecoderImpl::DoBindAttribLocation(
5463 GLuint program_id
, GLuint index
, const char* name
) {
5464 if (!StringIsValidForGLES(name
)) {
5466 GL_INVALID_VALUE
, "glBindAttribLocation", "Invalid character");
5469 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
5471 GL_INVALID_OPERATION
, "glBindAttribLocation", "reserved prefix");
5474 if (index
>= group_
->max_vertex_attribs()) {
5476 GL_INVALID_VALUE
, "glBindAttribLocation", "index out of range");
5479 Program
* program
= GetProgramInfoNotShader(
5480 program_id
, "glBindAttribLocation");
5484 // At this point, the program's shaders may not be translated yet,
5485 // therefore, we may not find the hashed attribute name.
5486 // glBindAttribLocation call with original name is useless.
5487 // So instead, we should simply cache the binding, and then call
5488 // Program::ExecuteBindAttribLocationCalls() right before link.
5489 program
->SetAttribLocationBinding(name
, static_cast<GLint
>(index
));
5490 // TODO(zmo): Get rid of the following glBindAttribLocation call.
5491 glBindAttribLocation(program
->service_id(), index
, name
);
5494 error::Error
GLES2DecoderImpl::HandleBindAttribLocationBucket(
5495 uint32 immediate_data_size
,
5496 const void* cmd_data
) {
5497 const gles2::cmds::BindAttribLocationBucket
& c
=
5498 *static_cast<const gles2::cmds::BindAttribLocationBucket
*>(cmd_data
);
5499 GLuint program
= static_cast<GLuint
>(c
.program
);
5500 GLuint index
= static_cast<GLuint
>(c
.index
);
5501 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
5502 if (!bucket
|| bucket
->size() == 0) {
5503 return error::kInvalidArguments
;
5505 std::string name_str
;
5506 if (!bucket
->GetAsString(&name_str
)) {
5507 return error::kInvalidArguments
;
5509 DoBindAttribLocation(program
, index
, name_str
.c_str());
5510 return error::kNoError
;
5513 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
5514 GLuint program_id
, GLint location
, const char* name
) {
5515 if (!StringIsValidForGLES(name
)) {
5518 "glBindUniformLocationCHROMIUM", "Invalid character");
5521 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
5523 GL_INVALID_OPERATION
,
5524 "glBindUniformLocationCHROMIUM", "reserved prefix");
5527 if (location
< 0 || static_cast<uint32
>(location
) >=
5528 (group_
->max_fragment_uniform_vectors() +
5529 group_
->max_vertex_uniform_vectors()) * 4) {
5532 "glBindUniformLocationCHROMIUM", "location out of range");
5535 Program
* program
= GetProgramInfoNotShader(
5536 program_id
, "glBindUniformLocationCHROMIUM");
5540 if (!program
->SetUniformLocationBinding(name
, location
)) {
5543 "glBindUniformLocationCHROMIUM", "location out of range");
5547 error::Error
GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
5548 uint32 immediate_data_size
,
5549 const void* cmd_data
) {
5550 const gles2::cmds::BindUniformLocationCHROMIUMBucket
& c
=
5551 *static_cast<const gles2::cmds::BindUniformLocationCHROMIUMBucket
*>(
5553 GLuint program
= static_cast<GLuint
>(c
.program
);
5554 GLint location
= static_cast<GLint
>(c
.location
);
5555 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
5556 if (!bucket
|| bucket
->size() == 0) {
5557 return error::kInvalidArguments
;
5559 std::string name_str
;
5560 if (!bucket
->GetAsString(&name_str
)) {
5561 return error::kInvalidArguments
;
5563 DoBindUniformLocationCHROMIUM(program
, location
, name_str
.c_str());
5564 return error::kNoError
;
5567 error::Error
GLES2DecoderImpl::HandleDeleteShader(uint32 immediate_data_size
,
5568 const void* cmd_data
) {
5569 const gles2::cmds::DeleteShader
& c
=
5570 *static_cast<const gles2::cmds::DeleteShader
*>(cmd_data
);
5571 GLuint client_id
= c
.shader
;
5573 Shader
* shader
= GetShader(client_id
);
5575 if (!shader
->IsDeleted()) {
5576 shader_manager()->Delete(shader
);
5579 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glDeleteShader", "unknown shader");
5582 return error::kNoError
;
5585 error::Error
GLES2DecoderImpl::HandleDeleteProgram(uint32 immediate_data_size
,
5586 const void* cmd_data
) {
5587 const gles2::cmds::DeleteProgram
& c
=
5588 *static_cast<const gles2::cmds::DeleteProgram
*>(cmd_data
);
5589 GLuint client_id
= c
.program
;
5591 Program
* program
= GetProgram(client_id
);
5593 if (!program
->IsDeleted()) {
5594 program_manager()->MarkAsDeleted(shader_manager(), program
);
5598 GL_INVALID_VALUE
, "glDeleteProgram", "unknown program");
5601 return error::kNoError
;
5604 error::Error
GLES2DecoderImpl::DoClear(GLbitfield mask
) {
5605 DCHECK(!ShouldDeferDraws());
5606 if (CheckBoundFramebuffersValid("glClear")) {
5608 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
5609 if (workarounds().gl_clear_broken
) {
5610 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::ClearWorkaround",
5612 if (!BoundFramebufferHasDepthAttachment())
5613 mask
&= ~GL_DEPTH_BUFFER_BIT
;
5614 if (!BoundFramebufferHasStencilAttachment())
5615 mask
&= ~GL_STENCIL_BUFFER_BIT
;
5616 clear_framebuffer_blit_
->ClearFramebuffer(
5617 this, GetBoundReadFrameBufferSize(), mask
, state_
.color_clear_red
,
5618 state_
.color_clear_green
, state_
.color_clear_blue
,
5619 state_
.color_clear_alpha
, state_
.depth_clear
, state_
.stencil_clear
);
5620 return error::kNoError
;
5624 return error::kNoError
;
5627 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
5628 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
5629 GLuint client_renderbuffer_id
) {
5630 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5633 GL_INVALID_OPERATION
,
5634 "glFramebufferRenderbuffer", "no framebuffer bound");
5637 GLuint service_id
= 0;
5638 Renderbuffer
* renderbuffer
= NULL
;
5639 if (client_renderbuffer_id
) {
5640 renderbuffer
= GetRenderbuffer(client_renderbuffer_id
);
5641 if (!renderbuffer
) {
5643 GL_INVALID_OPERATION
,
5644 "glFramebufferRenderbuffer", "unknown renderbuffer");
5647 service_id
= renderbuffer
->service_id();
5649 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
5650 glFramebufferRenderbufferEXT(
5651 target
, attachment
, renderbuffertarget
, service_id
);
5652 GLenum error
= LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
5653 if (error
== GL_NO_ERROR
) {
5654 framebuffer
->AttachRenderbuffer(attachment
, renderbuffer
);
5656 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
5657 framebuffer_state_
.clear_state_dirty
= true;
5662 void GLES2DecoderImpl::DoDisable(GLenum cap
) {
5663 if (SetCapabilityState(cap
, false)) {
5668 void GLES2DecoderImpl::DoEnable(GLenum cap
) {
5669 if (SetCapabilityState(cap
, true)) {
5674 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear
, GLclampf zfar
) {
5675 state_
.z_near
= std::min(1.0f
, std::max(0.0f
, znear
));
5676 state_
.z_far
= std::min(1.0f
, std::max(0.0f
, zfar
));
5677 glDepthRange(znear
, zfar
);
5680 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value
, GLboolean invert
) {
5681 state_
.sample_coverage_value
= std::min(1.0f
, std::max(0.0f
, value
));
5682 state_
.sample_coverage_invert
= (invert
!= 0);
5683 glSampleCoverage(state_
.sample_coverage_value
, invert
);
5686 // Assumes framebuffer is complete.
5687 void GLES2DecoderImpl::ClearUnclearedAttachments(
5688 GLenum target
, Framebuffer
* framebuffer
) {
5689 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
5690 // bind this to the DRAW point, clear then bind back to READ
5691 // TODO(gman): I don't think there is any guarantee that an FBO that
5692 // is complete on the READ attachment will be complete as a DRAW
5694 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, 0);
5695 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, framebuffer
->service_id());
5697 GLbitfield clear_bits
= 0;
5698 if (framebuffer
->HasUnclearedColorAttachments()) {
5701 (GLES2Util::GetChannelsForFormat(
5702 framebuffer
->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f
:
5704 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
5705 clear_bits
|= GL_COLOR_BUFFER_BIT
;
5706 if (feature_info_
->feature_flags().ext_draw_buffers
)
5707 framebuffer
->PrepareDrawBuffersForClear();
5710 if (framebuffer
->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT
) ||
5711 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
5713 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
5714 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
5715 clear_bits
|= GL_STENCIL_BUFFER_BIT
;
5718 if (framebuffer
->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT
) ||
5719 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
5721 state_
.SetDeviceDepthMask(GL_TRUE
);
5722 clear_bits
|= GL_DEPTH_BUFFER_BIT
;
5725 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5726 glClear(clear_bits
);
5728 if ((clear_bits
& GL_COLOR_BUFFER_BIT
) != 0 &&
5729 feature_info_
->feature_flags().ext_draw_buffers
)
5730 framebuffer
->RestoreDrawBuffersAfterClear();
5732 framebuffer_manager()->MarkAttachmentsAsCleared(
5733 framebuffer
, renderbuffer_manager(), texture_manager());
5735 RestoreClearState();
5737 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
5738 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, framebuffer
->service_id());
5739 Framebuffer
* draw_framebuffer
=
5740 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5741 GLuint service_id
= draw_framebuffer
? draw_framebuffer
->service_id() :
5742 GetBackbufferServiceId();
5743 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, service_id
);
5747 void GLES2DecoderImpl::RestoreClearState() {
5748 framebuffer_state_
.clear_state_dirty
= true;
5750 state_
.color_clear_red
, state_
.color_clear_green
, state_
.color_clear_blue
,
5751 state_
.color_clear_alpha
);
5752 glClearStencil(state_
.stencil_clear
);
5753 glClearDepth(state_
.depth_clear
);
5754 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
,
5755 state_
.enable_flags
.scissor_test
);
5756 glScissor(state_
.scissor_x
, state_
.scissor_y
, state_
.scissor_width
,
5757 state_
.scissor_height
);
5760 GLenum
GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target
) {
5761 Framebuffer
* framebuffer
=
5762 GetFramebufferInfoForTarget(target
);
5764 return GL_FRAMEBUFFER_COMPLETE
;
5766 GLenum completeness
= framebuffer
->IsPossiblyComplete();
5767 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
5768 return completeness
;
5770 return framebuffer
->GetStatus(texture_manager(), target
);
5773 void GLES2DecoderImpl::DoFramebufferTexture2D(
5774 GLenum target
, GLenum attachment
, GLenum textarget
,
5775 GLuint client_texture_id
, GLint level
) {
5776 DoFramebufferTexture2DCommon(
5777 "glFramebufferTexture2D", target
, attachment
,
5778 textarget
, client_texture_id
, level
, 0);
5781 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5782 GLenum target
, GLenum attachment
, GLenum textarget
,
5783 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
5784 DoFramebufferTexture2DCommon(
5785 "glFramebufferTexture2DMultisample", target
, attachment
,
5786 textarget
, client_texture_id
, level
, samples
);
5789 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5790 const char* name
, GLenum target
, GLenum attachment
, GLenum textarget
,
5791 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
5792 if (samples
> renderbuffer_manager()->max_samples()) {
5795 "glFramebufferTexture2DMultisample", "samples too large");
5798 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5801 GL_INVALID_OPERATION
,
5802 name
, "no framebuffer bound.");
5805 GLuint service_id
= 0;
5806 TextureRef
* texture_ref
= NULL
;
5807 if (client_texture_id
) {
5808 texture_ref
= GetTexture(client_texture_id
);
5811 GL_INVALID_OPERATION
,
5812 name
, "unknown texture_ref");
5815 service_id
= texture_ref
->service_id();
5818 if (!texture_manager()->ValidForTarget(textarget
, level
, 0, 0, 1)) {
5821 name
, "level out of range");
5826 DoWillUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
5828 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name
);
5830 glFramebufferTexture2DEXT(target
, attachment
, textarget
, service_id
, level
);
5832 if (features().use_img_for_multisampled_render_to_texture
) {
5833 glFramebufferTexture2DMultisampleIMG(target
, attachment
, textarget
,
5834 service_id
, level
, samples
);
5836 glFramebufferTexture2DMultisampleEXT(target
, attachment
, textarget
,
5837 service_id
, level
, samples
);
5840 GLenum error
= LOCAL_PEEK_GL_ERROR(name
);
5841 if (error
== GL_NO_ERROR
) {
5842 framebuffer
->AttachTexture(attachment
, texture_ref
, textarget
, level
,
5845 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
5846 framebuffer_state_
.clear_state_dirty
= true;
5850 DoDidUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
5855 void GLES2DecoderImpl::DoFramebufferTextureLayer(
5856 GLenum target
, GLenum attachment
, GLuint client_texture_id
,
5857 GLint level
, GLint layer
) {
5858 // TODO(zmo): Unsafe ES3 API, missing states update.
5859 GLuint service_id
= 0;
5860 TextureRef
* texture_ref
= NULL
;
5861 if (client_texture_id
) {
5862 texture_ref
= GetTexture(client_texture_id
);
5865 GL_INVALID_OPERATION
,
5866 "glFramebufferTextureLayer", "unknown texture_ref");
5869 service_id
= texture_ref
->service_id();
5871 glFramebufferTextureLayer(target
, attachment
, service_id
, level
, layer
);
5874 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5875 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
) {
5876 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5879 GL_INVALID_OPERATION
,
5880 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5883 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME
) {
5884 const Framebuffer::Attachment
* attachment_object
=
5885 framebuffer
->GetAttachment(attachment
);
5886 *params
= attachment_object
? attachment_object
->object_name() : 0;
5888 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT
&&
5889 features().use_img_for_multisampled_render_to_texture
) {
5890 pname
= GL_TEXTURE_SAMPLES_IMG
;
5892 glGetFramebufferAttachmentParameterivEXT(target
, attachment
, pname
, params
);
5896 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5897 GLenum target
, GLenum pname
, GLint
* params
) {
5898 Renderbuffer
* renderbuffer
=
5899 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5900 if (!renderbuffer
) {
5902 GL_INVALID_OPERATION
,
5903 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5907 EnsureRenderbufferBound();
5909 case GL_RENDERBUFFER_INTERNAL_FORMAT
:
5910 *params
= renderbuffer
->internal_format();
5912 case GL_RENDERBUFFER_WIDTH
:
5913 *params
= renderbuffer
->width();
5915 case GL_RENDERBUFFER_HEIGHT
:
5916 *params
= renderbuffer
->height();
5918 case GL_RENDERBUFFER_SAMPLES_EXT
:
5919 if (features().use_img_for_multisampled_render_to_texture
) {
5920 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_IMG
,
5923 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_EXT
,
5927 glGetRenderbufferParameterivEXT(target
, pname
, params
);
5932 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5933 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
5934 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
5935 GLbitfield mask
, GLenum filter
) {
5936 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5938 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5942 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5943 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
5944 BlitFramebufferHelper(
5945 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5946 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
,
5947 state_
.enable_flags
.scissor_test
);
5950 void GLES2DecoderImpl::EnsureRenderbufferBound() {
5951 if (!state_
.bound_renderbuffer_valid
) {
5952 state_
.bound_renderbuffer_valid
= true;
5953 glBindRenderbufferEXT(GL_RENDERBUFFER
,
5954 state_
.bound_renderbuffer
.get()
5955 ? state_
.bound_renderbuffer
->service_id()
5960 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
5961 const FeatureInfo
* feature_info
,
5964 GLenum internal_format
,
5967 // TODO(sievers): This could be resolved at the GL binding level, but the
5968 // binding process is currently a bit too 'brute force'.
5969 if (feature_info
->gl_version_info().is_angle
) {
5970 glRenderbufferStorageMultisampleANGLE(
5971 target
, samples
, internal_format
, width
, height
);
5972 } else if (feature_info
->feature_flags().use_core_framebuffer_multisample
) {
5973 glRenderbufferStorageMultisample(
5974 target
, samples
, internal_format
, width
, height
);
5976 glRenderbufferStorageMultisampleEXT(
5977 target
, samples
, internal_format
, width
, height
);
5981 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0
,
5991 // TODO(sievers): This could be resolved at the GL binding level, but the
5992 // binding process is currently a bit too 'brute force'.
5993 if (feature_info_
->gl_version_info().is_angle
) {
5994 glBlitFramebufferANGLE(
5995 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5996 } else if (feature_info_
->feature_flags().use_core_framebuffer_multisample
) {
5998 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
6000 glBlitFramebufferEXT(
6001 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
6005 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
6007 GLenum internalformat
,
6010 if (samples
> renderbuffer_manager()->max_samples()) {
6013 "glRenderbufferStorageMultisample", "samples too large");
6017 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
6018 height
> renderbuffer_manager()->max_renderbuffer_size()) {
6021 "glRenderbufferStorageMultisample", "dimensions too large");
6025 uint32 estimated_size
= 0;
6026 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6027 width
, height
, samples
, internalformat
, &estimated_size
)) {
6030 "glRenderbufferStorageMultisample", "dimensions too large");
6034 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
6037 "glRenderbufferStorageMultisample", "out of memory");
6044 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
6045 GLenum target
, GLsizei samples
, GLenum internalformat
,
6046 GLsizei width
, GLsizei height
) {
6047 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
6048 if (!renderbuffer
) {
6049 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
6050 "glRenderbufferStorageMultisampleCHROMIUM",
6051 "no renderbuffer bound");
6055 if (!ValidateRenderbufferStorageMultisample(
6056 samples
, internalformat
, width
, height
)) {
6060 EnsureRenderbufferBound();
6061 GLenum impl_format
=
6062 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6064 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
6065 "glRenderbufferStorageMultisampleCHROMIUM");
6066 RenderbufferStorageMultisampleHelper(
6067 feature_info_
.get(), target
, samples
, impl_format
, width
, height
);
6069 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
6070 if (error
== GL_NO_ERROR
) {
6071 if (workarounds().validate_multisample_buffer_allocation
) {
6072 if (!VerifyMultisampleRenderbufferIntegrity(
6073 renderbuffer
->service_id(), impl_format
)) {
6076 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
6081 // TODO(gman): If renderbuffers tracked which framebuffers they were
6082 // attached to we could just mark those framebuffers as not complete.
6083 framebuffer_manager()->IncFramebufferStateChangeCount();
6084 renderbuffer_manager()->SetInfo(
6085 renderbuffer
, samples
, internalformat
, width
, height
);
6089 // This is the handler for multisampled_render_to_texture extensions.
6090 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
6091 GLenum target
, GLsizei samples
, GLenum internalformat
,
6092 GLsizei width
, GLsizei height
) {
6093 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
6094 if (!renderbuffer
) {
6095 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
6096 "glRenderbufferStorageMultisampleEXT",
6097 "no renderbuffer bound");
6101 if (!ValidateRenderbufferStorageMultisample(
6102 samples
, internalformat
, width
, height
)) {
6106 EnsureRenderbufferBound();
6107 GLenum impl_format
=
6108 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6110 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
6111 if (features().use_img_for_multisampled_render_to_texture
) {
6112 glRenderbufferStorageMultisampleIMG(
6113 target
, samples
, impl_format
, width
, height
);
6115 glRenderbufferStorageMultisampleEXT(
6116 target
, samples
, impl_format
, width
, height
);
6118 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
6119 if (error
== GL_NO_ERROR
) {
6120 // TODO(gman): If renderbuffers tracked which framebuffers they were
6121 // attached to we could just mark those framebuffers as not complete.
6122 framebuffer_manager()->IncFramebufferStateChangeCount();
6123 renderbuffer_manager()->SetInfo(
6124 renderbuffer
, samples
, internalformat
, width
, height
);
6128 // This function validates the allocation of a multisampled renderbuffer
6129 // by clearing it to a key color, blitting the contents to a texture, and
6130 // reading back the color to ensure it matches the key.
6131 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
6132 GLuint renderbuffer
, GLenum format
) {
6134 // Only validate color buffers.
6135 // These formats have been selected because they are very common or are known
6136 // to be used by the WebGL backbuffer. If problems are observed with other
6137 // color formats they can be added here.
6148 GLint draw_framebuffer
, read_framebuffer
;
6150 // Cache framebuffer and texture bindings.
6151 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING
, &draw_framebuffer
);
6152 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING
, &read_framebuffer
);
6154 if (!validation_texture_
) {
6155 GLint bound_texture
;
6156 glGetIntegerv(GL_TEXTURE_BINDING_2D
, &bound_texture
);
6158 // Create additional resources needed for the verification.
6159 glGenTextures(1, &validation_texture_
);
6160 glGenFramebuffersEXT(1, &validation_fbo_multisample_
);
6161 glGenFramebuffersEXT(1, &validation_fbo_
);
6163 // Texture only needs to be 1x1.
6164 glBindTexture(GL_TEXTURE_2D
, validation_texture_
);
6165 // TODO(erikchen): When Chrome on Mac is linked against an OSX 10.9+ SDK, a
6166 // multisample will fail if the color format of the source and destination
6167 // do not match. Here, we assume that the source is GL_RGBA, and make the
6168 // destination GL_RGBA. http://crbug.com/484203
6169 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, 1, 1, 0, GL_RGBA
,
6170 GL_UNSIGNED_BYTE
, NULL
);
6172 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
6173 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
6174 GL_TEXTURE_2D
, validation_texture_
, 0);
6176 glBindTexture(GL_TEXTURE_2D
, bound_texture
);
6179 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
6180 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
6181 GL_RENDERBUFFER
, renderbuffer
);
6183 // Cache current state and reset it to the values we require.
6184 GLboolean scissor_enabled
= false;
6185 glGetBooleanv(GL_SCISSOR_TEST
, &scissor_enabled
);
6186 if (scissor_enabled
)
6187 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
6189 GLboolean color_mask
[4] = {GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
};
6190 glGetBooleanv(GL_COLOR_WRITEMASK
, color_mask
);
6191 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
6193 GLfloat clear_color
[4] = {0.0f
, 0.0f
, 0.0f
, 0.0f
};
6194 glGetFloatv(GL_COLOR_CLEAR_VALUE
, clear_color
);
6195 glClearColor(1.0f
, 0.0f
, 1.0f
, 1.0f
);
6197 // Clear the buffer to the desired key color.
6198 glClear(GL_COLOR_BUFFER_BIT
);
6200 // Blit from the multisample buffer to a standard texture.
6201 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, validation_fbo_multisample_
);
6202 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, validation_fbo_
);
6204 BlitFramebufferHelper(
6205 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
6207 // Read a pixel from the buffer.
6208 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
6210 unsigned char pixel
[3] = {0, 0, 0};
6211 glReadPixels(0, 0, 1, 1, GL_RGB
, GL_UNSIGNED_BYTE
, &pixel
);
6213 // Detach the renderbuffer.
6214 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
6215 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
6216 GL_RENDERBUFFER
, 0);
6218 // Restore cached state.
6219 if (scissor_enabled
)
6220 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
6222 state_
.SetDeviceColorMask(
6223 color_mask
[0], color_mask
[1], color_mask
[2], color_mask
[3]);
6224 glClearColor(clear_color
[0], clear_color
[1], clear_color
[2], clear_color
[3]);
6225 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, draw_framebuffer
);
6226 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, read_framebuffer
);
6228 // Return true if the pixel matched the desired key color.
6229 return (pixel
[0] == 0xFF &&
6234 void GLES2DecoderImpl::DoRenderbufferStorage(
6235 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
) {
6236 Renderbuffer
* renderbuffer
=
6237 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
6238 if (!renderbuffer
) {
6240 GL_INVALID_OPERATION
,
6241 "glRenderbufferStorage", "no renderbuffer bound");
6245 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
6246 height
> renderbuffer_manager()->max_renderbuffer_size()) {
6248 GL_INVALID_VALUE
, "glRenderbufferStorage", "dimensions too large");
6252 uint32 estimated_size
= 0;
6253 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6254 width
, height
, 1, internalformat
, &estimated_size
)) {
6256 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "dimensions too large");
6260 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
6262 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "out of memory");
6266 EnsureRenderbufferBound();
6267 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
6268 glRenderbufferStorageEXT(
6270 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6274 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
6275 if (error
== GL_NO_ERROR
) {
6276 // TODO(gman): If tetxures tracked which framebuffers they were attached to
6277 // we could just mark those framebuffers as not complete.
6278 framebuffer_manager()->IncFramebufferStateChangeCount();
6279 renderbuffer_manager()->SetInfo(
6280 renderbuffer
, 1, internalformat
, width
, height
);
6284 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id
) {
6285 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
6286 Program
* program
= GetProgramInfoNotShader(
6287 program_id
, "glLinkProgram");
6292 LogClientServiceForInfo(program
, program_id
, "glLinkProgram");
6293 if (program
->Link(shader_manager(),
6294 workarounds().count_all_in_varyings_packing
?
6295 Program::kCountAll
: Program::kCountOnlyStaticallyUsed
,
6296 shader_cache_callback_
)) {
6297 if (program
== state_
.current_program
.get()) {
6298 if (workarounds().use_current_program_after_successful_link
)
6299 glUseProgram(program
->service_id());
6300 if (workarounds().clear_uniforms_before_first_program_use
)
6301 program_manager()->ClearUniforms(program
);
6305 // LinkProgram can be very slow. Exit command processing to allow for
6306 // context preemption and GPU watchdog checks.
6307 ExitCommandProcessingEarly();
6310 void GLES2DecoderImpl::DoSamplerParameterfv(
6311 GLuint sampler
, GLenum pname
, const GLfloat
* params
) {
6313 glSamplerParameterf(sampler
, pname
, params
[0]);
6316 void GLES2DecoderImpl::DoSamplerParameteriv(
6317 GLuint sampler
, GLenum pname
, const GLint
* params
) {
6319 glSamplerParameteri(sampler
, pname
, params
[0]);
6322 void GLES2DecoderImpl::DoTexParameterf(
6323 GLenum target
, GLenum pname
, GLfloat param
) {
6324 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6327 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterf", "unknown texture");
6331 texture_manager()->SetParameterf(
6332 "glTexParameterf", GetErrorState(), texture
, pname
, param
);
6335 void GLES2DecoderImpl::DoTexParameteri(
6336 GLenum target
, GLenum pname
, GLint param
) {
6337 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6340 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameteri", "unknown texture");
6344 texture_manager()->SetParameteri(
6345 "glTexParameteri", GetErrorState(), texture
, pname
, param
);
6348 void GLES2DecoderImpl::DoTexParameterfv(
6349 GLenum target
, GLenum pname
, const GLfloat
* params
) {
6350 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6353 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterfv", "unknown texture");
6357 texture_manager()->SetParameterf(
6358 "glTexParameterfv", GetErrorState(), texture
, pname
, *params
);
6361 void GLES2DecoderImpl::DoTexParameteriv(
6362 GLenum target
, GLenum pname
, const GLint
* params
) {
6363 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6367 GL_INVALID_VALUE
, "glTexParameteriv", "unknown texture");
6371 texture_manager()->SetParameteri(
6372 "glTexParameteriv", GetErrorState(), texture
, pname
, *params
);
6375 bool GLES2DecoderImpl::CheckCurrentValuebuffer(const char* function_name
) {
6376 if (!state_
.bound_valuebuffer
.get()) {
6377 // There is no valuebuffer bound
6378 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6379 "no valuebuffer in use");
6385 bool GLES2DecoderImpl::CheckCurrentValuebufferForSubscription(
6386 GLenum subscription
,
6387 const char* function_name
) {
6388 if (!CheckCurrentValuebuffer(function_name
)) {
6391 if (!state_
.bound_valuebuffer
.get()->IsSubscribed(subscription
)) {
6392 // The valuebuffer is not subscribed to the target
6393 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6394 "valuebuffer is not subscribed");
6400 bool GLES2DecoderImpl::CheckSubscriptionTarget(GLint location
,
6401 GLenum subscription
,
6402 const char* function_name
) {
6403 if (!CheckCurrentProgramForUniform(location
, function_name
)) {
6406 GLint real_location
= -1;
6407 GLint array_index
= -1;
6408 const Program::UniformInfo
* info
=
6409 state_
.current_program
->GetUniformInfoByFakeLocation(
6410 location
, &real_location
, &array_index
);
6412 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
, "unknown location");
6415 if ((ValuebufferManager::ApiTypeForSubscriptionTarget(subscription
) &
6416 info
->accepts_api_type
) == 0) {
6417 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6418 "wrong type for subscription");
6424 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name
) {
6425 if (!state_
.current_program
.get()) {
6426 // The program does not exist.
6428 GL_INVALID_OPERATION
, function_name
, "no program in use");
6431 if (!state_
.current_program
->InUse()) {
6433 GL_INVALID_OPERATION
, function_name
, "program not linked");
6439 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
6440 GLint location
, const char* function_name
) {
6441 if (!CheckCurrentProgram(function_name
)) {
6444 return location
!= -1;
6447 bool GLES2DecoderImpl::CheckDrawingFeedbackLoops() {
6448 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
6451 const Framebuffer::Attachment
* attachment
=
6452 framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
);
6456 DCHECK(state_
.current_program
.get());
6457 const Program::SamplerIndices
& sampler_indices
=
6458 state_
.current_program
->sampler_indices();
6459 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6460 const Program::UniformInfo
* uniform_info
=
6461 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6462 DCHECK(uniform_info
);
6463 if (uniform_info
->type
!= GL_SAMPLER_2D
)
6465 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6466 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6467 if (texture_unit_index
>= state_
.texture_units
.size())
6469 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6470 TextureRef
* texture_ref
=
6471 texture_unit
.GetInfoForSamplerType(GL_SAMPLER_2D
).get();
6472 if (attachment
->IsTexture(texture_ref
))
6479 bool GLES2DecoderImpl::CheckUniformForApiType(
6480 const Program::UniformInfo
* info
,
6481 const char* function_name
,
6482 Program::UniformApiType api_type
) {
6484 if ((api_type
& info
->accepts_api_type
) == 0) {
6485 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6486 "wrong uniform function for type");
6492 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
6493 GLint fake_location
,
6494 const char* function_name
,
6495 Program::UniformApiType api_type
,
6496 GLint
* real_location
,
6501 DCHECK(real_location
);
6503 if (!CheckCurrentProgramForUniform(fake_location
, function_name
)) {
6506 GLint array_index
= -1;
6507 const Program::UniformInfo
* info
=
6508 state_
.current_program
->GetUniformInfoByFakeLocation(
6509 fake_location
, real_location
, &array_index
);
6512 GL_INVALID_OPERATION
, function_name
, "unknown location");
6515 if (!CheckUniformForApiType(info
, function_name
, api_type
)) {
6518 if (*count
> 1 && !info
->is_array
) {
6520 GL_INVALID_OPERATION
, function_name
, "count > 1 for non-array");
6523 *count
= std::min(info
->size
- array_index
, *count
);
6531 void GLES2DecoderImpl::DoUniform1i(GLint fake_location
, GLint v0
) {
6534 GLint real_location
= -1;
6535 if (!PrepForSetUniformByLocation(fake_location
,
6537 Program::kUniform1i
,
6543 if (!state_
.current_program
->SetSamplers(
6544 state_
.texture_units
.size(), fake_location
, 1, &v0
)) {
6546 GL_INVALID_VALUE
, "glUniform1i", "texture unit out of range");
6549 glUniform1i(real_location
, v0
);
6552 void GLES2DecoderImpl::DoUniform1iv(
6553 GLint fake_location
, GLsizei count
, const GLint
*value
) {
6555 GLint real_location
= -1;
6556 if (!PrepForSetUniformByLocation(fake_location
,
6558 Program::kUniform1i
,
6564 if (type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_2D_RECT_ARB
||
6565 type
== GL_SAMPLER_CUBE
|| type
== GL_SAMPLER_EXTERNAL_OES
) {
6566 if (!state_
.current_program
->SetSamplers(
6567 state_
.texture_units
.size(), fake_location
, count
, value
)) {
6569 GL_INVALID_VALUE
, "glUniform1iv", "texture unit out of range");
6573 glUniform1iv(real_location
, count
, value
);
6576 void GLES2DecoderImpl::DoUniform1fv(
6577 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6579 GLint real_location
= -1;
6580 if (!PrepForSetUniformByLocation(fake_location
,
6582 Program::kUniform1f
,
6588 if (type
== GL_BOOL
) {
6589 scoped_ptr
<GLint
[]> temp(new GLint
[count
]);
6590 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
6591 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6593 DoUniform1iv(real_location
, count
, temp
.get());
6595 glUniform1fv(real_location
, count
, value
);
6599 void GLES2DecoderImpl::DoUniform2fv(
6600 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6602 GLint real_location
= -1;
6603 if (!PrepForSetUniformByLocation(fake_location
,
6605 Program::kUniform2f
,
6611 if (type
== GL_BOOL_VEC2
) {
6612 GLsizei num_values
= count
* 2;
6613 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6614 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6615 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6617 glUniform2iv(real_location
, count
, temp
.get());
6619 glUniform2fv(real_location
, count
, value
);
6623 void GLES2DecoderImpl::DoUniform3fv(
6624 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6626 GLint real_location
= -1;
6627 if (!PrepForSetUniformByLocation(fake_location
,
6629 Program::kUniform3f
,
6635 if (type
== GL_BOOL_VEC3
) {
6636 GLsizei num_values
= count
* 3;
6637 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6638 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6639 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6641 glUniform3iv(real_location
, count
, temp
.get());
6643 glUniform3fv(real_location
, count
, value
);
6647 void GLES2DecoderImpl::DoUniform4fv(
6648 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6650 GLint real_location
= -1;
6651 if (!PrepForSetUniformByLocation(fake_location
,
6653 Program::kUniform4f
,
6659 if (type
== GL_BOOL_VEC4
) {
6660 GLsizei num_values
= count
* 4;
6661 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6662 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6663 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6665 glUniform4iv(real_location
, count
, temp
.get());
6667 glUniform4fv(real_location
, count
, value
);
6671 void GLES2DecoderImpl::DoUniform2iv(
6672 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6674 GLint real_location
= -1;
6675 if (!PrepForSetUniformByLocation(fake_location
,
6677 Program::kUniform2i
,
6683 glUniform2iv(real_location
, count
, value
);
6686 void GLES2DecoderImpl::DoUniform3iv(
6687 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6689 GLint real_location
= -1;
6690 if (!PrepForSetUniformByLocation(fake_location
,
6692 Program::kUniform3i
,
6698 glUniform3iv(real_location
, count
, value
);
6701 void GLES2DecoderImpl::DoUniform4iv(
6702 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6704 GLint real_location
= -1;
6705 if (!PrepForSetUniformByLocation(fake_location
,
6707 Program::kUniform4i
,
6713 glUniform4iv(real_location
, count
, value
);
6716 void GLES2DecoderImpl::DoUniformMatrix2fv(
6717 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6718 const GLfloat
* value
) {
6720 GLint real_location
= -1;
6721 if (!PrepForSetUniformByLocation(fake_location
,
6722 "glUniformMatrix2fv",
6723 Program::kUniformMatrix2f
,
6729 glUniformMatrix2fv(real_location
, count
, transpose
, value
);
6732 void GLES2DecoderImpl::DoUniformMatrix3fv(
6733 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6734 const GLfloat
* value
) {
6736 GLint real_location
= -1;
6737 if (!PrepForSetUniformByLocation(fake_location
,
6738 "glUniformMatrix3fv",
6739 Program::kUniformMatrix3f
,
6745 glUniformMatrix3fv(real_location
, count
, transpose
, value
);
6748 void GLES2DecoderImpl::DoUniformMatrix4fv(
6749 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6750 const GLfloat
* value
) {
6752 GLint real_location
= -1;
6753 if (!PrepForSetUniformByLocation(fake_location
,
6754 "glUniformMatrix4fv",
6755 Program::kUniformMatrix4f
,
6761 glUniformMatrix4fv(real_location
, count
, transpose
, value
);
6764 void GLES2DecoderImpl::DoUseProgram(GLuint program_id
) {
6765 GLuint service_id
= 0;
6766 Program
* program
= NULL
;
6768 program
= GetProgramInfoNotShader(program_id
, "glUseProgram");
6772 if (!program
->IsValid()) {
6773 // Program was not linked successfully. (ie, glLinkProgram)
6775 GL_INVALID_OPERATION
, "glUseProgram", "program not linked");
6778 service_id
= program
->service_id();
6780 if (state_
.current_program
.get()) {
6781 program_manager()->UnuseProgram(shader_manager(),
6782 state_
.current_program
.get());
6784 state_
.current_program
= program
;
6785 LogClientServiceMapping("glUseProgram", program_id
, service_id
);
6786 glUseProgram(service_id
);
6787 if (state_
.current_program
.get()) {
6788 program_manager()->UseProgram(state_
.current_program
.get());
6789 if (workarounds().clear_uniforms_before_first_program_use
)
6790 program_manager()->ClearUniforms(program
);
6794 void GLES2DecoderImpl::RenderWarning(
6795 const char* filename
, int line
, const std::string
& msg
) {
6796 logger_
.LogMessage(filename
, line
, std::string("RENDER WARNING: ") + msg
);
6799 void GLES2DecoderImpl::PerformanceWarning(
6800 const char* filename
, int line
, const std::string
& msg
) {
6801 logger_
.LogMessage(filename
, line
,
6802 std::string("PERFORMANCE WARNING: ") + msg
);
6805 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
6806 Texture
* texture
, GLenum textarget
) {
6807 // Image is already in use if texture is attached to a framebuffer.
6808 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
6809 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6811 ScopedGLErrorSuppressor
suppressor(
6812 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
6814 glBindTexture(textarget
, texture
->service_id());
6815 image
->WillUseTexImage();
6816 RestoreCurrentTextureBindings(&state_
, textarget
);
6821 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6822 Texture
* texture
, GLenum textarget
) {
6823 // Image is still in use if texture is attached to a framebuffer.
6824 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
6825 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6827 ScopedGLErrorSuppressor
suppressor(
6828 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6830 glBindTexture(textarget
, texture
->service_id());
6831 image
->DidUseTexImage();
6832 RestoreCurrentTextureBindings(&state_
, textarget
);
6837 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6838 DCHECK(state_
.current_program
.get());
6839 if (!texture_manager()->HaveUnrenderableTextures() &&
6840 !texture_manager()->HaveImages()) {
6844 bool textures_set
= false;
6845 const Program::SamplerIndices
& sampler_indices
=
6846 state_
.current_program
->sampler_indices();
6847 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6848 const Program::UniformInfo
* uniform_info
=
6849 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6850 DCHECK(uniform_info
);
6851 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6852 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6853 if (texture_unit_index
< state_
.texture_units
.size()) {
6854 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6855 TextureRef
* texture_ref
=
6856 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6857 GLenum textarget
= GetBindTargetForSamplerType(uniform_info
->type
);
6858 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
6859 textures_set
= true;
6860 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6863 texture_manager()->black_texture_id(uniform_info
->type
));
6865 LOCAL_RENDER_WARNING(
6866 std::string("there is no texture bound to the unit ") +
6867 base::IntToString(texture_unit_index
));
6869 LOCAL_RENDER_WARNING(
6870 std::string("texture bound to texture unit ") +
6871 base::IntToString(texture_unit_index
) +
6872 " is not renderable. It maybe non-power-of-2 and have"
6873 " incompatible texture filtering.");
6878 if (textarget
!= GL_TEXTURE_CUBE_MAP
) {
6879 Texture
* texture
= texture_ref
->texture();
6880 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6881 if (image
&& !texture
->IsAttachedToFramebuffer()) {
6882 ScopedGLErrorSuppressor
suppressor(
6883 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6884 textures_set
= true;
6885 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6886 image
->WillUseTexImage();
6891 // else: should this be an error?
6894 return !textures_set
;
6897 void GLES2DecoderImpl::RestoreStateForTextures() {
6898 DCHECK(state_
.current_program
.get());
6899 const Program::SamplerIndices
& sampler_indices
=
6900 state_
.current_program
->sampler_indices();
6901 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6902 const Program::UniformInfo
* uniform_info
=
6903 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6904 DCHECK(uniform_info
);
6905 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6906 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6907 if (texture_unit_index
< state_
.texture_units
.size()) {
6908 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6909 TextureRef
* texture_ref
=
6910 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6911 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
6912 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6913 // Get the texture_ref info that was previously bound here.
6914 texture_ref
= texture_unit
.bind_target
== GL_TEXTURE_2D
6915 ? texture_unit
.bound_texture_2d
.get()
6916 : texture_unit
.bound_texture_cube_map
.get();
6917 glBindTexture(texture_unit
.bind_target
,
6918 texture_ref
? texture_ref
->service_id() : 0);
6922 if (texture_unit
.bind_target
!= GL_TEXTURE_CUBE_MAP
) {
6923 Texture
* texture
= texture_ref
->texture();
6924 gfx::GLImage
* image
=
6925 texture
->GetLevelImage(texture_unit
.bind_target
, 0);
6926 if (image
&& !texture
->IsAttachedToFramebuffer()) {
6927 ScopedGLErrorSuppressor
suppressor(
6928 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
6929 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6930 image
->DidUseTexImage();
6937 // Set the active texture back to whatever the user had it as.
6938 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
6941 bool GLES2DecoderImpl::ClearUnclearedTextures() {
6942 // Only check if there are some uncleared textures.
6943 if (!texture_manager()->HaveUnsafeTextures()) {
6947 // 1: Check all textures we are about to render with.
6948 if (state_
.current_program
.get()) {
6949 const Program::SamplerIndices
& sampler_indices
=
6950 state_
.current_program
->sampler_indices();
6951 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6952 const Program::UniformInfo
* uniform_info
=
6953 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6954 DCHECK(uniform_info
);
6955 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6956 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6957 if (texture_unit_index
< state_
.texture_units
.size()) {
6958 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6959 TextureRef
* texture_ref
=
6960 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6961 if (texture_ref
&& !texture_ref
->texture()->SafeToRenderFrom()) {
6962 if (!texture_manager()->ClearRenderableLevels(this, texture_ref
)) {
6973 bool GLES2DecoderImpl::IsDrawValid(
6974 const char* function_name
, GLuint max_vertex_accessed
, bool instanced
,
6975 GLsizei primcount
) {
6976 DCHECK(instanced
|| primcount
== 1);
6978 // NOTE: We specifically do not check current_program->IsValid() because
6979 // it could never be invalid since glUseProgram would have failed. While
6980 // glLinkProgram could later mark the program as invalid the previous
6981 // valid program will still function if it is still the current program.
6982 if (!state_
.current_program
.get()) {
6983 // The program does not exist.
6984 // But GL says no ERROR.
6985 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
6989 if (CheckDrawingFeedbackLoops()) {
6991 GL_INVALID_OPERATION
, function_name
,
6992 "Source and destination textures of the draw are the same.");
6996 return state_
.vertex_attrib_manager
6997 ->ValidateBindings(function_name
,
6999 feature_info_
.get(),
7000 state_
.current_program
.get(),
7001 max_vertex_accessed
,
7006 bool GLES2DecoderImpl::SimulateAttrib0(
7007 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
) {
7011 if (feature_info_
->gl_version_info().BehavesLikeGLES())
7014 const VertexAttrib
* attrib
=
7015 state_
.vertex_attrib_manager
->GetVertexAttrib(0);
7016 // If it's enabled or it's not used then we don't need to do anything.
7017 bool attrib_0_used
=
7018 state_
.current_program
->GetAttribInfoByLocation(0) != NULL
;
7019 if (attrib
->enabled() && attrib_0_used
) {
7023 // Make a buffer with a single repeated vec4 value enough to
7024 // simulate the constant value that is supposed to be here.
7025 // This is required to emulate GLES2 on GL.
7026 GLuint num_vertices
= max_vertex_accessed
+ 1;
7027 uint32 size_needed
= 0;
7029 if (num_vertices
== 0 ||
7030 !SafeMultiplyUint32(num_vertices
, sizeof(Vec4f
), &size_needed
) ||
7031 size_needed
> 0x7FFFFFFFU
) {
7032 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
7036 LOCAL_PERFORMANCE_WARNING(
7037 "Attribute 0 is disabled. This has signficant performance penalty");
7039 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
7040 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
7042 bool new_buffer
= static_cast<GLsizei
>(size_needed
) > attrib_0_size_
;
7044 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
7045 GLenum error
= glGetError();
7046 if (error
!= GL_NO_ERROR
) {
7048 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
7053 const Vec4
& value
= state_
.attrib_values
[0];
7056 (!attrib_0_buffer_matches_value_
|| !value
.Equal(attrib_0_value_
)))){
7057 // TODO(zmo): This is not 100% correct because we might lose data when
7058 // casting to float type, but it is a corner case and once we migrate to
7059 // core profiles on desktop GL, it is no longer relevant.
7060 Vec4f
fvalue(value
);
7061 std::vector
<Vec4f
> temp(num_vertices
, fvalue
);
7062 glBufferSubData(GL_ARRAY_BUFFER
, 0, size_needed
, &temp
[0].v
[0]);
7063 attrib_0_buffer_matches_value_
= true;
7064 attrib_0_value_
= value
;
7065 attrib_0_size_
= size_needed
;
7068 glVertexAttribPointer(0, 4, GL_FLOAT
, GL_FALSE
, 0, NULL
);
7070 if (attrib
->divisor())
7071 glVertexAttribDivisorANGLE(0, 0);
7077 void GLES2DecoderImpl::RestoreStateForAttrib(
7078 GLuint attrib_index
, bool restore_array_binding
) {
7079 const VertexAttrib
* attrib
=
7080 state_
.vertex_attrib_manager
->GetVertexAttrib(attrib_index
);
7081 if (restore_array_binding
) {
7082 const void* ptr
= reinterpret_cast<const void*>(attrib
->offset());
7083 Buffer
* buffer
= attrib
->buffer();
7084 glBindBuffer(GL_ARRAY_BUFFER
, buffer
? buffer
->service_id() : 0);
7085 glVertexAttribPointer(
7086 attrib_index
, attrib
->size(), attrib
->type(), attrib
->normalized(),
7087 attrib
->gl_stride(), ptr
);
7089 if (attrib
->divisor())
7090 glVertexAttribDivisorANGLE(attrib_index
, attrib
->divisor());
7092 GL_ARRAY_BUFFER
, state_
.bound_array_buffer
.get() ?
7093 state_
.bound_array_buffer
->service_id() : 0);
7095 // Never touch vertex attribute 0's state (in particular, never
7096 // disable it) when running on desktop GL because it will never be
7098 if (attrib_index
!= 0 ||
7099 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
7100 if (attrib
->enabled()) {
7101 glEnableVertexAttribArray(attrib_index
);
7103 glDisableVertexAttribArray(attrib_index
);
7108 bool GLES2DecoderImpl::SimulateFixedAttribs(
7109 const char* function_name
,
7110 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
) {
7113 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
)
7116 if (!state_
.vertex_attrib_manager
->HaveFixedAttribs()) {
7120 LOCAL_PERFORMANCE_WARNING(
7121 "GL_FIXED attributes have a signficant performance penalty");
7123 // NOTE: we could be smart and try to check if a buffer is used
7124 // twice in 2 different attribs, find the overlapping parts and therefore
7125 // duplicate the minimum amount of data but this whole code path is not meant
7126 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
7127 // tests so we just add to the buffer attrib used.
7129 GLuint elements_needed
= 0;
7130 const VertexAttribManager::VertexAttribList
& enabled_attribs
=
7131 state_
.vertex_attrib_manager
->GetEnabledVertexAttribs();
7132 for (VertexAttribManager::VertexAttribList::const_iterator it
=
7133 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
7134 const VertexAttrib
* attrib
= *it
;
7135 const Program::VertexAttrib
* attrib_info
=
7136 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
7137 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
7138 max_vertex_accessed
);
7139 GLuint num_vertices
= max_accessed
+ 1;
7140 if (num_vertices
== 0) {
7142 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
7146 attrib
->CanAccess(max_accessed
) &&
7147 attrib
->type() == GL_FIXED
) {
7148 uint32 elements_used
= 0;
7149 if (!SafeMultiplyUint32(num_vertices
, attrib
->size(), &elements_used
) ||
7150 !SafeAddUint32(elements_needed
, elements_used
, &elements_needed
)) {
7152 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
7158 const uint32 kSizeOfFloat
= sizeof(float); // NOLINT
7159 uint32 size_needed
= 0;
7160 if (!SafeMultiplyUint32(elements_needed
, kSizeOfFloat
, &size_needed
) ||
7161 size_needed
> 0x7FFFFFFFU
) {
7163 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
7167 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
7169 glBindBuffer(GL_ARRAY_BUFFER
, fixed_attrib_buffer_id_
);
7170 if (static_cast<GLsizei
>(size_needed
) > fixed_attrib_buffer_size_
) {
7171 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
7172 GLenum error
= glGetError();
7173 if (error
!= GL_NO_ERROR
) {
7175 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
7180 // Copy the elements and convert to float
7181 GLintptr offset
= 0;
7182 for (VertexAttribManager::VertexAttribList::const_iterator it
=
7183 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
7184 const VertexAttrib
* attrib
= *it
;
7185 const Program::VertexAttrib
* attrib_info
=
7186 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
7187 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
7188 max_vertex_accessed
);
7189 GLuint num_vertices
= max_accessed
+ 1;
7190 if (num_vertices
== 0) {
7192 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
7196 attrib
->CanAccess(max_accessed
) &&
7197 attrib
->type() == GL_FIXED
) {
7198 int num_elements
= attrib
->size() * num_vertices
;
7199 const int src_size
= num_elements
* sizeof(int32
);
7200 const int dst_size
= num_elements
* sizeof(float);
7201 scoped_ptr
<float[]> data(new float[num_elements
]);
7202 const int32
* src
= reinterpret_cast<const int32
*>(
7203 attrib
->buffer()->GetRange(attrib
->offset(), src_size
));
7204 const int32
* end
= src
+ num_elements
;
7205 float* dst
= data
.get();
7206 while (src
!= end
) {
7207 *dst
++ = static_cast<float>(*src
++) / 65536.0f
;
7209 glBufferSubData(GL_ARRAY_BUFFER
, offset
, dst_size
, data
.get());
7210 glVertexAttribPointer(
7211 attrib
->index(), attrib
->size(), GL_FLOAT
, false, 0,
7212 reinterpret_cast<GLvoid
*>(offset
));
7220 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
7221 // There's no need to call glVertexAttribPointer because we shadow all the
7222 // settings and passing GL_FIXED to it will not work.
7225 state_
.bound_array_buffer
.get() ? state_
.bound_array_buffer
->service_id()
7229 error::Error
GLES2DecoderImpl::DoDrawArrays(
7230 const char* function_name
,
7235 GLsizei primcount
) {
7236 error::Error error
= WillAccessBoundFramebufferForDraw();
7237 if (error
!= error::kNoError
)
7239 if (!validators_
->draw_mode
.IsValid(mode
)) {
7240 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
7241 return error::kNoError
;
7244 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
7245 return error::kNoError
;
7247 if (primcount
< 0) {
7248 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
7249 return error::kNoError
;
7251 if (!CheckBoundFramebuffersValid(function_name
)) {
7252 return error::kNoError
;
7254 // We have to check this here because the prototype for glDrawArrays
7255 // is GLint not GLsizei.
7257 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "first < 0");
7258 return error::kNoError
;
7261 if (count
== 0 || primcount
== 0) {
7262 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
7263 return error::kNoError
;
7266 GLuint max_vertex_accessed
= first
+ count
- 1;
7267 if (IsDrawValid(function_name
, max_vertex_accessed
, instanced
, primcount
)) {
7268 if (!ClearUnclearedTextures()) {
7269 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
7270 return error::kNoError
;
7272 bool simulated_attrib_0
= false;
7273 if (!SimulateAttrib0(
7274 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
7275 return error::kNoError
;
7277 bool simulated_fixed_attribs
= false;
7278 if (SimulateFixedAttribs(
7279 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
7281 bool textures_set
= !PrepareTexturesForRender();
7283 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
7285 glDrawArrays(mode
, first
, count
);
7287 glDrawArraysInstancedANGLE(mode
, first
, count
, primcount
);
7290 RestoreStateForTextures();
7292 if (simulated_fixed_attribs
) {
7293 RestoreStateForSimulatedFixedAttribs();
7296 if (simulated_attrib_0
) {
7297 // We don't have to restore attrib 0 generic data at the end of this
7298 // function even if it is simulated. This is because we will simulate
7299 // it in each draw call, and attrib 0 generic data queries use cached
7300 // values instead of passing down to the underlying driver.
7301 RestoreStateForAttrib(0, false);
7304 return error::kNoError
;
7307 error::Error
GLES2DecoderImpl::HandleDrawArrays(uint32 immediate_data_size
,
7308 const void* cmd_data
) {
7309 // TODO(zmo): crbug.com/481184
7310 // On Desktop GL with versions lower than 4.3, we need to emulate
7311 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7312 const cmds::DrawArrays
& c
= *static_cast<const cmds::DrawArrays
*>(cmd_data
);
7313 return DoDrawArrays("glDrawArrays",
7315 static_cast<GLenum
>(c
.mode
),
7316 static_cast<GLint
>(c
.first
),
7317 static_cast<GLsizei
>(c
.count
),
7321 error::Error
GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
7322 uint32 immediate_data_size
,
7323 const void* cmd_data
) {
7324 const gles2::cmds::DrawArraysInstancedANGLE
& c
=
7325 *static_cast<const gles2::cmds::DrawArraysInstancedANGLE
*>(cmd_data
);
7326 if (!features().angle_instanced_arrays
) {
7328 GL_INVALID_OPERATION
,
7329 "glDrawArraysInstancedANGLE", "function not available");
7330 return error::kNoError
;
7332 return DoDrawArrays("glDrawArraysIntancedANGLE",
7334 static_cast<GLenum
>(c
.mode
),
7335 static_cast<GLint
>(c
.first
),
7336 static_cast<GLsizei
>(c
.count
),
7337 static_cast<GLsizei
>(c
.primcount
));
7340 error::Error
GLES2DecoderImpl::DoDrawElements(
7341 const char* function_name
,
7347 GLsizei primcount
) {
7348 error::Error error
= WillAccessBoundFramebufferForDraw();
7349 if (error
!= error::kNoError
)
7351 if (!state_
.vertex_attrib_manager
->element_array_buffer()) {
7353 GL_INVALID_OPERATION
, function_name
, "No element array buffer bound");
7354 return error::kNoError
;
7358 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
7359 return error::kNoError
;
7362 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "offset < 0");
7363 return error::kNoError
;
7365 if (!validators_
->draw_mode
.IsValid(mode
)) {
7366 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
7367 return error::kNoError
;
7369 if (!validators_
->index_type
.IsValid(type
)) {
7370 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, type
, "type");
7371 return error::kNoError
;
7373 if (primcount
< 0) {
7374 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
7375 return error::kNoError
;
7378 if (!CheckBoundFramebuffersValid(function_name
)) {
7379 return error::kNoError
;
7382 if (count
== 0 || primcount
== 0) {
7383 return error::kNoError
;
7386 GLuint max_vertex_accessed
;
7387 Buffer
* element_array_buffer
=
7388 state_
.vertex_attrib_manager
->element_array_buffer();
7390 if (!element_array_buffer
->GetMaxValueForRange(
7391 offset
, count
, type
, &max_vertex_accessed
)) {
7393 GL_INVALID_OPERATION
, function_name
, "range out of bounds for buffer");
7394 return error::kNoError
;
7397 if (IsDrawValid(function_name
, max_vertex_accessed
, instanced
, primcount
)) {
7398 if (!ClearUnclearedTextures()) {
7399 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
7400 return error::kNoError
;
7402 bool simulated_attrib_0
= false;
7403 if (!SimulateAttrib0(
7404 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
7405 return error::kNoError
;
7407 bool simulated_fixed_attribs
= false;
7408 if (SimulateFixedAttribs(
7409 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
7411 bool textures_set
= !PrepareTexturesForRender();
7413 // TODO(gman): Refactor to hide these details in BufferManager or
7414 // VertexAttribManager.
7415 const GLvoid
* indices
= reinterpret_cast<const GLvoid
*>(offset
);
7416 bool used_client_side_array
= false;
7417 if (element_array_buffer
->IsClientSideArray()) {
7418 used_client_side_array
= true;
7419 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
7420 indices
= element_array_buffer
->GetRange(offset
, 0);
7423 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
7425 glDrawElements(mode
, count
, type
, indices
);
7427 glDrawElementsInstancedANGLE(mode
, count
, type
, indices
, primcount
);
7430 if (used_client_side_array
) {
7431 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
7432 element_array_buffer
->service_id());
7436 RestoreStateForTextures();
7438 if (simulated_fixed_attribs
) {
7439 RestoreStateForSimulatedFixedAttribs();
7442 if (simulated_attrib_0
) {
7443 // We don't have to restore attrib 0 generic data at the end of this
7444 // function even if it is simulated. This is because we will simulate
7445 // it in each draw call, and attrib 0 generic data queries use cached
7446 // values instead of passing down to the underlying driver.
7447 RestoreStateForAttrib(0, false);
7450 return error::kNoError
;
7453 error::Error
GLES2DecoderImpl::HandleDrawElements(uint32 immediate_data_size
,
7454 const void* cmd_data
) {
7455 // TODO(zmo): crbug.com/481184
7456 // On Desktop GL with versions lower than 4.3, we need to emulate
7457 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7458 const gles2::cmds::DrawElements
& c
=
7459 *static_cast<const gles2::cmds::DrawElements
*>(cmd_data
);
7460 return DoDrawElements("glDrawElements",
7462 static_cast<GLenum
>(c
.mode
),
7463 static_cast<GLsizei
>(c
.count
),
7464 static_cast<GLenum
>(c
.type
),
7465 static_cast<int32
>(c
.index_offset
),
7469 error::Error
GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
7470 uint32 immediate_data_size
,
7471 const void* cmd_data
) {
7472 const gles2::cmds::DrawElementsInstancedANGLE
& c
=
7473 *static_cast<const gles2::cmds::DrawElementsInstancedANGLE
*>(cmd_data
);
7474 if (!features().angle_instanced_arrays
) {
7476 GL_INVALID_OPERATION
,
7477 "glDrawElementsInstancedANGLE", "function not available");
7478 return error::kNoError
;
7480 return DoDrawElements("glDrawElementsInstancedANGLE",
7482 static_cast<GLenum
>(c
.mode
),
7483 static_cast<GLsizei
>(c
.count
),
7484 static_cast<GLenum
>(c
.type
),
7485 static_cast<int32
>(c
.index_offset
),
7486 static_cast<GLsizei
>(c
.primcount
));
7489 GLuint
GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
7490 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
7491 GLuint max_vertex_accessed
= 0;
7492 Buffer
* buffer
= GetBuffer(buffer_id
);
7494 // TODO(gman): Should this be a GL error or a command buffer error?
7496 GL_INVALID_VALUE
, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
7498 if (!buffer
->GetMaxValueForRange(
7499 offset
, count
, type
, &max_vertex_accessed
)) {
7500 // TODO(gman): Should this be a GL error or a command buffer error?
7502 GL_INVALID_OPERATION
,
7503 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
7506 return max_vertex_accessed
;
7509 void GLES2DecoderImpl::DoShaderSource(
7510 GLuint client_id
, GLsizei count
, const char** data
, const GLint
* length
) {
7512 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
7513 if (length
&& length
[ii
] > 0)
7514 str
.append(data
[ii
], length
[ii
]);
7516 str
.append(data
[ii
]);
7518 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glShaderSource");
7522 // Note: We don't actually call glShaderSource here. We wait until
7523 // we actually compile the shader.
7524 shader
->set_source(str
);
7527 void GLES2DecoderImpl::DoTransformFeedbackVaryings(
7528 GLuint client_program_id
, GLsizei count
, const char* const* varyings
,
7529 GLenum buffer_mode
) {
7530 Program
* program
= GetProgramInfoNotShader(
7531 client_program_id
, "glTransformFeedbackVaryings");
7535 program
->TransformFeedbackVaryings(count
, varyings
, buffer_mode
);
7536 glTransformFeedbackVaryings(
7537 program
->service_id(), count
, varyings
, buffer_mode
);
7540 void GLES2DecoderImpl::DoCompileShader(GLuint client_id
) {
7541 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
7542 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glCompileShader");
7547 scoped_refptr
<ShaderTranslatorInterface
> translator
;
7548 if (use_shader_translator_
) {
7549 translator
= shader
->shader_type() == GL_VERTEX_SHADER
?
7550 vertex_translator_
: fragment_translator_
;
7553 const Shader::TranslatedShaderSourceType source_type
=
7554 feature_info_
->feature_flags().angle_translated_shader_source
?
7555 Shader::kANGLE
: Shader::kGL
;
7556 shader
->RequestCompile(translator
, source_type
);
7559 void GLES2DecoderImpl::DoGetShaderiv(
7560 GLuint shader_id
, GLenum pname
, GLint
* params
) {
7561 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderiv");
7566 // Compile now for statuses that require it.
7568 case GL_COMPILE_STATUS
:
7569 case GL_INFO_LOG_LENGTH
:
7570 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE
:
7571 shader
->DoCompile();
7579 case GL_SHADER_SOURCE_LENGTH
:
7580 *params
= shader
->source().size();
7584 case GL_COMPILE_STATUS
:
7585 *params
= compile_shader_always_succeeds_
? true : shader
->valid();
7587 case GL_INFO_LOG_LENGTH
:
7588 *params
= shader
->log_info().size();
7592 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE
:
7593 *params
= shader
->translated_source().size();
7600 glGetShaderiv(shader
->service_id(), pname
, params
);
7603 error::Error
GLES2DecoderImpl::HandleGetShaderSource(uint32 immediate_data_size
,
7604 const void* cmd_data
) {
7605 const gles2::cmds::GetShaderSource
& c
=
7606 *static_cast<const gles2::cmds::GetShaderSource
*>(cmd_data
);
7607 GLuint shader_id
= c
.shader
;
7608 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7609 Bucket
* bucket
= CreateBucket(bucket_id
);
7610 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderSource");
7611 if (!shader
|| shader
->source().empty()) {
7613 return error::kNoError
;
7615 bucket
->SetFromString(shader
->source().c_str());
7616 return error::kNoError
;
7619 error::Error
GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
7620 uint32 immediate_data_size
,
7621 const void* cmd_data
) {
7622 const gles2::cmds::GetTranslatedShaderSourceANGLE
& c
=
7623 *static_cast<const gles2::cmds::GetTranslatedShaderSourceANGLE
*>(
7625 GLuint shader_id
= c
.shader
;
7626 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7627 Bucket
* bucket
= CreateBucket(bucket_id
);
7628 Shader
* shader
= GetShaderInfoNotProgram(
7629 shader_id
, "glGetTranslatedShaderSourceANGLE");
7632 return error::kNoError
;
7635 // Make sure translator has been utilized in compile.
7636 shader
->DoCompile();
7638 bucket
->SetFromString(shader
->translated_source().c_str());
7639 return error::kNoError
;
7642 error::Error
GLES2DecoderImpl::HandleGetProgramInfoLog(
7643 uint32 immediate_data_size
,
7644 const void* cmd_data
) {
7645 const gles2::cmds::GetProgramInfoLog
& c
=
7646 *static_cast<const gles2::cmds::GetProgramInfoLog
*>(cmd_data
);
7647 GLuint program_id
= c
.program
;
7648 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7649 Bucket
* bucket
= CreateBucket(bucket_id
);
7650 Program
* program
= GetProgramInfoNotShader(
7651 program_id
, "glGetProgramInfoLog");
7652 if (!program
|| !program
->log_info()) {
7653 bucket
->SetFromString("");
7654 return error::kNoError
;
7656 bucket
->SetFromString(program
->log_info()->c_str());
7657 return error::kNoError
;
7660 error::Error
GLES2DecoderImpl::HandleGetShaderInfoLog(
7661 uint32 immediate_data_size
,
7662 const void* cmd_data
) {
7663 const gles2::cmds::GetShaderInfoLog
& c
=
7664 *static_cast<const gles2::cmds::GetShaderInfoLog
*>(cmd_data
);
7665 GLuint shader_id
= c
.shader
;
7666 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7667 Bucket
* bucket
= CreateBucket(bucket_id
);
7668 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderInfoLog");
7670 bucket
->SetFromString("");
7671 return error::kNoError
;
7674 // Shader must be compiled in order to get the info log.
7675 shader
->DoCompile();
7677 bucket
->SetFromString(shader
->log_info().c_str());
7678 return error::kNoError
;
7681 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap
) {
7682 return state_
.GetEnabled(cap
);
7685 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id
) {
7686 const Buffer
* buffer
= GetBuffer(client_id
);
7687 return buffer
&& buffer
->IsValid() && !buffer
->IsDeleted();
7690 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id
) {
7691 const Framebuffer
* framebuffer
=
7692 GetFramebuffer(client_id
);
7693 return framebuffer
&& framebuffer
->IsValid() && !framebuffer
->IsDeleted();
7696 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id
) {
7697 // IsProgram is true for programs as soon as they are created, until they are
7698 // deleted and no longer in use.
7699 const Program
* program
= GetProgram(client_id
);
7700 return program
!= NULL
&& !program
->IsDeleted();
7703 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id
) {
7704 const Renderbuffer
* renderbuffer
=
7705 GetRenderbuffer(client_id
);
7706 return renderbuffer
&& renderbuffer
->IsValid() && !renderbuffer
->IsDeleted();
7709 bool GLES2DecoderImpl::DoIsShader(GLuint client_id
) {
7710 // IsShader is true for shaders as soon as they are created, until they
7711 // are deleted and not attached to any programs.
7712 const Shader
* shader
= GetShader(client_id
);
7713 return shader
!= NULL
&& !shader
->IsDeleted();
7716 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id
) {
7717 const TextureRef
* texture_ref
= GetTexture(client_id
);
7718 return texture_ref
&& texture_ref
->texture()->IsValid();
7721 void GLES2DecoderImpl::DoAttachShader(
7722 GLuint program_client_id
, GLint shader_client_id
) {
7723 Program
* program
= GetProgramInfoNotShader(
7724 program_client_id
, "glAttachShader");
7728 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glAttachShader");
7732 if (!program
->AttachShader(shader_manager(), shader
)) {
7734 GL_INVALID_OPERATION
,
7736 "can not attach more than one shader of the same type.");
7739 glAttachShader(program
->service_id(), shader
->service_id());
7742 void GLES2DecoderImpl::DoDetachShader(
7743 GLuint program_client_id
, GLint shader_client_id
) {
7744 Program
* program
= GetProgramInfoNotShader(
7745 program_client_id
, "glDetachShader");
7749 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glDetachShader");
7753 if (!program
->DetachShader(shader_manager(), shader
)) {
7755 GL_INVALID_OPERATION
,
7756 "glDetachShader", "shader not attached to program");
7759 glDetachShader(program
->service_id(), shader
->service_id());
7762 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id
) {
7763 Program
* program
= GetProgramInfoNotShader(
7764 program_client_id
, "glValidateProgram");
7768 program
->Validate();
7771 void GLES2DecoderImpl::GetVertexAttribHelper(
7772 const VertexAttrib
* attrib
, GLenum pname
, GLint
* params
) {
7774 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
:
7776 Buffer
* buffer
= attrib
->buffer();
7777 if (buffer
&& !buffer
->IsDeleted()) {
7779 buffer_manager()->GetClientId(buffer
->service_id(), &client_id
);
7780 *params
= client_id
;
7784 case GL_VERTEX_ATTRIB_ARRAY_ENABLED
:
7785 *params
= attrib
->enabled();
7787 case GL_VERTEX_ATTRIB_ARRAY_SIZE
:
7788 *params
= attrib
->size();
7790 case GL_VERTEX_ATTRIB_ARRAY_STRIDE
:
7791 *params
= attrib
->gl_stride();
7793 case GL_VERTEX_ATTRIB_ARRAY_TYPE
:
7794 *params
= attrib
->type();
7796 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED
:
7797 *params
= attrib
->normalized();
7799 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR
:
7800 *params
= attrib
->divisor();
7802 case GL_VERTEX_ATTRIB_ARRAY_INTEGER
:
7803 *params
= attrib
->integer();
7811 void GLES2DecoderImpl::DoGetTexParameterfv(
7812 GLenum target
, GLenum pname
, GLfloat
* params
) {
7813 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
7814 glGetTexParameterfv(target
, pname
, params
);
7817 void GLES2DecoderImpl::DoGetTexParameteriv(
7818 GLenum target
, GLenum pname
, GLint
* params
) {
7819 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
7820 glGetTexParameteriv(target
, pname
, params
);
7823 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
7824 GLenum target
, GLenum pname
) {
7825 if (!workarounds().init_texture_max_anisotropy
)
7827 if (pname
!= GL_TEXTURE_MAX_ANISOTROPY_EXT
||
7828 !validators_
->texture_parameter
.IsValid(pname
)) {
7832 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
7836 GL_INVALID_OPERATION
,
7837 "glGetTexParamter{fi}v", "unknown texture for target");
7840 Texture
* texture
= texture_ref
->texture();
7841 texture
->InitTextureMaxAnisotropyIfNeeded(target
);
7844 template <typename T
>
7845 void GLES2DecoderImpl::DoGetVertexAttribImpl(
7846 GLuint index
, GLenum pname
, T
* params
) {
7847 VertexAttrib
* attrib
= state_
.vertex_attrib_manager
->GetVertexAttrib(index
);
7850 GL_INVALID_VALUE
, "glGetVertexAttrib", "index out of range");
7854 case GL_CURRENT_VERTEX_ATTRIB
:
7855 state_
.attrib_values
[index
].GetValues(params
);
7859 GetVertexAttribHelper(attrib
, pname
, &value
);
7860 *params
= static_cast<T
>(value
);
7866 void GLES2DecoderImpl::DoGetVertexAttribfv(
7867 GLuint index
, GLenum pname
, GLfloat
* params
) {
7868 DoGetVertexAttribImpl
<GLfloat
>(index
, pname
, params
);
7871 void GLES2DecoderImpl::DoGetVertexAttribiv(
7872 GLuint index
, GLenum pname
, GLint
* params
) {
7873 DoGetVertexAttribImpl
<GLint
>(index
, pname
, params
);
7876 void GLES2DecoderImpl::DoGetVertexAttribIiv(
7877 GLuint index
, GLenum pname
, GLint
* params
) {
7878 DoGetVertexAttribImpl
<GLint
>(index
, pname
, params
);
7881 void GLES2DecoderImpl::DoGetVertexAttribIuiv(
7882 GLuint index
, GLenum pname
, GLuint
* params
) {
7883 DoGetVertexAttribImpl
<GLuint
>(index
, pname
, params
);
7886 template <typename T
>
7887 bool GLES2DecoderImpl::SetVertexAttribValue(
7888 const char* function_name
, GLuint index
, const T
* value
) {
7889 if (index
>= state_
.attrib_values
.size()) {
7890 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "index out of range");
7893 state_
.attrib_values
[index
].SetValues(value
);
7897 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index
, GLfloat v0
) {
7898 GLfloat v
[4] = { v0
, 0.0f
, 0.0f
, 1.0f
, };
7899 if (SetVertexAttribValue("glVertexAttrib1f", index
, v
)) {
7900 glVertexAttrib1f(index
, v0
);
7904 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
) {
7905 GLfloat v
[4] = { v0
, v1
, 0.0f
, 1.0f
, };
7906 if (SetVertexAttribValue("glVertexAttrib2f", index
, v
)) {
7907 glVertexAttrib2f(index
, v0
, v1
);
7911 void GLES2DecoderImpl::DoVertexAttrib3f(
7912 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
) {
7913 GLfloat v
[4] = { v0
, v1
, v2
, 1.0f
, };
7914 if (SetVertexAttribValue("glVertexAttrib3f", index
, v
)) {
7915 glVertexAttrib3f(index
, v0
, v1
, v2
);
7919 void GLES2DecoderImpl::DoVertexAttrib4f(
7920 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
) {
7921 GLfloat v
[4] = { v0
, v1
, v2
, v3
, };
7922 if (SetVertexAttribValue("glVertexAttrib4f", index
, v
)) {
7923 glVertexAttrib4f(index
, v0
, v1
, v2
, v3
);
7927 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index
, const GLfloat
* v
) {
7928 GLfloat t
[4] = { v
[0], 0.0f
, 0.0f
, 1.0f
, };
7929 if (SetVertexAttribValue("glVertexAttrib1fv", index
, t
)) {
7930 glVertexAttrib1fv(index
, v
);
7934 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index
, const GLfloat
* v
) {
7935 GLfloat t
[4] = { v
[0], v
[1], 0.0f
, 1.0f
, };
7936 if (SetVertexAttribValue("glVertexAttrib2fv", index
, t
)) {
7937 glVertexAttrib2fv(index
, v
);
7941 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index
, const GLfloat
* v
) {
7942 GLfloat t
[4] = { v
[0], v
[1], v
[2], 1.0f
, };
7943 if (SetVertexAttribValue("glVertexAttrib3fv", index
, t
)) {
7944 glVertexAttrib3fv(index
, v
);
7948 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index
, const GLfloat
* v
) {
7949 if (SetVertexAttribValue("glVertexAttrib4fv", index
, v
)) {
7950 glVertexAttrib4fv(index
, v
);
7954 void GLES2DecoderImpl::DoVertexAttribI4i(
7955 GLuint index
, GLint v0
, GLint v1
, GLint v2
, GLint v3
) {
7956 GLint v
[4] = { v0
, v1
, v2
, v3
};
7957 if (SetVertexAttribValue("glVertexAttribI4i", index
, v
)) {
7958 glVertexAttribI4i(index
, v0
, v1
, v2
, v3
);
7962 void GLES2DecoderImpl::DoVertexAttribI4iv(GLuint index
, const GLint
* v
) {
7963 if (SetVertexAttribValue("glVertexAttribI4iv", index
, v
)) {
7964 glVertexAttribI4iv(index
, v
);
7968 void GLES2DecoderImpl::DoVertexAttribI4ui(
7969 GLuint index
, GLuint v0
, GLuint v1
, GLuint v2
, GLuint v3
) {
7970 GLuint v
[4] = { v0
, v1
, v2
, v3
};
7971 if (SetVertexAttribValue("glVertexAttribI4ui", index
, v
)) {
7972 glVertexAttribI4ui(index
, v0
, v1
, v2
, v3
);
7976 void GLES2DecoderImpl::DoVertexAttribI4uiv(GLuint index
, const GLuint
* v
) {
7977 if (SetVertexAttribValue("glVertexAttribI4uiv", index
, v
)) {
7978 glVertexAttribI4uiv(index
, v
);
7982 error::Error
GLES2DecoderImpl::HandleVertexAttribIPointer(
7983 uint32 immediate_data_size
,
7984 const void* cmd_data
) {
7985 if (!unsafe_es3_apis_enabled())
7986 return error::kUnknownCommand
;
7987 const gles2::cmds::VertexAttribIPointer
& c
=
7988 *static_cast<const gles2::cmds::VertexAttribIPointer
*>(cmd_data
);
7990 if (!state_
.bound_array_buffer
.get() ||
7991 state_
.bound_array_buffer
->IsDeleted()) {
7992 if (state_
.vertex_attrib_manager
.get() ==
7993 state_
.default_vertex_attrib_manager
.get()) {
7995 GL_INVALID_VALUE
, "glVertexAttribIPointer", "no array buffer bound");
7996 return error::kNoError
;
7997 } else if (c
.offset
!= 0) {
8000 "glVertexAttribIPointer", "client side arrays are not allowed");
8001 return error::kNoError
;
8005 GLuint indx
= c
.indx
;
8006 GLint size
= c
.size
;
8007 GLenum type
= c
.type
;
8008 GLsizei stride
= c
.stride
;
8009 GLsizei offset
= c
.offset
;
8010 const void* ptr
= reinterpret_cast<const void*>(offset
);
8011 if (!validators_
->vertex_attrib_i_type
.IsValid(type
)) {
8012 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribIPointer", type
, "type");
8013 return error::kNoError
;
8015 if (!validators_
->vertex_attrib_size
.IsValid(size
)) {
8017 GL_INVALID_VALUE
, "glVertexAttribIPointer", "size GL_INVALID_VALUE");
8018 return error::kNoError
;
8020 if (indx
>= group_
->max_vertex_attribs()) {
8022 GL_INVALID_VALUE
, "glVertexAttribIPointer", "index out of range");
8023 return error::kNoError
;
8027 GL_INVALID_VALUE
, "glVertexAttribIPointer", "stride < 0");
8028 return error::kNoError
;
8032 GL_INVALID_VALUE
, "glVertexAttribIPointer", "stride > 255");
8033 return error::kNoError
;
8037 GL_INVALID_VALUE
, "glVertexAttribIPointer", "offset < 0");
8038 return error::kNoError
;
8040 GLsizei component_size
=
8041 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type
);
8042 // component_size must be a power of two to use & as optimized modulo.
8043 DCHECK(GLES2Util::IsPOT(component_size
));
8044 if (offset
& (component_size
- 1)) {
8046 GL_INVALID_OPERATION
,
8047 "glVertexAttribIPointer", "offset not valid for type");
8048 return error::kNoError
;
8050 if (stride
& (component_size
- 1)) {
8052 GL_INVALID_OPERATION
,
8053 "glVertexAttribIPointer", "stride not valid for type");
8054 return error::kNoError
;
8056 state_
.vertex_attrib_manager
8057 ->SetAttribInfo(indx
,
8058 state_
.bound_array_buffer
.get(),
8063 stride
!= 0 ? stride
: component_size
* size
,
8066 glVertexAttribIPointer(indx
, size
, type
, stride
, ptr
);
8067 return error::kNoError
;
8070 error::Error
GLES2DecoderImpl::HandleVertexAttribPointer(
8071 uint32 immediate_data_size
,
8072 const void* cmd_data
) {
8073 const gles2::cmds::VertexAttribPointer
& c
=
8074 *static_cast<const gles2::cmds::VertexAttribPointer
*>(cmd_data
);
8076 if (!state_
.bound_array_buffer
.get() ||
8077 state_
.bound_array_buffer
->IsDeleted()) {
8078 if (state_
.vertex_attrib_manager
.get() ==
8079 state_
.default_vertex_attrib_manager
.get()) {
8081 GL_INVALID_VALUE
, "glVertexAttribPointer", "no array buffer bound");
8082 return error::kNoError
;
8083 } else if (c
.offset
!= 0) {
8086 "glVertexAttribPointer", "client side arrays are not allowed");
8087 return error::kNoError
;
8091 GLuint indx
= c
.indx
;
8092 GLint size
= c
.size
;
8093 GLenum type
= c
.type
;
8094 GLboolean normalized
= static_cast<GLboolean
>(c
.normalized
);
8095 GLsizei stride
= c
.stride
;
8096 GLsizei offset
= c
.offset
;
8097 const void* ptr
= reinterpret_cast<const void*>(offset
);
8098 if (!validators_
->vertex_attrib_type
.IsValid(type
)) {
8099 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type
, "type");
8100 return error::kNoError
;
8102 if (!validators_
->vertex_attrib_size
.IsValid(size
)) {
8104 GL_INVALID_VALUE
, "glVertexAttribPointer", "size GL_INVALID_VALUE");
8105 return error::kNoError
;
8107 if (indx
>= group_
->max_vertex_attribs()) {
8109 GL_INVALID_VALUE
, "glVertexAttribPointer", "index out of range");
8110 return error::kNoError
;
8114 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride < 0");
8115 return error::kNoError
;
8119 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride > 255");
8120 return error::kNoError
;
8124 GL_INVALID_VALUE
, "glVertexAttribPointer", "offset < 0");
8125 return error::kNoError
;
8127 GLsizei component_size
=
8128 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type
);
8129 // component_size must be a power of two to use & as optimized modulo.
8130 DCHECK(GLES2Util::IsPOT(component_size
));
8131 if (offset
& (component_size
- 1)) {
8133 GL_INVALID_OPERATION
,
8134 "glVertexAttribPointer", "offset not valid for type");
8135 return error::kNoError
;
8137 if (stride
& (component_size
- 1)) {
8139 GL_INVALID_OPERATION
,
8140 "glVertexAttribPointer", "stride not valid for type");
8141 return error::kNoError
;
8143 state_
.vertex_attrib_manager
8144 ->SetAttribInfo(indx
,
8145 state_
.bound_array_buffer
.get(),
8150 stride
!= 0 ? stride
: component_size
* size
,
8153 // We support GL_FIXED natively on EGL/GLES2 implementations
8154 if (type
!= GL_FIXED
|| feature_info_
->gl_version_info().is_es
) {
8155 glVertexAttribPointer(indx
, size
, type
, normalized
, stride
, ptr
);
8157 return error::kNoError
;
8160 void GLES2DecoderImpl::DoViewport(GLint x
, GLint y
, GLsizei width
,
8162 state_
.viewport_x
= x
;
8163 state_
.viewport_y
= y
;
8164 state_
.viewport_width
= std::min(width
, viewport_max_width_
);
8165 state_
.viewport_height
= std::min(height
, viewport_max_height_
);
8166 glViewport(x
, y
, width
, height
);
8169 error::Error
GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
8170 uint32 immediate_data_size
,
8171 const void* cmd_data
) {
8172 const gles2::cmds::VertexAttribDivisorANGLE
& c
=
8173 *static_cast<const gles2::cmds::VertexAttribDivisorANGLE
*>(cmd_data
);
8174 if (!features().angle_instanced_arrays
) {
8176 GL_INVALID_OPERATION
,
8177 "glVertexAttribDivisorANGLE", "function not available");
8178 return error::kNoError
;
8180 GLuint index
= c
.index
;
8181 GLuint divisor
= c
.divisor
;
8182 if (index
>= group_
->max_vertex_attribs()) {
8185 "glVertexAttribDivisorANGLE", "index out of range");
8186 return error::kNoError
;
8189 state_
.vertex_attrib_manager
->SetDivisor(
8192 glVertexAttribDivisorANGLE(index
, divisor
);
8193 return error::kNoError
;
8196 template <typename pixel_data_type
>
8197 static void WriteAlphaData(
8198 void* pixels
, uint32 row_count
, uint32 channel_count
,
8199 uint32 alpha_channel_index
, uint32 unpadded_row_size
,
8200 uint32 padded_row_size
, pixel_data_type alpha_value
) {
8201 DCHECK_GT(channel_count
, 0U);
8202 DCHECK_EQ(unpadded_row_size
% sizeof(pixel_data_type
), 0U);
8203 uint32 unpadded_row_size_in_elements
=
8204 unpadded_row_size
/ sizeof(pixel_data_type
);
8205 DCHECK_EQ(padded_row_size
% sizeof(pixel_data_type
), 0U);
8206 uint32 padded_row_size_in_elements
=
8207 padded_row_size
/ sizeof(pixel_data_type
);
8208 pixel_data_type
* dst
=
8209 static_cast<pixel_data_type
*>(pixels
) + alpha_channel_index
;
8210 for (uint32 yy
= 0; yy
< row_count
; ++yy
) {
8211 pixel_data_type
* end
= dst
+ unpadded_row_size_in_elements
;
8212 for (pixel_data_type
* d
= dst
; d
< end
; d
+= channel_count
) {
8215 dst
+= padded_row_size_in_elements
;
8219 void GLES2DecoderImpl::FinishReadPixels(
8220 const cmds::ReadPixels
& c
,
8222 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
8223 GLsizei width
= c
.width
;
8224 GLsizei height
= c
.height
;
8225 GLenum format
= c
.format
;
8226 GLenum type
= c
.type
;
8227 typedef cmds::ReadPixels::Result Result
;
8229 Result
* result
= NULL
;
8230 if (c
.result_shm_id
!= 0) {
8231 result
= GetSharedMemoryAs
<Result
*>(
8232 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
8235 glDeleteBuffersARB(1, &buffer
);
8240 GLES2Util::ComputeImageDataSizes(
8241 width
, height
, 1, format
, type
, state_
.pack_alignment
, &pixels_size
,
8243 void* pixels
= GetSharedMemoryAs
<void*>(
8244 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
8247 glDeleteBuffersARB(1, &buffer
);
8253 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
8255 if (features().map_buffer_range
) {
8256 data
= glMapBufferRange(
8257 GL_PIXEL_PACK_BUFFER_ARB
, 0, pixels_size
, GL_MAP_READ_BIT
);
8259 data
= glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB
, GL_READ_ONLY
);
8262 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glMapBuffer",
8263 "Unable to map memory for readback.");
8266 memcpy(pixels
, data
, pixels_size
);
8267 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
8268 // have to restore the state.
8269 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB
);
8270 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
8271 glDeleteBuffersARB(1, &buffer
);
8274 if (result
!= NULL
) {
8278 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
8279 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
8280 if ((channels_exist
& 0x0008) == 0 &&
8281 workarounds().clear_alpha_in_readpixels
) {
8282 // Set the alpha to 255 because some drivers are buggy in this regard.
8285 uint32 unpadded_row_size
;
8286 uint32 padded_row_size
;
8287 if (!GLES2Util::ComputeImageDataSizes(
8288 width
, 2, 1, format
, type
, state_
.pack_alignment
, &temp_size
,
8289 &unpadded_row_size
, &padded_row_size
)) {
8293 uint32 channel_count
= 0;
8294 uint32 alpha_channel
= 0;
8307 if (channel_count
> 0) {
8309 case GL_UNSIGNED_BYTE
:
8310 WriteAlphaData
<uint8
>(
8311 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
8312 padded_row_size
, 0xFF);
8315 WriteAlphaData
<float>(
8316 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
8317 padded_row_size
, 1.0f
);
8320 WriteAlphaData
<uint16
>(
8321 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
8322 padded_row_size
, 0x3C00);
8329 error::Error
GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size
,
8330 const void* cmd_data
) {
8331 const gles2::cmds::ReadPixels
& c
=
8332 *static_cast<const gles2::cmds::ReadPixels
*>(cmd_data
);
8333 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
8334 error::Error fbo_error
= WillAccessBoundFramebufferForRead();
8335 if (fbo_error
!= error::kNoError
)
8339 GLsizei width
= c
.width
;
8340 GLsizei height
= c
.height
;
8341 GLenum format
= c
.format
;
8342 GLenum type
= c
.type
;
8343 GLboolean async
= static_cast<GLboolean
>(c
.async
);
8344 if (width
< 0 || height
< 0) {
8345 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glReadPixels", "dimensions < 0");
8346 return error::kNoError
;
8348 typedef cmds::ReadPixels::Result Result
;
8350 if (!GLES2Util::ComputeImageDataSizes(
8351 width
, height
, 1, format
, type
, state_
.pack_alignment
, &pixels_size
,
8353 return error::kOutOfBounds
;
8355 void* pixels
= GetSharedMemoryAs
<void*>(
8356 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
8358 return error::kOutOfBounds
;
8360 Result
* result
= NULL
;
8361 if (c
.result_shm_id
!= 0) {
8362 result
= GetSharedMemoryAs
<Result
*>(
8363 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
8365 return error::kOutOfBounds
;
8369 if (!validators_
->read_pixel_format
.IsValid(format
)) {
8370 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format
, "format");
8371 return error::kNoError
;
8373 if (!validators_
->read_pixel_type
.IsValid(type
)) {
8374 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type
, "type");
8375 return error::kNoError
;
8377 if ((format
!= GL_RGBA
&& format
!= GL_BGRA_EXT
&& format
!= GL_RGB
&&
8378 format
!= GL_ALPHA
) || type
!= GL_UNSIGNED_BYTE
) {
8379 // format and type are acceptable enums but not guaranteed to be supported
8380 // for this framebuffer. Have to ask gl if they are valid.
8381 GLint preferred_format
= 0;
8382 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT
, &preferred_format
);
8383 GLint preferred_type
= 0;
8384 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE
, &preferred_type
);
8385 if (format
!= static_cast<GLenum
>(preferred_format
) ||
8386 type
!= static_cast<GLenum
>(preferred_type
)) {
8388 GL_INVALID_OPERATION
, "glReadPixels", "format and type incompatible "
8389 "with the current read framebuffer");
8390 return error::kNoError
;
8393 if (width
== 0 || height
== 0) {
8394 return error::kNoError
;
8397 // Get the size of the current fbo or backbuffer.
8398 gfx::Size max_size
= GetBoundReadFrameBufferSize();
8402 if (!SafeAddInt32(x
, width
, &max_x
) || !SafeAddInt32(y
, height
, &max_y
)) {
8404 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
8405 return error::kNoError
;
8408 if (!CheckBoundReadFramebufferColorAttachment("glReadPixels")) {
8409 return error::kNoError
;
8412 if (!CheckBoundFramebuffersValid("glReadPixels")) {
8413 return error::kNoError
;
8416 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
8418 ScopedResolvedFrameBufferBinder
binder(this, false, true);
8420 if (x
< 0 || y
< 0 || max_x
> max_size
.width() || max_y
> max_size
.height()) {
8421 // The user requested an out of range area. Get the results 1 line
8424 uint32 unpadded_row_size
;
8425 uint32 padded_row_size
;
8426 if (!GLES2Util::ComputeImageDataSizes(
8427 width
, 2, 1, format
, type
, state_
.pack_alignment
, &temp_size
,
8428 &unpadded_row_size
, &padded_row_size
)) {
8430 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
8431 return error::kNoError
;
8434 GLint dest_x_offset
= std::max(-x
, 0);
8435 uint32 dest_row_offset
;
8436 if (!GLES2Util::ComputeImageDataSizes(
8437 dest_x_offset
, 1, 1, format
, type
, state_
.pack_alignment
,
8438 &dest_row_offset
, NULL
, NULL
)) {
8440 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
8441 return error::kNoError
;
8444 // Copy each row into the larger dest rect.
8445 int8
* dst
= static_cast<int8
*>(pixels
);
8446 GLint read_x
= std::max(0, x
);
8447 GLint read_end_x
= std::max(0, std::min(max_size
.width(), max_x
));
8448 GLint read_width
= read_end_x
- read_x
;
8449 for (GLint yy
= 0; yy
< height
; ++yy
) {
8453 memset(dst
, 0, unpadded_row_size
);
8455 // If the row is in range, copy it.
8456 if (ry
>= 0 && ry
< max_size
.height() && read_width
> 0) {
8458 read_x
, ry
, read_width
, 1, format
, type
, dst
+ dest_row_offset
);
8460 dst
+= padded_row_size
;
8463 if (async
&& features().use_async_readpixels
) {
8465 glGenBuffersARB(1, &buffer
);
8466 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
8467 // For ANGLE client version 2, GL_STREAM_READ is not available.
8468 const GLenum usage_hint
= feature_info_
->gl_version_info().is_angle
?
8469 GL_STATIC_DRAW
: GL_STREAM_READ
;
8470 glBufferData(GL_PIXEL_PACK_BUFFER_ARB
, pixels_size
, NULL
, usage_hint
);
8471 GLenum error
= glGetError();
8472 if (error
== GL_NO_ERROR
) {
8473 glReadPixels(x
, y
, width
, height
, format
, type
, 0);
8474 pending_readpixel_fences_
.push(linked_ptr
<FenceCallback
>(
8475 new FenceCallback()));
8476 WaitForReadPixels(base::Bind(
8477 &GLES2DecoderImpl::FinishReadPixels
,
8478 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
8479 <GLES2DecoderImpl
>(this),
8481 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
8482 return error::kNoError
;
8484 // On error, unbind pack buffer and fall through to sync readpixels
8485 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
8486 glDeleteBuffersARB(1, &buffer
);
8489 glReadPixels(x
, y
, width
, height
, format
, type
, pixels
);
8491 GLenum error
= LOCAL_PEEK_GL_ERROR("glReadPixels");
8492 if (error
== GL_NO_ERROR
) {
8493 if (result
!= NULL
) {
8496 FinishReadPixels(c
, 0);
8499 return error::kNoError
;
8502 error::Error
GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size
,
8503 const void* cmd_data
) {
8504 const gles2::cmds::PixelStorei
& c
=
8505 *static_cast<const gles2::cmds::PixelStorei
*>(cmd_data
);
8506 GLenum pname
= c
.pname
;
8507 GLenum param
= c
.param
;
8508 if (!validators_
->pixel_store
.IsValid(pname
)) {
8509 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname
, "pname");
8510 return error::kNoError
;
8513 case GL_PACK_ALIGNMENT
:
8514 case GL_UNPACK_ALIGNMENT
:
8515 if (!validators_
->pixel_store_alignment
.IsValid(param
)) {
8517 GL_INVALID_VALUE
, "glPixelStorei", "param GL_INVALID_VALUE");
8518 return error::kNoError
;
8524 glPixelStorei(pname
, param
);
8526 case GL_PACK_ALIGNMENT
:
8527 state_
.pack_alignment
= param
;
8529 case GL_PACK_REVERSE_ROW_ORDER_ANGLE
:
8530 state_
.pack_reverse_row_order
= (param
!= 0);
8532 case GL_UNPACK_ALIGNMENT
:
8533 state_
.unpack_alignment
= param
;
8536 // Validation should have prevented us from getting here.
8540 return error::kNoError
;
8543 error::Error
GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
8544 uint32 immediate_data_size
,
8545 const void* cmd_data
) {
8546 const gles2::cmds::PostSubBufferCHROMIUM
& c
=
8547 *static_cast<const gles2::cmds::PostSubBufferCHROMIUM
*>(cmd_data
);
8548 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
8550 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
8552 if (!supports_post_sub_buffer_
) {
8554 GL_INVALID_OPERATION
,
8555 "glPostSubBufferCHROMIUM", "command not supported by surface");
8556 return error::kNoError
;
8559 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
8562 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
8563 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
8564 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
8565 is_offscreen
? offscreen_size_
: surface_
->GetSize());
8567 if (surface_
->PostSubBuffer(c
.x
, c
.y
, c
.width
, c
.height
) !=
8568 gfx::SwapResult::SWAP_FAILED
) {
8569 return error::kNoError
;
8571 LOG(ERROR
) << "Context lost because PostSubBuffer failed.";
8572 return error::kLostContext
;
8576 error::Error
GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
8577 uint32 immediate_data_size
,
8578 const void* cmd_data
) {
8579 const gles2::cmds::ScheduleOverlayPlaneCHROMIUM
& c
=
8580 *static_cast<const gles2::cmds::ScheduleOverlayPlaneCHROMIUM
*>(cmd_data
);
8581 TextureRef
* ref
= texture_manager()->GetTexture(c
.overlay_texture_id
);
8583 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
8584 "glScheduleOverlayPlaneCHROMIUM",
8586 return error::kNoError
;
8588 gfx::GLImage
* image
=
8589 ref
->texture()->GetLevelImage(ref
->texture()->target(), 0);
8591 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
8592 "glScheduleOverlayPlaneCHROMIUM",
8593 "unsupported texture format");
8594 return error::kNoError
;
8596 gfx::OverlayTransform transform
= GetGFXOverlayTransform(c
.plane_transform
);
8597 if (transform
== gfx::OVERLAY_TRANSFORM_INVALID
) {
8598 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM
,
8599 "glScheduleOverlayPlaneCHROMIUM",
8600 "invalid transform enum");
8601 return error::kNoError
;
8603 if (!surface_
->ScheduleOverlayPlane(
8607 gfx::Rect(c
.bounds_x
, c
.bounds_y
, c
.bounds_width
, c
.bounds_height
),
8608 gfx::RectF(c
.uv_x
, c
.uv_y
, c
.uv_width
, c
.uv_height
))) {
8609 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
8610 "glScheduleOverlayPlaneCHROMIUM",
8611 "failed to schedule overlay");
8613 return error::kNoError
;
8616 error::Error
GLES2DecoderImpl::GetAttribLocationHelper(
8617 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8618 const std::string
& name_str
) {
8619 if (!StringIsValidForGLES(name_str
.c_str())) {
8621 GL_INVALID_VALUE
, "glGetAttribLocation", "Invalid character");
8622 return error::kNoError
;
8624 Program
* program
= GetProgramInfoNotShader(
8625 client_id
, "glGetAttribLocation");
8627 return error::kNoError
;
8629 if (!program
->IsValid()) {
8631 GL_INVALID_OPERATION
, "glGetAttribLocation", "program not linked");
8632 return error::kNoError
;
8634 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8635 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8637 return error::kOutOfBounds
;
8639 // Require the client to init this incase the context is lost and we are no
8640 // longer executing commands.
8641 if (*location
!= -1) {
8642 return error::kGenericError
;
8644 *location
= program
->GetAttribLocation(name_str
);
8645 return error::kNoError
;
8648 error::Error
GLES2DecoderImpl::HandleGetAttribLocation(
8649 uint32 immediate_data_size
,
8650 const void* cmd_data
) {
8651 const gles2::cmds::GetAttribLocation
& c
=
8652 *static_cast<const gles2::cmds::GetAttribLocation
*>(cmd_data
);
8653 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8655 return error::kInvalidArguments
;
8657 std::string name_str
;
8658 if (!bucket
->GetAsString(&name_str
)) {
8659 return error::kInvalidArguments
;
8661 return GetAttribLocationHelper(
8662 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8665 error::Error
GLES2DecoderImpl::GetUniformLocationHelper(
8666 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8667 const std::string
& name_str
) {
8668 if (!StringIsValidForGLES(name_str
.c_str())) {
8670 GL_INVALID_VALUE
, "glGetUniformLocation", "Invalid character");
8671 return error::kNoError
;
8673 Program
* program
= GetProgramInfoNotShader(
8674 client_id
, "glGetUniformLocation");
8676 return error::kNoError
;
8678 if (!program
->IsValid()) {
8680 GL_INVALID_OPERATION
, "glGetUniformLocation", "program not linked");
8681 return error::kNoError
;
8683 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8684 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8686 return error::kOutOfBounds
;
8688 // Require the client to init this incase the context is lost an we are no
8689 // longer executing commands.
8690 if (*location
!= -1) {
8691 return error::kGenericError
;
8693 *location
= program
->GetUniformFakeLocation(name_str
);
8694 return error::kNoError
;
8697 error::Error
GLES2DecoderImpl::HandleGetUniformLocation(
8698 uint32 immediate_data_size
,
8699 const void* cmd_data
) {
8700 const gles2::cmds::GetUniformLocation
& c
=
8701 *static_cast<const gles2::cmds::GetUniformLocation
*>(cmd_data
);
8702 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8704 return error::kInvalidArguments
;
8706 std::string name_str
;
8707 if (!bucket
->GetAsString(&name_str
)) {
8708 return error::kInvalidArguments
;
8710 return GetUniformLocationHelper(
8711 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8714 error::Error
GLES2DecoderImpl::HandleGetUniformIndices(
8715 uint32 immediate_data_size
,
8716 const void* cmd_data
) {
8717 if (!unsafe_es3_apis_enabled())
8718 return error::kUnknownCommand
;
8719 const gles2::cmds::GetUniformIndices
& c
=
8720 *static_cast<const gles2::cmds::GetUniformIndices
*>(cmd_data
);
8721 Bucket
* bucket
= GetBucket(c
.names_bucket_id
);
8723 return error::kInvalidArguments
;
8726 std::vector
<char*> names
;
8727 std::vector
<GLint
> len
;
8728 if (!bucket
->GetAsStrings(&count
, &names
, &len
) || count
<= 0) {
8729 return error::kInvalidArguments
;
8731 typedef cmds::GetUniformIndices::Result Result
;
8732 Result
* result
= GetSharedMemoryAs
<Result
*>(
8733 c
.indices_shm_id
, c
.indices_shm_offset
,
8734 Result::ComputeSize(static_cast<size_t>(count
)));
8735 GLuint
* indices
= result
? result
->GetData() : NULL
;
8736 if (indices
== NULL
) {
8737 return error::kOutOfBounds
;
8739 // Check that the client initialized the result.
8740 if (result
->size
!= 0) {
8741 return error::kInvalidArguments
;
8743 Program
* program
= GetProgramInfoNotShader(c
.program
, "glGetUniformIndices");
8745 return error::kNoError
;
8747 GLuint service_id
= program
->service_id();
8748 GLint link_status
= GL_FALSE
;
8749 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
8750 if (link_status
!= GL_TRUE
) {
8751 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
8752 "glGetUniformIndices", "program not linked");
8753 return error::kNoError
;
8755 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetUniformIndices");
8756 glGetUniformIndices(service_id
, count
, &names
[0], indices
);
8757 GLenum error
= glGetError();
8758 if (error
== GL_NO_ERROR
) {
8759 result
->SetNumResults(count
);
8761 LOCAL_SET_GL_ERROR(error
, "GetUniformIndices", "");
8763 return error::kNoError
;
8766 error::Error
GLES2DecoderImpl::GetFragDataLocationHelper(
8767 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8768 const std::string
& name_str
) {
8769 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8770 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8772 return error::kOutOfBounds
;
8774 // Require the client to init this incase the context is lost and we are no
8775 // longer executing commands.
8776 if (*location
!= -1) {
8777 return error::kGenericError
;
8779 Program
* program
= GetProgramInfoNotShader(
8780 client_id
, "glGetFragDataLocation");
8782 return error::kNoError
;
8784 *location
= glGetFragDataLocation(program
->service_id(), name_str
.c_str());
8785 return error::kNoError
;
8788 error::Error
GLES2DecoderImpl::HandleGetFragDataLocation(
8789 uint32 immediate_data_size
,
8790 const void* cmd_data
) {
8791 if (!unsafe_es3_apis_enabled())
8792 return error::kUnknownCommand
;
8793 const gles2::cmds::GetFragDataLocation
& c
=
8794 *static_cast<const gles2::cmds::GetFragDataLocation
*>(cmd_data
);
8795 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8797 return error::kInvalidArguments
;
8799 std::string name_str
;
8800 if (!bucket
->GetAsString(&name_str
)) {
8801 return error::kInvalidArguments
;
8803 return GetFragDataLocationHelper(
8804 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8807 error::Error
GLES2DecoderImpl::HandleGetUniformBlockIndex(
8808 uint32 immediate_data_size
, const void* cmd_data
) {
8809 if (!unsafe_es3_apis_enabled())
8810 return error::kUnknownCommand
;
8811 const gles2::cmds::GetUniformBlockIndex
& c
=
8812 *static_cast<const gles2::cmds::GetUniformBlockIndex
*>(cmd_data
);
8813 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8815 return error::kInvalidArguments
;
8817 std::string name_str
;
8818 if (!bucket
->GetAsString(&name_str
)) {
8819 return error::kInvalidArguments
;
8821 GLuint
* index
= GetSharedMemoryAs
<GLuint
*>(
8822 c
.index_shm_id
, c
.index_shm_offset
, sizeof(GLuint
));
8824 return error::kOutOfBounds
;
8826 // Require the client to init this in case the context is lost and we are no
8827 // longer executing commands.
8828 if (*index
!= GL_INVALID_INDEX
) {
8829 return error::kGenericError
;
8831 Program
* program
= GetProgramInfoNotShader(
8832 c
.program
, "glGetUniformBlockIndex");
8834 return error::kNoError
;
8836 *index
= glGetUniformBlockIndex(program
->service_id(), name_str
.c_str());
8837 return error::kNoError
;
8840 error::Error
GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size
,
8841 const void* cmd_data
) {
8842 const gles2::cmds::GetString
& c
=
8843 *static_cast<const gles2::cmds::GetString
*>(cmd_data
);
8844 GLenum name
= static_cast<GLenum
>(c
.name
);
8845 if (!validators_
->string_type
.IsValid(name
)) {
8846 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name
, "name");
8847 return error::kNoError
;
8850 const char* str
= nullptr;
8851 std::string extensions
;
8854 if (unsafe_es3_apis_enabled())
8855 str
= "OpenGL ES 3.0 Chromium";
8857 str
= "OpenGL ES 2.0 Chromium";
8859 case GL_SHADING_LANGUAGE_VERSION
:
8860 if (unsafe_es3_apis_enabled())
8861 str
= "OpenGL ES GLSL ES 3.0 Chromium";
8863 str
= "OpenGL ES GLSL ES 1.0 Chromium";
8867 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
8868 // They are used by WEBGL_debug_renderer_info.
8869 if (!IsWebGLContext())
8872 str
= reinterpret_cast<const char*>(glGetString(name
));
8876 // For WebGL contexts, strip out the OES derivatives and
8877 // EXT frag depth extensions if they have not been enabled.
8878 if (IsWebGLContext()) {
8879 extensions
= feature_info_
->extensions();
8880 if (!derivatives_explicitly_enabled_
) {
8881 size_t offset
= extensions
.find(kOESDerivativeExtension
);
8882 if (std::string::npos
!= offset
) {
8883 extensions
.replace(offset
, arraysize(kOESDerivativeExtension
),
8887 if (!frag_depth_explicitly_enabled_
) {
8888 size_t offset
= extensions
.find(kEXTFragDepthExtension
);
8889 if (std::string::npos
!= offset
) {
8890 extensions
.replace(offset
, arraysize(kEXTFragDepthExtension
),
8894 if (!draw_buffers_explicitly_enabled_
) {
8895 size_t offset
= extensions
.find(kEXTDrawBuffersExtension
);
8896 if (std::string::npos
!= offset
) {
8897 extensions
.replace(offset
, arraysize(kEXTDrawBuffersExtension
),
8901 if (!shader_texture_lod_explicitly_enabled_
) {
8902 size_t offset
= extensions
.find(kEXTShaderTextureLodExtension
);
8903 if (std::string::npos
!= offset
) {
8904 extensions
.replace(offset
,
8905 arraysize(kEXTShaderTextureLodExtension
),
8910 extensions
= feature_info_
->extensions().c_str();
8912 if (supports_post_sub_buffer_
)
8913 extensions
+= " GL_CHROMIUM_post_sub_buffer";
8914 str
= extensions
.c_str();
8918 str
= reinterpret_cast<const char*>(glGetString(name
));
8921 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
8922 bucket
->SetFromString(str
);
8923 return error::kNoError
;
8926 error::Error
GLES2DecoderImpl::HandleBufferData(uint32 immediate_data_size
,
8927 const void* cmd_data
) {
8928 const gles2::cmds::BufferData
& c
=
8929 *static_cast<const gles2::cmds::BufferData
*>(cmd_data
);
8930 GLenum target
= static_cast<GLenum
>(c
.target
);
8931 GLsizeiptr size
= static_cast<GLsizeiptr
>(c
.size
);
8932 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
8933 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
8934 GLenum usage
= static_cast<GLenum
>(c
.usage
);
8935 const void* data
= NULL
;
8936 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
8937 data
= GetSharedMemoryAs
<const void*>(data_shm_id
, data_shm_offset
, size
);
8939 return error::kOutOfBounds
;
8942 buffer_manager()->ValidateAndDoBufferData(&state_
, target
, size
, data
, usage
);
8943 return error::kNoError
;
8946 void GLES2DecoderImpl::DoBufferSubData(
8947 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
) {
8948 // Just delegate it. Some validation is actually done before this.
8949 buffer_manager()->ValidateAndDoBufferSubData(
8950 &state_
, target
, offset
, size
, data
);
8953 bool GLES2DecoderImpl::ClearLevel(Texture
* texture
,
8962 uint32 channels
= GLES2Util::GetChannelsForFormat(format
);
8963 if (feature_info_
->feature_flags().angle_depth_texture
&&
8964 (channels
& GLES2Util::kDepth
) != 0) {
8965 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
8966 // on depth formats.
8968 glGenFramebuffersEXT(1, &fb
);
8969 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb
);
8971 bool have_stencil
= (channels
& GLES2Util::kStencil
) != 0;
8972 GLenum attachment
= have_stencil
? GL_DEPTH_STENCIL_ATTACHMENT
:
8973 GL_DEPTH_ATTACHMENT
;
8975 glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT
, attachment
, target
,
8976 texture
->service_id(), level
);
8977 // ANGLE promises a depth only attachment ok.
8978 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT
) !=
8979 GL_FRAMEBUFFER_COMPLETE
) {
8983 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
8984 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
8986 state_
.SetDeviceDepthMask(GL_TRUE
);
8987 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
8988 glScissor(xoffset
, yoffset
, width
, height
);
8989 glClear(GL_DEPTH_BUFFER_BIT
| (have_stencil
? GL_STENCIL_BUFFER_BIT
: 0));
8991 RestoreClearState();
8993 glDeleteFramebuffersEXT(1, &fb
);
8994 Framebuffer
* framebuffer
=
8995 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
8996 GLuint fb_service_id
=
8997 framebuffer
? framebuffer
->service_id() : GetBackbufferServiceId();
8998 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb_service_id
);
9002 static const uint32 kMaxZeroSize
= 1024 * 1024 * 4;
9005 uint32 padded_row_size
;
9006 if (!GLES2Util::ComputeImageDataSizes(
9007 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &size
,
9008 NULL
, &padded_row_size
)) {
9012 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size
);
9016 if (size
> kMaxZeroSize
) {
9017 if (kMaxZeroSize
< padded_row_size
) {
9018 // That'd be an awfully large texture.
9021 // We should never have a large total size with a zero row size.
9022 DCHECK_GT(padded_row_size
, 0U);
9023 tile_height
= kMaxZeroSize
/ padded_row_size
;
9024 if (!GLES2Util::ComputeImageDataSizes(
9025 width
, tile_height
, 1, format
, type
, state_
.unpack_alignment
, &size
,
9030 tile_height
= height
;
9033 // Assumes the size has already been checked.
9034 scoped_ptr
<char[]> zero(new char[size
]);
9035 memset(zero
.get(), 0, size
);
9036 glBindTexture(texture
->target(), texture
->service_id());
9039 while (y
< height
) {
9040 GLint h
= y
+ tile_height
> height
? height
- y
: tile_height
;
9041 glTexSubImage2D(target
, level
, xoffset
, yoffset
+ y
, width
, h
, format
, type
,
9045 TextureRef
* bound_texture
=
9046 texture_manager()->GetTextureInfoForTarget(&state_
, texture
->target());
9047 glBindTexture(texture
->target(),
9048 bound_texture
? bound_texture
->service_id() : 0);
9054 const int kS3TCBlockWidth
= 4;
9055 const int kS3TCBlockHeight
= 4;
9056 const int kS3TCDXT1BlockSize
= 8;
9057 const int kS3TCDXT3AndDXT5BlockSize
= 16;
9058 const int kEACAndETC2BlockSize
= 4;
9060 bool IsValidDXTSize(GLint level
, GLsizei size
) {
9061 return (size
== 1) ||
9062 (size
== 2) || !(size
% kS3TCBlockWidth
);
9065 bool IsValidPVRTCSize(GLint level
, GLsizei size
) {
9066 return GLES2Util::IsPOT(size
);
9069 } // anonymous namespace.
9071 bool GLES2DecoderImpl::GetCompressedTexSizeInBytes(
9072 const char* function_name
, GLsizei width
, GLsizei height
, GLsizei depth
,
9073 GLenum format
, GLsizei
* size_in_bytes
) {
9074 base::CheckedNumeric
<GLsizei
> bytes_required(0);
9077 case GL_ATC_RGB_AMD
:
9078 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
9079 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
9080 case GL_ETC1_RGB8_OES
:
9082 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
9084 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
9085 bytes_required
*= kS3TCDXT1BlockSize
;
9087 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
9088 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
9089 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
9090 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
9092 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
9094 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
9095 bytes_required
*= kS3TCDXT3AndDXT5BlockSize
;
9097 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
9098 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
9099 bytes_required
= std::max(width
, 8);
9100 bytes_required
*= std::max(height
, 8);
9101 bytes_required
*= 4;
9102 bytes_required
+= 7;
9103 bytes_required
/= 8;
9105 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
9106 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
:
9107 bytes_required
= std::max(width
, 16);
9108 bytes_required
*= std::max(height
, 8);
9109 bytes_required
*= 2;
9110 bytes_required
+= 7;
9111 bytes_required
/= 8;
9115 case GL_COMPRESSED_R11_EAC
:
9116 case GL_COMPRESSED_SIGNED_R11_EAC
:
9117 case GL_COMPRESSED_RGB8_ETC2
:
9118 case GL_COMPRESSED_SRGB8_ETC2
:
9119 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9120 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9122 (width
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9124 (height
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9125 bytes_required
*= 8;
9126 bytes_required
*= depth
;
9128 case GL_COMPRESSED_RG11_EAC
:
9129 case GL_COMPRESSED_SIGNED_RG11_EAC
:
9130 case GL_COMPRESSED_RGBA8_ETC2_EAC
:
9131 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
:
9133 (width
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9135 (height
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9136 bytes_required
*= 16;
9137 bytes_required
*= depth
;
9140 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, format
, "format");
9144 if (!bytes_required
.IsValid()) {
9145 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "invalid size");
9149 *size_in_bytes
= bytes_required
.ValueOrDefault(0);
9153 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
9154 const char* function_name
, GLsizei width
, GLsizei height
, GLsizei depth
,
9155 GLenum format
, GLsizei size
) {
9156 GLsizei bytes_required
= 0;
9157 if (!GetCompressedTexSizeInBytes(
9158 function_name
, width
, height
, depth
, format
, &bytes_required
)) {
9162 if (size
!= bytes_required
) {
9164 GL_INVALID_VALUE
, function_name
, "size is not correct for dimensions");
9171 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
9172 const char* function_name
, GLenum target
, GLint level
,
9173 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
) {
9175 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
9176 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
9177 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
9178 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
9179 DCHECK_EQ(1, depth
); // 2D formats.
9180 if (!IsValidDXTSize(level
, width
) || !IsValidDXTSize(level
, height
)) {
9182 GL_INVALID_OPERATION
, function_name
,
9183 "width or height invalid for level");
9187 case GL_ATC_RGB_AMD
:
9188 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
9189 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
9190 case GL_ETC1_RGB8_OES
:
9191 DCHECK_EQ(1, depth
); // 2D formats.
9192 if (width
<= 0 || height
<= 0) {
9194 GL_INVALID_OPERATION
, function_name
,
9195 "width or height invalid for level");
9199 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
9200 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
9201 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
9202 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
:
9203 DCHECK_EQ(1, depth
); // 2D formats.
9204 if (!IsValidPVRTCSize(level
, width
) ||
9205 !IsValidPVRTCSize(level
, height
)) {
9207 GL_INVALID_OPERATION
, function_name
,
9208 "width or height invalid for level");
9214 case GL_COMPRESSED_R11_EAC
:
9215 case GL_COMPRESSED_SIGNED_R11_EAC
:
9216 case GL_COMPRESSED_RG11_EAC
:
9217 case GL_COMPRESSED_SIGNED_RG11_EAC
:
9218 case GL_COMPRESSED_RGB8_ETC2
:
9219 case GL_COMPRESSED_SRGB8_ETC2
:
9220 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9221 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9222 case GL_COMPRESSED_RGBA8_ETC2_EAC
:
9223 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
:
9224 if (width
<= 0 || height
<= 0 || depth
<= 0) {
9226 GL_INVALID_OPERATION
, function_name
,
9227 "width, height, or depth invalid");
9230 if (target
== GL_TEXTURE_3D
) {
9232 GL_INVALID_OPERATION
, function_name
,
9233 "target invalid for format");
9242 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
9243 const char* function_name
,
9244 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
9245 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
,
9247 if (xoffset
< 0 || yoffset
< 0 || zoffset
< 0) {
9249 GL_INVALID_VALUE
, function_name
, "x/y/z offset < 0");
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 const int kBlockWidth
= 4;
9259 const int kBlockHeight
= 4;
9260 if ((xoffset
% kBlockWidth
) || (yoffset
% kBlockHeight
)) {
9262 GL_INVALID_OPERATION
, function_name
,
9263 "xoffset or yoffset not multiple of 4");
9266 GLsizei tex_width
= 0;
9267 GLsizei tex_height
= 0;
9268 if (!texture
->GetLevelSize(target
, level
,
9269 &tex_width
, &tex_height
, nullptr) ||
9270 width
- xoffset
> tex_width
||
9271 height
- yoffset
> tex_height
) {
9273 GL_INVALID_OPERATION
, function_name
, "dimensions out of range");
9276 return ValidateCompressedTexDimensions(
9277 function_name
, target
, level
, width
, height
, 1, format
);
9279 case GL_ATC_RGB_AMD
:
9280 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
9281 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
: {
9283 GL_INVALID_OPERATION
, function_name
,
9284 "not supported for ATC textures");
9287 case GL_ETC1_RGB8_OES
: {
9289 GL_INVALID_OPERATION
, function_name
,
9290 "not supported for ECT1_RGB8_OES textures");
9293 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
9294 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
9295 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
9296 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
: {
9297 if ((xoffset
!= 0) || (yoffset
!= 0)) {
9299 GL_INVALID_OPERATION
, function_name
,
9300 "xoffset and yoffset must be zero");
9303 GLsizei tex_width
= 0;
9304 GLsizei tex_height
= 0;
9305 if (!texture
->GetLevelSize(target
, level
,
9306 &tex_width
, &tex_height
, nullptr) ||
9307 width
!= tex_width
||
9308 height
!= tex_height
) {
9310 GL_INVALID_OPERATION
, function_name
,
9311 "dimensions must match existing texture level dimensions");
9314 return ValidateCompressedTexDimensions(
9315 function_name
, target
, level
, width
, height
, 1, format
);
9319 case GL_COMPRESSED_R11_EAC
:
9320 case GL_COMPRESSED_SIGNED_R11_EAC
:
9321 case GL_COMPRESSED_RG11_EAC
:
9322 case GL_COMPRESSED_SIGNED_RG11_EAC
:
9323 case GL_COMPRESSED_RGB8_ETC2
:
9324 case GL_COMPRESSED_SRGB8_ETC2
:
9325 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9326 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9327 case GL_COMPRESSED_RGBA8_ETC2_EAC
:
9328 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
:
9330 const int kBlockSize
= 4;
9331 GLsizei tex_width
, tex_height
;
9332 if (target
== GL_TEXTURE_3D
||
9333 !texture
->GetLevelSize(target
, level
,
9334 &tex_width
, &tex_height
, nullptr) ||
9335 (xoffset
% kBlockSize
) || (yoffset
% kBlockSize
) ||
9336 ((width
% kBlockSize
) && xoffset
+ width
!= tex_width
) ||
9337 ((height
% kBlockSize
) && yoffset
+ height
!= tex_height
)) {
9339 GL_INVALID_OPERATION
, function_name
,
9340 "dimensions must match existing texture level dimensions");
9350 error::Error
GLES2DecoderImpl::DoCompressedTexImage2D(
9353 GLenum internal_format
,
9359 if (!validators_
->texture_target
.IsValid(target
)) {
9360 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9361 "glCompressedTexImage2D", target
, "target");
9362 return error::kNoError
;
9364 if (!validators_
->compressed_texture_format
.IsValid(
9366 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9367 "glCompressedTexImage2D", internal_format
, "internal_format");
9368 return error::kNoError
;
9370 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
9374 "glCompressedTexImage2D", "dimensions out of range");
9375 return error::kNoError
;
9377 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9382 "glCompressedTexImage2D", "unknown texture target");
9383 return error::kNoError
;
9385 Texture
* texture
= texture_ref
->texture();
9386 if (texture
->IsImmutable()) {
9388 GL_INVALID_OPERATION
,
9389 "glCompressedTexImage2D", "texture is immutable");
9390 return error::kNoError
;
9393 if (!ValidateCompressedTexDimensions("glCompressedTexImage2D", target
, level
,
9394 width
, height
, 1, internal_format
) ||
9395 !ValidateCompressedTexFuncData("glCompressedTexImage2D", width
, height
,
9396 1, internal_format
, image_size
)) {
9397 return error::kNoError
;
9400 if (!EnsureGPUMemoryAvailable(image_size
)) {
9402 GL_OUT_OF_MEMORY
, "glCompressedTexImage2D", "out of memory");
9403 return error::kNoError
;
9406 if (texture
->IsAttachedToFramebuffer()) {
9407 framebuffer_state_
.clear_state_dirty
= true;
9410 scoped_ptr
<int8
[]> zero
;
9412 zero
.reset(new int8
[image_size
]);
9413 memset(zero
.get(), 0, image_size
);
9416 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
9417 glCompressedTexImage2D(
9418 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
9419 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
9420 if (error
== GL_NO_ERROR
) {
9421 texture_manager()->SetLevelInfo(texture_ref
, target
, level
, internal_format
,
9422 width
, height
, 1, border
, 0, 0,
9423 gfx::Rect(width
, height
));
9426 // This may be a slow command. Exit command processing to allow for
9427 // context preemption and GPU watchdog checks.
9428 ExitCommandProcessingEarly();
9429 return error::kNoError
;
9432 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2D(
9433 uint32 immediate_data_size
,
9434 const void* cmd_data
) {
9435 const gles2::cmds::CompressedTexImage2D
& c
=
9436 *static_cast<const gles2::cmds::CompressedTexImage2D
*>(cmd_data
);
9437 GLenum target
= static_cast<GLenum
>(c
.target
);
9438 GLint level
= static_cast<GLint
>(c
.level
);
9439 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9440 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9441 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9442 GLint border
= static_cast<GLint
>(c
.border
);
9443 GLsizei image_size
= static_cast<GLsizei
>(c
.imageSize
);
9444 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
9445 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
9446 const void* data
= NULL
;
9447 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
9448 data
= GetSharedMemoryAs
<const void*>(
9449 data_shm_id
, data_shm_offset
, image_size
);
9451 return error::kOutOfBounds
;
9454 return DoCompressedTexImage2D(
9455 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
9458 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
9459 uint32 immediate_data_size
,
9460 const void* cmd_data
) {
9461 const gles2::cmds::CompressedTexImage2DBucket
& c
=
9462 *static_cast<const gles2::cmds::CompressedTexImage2DBucket
*>(cmd_data
);
9463 GLenum target
= static_cast<GLenum
>(c
.target
);
9464 GLint level
= static_cast<GLint
>(c
.level
);
9465 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9466 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9467 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9468 GLint border
= static_cast<GLint
>(c
.border
);
9469 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9471 return error::kInvalidArguments
;
9473 uint32 data_size
= bucket
->size();
9474 GLsizei imageSize
= data_size
;
9475 const void* data
= bucket
->GetData(0, data_size
);
9477 return error::kInvalidArguments
;
9479 return DoCompressedTexImage2D(
9480 target
, level
, internal_format
, width
, height
, border
,
9484 error::Error
GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
9485 uint32 immediate_data_size
,
9486 const void* cmd_data
) {
9487 const gles2::cmds::CompressedTexSubImage2DBucket
& c
=
9488 *static_cast<const gles2::cmds::CompressedTexSubImage2DBucket
*>(cmd_data
);
9489 GLenum target
= static_cast<GLenum
>(c
.target
);
9490 GLint level
= static_cast<GLint
>(c
.level
);
9491 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
9492 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
9493 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9494 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9495 GLenum format
= static_cast<GLenum
>(c
.format
);
9496 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9498 return error::kInvalidArguments
;
9500 uint32 data_size
= bucket
->size();
9501 GLsizei imageSize
= data_size
;
9502 const void* data
= bucket
->GetData(0, data_size
);
9504 return error::kInvalidArguments
;
9506 if (!validators_
->texture_target
.IsValid(target
)) {
9508 GL_INVALID_ENUM
, "glCompressedTexSubImage2D", "target");
9509 return error::kNoError
;
9511 if (!validators_
->compressed_texture_format
.IsValid(format
)) {
9512 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9513 "glCompressedTexSubImage2D", format
, "format");
9514 return error::kNoError
;
9518 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "width < 0");
9519 return error::kNoError
;
9523 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "height < 0");
9524 return error::kNoError
;
9526 if (imageSize
< 0) {
9528 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "imageSize < 0");
9529 return error::kNoError
;
9531 DoCompressedTexSubImage2D(
9532 target
, level
, xoffset
, yoffset
, width
, height
, format
, imageSize
, data
);
9533 return error::kNoError
;
9536 error::Error
GLES2DecoderImpl::DoCompressedTexImage3D(
9539 GLenum internal_format
,
9546 if (!validators_
->texture_3_d_target
.IsValid(target
)) {
9547 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9548 "glCompressedTexImage3D", target
, "target");
9549 return error::kNoError
;
9551 if (!validators_
->compressed_texture_format
.IsValid(
9553 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9554 "glCompressedTexImage3D", internal_format
, "internal_format");
9555 return error::kNoError
;
9557 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, depth
) ||
9561 "glCompressedTexImage3D", "dimensions out of range");
9562 return error::kNoError
;
9564 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9569 "glCompressedTexImage3D", "unknown texture target");
9570 return error::kNoError
;
9572 Texture
* texture
= texture_ref
->texture();
9573 if (texture
->IsImmutable()) {
9575 GL_INVALID_OPERATION
,
9576 "glCompressedTexImage3D", "texture is immutable");
9577 return error::kNoError
;
9580 if (!ValidateCompressedTexDimensions("glCompressedTexImage3D", target
, level
,
9581 width
, height
, depth
, internal_format
) ||
9582 !ValidateCompressedTexFuncData("glCompressedTexImage3D", width
, height
,
9583 depth
, internal_format
, image_size
)) {
9584 return error::kNoError
;
9587 if (!EnsureGPUMemoryAvailable(image_size
)) {
9589 GL_OUT_OF_MEMORY
, "glCompressedTexImage3D", "out of memory");
9590 return error::kNoError
;
9593 if (texture
->IsAttachedToFramebuffer()) {
9594 framebuffer_state_
.clear_state_dirty
= true;
9597 scoped_ptr
<int8
[]> zero
;
9599 zero
.reset(new int8
[image_size
]);
9600 memset(zero
.get(), 0, image_size
);
9603 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage3D");
9604 glCompressedTexImage3D(target
, level
, internal_format
, width
, height
, depth
,
9605 border
, image_size
, data
);
9606 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedTexImage3D");
9607 if (error
== GL_NO_ERROR
) {
9608 texture_manager()->SetLevelInfo(texture_ref
, target
, level
, internal_format
,
9609 width
, height
, depth
, border
, 0, 0,
9610 gfx::Rect(width
, height
));
9613 // This may be a slow command. Exit command processing to allow for
9614 // context preemption and GPU watchdog checks.
9615 ExitCommandProcessingEarly();
9616 return error::kNoError
;
9619 error::Error
GLES2DecoderImpl::HandleCompressedTexImage3D(
9620 uint32 immediate_data_size
, const void* cmd_data
) {
9621 if (!unsafe_es3_apis_enabled())
9622 return error::kUnknownCommand
;
9624 const gles2::cmds::CompressedTexImage3D
& c
=
9625 *static_cast<const gles2::cmds::CompressedTexImage3D
*>(cmd_data
);
9626 GLenum target
= static_cast<GLenum
>(c
.target
);
9627 GLint level
= static_cast<GLint
>(c
.level
);
9628 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9629 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9630 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9631 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9632 GLint border
= static_cast<GLint
>(c
.border
);
9633 GLsizei image_size
= static_cast<GLsizei
>(c
.imageSize
);
9634 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
9635 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
9636 const void* data
= NULL
;
9637 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
9638 data
= GetSharedMemoryAs
<const void*>(
9639 data_shm_id
, data_shm_offset
, image_size
);
9641 return error::kOutOfBounds
;
9644 return DoCompressedTexImage3D(target
, level
, internal_format
, width
, height
,
9645 depth
, border
, image_size
, data
);
9648 error::Error
GLES2DecoderImpl::HandleCompressedTexImage3DBucket(
9649 uint32 immediate_data_size
, const void* cmd_data
) {
9650 if (!unsafe_es3_apis_enabled())
9651 return error::kUnknownCommand
;
9653 const gles2::cmds::CompressedTexImage3DBucket
& c
=
9654 *static_cast<const gles2::cmds::CompressedTexImage3DBucket
*>(cmd_data
);
9655 GLenum target
= static_cast<GLenum
>(c
.target
);
9656 GLint level
= static_cast<GLint
>(c
.level
);
9657 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9658 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9659 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9660 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9661 GLint border
= static_cast<GLint
>(c
.border
);
9662 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9664 return error::kInvalidArguments
;
9666 uint32 data_size
= bucket
->size();
9667 GLsizei imageSize
= data_size
;
9668 const void* data
= bucket
->GetData(0, data_size
);
9670 return error::kInvalidArguments
;
9672 return DoCompressedTexImage3D(target
, level
, internal_format
, width
, height
,
9673 depth
, border
, imageSize
, data
);
9676 void GLES2DecoderImpl::DoCompressedTexSubImage3D(
9677 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
9678 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
,
9679 GLsizei image_size
, const void* data
) {
9680 if (!validators_
->texture_3_d_target
.IsValid(target
)) {
9682 GL_INVALID_ENUM
, "glCompressedTexSubImage3D", "target");
9685 if (!validators_
->compressed_texture_format
.IsValid(format
)) {
9686 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9687 "glCompressedTexSubImage3D", format
, "format");
9690 if (width
< 0 || height
< 0 || depth
< 0) {
9692 GL_INVALID_VALUE
, "glCompressedTexSubImage3D", "size < 0");
9695 if (image_size
< 0) {
9697 GL_INVALID_VALUE
, "glCompressedTexSubImage3D", "imageSize < 0");
9700 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9703 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCompressedTexSubImage3D",
9704 "unknown texture for target");
9707 Texture
* texture
= texture_ref
->texture();
9708 GLenum type
= 0, internal_format
= 0;
9709 if (!texture
->GetLevelType(target
, level
, &type
, &internal_format
)) {
9710 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCompressedTexSubImage3D",
9711 "level does not exist");
9714 if (internal_format
!= format
) {
9715 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCompressedTexSubImage3D",
9716 "format does not match internal format");
9719 if (!texture
->ValidForTexture(target
, level
, xoffset
, yoffset
, zoffset
,
9720 width
, height
, depth
, type
)) {
9721 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCompressedTexSubImage3D",
9725 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage3D",
9726 width
, height
, depth
, format
,
9728 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage3D",
9729 target
, level
, xoffset
, yoffset
,
9730 zoffset
, width
, height
, depth
,
9735 // Note: There is no need to deal with texture cleared tracking here
9736 // because the validation above means you can only get here if the level
9737 // is already a matching compressed format and in that case
9738 // CompressedTexImage3D already cleared the texture.
9739 glCompressedTexSubImage3D(
9740 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
, format
,
9743 // This may be a slow command. Exit command processing to allow for
9744 // context preemption and GPU watchdog checks.
9745 ExitCommandProcessingEarly();
9748 error::Error
GLES2DecoderImpl::HandleCompressedTexSubImage3DBucket(
9749 uint32 immediate_data_size
, const void* cmd_data
) {
9750 if (!unsafe_es3_apis_enabled())
9751 return error::kUnknownCommand
;
9752 const gles2::cmds::CompressedTexSubImage3DBucket
& c
=
9753 *static_cast<const gles2::cmds::CompressedTexSubImage3DBucket
*>(cmd_data
);
9754 GLenum target
= static_cast<GLenum
>(c
.target
);
9755 GLint level
= static_cast<GLint
>(c
.level
);
9756 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
9757 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
9758 GLint zoffset
= static_cast<GLint
>(c
.zoffset
);
9759 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9760 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9761 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9762 GLenum format
= static_cast<GLenum
>(c
.format
);
9763 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9765 return error::kInvalidArguments
;
9767 uint32 data_size
= bucket
->size();
9768 GLsizei image_size
= data_size
;
9769 const void* data
= bucket
->GetData(0, data_size
);
9771 return error::kInvalidArguments
;
9773 DoCompressedTexSubImage3D(
9774 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
, format
,
9776 return error::kNoError
;
9779 error::Error
GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size
,
9780 const void* cmd_data
) {
9781 const gles2::cmds::TexImage2D
& c
=
9782 *static_cast<const gles2::cmds::TexImage2D
*>(cmd_data
);
9783 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
9784 "width", c
.width
, "height", c
.height
);
9785 // Set as failed for now, but if it successed, this will be set to not failed.
9786 texture_state_
.tex_image_failed
= true;
9787 GLenum target
= static_cast<GLenum
>(c
.target
);
9788 GLint level
= static_cast<GLint
>(c
.level
);
9789 // TODO(kloveless): Change TexImage2D command to use unsigned integer
9790 // for internalformat.
9791 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9792 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9793 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9794 GLint border
= static_cast<GLint
>(c
.border
);
9795 GLenum format
= static_cast<GLenum
>(c
.format
);
9796 GLenum type
= static_cast<GLenum
>(c
.type
);
9797 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
9798 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
9800 if (!GLES2Util::ComputeImageDataSizes(
9801 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
9803 return error::kOutOfBounds
;
9805 const void* pixels
= NULL
;
9806 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
9807 pixels
= GetSharedMemoryAs
<const void*>(
9808 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
9810 return error::kOutOfBounds
;
9814 // For testing only. Allows us to stress the ability to respond to OOM errors.
9815 if (workarounds().simulate_out_of_memory_on_large_textures
&&
9816 (width
* height
>= 4096 * 4096)) {
9819 "glTexImage2D", "synthetic out of memory");
9820 return error::kNoError
;
9823 TextureManager::DoTexImageArguments args
= {
9824 target
, level
, internal_format
, width
, height
, 1, border
, format
, type
,
9825 pixels
, pixels_size
, TextureManager::DoTexImageArguments::kTexImage2D
};
9826 texture_manager()->ValidateAndDoTexImage(
9827 &texture_state_
, &state_
, &framebuffer_state_
, "glTexImage2D", args
);
9829 // This may be a slow command. Exit command processing to allow for
9830 // context preemption and GPU watchdog checks.
9831 ExitCommandProcessingEarly();
9832 return error::kNoError
;
9835 error::Error
GLES2DecoderImpl::HandleTexImage3D(uint32 immediate_data_size
,
9836 const void* cmd_data
) {
9837 if (!unsafe_es3_apis_enabled())
9838 return error::kUnknownCommand
;
9840 const gles2::cmds::TexImage3D
& c
=
9841 *static_cast<const gles2::cmds::TexImage3D
*>(cmd_data
);
9842 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage3D",
9843 "widthXheight", c
.width
* c
.height
, "depth", c
.depth
);
9844 // Set as failed for now, but if it successed, this will be set to not failed.
9845 texture_state_
.tex_image_failed
= true;
9846 GLenum target
= static_cast<GLenum
>(c
.target
);
9847 GLint level
= static_cast<GLint
>(c
.level
);
9848 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9849 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9850 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9851 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9852 GLint border
= static_cast<GLint
>(c
.border
);
9853 GLenum format
= static_cast<GLenum
>(c
.format
);
9854 GLenum type
= static_cast<GLenum
>(c
.type
);
9855 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
9856 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
9858 if (!GLES2Util::ComputeImageDataSizes(
9859 width
, height
, depth
, format
, type
, state_
.unpack_alignment
, &pixels_size
,
9861 return error::kOutOfBounds
;
9863 const void* pixels
= NULL
;
9864 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
9865 pixels
= GetSharedMemoryAs
<const void*>(
9866 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
9868 return error::kOutOfBounds
;
9872 // For testing only. Allows us to stress the ability to respond to OOM errors.
9873 if (workarounds().simulate_out_of_memory_on_large_textures
&&
9874 (width
* height
* depth
>= 4096 * 4096)) {
9877 "glTexImage3D", "synthetic out of memory");
9878 return error::kNoError
;
9881 TextureManager::DoTexImageArguments args
= {
9882 target
, level
, internal_format
, width
, height
, depth
, border
, format
, type
,
9883 pixels
, pixels_size
, TextureManager::DoTexImageArguments::kTexImage3D
};
9884 texture_manager()->ValidateAndDoTexImage(
9885 &texture_state_
, &state_
, &framebuffer_state_
, "glTexImage3D", args
);
9887 // This may be a slow command. Exit command processing to allow for
9888 // context preemption and GPU watchdog checks.
9889 ExitCommandProcessingEarly();
9890 return error::kNoError
;
9893 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
9902 const void * data
) {
9903 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9907 GL_INVALID_OPERATION
,
9908 "glCompressedTexSubImage2D", "unknown texture for target");
9911 Texture
* texture
= texture_ref
->texture();
9913 GLenum internal_format
= 0;
9914 if (!texture
->GetLevelType(target
, level
, &type
, &internal_format
)) {
9916 GL_INVALID_OPERATION
,
9917 "glCompressedTexSubImage2D", "level does not exist.");
9920 if (internal_format
!= format
) {
9922 GL_INVALID_OPERATION
,
9923 "glCompressedTexSubImage2D", "format does not match internal format.");
9926 if (!texture
->ValidForTexture(target
, level
, xoffset
, yoffset
, 0, width
,
9929 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "bad dimensions.");
9933 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage2D",
9934 width
, height
, 1, format
, image_size
) ||
9935 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage2D",
9936 target
, level
, xoffset
, yoffset
, 0,
9937 width
, height
, 1, format
, texture
)) {
9942 // Note: There is no need to deal with texture cleared tracking here
9943 // because the validation above means you can only get here if the level
9944 // is already a matching compressed format and in that case
9945 // CompressedTexImage2D already cleared the texture.
9946 glCompressedTexSubImage2D(
9947 target
, level
, xoffset
, yoffset
, width
, height
, format
, image_size
, data
);
9949 // This may be a slow command. Exit command processing to allow for
9950 // context preemption and GPU watchdog checks.
9951 ExitCommandProcessingEarly();
9955 GLint start
, GLint range
, GLint sourceRange
,
9956 GLint
* out_start
, GLint
* out_range
) {
9963 GLint end
= start
+ range
;
9964 if (end
> sourceRange
) {
9965 range
-= end
- sourceRange
;
9971 void GLES2DecoderImpl::DoCopyTexImage2D(
9974 GLenum internal_format
,
9980 DCHECK(!ShouldDeferReads());
9981 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9985 GL_INVALID_OPERATION
,
9986 "glCopyTexImage2D", "unknown texture for target");
9989 Texture
* texture
= texture_ref
->texture();
9990 if (texture
->IsImmutable()) {
9992 GL_INVALID_OPERATION
, "glCopyTexImage2D", "texture is immutable");
9995 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
9998 GL_INVALID_VALUE
, "glCopyTexImage2D", "dimensions out of range");
10001 if (!texture_manager()->ValidateFormatAndTypeCombination(
10002 state_
.GetErrorState(), "glCopyTexImage2D", internal_format
,
10003 GL_UNSIGNED_BYTE
)) {
10007 // Check we have compatible formats.
10008 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
10009 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
10010 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(internal_format
);
10012 if ((channels_needed
& channels_exist
) != channels_needed
) {
10013 LOCAL_SET_GL_ERROR(
10014 GL_INVALID_OPERATION
, "glCopyTexImage2D", "incompatible format");
10018 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
10019 LOCAL_SET_GL_ERROR(
10020 GL_INVALID_OPERATION
,
10021 "glCopyTexImage2D", "can not be used with depth or stencil textures");
10025 uint32 estimated_size
= 0;
10026 if (!GLES2Util::ComputeImageDataSizes(
10027 width
, height
, 1, internal_format
, GL_UNSIGNED_BYTE
,
10028 state_
.unpack_alignment
, &estimated_size
, NULL
, NULL
)) {
10029 LOCAL_SET_GL_ERROR(
10030 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too large");
10034 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
10035 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "out of memory");
10039 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexImage2D")) {
10043 if (FormsTextureCopyingFeedbackLoop(texture_ref
, level
)) {
10044 LOCAL_SET_GL_ERROR(
10045 GL_INVALID_OPERATION
,
10046 "glCopyTexImage2D", "source and destination textures are the same");
10050 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
10054 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
10055 ScopedResolvedFrameBufferBinder
binder(this, false, true);
10056 gfx::Size size
= GetBoundReadFrameBufferSize();
10058 if (texture
->IsAttachedToFramebuffer()) {
10059 framebuffer_state_
.clear_state_dirty
= true;
10062 // Clip to size to source dimensions
10065 GLint copyWidth
= 0;
10066 GLint copyHeight
= 0;
10067 Clip(x
, width
, size
.width(), ©X
, ©Width
);
10068 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
10072 copyWidth
!= width
||
10073 copyHeight
!= height
) {
10074 // some part was clipped so clear the rect.
10075 uint32 pixels_size
= 0;
10076 if (!GLES2Util::ComputeImageDataSizes(
10077 width
, height
, 1, internal_format
, GL_UNSIGNED_BYTE
,
10078 state_
.unpack_alignment
, &pixels_size
, NULL
, NULL
)) {
10079 LOCAL_SET_GL_ERROR(
10080 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too big");
10083 scoped_ptr
<char[]> zero(new char[pixels_size
]);
10084 memset(zero
.get(), 0, pixels_size
);
10085 ScopedModifyPixels
modify(texture_ref
);
10086 glTexImage2D(target
, level
, internal_format
, width
, height
, border
,
10087 internal_format
, GL_UNSIGNED_BYTE
, zero
.get());
10088 if (copyHeight
> 0 && copyWidth
> 0) {
10089 GLint dx
= copyX
- x
;
10090 GLint dy
= copyY
- y
;
10093 glCopyTexSubImage2D(target
, level
,
10094 destX
, destY
, copyX
, copyY
,
10095 copyWidth
, copyHeight
);
10098 ScopedModifyPixels
modify(texture_ref
);
10099 glCopyTexImage2D(target
, level
, internal_format
,
10100 copyX
, copyY
, copyWidth
, copyHeight
, border
);
10102 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
10103 if (error
== GL_NO_ERROR
) {
10104 texture_manager()->SetLevelInfo(texture_ref
, target
, level
, internal_format
,
10105 width
, height
, 1, border
, internal_format
,
10106 GL_UNSIGNED_BYTE
, gfx::Rect(width
, height
));
10109 // This may be a slow command. Exit command processing to allow for
10110 // context preemption and GPU watchdog checks.
10111 ExitCommandProcessingEarly();
10114 void GLES2DecoderImpl::DoCopyTexSubImage2D(
10123 DCHECK(!ShouldDeferReads());
10124 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10126 if (!texture_ref
) {
10127 LOCAL_SET_GL_ERROR(
10128 GL_INVALID_OPERATION
,
10129 "glCopyTexSubImage2D", "unknown texture for target");
10132 Texture
* texture
= texture_ref
->texture();
10135 if (!texture
->GetLevelType(target
, level
, &type
, &format
) ||
10136 !texture
->ValidForTexture(
10137 target
, level
, xoffset
, yoffset
, 0, width
, height
, 1, type
)) {
10138 LOCAL_SET_GL_ERROR(
10139 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "bad dimensions.");
10142 if (async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
10143 LOCAL_SET_GL_ERROR(
10144 GL_INVALID_OPERATION
,
10145 "glCopyTexSubImage2D", "async upload pending for texture");
10149 // Check we have compatible formats.
10150 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
10151 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
10152 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(format
);
10154 if (!channels_needed
||
10155 (channels_needed
& channels_exist
) != channels_needed
) {
10156 LOCAL_SET_GL_ERROR(
10157 GL_INVALID_OPERATION
, "glCopyTexSubImage2D", "incompatible format");
10161 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
10162 LOCAL_SET_GL_ERROR(
10163 GL_INVALID_OPERATION
,
10164 "glCopySubImage2D", "can not be used with depth or stencil textures");
10168 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexSubImage2D")) {
10172 if (FormsTextureCopyingFeedbackLoop(texture_ref
, level
)) {
10173 LOCAL_SET_GL_ERROR(
10174 GL_INVALID_OPERATION
,
10175 "glCopyTexSubImage2D", "source and destination textures are the same");
10179 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
10183 ScopedResolvedFrameBufferBinder
binder(this, false, true);
10184 gfx::Size size
= GetBoundReadFrameBufferSize();
10187 GLint copyWidth
= 0;
10188 GLint copyHeight
= 0;
10189 Clip(x
, width
, size
.width(), ©X
, ©Width
);
10190 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
10192 if (xoffset
!= 0 || yoffset
!= 0 || width
!= size
.width() ||
10193 height
!= size
.height()) {
10194 gfx::Rect cleared_rect
;
10195 if (CombineAdjacentRects(texture
->GetLevelClearedRect(target
, level
),
10196 gfx::Rect(xoffset
, yoffset
, width
, height
),
10198 DCHECK_GE(cleared_rect
.size().GetArea(),
10199 texture
->GetLevelClearedRect(target
, level
).size().GetArea());
10200 texture_manager()->SetLevelClearedRect(texture_ref
, target
, level
,
10203 // Otherwise clear part of texture level that is not already cleared.
10204 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
,
10206 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D",
10207 "dimensions too big");
10212 // Write all pixels in below.
10213 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
10218 copyWidth
!= width
||
10219 copyHeight
!= height
) {
10220 // some part was clipped so clear the sub rect.
10221 uint32 pixels_size
= 0;
10222 if (!GLES2Util::ComputeImageDataSizes(
10223 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
10225 LOCAL_SET_GL_ERROR(
10226 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "dimensions too large");
10229 scoped_ptr
<char[]> zero(new char[pixels_size
]);
10230 memset(zero
.get(), 0, pixels_size
);
10231 ScopedModifyPixels
modify(texture_ref
);
10233 target
, level
, xoffset
, yoffset
, width
, height
,
10234 format
, type
, zero
.get());
10237 if (copyHeight
> 0 && copyWidth
> 0) {
10238 GLint dx
= copyX
- x
;
10239 GLint dy
= copyY
- y
;
10240 GLint destX
= xoffset
+ dx
;
10241 GLint destY
= yoffset
+ dy
;
10242 ScopedModifyPixels
modify(texture_ref
);
10243 glCopyTexSubImage2D(target
, level
,
10244 destX
, destY
, copyX
, copyY
,
10245 copyWidth
, copyHeight
);
10248 // This may be a slow command. Exit command processing to allow for
10249 // context preemption and GPU watchdog checks.
10250 ExitCommandProcessingEarly();
10253 bool GLES2DecoderImpl::ValidateTexSubImage2D(
10254 error::Error
* error
,
10255 const char* function_name
,
10264 const void * data
) {
10265 (*error
) = error::kNoError
;
10266 if (!validators_
->texture_target
.IsValid(target
)) {
10267 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
10271 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "width < 0");
10275 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "height < 0");
10278 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10280 if (!texture_ref
) {
10281 LOCAL_SET_GL_ERROR(
10282 GL_INVALID_OPERATION
,
10283 function_name
, "unknown texture for target");
10286 Texture
* texture
= texture_ref
->texture();
10287 GLenum current_type
= 0;
10288 GLenum internal_format
= 0;
10289 if (!texture
->GetLevelType(target
, level
, ¤t_type
, &internal_format
)) {
10290 LOCAL_SET_GL_ERROR(
10291 GL_INVALID_OPERATION
, function_name
, "level does not exist.");
10294 if (!texture_manager()->ValidateTextureParameters(state_
.GetErrorState(),
10295 function_name
, format
, type
, internal_format
, level
)) {
10298 if (type
!= current_type
) {
10299 LOCAL_SET_GL_ERROR(
10300 GL_INVALID_OPERATION
,
10301 function_name
, "type does not match type of texture.");
10304 if (async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
10305 LOCAL_SET_GL_ERROR(
10306 GL_INVALID_OPERATION
,
10307 function_name
, "async upload pending for texture");
10310 if (!texture
->ValidForTexture(
10311 target
, level
, xoffset
, yoffset
, 0, width
, height
, 1, type
)) {
10312 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "bad dimensions.");
10315 if ((GLES2Util::GetChannelsForFormat(format
) &
10316 (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
10317 LOCAL_SET_GL_ERROR(
10318 GL_INVALID_OPERATION
,
10319 function_name
, "can not supply data for depth or stencil textures");
10322 if (data
== NULL
) {
10323 (*error
) = error::kOutOfBounds
;
10329 error::Error
GLES2DecoderImpl::DoTexSubImage2D(
10338 const void * data
) {
10339 error::Error error
= error::kNoError
;
10340 if (!ValidateTexSubImage2D(&error
, "glTexSubImage2D", target
, level
,
10341 xoffset
, yoffset
, width
, height
, format
, type
, data
)) {
10344 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10346 Texture
* texture
= texture_ref
->texture();
10347 GLsizei tex_width
= 0;
10348 GLsizei tex_height
= 0;
10349 bool ok
= texture
->GetLevelSize(
10350 target
, level
, &tex_width
, &tex_height
, nullptr);
10352 if (xoffset
!= 0 || yoffset
!= 0 ||
10353 width
!= tex_width
|| height
!= tex_height
) {
10354 gfx::Rect cleared_rect
;
10355 if (CombineAdjacentRects(texture
->GetLevelClearedRect(target
, level
),
10356 gfx::Rect(xoffset
, yoffset
, width
, height
),
10358 DCHECK_GE(cleared_rect
.size().GetArea(),
10359 texture
->GetLevelClearedRect(target
, level
).size().GetArea());
10360 texture_manager()->SetLevelClearedRect(texture_ref
, target
, level
,
10363 // Otherwise clear part of texture level that is not already cleared.
10364 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
,
10366 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glTexSubImage2D",
10367 "dimensions too big");
10368 return error::kNoError
;
10371 ScopedTextureUploadTimer
timer(&texture_state_
);
10373 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
10374 return error::kNoError
;
10377 if (!texture_state_
.texsubimage_faster_than_teximage
&&
10378 !texture
->IsImmutable() &&
10379 !texture
->HasImages()) {
10380 ScopedTextureUploadTimer
timer(&texture_state_
);
10381 GLenum internal_format
;
10383 texture
->GetLevelType(target
, level
, &tex_type
, &internal_format
);
10384 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
10387 target
, level
, internal_format
, width
, height
, 0, format
, type
, data
);
10389 ScopedTextureUploadTimer
timer(&texture_state_
);
10391 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
10393 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
10395 // This may be a slow command. Exit command processing to allow for
10396 // context preemption and GPU watchdog checks.
10397 ExitCommandProcessingEarly();
10398 return error::kNoError
;
10401 error::Error
GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size
,
10402 const void* cmd_data
) {
10403 const gles2::cmds::TexSubImage2D
& c
=
10404 *static_cast<const gles2::cmds::TexSubImage2D
*>(cmd_data
);
10405 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
10406 "width", c
.width
, "height", c
.height
);
10407 GLboolean internal
= static_cast<GLboolean
>(c
.internal
);
10408 if (internal
== GL_TRUE
&& texture_state_
.tex_image_failed
)
10409 return error::kNoError
;
10411 GLenum target
= static_cast<GLenum
>(c
.target
);
10412 GLint level
= static_cast<GLint
>(c
.level
);
10413 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
10414 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
10415 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10416 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10417 GLenum format
= static_cast<GLenum
>(c
.format
);
10418 GLenum type
= static_cast<GLenum
>(c
.type
);
10420 if (!GLES2Util::ComputeImageDataSizes(
10421 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &data_size
,
10423 return error::kOutOfBounds
;
10425 const void* pixels
= GetSharedMemoryAs
<const void*>(
10426 c
.pixels_shm_id
, c
.pixels_shm_offset
, data_size
);
10427 return DoTexSubImage2D(
10428 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
);
10431 error::Error
GLES2DecoderImpl::DoTexSubImage3D(
10442 const void * data
) {
10443 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10445 if (!texture_ref
) {
10446 LOCAL_SET_GL_ERROR(
10447 GL_INVALID_ENUM
, "glTexSubImage3D", "invalid target");
10450 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexSubImage3D");
10451 ScopedTextureUploadTimer
timer(&texture_state_
);
10452 glTexSubImage3D(target
, level
, xoffset
, yoffset
, zoffset
, width
, height
,
10453 depth
, format
, type
, data
);
10454 GLenum error
= LOCAL_PEEK_GL_ERROR("glTexSubImage3D");
10455 if (error
== GL_NO_ERROR
) {
10456 // TODO(zmo): This is not 100% correct because only part of the level
10457 // image is cleared.
10458 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
10461 // This may be a slow command. Exit command processing to allow for
10462 // context preemption and GPU watchdog checks.
10463 ExitCommandProcessingEarly();
10464 return error::kNoError
;
10467 error::Error
GLES2DecoderImpl::HandleTexSubImage3D(uint32 immediate_data_size
,
10468 const void* cmd_data
) {
10469 if (!unsafe_es3_apis_enabled())
10470 return error::kUnknownCommand
;
10472 const gles2::cmds::TexSubImage3D
& c
=
10473 *static_cast<const gles2::cmds::TexSubImage3D
*>(cmd_data
);
10474 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage3D",
10475 "widthXheight", c
.width
* c
.height
, "depth", c
.depth
);
10476 GLboolean internal
= static_cast<GLboolean
>(c
.internal
);
10477 if (internal
== GL_TRUE
&& texture_state_
.tex_image_failed
)
10478 return error::kNoError
;
10480 GLenum target
= static_cast<GLenum
>(c
.target
);
10481 GLint level
= static_cast<GLint
>(c
.level
);
10482 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
10483 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
10484 GLint zoffset
= static_cast<GLint
>(c
.zoffset
);
10485 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10486 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10487 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
10488 GLenum format
= static_cast<GLenum
>(c
.format
);
10489 GLenum type
= static_cast<GLenum
>(c
.type
);
10491 if (!GLES2Util::ComputeImageDataSizes(
10492 width
, height
, depth
, format
, type
, state_
.unpack_alignment
, &data_size
,
10494 return error::kOutOfBounds
;
10496 const void* pixels
= GetSharedMemoryAs
<const void*>(
10497 c
.pixels_shm_id
, c
.pixels_shm_offset
, data_size
);
10498 return DoTexSubImage3D(target
, level
, xoffset
, yoffset
, zoffset
, width
,
10499 height
, depth
, format
, type
, pixels
);
10502 error::Error
GLES2DecoderImpl::HandleGetVertexAttribPointerv(
10503 uint32 immediate_data_size
,
10504 const void* cmd_data
) {
10505 const gles2::cmds::GetVertexAttribPointerv
& c
=
10506 *static_cast<const gles2::cmds::GetVertexAttribPointerv
*>(cmd_data
);
10507 GLuint index
= static_cast<GLuint
>(c
.index
);
10508 GLenum pname
= static_cast<GLenum
>(c
.pname
);
10509 typedef cmds::GetVertexAttribPointerv::Result Result
;
10510 Result
* result
= GetSharedMemoryAs
<Result
*>(
10511 c
.pointer_shm_id
, c
.pointer_shm_offset
, Result::ComputeSize(1));
10513 return error::kOutOfBounds
;
10515 // Check that the client initialized the result.
10516 if (result
->size
!= 0) {
10517 return error::kInvalidArguments
;
10519 if (!validators_
->vertex_pointer
.IsValid(pname
)) {
10520 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10521 "glGetVertexAttribPointerv", pname
, "pname");
10522 return error::kNoError
;
10524 if (index
>= group_
->max_vertex_attribs()) {
10525 LOCAL_SET_GL_ERROR(
10526 GL_INVALID_VALUE
, "glGetVertexAttribPointerv", "index out of range.");
10527 return error::kNoError
;
10529 result
->SetNumResults(1);
10530 *result
->GetData() =
10531 state_
.vertex_attrib_manager
->GetVertexAttrib(index
)->offset();
10532 return error::kNoError
;
10536 bool GLES2DecoderImpl::GetUniformSetup(GLuint program_id
,
10537 GLint fake_location
,
10540 error::Error
* error
,
10541 GLint
* real_location
,
10542 GLuint
* service_id
,
10543 SizedResult
<T
>** result_pointer
,
10544 GLenum
* result_type
,
10545 GLsizei
* result_size
) {
10547 DCHECK(service_id
);
10548 DCHECK(result_pointer
);
10549 DCHECK(result_type
);
10550 DCHECK(result_size
);
10551 DCHECK(real_location
);
10552 *error
= error::kNoError
;
10553 // Make sure we have enough room for the result on failure.
10554 SizedResult
<T
>* result
;
10555 result
= GetSharedMemoryAs
<SizedResult
<T
>*>(
10556 shm_id
, shm_offset
, SizedResult
<T
>::ComputeSize(0));
10558 *error
= error::kOutOfBounds
;
10561 *result_pointer
= result
;
10562 // Set the result size to 0 so the client does not have to check for success.
10563 result
->SetNumResults(0);
10564 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetUniform");
10568 if (!program
->IsValid()) {
10569 // Program was not linked successfully. (ie, glLinkProgram)
10570 LOCAL_SET_GL_ERROR(
10571 GL_INVALID_OPERATION
, "glGetUniform", "program not linked");
10574 *service_id
= program
->service_id();
10575 GLint array_index
= -1;
10576 const Program::UniformInfo
* uniform_info
=
10577 program
->GetUniformInfoByFakeLocation(
10578 fake_location
, real_location
, &array_index
);
10579 if (!uniform_info
) {
10580 // No such location.
10581 LOCAL_SET_GL_ERROR(
10582 GL_INVALID_OPERATION
, "glGetUniform", "unknown location");
10585 GLenum type
= uniform_info
->type
;
10586 uint32 num_elements
= GLES2Util::GetElementCountForUniformType(type
);
10587 if (num_elements
== 0) {
10588 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glGetUniform", "unknown type");
10591 result
= GetSharedMemoryAs
<SizedResult
<T
>*>(
10592 shm_id
, shm_offset
, SizedResult
<T
>::ComputeSize(num_elements
));
10594 *error
= error::kOutOfBounds
;
10597 result
->SetNumResults(num_elements
);
10598 *result_size
= num_elements
* sizeof(T
);
10599 *result_type
= type
;
10603 error::Error
GLES2DecoderImpl::HandleGetUniformiv(uint32 immediate_data_size
,
10604 const void* cmd_data
) {
10605 const gles2::cmds::GetUniformiv
& c
=
10606 *static_cast<const gles2::cmds::GetUniformiv
*>(cmd_data
);
10607 GLuint program
= c
.program
;
10608 GLint fake_location
= c
.location
;
10610 GLenum result_type
;
10611 GLsizei result_size
;
10612 GLint real_location
= -1;
10614 cmds::GetUniformiv::Result
* result
;
10615 if (GetUniformSetup
<GLint
>(program
, fake_location
, c
.params_shm_id
,
10616 c
.params_shm_offset
, &error
, &real_location
,
10617 &service_id
, &result
, &result_type
,
10620 service_id
, real_location
, result
->GetData());
10625 error::Error
GLES2DecoderImpl::HandleGetUniformuiv(uint32 immediate_data_size
,
10626 const void* cmd_data
) {
10627 if (!unsafe_es3_apis_enabled())
10628 return error::kUnknownCommand
;
10630 const gles2::cmds::GetUniformuiv
& c
=
10631 *static_cast<const gles2::cmds::GetUniformuiv
*>(cmd_data
);
10632 GLuint program
= c
.program
;
10633 GLint fake_location
= c
.location
;
10635 GLenum result_type
;
10636 GLsizei result_size
;
10637 GLint real_location
= -1;
10639 cmds::GetUniformuiv::Result
* result
;
10640 if (GetUniformSetup
<GLuint
>(program
, fake_location
, c
.params_shm_id
,
10641 c
.params_shm_offset
, &error
, &real_location
,
10642 &service_id
, &result
, &result_type
,
10645 service_id
, real_location
, result
->GetData());
10650 error::Error
GLES2DecoderImpl::HandleGetUniformfv(uint32 immediate_data_size
,
10651 const void* cmd_data
) {
10652 const gles2::cmds::GetUniformfv
& c
=
10653 *static_cast<const gles2::cmds::GetUniformfv
*>(cmd_data
);
10654 GLuint program
= c
.program
;
10655 GLint fake_location
= c
.location
;
10657 GLint real_location
= -1;
10659 cmds::GetUniformfv::Result
* result
;
10660 GLenum result_type
;
10661 GLsizei result_size
;
10662 if (GetUniformSetup
<GLfloat
>(program
, fake_location
, c
.params_shm_id
,
10663 c
.params_shm_offset
, &error
, &real_location
,
10664 &service_id
, &result
, &result_type
,
10666 if (result_type
== GL_BOOL
|| result_type
== GL_BOOL_VEC2
||
10667 result_type
== GL_BOOL_VEC3
|| result_type
== GL_BOOL_VEC4
) {
10668 GLsizei num_values
= result_size
/ sizeof(GLfloat
);
10669 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
10670 glGetUniformiv(service_id
, real_location
, temp
.get());
10671 GLfloat
* dst
= result
->GetData();
10672 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
10673 dst
[ii
] = (temp
[ii
] != 0);
10676 glGetUniformfv(service_id
, real_location
, result
->GetData());
10682 error::Error
GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
10683 uint32 immediate_data_size
,
10684 const void* cmd_data
) {
10685 const gles2::cmds::GetShaderPrecisionFormat
& c
=
10686 *static_cast<const gles2::cmds::GetShaderPrecisionFormat
*>(cmd_data
);
10687 GLenum shader_type
= static_cast<GLenum
>(c
.shadertype
);
10688 GLenum precision_type
= static_cast<GLenum
>(c
.precisiontype
);
10689 typedef cmds::GetShaderPrecisionFormat::Result Result
;
10690 Result
* result
= GetSharedMemoryAs
<Result
*>(
10691 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10693 return error::kOutOfBounds
;
10695 // Check that the client initialized the result.
10696 if (result
->success
!= 0) {
10697 return error::kInvalidArguments
;
10699 if (!validators_
->shader_type
.IsValid(shader_type
)) {
10700 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10701 "glGetShaderPrecisionFormat", shader_type
, "shader_type");
10702 return error::kNoError
;
10704 if (!validators_
->shader_precision
.IsValid(precision_type
)) {
10705 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10706 "glGetShaderPrecisionFormat", precision_type
, "precision_type");
10707 return error::kNoError
;
10710 result
->success
= 1; // true
10712 GLint range
[2] = { 0, 0 };
10713 GLint precision
= 0;
10714 GetShaderPrecisionFormatImpl(shader_type
, precision_type
, range
, &precision
);
10716 result
->min_range
= range
[0];
10717 result
->max_range
= range
[1];
10718 result
->precision
= precision
;
10720 return error::kNoError
;
10723 error::Error
GLES2DecoderImpl::HandleGetAttachedShaders(
10724 uint32 immediate_data_size
,
10725 const void* cmd_data
) {
10726 const gles2::cmds::GetAttachedShaders
& c
=
10727 *static_cast<const gles2::cmds::GetAttachedShaders
*>(cmd_data
);
10728 uint32 result_size
= c
.result_size
;
10729 GLuint program_id
= static_cast<GLuint
>(c
.program
);
10730 Program
* program
= GetProgramInfoNotShader(
10731 program_id
, "glGetAttachedShaders");
10733 return error::kNoError
;
10735 typedef cmds::GetAttachedShaders::Result Result
;
10736 uint32 max_count
= Result::ComputeMaxResults(result_size
);
10737 Result
* result
= GetSharedMemoryAs
<Result
*>(
10738 c
.result_shm_id
, c
.result_shm_offset
, Result::ComputeSize(max_count
));
10740 return error::kOutOfBounds
;
10742 // Check that the client initialized the result.
10743 if (result
->size
!= 0) {
10744 return error::kInvalidArguments
;
10747 glGetAttachedShaders(
10748 program
->service_id(), max_count
, &count
, result
->GetData());
10749 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
10750 if (!shader_manager()->GetClientId(result
->GetData()[ii
],
10751 &result
->GetData()[ii
])) {
10753 return error::kGenericError
;
10756 result
->SetNumResults(count
);
10757 return error::kNoError
;
10760 error::Error
GLES2DecoderImpl::HandleGetActiveUniform(
10761 uint32 immediate_data_size
,
10762 const void* cmd_data
) {
10763 const gles2::cmds::GetActiveUniform
& c
=
10764 *static_cast<const gles2::cmds::GetActiveUniform
*>(cmd_data
);
10765 GLuint program_id
= c
.program
;
10766 GLuint index
= c
.index
;
10767 uint32 name_bucket_id
= c
.name_bucket_id
;
10768 typedef cmds::GetActiveUniform::Result Result
;
10769 Result
* result
= GetSharedMemoryAs
<Result
*>(
10770 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10772 return error::kOutOfBounds
;
10774 // Check that the client initialized the result.
10775 if (result
->success
!= 0) {
10776 return error::kInvalidArguments
;
10778 Program
* program
= GetProgramInfoNotShader(
10779 program_id
, "glGetActiveUniform");
10781 return error::kNoError
;
10783 const Program::UniformInfo
* uniform_info
=
10784 program
->GetUniformInfo(index
);
10785 if (!uniform_info
) {
10786 LOCAL_SET_GL_ERROR(
10787 GL_INVALID_VALUE
, "glGetActiveUniform", "index out of range");
10788 return error::kNoError
;
10790 result
->success
= 1; // true.
10791 result
->size
= uniform_info
->size
;
10792 result
->type
= uniform_info
->type
;
10793 Bucket
* bucket
= CreateBucket(name_bucket_id
);
10794 bucket
->SetFromString(uniform_info
->name
.c_str());
10795 return error::kNoError
;
10798 error::Error
GLES2DecoderImpl::HandleGetActiveUniformBlockiv(
10799 uint32 immediate_data_size
, const void* cmd_data
) {
10800 if (!unsafe_es3_apis_enabled())
10801 return error::kUnknownCommand
;
10802 const gles2::cmds::GetActiveUniformBlockiv
& c
=
10803 *static_cast<const gles2::cmds::GetActiveUniformBlockiv
*>(cmd_data
);
10804 GLuint program_id
= c
.program
;
10805 GLuint index
= static_cast<GLuint
>(c
.index
);
10806 GLenum pname
= static_cast<GLenum
>(c
.pname
);
10807 Program
* program
= GetProgramInfoNotShader(
10808 program_id
, "glGetActiveUniformBlockiv");
10810 return error::kNoError
;
10812 GLuint service_id
= program
->service_id();
10813 GLint link_status
= GL_FALSE
;
10814 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
10815 if (link_status
!= GL_TRUE
) {
10816 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10817 "glGetActiveActiveUniformBlockiv", "program not linked");
10818 return error::kNoError
;
10820 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformBlockiv");
10821 GLsizei num_values
= 1;
10822 if (pname
== GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES
) {
10824 glGetActiveUniformBlockiv(
10825 service_id
, index
, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS
, &num
);
10826 GLenum error
= glGetError();
10827 if (error
!= GL_NO_ERROR
) {
10828 // Assume this will the same error if calling with pname.
10829 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformBlockiv", "");
10830 return error::kNoError
;
10832 num_values
= static_cast<GLsizei
>(num
);
10834 typedef cmds::GetActiveUniformBlockiv::Result Result
;
10835 Result
* result
= GetSharedMemoryAs
<Result
*>(
10836 c
.params_shm_id
, c
.params_shm_offset
, Result::ComputeSize(num_values
));
10837 GLint
* params
= result
? result
->GetData() : NULL
;
10838 if (params
== NULL
) {
10839 return error::kOutOfBounds
;
10841 // Check that the client initialized the result.
10842 if (result
->size
!= 0) {
10843 return error::kInvalidArguments
;
10845 glGetActiveUniformBlockiv(service_id
, index
, pname
, params
);
10846 GLenum error
= glGetError();
10847 if (error
== GL_NO_ERROR
) {
10848 result
->SetNumResults(num_values
);
10850 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformBlockiv", "");
10852 return error::kNoError
;
10855 error::Error
GLES2DecoderImpl::HandleGetActiveUniformBlockName(
10856 uint32 immediate_data_size
, const void* cmd_data
) {
10857 if (!unsafe_es3_apis_enabled())
10858 return error::kUnknownCommand
;
10859 const gles2::cmds::GetActiveUniformBlockName
& c
=
10860 *static_cast<const gles2::cmds::GetActiveUniformBlockName
*>(cmd_data
);
10861 GLuint program_id
= c
.program
;
10862 GLuint index
= c
.index
;
10863 uint32 name_bucket_id
= c
.name_bucket_id
;
10864 typedef cmds::GetActiveUniformBlockName::Result Result
;
10865 Result
* result
= GetSharedMemoryAs
<Result
*>(
10866 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10868 return error::kOutOfBounds
;
10870 // Check that the client initialized the result.
10871 if (*result
!= 0) {
10872 return error::kInvalidArguments
;
10874 Program
* program
= GetProgramInfoNotShader(
10875 program_id
, "glGetActiveUniformBlockName");
10877 return error::kNoError
;
10879 GLuint service_id
= program
->service_id();
10880 GLint link_status
= GL_FALSE
;
10881 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
10882 if (link_status
!= GL_TRUE
) {
10883 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10884 "glGetActiveActiveUniformBlockName", "program not linked");
10885 return error::kNoError
;
10887 GLint max_length
= 0;
10889 service_id
, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH
, &max_length
);
10890 // Increase one so &buffer[0] is always valid.
10891 GLsizei buf_size
= static_cast<GLsizei
>(max_length
) + 1;
10892 std::vector
<char> buffer(buf_size
);
10893 GLsizei length
= 0;
10894 glGetActiveUniformBlockName(
10895 service_id
, index
, buf_size
, &length
, &buffer
[0]);
10898 return error::kNoError
;
10901 Bucket
* bucket
= CreateBucket(name_bucket_id
);
10902 DCHECK_GT(buf_size
, length
);
10903 DCHECK_EQ(0, buffer
[length
]);
10904 bucket
->SetFromString(&buffer
[0]);
10905 return error::kNoError
;
10908 error::Error
GLES2DecoderImpl::HandleGetActiveUniformsiv(
10909 uint32 immediate_data_size
, const void* cmd_data
) {
10910 if (!unsafe_es3_apis_enabled())
10911 return error::kUnknownCommand
;
10912 const gles2::cmds::GetActiveUniformsiv
& c
=
10913 *static_cast<const gles2::cmds::GetActiveUniformsiv
*>(cmd_data
);
10914 GLuint program_id
= c
.program
;
10915 GLenum pname
= static_cast<GLenum
>(c
.pname
);
10916 Bucket
* bucket
= GetBucket(c
.indices_bucket_id
);
10918 return error::kInvalidArguments
;
10920 GLsizei count
= static_cast<GLsizei
>(bucket
->size() / sizeof(GLuint
));
10921 const GLuint
* indices
= bucket
->GetDataAs
<const GLuint
*>(0, bucket
->size());
10922 typedef cmds::GetActiveUniformsiv::Result Result
;
10923 Result
* result
= GetSharedMemoryAs
<Result
*>(
10924 c
.params_shm_id
, c
.params_shm_offset
, Result::ComputeSize(count
));
10925 GLint
* params
= result
? result
->GetData() : NULL
;
10926 if (params
== NULL
) {
10927 return error::kOutOfBounds
;
10929 // Check that the client initialized the result.
10930 if (result
->size
!= 0) {
10931 return error::kInvalidArguments
;
10933 Program
* program
= GetProgramInfoNotShader(
10934 program_id
, "glGetActiveUniformsiv");
10936 return error::kNoError
;
10938 GLuint service_id
= program
->service_id();
10939 GLint link_status
= GL_FALSE
;
10940 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
10941 if (link_status
!= GL_TRUE
) {
10942 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10943 "glGetActiveUniformsiv", "program not linked");
10944 return error::kNoError
;
10946 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformsiv");
10947 glGetActiveUniformsiv(service_id
, count
, indices
, pname
, params
);
10948 GLenum error
= glGetError();
10949 if (error
== GL_NO_ERROR
) {
10950 result
->SetNumResults(count
);
10952 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformsiv", "");
10954 return error::kNoError
;
10957 error::Error
GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size
,
10958 const void* cmd_data
) {
10959 const gles2::cmds::GetActiveAttrib
& c
=
10960 *static_cast<const gles2::cmds::GetActiveAttrib
*>(cmd_data
);
10961 GLuint program_id
= c
.program
;
10962 GLuint index
= c
.index
;
10963 uint32 name_bucket_id
= c
.name_bucket_id
;
10964 typedef cmds::GetActiveAttrib::Result Result
;
10965 Result
* result
= GetSharedMemoryAs
<Result
*>(
10966 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10968 return error::kOutOfBounds
;
10970 // Check that the client initialized the result.
10971 if (result
->success
!= 0) {
10972 return error::kInvalidArguments
;
10974 Program
* program
= GetProgramInfoNotShader(
10975 program_id
, "glGetActiveAttrib");
10977 return error::kNoError
;
10979 const Program::VertexAttrib
* attrib_info
=
10980 program
->GetAttribInfo(index
);
10981 if (!attrib_info
) {
10982 LOCAL_SET_GL_ERROR(
10983 GL_INVALID_VALUE
, "glGetActiveAttrib", "index out of range");
10984 return error::kNoError
;
10986 result
->success
= 1; // true.
10987 result
->size
= attrib_info
->size
;
10988 result
->type
= attrib_info
->type
;
10989 Bucket
* bucket
= CreateBucket(name_bucket_id
);
10990 bucket
->SetFromString(attrib_info
->name
.c_str());
10991 return error::kNoError
;
10994 error::Error
GLES2DecoderImpl::HandleShaderBinary(uint32 immediate_data_size
,
10995 const void* cmd_data
) {
10996 #if 1 // No binary shader support.
10997 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glShaderBinary", "not supported");
10998 return error::kNoError
;
11000 GLsizei n
= static_cast<GLsizei
>(c
.n
);
11002 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "n < 0");
11003 return error::kNoError
;
11005 GLsizei length
= static_cast<GLsizei
>(c
.length
);
11007 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "length < 0");
11008 return error::kNoError
;
11011 if (!SafeMultiplyUint32(n
, sizeof(GLuint
), &data_size
)) {
11012 return error::kOutOfBounds
;
11014 const GLuint
* shaders
= GetSharedMemoryAs
<const GLuint
*>(
11015 c
.shaders_shm_id
, c
.shaders_shm_offset
, data_size
);
11016 GLenum binaryformat
= static_cast<GLenum
>(c
.binaryformat
);
11017 const void* binary
= GetSharedMemoryAs
<const void*>(
11018 c
.binary_shm_id
, c
.binary_shm_offset
, length
);
11019 if (shaders
== NULL
|| binary
== NULL
) {
11020 return error::kOutOfBounds
;
11022 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
11023 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11024 Shader
* shader
= GetShader(shaders
[ii
]);
11026 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "unknown shader");
11027 return error::kNoError
;
11029 service_ids
[ii
] = shader
->service_id();
11031 // TODO(gman): call glShaderBinary
11032 return error::kNoError
;
11036 void GLES2DecoderImpl::DoSwapBuffers() {
11037 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
11039 int this_frame_number
= frame_number_
++;
11040 // TRACE_EVENT for gpu tests:
11041 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
11042 TRACE_EVENT_SCOPE_THREAD
,
11043 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
11044 "width", (is_offscreen
? offscreen_size_
.width() :
11045 surface_
->GetSize().width()));
11046 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
11047 "offscreen", is_offscreen
,
11048 "frame", this_frame_number
);
11050 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
11053 ScopedGPUTrace
scoped_gpu_trace(gpu_tracer_
.get(), kTraceDecoder
,
11054 "GLES2Decoder", "SwapBuffer");
11057 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
11060 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
11061 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
11062 is_offscreen
? offscreen_size_
: surface_
->GetSize());
11065 // If offscreen then don't actually SwapBuffers to the display. Just copy
11066 // the rendered frame to another frame buffer.
11067 if (is_offscreen
) {
11068 TRACE_EVENT2("gpu", "Offscreen",
11069 "width", offscreen_size_
.width(), "height", offscreen_size_
.height());
11070 if (offscreen_size_
!= offscreen_saved_color_texture_
->size()) {
11071 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
11072 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
11074 if (workarounds().needs_offscreen_buffer_workaround
) {
11075 offscreen_saved_frame_buffer_
->Create();
11079 // Allocate the offscreen saved color texture.
11080 DCHECK(offscreen_saved_color_format_
);
11081 offscreen_saved_color_texture_
->AllocateStorage(
11082 offscreen_size_
, offscreen_saved_color_format_
, false);
11084 offscreen_saved_frame_buffer_
->AttachRenderTexture(
11085 offscreen_saved_color_texture_
.get());
11086 if (offscreen_size_
.width() != 0 && offscreen_size_
.height() != 0) {
11087 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
11088 GL_FRAMEBUFFER_COMPLETE
) {
11089 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
11090 << "because offscreen saved FBO was incomplete.";
11091 MarkContextLost(error::kUnknown
);
11092 group_
->LoseContexts(error::kUnknown
);
11096 // Clear the offscreen color texture.
11097 // TODO(piman): Is this still necessary?
11099 ScopedFrameBufferBinder
binder(this,
11100 offscreen_saved_frame_buffer_
->id());
11101 glClearColor(0, 0, 0, 0);
11102 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
11103 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
11104 glClear(GL_COLOR_BUFFER_BIT
);
11105 RestoreClearState();
11109 UpdateParentTextureInfo();
11112 if (offscreen_size_
.width() == 0 || offscreen_size_
.height() == 0)
11114 ScopedGLErrorSuppressor
suppressor(
11115 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
11117 if (IsOffscreenBufferMultisampled()) {
11118 // For multisampled buffers, resolve the frame buffer.
11119 ScopedResolvedFrameBufferBinder
binder(this, true, false);
11121 ScopedFrameBufferBinder
binder(this,
11122 offscreen_target_frame_buffer_
->id());
11124 if (offscreen_target_buffer_preserved_
) {
11125 // Copy the target frame buffer to the saved offscreen texture.
11126 offscreen_saved_color_texture_
->Copy(
11127 offscreen_saved_color_texture_
->size(),
11128 offscreen_saved_color_format_
);
11130 // Flip the textures in the parent context via the texture manager.
11131 if (!!offscreen_saved_color_texture_info_
.get())
11132 offscreen_saved_color_texture_info_
->texture()->
11133 SetServiceId(offscreen_target_color_texture_
->id());
11135 offscreen_saved_color_texture_
.swap(offscreen_target_color_texture_
);
11136 offscreen_target_frame_buffer_
->AttachRenderTexture(
11137 offscreen_target_color_texture_
.get());
11140 // Ensure the side effects of the copy are visible to the parent
11141 // context. There is no need to do this for ANGLE because it uses a
11142 // single D3D device for all contexts.
11143 if (!feature_info_
->gl_version_info().is_angle
)
11147 if (surface_
->SwapBuffers() == gfx::SwapResult::SWAP_FAILED
) {
11148 LOG(ERROR
) << "Context lost because SwapBuffers failed.";
11149 if (!CheckResetStatus()) {
11150 MarkContextLost(error::kUnknown
);
11151 group_
->LoseContexts(error::kUnknown
);
11156 // This may be a slow command. Exit command processing to allow for
11157 // context preemption and GPU watchdog checks.
11158 ExitCommandProcessingEarly();
11161 void GLES2DecoderImpl::DoSwapInterval(int interval
) {
11162 context_
->SetSwapInterval(interval
);
11165 error::Error
GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
11166 uint32 immediate_data_size
,
11167 const void* cmd_data
) {
11168 const gles2::cmds::EnableFeatureCHROMIUM
& c
=
11169 *static_cast<const gles2::cmds::EnableFeatureCHROMIUM
*>(cmd_data
);
11170 Bucket
* bucket
= GetBucket(c
.bucket_id
);
11171 if (!bucket
|| bucket
->size() == 0) {
11172 return error::kInvalidArguments
;
11174 typedef cmds::EnableFeatureCHROMIUM::Result Result
;
11175 Result
* result
= GetSharedMemoryAs
<Result
*>(
11176 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
11178 return error::kOutOfBounds
;
11180 // Check that the client initialized the result.
11181 if (*result
!= 0) {
11182 return error::kInvalidArguments
;
11184 std::string feature_str
;
11185 if (!bucket
->GetAsString(&feature_str
)) {
11186 return error::kInvalidArguments
;
11189 // TODO(gman): make this some kind of table to function pointer thingy.
11190 if (feature_str
.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
11191 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
11192 } else if (feature_str
.compare("pepper3d_support_fixed_attribs") == 0) {
11193 buffer_manager()->set_allow_fixed_attribs(true);
11194 // TODO(gman): decide how to remove the need for this const_cast.
11195 // I could make validators_ non const but that seems bad as this is the only
11196 // place it is needed. I could make some special friend class of validators
11197 // just to allow this to set them. That seems silly. I could refactor this
11198 // code to use the extension mechanism or the initialization attributes to
11199 // turn this feature on. Given that the only real point of this is to make
11200 // the conformance tests pass and given that there is lots of real work that
11201 // needs to be done it seems like refactoring for one to one of those
11202 // methods is a very low priority.
11203 const_cast<Validators
*>(validators_
)->vertex_attrib_type
.AddValue(GL_FIXED
);
11205 return error::kNoError
;
11208 *result
= 1; // true.
11209 return error::kNoError
;
11212 error::Error
GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
11213 uint32 immediate_data_size
,
11214 const void* cmd_data
) {
11215 const gles2::cmds::GetRequestableExtensionsCHROMIUM
& c
=
11216 *static_cast<const gles2::cmds::GetRequestableExtensionsCHROMIUM
*>(
11218 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
11219 scoped_refptr
<FeatureInfo
> info(new FeatureInfo());
11220 info
->Initialize(disallowed_features_
);
11221 bucket
->SetFromString(info
->extensions().c_str());
11222 return error::kNoError
;
11225 error::Error
GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
11226 uint32 immediate_data_size
,
11227 const void* cmd_data
) {
11228 const gles2::cmds::RequestExtensionCHROMIUM
& c
=
11229 *static_cast<const gles2::cmds::RequestExtensionCHROMIUM
*>(cmd_data
);
11230 Bucket
* bucket
= GetBucket(c
.bucket_id
);
11231 if (!bucket
|| bucket
->size() == 0) {
11232 return error::kInvalidArguments
;
11234 std::string feature_str
;
11235 if (!bucket
->GetAsString(&feature_str
)) {
11236 return error::kInvalidArguments
;
11239 bool desire_standard_derivatives
= false;
11240 bool desire_frag_depth
= false;
11241 bool desire_draw_buffers
= false;
11242 bool desire_shader_texture_lod
= false;
11243 if (IsWebGLContext()) {
11244 desire_standard_derivatives
=
11245 feature_str
.find("GL_OES_standard_derivatives") != std::string::npos
;
11246 desire_frag_depth
=
11247 feature_str
.find("GL_EXT_frag_depth") != std::string::npos
;
11248 desire_draw_buffers
=
11249 feature_str
.find("GL_EXT_draw_buffers") != std::string::npos
;
11250 desire_shader_texture_lod
=
11251 feature_str
.find("GL_EXT_shader_texture_lod") != std::string::npos
;
11254 if (desire_standard_derivatives
!= derivatives_explicitly_enabled_
||
11255 desire_frag_depth
!= frag_depth_explicitly_enabled_
||
11256 desire_draw_buffers
!= draw_buffers_explicitly_enabled_
||
11257 desire_shader_texture_lod
!= shader_texture_lod_explicitly_enabled_
) {
11258 derivatives_explicitly_enabled_
|= desire_standard_derivatives
;
11259 frag_depth_explicitly_enabled_
|= desire_frag_depth
;
11260 draw_buffers_explicitly_enabled_
|= desire_draw_buffers
;
11261 shader_texture_lod_explicitly_enabled_
|= desire_shader_texture_lod
;
11262 InitializeShaderTranslator();
11265 UpdateCapabilities();
11267 return error::kNoError
;
11270 error::Error
GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
11271 uint32 immediate_data_size
,
11272 const void* cmd_data
) {
11273 const gles2::cmds::GetProgramInfoCHROMIUM
& c
=
11274 *static_cast<const gles2::cmds::GetProgramInfoCHROMIUM
*>(cmd_data
);
11275 GLuint program_id
= static_cast<GLuint
>(c
.program
);
11276 uint32 bucket_id
= c
.bucket_id
;
11277 Bucket
* bucket
= CreateBucket(bucket_id
);
11278 bucket
->SetSize(sizeof(ProgramInfoHeader
)); // in case we fail.
11279 Program
* program
= NULL
;
11280 program
= GetProgram(program_id
);
11281 if (!program
|| !program
->IsValid()) {
11282 return error::kNoError
;
11284 program
->GetProgramInfo(program_manager(), bucket
);
11285 return error::kNoError
;
11288 error::Error
GLES2DecoderImpl::HandleGetUniformBlocksCHROMIUM(
11289 uint32 immediate_data_size
, const void* cmd_data
) {
11290 if (!unsafe_es3_apis_enabled())
11291 return error::kUnknownCommand
;
11292 const gles2::cmds::GetUniformBlocksCHROMIUM
& c
=
11293 *static_cast<const gles2::cmds::GetUniformBlocksCHROMIUM
*>(cmd_data
);
11294 GLuint program_id
= static_cast<GLuint
>(c
.program
);
11295 uint32 bucket_id
= c
.bucket_id
;
11296 Bucket
* bucket
= CreateBucket(bucket_id
);
11297 bucket
->SetSize(sizeof(UniformBlocksHeader
)); // in case we fail.
11298 Program
* program
= NULL
;
11299 program
= GetProgram(program_id
);
11300 if (!program
|| !program
->IsValid()) {
11301 return error::kNoError
;
11303 program
->GetUniformBlocks(bucket
);
11304 return error::kNoError
;
11307 error::Error
GLES2DecoderImpl::HandleGetUniformsES3CHROMIUM(
11308 uint32 immediate_data_size
, const void* cmd_data
) {
11309 if (!unsafe_es3_apis_enabled())
11310 return error::kUnknownCommand
;
11311 const gles2::cmds::GetUniformsES3CHROMIUM
& c
=
11312 *static_cast<const gles2::cmds::GetUniformsES3CHROMIUM
*>(cmd_data
);
11313 GLuint program_id
= static_cast<GLuint
>(c
.program
);
11314 uint32 bucket_id
= c
.bucket_id
;
11315 Bucket
* bucket
= CreateBucket(bucket_id
);
11316 bucket
->SetSize(sizeof(UniformsES3Header
)); // in case we fail.
11317 Program
* program
= NULL
;
11318 program
= GetProgram(program_id
);
11319 if (!program
|| !program
->IsValid()) {
11320 return error::kNoError
;
11322 program
->GetUniformsES3(bucket
);
11323 return error::kNoError
;
11326 error::Error
GLES2DecoderImpl::HandleGetTransformFeedbackVarying(
11327 uint32 immediate_data_size
,
11328 const void* cmd_data
) {
11329 if (!unsafe_es3_apis_enabled())
11330 return error::kUnknownCommand
;
11331 const gles2::cmds::GetTransformFeedbackVarying
& c
=
11332 *static_cast<const gles2::cmds::GetTransformFeedbackVarying
*>(cmd_data
);
11333 GLuint program_id
= c
.program
;
11334 GLuint index
= c
.index
;
11335 uint32 name_bucket_id
= c
.name_bucket_id
;
11336 typedef cmds::GetTransformFeedbackVarying::Result Result
;
11337 Result
* result
= GetSharedMemoryAs
<Result
*>(
11338 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
11340 return error::kOutOfBounds
;
11342 // Check that the client initialized the result.
11343 if (result
->success
!= 0) {
11344 return error::kInvalidArguments
;
11346 Program
* program
= GetProgramInfoNotShader(
11347 program_id
, "glGetTransformFeedbackVarying");
11349 return error::kNoError
;
11351 GLuint service_id
= program
->service_id();
11352 GLint link_status
= GL_FALSE
;
11353 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
11354 if (link_status
!= GL_TRUE
) {
11355 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11356 "glGetTransformFeedbackVarying", "program not linked");
11357 return error::kNoError
;
11359 GLint max_length
= 0;
11361 service_id
, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH
, &max_length
);
11362 max_length
= std::max(1, max_length
);
11363 std::vector
<char> buffer(max_length
);
11364 GLsizei length
= 0;
11367 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetTransformFeedbackVarying");
11368 glGetTransformFeedbackVarying(
11369 service_id
, index
, max_length
, &length
, &size
, &type
, &buffer
[0]);
11370 GLenum error
= glGetError();
11371 if (error
!= GL_NO_ERROR
) {
11372 LOCAL_SET_GL_ERROR(error
, "glGetTransformFeedbackVarying", "");
11373 return error::kNoError
;
11375 result
->success
= 1; // true.
11376 result
->size
= static_cast<int32_t>(size
);
11377 result
->type
= static_cast<uint32_t>(type
);
11378 Bucket
* bucket
= CreateBucket(name_bucket_id
);
11379 DCHECK(length
>= 0 && length
< max_length
);
11380 buffer
[length
] = '\0'; // Just to be safe.
11381 bucket
->SetFromString(&buffer
[0]);
11382 return error::kNoError
;
11385 error::Error
GLES2DecoderImpl::HandleGetTransformFeedbackVaryingsCHROMIUM(
11386 uint32 immediate_data_size
, const void* cmd_data
) {
11387 if (!unsafe_es3_apis_enabled())
11388 return error::kUnknownCommand
;
11389 const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM
& c
=
11390 *static_cast<const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM
*>(
11392 GLuint program_id
= static_cast<GLuint
>(c
.program
);
11393 uint32 bucket_id
= c
.bucket_id
;
11394 Bucket
* bucket
= CreateBucket(bucket_id
);
11395 bucket
->SetSize(sizeof(TransformFeedbackVaryingsHeader
)); // in case we fail.
11396 Program
* program
= NULL
;
11397 program
= GetProgram(program_id
);
11398 if (!program
|| !program
->IsValid()) {
11399 return error::kNoError
;
11401 program
->GetTransformFeedbackVaryings(bucket
);
11402 return error::kNoError
;
11405 error::ContextLostReason
GLES2DecoderImpl::GetContextLostReason() {
11406 return context_lost_reason_
;
11409 error::ContextLostReason
GLES2DecoderImpl::GetContextLostReasonFromResetStatus(
11410 GLenum reset_status
) const {
11411 switch (reset_status
) {
11413 // TODO(kbr): improve the precision of the error code in this case.
11414 // Consider delegating to context for error code if MakeCurrent fails.
11415 return error::kUnknown
;
11416 case GL_GUILTY_CONTEXT_RESET_ARB
:
11417 return error::kGuilty
;
11418 case GL_INNOCENT_CONTEXT_RESET_ARB
:
11419 return error::kInnocent
;
11420 case GL_UNKNOWN_CONTEXT_RESET_ARB
:
11421 return error::kUnknown
;
11425 return error::kUnknown
;
11428 bool GLES2DecoderImpl::WasContextLost() const {
11429 return context_was_lost_
;
11432 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() const {
11433 return WasContextLost() && reset_by_robustness_extension_
;
11436 void GLES2DecoderImpl::MarkContextLost(error::ContextLostReason reason
) {
11437 // Only lose the context once.
11438 if (WasContextLost())
11441 // Don't make GL calls in here, the context might not be current.
11442 context_lost_reason_
= reason
;
11443 current_decoder_error_
= error::kLostContext
;
11444 context_was_lost_
= true;
11447 bool GLES2DecoderImpl::CheckResetStatus() {
11448 DCHECK(!WasContextLost());
11449 DCHECK(context_
->IsCurrent(NULL
));
11451 if (IsRobustnessSupported()) {
11452 // If the reason for the call was a GL error, we can try to determine the
11453 // reset status more accurately.
11454 GLenum driver_status
= glGetGraphicsResetStatusARB();
11455 if (driver_status
== GL_NO_ERROR
)
11458 LOG(ERROR
) << (surface_
->IsOffscreen() ? "Offscreen" : "Onscreen")
11459 << " context lost via ARB/EXT_robustness. Reset status = "
11460 << GLES2Util::GetStringEnum(driver_status
);
11462 // Don't pretend we know which client was responsible.
11463 if (workarounds().use_virtualized_gl_contexts
)
11464 driver_status
= GL_UNKNOWN_CONTEXT_RESET_ARB
;
11466 switch (driver_status
) {
11467 case GL_GUILTY_CONTEXT_RESET_ARB
:
11468 MarkContextLost(error::kGuilty
);
11470 case GL_INNOCENT_CONTEXT_RESET_ARB
:
11471 MarkContextLost(error::kInnocent
);
11473 case GL_UNKNOWN_CONTEXT_RESET_ARB
:
11474 MarkContextLost(error::kUnknown
);
11480 reset_by_robustness_extension_
= true;
11486 error::Error
GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
11487 uint32 immediate_data_size
,
11488 const void* cmd_data
) {
11489 return error::kUnknownCommand
;
11492 error::Error
GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
11493 uint32 immediate_data_size
,
11494 const void* cmd_data
) {
11495 const gles2::cmds::WaitSyncPointCHROMIUM
& c
=
11496 *static_cast<const gles2::cmds::WaitSyncPointCHROMIUM
*>(cmd_data
);
11497 uint32 sync_point
= c
.sync_point
;
11498 if (wait_sync_point_callback_
.is_null())
11499 return error::kNoError
;
11501 return wait_sync_point_callback_
.Run(sync_point
) ?
11502 error::kNoError
: error::kDeferCommandUntilLater
;
11505 error::Error
GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
11506 uint32 immediate_data_size
,
11507 const void* cmd_data
) {
11508 if (surface_
->DeferDraws())
11509 return error::kDeferCommandUntilLater
;
11510 if (!surface_
->SetBackbufferAllocation(false))
11511 return error::kLostContext
;
11512 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
11513 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
11514 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
11515 return error::kNoError
;
11518 bool GLES2DecoderImpl::GenQueriesEXTHelper(
11519 GLsizei n
, const GLuint
* client_ids
) {
11520 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11521 if (query_manager_
->GetQuery(client_ids
[ii
])) {
11525 query_manager_
->GenQueries(n
, client_ids
);
11529 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
11530 GLsizei n
, const GLuint
* client_ids
) {
11531 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11532 query_manager_
->RemoveQuery(client_ids
[ii
]);
11536 bool GLES2DecoderImpl::ProcessPendingQueries(bool did_finish
) {
11537 if (query_manager_
.get() == NULL
) {
11540 if (!query_manager_
->ProcessPendingQueries(did_finish
)) {
11541 current_decoder_error_
= error::kOutOfBounds
;
11543 return query_manager_
->HavePendingQueries();
11546 // Note that if there are no pending readpixels right now,
11547 // this function will call the callback immediately.
11548 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback
) {
11549 if (features().use_async_readpixels
&& !pending_readpixel_fences_
.empty()) {
11550 pending_readpixel_fences_
.back()->callbacks
.push_back(callback
);
11556 void GLES2DecoderImpl::ProcessPendingReadPixels(bool did_finish
) {
11557 // Note: |did_finish| guarantees that the GPU has passed the fence but
11558 // we cannot assume that GLFence::HasCompleted() will return true yet as
11559 // that's not guaranteed by all GLFence implementations.
11560 while (!pending_readpixel_fences_
.empty() &&
11562 pending_readpixel_fences_
.front()->fence
->HasCompleted())) {
11563 std::vector
<base::Closure
> callbacks
=
11564 pending_readpixel_fences_
.front()->callbacks
;
11565 pending_readpixel_fences_
.pop();
11566 for (size_t i
= 0; i
< callbacks
.size(); i
++) {
11567 callbacks
[i
].Run();
11572 bool GLES2DecoderImpl::HasMoreIdleWork() {
11573 return !pending_readpixel_fences_
.empty() ||
11574 async_pixel_transfer_manager_
->NeedsProcessMorePendingTransfers();
11577 void GLES2DecoderImpl::PerformIdleWork() {
11578 ProcessPendingReadPixels(false);
11579 if (!async_pixel_transfer_manager_
->NeedsProcessMorePendingTransfers())
11581 async_pixel_transfer_manager_
->ProcessMorePendingTransfers();
11582 ProcessFinishedAsyncTransfers();
11585 error::Error
GLES2DecoderImpl::HandleBeginQueryEXT(uint32 immediate_data_size
,
11586 const void* cmd_data
) {
11587 const gles2::cmds::BeginQueryEXT
& c
=
11588 *static_cast<const gles2::cmds::BeginQueryEXT
*>(cmd_data
);
11589 GLenum target
= static_cast<GLenum
>(c
.target
);
11590 GLuint client_id
= static_cast<GLuint
>(c
.id
);
11591 int32 sync_shm_id
= static_cast<int32
>(c
.sync_data_shm_id
);
11592 uint32 sync_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
11595 case GL_COMMANDS_ISSUED_CHROMIUM
:
11596 case GL_LATENCY_QUERY_CHROMIUM
:
11597 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
:
11598 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM
:
11599 case GL_GET_ERROR_QUERY_CHROMIUM
:
11601 case GL_COMMANDS_COMPLETED_CHROMIUM
:
11602 if (!features().chromium_sync_query
) {
11603 #if defined(OS_MACOSX)
11604 // TODO(dyen): Remove once we know what is failing.
11605 uint32_t boolean_flags
= 0;
11606 if (gfx::g_driver_gl
.ext
.b_GL_ARB_sync
)
11607 boolean_flags
|= 1;
11608 if (gfx::g_driver_gl
.ext
.b_GL_APPLE_fence
)
11609 boolean_flags
|= 2;
11610 if (gfx::g_driver_gl
.ext
.b_GL_NV_fence
)
11611 boolean_flags
|= 4;
11613 CHECK(boolean_flags
!= 0) << "Nothing supported";
11614 CHECK(boolean_flags
!= 1) << "ARB";
11615 CHECK(boolean_flags
!= 2) << "APPLE";
11616 CHECK(boolean_flags
!= 3) << "ARB APPLE";
11617 CHECK(boolean_flags
!= 4) << "NV";
11618 CHECK(boolean_flags
!= 5) << "NV ARB";
11619 CHECK(boolean_flags
!= 6) << "NV APPLE";
11620 CHECK(boolean_flags
!= 7) << "NV ARB APPLE";
11621 CHECK(false) << "Unknown error.";
11623 LOCAL_SET_GL_ERROR(
11624 GL_INVALID_OPERATION
, "glBeginQueryEXT",
11625 "not enabled for commands completed queries");
11626 return error::kNoError
;
11629 case GL_SAMPLES_PASSED
:
11630 case GL_ANY_SAMPLES_PASSED
:
11631 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE
:
11632 if (!features().occlusion_query_boolean
) {
11633 LOCAL_SET_GL_ERROR(
11634 GL_INVALID_OPERATION
, "glBeginQueryEXT",
11635 "not enabled for occlusion queries");
11636 return error::kNoError
;
11639 case GL_TIME_ELAPSED
:
11640 if (!query_manager_
->GPUTimingAvailable()) {
11641 LOCAL_SET_GL_ERROR(
11642 GL_INVALID_OPERATION
, "glBeginQueryEXT",
11643 "not enabled for timing queries");
11644 return error::kNoError
;
11648 LOCAL_SET_GL_ERROR(
11649 GL_INVALID_ENUM
, "glBeginQueryEXT",
11650 "unknown query target");
11651 return error::kNoError
;
11654 if (query_manager_
->GetActiveQuery(target
)) {
11655 #if defined(OS_MACOSX)
11656 // TODO(dyen): Remove once we know what is failing.
11657 CHECK(target
!= GL_COMMANDS_COMPLETED_CHROMIUM
)
11658 << "Query already in progress";
11660 LOCAL_SET_GL_ERROR(
11661 GL_INVALID_OPERATION
, "glBeginQueryEXT", "query already in progress");
11662 return error::kNoError
;
11665 if (client_id
== 0) {
11666 #if defined(OS_MACOSX)
11667 // TODO(dyen): Remove once we know what is failing.
11668 CHECK(target
!= GL_COMMANDS_COMPLETED_CHROMIUM
) << "Id is 0";
11670 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glBeginQueryEXT", "id is 0");
11671 return error::kNoError
;
11674 QueryManager::Query
* query
= query_manager_
->GetQuery(client_id
);
11676 if (!query_manager_
->IsValidQuery(client_id
)) {
11677 #if defined(OS_MACOSX)
11678 // TODO(dyen): Remove once we know what is failing.
11679 CHECK(target
!= GL_COMMANDS_COMPLETED_CHROMIUM
) << "Invalid ID";
11681 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11683 "id not made by glGenQueriesEXT");
11684 return error::kNoError
;
11686 query
= query_manager_
->CreateQuery(
11687 target
, client_id
, sync_shm_id
, sync_shm_offset
);
11690 if (query
->target() != target
) {
11691 #if defined(OS_MACOSX)
11692 // TODO(dyen): Remove once we know what is failing.
11693 CHECK(target
!= GL_COMMANDS_COMPLETED_CHROMIUM
) << "Non-Matching Target";
11695 LOCAL_SET_GL_ERROR(
11696 GL_INVALID_OPERATION
, "glBeginQueryEXT", "target does not match");
11697 return error::kNoError
;
11698 } else if (query
->shm_id() != sync_shm_id
||
11699 query
->shm_offset() != sync_shm_offset
) {
11700 DLOG(ERROR
) << "Shared memory used by query not the same as before";
11701 return error::kInvalidArguments
;
11704 if (!query_manager_
->BeginQuery(query
)) {
11705 #if defined(OS_MACOSX)
11706 // TODO(dyen): Remove once we know what is failing.
11707 CHECK(target
!= GL_COMMANDS_COMPLETED_CHROMIUM
) << "Out of bounds";
11709 return error::kOutOfBounds
;
11712 return error::kNoError
;
11715 error::Error
GLES2DecoderImpl::HandleEndQueryEXT(uint32 immediate_data_size
,
11716 const void* cmd_data
) {
11717 const gles2::cmds::EndQueryEXT
& c
=
11718 *static_cast<const gles2::cmds::EndQueryEXT
*>(cmd_data
);
11719 GLenum target
= static_cast<GLenum
>(c
.target
);
11720 uint32 submit_count
= static_cast<GLuint
>(c
.submit_count
);
11722 QueryManager::Query
* query
= query_manager_
->GetActiveQuery(target
);
11724 #if defined(OS_MACOSX)
11725 // TODO(dyen): Remove once we know what is failing.
11726 CHECK(target
!= GL_COMMANDS_COMPLETED_CHROMIUM
) << "Target not active";
11728 LOCAL_SET_GL_ERROR(
11729 GL_INVALID_OPERATION
, "glEndQueryEXT", "No active query");
11730 return error::kNoError
;
11733 if (!query_manager_
->EndQuery(query
, submit_count
)) {
11734 #if defined(OS_MACOSX)
11735 // TODO(dyen): Remove once we know what is failing.
11736 CHECK(target
!= GL_COMMANDS_COMPLETED_CHROMIUM
) << "Out of bounds";
11738 return error::kOutOfBounds
;
11741 query_manager_
->ProcessPendingTransferQueries();
11743 return error::kNoError
;
11746 error::Error
GLES2DecoderImpl::HandleQueryCounterEXT(uint32 immediate_data_size
,
11747 const void* cmd_data
) {
11748 const gles2::cmds::QueryCounterEXT
& c
=
11749 *static_cast<const gles2::cmds::QueryCounterEXT
*>(cmd_data
);
11750 GLuint client_id
= static_cast<GLuint
>(c
.id
);
11751 GLenum target
= static_cast<GLenum
>(c
.target
);
11752 int32 sync_shm_id
= static_cast<int32
>(c
.sync_data_shm_id
);
11753 uint32 sync_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
11754 uint32 submit_count
= static_cast<GLuint
>(c
.submit_count
);
11758 if (!query_manager_
->GPUTimingAvailable()) {
11759 LOCAL_SET_GL_ERROR(
11760 GL_INVALID_OPERATION
, "glQueryCounterEXT",
11761 "not enabled for timing queries");
11762 return error::kNoError
;
11766 LOCAL_SET_GL_ERROR(
11767 GL_INVALID_ENUM
, "glQueryCounterEXT",
11768 "unknown query target");
11769 return error::kNoError
;
11772 QueryManager::Query
* query
= query_manager_
->GetQuery(client_id
);
11774 if (!query_manager_
->IsValidQuery(client_id
)) {
11775 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11776 "glQueryCounterEXT",
11777 "id not made by glGenQueriesEXT");
11778 return error::kNoError
;
11780 query
= query_manager_
->CreateQuery(
11781 target
, client_id
, sync_shm_id
, sync_shm_offset
);
11783 if (!query_manager_
->QueryCounter(query
, submit_count
)) {
11784 return error::kOutOfBounds
;
11787 return error::kNoError
;
11790 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
11791 GLsizei n
, const GLuint
* client_ids
) {
11792 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11793 if (GetVertexAttribManager(client_ids
[ii
])) {
11798 if (!features().native_vertex_array_object
) {
11800 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11801 CreateVertexAttribManager(client_ids
[ii
], 0, true);
11804 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
11806 glGenVertexArraysOES(n
, service_ids
.get());
11807 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11808 CreateVertexAttribManager(client_ids
[ii
], service_ids
[ii
], true);
11815 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
11816 GLsizei n
, const GLuint
* client_ids
) {
11817 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11818 VertexAttribManager
* vao
=
11819 GetVertexAttribManager(client_ids
[ii
]);
11820 if (vao
&& !vao
->IsDeleted()) {
11821 if (state_
.vertex_attrib_manager
.get() == vao
) {
11822 DoBindVertexArrayOES(0);
11824 RemoveVertexAttribManager(client_ids
[ii
]);
11829 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id
) {
11830 VertexAttribManager
* vao
= NULL
;
11831 if (client_id
!= 0) {
11832 vao
= GetVertexAttribManager(client_id
);
11834 // Unlike most Bind* methods, the spec explicitly states that VertexArray
11835 // only allows names that have been previously generated. As such, we do
11836 // not generate new names here.
11837 LOCAL_SET_GL_ERROR(
11838 GL_INVALID_OPERATION
,
11839 "glBindVertexArrayOES", "bad vertex array id.");
11840 current_decoder_error_
= error::kNoError
;
11844 vao
= state_
.default_vertex_attrib_manager
.get();
11847 // Only set the VAO state if it's changed
11848 if (state_
.vertex_attrib_manager
.get() != vao
) {
11849 state_
.vertex_attrib_manager
= vao
;
11850 if (!features().native_vertex_array_object
) {
11851 EmulateVertexArrayState();
11853 GLuint service_id
= vao
->service_id();
11854 glBindVertexArrayOES(service_id
);
11859 // Used when OES_vertex_array_object isn't natively supported
11860 void GLES2DecoderImpl::EmulateVertexArrayState() {
11861 // Setup the Vertex attribute state
11862 for (uint32 vv
= 0; vv
< group_
->max_vertex_attribs(); ++vv
) {
11863 RestoreStateForAttrib(vv
, true);
11866 // Setup the element buffer
11867 Buffer
* element_array_buffer
=
11868 state_
.vertex_attrib_manager
->element_array_buffer();
11869 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
11870 element_array_buffer
? element_array_buffer
->service_id() : 0);
11873 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id
) {
11874 const VertexAttribManager
* vao
=
11875 GetVertexAttribManager(client_id
);
11876 return vao
&& vao
->IsValid() && !vao
->IsDeleted();
11879 bool GLES2DecoderImpl::DoIsPathCHROMIUM(GLuint client_id
) {
11880 GLuint service_id
= 0;
11881 return path_manager()->GetPath(client_id
, &service_id
) &&
11882 glIsPathNV(service_id
) == GL_TRUE
;
11885 #if defined(OS_MACOSX)
11886 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id
) {
11887 TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.find(
11889 if (it
!= texture_to_io_surface_map_
.end()) {
11890 // Found a previous IOSurface bound to this texture; release it.
11891 IOSurfaceRef surface
= it
->second
;
11892 CFRelease(surface
);
11893 texture_to_io_surface_map_
.erase(it
);
11898 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
11899 GLenum target
, GLsizei width
, GLsizei height
,
11900 GLuint io_surface_id
, GLuint plane
) {
11901 #if defined(OS_MACOSX)
11902 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL
) {
11903 LOCAL_SET_GL_ERROR(
11904 GL_INVALID_OPERATION
,
11905 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
11909 if (target
!= GL_TEXTURE_RECTANGLE_ARB
) {
11910 // This might be supported in the future, and if we could require
11911 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
11912 // could delete a lot of code. For now, perform strict validation so we
11913 // know what's going on.
11914 LOCAL_SET_GL_ERROR(
11915 GL_INVALID_OPERATION
,
11916 "glTexImageIOSurface2DCHROMIUM",
11917 "requires TEXTURE_RECTANGLE_ARB target");
11921 // Default target might be conceptually valid, but disallow it to avoid
11923 TextureRef
* texture_ref
=
11924 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
11925 if (!texture_ref
) {
11926 LOCAL_SET_GL_ERROR(
11927 GL_INVALID_OPERATION
,
11928 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
11932 // Look up the new IOSurface. Note that because of asynchrony
11933 // between processes this might fail; during live resizing the
11934 // plugin process might allocate and release an IOSurface before
11935 // this process gets a chance to look it up. Hold on to any old
11936 // IOSurface in this case.
11937 IOSurfaceRef surface
= IOSurfaceLookup(io_surface_id
);
11939 LOCAL_SET_GL_ERROR(
11940 GL_INVALID_OPERATION
,
11941 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
11945 // Release any IOSurface previously bound to this texture.
11946 ReleaseIOSurfaceForTexture(texture_ref
->service_id());
11948 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
11949 texture_to_io_surface_map_
.insert(
11950 std::make_pair(texture_ref
->service_id(), surface
));
11952 CGLContextObj context
=
11953 static_cast<CGLContextObj
>(context_
->GetHandle());
11955 CGLError err
= CGLTexImageIOSurface2D(
11962 GL_UNSIGNED_INT_8_8_8_8_REV
,
11966 if (err
!= kCGLNoError
) {
11967 LOCAL_SET_GL_ERROR(
11968 GL_INVALID_OPERATION
,
11969 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
11973 texture_manager()->SetLevelInfo(
11974 texture_ref
, target
, 0, GL_RGBA
, width
, height
, 1, 0, GL_BGRA
,
11975 GL_UNSIGNED_INT_8_8_8_8_REV
, gfx::Rect(width
, height
));
11978 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11979 "glTexImageIOSurface2DCHROMIUM", "not supported.");
11983 static GLenum
ExtractFormatFromStorageFormat(GLenum internalformat
) {
11984 switch (internalformat
) {
11996 return GL_RED_INTEGER
;
12008 return GL_RG_INTEGER
;
12010 case GL_R11F_G11F_B10F
:
12012 case GL_RGB8_SNORM
:
12023 return GL_RGB_INTEGER
;
12025 case GL_SRGB8_ALPHA8
:
12026 case GL_RGBA8_SNORM
:
12035 case GL_RGB10_A2UI
:
12040 return GL_RGBA_INTEGER
;
12041 case GL_DEPTH_COMPONENT16
:
12042 case GL_DEPTH_COMPONENT24
:
12043 case GL_DEPTH_COMPONENT32F
:
12044 return GL_DEPTH_COMPONENT
;
12045 case GL_DEPTH24_STENCIL8
:
12046 case GL_DEPTH32F_STENCIL8
:
12047 return GL_DEPTH_STENCIL
;
12048 case GL_LUMINANCE8_ALPHA8_EXT
:
12049 return GL_LUMINANCE_ALPHA
;
12050 case GL_LUMINANCE8_EXT
:
12051 return GL_LUMINANCE
;
12052 case GL_ALPHA8_EXT
:
12054 case GL_ALPHA32F_EXT
:
12056 case GL_LUMINANCE32F_EXT
:
12057 return GL_LUMINANCE
;
12058 case GL_LUMINANCE_ALPHA32F_EXT
:
12059 return GL_LUMINANCE_ALPHA
;
12060 case GL_ALPHA16F_EXT
:
12062 case GL_LUMINANCE16F_EXT
:
12063 return GL_LUMINANCE
;
12064 case GL_LUMINANCE_ALPHA16F_EXT
:
12065 return GL_LUMINANCE_ALPHA
;
12067 return GL_BGRA_EXT
;
12073 bool GLES2DecoderImpl::ValidateCopyTextureCHROMIUM(
12074 const char* function_name
,
12076 TextureRef
* source_texture_ref
,
12077 TextureRef
* dest_texture_ref
,
12078 GLenum dest_internal_format
) {
12079 if (!source_texture_ref
|| !dest_texture_ref
) {
12080 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown texture id");
12084 if (GL_TEXTURE_2D
!= target
) {
12085 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
12086 "invalid texture target");
12090 Texture
* source_texture
= source_texture_ref
->texture();
12091 Texture
* dest_texture
= dest_texture_ref
->texture();
12092 if (source_texture
== dest_texture
) {
12093 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
12094 "source and destination textures are the same");
12098 if (dest_texture
->target() != GL_TEXTURE_2D
||
12099 (source_texture
->target() != GL_TEXTURE_2D
&&
12100 source_texture
->target() != GL_TEXTURE_RECTANGLE_ARB
&&
12101 source_texture
->target() != GL_TEXTURE_EXTERNAL_OES
)) {
12102 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
12103 "invalid texture target binding");
12107 GLenum source_type
= 0;
12108 GLenum source_internal_format
= 0;
12109 source_texture
->GetLevelType(source_texture
->target(), 0, &source_type
,
12110 &source_internal_format
);
12112 // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
12113 // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
12114 // renderable on some platforms.
12115 bool valid_dest_format
= dest_internal_format
== GL_RGB
||
12116 dest_internal_format
== GL_RGBA
||
12117 dest_internal_format
== GL_BGRA_EXT
;
12118 bool valid_source_format
=
12119 source_internal_format
== GL_R8
|| source_internal_format
== GL_ALPHA
||
12120 source_internal_format
== GL_RGB
|| source_internal_format
== GL_RGBA
||
12121 source_internal_format
== GL_LUMINANCE
||
12122 source_internal_format
== GL_LUMINANCE_ALPHA
||
12123 source_internal_format
== GL_BGRA_EXT
;
12124 if (!valid_source_format
|| !valid_dest_format
) {
12125 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
12126 "invalid internal format");
12132 bool GLES2DecoderImpl::ValidateCompressedCopyTextureCHROMIUM(
12133 const char* function_name
,
12135 TextureRef
* source_texture_ref
,
12136 TextureRef
* dest_texture_ref
) {
12137 if (!source_texture_ref
|| !dest_texture_ref
) {
12138 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown texture id");
12142 if (GL_TEXTURE_2D
!= target
) {
12143 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
12144 "invalid texture target");
12148 Texture
* source_texture
= source_texture_ref
->texture();
12149 Texture
* dest_texture
= dest_texture_ref
->texture();
12150 if (source_texture
== dest_texture
) {
12151 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
12152 "source and destination textures are the same");
12156 if (dest_texture
->target() != GL_TEXTURE_2D
||
12157 (source_texture
->target() != GL_TEXTURE_2D
&&
12158 source_texture
->target() != GL_TEXTURE_RECTANGLE_ARB
&&
12159 source_texture
->target() != GL_TEXTURE_EXTERNAL_OES
)) {
12160 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
12161 "invalid texture target binding");
12165 GLenum source_type
= 0;
12166 GLenum source_internal_format
= 0;
12167 source_texture
->GetLevelType(source_texture
->target(), 0, &source_type
,
12168 &source_internal_format
);
12170 bool valid_format
=
12171 source_internal_format
== GL_ATC_RGB_AMD
||
12172 source_internal_format
== GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
||
12173 source_internal_format
== GL_COMPRESSED_RGB_S3TC_DXT1_EXT
||
12174 source_internal_format
== GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
||
12175 source_internal_format
== GL_ETC1_RGB8_OES
;
12177 if (!valid_format
) {
12178 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
12179 "invalid internal format");
12186 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
12190 GLenum internal_format
,
12192 GLboolean unpack_flip_y
,
12193 GLboolean unpack_premultiply_alpha
,
12194 GLboolean unpack_unmultiply_alpha
) {
12195 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
12197 TextureRef
* source_texture_ref
= GetTexture(source_id
);
12198 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
12199 Texture
* source_texture
= source_texture_ref
->texture();
12200 Texture
* dest_texture
= dest_texture_ref
->texture();
12201 int source_width
= 0;
12202 int source_height
= 0;
12203 gfx::GLImage
* image
=
12204 source_texture
->GetLevelImage(source_texture
->target(), 0);
12206 gfx::Size size
= image
->GetSize();
12207 source_width
= size
.width();
12208 source_height
= size
.height();
12209 if (source_width
<= 0 || source_height
<= 0) {
12210 LOCAL_SET_GL_ERROR(
12212 "glCopyTextureChromium", "invalid image size");
12216 if (!source_texture
->GetLevelSize(source_texture
->target(), 0,
12217 &source_width
, &source_height
, nullptr)) {
12218 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
12219 "glCopyTextureChromium",
12220 "source texture has no level 0");
12224 // Check that this type of texture is allowed.
12225 if (!texture_manager()->ValidForTarget(source_texture
->target(), 0,
12226 source_width
, source_height
, 1)) {
12227 LOCAL_SET_GL_ERROR(
12228 GL_INVALID_VALUE
, "glCopyTextureCHROMIUM", "Bad dimensions");
12233 GLenum source_type
= 0;
12234 GLenum source_internal_format
= 0;
12235 source_texture
->GetLevelType(
12236 source_texture
->target(), 0, &source_type
, &source_internal_format
);
12238 if (dest_texture
->IsImmutable()) {
12239 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCopyTextureCHROMIUM",
12240 "texture is immutable");
12244 if (!ValidateCopyTextureCHROMIUM("glCopyTextureCHROMIUM", target
,
12245 source_texture_ref
, dest_texture_ref
,
12246 internal_format
)) {
12250 // Clear the source texture if necessary.
12251 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref
,
12252 source_texture
->target(), 0)) {
12253 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTextureCHROMIUM",
12254 "dimensions too big");
12258 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12259 // needed because it takes 10s of milliseconds to initialize.
12260 if (!copy_texture_CHROMIUM_
.get()) {
12261 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12262 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
12263 copy_texture_CHROMIUM_
->Initialize(this);
12264 RestoreCurrentFramebufferBindings();
12265 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR
)
12269 GLenum dest_type_previous
= dest_type
;
12270 GLenum dest_internal_format
= internal_format
;
12271 int dest_width
= 0;
12272 int dest_height
= 0;
12273 bool dest_level_defined
= dest_texture
->GetLevelSize(
12274 GL_TEXTURE_2D
, 0, &dest_width
, &dest_height
, nullptr);
12276 if (dest_level_defined
) {
12277 dest_texture
->GetLevelType(GL_TEXTURE_2D
, 0, &dest_type_previous
,
12278 &dest_internal_format
);
12281 // Resize the destination texture to the dimensions of the source texture.
12282 if (!dest_level_defined
|| dest_width
!= source_width
||
12283 dest_height
!= source_height
||
12284 dest_internal_format
!= internal_format
||
12285 dest_type_previous
!= dest_type
) {
12286 // Ensure that the glTexImage2D succeeds.
12287 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12288 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
12289 glTexImage2D(GL_TEXTURE_2D
, 0, internal_format
, source_width
, source_height
,
12290 0, internal_format
, dest_type
, NULL
);
12291 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
12292 if (error
!= GL_NO_ERROR
) {
12293 RestoreCurrentTextureBindings(&state_
, GL_TEXTURE_2D
);
12297 texture_manager()->SetLevelInfo(
12298 dest_texture_ref
, GL_TEXTURE_2D
, 0, internal_format
, source_width
,
12299 source_height
, 1, 0, internal_format
, dest_type
,
12300 gfx::Rect(source_width
, source_height
));
12302 texture_manager()->SetLevelCleared(dest_texture_ref
, GL_TEXTURE_2D
, 0,
12306 ScopedModifyPixels
modify(dest_texture_ref
);
12308 // Try using GLImage::CopyTexSubImage when possible.
12309 bool unpack_premultiply_alpha_change
=
12310 (unpack_premultiply_alpha
^ unpack_unmultiply_alpha
) != 0;
12311 if (image
&& !unpack_flip_y
&& !unpack_premultiply_alpha_change
) {
12312 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
12313 if (image
->CopyTexSubImage(GL_TEXTURE_2D
, gfx::Point(0, 0),
12314 gfx::Rect(0, 0, source_width
, source_height
))) {
12319 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
12321 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
12322 // before presenting.
12323 if (source_texture
->target() == GL_TEXTURE_EXTERNAL_OES
) {
12324 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
12325 // instead of using kIdentityMatrix crbug.com/226218.
12326 copy_texture_CHROMIUM_
->DoCopyTextureWithTransform(
12327 this, source_texture
->target(), source_texture
->service_id(),
12328 dest_texture
->service_id(), source_width
, source_height
,
12329 unpack_flip_y
== GL_TRUE
,
12330 unpack_premultiply_alpha
== GL_TRUE
,
12331 unpack_unmultiply_alpha
== GL_TRUE
,
12334 copy_texture_CHROMIUM_
->DoCopyTexture(
12335 this, source_texture
->target(), source_texture
->service_id(),
12336 source_internal_format
, dest_texture
->service_id(), internal_format
,
12337 source_width
, source_height
,
12338 unpack_flip_y
== GL_TRUE
,
12339 unpack_premultiply_alpha
== GL_TRUE
,
12340 unpack_unmultiply_alpha
== GL_TRUE
);
12343 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
12346 void GLES2DecoderImpl::DoCopySubTextureCHROMIUM(
12356 GLboolean unpack_flip_y
,
12357 GLboolean unpack_premultiply_alpha
,
12358 GLboolean unpack_unmultiply_alpha
) {
12359 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopySubTextureCHROMIUM");
12361 TextureRef
* source_texture_ref
= GetTexture(source_id
);
12362 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
12363 Texture
* source_texture
= source_texture_ref
->texture();
12364 Texture
* dest_texture
= dest_texture_ref
->texture();
12365 int source_width
= 0;
12366 int source_height
= 0;
12367 gfx::GLImage
* image
=
12368 source_texture
->GetLevelImage(source_texture
->target(), 0);
12370 gfx::Size size
= image
->GetSize();
12371 source_width
= size
.width();
12372 source_height
= size
.height();
12373 if (source_width
<= 0 || source_height
<= 0) {
12374 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
12375 "invalid image size");
12379 if (!source_texture
->GetLevelSize(source_texture
->target(), 0,
12380 &source_width
, &source_height
, nullptr)) {
12381 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
12382 "source texture has no level 0");
12386 // Check that this type of texture is allowed.
12387 if (!texture_manager()->ValidForTarget(source_texture
->target(), 0,
12388 source_width
, source_height
, 1)) {
12389 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
12390 "source texture bad dimensions");
12395 GLenum source_type
= 0;
12396 GLenum source_internal_format
= 0;
12397 source_texture
->GetLevelType(source_texture
->target(), 0, &source_type
,
12398 &source_internal_format
);
12399 if (!source_texture
->ValidForTexture(source_texture
->target(), 0, x
, y
, 0,
12400 width
, height
, 1, source_type
)) {
12401 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
12402 "source texture bad dimensions.");
12406 GLenum dest_type
= 0;
12407 GLenum dest_internal_format
= 0;
12408 bool dest_level_defined
= dest_texture
->GetLevelType(
12409 dest_texture
->target(), 0, &dest_type
, &dest_internal_format
);
12410 if (!dest_level_defined
) {
12411 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCopySubTextureCHROMIUM",
12412 "destination texture is not defined");
12415 if (!dest_texture
->ValidForTexture(dest_texture
->target(), 0, xoffset
,
12416 yoffset
, 0, width
, height
, 1, dest_type
)) {
12417 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
12418 "destination texture bad dimensions.");
12422 if (!ValidateCopyTextureCHROMIUM("glCopySubTextureCHROMIUM", target
,
12423 source_texture_ref
, dest_texture_ref
,
12424 dest_internal_format
)) {
12428 // Clear the source texture if necessary.
12429 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref
,
12430 source_texture
->target(), 0)) {
12431 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopySubTextureCHROMIUM",
12432 "source texture dimensions too big");
12436 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12437 // needed because it takes 10s of milliseconds to initialize.
12438 if (!copy_texture_CHROMIUM_
.get()) {
12439 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopySubTextureCHROMIUM");
12440 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
12441 copy_texture_CHROMIUM_
->Initialize(this);
12442 RestoreCurrentFramebufferBindings();
12443 if (LOCAL_PEEK_GL_ERROR("glCopySubTextureCHROMIUM") != GL_NO_ERROR
)
12447 int dest_width
= 0;
12448 int dest_height
= 0;
12449 bool ok
= dest_texture
->GetLevelSize(
12450 GL_TEXTURE_2D
, 0, &dest_width
, &dest_height
, nullptr);
12452 if (xoffset
!= 0 || yoffset
!= 0 || width
!= dest_width
||
12453 height
!= dest_height
) {
12454 gfx::Rect cleared_rect
;
12455 if (CombineAdjacentRects(dest_texture
->GetLevelClearedRect(target
, 0),
12456 gfx::Rect(xoffset
, yoffset
, width
, height
),
12458 DCHECK_GE(cleared_rect
.size().GetArea(),
12459 dest_texture
->GetLevelClearedRect(target
, 0).size().GetArea());
12460 texture_manager()->SetLevelClearedRect(dest_texture_ref
, target
, 0,
12463 // Otherwise clear part of texture level that is not already cleared.
12464 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref
, target
,
12466 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopySubTextureCHROMIUM",
12467 "destination texture dimensions too big");
12472 texture_manager()->SetLevelCleared(dest_texture_ref
, GL_TEXTURE_2D
, 0,
12476 ScopedModifyPixels
modify(dest_texture_ref
);
12478 // Try using GLImage::CopyTexSubImage when possible.
12479 bool unpack_premultiply_alpha_change
=
12480 (unpack_premultiply_alpha
^ unpack_unmultiply_alpha
) != 0;
12481 if (image
&& !unpack_flip_y
&& !unpack_premultiply_alpha_change
) {
12482 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
12483 if (image
->CopyTexSubImage(GL_TEXTURE_2D
, gfx::Point(xoffset
, yoffset
),
12484 gfx::Rect(x
, y
, width
, height
))) {
12489 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
12491 // TODO(hkuang): get the StreamTexture transform matrix in GPU process.
12492 // crbug.com/226218.
12493 copy_texture_CHROMIUM_
->DoCopySubTexture(
12494 this, source_texture
->target(), source_texture
->service_id(),
12495 source_internal_format
, dest_texture
->service_id(), dest_internal_format
,
12496 xoffset
, yoffset
, x
, y
, width
, height
, dest_width
, dest_height
,
12497 source_width
, source_height
,
12498 unpack_flip_y
== GL_TRUE
,
12499 unpack_premultiply_alpha
== GL_TRUE
,
12500 unpack_unmultiply_alpha
== GL_TRUE
);
12502 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
12505 void GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM(GLenum target
,
12508 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM");
12510 TextureRef
* source_texture_ref
= GetTexture(source_id
);
12511 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
12512 Texture
* source_texture
= source_texture_ref
->texture();
12513 Texture
* dest_texture
= dest_texture_ref
->texture();
12514 int source_width
= 0;
12515 int source_height
= 0;
12516 gfx::GLImage
* image
=
12517 source_texture
->GetLevelImage(source_texture
->target(), 0);
12519 gfx::Size size
= image
->GetSize();
12520 source_width
= size
.width();
12521 source_height
= size
.height();
12522 if (source_width
<= 0 || source_height
<= 0) {
12523 LOCAL_SET_GL_ERROR(
12525 "glCompressedCopyTextureCHROMIUM", "invalid image size");
12529 if (!source_texture
->GetLevelSize(source_texture
->target(), 0,
12530 &source_width
, &source_height
, nullptr)) {
12531 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
12532 "glCompressedCopyTextureCHROMIUM",
12533 "source texture has no level 0");
12537 // Check that this type of texture is allowed.
12538 if (!texture_manager()->ValidForTarget(source_texture
->target(), 0,
12539 source_width
, source_height
, 1)) {
12540 LOCAL_SET_GL_ERROR(
12541 GL_INVALID_VALUE
, "glCompressedCopyTextureCHROMIUM",
12547 GLenum source_type
= 0;
12548 GLenum source_internal_format
= 0;
12549 source_texture
->GetLevelType(
12550 source_texture
->target(), 0, &source_type
, &source_internal_format
);
12552 if (dest_texture
->IsImmutable()) {
12553 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12554 "glCompressedCopyTextureCHROMIUM",
12555 "texture is immutable");
12559 if (!ValidateCompressedCopyTextureCHROMIUM(
12560 "glCompressedCopyTextureCHROMIUM",
12562 source_texture_ref
, dest_texture_ref
)) {
12566 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12567 // needed because it takes 10s of milliseconds to initialize.
12568 if (!copy_texture_CHROMIUM_
.get()) {
12569 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12570 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
12571 copy_texture_CHROMIUM_
->Initialize(this);
12572 RestoreCurrentFramebufferBindings();
12573 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR
)
12577 // Clear the source texture if necessary.
12578 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref
,
12579 source_texture
->target(), 0)) {
12580 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCompressedCopyTextureCHROMIUM",
12581 "dimensions too big");
12585 ScopedTextureBinder
binder(
12586 &state_
, dest_texture
->service_id(), GL_TEXTURE_2D
);
12588 ScopedModifyPixels
modify(dest_texture_ref
);
12590 // Try using GLImage::CopyTexImage when possible.
12592 GLenum dest_type
= 0;
12593 GLenum dest_internal_format
= 0;
12594 int dest_width
= 0;
12595 int dest_height
= 0;
12596 bool dest_level_defined
= dest_texture
->GetLevelSize(
12597 GL_TEXTURE_2D
, 0, &dest_width
, &dest_height
, nullptr);
12599 if (dest_level_defined
) {
12600 dest_texture
->GetLevelType(GL_TEXTURE_2D
, 0, &dest_type
,
12601 &dest_internal_format
);
12604 // Resize the destination texture to the dimensions of the source texture.
12605 if (!dest_level_defined
|| dest_width
!= source_width
||
12606 dest_height
!= source_height
||
12607 dest_internal_format
!= source_internal_format
) {
12608 GLsizei source_size
= 0;
12610 bool did_get_size
= GetCompressedTexSizeInBytes(
12611 "glCompressedCopyTextureCHROMIUM", source_width
, source_height
,
12612 1, source_internal_format
, &source_size
);
12613 DCHECK(did_get_size
);
12615 // Ensure that the glCompressedTexImage2D succeeds.
12616 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
12617 glCompressedTexImage2D(GL_TEXTURE_2D
, 0, source_internal_format
,
12618 source_width
, source_height
, 0, source_size
,
12620 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedCopyTextureCHROMIUM");
12621 if (error
!= GL_NO_ERROR
) {
12622 RestoreCurrentTextureBindings(&state_
, GL_TEXTURE_2D
);
12626 texture_manager()->SetLevelInfo(
12627 dest_texture_ref
, GL_TEXTURE_2D
, 0, source_internal_format
,
12628 source_width
, source_height
, 1, 0, source_internal_format
,
12629 source_type
, gfx::Rect(source_width
, source_height
));
12631 texture_manager()->SetLevelCleared(dest_texture_ref
, GL_TEXTURE_2D
, 0,
12635 if (image
->CopyTexSubImage(GL_TEXTURE_2D
, gfx::Point(0, 0),
12636 gfx::Rect(0, 0, source_width
, source_height
))) {
12643 "GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM, fallback");
12645 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
12647 // As a fallback, copy into a non-compressed GL_RGBA texture.
12648 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
12649 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, source_width
, source_height
,
12650 0, GL_RGBA
, GL_UNSIGNED_BYTE
, NULL
);
12651 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedCopyTextureCHROMIUM");
12652 if (error
!= GL_NO_ERROR
) {
12653 RestoreCurrentTextureBindings(&state_
, GL_TEXTURE_2D
);
12657 texture_manager()->SetLevelInfo(
12658 dest_texture_ref
, GL_TEXTURE_2D
, 0, GL_RGBA
, source_width
,
12659 source_height
, 1, 0, GL_RGBA
, GL_UNSIGNED_BYTE
,
12660 gfx::Rect(source_width
, source_height
));
12662 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
12663 // before presenting.
12664 if (source_texture
->target() == GL_TEXTURE_EXTERNAL_OES
) {
12665 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
12666 // instead of using kIdentityMatrix crbug.com/226218.
12667 copy_texture_CHROMIUM_
->DoCopyTextureWithTransform(
12668 this, source_texture
->target(), source_texture
->service_id(),
12669 dest_texture
->service_id(), source_width
, source_height
,
12670 false, false, false, kIdentityMatrix
);
12672 copy_texture_CHROMIUM_
->DoCopyTexture(
12673 this, source_texture
->target(), source_texture
->service_id(),
12674 source_internal_format
, dest_texture
->service_id(), GL_RGBA
,
12675 source_width
, source_height
, false, false, false);
12678 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
12681 static GLenum
ExtractTypeFromStorageFormat(GLenum internalformat
) {
12682 switch (internalformat
) {
12684 return GL_UNSIGNED_BYTE
;
12688 return GL_HALF_FLOAT
;
12692 return GL_UNSIGNED_BYTE
;
12696 return GL_UNSIGNED_SHORT
;
12700 return GL_UNSIGNED_INT
;
12704 return GL_UNSIGNED_BYTE
;
12708 return GL_HALF_FLOAT
;
12712 return GL_UNSIGNED_BYTE
;
12716 return GL_UNSIGNED_SHORT
;
12720 return GL_UNSIGNED_INT
;
12725 return GL_UNSIGNED_BYTE
;
12726 case GL_R11F_G11F_B10F
:
12727 return GL_UNSIGNED_INT_10F_11F_11F_REV
;
12729 return GL_UNSIGNED_SHORT_5_6_5
;
12730 case GL_RGB8_SNORM
:
12733 return GL_UNSIGNED_INT_5_9_9_9_REV
;
12735 return GL_HALF_FLOAT
;
12739 return GL_UNSIGNED_BYTE
;
12743 return GL_UNSIGNED_SHORT
;
12747 return GL_UNSIGNED_INT
;
12751 return GL_UNSIGNED_BYTE
;
12752 case GL_SRGB8_ALPHA8
:
12753 return GL_UNSIGNED_BYTE
;
12754 case GL_RGBA8_SNORM
:
12757 return GL_UNSIGNED_SHORT_4_4_4_4
;
12759 return GL_UNSIGNED_INT_2_10_10_10_REV
;
12761 return GL_UNSIGNED_SHORT_5_5_5_1
;
12763 return GL_HALF_FLOAT
;
12767 return GL_UNSIGNED_BYTE
;
12770 case GL_RGB10_A2UI
:
12771 return GL_UNSIGNED_INT_2_10_10_10_REV
;
12773 return GL_UNSIGNED_SHORT
;
12779 return GL_UNSIGNED_INT
;
12780 case GL_DEPTH_COMPONENT16
:
12781 return GL_UNSIGNED_SHORT
;
12782 case GL_DEPTH_COMPONENT24
:
12783 return GL_UNSIGNED_INT
;
12784 case GL_DEPTH_COMPONENT32F
:
12786 case GL_DEPTH24_STENCIL8
:
12787 return GL_UNSIGNED_INT_24_8
;
12788 case GL_DEPTH32F_STENCIL8
:
12789 return GL_FLOAT_32_UNSIGNED_INT_24_8_REV
;
12790 case GL_LUMINANCE8_ALPHA8_EXT
:
12791 return GL_UNSIGNED_BYTE
;
12792 case GL_LUMINANCE8_EXT
:
12793 return GL_UNSIGNED_BYTE
;
12794 case GL_ALPHA8_EXT
:
12795 return GL_UNSIGNED_BYTE
;
12796 case GL_ALPHA32F_EXT
:
12798 case GL_LUMINANCE32F_EXT
:
12800 case GL_LUMINANCE_ALPHA32F_EXT
:
12802 case GL_ALPHA16F_EXT
:
12803 return GL_HALF_FLOAT_OES
;
12804 case GL_LUMINANCE16F_EXT
:
12805 return GL_HALF_FLOAT_OES
;
12806 case GL_LUMINANCE_ALPHA16F_EXT
:
12807 return GL_HALF_FLOAT_OES
;
12809 return GL_UNSIGNED_BYTE
;
12815 void GLES2DecoderImpl::DoTexStorage2DEXT(
12818 GLenum internal_format
,
12821 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
12822 "width", width
, "height", height
);
12823 if (!texture_manager()->ValidForTarget(target
, 0, width
, height
, 1) ||
12824 TextureManager::ComputeMipMapCount(target
, width
, height
, 1) < levels
) {
12825 LOCAL_SET_GL_ERROR(
12826 GL_INVALID_VALUE
, "glTexStorage2DEXT", "dimensions out of range");
12829 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
12831 if (!texture_ref
) {
12832 LOCAL_SET_GL_ERROR(
12833 GL_INVALID_OPERATION
,
12834 "glTexStorage2DEXT", "unknown texture for target");
12837 Texture
* texture
= texture_ref
->texture();
12838 if (texture
->IsAttachedToFramebuffer()) {
12839 framebuffer_state_
.clear_state_dirty
= true;
12841 if (texture
->IsImmutable()) {
12842 LOCAL_SET_GL_ERROR(
12843 GL_INVALID_OPERATION
,
12844 "glTexStorage2DEXT", "texture is immutable");
12848 GLenum format
= ExtractFormatFromStorageFormat(internal_format
);
12849 GLenum type
= ExtractTypeFromStorageFormat(internal_format
);
12852 GLsizei level_width
= width
;
12853 GLsizei level_height
= height
;
12854 uint32 estimated_size
= 0;
12855 for (int ii
= 0; ii
< levels
; ++ii
) {
12856 uint32 level_size
= 0;
12857 if (!GLES2Util::ComputeImageDataSizes(
12858 level_width
, level_height
, 1, format
, type
, state_
.unpack_alignment
,
12859 &estimated_size
, NULL
, NULL
) ||
12860 !SafeAddUint32(estimated_size
, level_size
, &estimated_size
)) {
12861 LOCAL_SET_GL_ERROR(
12862 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "dimensions too large");
12865 level_width
= std::max(1, level_width
>> 1);
12866 level_height
= std::max(1, level_height
>> 1);
12868 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
12869 LOCAL_SET_GL_ERROR(
12870 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "out of memory");
12875 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
12876 glTexStorage2DEXT(target
, levels
, internal_format
, width
, height
);
12877 GLenum error
= LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
12878 if (error
== GL_NO_ERROR
) {
12879 GLsizei level_width
= width
;
12880 GLsizei level_height
= height
;
12881 for (int ii
= 0; ii
< levels
; ++ii
) {
12882 GLenum cur_format
= feature_info_
->IsES3Enabled() ?
12883 internal_format
: format
;
12884 texture_manager()->SetLevelInfo(texture_ref
, target
, ii
, cur_format
,
12885 level_width
, level_height
, 1, 0, format
,
12886 type
, gfx::Rect());
12887 level_width
= std::max(1, level_width
>> 1);
12888 level_height
= std::max(1, level_height
>> 1);
12890 texture
->SetImmutable(true);
12894 error::Error
GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
12895 uint32 immediate_data_size
,
12896 const void* cmd_data
) {
12897 return error::kUnknownCommand
;
12900 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target
,
12901 const GLbyte
* data
) {
12902 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
12903 "context", logger_
.GetLogPrefix(),
12904 "mailbox[0]", static_cast<unsigned char>(data
[0]));
12906 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
12908 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref
, target
, data
);
12911 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id
,
12912 GLenum target
, const GLbyte
* data
) {
12913 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
12914 "context", logger_
.GetLogPrefix(),
12915 "mailbox[0]", static_cast<unsigned char>(data
[0]));
12917 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id
),
12921 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name
,
12922 TextureRef
* texture_ref
, GLenum target
, const GLbyte
* data
) {
12923 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
12924 DLOG_IF(ERROR
, !mailbox
.Verify()) << func_name
<< " was passed a "
12925 "mailbox that was not generated by "
12926 "GenMailboxCHROMIUM.";
12928 if (!texture_ref
) {
12929 LOCAL_SET_GL_ERROR(
12930 GL_INVALID_OPERATION
, func_name
.c_str(), "unknown texture for target");
12934 Texture
* produced
= texture_manager()->Produce(texture_ref
);
12936 LOCAL_SET_GL_ERROR(
12937 GL_INVALID_OPERATION
, func_name
.c_str(), "invalid texture");
12941 if (produced
->target() != target
) {
12942 LOCAL_SET_GL_ERROR(
12943 GL_INVALID_OPERATION
, func_name
.c_str(), "invalid target");
12947 group_
->mailbox_manager()->ProduceTexture(mailbox
, produced
);
12950 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target
,
12951 const GLbyte
* data
) {
12952 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
12953 "context", logger_
.GetLogPrefix(),
12954 "mailbox[0]", static_cast<unsigned char>(data
[0]));
12955 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
12956 DLOG_IF(ERROR
, !mailbox
.Verify()) << "ConsumeTextureCHROMIUM was passed a "
12957 "mailbox that was not generated by "
12958 "GenMailboxCHROMIUM.";
12960 scoped_refptr
<TextureRef
> texture_ref
=
12961 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
12962 if (!texture_ref
.get()) {
12963 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12964 "glConsumeTextureCHROMIUM",
12965 "unknown texture for target");
12968 GLuint client_id
= texture_ref
->client_id();
12970 LOCAL_SET_GL_ERROR(
12971 GL_INVALID_OPERATION
,
12972 "glConsumeTextureCHROMIUM", "unknown texture for target");
12975 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(mailbox
);
12977 LOCAL_SET_GL_ERROR(
12978 GL_INVALID_OPERATION
,
12979 "glConsumeTextureCHROMIUM", "invalid mailbox name");
12982 if (texture
->target() != target
) {
12983 LOCAL_SET_GL_ERROR(
12984 GL_INVALID_OPERATION
,
12985 "glConsumeTextureCHROMIUM", "invalid target");
12989 DeleteTexturesHelper(1, &client_id
);
12990 texture_ref
= texture_manager()->Consume(client_id
, texture
);
12991 glBindTexture(target
, texture_ref
->service_id());
12993 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
12994 unit
.bind_target
= target
;
12996 case GL_TEXTURE_2D
:
12997 unit
.bound_texture_2d
= texture_ref
;
12999 case GL_TEXTURE_CUBE_MAP
:
13000 unit
.bound_texture_cube_map
= texture_ref
;
13002 case GL_TEXTURE_EXTERNAL_OES
:
13003 unit
.bound_texture_external_oes
= texture_ref
;
13005 case GL_TEXTURE_RECTANGLE_ARB
:
13006 unit
.bound_texture_rectangle_arb
= texture_ref
;
13009 NOTREACHED(); // Validation should prevent us getting here.
13014 void GLES2DecoderImpl::EnsureTextureForClientId(
13016 GLuint client_id
) {
13017 TextureRef
* texture_ref
= GetTexture(client_id
);
13018 if (!texture_ref
) {
13020 glGenTextures(1, &service_id
);
13021 DCHECK_NE(0u, service_id
);
13022 texture_ref
= CreateTexture(client_id
, service_id
);
13023 texture_manager()->SetTarget(texture_ref
, target
);
13024 glBindTexture(target
, service_id
);
13025 RestoreCurrentTextureBindings(&state_
, target
);
13029 // If CreateAndConsumeTexture fails we still need to ensure that the client_id
13030 // provided is associated with a service_id/TextureRef for consistency, even if
13031 // the resulting texture is incomplete.
13032 error::Error
GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
13033 uint32_t immediate_data_size
,
13034 const void* cmd_data
) {
13035 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate
& c
=
13037 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate
*>(
13039 GLenum target
= static_cast<GLenum
>(c
.target
);
13040 uint32_t data_size
;
13041 if (!ComputeDataSize(1, sizeof(GLbyte
), 64, &data_size
)) {
13042 return error::kOutOfBounds
;
13044 if (data_size
> immediate_data_size
) {
13045 return error::kOutOfBounds
;
13047 const GLbyte
* mailbox
=
13048 GetImmediateDataAs
<const GLbyte
*>(c
, data_size
, immediate_data_size
);
13049 if (!validators_
->texture_bind_target
.IsValid(target
)) {
13050 LOCAL_SET_GL_ERROR_INVALID_ENUM(
13051 "glCreateAndConsumeTextureCHROMIUM", target
, "target");
13052 return error::kNoError
;
13054 if (mailbox
== NULL
) {
13055 return error::kOutOfBounds
;
13057 uint32_t client_id
= c
.client_id
;
13058 DoCreateAndConsumeTextureCHROMIUM(target
, mailbox
, client_id
);
13059 return error::kNoError
;
13062 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target
,
13063 const GLbyte
* data
, GLuint client_id
) {
13064 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
13065 "context", logger_
.GetLogPrefix(),
13066 "mailbox[0]", static_cast<unsigned char>(data
[0]));
13067 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
13068 DLOG_IF(ERROR
, !mailbox
.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
13069 "passed a mailbox that was not "
13070 "generated by GenMailboxCHROMIUM.";
13072 TextureRef
* texture_ref
= GetTexture(client_id
);
13074 // No need to call EnsureTextureForClientId here, the client_id already has
13075 // an associated texture.
13076 LOCAL_SET_GL_ERROR(
13077 GL_INVALID_OPERATION
,
13078 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
13081 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(mailbox
);
13083 EnsureTextureForClientId(target
, client_id
);
13084 LOCAL_SET_GL_ERROR(
13085 GL_INVALID_OPERATION
,
13086 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
13090 if (texture
->target() != target
) {
13091 EnsureTextureForClientId(target
, client_id
);
13092 LOCAL_SET_GL_ERROR(
13093 GL_INVALID_OPERATION
,
13094 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
13098 texture_ref
= texture_manager()->Consume(client_id
, texture
);
13101 bool GLES2DecoderImpl::DoIsValuebufferCHROMIUM(GLuint client_id
) {
13102 const Valuebuffer
* valuebuffer
= GetValuebuffer(client_id
);
13103 return valuebuffer
&& valuebuffer
->IsValid();
13106 void GLES2DecoderImpl::DoBindValueBufferCHROMIUM(GLenum target
,
13107 GLuint client_id
) {
13108 Valuebuffer
* valuebuffer
= NULL
;
13109 if (client_id
!= 0) {
13110 valuebuffer
= GetValuebuffer(client_id
);
13111 if (!valuebuffer
) {
13112 if (!group_
->bind_generates_resource()) {
13113 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glBindValuebufferCHROMIUM",
13114 "id not generated by glBindValuebufferCHROMIUM");
13118 // It's a new id so make a valuebuffer for it.
13119 CreateValuebuffer(client_id
);
13120 valuebuffer
= GetValuebuffer(client_id
);
13122 valuebuffer
->MarkAsValid();
13124 state_
.bound_valuebuffer
= valuebuffer
;
13127 void GLES2DecoderImpl::DoSubscribeValueCHROMIUM(GLenum target
,
13128 GLenum subscription
) {
13129 if (!CheckCurrentValuebuffer("glSubscribeValueCHROMIUM")) {
13132 state_
.bound_valuebuffer
.get()->AddSubscription(subscription
);
13135 void GLES2DecoderImpl::DoPopulateSubscribedValuesCHROMIUM(GLenum target
) {
13136 if (!CheckCurrentValuebuffer("glPopulateSubscribedValuesCHROMIUM")) {
13139 valuebuffer_manager()->UpdateValuebufferState(state_
.bound_valuebuffer
.get());
13142 void GLES2DecoderImpl::DoUniformValueBufferCHROMIUM(GLint location
,
13144 GLenum subscription
) {
13145 if (!CheckCurrentValuebufferForSubscription(
13146 subscription
, "glPopulateSubscribedValuesCHROMIUM")) {
13149 if (!CheckSubscriptionTarget(location
, subscription
,
13150 "glPopulateSubscribedValuesCHROMIUM")) {
13153 const ValueState
* state
=
13154 state_
.bound_valuebuffer
.get()->GetState(subscription
);
13156 switch (subscription
) {
13157 case GL_MOUSE_POSITION_CHROMIUM
:
13158 DoUniform2iv(location
, 1, state
->int_value
);
13161 NOTREACHED() << "Unhandled uniform subscription target "
13168 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
13169 GLsizei length
, const GLchar
* marker
) {
13173 debug_marker_manager_
.SetMarker(
13174 length
? std::string(marker
, length
) : std::string(marker
));
13177 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
13178 GLsizei
/*length*/, const GLchar
* /*marker*/) {
13181 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
13184 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
13185 GLenum target
, GLint image_id
) {
13186 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
13188 if (target
== GL_TEXTURE_CUBE_MAP
) {
13189 LOCAL_SET_GL_ERROR(
13191 "glBindTexImage2DCHROMIUM", "invalid target");
13195 // Default target might be conceptually valid, but disallow it to avoid
13197 TextureRef
* texture_ref
=
13198 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
13199 if (!texture_ref
) {
13200 LOCAL_SET_GL_ERROR(
13201 GL_INVALID_OPERATION
,
13202 "glBindTexImage2DCHROMIUM", "no texture bound");
13206 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
13208 LOCAL_SET_GL_ERROR(
13209 GL_INVALID_OPERATION
,
13210 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
13215 ScopedGLErrorSuppressor
suppressor(
13216 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
13217 if (!gl_image
->BindTexImage(target
)) {
13218 LOCAL_SET_GL_ERROR(
13219 GL_INVALID_OPERATION
,
13220 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
13225 gfx::Size size
= gl_image
->GetSize();
13226 texture_manager()->SetLevelInfo(
13227 texture_ref
, target
, 0, gl_image
->GetInternalFormat(), size
.width(),
13228 size
.height(), 1, 0, gl_image
->GetInternalFormat(), GL_UNSIGNED_BYTE
,
13230 texture_manager()->SetLevelImage(texture_ref
, target
, 0, gl_image
);
13233 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
13234 GLenum target
, GLint image_id
) {
13235 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
13237 // Default target might be conceptually valid, but disallow it to avoid
13239 TextureRef
* texture_ref
=
13240 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
13241 if (!texture_ref
) {
13242 LOCAL_SET_GL_ERROR(
13243 GL_INVALID_OPERATION
,
13244 "glReleaseTexImage2DCHROMIUM", "no texture bound");
13248 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
13250 LOCAL_SET_GL_ERROR(
13251 GL_INVALID_OPERATION
,
13252 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
13256 // Do nothing when image is not currently bound.
13257 if (texture_ref
->texture()->GetLevelImage(target
, 0) != gl_image
)
13261 ScopedGLErrorSuppressor
suppressor(
13262 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
13263 gl_image
->ReleaseTexImage(target
);
13266 texture_manager()->SetLevelInfo(
13267 texture_ref
, target
, 0, gl_image
->GetInternalFormat(), 0, 0, 1, 0,
13268 gl_image
->GetInternalFormat(), GL_UNSIGNED_BYTE
, gfx::Rect());
13271 error::Error
GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
13272 uint32 immediate_data_size
,
13273 const void* cmd_data
) {
13274 const gles2::cmds::TraceBeginCHROMIUM
& c
=
13275 *static_cast<const gles2::cmds::TraceBeginCHROMIUM
*>(cmd_data
);
13276 Bucket
* category_bucket
= GetBucket(c
.category_bucket_id
);
13277 Bucket
* name_bucket
= GetBucket(c
.name_bucket_id
);
13278 if (!category_bucket
|| category_bucket
->size() == 0 ||
13279 !name_bucket
|| name_bucket
->size() == 0) {
13280 return error::kInvalidArguments
;
13283 std::string category_name
;
13284 std::string trace_name
;
13285 if (!category_bucket
->GetAsString(&category_name
) ||
13286 !name_bucket
->GetAsString(&trace_name
)) {
13287 return error::kInvalidArguments
;
13290 debug_marker_manager_
.PushGroup(trace_name
);
13291 if (!gpu_tracer_
->Begin(category_name
, trace_name
, kTraceCHROMIUM
)) {
13292 LOCAL_SET_GL_ERROR(
13293 GL_INVALID_OPERATION
,
13294 "glTraceBeginCHROMIUM", "unable to create begin trace");
13295 return error::kNoError
;
13297 return error::kNoError
;
13300 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
13301 debug_marker_manager_
.PopGroup();
13302 if (!gpu_tracer_
->End(kTraceCHROMIUM
)) {
13303 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
13304 "glTraceEndCHROMIUM", "no trace begin found");
13309 void GLES2DecoderImpl::DoDrawBuffersEXT(
13310 GLsizei count
, const GLenum
* bufs
) {
13311 if (count
> static_cast<GLsizei
>(group_
->max_draw_buffers())) {
13312 LOCAL_SET_GL_ERROR(
13314 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
13318 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
13320 for (GLsizei i
= 0; i
< count
; ++i
) {
13321 if (bufs
[i
] != static_cast<GLenum
>(GL_COLOR_ATTACHMENT0
+ i
) &&
13322 bufs
[i
] != GL_NONE
) {
13323 LOCAL_SET_GL_ERROR(
13324 GL_INVALID_OPERATION
,
13325 "glDrawBuffersEXT",
13326 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
13330 glDrawBuffersARB(count
, bufs
);
13331 framebuffer
->SetDrawBuffers(count
, bufs
);
13332 } else { // backbuffer
13334 (bufs
[0] != GL_BACK
&& bufs
[0] != GL_NONE
)) {
13335 LOCAL_SET_GL_ERROR(
13336 GL_INVALID_OPERATION
,
13337 "glDrawBuffersEXT",
13338 "more than one buffer or bufs not GL_NONE or GL_BACK");
13341 GLenum mapped_buf
= bufs
[0];
13342 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
13343 bufs
[0] == GL_BACK
) {
13344 mapped_buf
= GL_COLOR_ATTACHMENT0
;
13346 glDrawBuffersARB(count
, &mapped_buf
);
13347 group_
->set_draw_buffer(bufs
[0]);
13351 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current
, GLenum other
) {
13352 MarkContextLost(GetContextLostReasonFromResetStatus(current
));
13353 group_
->LoseContexts(GetContextLostReasonFromResetStatus(other
));
13354 reset_by_robustness_extension_
= true;
13357 void GLES2DecoderImpl::DoFlushDriverCachesCHROMIUM(void) {
13358 // On Adreno Android devices we need to use a workaround to force caches to
13360 if (feature_info_
->workarounds().unbind_egl_context_to_flush_driver_caches
) {
13361 context_
->ReleaseCurrent(nullptr);
13362 context_
->MakeCurrent(surface_
.get());
13366 void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode
,
13367 const GLfloat
* matrix
) {
13368 DCHECK(matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
||
13369 matrix_mode
== GL_PATH_MODELVIEW_CHROMIUM
);
13370 if (!features().chromium_path_rendering
) {
13371 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
13372 "glMatrixLoadfCHROMIUM",
13373 "function not available");
13377 GLfloat
* target_matrix
= matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
13378 ? state_
.projection_matrix
13379 : state_
.modelview_matrix
;
13380 memcpy(target_matrix
, matrix
, sizeof(GLfloat
) * 16);
13381 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
13382 // since the values of the _NV and _CHROMIUM tokens match.
13383 glMatrixLoadfEXT(matrix_mode
, matrix
);
13386 void GLES2DecoderImpl::DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode
) {
13387 DCHECK(matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
||
13388 matrix_mode
== GL_PATH_MODELVIEW_CHROMIUM
);
13390 if (!features().chromium_path_rendering
) {
13391 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
13392 "glMatrixLoadIdentityCHROMIUM",
13393 "function not available");
13397 GLfloat
* target_matrix
= matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
13398 ? state_
.projection_matrix
13399 : state_
.modelview_matrix
;
13400 memcpy(target_matrix
, kIdentityMatrix
, sizeof(kIdentityMatrix
));
13401 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
13402 // since the values of the _NV and _CHROMIUM tokens match.
13403 glMatrixLoadIdentityEXT(matrix_mode
);
13406 bool GLES2DecoderImpl::ValidateAsyncTransfer(
13407 const char* function_name
,
13408 TextureRef
* texture_ref
,
13411 const void * data
) {
13412 // We only support async uploads to 2D textures for now.
13413 if (GL_TEXTURE_2D
!= target
) {
13414 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
13417 // We only support uploads to level zero for now.
13419 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "level != 0");
13422 // A transfer buffer must be bound, even for asyncTexImage2D.
13423 if (data
== NULL
) {
13424 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
, "buffer == 0");
13427 // We only support one async transfer in progress.
13428 if (!texture_ref
||
13429 async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
13430 LOCAL_SET_GL_ERROR(
13431 GL_INVALID_OPERATION
,
13432 function_name
, "transfer already in progress");
13438 base::Closure
GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
13439 uint32 async_upload_token
,
13440 uint32 sync_data_shm_id
,
13441 uint32 sync_data_shm_offset
) {
13442 scoped_refptr
<gpu::Buffer
> buffer
= GetSharedMemoryBuffer(sync_data_shm_id
);
13443 if (!buffer
.get() ||
13444 !buffer
->GetDataAddress(sync_data_shm_offset
, sizeof(AsyncUploadSync
)))
13445 return base::Closure();
13447 AsyncMemoryParams
mem_params(buffer
,
13448 sync_data_shm_offset
,
13449 sizeof(AsyncUploadSync
));
13451 scoped_refptr
<AsyncUploadTokenCompletionObserver
> observer(
13452 new AsyncUploadTokenCompletionObserver(async_upload_token
));
13455 &AsyncPixelTransferManager::AsyncNotifyCompletion
,
13456 base::Unretained(GetAsyncPixelTransferManager()),
13461 error::Error
GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
13462 uint32 immediate_data_size
,
13463 const void* cmd_data
) {
13464 const gles2::cmds::AsyncTexImage2DCHROMIUM
& c
=
13465 *static_cast<const gles2::cmds::AsyncTexImage2DCHROMIUM
*>(cmd_data
);
13466 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
13467 GLenum target
= static_cast<GLenum
>(c
.target
);
13468 GLint level
= static_cast<GLint
>(c
.level
);
13469 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
13470 GLsizei width
= static_cast<GLsizei
>(c
.width
);
13471 GLsizei height
= static_cast<GLsizei
>(c
.height
);
13472 GLint border
= static_cast<GLint
>(c
.border
);
13473 GLenum format
= static_cast<GLenum
>(c
.format
);
13474 GLenum type
= static_cast<GLenum
>(c
.type
);
13475 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
13476 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
13477 uint32 pixels_size
;
13478 uint32 async_upload_token
= static_cast<uint32
>(c
.async_upload_token
);
13479 uint32 sync_data_shm_id
= static_cast<uint32
>(c
.sync_data_shm_id
);
13480 uint32 sync_data_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
13482 base::ScopedClosureRunner scoped_completion_callback
;
13483 if (async_upload_token
) {
13484 base::Closure completion_closure
=
13485 AsyncUploadTokenCompletionClosure(async_upload_token
,
13487 sync_data_shm_offset
);
13488 if (completion_closure
.is_null())
13489 return error::kInvalidArguments
;
13491 scoped_completion_callback
.Reset(completion_closure
);
13494 // TODO(epenner): Move this and copies of this memory validation
13495 // into ValidateTexImage2D step.
13496 if (!GLES2Util::ComputeImageDataSizes(
13497 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
13499 return error::kOutOfBounds
;
13501 const void* pixels
= NULL
;
13502 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
13503 pixels
= GetSharedMemoryAs
<const void*>(
13504 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
13506 return error::kOutOfBounds
;
13510 TextureManager::DoTexImageArguments args
= {
13511 target
, level
, internal_format
, width
, height
, 1, border
, format
, type
,
13512 pixels
, pixels_size
, TextureManager::DoTexImageArguments::kTexImage2D
};
13513 TextureRef
* texture_ref
;
13514 // All the normal glTexSubImage2D validation.
13515 if (!texture_manager()->ValidateTexImage(
13516 &state_
, "glAsyncTexImage2DCHROMIUM", args
, &texture_ref
)) {
13517 return error::kNoError
;
13520 // Extra async validation.
13521 Texture
* texture
= texture_ref
->texture();
13522 if (!ValidateAsyncTransfer(
13523 "glAsyncTexImage2DCHROMIUM", texture_ref
, target
, level
, pixels
))
13524 return error::kNoError
;
13526 // Don't allow async redefinition of a textures.
13527 if (texture
->IsDefined()) {
13528 LOCAL_SET_GL_ERROR(
13529 GL_INVALID_OPERATION
,
13530 "glAsyncTexImage2DCHROMIUM", "already defined");
13531 return error::kNoError
;
13534 if (!EnsureGPUMemoryAvailable(pixels_size
)) {
13535 LOCAL_SET_GL_ERROR(
13536 GL_OUT_OF_MEMORY
, "glAsyncTexImage2DCHROMIUM", "out of memory");
13537 return error::kNoError
;
13540 // Setup the parameters.
13541 AsyncTexImage2DParams tex_params
= {
13542 target
, level
, static_cast<GLenum
>(internal_format
),
13543 width
, height
, border
, format
, type
};
13544 AsyncMemoryParams
mem_params(
13545 GetSharedMemoryBuffer(c
.pixels_shm_id
), c
.pixels_shm_offset
, pixels_size
);
13547 // Set up the async state if needed, and make the texture
13548 // immutable so the async state stays valid. The level info
13549 // is set up lazily when the transfer completes.
13550 AsyncPixelTransferDelegate
* delegate
=
13551 async_pixel_transfer_manager_
->CreatePixelTransferDelegate(texture_ref
,
13553 texture
->SetImmutable(true);
13555 delegate
->AsyncTexImage2D(
13558 base::Bind(&TextureManager::SetLevelInfoFromParams
,
13559 // The callback is only invoked if the transfer delegate still
13560 // exists, which implies through manager->texture_ref->state
13561 // ownership that both of these pointers are valid.
13562 base::Unretained(texture_manager()),
13563 base::Unretained(texture_ref
),
13565 return error::kNoError
;
13568 error::Error
GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
13569 uint32 immediate_data_size
,
13570 const void* cmd_data
) {
13571 const gles2::cmds::AsyncTexSubImage2DCHROMIUM
& c
=
13572 *static_cast<const gles2::cmds::AsyncTexSubImage2DCHROMIUM
*>(cmd_data
);
13573 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
13574 GLenum target
= static_cast<GLenum
>(c
.target
);
13575 GLint level
= static_cast<GLint
>(c
.level
);
13576 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
13577 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
13578 GLsizei width
= static_cast<GLsizei
>(c
.width
);
13579 GLsizei height
= static_cast<GLsizei
>(c
.height
);
13580 GLenum format
= static_cast<GLenum
>(c
.format
);
13581 GLenum type
= static_cast<GLenum
>(c
.type
);
13582 uint32 async_upload_token
= static_cast<uint32
>(c
.async_upload_token
);
13583 uint32 sync_data_shm_id
= static_cast<uint32
>(c
.sync_data_shm_id
);
13584 uint32 sync_data_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
13586 base::ScopedClosureRunner scoped_completion_callback
;
13587 if (async_upload_token
) {
13588 base::Closure completion_closure
=
13589 AsyncUploadTokenCompletionClosure(async_upload_token
,
13591 sync_data_shm_offset
);
13592 if (completion_closure
.is_null())
13593 return error::kInvalidArguments
;
13595 scoped_completion_callback
.Reset(completion_closure
);
13598 // TODO(epenner): Move this and copies of this memory validation
13599 // into ValidateTexSubImage2D step.
13601 if (!GLES2Util::ComputeImageDataSizes(
13602 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &data_size
,
13604 return error::kOutOfBounds
;
13606 const void* pixels
= GetSharedMemoryAs
<const void*>(
13607 c
.data_shm_id
, c
.data_shm_offset
, data_size
);
13609 // All the normal glTexSubImage2D validation.
13610 error::Error error
= error::kNoError
;
13611 if (!ValidateTexSubImage2D(&error
, "glAsyncTexSubImage2DCHROMIUM",
13612 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
)) {
13616 // Extra async validation.
13617 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
13619 Texture
* texture
= texture_ref
->texture();
13620 if (!ValidateAsyncTransfer(
13621 "glAsyncTexSubImage2DCHROMIUM", texture_ref
, target
, level
, pixels
))
13622 return error::kNoError
;
13624 // Guarantee async textures are always 'cleared' as follows:
13625 // - AsyncTexImage2D can not redefine an existing texture
13626 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
13627 // - AsyncTexSubImage2D clears synchronously if not already cleared.
13628 // - Textures become immutable after an async call.
13629 // This way we know in all cases that an async texture is always clear.
13630 if (!texture
->SafeToRenderFrom()) {
13631 if (!texture_manager()->ClearTextureLevel(this, texture_ref
,
13633 LOCAL_SET_GL_ERROR(
13635 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
13636 return error::kNoError
;
13640 // Setup the parameters.
13641 AsyncTexSubImage2DParams tex_params
= {target
, level
, xoffset
, yoffset
,
13642 width
, height
, format
, type
};
13643 AsyncMemoryParams
mem_params(
13644 GetSharedMemoryBuffer(c
.data_shm_id
), c
.data_shm_offset
, data_size
);
13645 AsyncPixelTransferDelegate
* delegate
=
13646 async_pixel_transfer_manager_
->GetPixelTransferDelegate(texture_ref
);
13648 // TODO(epenner): We may want to enforce exclusive use
13649 // of async APIs in which case this should become an error,
13650 // (the texture should have been async defined).
13651 AsyncTexImage2DParams define_params
= {target
, level
,
13653 texture
->GetLevelSize(
13654 target
, level
, &define_params
.width
, &define_params
.height
, nullptr);
13655 texture
->GetLevelType(
13656 target
, level
, &define_params
.type
, &define_params
.internal_format
);
13657 // Set up the async state if needed, and make the texture
13658 // immutable so the async state stays valid.
13659 delegate
= async_pixel_transfer_manager_
->CreatePixelTransferDelegate(
13660 texture_ref
, define_params
);
13661 texture
->SetImmutable(true);
13664 delegate
->AsyncTexSubImage2D(tex_params
, mem_params
);
13665 return error::kNoError
;
13668 error::Error
GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
13669 uint32 immediate_data_size
,
13670 const void* cmd_data
) {
13671 const gles2::cmds::WaitAsyncTexImage2DCHROMIUM
& c
=
13672 *static_cast<const gles2::cmds::WaitAsyncTexImage2DCHROMIUM
*>(cmd_data
);
13673 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
13674 GLenum target
= static_cast<GLenum
>(c
.target
);
13676 if (GL_TEXTURE_2D
!= target
) {
13677 LOCAL_SET_GL_ERROR(
13678 GL_INVALID_ENUM
, "glWaitAsyncTexImage2DCHROMIUM", "target");
13679 return error::kNoError
;
13681 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
13683 if (!texture_ref
) {
13684 LOCAL_SET_GL_ERROR(
13685 GL_INVALID_OPERATION
,
13686 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
13687 return error::kNoError
;
13689 AsyncPixelTransferDelegate
* delegate
=
13690 async_pixel_transfer_manager_
->GetPixelTransferDelegate(texture_ref
);
13692 LOCAL_SET_GL_ERROR(
13693 GL_INVALID_OPERATION
,
13694 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
13695 return error::kNoError
;
13697 delegate
->WaitForTransferCompletion();
13698 ProcessFinishedAsyncTransfers();
13699 return error::kNoError
;
13702 error::Error
GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
13703 uint32 immediate_data_size
,
13704 const void* data
) {
13705 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
13707 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
13708 ProcessFinishedAsyncTransfers();
13709 return error::kNoError
;
13712 error::Error
GLES2DecoderImpl::HandleUniformBlockBinding(
13713 uint32_t immediate_data_size
, const void* cmd_data
) {
13714 if (!unsafe_es3_apis_enabled())
13715 return error::kUnknownCommand
;
13716 const gles2::cmds::UniformBlockBinding
& c
=
13717 *static_cast<const gles2::cmds::UniformBlockBinding
*>(cmd_data
);
13718 GLuint client_id
= c
.program
;
13719 GLuint index
= static_cast<GLuint
>(c
.index
);
13720 GLuint binding
= static_cast<GLuint
>(c
.binding
);
13721 Program
* program
= GetProgramInfoNotShader(
13722 client_id
, "glUniformBlockBinding");
13724 return error::kNoError
;
13726 GLuint service_id
= program
->service_id();
13727 glUniformBlockBinding(service_id
, index
, binding
);
13728 return error::kNoError
;
13731 error::Error
GLES2DecoderImpl::HandleClientWaitSync(
13732 uint32_t immediate_data_size
, const void* cmd_data
) {
13733 if (!unsafe_es3_apis_enabled())
13734 return error::kUnknownCommand
;
13735 const gles2::cmds::ClientWaitSync
& c
=
13736 *static_cast<const gles2::cmds::ClientWaitSync
*>(cmd_data
);
13737 GLuint sync
= static_cast<GLuint
>(c
.sync
);
13738 GLbitfield flags
= static_cast<GLbitfield
>(c
.flags
);
13739 GLuint64 timeout
= GLES2Util::MapTwoUint32ToUint64(c
.timeout_0
, c
.timeout_1
);
13740 typedef cmds::ClientWaitSync::Result Result
;
13741 Result
* result_dst
= GetSharedMemoryAs
<Result
*>(
13742 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result_dst
));
13744 return error::kOutOfBounds
;
13746 if (*result_dst
!= GL_WAIT_FAILED
) {
13747 return error::kInvalidArguments
;
13749 GLsync service_sync
= 0;
13750 if (!group_
->GetSyncServiceId(sync
, &service_sync
)) {
13751 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "ClientWaitSync", "invalid sync");
13752 return error::kNoError
;
13754 *result_dst
= glClientWaitSync(service_sync
, flags
, timeout
);
13755 return error::kNoError
;
13758 error::Error
GLES2DecoderImpl::HandleWaitSync(
13759 uint32_t immediate_data_size
, const void* cmd_data
) {
13760 if (!unsafe_es3_apis_enabled())
13761 return error::kUnknownCommand
;
13762 const gles2::cmds::WaitSync
& c
=
13763 *static_cast<const gles2::cmds::WaitSync
*>(cmd_data
);
13764 GLuint sync
= static_cast<GLuint
>(c
.sync
);
13765 GLbitfield flags
= static_cast<GLbitfield
>(c
.flags
);
13766 GLuint64 timeout
= GLES2Util::MapTwoUint32ToUint64(c
.timeout_0
, c
.timeout_1
);
13767 GLsync service_sync
= 0;
13768 if (!group_
->GetSyncServiceId(sync
, &service_sync
)) {
13769 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "WaitSync", "invalid sync");
13770 return error::kNoError
;
13772 glWaitSync(service_sync
, flags
, timeout
);
13773 return error::kNoError
;
13776 error::Error
GLES2DecoderImpl::HandleGetInternalformativ(
13777 uint32_t immediate_data_size
, const void* cmd_data
) {
13778 if (!unsafe_es3_apis_enabled())
13779 return error::kUnknownCommand
;
13780 const gles2::cmds::GetInternalformativ
& c
=
13781 *static_cast<const gles2::cmds::GetInternalformativ
*>(cmd_data
);
13782 GLenum target
= static_cast<GLenum
>(c
.target
);
13783 GLenum format
= static_cast<GLenum
>(c
.format
);
13784 GLenum pname
= static_cast<GLenum
>(c
.pname
);
13785 if (!validators_
->render_buffer_target
.IsValid(target
)) {
13786 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", target
, "target");
13787 return error::kNoError
;
13789 if (!validators_
->render_buffer_format
.IsValid(format
)) {
13790 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", format
, "format");
13791 return error::kNoError
;
13793 if (!validators_
->internal_format_parameter
.IsValid(pname
)) {
13794 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", pname
, "pname");
13795 return error::kNoError
;
13797 typedef cmds::GetInternalformativ::Result Result
;
13798 GLsizei num_values
= 0;
13800 case GL_NUM_SAMPLE_COUNTS
:
13806 glGetInternalformativ(target
, format
, GL_NUM_SAMPLE_COUNTS
, 1, &value
);
13807 num_values
= static_cast<GLsizei
>(value
);
13814 Result
* result
= GetSharedMemoryAs
<Result
*>(
13815 c
.params_shm_id
, c
.params_shm_offset
, Result::ComputeSize(num_values
));
13816 GLint
* params
= result
? result
->GetData() : NULL
;
13817 if (params
== NULL
) {
13818 return error::kOutOfBounds
;
13820 // Check that the client initialized the result.
13821 if (result
->size
!= 0) {
13822 return error::kInvalidArguments
;
13824 glGetInternalformativ(target
, format
, pname
, num_values
, params
);
13825 result
->SetNumResults(num_values
);
13826 return error::kNoError
;
13829 error::Error
GLES2DecoderImpl::HandleMapBufferRange(
13830 uint32_t immediate_data_size
, const void* cmd_data
) {
13831 if (!unsafe_es3_apis_enabled()) {
13832 return error::kUnknownCommand
;
13834 const gles2::cmds::MapBufferRange
& c
=
13835 *static_cast<const gles2::cmds::MapBufferRange
*>(cmd_data
);
13836 GLenum target
= static_cast<GLenum
>(c
.target
);
13837 GLbitfield access
= static_cast<GLbitfield
>(c
.access
);
13838 GLintptr offset
= static_cast<GLintptr
>(c
.offset
);
13839 GLsizeiptr size
= static_cast<GLsizeiptr
>(c
.size
);
13841 typedef cmds::MapBufferRange::Result Result
;
13842 Result
* result
= GetSharedMemoryAs
<Result
*>(
13843 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
13845 return error::kOutOfBounds
;
13847 if (*result
!= 0) {
13849 return error::kInvalidArguments
;
13852 GetSharedMemoryAs
<int8_t*>(c
.data_shm_id
, c
.data_shm_offset
, size
);
13854 return error::kOutOfBounds
;
13857 GLbitfield mask
= GL_MAP_INVALIDATE_BUFFER_BIT
;
13858 if ((access
& mask
) == mask
) {
13859 // TODO(zmo): To be on the safe side, always map
13860 // GL_MAP_INVALIDATE_BUFFER_BIT to GL_MAP_INVALIDATE_RANGE_BIT.
13861 access
= (access
& ~GL_MAP_INVALIDATE_BUFFER_BIT
);
13862 access
= (access
| GL_MAP_INVALIDATE_RANGE_BIT
);
13864 // TODO(zmo): Always filter out GL_MAP_UNSYNCHRONIZED_BIT to get rid of
13865 // undefined behaviors.
13866 mask
= GL_MAP_READ_BIT
| GL_MAP_UNSYNCHRONIZED_BIT
;
13867 if ((access
& mask
) == mask
) {
13868 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "MapBufferRange",
13869 "incompatible access bits");
13870 return error::kNoError
;
13872 access
= (access
& ~GL_MAP_UNSYNCHRONIZED_BIT
);
13873 if ((access
& GL_MAP_WRITE_BIT
) == GL_MAP_WRITE_BIT
&&
13874 (access
& GL_MAP_INVALIDATE_RANGE_BIT
) == 0) {
13875 access
= (access
| GL_MAP_READ_BIT
);
13877 void* ptr
= glMapBufferRange(target
, offset
, size
, access
);
13878 if (ptr
== nullptr) {
13879 return error::kNoError
;
13881 Buffer
* buffer
= buffer_manager()->GetBufferInfoForTarget(&state_
, target
);
13883 buffer
->SetMappedRange(offset
, size
, access
, ptr
,
13884 GetSharedMemoryBuffer(c
.data_shm_id
));
13885 if ((access
& GL_MAP_INVALIDATE_RANGE_BIT
) == 0) {
13886 memcpy(mem
, ptr
, size
);
13889 return error::kNoError
;
13892 error::Error
GLES2DecoderImpl::HandleUnmapBuffer(
13893 uint32_t immediate_data_size
, const void* cmd_data
) {
13894 if (!unsafe_es3_apis_enabled()) {
13895 return error::kUnknownCommand
;
13897 const gles2::cmds::UnmapBuffer
& c
=
13898 *static_cast<const gles2::cmds::UnmapBuffer
*>(cmd_data
);
13899 GLenum target
= static_cast<GLenum
>(c
.target
);
13901 Buffer
* buffer
= buffer_manager()->GetBufferInfoForTarget(&state_
, target
);
13903 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "UnmapBuffer", "no buffer bound");
13904 return error::kNoError
;
13906 const Buffer::MappedRange
* mapped_range
= buffer
->GetMappedRange();
13907 if (!mapped_range
) {
13908 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "UnmapBuffer",
13909 "buffer is unmapped");
13910 return error::kNoError
;
13912 if ((mapped_range
->access
& GL_MAP_WRITE_BIT
) == 0 ||
13913 (mapped_range
->access
& GL_MAP_FLUSH_EXPLICIT_BIT
) ==
13914 GL_MAP_FLUSH_EXPLICIT_BIT
) {
13915 // If we don't need to write back, or explict flush is required, no copying
13918 void* mem
= mapped_range
->GetShmPointer();
13920 return error::kOutOfBounds
;
13922 DCHECK(mapped_range
->pointer
);
13923 memcpy(mapped_range
->pointer
, mem
, mapped_range
->size
);
13925 buffer
->RemoveMappedRange();
13926 GLboolean rt
= glUnmapBuffer(target
);
13927 if (rt
== GL_FALSE
) {
13928 // At this point, we have already done the necessary validation, so
13929 // GL_FALSE indicates data corruption.
13930 // TODO(zmo): We could redo the map / copy data / unmap to recover, but
13931 // the second unmap could still return GL_FALSE. For now, we simply lose
13932 // the contexts in the share group.
13933 LOG(ERROR
) << "glUnmapBuffer unexpectedly returned GL_FALSE";
13934 // Need to lose current context before broadcasting!
13935 MarkContextLost(error::kGuilty
);
13936 group_
->LoseContexts(error::kInnocent
);
13937 return error::kLostContext
;
13939 return error::kNoError
;
13942 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
13943 TextureRef
* texture_ref
) {
13944 Texture
* texture
= texture_ref
->texture();
13945 DoDidUseTexImageIfNeeded(texture
, texture
->target());
13948 // Note that GL_LOST_CONTEXT is specific to GLES.
13949 // For desktop GL we have to query the reset status proactively.
13950 void GLES2DecoderImpl::OnContextLostError() {
13951 if (!WasContextLost()) {
13952 // Need to lose current context before broadcasting!
13953 CheckResetStatus();
13954 group_
->LoseContexts(error::kUnknown
);
13955 reset_by_robustness_extension_
= true;
13959 void GLES2DecoderImpl::OnOutOfMemoryError() {
13960 if (lose_context_when_out_of_memory_
&& !WasContextLost()) {
13961 error::ContextLostReason other
= error::kOutOfMemory
;
13962 if (CheckResetStatus()) {
13963 other
= error::kUnknown
;
13965 // Need to lose current context before broadcasting!
13966 MarkContextLost(error::kOutOfMemory
);
13968 group_
->LoseContexts(other
);
13972 error::Error
GLES2DecoderImpl::HandleGenPathsCHROMIUM(
13973 uint32 immediate_data_size
,
13974 const void* cmd_data
) {
13975 static const char kFunctionName
[] = "glGenPathsCHROMIUM";
13976 const gles2::cmds::GenPathsCHROMIUM
& c
=
13977 *static_cast<const gles2::cmds::GenPathsCHROMIUM
*>(cmd_data
);
13978 if (!features().chromium_path_rendering
) {
13979 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
13980 "function not available");
13981 return error::kNoError
;
13984 GLsizei range
= static_cast<GLsizei
>(c
.range
);
13986 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "range < 0");
13987 return error::kNoError
;
13990 GLuint first_client_id
= static_cast<GLuint
>(c
.first_client_id
);
13991 if (first_client_id
== 0)
13992 return error::kInvalidArguments
;
13995 return error::kNoError
;
13997 if (!GenPathsCHROMIUMHelper(first_client_id
, range
))
13998 return error::kInvalidArguments
;
14000 return error::kNoError
;
14002 error::Error
GLES2DecoderImpl::HandleDeletePathsCHROMIUM(
14003 uint32_t immediate_data_size
,
14004 const void* cmd_data
) {
14005 static const char kFunctionName
[] = "glDeletePathsCHROMIUM";
14006 const gles2::cmds::DeletePathsCHROMIUM
& c
=
14007 *static_cast<const gles2::cmds::DeletePathsCHROMIUM
*>(cmd_data
);
14008 if (!features().chromium_path_rendering
) {
14009 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14010 "function not available");
14011 return error::kNoError
;
14014 GLsizei range
= static_cast<GLsizei
>(c
.range
);
14016 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "range < 0");
14017 return error::kNoError
;
14021 return error::kNoError
;
14023 GLuint first_client_id
= c
.first_client_id
;
14024 // first_client_id can be 0, because non-existing path ids are skipped.
14026 if (!DeletePathsCHROMIUMHelper(first_client_id
, range
))
14027 return error::kInvalidArguments
;
14029 return error::kNoError
;
14032 error::Error
GLES2DecoderImpl::HandlePathCommandsCHROMIUM(
14033 uint32 immediate_data_size
,
14034 const void* cmd_data
) {
14035 static const char kFunctionName
[] = "glPathCommandsCHROMIUM";
14036 const gles2::cmds::PathCommandsCHROMIUM
& c
=
14037 *static_cast<const gles2::cmds::PathCommandsCHROMIUM
*>(cmd_data
);
14038 if (!features().chromium_path_rendering
) {
14039 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14040 "function not available");
14041 return error::kNoError
;
14044 GLuint service_id
= 0;
14045 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
)) {
14046 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14047 "invalid path name");
14048 return error::kNoError
;
14051 GLsizei num_commands
= static_cast<GLsizei
>(c
.numCommands
);
14052 if (num_commands
< 0) {
14053 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "numCommands < 0");
14054 return error::kNoError
;
14057 GLsizei num_coords
= static_cast<uint32
>(c
.numCoords
);
14058 if (num_coords
< 0) {
14059 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "numCoords < 0");
14060 return error::kNoError
;
14063 GLenum coord_type
= static_cast<uint32
>(c
.coordType
);
14064 if (!validators_
->path_coord_type
.IsValid(static_cast<GLint
>(coord_type
))) {
14065 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM
, kFunctionName
, "invalid coordType");
14066 return error::kNoError
;
14069 const GLubyte
* commands
= NULL
;
14070 base::CheckedNumeric
<GLsizei
> num_coords_expected
= 0;
14072 if (num_commands
> 0) {
14073 uint32 commands_shm_id
= static_cast<uint32
>(c
.commands_shm_id
);
14074 uint32 commands_shm_offset
= static_cast<uint32
>(c
.commands_shm_offset
);
14075 if (commands_shm_id
!= 0 || commands_shm_offset
!= 0)
14076 commands
= GetSharedMemoryAs
<const GLubyte
*>(
14077 commands_shm_id
, commands_shm_offset
, num_commands
);
14080 return error::kOutOfBounds
;
14082 for (GLsizei i
= 0; i
< num_commands
; ++i
) {
14083 switch (commands
[i
]) {
14084 case GL_CLOSE_PATH_CHROMIUM
:
14085 // Close has no coords.
14087 case GL_MOVE_TO_CHROMIUM
:
14089 case GL_LINE_TO_CHROMIUM
:
14090 num_coords_expected
+= 2;
14092 case GL_QUADRATIC_CURVE_TO_CHROMIUM
:
14093 num_coords_expected
+= 4;
14095 case GL_CUBIC_CURVE_TO_CHROMIUM
:
14096 num_coords_expected
+= 6;
14098 case GL_CONIC_CURVE_TO_CHROMIUM
:
14099 num_coords_expected
+= 5;
14102 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM
, kFunctionName
, "invalid command");
14103 return error::kNoError
;
14108 if (!num_coords_expected
.IsValid() ||
14109 num_coords
!= num_coords_expected
.ValueOrDie()) {
14110 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14111 "numCoords does not match commands");
14112 return error::kNoError
;
14115 const void* coords
= NULL
;
14117 if (num_coords
> 0) {
14118 uint32 coords_size
= 0;
14119 uint32 coord_type_size
=
14120 GLES2Util::GetGLTypeSizeForPathCoordType(coord_type
);
14121 if (!SafeMultiplyUint32(num_coords
, coord_type_size
, &coords_size
))
14122 return error::kOutOfBounds
;
14124 uint32 coords_shm_id
= static_cast<uint32
>(c
.coords_shm_id
);
14125 uint32 coords_shm_offset
= static_cast<uint32
>(c
.coords_shm_offset
);
14126 if (coords_shm_id
!= 0 || coords_shm_offset
!= 0)
14127 coords
= GetSharedMemoryAs
<const void*>(coords_shm_id
, coords_shm_offset
,
14131 return error::kOutOfBounds
;
14134 glPathCommandsNV(service_id
, num_commands
, commands
, num_coords
, coord_type
,
14137 return error::kNoError
;
14140 error::Error
GLES2DecoderImpl::HandlePathParameterfCHROMIUM(
14141 uint32 immediate_data_size
,
14142 const void* cmd_data
) {
14143 static const char kFunctionName
[] = "glPathParameterfCHROMIUM";
14144 const gles2::cmds::PathParameterfCHROMIUM
& c
=
14145 *static_cast<const gles2::cmds::PathParameterfCHROMIUM
*>(cmd_data
);
14146 if (!features().chromium_path_rendering
) {
14147 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14148 "function not available");
14149 return error::kNoError
;
14151 GLuint service_id
= 0;
14152 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
)) {
14153 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14154 "invalid path name");
14155 return error::kNoError
;
14158 GLenum pname
= static_cast<GLenum
>(c
.pname
);
14159 GLfloat value
= static_cast<GLfloat
>(c
.value
);
14160 bool hasValueError
= false;
14163 case GL_PATH_STROKE_WIDTH_CHROMIUM
:
14164 case GL_PATH_MITER_LIMIT_CHROMIUM
:
14165 hasValueError
= std::isnan(value
) || !std::isfinite(value
) || value
< 0;
14167 case GL_PATH_STROKE_BOUND_CHROMIUM
:
14168 value
= std::max(std::min(1.0f
, value
), 0.0f
);
14170 case GL_PATH_END_CAPS_CHROMIUM
:
14171 hasValueError
= !validators_
->path_parameter_cap_values
.IsValid(
14172 static_cast<GLint
>(value
));
14174 case GL_PATH_JOIN_STYLE_CHROMIUM
:
14175 hasValueError
= !validators_
->path_parameter_join_values
.IsValid(
14176 static_cast<GLint
>(value
));
14179 DCHECK(!validators_
->path_parameter
.IsValid(pname
));
14180 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, pname
, "pname");
14181 return error::kNoError
;
14183 DCHECK(validators_
->path_parameter
.IsValid(pname
));
14185 if (hasValueError
) {
14186 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "value not correct");
14187 return error::kNoError
;
14190 glPathParameterfNV(service_id
, pname
, value
);
14191 return error::kNoError
;
14194 error::Error
GLES2DecoderImpl::HandlePathParameteriCHROMIUM(
14195 uint32 immediate_data_size
,
14196 const void* cmd_data
) {
14197 static const char kFunctionName
[] = "glPathParameteriCHROMIUM";
14198 const gles2::cmds::PathParameteriCHROMIUM
& c
=
14199 *static_cast<const gles2::cmds::PathParameteriCHROMIUM
*>(cmd_data
);
14200 if (!features().chromium_path_rendering
) {
14201 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14202 "function not available");
14203 return error::kNoError
;
14205 GLuint service_id
= 0;
14206 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
)) {
14207 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14208 "invalid path name");
14209 return error::kNoError
;
14212 GLenum pname
= static_cast<GLenum
>(c
.pname
);
14213 GLint value
= static_cast<GLint
>(c
.value
);
14214 bool hasValueError
= false;
14217 case GL_PATH_STROKE_WIDTH_CHROMIUM
:
14218 case GL_PATH_MITER_LIMIT_CHROMIUM
:
14219 hasValueError
= value
< 0;
14221 case GL_PATH_STROKE_BOUND_CHROMIUM
:
14222 value
= std::max(std::min(1, value
), 0);
14224 case GL_PATH_END_CAPS_CHROMIUM
:
14225 hasValueError
= !validators_
->path_parameter_cap_values
.IsValid(value
);
14227 case GL_PATH_JOIN_STYLE_CHROMIUM
:
14228 hasValueError
= !validators_
->path_parameter_join_values
.IsValid(value
);
14231 DCHECK(!validators_
->path_parameter
.IsValid(pname
));
14232 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, pname
, "pname");
14233 return error::kNoError
;
14235 DCHECK(validators_
->path_parameter
.IsValid(pname
));
14237 if (hasValueError
) {
14238 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "value not correct");
14239 return error::kNoError
;
14242 glPathParameteriNV(service_id
, pname
, value
);
14243 return error::kNoError
;
14246 error::Error
GLES2DecoderImpl::HandleStencilFillPathCHROMIUM(
14247 uint32 immediate_data_size
,
14248 const void* cmd_data
) {
14249 static const char kFunctionName
[] = "glStencilFillPathCHROMIUM";
14250 const gles2::cmds::StencilFillPathCHROMIUM
& c
=
14251 *static_cast<const gles2::cmds::StencilFillPathCHROMIUM
*>(cmd_data
);
14252 if (!features().chromium_path_rendering
) {
14253 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14254 "function not available");
14255 return error::kNoError
;
14257 GLenum fill_mode
= static_cast<GLenum
>(c
.fillMode
);
14258 if (!validators_
->path_fill_mode
.IsValid(fill_mode
)) {
14259 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, fill_mode
, "fillMode");
14260 return error::kNoError
;
14262 GLuint mask
= static_cast<GLuint
>(c
.mask
);
14263 if ((fill_mode
== GL_COUNT_UP_CHROMIUM
||
14264 fill_mode
== GL_COUNT_DOWN_CHROMIUM
) &&
14265 GLES2Util::IsNPOT(mask
+ 1)) {
14266 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
,
14267 "mask + 1 is not power of two");
14268 return error::kNoError
;
14270 GLuint service_id
= 0;
14271 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
)) {
14272 // "If /path/ does not name an existing path object, the command does
14273 // nothing (and no error is generated)."
14274 // This holds for other rendering functions, too.
14275 return error::kNoError
;
14278 glStencilFillPathNV(service_id
, fill_mode
, mask
);
14279 return error::kNoError
;
14282 error::Error
GLES2DecoderImpl::HandleStencilStrokePathCHROMIUM(
14283 uint32 immediate_data_size
,
14284 const void* cmd_data
) {
14285 static const char kFunctionName
[] = "glStencilStrokePathCHROMIUM";
14286 const gles2::cmds::StencilStrokePathCHROMIUM
& c
=
14287 *static_cast<const gles2::cmds::StencilStrokePathCHROMIUM
*>(cmd_data
);
14288 if (!features().chromium_path_rendering
) {
14289 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14290 "function not available");
14291 return error::kNoError
;
14293 GLuint service_id
= 0;
14294 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
)) {
14295 return error::kNoError
;
14297 GLint reference
= static_cast<GLint
>(c
.reference
);
14298 GLuint mask
= static_cast<GLuint
>(c
.mask
);
14300 glStencilStrokePathNV(service_id
, reference
, mask
);
14301 return error::kNoError
;
14304 error::Error
GLES2DecoderImpl::HandleCoverFillPathCHROMIUM(
14305 uint32 immediate_data_size
,
14306 const void* cmd_data
) {
14307 static const char kFunctionName
[] = "glCoverFillPathCHROMIUM";
14308 const gles2::cmds::CoverFillPathCHROMIUM
& c
=
14309 *static_cast<const gles2::cmds::CoverFillPathCHROMIUM
*>(cmd_data
);
14310 if (!features().chromium_path_rendering
) {
14311 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14312 "function not available");
14313 return error::kNoError
;
14315 GLenum cover_mode
= static_cast<GLenum
>(c
.coverMode
);
14316 if (!validators_
->path_cover_mode
.IsValid(cover_mode
)) {
14317 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, cover_mode
, "coverMode");
14318 return error::kNoError
;
14320 GLuint service_id
= 0;
14321 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
))
14322 return error::kNoError
;
14325 glCoverFillPathNV(service_id
, cover_mode
);
14326 return error::kNoError
;
14329 error::Error
GLES2DecoderImpl::HandleCoverStrokePathCHROMIUM(
14330 uint32 immediate_data_size
,
14331 const void* cmd_data
) {
14332 static const char kFunctionName
[] = "glCoverStrokePathCHROMIUM";
14333 const gles2::cmds::CoverStrokePathCHROMIUM
& c
=
14334 *static_cast<const gles2::cmds::CoverStrokePathCHROMIUM
*>(cmd_data
);
14335 if (!features().chromium_path_rendering
) {
14336 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14337 "function not available");
14338 return error::kNoError
;
14340 GLenum cover_mode
= static_cast<GLenum
>(c
.coverMode
);
14341 if (!validators_
->path_cover_mode
.IsValid(cover_mode
)) {
14342 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, cover_mode
, "coverMode");
14343 return error::kNoError
;
14345 GLuint service_id
= 0;
14346 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
))
14347 return error::kNoError
;
14350 glCoverStrokePathNV(service_id
, cover_mode
);
14351 return error::kNoError
;
14354 error::Error
GLES2DecoderImpl::HandleStencilThenCoverFillPathCHROMIUM(
14355 uint32 immediate_data_size
,
14356 const void* cmd_data
) {
14357 static const char kFunctionName
[] = "glStencilThenCoverFillPathCHROMIUM";
14358 const gles2::cmds::StencilThenCoverFillPathCHROMIUM
& c
=
14359 *static_cast<const gles2::cmds::StencilThenCoverFillPathCHROMIUM
*>(
14361 if (!features().chromium_path_rendering
) {
14362 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14363 "function not available");
14364 return error::kNoError
;
14366 GLenum fill_mode
= static_cast<GLenum
>(c
.fillMode
);
14367 if (!validators_
->path_fill_mode
.IsValid(fill_mode
)) {
14368 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, fill_mode
, "fillMode");
14369 return error::kNoError
;
14371 GLuint mask
= static_cast<GLuint
>(c
.mask
);
14372 if ((fill_mode
== GL_COUNT_UP_CHROMIUM
||
14373 fill_mode
== GL_COUNT_DOWN_CHROMIUM
) &&
14374 GLES2Util::IsNPOT(mask
+ 1)) {
14375 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
,
14376 "mask + 1 is not power of two");
14377 return error::kNoError
;
14379 GLenum cover_mode
= static_cast<GLenum
>(c
.coverMode
);
14380 if (!validators_
->path_cover_mode
.IsValid(cover_mode
)) {
14381 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, cover_mode
, "coverMode");
14382 return error::kNoError
;
14384 GLuint service_id
= 0;
14385 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
))
14386 return error::kNoError
;
14389 glStencilThenCoverFillPathNV(service_id
, fill_mode
, mask
, cover_mode
);
14390 return error::kNoError
;
14393 error::Error
GLES2DecoderImpl::HandleStencilThenCoverStrokePathCHROMIUM(
14394 uint32 immediate_data_size
,
14395 const void* cmd_data
) {
14396 static const char kFunctionName
[] = "glStencilThenCoverStrokePathCHROMIUM";
14397 const gles2::cmds::StencilThenCoverStrokePathCHROMIUM
& c
=
14398 *static_cast<const gles2::cmds::StencilThenCoverStrokePathCHROMIUM
*>(
14400 if (!features().chromium_path_rendering
) {
14401 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14402 "function not available");
14403 return error::kNoError
;
14405 GLenum cover_mode
= static_cast<GLenum
>(c
.coverMode
);
14406 if (!validators_
->path_cover_mode
.IsValid(cover_mode
)) {
14407 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, cover_mode
, "coverMode");
14408 return error::kNoError
;
14410 GLuint service_id
= 0;
14411 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
))
14412 return error::kNoError
;
14414 GLint reference
= static_cast<GLint
>(c
.reference
);
14415 GLuint mask
= static_cast<GLuint
>(c
.mask
);
14417 glStencilThenCoverStrokePathNV(service_id
, reference
, mask
, cover_mode
);
14418 return error::kNoError
;
14421 // Include the auto-generated part of this file. We split this because it means
14422 // we can easily edit the non-auto generated parts right here in this file
14423 // instead of having to edit some template or the code generator.
14424 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
14426 } // namespace gles2