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"
16 #include "base/at_exit.h"
17 #include "base/bind.h"
18 #include "base/callback_helpers.h"
19 #include "base/command_line.h"
20 #include "base/debug/trace_event.h"
21 #include "base/debug/trace_event_synthetic_delay.h"
22 #include "base/float_util.h"
23 #include "base/memory/scoped_ptr.h"
24 #include "base/numerics/safe_math.h"
25 #include "base/strings/string_number_conversions.h"
26 #include "base/strings/string_split.h"
27 #include "build/build_config.h"
28 #define GLES2_GPU_SERVICE 1
29 #include "gpu/command_buffer/common/debug_marker_manager.h"
30 #include "gpu/command_buffer/common/gles2_cmd_format.h"
31 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
32 #include "gpu/command_buffer/common/id_allocator.h"
33 #include "gpu/command_buffer/common/mailbox.h"
34 #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
35 #include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
36 #include "gpu/command_buffer/service/buffer_manager.h"
37 #include "gpu/command_buffer/service/cmd_buffer_engine.h"
38 #include "gpu/command_buffer/service/context_group.h"
39 #include "gpu/command_buffer/service/context_state.h"
40 #include "gpu/command_buffer/service/error_state.h"
41 #include "gpu/command_buffer/service/feature_info.h"
42 #include "gpu/command_buffer/service/framebuffer_manager.h"
43 #include "gpu/command_buffer/service/gl_utils.h"
44 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
45 #include "gpu/command_buffer/service/gles2_cmd_validation.h"
46 #include "gpu/command_buffer/service/gpu_state_tracer.h"
47 #include "gpu/command_buffer/service/gpu_switches.h"
48 #include "gpu/command_buffer/service/gpu_tracer.h"
49 #include "gpu/command_buffer/service/image_manager.h"
50 #include "gpu/command_buffer/service/mailbox_manager.h"
51 #include "gpu/command_buffer/service/memory_tracking.h"
52 #include "gpu/command_buffer/service/program_manager.h"
53 #include "gpu/command_buffer/service/query_manager.h"
54 #include "gpu/command_buffer/service/renderbuffer_manager.h"
55 #include "gpu/command_buffer/service/shader_manager.h"
56 #include "gpu/command_buffer/service/shader_translator.h"
57 #include "gpu/command_buffer/service/shader_translator_cache.h"
58 #include "gpu/command_buffer/service/texture_manager.h"
59 #include "gpu/command_buffer/service/vertex_array_manager.h"
60 #include "gpu/command_buffer/service/vertex_attrib_manager.h"
61 #include "third_party/smhasher/src/City.h"
62 #include "ui/gl/gl_fence.h"
63 #include "ui/gl/gl_image.h"
64 #include "ui/gl/gl_implementation.h"
65 #include "ui/gl/gl_surface.h"
67 #if defined(OS_MACOSX)
68 #include <IOSurface/IOSurfaceAPI.h>
69 // Note that this must be included after gl_bindings.h to avoid conflicts.
70 #include <OpenGL/CGLIOSurface.h>
74 #include "base/win/win_util.h"
82 static const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
83 static const char kEXTFragDepthExtension[] = "GL_EXT_frag_depth";
84 static const char kEXTDrawBuffersExtension[] = "GL_EXT_draw_buffers";
85 static const char kEXTShaderTextureLodExtension[] = "GL_EXT_shader_texture_lod";
87 static bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin,
90 return (rangeMin >= 62) && (rangeMax >= 62) && (precision >= 16);
93 static void GetShaderPrecisionFormatImpl(GLenum shader_type,
94 GLenum precision_type,
95 GLint *range, GLint *precision) {
96 switch (precision_type) {
100 // These values are for a 32-bit twos-complement integer format.
106 case GL_MEDIUM_FLOAT:
108 // These values are for an IEEE single-precision floating-point format.
118 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
119 gfx::g_driver_gl.fn.glGetShaderPrecisionFormatFn) {
120 // This function is sometimes defined even though it's really just
121 // a stub, so we need to set range and precision as if it weren't
122 // defined before calling it.
123 // On Mac OS with some GPUs, calling this generates a
124 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
126 glGetShaderPrecisionFormat(shader_type, precision_type,
129 // TODO(brianderson): Make the following official workarounds.
131 // Some drivers have bugs where they report the ranges as a negative number.
132 // Taking the absolute value here shouldn't hurt because negative numbers
133 // aren't expected anyway.
134 range[0] = abs(range[0]);
135 range[1] = abs(range[1]);
137 // If the driver reports a precision for highp float that isn't actually
138 // highp, don't pretend like it's supported because shader compilation will
140 if (precision_type == GL_HIGH_FLOAT &&
141 !PrecisionMeetsSpecForHighpFloat(range[0], range[1], *precision)) {
149 static gfx::OverlayTransform GetGFXOverlayTransform(GLenum plane_transform) {
150 switch (plane_transform) {
151 case GL_OVERLAY_TRANSFORM_NONE_CHROMIUM:
152 return gfx::OVERLAY_TRANSFORM_NONE;
153 case GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM:
154 return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL;
155 case GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM:
156 return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL;
157 case GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM:
158 return gfx::OVERLAY_TRANSFORM_ROTATE_90;
159 case GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM:
160 return gfx::OVERLAY_TRANSFORM_ROTATE_180;
161 case GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM:
162 return gfx::OVERLAY_TRANSFORM_ROTATE_270;
164 return gfx::OVERLAY_TRANSFORM_INVALID;
170 class GLES2DecoderImpl;
172 // Local versions of the SET_GL_ERROR macros
173 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
174 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
175 #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
176 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
177 function_name, value, label)
178 #define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
179 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
180 function_name, pname)
181 #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
182 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
184 #define LOCAL_PEEK_GL_ERROR(function_name) \
185 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
186 #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
187 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
188 #define LOCAL_PERFORMANCE_WARNING(msg) \
189 PerformanceWarning(__FILE__, __LINE__, msg)
190 #define LOCAL_RENDER_WARNING(msg) \
191 RenderWarning(__FILE__, __LINE__, msg)
193 // Check that certain assumptions the code makes are true. There are places in
194 // the code where shared memory is passed direclty to GL. Example, glUniformiv,
195 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
196 // a few others) are 32bits. If they are not 32bits the code will have to change
197 // to call those GL functions with service side memory and then copy the results
198 // to shared memory, converting the sizes.
199 COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
200 GLint_not_same_size_as_uint32);
201 COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
202 GLint_not_same_size_as_uint32);
203 COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
204 GLfloat_not_same_size_as_float);
206 // TODO(kbr): the use of this anonymous namespace core dumps the
207 // linker on Mac OS X 10.6 when the symbol ordering file is used
210 // Returns the address of the first byte after a struct.
211 template <typename T>
212 const void* AddressAfterStruct(const T& pod) {
213 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
216 // Returns the address of the frst byte after the struct or NULL if size >
217 // immediate_data_size.
218 template <typename RETURN_TYPE, typename COMMAND_TYPE>
219 RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
221 uint32 immediate_data_size) {
222 return (size <= immediate_data_size) ?
223 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
227 // Computes the data size for certain gl commands like glUniform.
228 bool ComputeDataSize(
231 unsigned int elements_per_unit,
234 if (!SafeMultiplyUint32(count, size, &value)) {
237 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
244 // Return true if a character belongs to the ASCII subset as defined in
245 // GLSL ES 1.0 spec section 3.1.
246 static bool CharacterIsValidForGLES(unsigned char c) {
247 // Printing characters are valid except " $ ` @ \ ' DEL.
248 if (c >= 32 && c <= 126 &&
257 // Horizontal tab, line feed, vertical tab, form feed, carriage return
259 if (c >= 9 && c <= 13) {
266 static bool StringIsValidForGLES(const char* str) {
267 for (; *str; ++str) {
268 if (!CharacterIsValidForGLES(*str)) {
275 // This class prevents any GL errors that occur when it is in scope from
276 // being reported to the client.
277 class ScopedGLErrorSuppressor {
279 explicit ScopedGLErrorSuppressor(
280 const char* function_name, ErrorState* error_state);
281 ~ScopedGLErrorSuppressor();
283 const char* function_name_;
284 ErrorState* error_state_;
285 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
288 // Temporarily changes a decoder's bound texture and restore it when this
289 // object goes out of scope. Also temporarily switches to using active texture
290 // unit zero in case the client has changed that to something invalid.
291 class ScopedTextureBinder {
293 explicit ScopedTextureBinder(ContextState* state, GLuint id, GLenum target);
294 ~ScopedTextureBinder();
297 ContextState* state_;
299 DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder);
302 // Temporarily changes a decoder's bound render buffer and restore it when this
303 // object goes out of scope.
304 class ScopedRenderBufferBinder {
306 explicit ScopedRenderBufferBinder(ContextState* state, GLuint id);
307 ~ScopedRenderBufferBinder();
310 ContextState* state_;
311 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
314 // Temporarily changes a decoder's bound frame buffer and restore it when this
315 // object goes out of scope.
316 class ScopedFrameBufferBinder {
318 explicit ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
319 ~ScopedFrameBufferBinder();
322 GLES2DecoderImpl* decoder_;
323 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
326 // Temporarily changes a decoder's bound frame buffer to a resolved version of
327 // the multisampled offscreen render buffer if that buffer is multisampled, and,
328 // if it is bound or enforce_internal_framebuffer is true. If internal is
329 // true, the resolved framebuffer is not visible to the parent.
330 class ScopedResolvedFrameBufferBinder {
332 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
333 bool enforce_internal_framebuffer,
335 ~ScopedResolvedFrameBufferBinder();
338 GLES2DecoderImpl* decoder_;
339 bool resolve_and_bind_;
340 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
343 class ScopedModifyPixels {
345 explicit ScopedModifyPixels(TextureRef* ref);
346 ~ScopedModifyPixels();
352 ScopedModifyPixels::ScopedModifyPixels(TextureRef* ref) : ref_(ref) {
354 ref_->texture()->OnWillModifyPixels();
357 ScopedModifyPixels::~ScopedModifyPixels() {
359 ref_->texture()->OnDidModifyPixels();
362 class ScopedRenderTo {
364 explicit ScopedRenderTo(Framebuffer* framebuffer);
368 const Framebuffer* framebuffer_;
371 ScopedRenderTo::ScopedRenderTo(Framebuffer* framebuffer)
372 : framebuffer_(framebuffer) {
374 framebuffer_->OnWillRenderTo();
377 ScopedRenderTo::~ScopedRenderTo() {
379 framebuffer_->OnDidRenderTo();
382 // Encapsulates an OpenGL texture.
385 explicit BackTexture(MemoryTracker* memory_tracker, ContextState* state);
388 // Create a new render texture.
391 // Set the initial size and format of a render texture or resize it.
392 bool AllocateStorage(const gfx::Size& size, GLenum format, bool zero);
394 // Copy the contents of the currently bound frame buffer.
395 void Copy(const gfx::Size& size, GLenum format);
397 // Destroy the render texture. This must be explicitly called before
398 // destroying this object.
401 // Invalidate the texture. This can be used when a context is lost and it is
402 // not possible to make it current in order to free the resource.
409 gfx::Size size() const {
414 MemoryTypeTracker memory_tracker_;
415 ContextState* state_;
416 size_t bytes_allocated_;
419 DISALLOW_COPY_AND_ASSIGN(BackTexture);
422 // Encapsulates an OpenGL render buffer of any format.
423 class BackRenderbuffer {
425 explicit BackRenderbuffer(
426 RenderbufferManager* renderbuffer_manager,
427 MemoryTracker* memory_tracker,
428 ContextState* state);
431 // Create a new render buffer.
434 // Set the initial size and format of a render buffer or resize it.
435 bool AllocateStorage(const FeatureInfo* feature_info,
436 const gfx::Size& size,
440 // Destroy the render buffer. This must be explicitly called before destroying
444 // Invalidate the render buffer. This can be used when a context is lost and
445 // it is not possible to make it current in order to free the resource.
453 RenderbufferManager* renderbuffer_manager_;
454 MemoryTypeTracker memory_tracker_;
455 ContextState* state_;
456 size_t bytes_allocated_;
458 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer);
461 // Encapsulates an OpenGL frame buffer.
462 class BackFramebuffer {
464 explicit BackFramebuffer(GLES2DecoderImpl* decoder);
467 // Create a new frame buffer.
470 // Attach a color render buffer to a frame buffer.
471 void AttachRenderTexture(BackTexture* texture);
473 // Attach a render buffer to a frame buffer. Note that this unbinds any
474 // currently bound frame buffer.
475 void AttachRenderBuffer(GLenum target, BackRenderbuffer* render_buffer);
477 // Destroy the frame buffer. This must be explicitly called before destroying
481 // Invalidate the frame buffer. This can be used when a context is lost and it
482 // is not possible to make it current in order to free the resource.
485 // See glCheckFramebufferStatusEXT.
486 GLenum CheckStatus();
493 GLES2DecoderImpl* decoder_;
495 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer);
498 struct FenceCallback {
499 explicit FenceCallback()
500 : fence(gfx::GLFence::Create()) {
503 std::vector<base::Closure> callbacks;
504 scoped_ptr<gfx::GLFence> fence;
507 class AsyncUploadTokenCompletionObserver
508 : public AsyncPixelTransferCompletionObserver {
510 explicit AsyncUploadTokenCompletionObserver(uint32 async_upload_token)
511 : async_upload_token_(async_upload_token) {
514 virtual void DidComplete(const AsyncMemoryParams& mem_params) OVERRIDE {
515 DCHECK(mem_params.buffer().get());
516 void* data = mem_params.GetDataAddress();
517 AsyncUploadSync* sync = static_cast<AsyncUploadSync*>(data);
518 sync->SetAsyncUploadToken(async_upload_token_);
522 virtual ~AsyncUploadTokenCompletionObserver() {
525 uint32 async_upload_token_;
527 DISALLOW_COPY_AND_ASSIGN(AsyncUploadTokenCompletionObserver);
530 // } // anonymous namespace.
533 const unsigned int GLES2Decoder::kDefaultStencilMask =
534 static_cast<unsigned int>(-1);
536 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
537 uint32* service_texture_id) {
541 GLES2Decoder::GLES2Decoder()
542 : initialized_(false),
544 log_commands_(false) {
547 GLES2Decoder::~GLES2Decoder() {
550 void GLES2Decoder::BeginDecoding() {}
552 void GLES2Decoder::EndDecoding() {}
554 // This class implements GLES2Decoder so we don't have to expose all the GLES2
555 // cmd stuff to outside this class.
556 class GLES2DecoderImpl : public GLES2Decoder,
557 public FramebufferManager::TextureDetachObserver,
558 public ErrorStateClient {
560 explicit GLES2DecoderImpl(ContextGroup* group);
561 virtual ~GLES2DecoderImpl();
563 // Overridden from AsyncAPIInterface.
564 virtual Error DoCommand(unsigned int command,
565 unsigned int arg_count,
566 const void* args) OVERRIDE;
568 virtual error::Error DoCommands(unsigned int num_commands,
571 int* entries_processed) OVERRIDE;
573 template <bool DebugImpl>
574 error::Error DoCommandsImpl(unsigned int num_commands,
577 int* entries_processed);
579 // Overridden from AsyncAPIInterface.
580 virtual const char* GetCommandName(unsigned int command_id) const OVERRIDE;
582 // Overridden from GLES2Decoder.
583 virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
584 const scoped_refptr<gfx::GLContext>& context,
586 const gfx::Size& size,
587 const DisallowedFeatures& disallowed_features,
588 const std::vector<int32>& attribs) OVERRIDE;
589 virtual void Destroy(bool have_context) OVERRIDE;
590 virtual void SetSurface(
591 const scoped_refptr<gfx::GLSurface>& surface) OVERRIDE;
592 virtual void ProduceFrontBuffer(const Mailbox& mailbox) OVERRIDE;
593 virtual bool ResizeOffscreenFrameBuffer(const gfx::Size& size) OVERRIDE;
594 void UpdateParentTextureInfo();
595 virtual bool MakeCurrent() OVERRIDE;
596 virtual GLES2Util* GetGLES2Util() OVERRIDE { return &util_; }
597 virtual gfx::GLContext* GetGLContext() OVERRIDE { return context_.get(); }
598 virtual ContextGroup* GetContextGroup() OVERRIDE { return group_.get(); }
599 virtual Capabilities GetCapabilities() OVERRIDE;
600 virtual void RestoreState(const ContextState* prev_state) OVERRIDE;
602 virtual void RestoreActiveTexture() const OVERRIDE {
603 state_.RestoreActiveTexture();
605 virtual void RestoreAllTextureUnitBindings(
606 const ContextState* prev_state) const OVERRIDE {
607 state_.RestoreAllTextureUnitBindings(prev_state);
609 virtual void RestoreActiveTextureUnitBinding(
610 unsigned int target) const OVERRIDE {
611 state_.RestoreActiveTextureUnitBinding(target);
613 virtual void RestoreBufferBindings() const OVERRIDE {
614 state_.RestoreBufferBindings();
616 virtual void RestoreGlobalState() const OVERRIDE {
617 state_.RestoreGlobalState(NULL);
619 virtual void RestoreProgramBindings() const OVERRIDE {
620 state_.RestoreProgramBindings();
622 virtual void RestoreTextureUnitBindings(unsigned unit) const OVERRIDE {
623 state_.RestoreTextureUnitBindings(unit, NULL);
625 virtual void RestoreFramebufferBindings() const OVERRIDE;
626 virtual void RestoreRenderbufferBindings() OVERRIDE;
627 virtual void RestoreTextureState(unsigned service_id) const OVERRIDE;
629 virtual void ClearAllAttributes() const OVERRIDE;
630 virtual void RestoreAllAttributes() const OVERRIDE;
632 virtual QueryManager* GetQueryManager() OVERRIDE {
633 return query_manager_.get();
635 virtual VertexArrayManager* GetVertexArrayManager() OVERRIDE {
636 return vertex_array_manager_.get();
638 virtual ImageManager* GetImageManager() OVERRIDE {
639 return image_manager_.get();
641 virtual bool ProcessPendingQueries() OVERRIDE;
642 virtual bool HasMoreIdleWork() OVERRIDE;
643 virtual void PerformIdleWork() OVERRIDE;
645 virtual void WaitForReadPixels(base::Closure callback) OVERRIDE;
647 virtual void SetResizeCallback(
648 const base::Callback<void(gfx::Size, float)>& callback) OVERRIDE;
650 virtual Logger* GetLogger() OVERRIDE;
652 virtual void BeginDecoding() OVERRIDE;
653 virtual void EndDecoding() OVERRIDE;
655 virtual ErrorState* GetErrorState() OVERRIDE;
656 virtual const ContextState* GetContextState() OVERRIDE { return &state_; }
658 virtual void SetShaderCacheCallback(
659 const ShaderCacheCallback& callback) OVERRIDE;
660 virtual void SetWaitSyncPointCallback(
661 const WaitSyncPointCallback& callback) OVERRIDE;
663 virtual AsyncPixelTransferManager*
664 GetAsyncPixelTransferManager() OVERRIDE;
665 virtual void ResetAsyncPixelTransferManagerForTest() OVERRIDE;
666 virtual void SetAsyncPixelTransferManagerForTest(
667 AsyncPixelTransferManager* manager) OVERRIDE;
668 virtual void SetIgnoreCachedStateForTest(bool ignore) OVERRIDE;
669 void ProcessFinishedAsyncTransfers();
671 virtual bool GetServiceTextureId(uint32 client_texture_id,
672 uint32* service_texture_id) OVERRIDE;
674 virtual uint32 GetTextureUploadCount() OVERRIDE;
675 virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE;
676 virtual base::TimeDelta GetTotalProcessingCommandsTime() OVERRIDE;
677 virtual void AddProcessingCommandsTime(base::TimeDelta) OVERRIDE;
679 // Restores the current state to the user's settings.
680 void RestoreCurrentFramebufferBindings();
682 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
683 void ApplyDirtyState();
685 // These check the state of the currently bound framebuffer or the
686 // backbuffer if no framebuffer is bound.
687 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
688 // check with all attached and enabled color attachments.
689 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers);
690 bool BoundFramebufferHasDepthAttachment();
691 bool BoundFramebufferHasStencilAttachment();
693 virtual error::ContextLostReason GetContextLostReason() OVERRIDE;
695 // Overridden from FramebufferManager::TextureDetachObserver:
696 virtual void OnTextureRefDetachedFromFramebuffer(
697 TextureRef* texture) OVERRIDE;
699 // Overriden from ErrorStateClient.
700 virtual void OnOutOfMemoryError() OVERRIDE;
702 // Ensure Renderbuffer corresponding to last DoBindRenderbuffer() is bound.
703 void EnsureRenderbufferBound();
705 // Helpers to facilitate calling into compatible extensions.
706 static void RenderbufferStorageMultisampleHelper(
707 const FeatureInfo* feature_info,
710 GLenum internal_format,
714 void BlitFramebufferHelper(GLint srcX0,
726 friend class ScopedFrameBufferBinder;
727 friend class ScopedResolvedFrameBufferBinder;
728 friend class BackFramebuffer;
730 // Initialize or re-initialize the shader translator.
731 bool InitializeShaderTranslator();
733 void UpdateCapabilities();
735 // Helpers for the glGen and glDelete functions.
736 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
737 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
738 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
739 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
740 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
741 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
742 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
743 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
744 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
745 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
746 bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
747 void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
749 // Helper for async upload token completion notification callback.
750 base::Closure AsyncUploadTokenCompletionClosure(uint32 async_upload_token,
751 uint32 sync_data_shm_id,
752 uint32 sync_data_shm_offset);
757 void OnFboChanged() const;
758 void OnUseFramebuffer() const;
760 // TODO(gman): Cache these pointers?
761 BufferManager* buffer_manager() {
762 return group_->buffer_manager();
765 RenderbufferManager* renderbuffer_manager() {
766 return group_->renderbuffer_manager();
769 FramebufferManager* framebuffer_manager() {
770 return group_->framebuffer_manager();
773 ProgramManager* program_manager() {
774 return group_->program_manager();
777 ShaderManager* shader_manager() {
778 return group_->shader_manager();
781 ShaderTranslatorCache* shader_translator_cache() {
782 return group_->shader_translator_cache();
785 const TextureManager* texture_manager() const {
786 return group_->texture_manager();
789 TextureManager* texture_manager() {
790 return group_->texture_manager();
793 MailboxManager* mailbox_manager() {
794 return group_->mailbox_manager();
797 ImageManager* image_manager() { return image_manager_.get(); }
799 VertexArrayManager* vertex_array_manager() {
800 return vertex_array_manager_.get();
803 MemoryTracker* memory_tracker() {
804 return group_->memory_tracker();
807 bool EnsureGPUMemoryAvailable(size_t estimated_size) {
808 MemoryTracker* tracker = memory_tracker();
810 return tracker->EnsureGPUMemoryAvailable(estimated_size);
815 bool IsOffscreenBufferMultisampled() const {
816 return offscreen_target_samples_ > 1;
819 // Creates a Texture for the given texture.
820 TextureRef* CreateTexture(
821 GLuint client_id, GLuint service_id) {
822 return texture_manager()->CreateTexture(client_id, service_id);
825 // Gets the texture info for the given texture. Returns NULL if none exists.
826 TextureRef* GetTexture(GLuint client_id) const {
827 return texture_manager()->GetTexture(client_id);
830 // Deletes the texture info for the given texture.
831 void RemoveTexture(GLuint client_id) {
832 texture_manager()->RemoveTexture(client_id);
835 // Get the size (in pixels) of the currently bound frame buffer (either FBO
836 // or regular back buffer).
837 gfx::Size GetBoundReadFrameBufferSize();
839 // Get the format of the currently bound frame buffer (either FBO or regular
841 GLenum GetBoundReadFrameBufferTextureType();
842 GLenum GetBoundReadFrameBufferInternalFormat();
843 GLenum GetBoundDrawFrameBufferInternalFormat();
845 // Wrapper for CompressedTexImage2D commands.
846 error::Error DoCompressedTexImage2D(
849 GLenum internal_format,
856 // Wrapper for CompressedTexSubImage2D.
857 void DoCompressedTexSubImage2D(
868 // Wrapper for CopyTexImage2D.
869 void DoCopyTexImage2D(
872 GLenum internal_format,
879 // Wrapper for SwapBuffers.
880 void DoSwapBuffers();
882 // Wrapper for CopyTexSubImage2D.
883 void DoCopyTexSubImage2D(
893 // Validation for TexSubImage2D.
894 bool ValidateTexSubImage2D(
896 const char* function_name,
907 // Wrapper for TexSubImage2D.
908 error::Error DoTexSubImage2D(
919 // Extra validation for async tex(Sub)Image2D.
920 bool ValidateAsyncTransfer(
921 const char* function_name,
922 TextureRef* texture_ref,
927 // Wrapper for TexImageIOSurface2DCHROMIUM.
928 void DoTexImageIOSurface2DCHROMIUM(
932 GLuint io_surface_id,
935 void DoCopyTextureCHROMIUM(
940 GLenum internal_format,
943 // Wrapper for TexStorage2DEXT.
944 void DoTexStorage2DEXT(
947 GLenum internal_format,
951 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
952 void DoProduceTextureDirectCHROMIUM(GLuint texture, GLenum target,
954 void ProduceTextureRef(std::string func_name, TextureRef* texture_ref,
955 GLenum target, const GLbyte* data);
957 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
958 void DoCreateAndConsumeTextureCHROMIUM(GLenum target, const GLbyte* key,
961 void DoBindTexImage2DCHROMIUM(
964 void DoReleaseTexImage2DCHROMIUM(
968 void DoTraceEndCHROMIUM(void);
970 void DoDrawBuffersEXT(GLsizei count, const GLenum* bufs);
972 void DoLoseContextCHROMIUM(GLenum current, GLenum other);
974 void DoMatrixLoadfCHROMIUM(GLenum matrix_mode, const GLfloat* matrix);
975 void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode);
977 // Creates a Program for the given program.
978 Program* CreateProgram(
979 GLuint client_id, GLuint service_id) {
980 return program_manager()->CreateProgram(client_id, service_id);
983 // Gets the program info for the given program. Returns NULL if none exists.
984 Program* GetProgram(GLuint client_id) {
985 return program_manager()->GetProgram(client_id);
989 void LogClientServiceMapping(
990 const char* /* function_name */,
991 GLuint /* client_id */,
992 GLuint /* service_id */) {
995 void LogClientServiceForInfo(
996 T* /* info */, GLuint /* client_id */, const char* /* function_name */) {
999 void LogClientServiceMapping(
1000 const char* function_name, GLuint client_id, GLuint service_id) {
1001 if (service_logging_) {
1002 VLOG(1) << "[" << logger_.GetLogPrefix() << "] " << function_name
1003 << ": client_id = " << client_id
1004 << ", service_id = " << service_id;
1007 template<typename T>
1008 void LogClientServiceForInfo(
1009 T* info, GLuint client_id, const char* function_name) {
1011 LogClientServiceMapping(function_name, client_id, info->service_id());
1016 // Gets the program info for the given program. If it's not a program
1017 // generates a GL error. Returns NULL if not program.
1018 Program* GetProgramInfoNotShader(
1019 GLuint client_id, const char* function_name) {
1020 Program* program = GetProgram(client_id);
1022 if (GetShader(client_id)) {
1024 GL_INVALID_OPERATION, function_name, "shader passed for program");
1026 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown program");
1029 LogClientServiceForInfo(program, client_id, function_name);
1034 // Creates a Shader for the given shader.
1035 Shader* CreateShader(
1038 GLenum shader_type) {
1039 return shader_manager()->CreateShader(
1040 client_id, service_id, shader_type);
1043 // Gets the shader info for the given shader. Returns NULL if none exists.
1044 Shader* GetShader(GLuint client_id) {
1045 return shader_manager()->GetShader(client_id);
1048 // Gets the shader info for the given shader. If it's not a shader generates a
1049 // GL error. Returns NULL if not shader.
1050 Shader* GetShaderInfoNotProgram(
1051 GLuint client_id, const char* function_name) {
1052 Shader* shader = GetShader(client_id);
1054 if (GetProgram(client_id)) {
1056 GL_INVALID_OPERATION, function_name, "program passed for shader");
1059 GL_INVALID_VALUE, function_name, "unknown shader");
1062 LogClientServiceForInfo(shader, client_id, function_name);
1066 // Creates a buffer info for the given buffer.
1067 void CreateBuffer(GLuint client_id, GLuint service_id) {
1068 return buffer_manager()->CreateBuffer(client_id, service_id);
1071 // Gets the buffer info for the given buffer.
1072 Buffer* GetBuffer(GLuint client_id) {
1073 Buffer* buffer = buffer_manager()->GetBuffer(client_id);
1077 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1078 // on glDeleteBuffers so we can make sure the user does not try to render
1079 // with deleted buffers.
1080 void RemoveBuffer(GLuint client_id);
1082 // Creates a framebuffer info for the given framebuffer.
1083 void CreateFramebuffer(GLuint client_id, GLuint service_id) {
1084 return framebuffer_manager()->CreateFramebuffer(client_id, service_id);
1087 // Gets the framebuffer info for the given framebuffer.
1088 Framebuffer* GetFramebuffer(GLuint client_id) {
1089 return framebuffer_manager()->GetFramebuffer(client_id);
1092 // Removes the framebuffer info for the given framebuffer.
1093 void RemoveFramebuffer(GLuint client_id) {
1094 framebuffer_manager()->RemoveFramebuffer(client_id);
1097 // Creates a renderbuffer info for the given renderbuffer.
1098 void CreateRenderbuffer(GLuint client_id, GLuint service_id) {
1099 return renderbuffer_manager()->CreateRenderbuffer(
1100 client_id, service_id);
1103 // Gets the renderbuffer info for the given renderbuffer.
1104 Renderbuffer* GetRenderbuffer(GLuint client_id) {
1105 return renderbuffer_manager()->GetRenderbuffer(client_id);
1108 // Removes the renderbuffer info for the given renderbuffer.
1109 void RemoveRenderbuffer(GLuint client_id) {
1110 renderbuffer_manager()->RemoveRenderbuffer(client_id);
1113 // Gets the vertex attrib manager for the given vertex array.
1114 VertexAttribManager* GetVertexAttribManager(GLuint client_id) {
1115 VertexAttribManager* info =
1116 vertex_array_manager()->GetVertexAttribManager(client_id);
1120 // Removes the vertex attrib manager for the given vertex array.
1121 void RemoveVertexAttribManager(GLuint client_id) {
1122 vertex_array_manager()->RemoveVertexAttribManager(client_id);
1125 // Creates a vertex attrib manager for the given vertex array.
1126 scoped_refptr<VertexAttribManager> CreateVertexAttribManager(
1129 bool client_visible) {
1130 return vertex_array_manager()->CreateVertexAttribManager(
1131 client_id, service_id, group_->max_vertex_attribs(), client_visible);
1134 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
1135 void DoBindUniformLocationCHROMIUM(
1136 GLuint client_id, GLint location, const char* name);
1138 error::Error GetAttribLocationHelper(
1139 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1140 const std::string& name_str);
1142 error::Error GetUniformLocationHelper(
1143 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1144 const std::string& name_str);
1146 // Helper for glShaderSource.
1147 error::Error ShaderSourceHelper(
1148 GLuint client_id, const char* data, uint32 data_size);
1150 // Clear any textures used by the current program.
1151 bool ClearUnclearedTextures();
1153 // Clears any uncleared attachments attached to the given frame buffer.
1154 // Returns false if there was a generated GL error.
1155 void ClearUnclearedAttachments(GLenum target, Framebuffer* framebuffer);
1157 // overridden from GLES2Decoder
1158 virtual bool ClearLevel(unsigned service_id,
1159 unsigned bind_target,
1162 unsigned internal_format,
1167 bool is_texture_immutable) OVERRIDE;
1169 // Restore all GL state that affects clearing.
1170 void RestoreClearState();
1172 // Remembers the state of some capabilities.
1173 // Returns: true if glEnable/glDisable should actually be called.
1174 bool SetCapabilityState(GLenum cap, bool enabled);
1176 // Check that the currently bound framebuffers are valid.
1177 // Generates GL error if not.
1178 bool CheckBoundFramebuffersValid(const char* func_name);
1180 // Check that the currently bound read framebuffer has a color image
1181 // attached. Generates GL error if not.
1182 bool CheckBoundReadFramebufferColorAttachment(const char* func_name);
1184 // Check if a framebuffer meets our requirements.
1185 bool CheckFramebufferValid(
1186 Framebuffer* framebuffer,
1188 const char* func_name);
1190 // Checks if the current program exists and is valid. If not generates the
1191 // appropriate GL error. Returns true if the current program is in a usable
1193 bool CheckCurrentProgram(const char* function_name);
1195 // Checks if the current program exists and is valid and that location is not
1196 // -1. If the current program is not valid generates the appropriate GL
1197 // error. Returns true if the current program is in a usable state and
1198 // location is not -1.
1199 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1201 // Gets the type of a uniform for a location in the current program. Sets GL
1202 // errors if the current program is not valid. Returns true if the current
1203 // program is valid and the location exists. Adjusts count so it
1204 // does not overflow the uniform.
1205 bool PrepForSetUniformByLocation(GLint fake_location,
1206 const char* function_name,
1207 Program::UniformApiType api_type,
1208 GLint* real_location,
1212 // Gets the service id for any simulated backbuffer fbo.
1213 GLuint GetBackbufferServiceId() const;
1215 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1216 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1218 // Helper for glGetVertexAttrib
1219 void GetVertexAttribHelper(
1220 const VertexAttrib* attrib, GLenum pname, GLint* param);
1222 // Wrapper for glCreateProgram
1223 bool CreateProgramHelper(GLuint client_id);
1225 // Wrapper for glCreateShader
1226 bool CreateShaderHelper(GLenum type, GLuint client_id);
1228 // Wrapper for glActiveTexture
1229 void DoActiveTexture(GLenum texture_unit);
1231 // Wrapper for glAttachShader
1232 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1234 // Wrapper for glBindBuffer since we need to track the current targets.
1235 void DoBindBuffer(GLenum target, GLuint buffer);
1237 // Wrapper for glBindFramebuffer since we need to track the current targets.
1238 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1240 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1241 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1243 // Wrapper for glBindTexture since we need to track the current targets.
1244 void DoBindTexture(GLenum target, GLuint texture);
1246 // Wrapper for glBindVertexArrayOES
1247 void DoBindVertexArrayOES(GLuint array);
1248 void EmulateVertexArrayState();
1250 // Wrapper for glBlitFramebufferCHROMIUM.
1251 void DoBlitFramebufferCHROMIUM(
1252 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1253 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1254 GLbitfield mask, GLenum filter);
1256 // Wrapper for glBufferSubData.
1257 void DoBufferSubData(
1258 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1260 // Wrapper for glCheckFramebufferStatus
1261 GLenum DoCheckFramebufferStatus(GLenum target);
1263 // Wrapper for glClear
1264 error::Error DoClear(GLbitfield mask);
1266 // Wrappers for various state.
1267 void DoDepthRangef(GLclampf znear, GLclampf zfar);
1268 void DoSampleCoverage(GLclampf value, GLboolean invert);
1270 // Wrapper for glCompileShader.
1271 void DoCompileShader(GLuint shader);
1273 // Helper for DeleteSharedIdsCHROMIUM commands.
1274 void DoDeleteSharedIdsCHROMIUM(
1275 GLuint namespace_id, GLsizei n, const GLuint* ids);
1277 // Wrapper for glDetachShader
1278 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1280 // Wrapper for glDisable
1281 void DoDisable(GLenum cap);
1283 // Wrapper for glDisableVertexAttribArray.
1284 void DoDisableVertexAttribArray(GLuint index);
1286 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1288 void DoDiscardFramebufferEXT(GLenum target,
1289 GLsizei numAttachments,
1290 const GLenum* attachments);
1292 // Wrapper for glEnable
1293 void DoEnable(GLenum cap);
1295 // Wrapper for glEnableVertexAttribArray.
1296 void DoEnableVertexAttribArray(GLuint index);
1298 // Wrapper for glFinish.
1301 // Wrapper for glFlush.
1304 // Wrapper for glFramebufferRenderbufffer.
1305 void DoFramebufferRenderbuffer(
1306 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1307 GLuint renderbuffer);
1309 // Wrapper for glFramebufferTexture2D.
1310 void DoFramebufferTexture2D(
1311 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1314 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1315 void DoFramebufferTexture2DMultisample(
1316 GLenum target, GLenum attachment, GLenum textarget,
1317 GLuint texture, GLint level, GLsizei samples);
1319 // Common implementation for both DoFramebufferTexture2D wrappers.
1320 void DoFramebufferTexture2DCommon(const char* name,
1321 GLenum target, GLenum attachment, GLenum textarget,
1322 GLuint texture, GLint level, GLsizei samples);
1324 // Wrapper for glGenerateMipmap
1325 void DoGenerateMipmap(GLenum target);
1327 // Helper for GenSharedIdsCHROMIUM commands.
1328 void DoGenSharedIdsCHROMIUM(
1329 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
1331 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1332 // to account for different pname values defined in different extension
1334 GLenum AdjustGetPname(GLenum pname);
1336 // Wrapper for DoGetBooleanv.
1337 void DoGetBooleanv(GLenum pname, GLboolean* params);
1339 // Wrapper for DoGetFloatv.
1340 void DoGetFloatv(GLenum pname, GLfloat* params);
1342 // Wrapper for glGetFramebufferAttachmentParameteriv.
1343 void DoGetFramebufferAttachmentParameteriv(
1344 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1346 // Wrapper for glGetIntegerv.
1347 void DoGetIntegerv(GLenum pname, GLint* params);
1349 // Gets the max value in a range in a buffer.
1350 GLuint DoGetMaxValueInBufferCHROMIUM(
1351 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1353 // Wrapper for glGetBufferParameteriv.
1354 void DoGetBufferParameteriv(
1355 GLenum target, GLenum pname, GLint* params);
1357 // Wrapper for glGetProgramiv.
1358 void DoGetProgramiv(
1359 GLuint program_id, GLenum pname, GLint* params);
1361 // Wrapper for glRenderbufferParameteriv.
1362 void DoGetRenderbufferParameteriv(
1363 GLenum target, GLenum pname, GLint* params);
1365 // Wrapper for glGetShaderiv
1366 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1368 // Wrappers for glGetTexParameter.
1369 void DoGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params);
1370 void DoGetTexParameteriv(GLenum target, GLenum pname, GLint* params);
1371 void InitTextureMaxAnisotropyIfNeeded(GLenum target, GLenum pname);
1373 // Wrappers for glGetVertexAttrib.
1374 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1375 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1377 // Wrappers for glIsXXX functions.
1378 bool DoIsEnabled(GLenum cap);
1379 bool DoIsBuffer(GLuint client_id);
1380 bool DoIsFramebuffer(GLuint client_id);
1381 bool DoIsProgram(GLuint client_id);
1382 bool DoIsRenderbuffer(GLuint client_id);
1383 bool DoIsShader(GLuint client_id);
1384 bool DoIsTexture(GLuint client_id);
1385 bool DoIsVertexArrayOES(GLuint client_id);
1387 // Wrapper for glLinkProgram
1388 void DoLinkProgram(GLuint program);
1390 // Helper for RegisterSharedIdsCHROMIUM.
1391 void DoRegisterSharedIdsCHROMIUM(
1392 GLuint namespace_id, GLsizei n, const GLuint* ids);
1394 // Wrapper for glRenderbufferStorage.
1395 void DoRenderbufferStorage(
1396 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
1398 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1399 void DoRenderbufferStorageMultisampleCHROMIUM(
1400 GLenum target, GLsizei samples, GLenum internalformat,
1401 GLsizei width, GLsizei height);
1403 // Handler for glRenderbufferStorageMultisampleEXT
1404 // (multisampled_render_to_texture).
1405 void DoRenderbufferStorageMultisampleEXT(
1406 GLenum target, GLsizei samples, GLenum internalformat,
1407 GLsizei width, GLsizei height);
1409 // Common validation for multisample extensions.
1410 bool ValidateRenderbufferStorageMultisample(GLsizei samples,
1411 GLenum internalformat,
1415 // Verifies that the currently bound multisample renderbuffer is valid
1416 // Very slow! Only done on platforms with driver bugs that return invalid
1417 // buffers under memory pressure
1418 bool VerifyMultisampleRenderbufferIntegrity(
1419 GLuint renderbuffer, GLenum format);
1421 // Wrapper for glReleaseShaderCompiler.
1422 void DoReleaseShaderCompiler() { }
1424 // Wrappers for glTexParameter functions.
1425 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1426 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1427 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1428 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1430 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1431 // spec only these 2 functions can be used to set sampler uniforms.
1432 void DoUniform1i(GLint fake_location, GLint v0);
1433 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1434 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1435 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1436 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
1438 // Wrappers for glUniformfv because some drivers don't correctly accept
1440 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1441 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1442 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1443 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
1445 void DoUniformMatrix2fv(
1446 GLint fake_location, GLsizei count, GLboolean transpose,
1447 const GLfloat* value);
1448 void DoUniformMatrix3fv(
1449 GLint fake_location, GLsizei count, GLboolean transpose,
1450 const GLfloat* value);
1451 void DoUniformMatrix4fv(
1452 GLint fake_location, GLsizei count, GLboolean transpose,
1453 const GLfloat* value);
1455 bool SetVertexAttribValue(
1456 const char* function_name, GLuint index, const GLfloat* value);
1458 // Wrappers for glVertexAttrib??
1459 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1460 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1461 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1462 void DoVertexAttrib4f(
1463 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1464 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1465 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1466 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1467 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1469 // Wrapper for glViewport
1470 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1472 // Wrapper for glUseProgram
1473 void DoUseProgram(GLuint program);
1475 // Wrapper for glValidateProgram.
1476 void DoValidateProgram(GLuint program_client_id);
1478 void DoInsertEventMarkerEXT(GLsizei length, const GLchar* marker);
1479 void DoPushGroupMarkerEXT(GLsizei length, const GLchar* group);
1480 void DoPopGroupMarkerEXT(void);
1482 // Gets the number of values that will be returned by glGetXXX. Returns
1483 // false if pname is unknown.
1484 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1486 // Checks if the current program and vertex attributes are valid for drawing.
1488 const char* function_name, GLuint max_vertex_accessed, bool instanced,
1491 // Returns true if successful, simulated will be true if attrib0 was
1493 bool SimulateAttrib0(
1494 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
1495 void RestoreStateForAttrib(GLuint attrib, bool restore_array_binding);
1497 // If an image is bound to texture, this will call Will/DidUseTexImage
1499 void DoWillUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1500 void DoDidUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1502 // Returns false if textures were replaced.
1503 bool PrepareTexturesForRender();
1504 void RestoreStateForTextures();
1506 // Returns true if GL_FIXED attribs were simulated.
1507 bool SimulateFixedAttribs(
1508 const char* function_name,
1509 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
1510 void RestoreStateForSimulatedFixedAttribs();
1512 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1513 // cases (primcount is always 1 for non-instanced).
1514 error::Error DoDrawArrays(
1515 const char* function_name,
1516 bool instanced, GLenum mode, GLint first, GLsizei count,
1518 error::Error DoDrawElements(
1519 const char* function_name,
1520 bool instanced, GLenum mode, GLsizei count, GLenum type,
1521 int32 offset, GLsizei primcount);
1523 GLenum GetBindTargetForSamplerType(GLenum type) {
1524 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
1525 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1528 return GL_TEXTURE_2D;
1529 case GL_SAMPLER_CUBE:
1530 return GL_TEXTURE_CUBE_MAP;
1531 case GL_SAMPLER_EXTERNAL_OES:
1532 return GL_TEXTURE_EXTERNAL_OES;
1533 case GL_SAMPLER_2D_RECT_ARB:
1534 return GL_TEXTURE_RECTANGLE_ARB;
1541 // Gets the framebuffer info for a particular target.
1542 Framebuffer* GetFramebufferInfoForTarget(GLenum target) {
1543 Framebuffer* framebuffer = NULL;
1545 case GL_FRAMEBUFFER:
1546 case GL_DRAW_FRAMEBUFFER_EXT:
1547 framebuffer = framebuffer_state_.bound_draw_framebuffer.get();
1549 case GL_READ_FRAMEBUFFER_EXT:
1550 framebuffer = framebuffer_state_.bound_read_framebuffer.get();
1559 Renderbuffer* GetRenderbufferInfoForTarget(
1561 Renderbuffer* renderbuffer = NULL;
1563 case GL_RENDERBUFFER:
1564 renderbuffer = state_.bound_renderbuffer.get();
1570 return renderbuffer;
1573 // Validates the program and location for a glGetUniform call and returns
1574 // a SizeResult setup to receive the result. Returns true if glGetUniform
1575 // should be called.
1576 bool GetUniformSetup(
1577 GLuint program, GLint fake_location,
1578 uint32 shm_id, uint32 shm_offset,
1579 error::Error* error, GLint* real_location, GLuint* service_id,
1580 void** result, GLenum* result_type);
1582 virtual bool WasContextLost() OVERRIDE;
1583 virtual bool WasContextLostByRobustnessExtension() OVERRIDE;
1584 virtual void LoseContext(uint32 reset_status) OVERRIDE;
1586 #if defined(OS_MACOSX)
1587 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1590 bool ValidateCompressedTexDimensions(
1591 const char* function_name,
1592 GLint level, GLsizei width, GLsizei height, GLenum format);
1593 bool ValidateCompressedTexFuncData(
1594 const char* function_name,
1595 GLsizei width, GLsizei height, GLenum format, size_t size);
1596 bool ValidateCompressedTexSubDimensions(
1597 const char* function_name,
1598 GLenum target, GLint level, GLint xoffset, GLint yoffset,
1599 GLsizei width, GLsizei height, GLenum format,
1602 void RenderWarning(const char* filename, int line, const std::string& msg);
1603 void PerformanceWarning(
1604 const char* filename, int line, const std::string& msg);
1606 const FeatureInfo::FeatureFlags& features() const {
1607 return feature_info_->feature_flags();
1610 const FeatureInfo::Workarounds& workarounds() const {
1611 return feature_info_->workarounds();
1614 bool ShouldDeferDraws() {
1615 return !offscreen_target_frame_buffer_.get() &&
1616 framebuffer_state_.bound_draw_framebuffer.get() == NULL &&
1617 surface_->DeferDraws();
1620 bool ShouldDeferReads() {
1621 return !offscreen_target_frame_buffer_.get() &&
1622 framebuffer_state_.bound_read_framebuffer.get() == NULL &&
1623 surface_->DeferDraws();
1626 error::Error WillAccessBoundFramebufferForDraw() {
1627 if (ShouldDeferDraws())
1628 return error::kDeferCommandUntilLater;
1629 if (!offscreen_target_frame_buffer_.get() &&
1630 !framebuffer_state_.bound_draw_framebuffer.get() &&
1631 !surface_->SetBackbufferAllocation(true))
1632 return error::kLostContext;
1633 return error::kNoError;
1636 error::Error WillAccessBoundFramebufferForRead() {
1637 if (ShouldDeferReads())
1638 return error::kDeferCommandUntilLater;
1639 if (!offscreen_target_frame_buffer_.get() &&
1640 !framebuffer_state_.bound_read_framebuffer.get() &&
1641 !surface_->SetBackbufferAllocation(true))
1642 return error::kLostContext;
1643 return error::kNoError;
1646 // Set remaining commands to process to 0 to force DoCommands to return
1647 // and allow context preemption and GPU watchdog checks in GpuScheduler().
1648 void ExitCommandProcessingEarly() { commands_to_process_ = 0; }
1650 void ProcessPendingReadPixels();
1651 void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
1653 // Generate a member function prototype for each command in an automated and
1655 #define GLES2_CMD_OP(name) \
1656 Error Handle##name(uint32 immediate_data_size, const void* data);
1658 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1662 // The GL context this decoder renders to on behalf of the client.
1663 scoped_refptr<gfx::GLSurface> surface_;
1664 scoped_refptr<gfx::GLContext> context_;
1666 // The ContextGroup for this decoder uses to track resources.
1667 scoped_refptr<ContextGroup> group_;
1669 DebugMarkerManager debug_marker_manager_;
1672 // All the state for this context.
1673 ContextState state_;
1675 // Current width and height of the offscreen frame buffer.
1676 gfx::Size offscreen_size_;
1678 // Util to help with GL.
1681 // unpack flip y as last set by glPixelStorei
1682 bool unpack_flip_y_;
1684 // unpack (un)premultiply alpha as last set by glPixelStorei
1685 bool unpack_premultiply_alpha_;
1686 bool unpack_unpremultiply_alpha_;
1688 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1689 GLuint attrib_0_buffer_id_;
1691 // The value currently in attrib_0.
1692 Vec4 attrib_0_value_;
1694 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1695 bool attrib_0_buffer_matches_value_;
1697 // The size of attrib 0.
1698 GLsizei attrib_0_size_;
1700 // The buffer used to simulate GL_FIXED attribs.
1701 GLuint fixed_attrib_buffer_id_;
1703 // The size of fiixed attrib buffer.
1704 GLsizei fixed_attrib_buffer_size_;
1706 // The offscreen frame buffer that the client renders to. With EGL, the
1707 // depth and stencil buffers are separate. With regular GL there is a single
1708 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1709 // offscreen_target_stencil_render_buffer_ is unused.
1710 scoped_ptr<BackFramebuffer> offscreen_target_frame_buffer_;
1711 scoped_ptr<BackTexture> offscreen_target_color_texture_;
1712 scoped_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_;
1713 scoped_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_;
1714 scoped_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_;
1715 GLenum offscreen_target_color_format_;
1716 GLenum offscreen_target_depth_format_;
1717 GLenum offscreen_target_stencil_format_;
1718 GLsizei offscreen_target_samples_;
1719 GLboolean offscreen_target_buffer_preserved_;
1721 // The copy that is saved when SwapBuffers is called.
1722 scoped_ptr<BackFramebuffer> offscreen_saved_frame_buffer_;
1723 scoped_ptr<BackTexture> offscreen_saved_color_texture_;
1724 scoped_refptr<TextureRef>
1725 offscreen_saved_color_texture_info_;
1727 // The copy that is used as the destination for multi-sample resolves.
1728 scoped_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_;
1729 scoped_ptr<BackTexture> offscreen_resolved_color_texture_;
1730 GLenum offscreen_saved_color_format_;
1732 scoped_ptr<QueryManager> query_manager_;
1734 scoped_ptr<VertexArrayManager> vertex_array_manager_;
1736 scoped_ptr<ImageManager> image_manager_;
1738 base::Callback<void(gfx::Size, float)> resize_callback_;
1740 WaitSyncPointCallback wait_sync_point_callback_;
1742 ShaderCacheCallback shader_cache_callback_;
1744 scoped_ptr<AsyncPixelTransferManager> async_pixel_transfer_manager_;
1746 // The format of the back buffer_
1747 GLenum back_buffer_color_format_;
1748 bool back_buffer_has_depth_;
1749 bool back_buffer_has_stencil_;
1753 // Backbuffer attachments that are currently undefined.
1754 uint32 backbuffer_needs_clear_bits_;
1756 // The current decoder error communicates the decoder error through command
1757 // processing functions that do not return the error value. Should be set only
1758 // if not returning an error.
1759 error::Error current_decoder_error_;
1761 bool use_shader_translator_;
1762 scoped_refptr<ShaderTranslator> vertex_translator_;
1763 scoped_refptr<ShaderTranslator> fragment_translator_;
1765 DisallowedFeatures disallowed_features_;
1767 // Cached from ContextGroup
1768 const Validators* validators_;
1769 scoped_refptr<FeatureInfo> feature_info_;
1773 // Number of commands remaining to be processed in DoCommands().
1774 int commands_to_process_;
1776 bool has_robustness_extension_;
1777 GLenum reset_status_;
1778 bool reset_by_robustness_extension_;
1779 bool supports_post_sub_buffer_;
1781 // These flags are used to override the state of the shared feature_info_
1782 // member. Because the same FeatureInfo instance may be shared among many
1783 // contexts, the assumptions on the availablity of extensions in WebGL
1784 // contexts may be broken. These flags override the shared state to preserve
1786 bool force_webgl_glsl_validation_;
1787 bool derivatives_explicitly_enabled_;
1788 bool frag_depth_explicitly_enabled_;
1789 bool draw_buffers_explicitly_enabled_;
1790 bool shader_texture_lod_explicitly_enabled_;
1792 bool compile_shader_always_succeeds_;
1794 // An optional behaviour to lose the context and group when OOM.
1795 bool lose_context_when_out_of_memory_;
1798 bool service_logging_;
1800 #if defined(OS_MACOSX)
1801 typedef std::map<GLuint, IOSurfaceRef> TextureToIOSurfaceMap;
1802 TextureToIOSurfaceMap texture_to_io_surface_map_;
1805 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
1807 // Cached values of the currently assigned viewport dimensions.
1808 GLsizei viewport_max_width_;
1809 GLsizei viewport_max_height_;
1811 // Command buffer stats.
1812 base::TimeDelta total_processing_commands_time_;
1814 // States related to each manager.
1815 DecoderTextureState texture_state_;
1816 DecoderFramebufferState framebuffer_state_;
1818 scoped_ptr<GPUTracer> gpu_tracer_;
1819 scoped_ptr<GPUStateTracer> gpu_state_tracer_;
1820 const unsigned char* cb_command_trace_category_;
1821 int gpu_trace_level_;
1822 bool gpu_trace_commands_;
1823 bool gpu_debug_commands_;
1825 std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_;
1827 // Used to validate multisample renderbuffers if needed
1828 GLuint validation_texture_;
1829 GLuint validation_fbo_multisample_;
1830 GLuint validation_fbo_;
1832 typedef gpu::gles2::GLES2Decoder::Error (GLES2DecoderImpl::*CmdHandler)(
1833 uint32 immediate_data_size,
1836 // A struct to hold info about each command.
1837 struct CommandInfo {
1838 CmdHandler cmd_handler;
1839 uint8 arg_flags; // How to handle the arguments for this command
1840 uint8 cmd_flags; // How to handle this command
1841 uint16 arg_count; // How many arguments are expected for this command.
1844 // A table of CommandInfo for all the commands.
1845 static const CommandInfo command_info[kNumCommands - kStartPoint];
1847 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1850 const GLES2DecoderImpl::CommandInfo GLES2DecoderImpl::command_info[] = {
1851 #define GLES2_CMD_OP(name) \
1853 &GLES2DecoderImpl::Handle##name, cmds::name::kArgFlags, \
1854 cmds::name::cmd_flags, \
1855 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, \
1858 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1862 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
1863 const char* function_name, ErrorState* error_state)
1864 : function_name_(function_name),
1865 error_state_(error_state) {
1866 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_, function_name_);
1869 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1870 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_, function_name_);
1873 static void RestoreCurrentTextureBindings(ContextState* state, GLenum target) {
1874 TextureUnit& info = state->texture_units[0];
1876 scoped_refptr<TextureRef> texture_ref;
1879 texture_ref = info.bound_texture_2d;
1881 case GL_TEXTURE_CUBE_MAP:
1882 texture_ref = info.bound_texture_cube_map;
1884 case GL_TEXTURE_EXTERNAL_OES:
1885 texture_ref = info.bound_texture_external_oes;
1887 case GL_TEXTURE_RECTANGLE_ARB:
1888 texture_ref = info.bound_texture_rectangle_arb;
1894 if (texture_ref.get()) {
1895 last_id = texture_ref->service_id();
1900 glBindTexture(target, last_id);
1901 glActiveTexture(GL_TEXTURE0 + state->active_texture_unit);
1904 ScopedTextureBinder::ScopedTextureBinder(ContextState* state,
1909 ScopedGLErrorSuppressor suppressor(
1910 "ScopedTextureBinder::ctor", state_->GetErrorState());
1912 // TODO(apatrick): Check if there are any other states that need to be reset
1913 // before binding a new texture.
1914 glActiveTexture(GL_TEXTURE0);
1915 glBindTexture(target, id);
1918 ScopedTextureBinder::~ScopedTextureBinder() {
1919 ScopedGLErrorSuppressor suppressor(
1920 "ScopedTextureBinder::dtor", state_->GetErrorState());
1921 RestoreCurrentTextureBindings(state_, target_);
1924 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState* state,
1927 ScopedGLErrorSuppressor suppressor(
1928 "ScopedRenderBufferBinder::ctor", state_->GetErrorState());
1929 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1932 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1933 ScopedGLErrorSuppressor suppressor(
1934 "ScopedRenderBufferBinder::dtor", state_->GetErrorState());
1935 state_->RestoreRenderbufferBindings();
1938 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1940 : decoder_(decoder) {
1941 ScopedGLErrorSuppressor suppressor(
1942 "ScopedFrameBufferBinder::ctor", decoder_->GetErrorState());
1943 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1944 decoder->OnFboChanged();
1947 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1948 ScopedGLErrorSuppressor suppressor(
1949 "ScopedFrameBufferBinder::dtor", decoder_->GetErrorState());
1950 decoder_->RestoreCurrentFramebufferBindings();
1953 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
1954 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
1955 : decoder_(decoder) {
1956 resolve_and_bind_ = (
1957 decoder_->offscreen_target_frame_buffer_.get() &&
1958 decoder_->IsOffscreenBufferMultisampled() &&
1959 (!decoder_->framebuffer_state_.bound_read_framebuffer.get() ||
1960 enforce_internal_framebuffer));
1961 if (!resolve_and_bind_)
1964 ScopedGLErrorSuppressor suppressor(
1965 "ScopedResolvedFrameBufferBinder::ctor", decoder_->GetErrorState());
1966 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1967 decoder_->offscreen_target_frame_buffer_->id());
1970 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
1971 decoder_->offscreen_resolved_frame_buffer_.reset(
1972 new BackFramebuffer(decoder_));
1973 decoder_->offscreen_resolved_frame_buffer_->Create();
1974 decoder_->offscreen_resolved_color_texture_.reset(
1975 new BackTexture(decoder->memory_tracker(), &decoder->state_));
1976 decoder_->offscreen_resolved_color_texture_->Create();
1978 DCHECK(decoder_->offscreen_saved_color_format_);
1979 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
1980 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_,
1982 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
1983 decoder_->offscreen_resolved_color_texture_.get());
1984 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
1985 GL_FRAMEBUFFER_COMPLETE) {
1986 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
1987 << "because offscreen resolved FBO was incomplete.";
1991 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
1993 targetid = decoder_->offscreen_saved_frame_buffer_->id();
1995 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
1996 const int width = decoder_->offscreen_size_.width();
1997 const int height = decoder_->offscreen_size_.height();
1998 decoder->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
1999 decoder->BlitFramebufferHelper(0,
2007 GL_COLOR_BUFFER_BIT,
2009 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
2012 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
2013 if (!resolve_and_bind_)
2016 ScopedGLErrorSuppressor suppressor(
2017 "ScopedResolvedFrameBufferBinder::dtor", decoder_->GetErrorState());
2018 decoder_->RestoreCurrentFramebufferBindings();
2019 if (decoder_->state_.enable_flags.scissor_test) {
2020 decoder_->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
2024 BackTexture::BackTexture(
2025 MemoryTracker* memory_tracker,
2026 ContextState* state)
2027 : memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2029 bytes_allocated_(0),
2033 BackTexture::~BackTexture() {
2034 // This does not destroy the render texture because that would require that
2035 // the associated GL context was current. Just check that it was explicitly
2040 void BackTexture::Create() {
2041 ScopedGLErrorSuppressor suppressor("BackTexture::Create",
2042 state_->GetErrorState());
2044 glGenTextures(1, &id_);
2045 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2046 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2047 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2048 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2049 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2051 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
2052 // never called on an offscreen context, no data will ever be uploaded to the
2053 // saved offscreen color texture (it is deferred until to when SwapBuffers
2054 // is called). My idea is that some nvidia drivers might have a bug where
2055 // deleting a texture that has never been populated might cause a
2058 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2060 bytes_allocated_ = 16u * 16u * 4u;
2061 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2064 bool BackTexture::AllocateStorage(
2065 const gfx::Size& size, GLenum format, bool zero) {
2067 ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage",
2068 state_->GetErrorState());
2069 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2070 uint32 image_size = 0;
2071 GLES2Util::ComputeImageDataSizes(
2072 size.width(), size.height(), format, GL_UNSIGNED_BYTE, 8, &image_size,
2075 if (!memory_tracker_.EnsureGPUMemoryAvailable(image_size)) {
2079 scoped_ptr<char[]> zero_data;
2081 zero_data.reset(new char[image_size]);
2082 memset(zero_data.get(), 0, image_size);
2085 glTexImage2D(GL_TEXTURE_2D,
2097 bool success = glGetError() == GL_NO_ERROR;
2099 memory_tracker_.TrackMemFree(bytes_allocated_);
2100 bytes_allocated_ = image_size;
2101 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2106 void BackTexture::Copy(const gfx::Size& size, GLenum format) {
2108 ScopedGLErrorSuppressor suppressor("BackTexture::Copy",
2109 state_->GetErrorState());
2110 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2111 glCopyTexImage2D(GL_TEXTURE_2D,
2120 void BackTexture::Destroy() {
2122 ScopedGLErrorSuppressor suppressor("BackTexture::Destroy",
2123 state_->GetErrorState());
2124 glDeleteTextures(1, &id_);
2127 memory_tracker_.TrackMemFree(bytes_allocated_);
2128 bytes_allocated_ = 0;
2131 void BackTexture::Invalidate() {
2135 BackRenderbuffer::BackRenderbuffer(
2136 RenderbufferManager* renderbuffer_manager,
2137 MemoryTracker* memory_tracker,
2138 ContextState* state)
2139 : renderbuffer_manager_(renderbuffer_manager),
2140 memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2142 bytes_allocated_(0),
2146 BackRenderbuffer::~BackRenderbuffer() {
2147 // This does not destroy the render buffer because that would require that
2148 // the associated GL context was current. Just check that it was explicitly
2153 void BackRenderbuffer::Create() {
2154 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create",
2155 state_->GetErrorState());
2157 glGenRenderbuffersEXT(1, &id_);
2160 bool BackRenderbuffer::AllocateStorage(const FeatureInfo* feature_info,
2161 const gfx::Size& size,
2164 ScopedGLErrorSuppressor suppressor(
2165 "BackRenderbuffer::AllocateStorage", state_->GetErrorState());
2166 ScopedRenderBufferBinder binder(state_, id_);
2168 uint32 estimated_size = 0;
2169 if (!renderbuffer_manager_->ComputeEstimatedRenderbufferSize(
2170 size.width(), size.height(), samples, format, &estimated_size)) {
2174 if (!memory_tracker_.EnsureGPUMemoryAvailable(estimated_size)) {
2179 glRenderbufferStorageEXT(GL_RENDERBUFFER,
2184 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info,
2191 bool success = glGetError() == GL_NO_ERROR;
2193 // Mark the previously allocated bytes as free.
2194 memory_tracker_.TrackMemFree(bytes_allocated_);
2195 bytes_allocated_ = estimated_size;
2196 // Track the newly allocated bytes.
2197 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2202 void BackRenderbuffer::Destroy() {
2204 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy",
2205 state_->GetErrorState());
2206 glDeleteRenderbuffersEXT(1, &id_);
2209 memory_tracker_.TrackMemFree(bytes_allocated_);
2210 bytes_allocated_ = 0;
2213 void BackRenderbuffer::Invalidate() {
2217 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl* decoder)
2218 : decoder_(decoder),
2222 BackFramebuffer::~BackFramebuffer() {
2223 // This does not destroy the frame buffer because that would require that
2224 // the associated GL context was current. Just check that it was explicitly
2229 void BackFramebuffer::Create() {
2230 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create",
2231 decoder_->GetErrorState());
2233 glGenFramebuffersEXT(1, &id_);
2236 void BackFramebuffer::AttachRenderTexture(BackTexture* texture) {
2238 ScopedGLErrorSuppressor suppressor(
2239 "BackFramebuffer::AttachRenderTexture", decoder_->GetErrorState());
2240 ScopedFrameBufferBinder binder(decoder_, id_);
2241 GLuint attach_id = texture ? texture->id() : 0;
2242 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2243 GL_COLOR_ATTACHMENT0,
2249 void BackFramebuffer::AttachRenderBuffer(GLenum target,
2250 BackRenderbuffer* render_buffer) {
2252 ScopedGLErrorSuppressor suppressor(
2253 "BackFramebuffer::AttachRenderBuffer", decoder_->GetErrorState());
2254 ScopedFrameBufferBinder binder(decoder_, id_);
2255 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
2256 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
2262 void BackFramebuffer::Destroy() {
2264 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy",
2265 decoder_->GetErrorState());
2266 glDeleteFramebuffersEXT(1, &id_);
2271 void BackFramebuffer::Invalidate() {
2275 GLenum BackFramebuffer::CheckStatus() {
2277 ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus",
2278 decoder_->GetErrorState());
2279 ScopedFrameBufferBinder binder(decoder_, id_);
2280 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
2283 GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
2284 return new GLES2DecoderImpl(group);
2287 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
2290 logger_(&debug_marker_manager_),
2291 state_(group_->feature_info(), this, &logger_),
2292 unpack_flip_y_(false),
2293 unpack_premultiply_alpha_(false),
2294 unpack_unpremultiply_alpha_(false),
2295 attrib_0_buffer_id_(0),
2296 attrib_0_buffer_matches_value_(true),
2298 fixed_attrib_buffer_id_(0),
2299 fixed_attrib_buffer_size_(0),
2300 offscreen_target_color_format_(0),
2301 offscreen_target_depth_format_(0),
2302 offscreen_target_stencil_format_(0),
2303 offscreen_target_samples_(0),
2304 offscreen_target_buffer_preserved_(true),
2305 offscreen_saved_color_format_(0),
2306 back_buffer_color_format_(0),
2307 back_buffer_has_depth_(false),
2308 back_buffer_has_stencil_(false),
2309 surfaceless_(false),
2310 backbuffer_needs_clear_bits_(0),
2311 current_decoder_error_(error::kNoError),
2312 use_shader_translator_(true),
2313 validators_(group_->feature_info()->validators()),
2314 feature_info_(group_->feature_info()),
2316 has_robustness_extension_(false),
2317 reset_status_(GL_NO_ERROR),
2318 reset_by_robustness_extension_(false),
2319 supports_post_sub_buffer_(false),
2320 force_webgl_glsl_validation_(false),
2321 derivatives_explicitly_enabled_(false),
2322 frag_depth_explicitly_enabled_(false),
2323 draw_buffers_explicitly_enabled_(false),
2324 shader_texture_lod_explicitly_enabled_(false),
2325 compile_shader_always_succeeds_(false),
2326 lose_context_when_out_of_memory_(false),
2327 service_logging_(CommandLine::ForCurrentProcess()->HasSwitch(
2328 switches::kEnableGPUServiceLoggingGPU)),
2329 viewport_max_width_(0),
2330 viewport_max_height_(0),
2331 texture_state_(group_->feature_info()
2333 .texsubimage2d_faster_than_teximage2d),
2334 cb_command_trace_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2335 TRACE_DISABLED_BY_DEFAULT("cb_command"))),
2336 gpu_trace_level_(2),
2337 gpu_trace_commands_(false),
2338 gpu_debug_commands_(false),
2339 validation_texture_(0),
2340 validation_fbo_multisample_(0),
2341 validation_fbo_(0) {
2344 attrib_0_value_.v[0] = 0.0f;
2345 attrib_0_value_.v[1] = 0.0f;
2346 attrib_0_value_.v[2] = 0.0f;
2347 attrib_0_value_.v[3] = 1.0f;
2349 // The shader translator is used for WebGL even when running on EGL
2350 // because additional restrictions are needed (like only enabling
2351 // GL_OES_standard_derivatives on demand). It is used for the unit
2352 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2353 // the empty string to CompileShader and this is not a valid shader.
2354 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
2355 CommandLine::ForCurrentProcess()->HasSwitch(
2356 switches::kDisableGLSLTranslator)) {
2357 use_shader_translator_ = false;
2361 GLES2DecoderImpl::~GLES2DecoderImpl() {
2364 bool GLES2DecoderImpl::Initialize(
2365 const scoped_refptr<gfx::GLSurface>& surface,
2366 const scoped_refptr<gfx::GLContext>& context,
2368 const gfx::Size& size,
2369 const DisallowedFeatures& disallowed_features,
2370 const std::vector<int32>& attribs) {
2371 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2372 DCHECK(context->IsCurrent(surface.get()));
2373 DCHECK(!context_.get());
2375 surfaceless_ = surface->IsSurfaceless();
2378 gpu_tracer_.reset(new GPUTracer(this));
2379 gpu_state_tracer_ = GPUStateTracer::Create(&state_);
2381 if (CommandLine::ForCurrentProcess()->HasSwitch(
2382 switches::kEnableGPUDebugging)) {
2386 if (CommandLine::ForCurrentProcess()->HasSwitch(
2387 switches::kEnableGPUCommandLogging)) {
2388 set_log_commands(true);
2391 compile_shader_always_succeeds_ = CommandLine::ForCurrentProcess()->HasSwitch(
2392 switches::kCompileShaderAlwaysSucceeds);
2395 // Take ownership of the context and surface. The surface can be replaced with
2400 ContextCreationAttribHelper attrib_parser;
2401 if (!attrib_parser.Parse(attribs))
2404 // Save the loseContextWhenOutOfMemory context creation attribute.
2405 lose_context_when_out_of_memory_ =
2406 attrib_parser.lose_context_when_out_of_memory;
2408 // If the failIfMajorPerformanceCaveat context creation attribute was true
2409 // and we are using a software renderer, fail.
2410 if (attrib_parser.fail_if_major_perf_caveat &&
2411 feature_info_->feature_flags().is_swiftshader) {
2412 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2417 if (!group_->Initialize(this, disallowed_features)) {
2418 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
2419 << "failed to initialize.";
2420 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2426 disallowed_features_ = disallowed_features;
2428 state_.attrib_values.resize(group_->max_vertex_attribs());
2429 vertex_array_manager_.reset(new VertexArrayManager());
2431 GLuint default_vertex_attrib_service_id = 0;
2432 if (features().native_vertex_array_object) {
2433 glGenVertexArraysOES(1, &default_vertex_attrib_service_id);
2434 glBindVertexArrayOES(default_vertex_attrib_service_id);
2437 state_.default_vertex_attrib_manager =
2438 CreateVertexAttribManager(0, default_vertex_attrib_service_id, false);
2440 state_.default_vertex_attrib_manager->Initialize(
2441 group_->max_vertex_attribs(),
2442 feature_info_->workarounds().init_vertex_attributes);
2444 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2445 DoBindVertexArrayOES(0);
2447 query_manager_.reset(new QueryManager(this, feature_info_.get()));
2449 image_manager_.reset(new ImageManager);
2451 util_.set_num_compressed_texture_formats(
2452 validators_->compressed_texture_format.GetValues().size());
2454 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2455 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2456 // OpenGL ES 2.0 does not have this issue.
2457 glEnableVertexAttribArray(0);
2459 glGenBuffersARB(1, &attrib_0_buffer_id_);
2460 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2461 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2462 glBindBuffer(GL_ARRAY_BUFFER, 0);
2463 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
2465 state_.texture_units.resize(group_->max_texture_units());
2466 for (uint32 tt = 0; tt < state_.texture_units.size(); ++tt) {
2467 glActiveTexture(GL_TEXTURE0 + tt);
2468 // We want the last bind to be 2D.
2470 if (features().oes_egl_image_external) {
2471 ref = texture_manager()->GetDefaultTextureInfo(
2472 GL_TEXTURE_EXTERNAL_OES);
2473 state_.texture_units[tt].bound_texture_external_oes = ref;
2474 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref ? ref->service_id() : 0);
2476 if (features().arb_texture_rectangle) {
2477 ref = texture_manager()->GetDefaultTextureInfo(
2478 GL_TEXTURE_RECTANGLE_ARB);
2479 state_.texture_units[tt].bound_texture_rectangle_arb = ref;
2480 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref ? ref->service_id() : 0);
2482 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
2483 state_.texture_units[tt].bound_texture_cube_map = ref;
2484 glBindTexture(GL_TEXTURE_CUBE_MAP, ref ? ref->service_id() : 0);
2485 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2486 state_.texture_units[tt].bound_texture_2d = ref;
2487 glBindTexture(GL_TEXTURE_2D, ref ? ref->service_id() : 0);
2489 glActiveTexture(GL_TEXTURE0);
2493 if (attrib_parser.samples > 0 && attrib_parser.sample_buffers > 0 &&
2494 features().chromium_framebuffer_multisample) {
2495 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2496 // max_sample_count must be initialized to a sane value. If
2497 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2498 GLint max_sample_count = 1;
2499 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2500 offscreen_target_samples_ = std::min(attrib_parser.samples,
2503 offscreen_target_samples_ = 1;
2505 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved;
2507 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2508 const bool rgb8_supported =
2509 context_->HasExtension("GL_OES_rgb8_rgba8");
2510 // The only available default render buffer formats in GLES2 have very
2511 // little precision. Don't enable multisampling unless 8-bit render
2512 // buffer formats are available--instead fall back to 8-bit textures.
2513 if (rgb8_supported && offscreen_target_samples_ > 1) {
2514 offscreen_target_color_format_ = attrib_parser.alpha_size > 0 ?
2517 offscreen_target_samples_ = 1;
2518 offscreen_target_color_format_ = attrib_parser.alpha_size > 0 ?
2522 // ANGLE only supports packed depth/stencil formats, so use it if it is
2524 const bool depth24_stencil8_supported =
2525 feature_info_->feature_flags().packed_depth24_stencil8;
2526 VLOG(1) << "GL_OES_packed_depth_stencil "
2527 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2528 if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) &&
2529 depth24_stencil8_supported) {
2530 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2531 offscreen_target_stencil_format_ = 0;
2533 // It may be the case that this depth/stencil combination is not
2534 // supported, but this will be checked later by CheckFramebufferStatus.
2535 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2536 GL_DEPTH_COMPONENT16 : 0;
2537 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2538 GL_STENCIL_INDEX8 : 0;
2541 offscreen_target_color_format_ = attrib_parser.alpha_size > 0 ?
2544 // If depth is requested at all, use the packed depth stencil format if
2545 // it's available, as some desktop GL drivers don't support any non-packed
2546 // formats for depth attachments.
2547 const bool depth24_stencil8_supported =
2548 feature_info_->feature_flags().packed_depth24_stencil8;
2549 VLOG(1) << "GL_EXT_packed_depth_stencil "
2550 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2552 if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) &&
2553 depth24_stencil8_supported) {
2554 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2555 offscreen_target_stencil_format_ = 0;
2557 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2558 GL_DEPTH_COMPONENT : 0;
2559 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2560 GL_STENCIL_INDEX : 0;
2564 offscreen_saved_color_format_ = attrib_parser.alpha_size > 0 ?
2567 // Create the target frame buffer. This is the one that the client renders
2569 offscreen_target_frame_buffer_.reset(new BackFramebuffer(this));
2570 offscreen_target_frame_buffer_->Create();
2571 // Due to GLES2 format limitations, either the color texture (for
2572 // non-multisampling) or the color render buffer (for multisampling) will be
2573 // attached to the offscreen frame buffer. The render buffer has more
2574 // limited formats available to it, but the texture can't do multisampling.
2575 if (IsOffscreenBufferMultisampled()) {
2576 offscreen_target_color_render_buffer_.reset(new BackRenderbuffer(
2577 renderbuffer_manager(), memory_tracker(), &state_));
2578 offscreen_target_color_render_buffer_->Create();
2580 offscreen_target_color_texture_.reset(new BackTexture(
2581 memory_tracker(), &state_));
2582 offscreen_target_color_texture_->Create();
2584 offscreen_target_depth_render_buffer_.reset(new BackRenderbuffer(
2585 renderbuffer_manager(), memory_tracker(), &state_));
2586 offscreen_target_depth_render_buffer_->Create();
2587 offscreen_target_stencil_render_buffer_.reset(new BackRenderbuffer(
2588 renderbuffer_manager(), memory_tracker(), &state_));
2589 offscreen_target_stencil_render_buffer_->Create();
2591 // Create the saved offscreen texture. The target frame buffer is copied
2592 // here when SwapBuffers is called.
2593 offscreen_saved_frame_buffer_.reset(new BackFramebuffer(this));
2594 offscreen_saved_frame_buffer_->Create();
2596 offscreen_saved_color_texture_.reset(new BackTexture(
2597 memory_tracker(), &state_));
2598 offscreen_saved_color_texture_->Create();
2600 // Allocate the render buffers at their initial size and check the status
2601 // of the frame buffers is okay.
2602 if (!ResizeOffscreenFrameBuffer(size)) {
2603 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
2608 // Allocate the offscreen saved color texture.
2609 DCHECK(offscreen_saved_color_format_);
2610 offscreen_saved_color_texture_->AllocateStorage(
2611 gfx::Size(1, 1), offscreen_saved_color_format_, true);
2613 offscreen_saved_frame_buffer_->AttachRenderTexture(
2614 offscreen_saved_color_texture_.get());
2615 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2616 GL_FRAMEBUFFER_COMPLETE) {
2617 LOG(ERROR) << "Offscreen saved FBO was incomplete.";
2622 // Bind to the new default frame buffer (the offscreen target frame buffer).
2623 // This should now be associated with ID zero.
2624 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2626 glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId());
2627 // These are NOT if the back buffer has these proprorties. They are
2628 // if we want the command buffer to enforce them regardless of what
2629 // the real backbuffer is assuming the real back buffer gives us more than
2630 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2631 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2632 // can't do anything about that.
2634 if (!surfaceless_) {
2636 glGetIntegerv(GL_ALPHA_BITS, &v);
2637 // This checks if the user requested RGBA and we have RGBA then RGBA. If
2638 // the user requested RGB then RGB. If the user did not specify a
2639 // preference than use whatever we were given. Same for DEPTH and STENCIL.
2640 back_buffer_color_format_ =
2641 (attrib_parser.alpha_size != 0 && v > 0) ? GL_RGBA : GL_RGB;
2642 glGetIntegerv(GL_DEPTH_BITS, &v);
2643 back_buffer_has_depth_ = attrib_parser.depth_size != 0 && v > 0;
2644 glGetIntegerv(GL_STENCIL_BITS, &v);
2645 back_buffer_has_stencil_ = attrib_parser.stencil_size != 0 && v > 0;
2649 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2650 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2651 // isn't well documented; it was discovered in the Khronos OpenGL ES
2652 // mailing list archives. It also implicitly enables the desktop GL
2653 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2654 // variable in fragment shaders.
2655 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2656 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
2657 glEnable(GL_POINT_SPRITE);
2660 has_robustness_extension_ =
2661 context->HasExtension("GL_ARB_robustness") ||
2662 context->HasExtension("GL_EXT_robustness");
2664 if (!InitializeShaderTranslator()) {
2668 state_.viewport_width = size.width();
2669 state_.viewport_height = size.height();
2671 GLint viewport_params[4] = { 0 };
2672 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
2673 viewport_max_width_ = viewport_params[0];
2674 viewport_max_height_ = viewport_params[1];
2676 state_.scissor_width = state_.viewport_width;
2677 state_.scissor_height = state_.viewport_height;
2679 // Set all the default state because some GL drivers get it wrong.
2680 state_.InitCapabilities(NULL);
2681 state_.InitState(NULL);
2682 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
2684 DoBindBuffer(GL_ARRAY_BUFFER, 0);
2685 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2686 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2687 DoBindRenderbuffer(GL_RENDERBUFFER, 0);
2689 bool call_gl_clear = !surfaceless_;
2690 #if defined(OS_ANDROID)
2691 // Temporary workaround for Android WebView because this clear ignores the
2692 // clip and corrupts that external UI of the App. Not calling glClear is ok
2693 // because the system already clears the buffer before each draw. Proper
2694 // fix might be setting the scissor clip properly before initialize. See
2695 // crbug.com/259023 for details.
2696 call_gl_clear = surface_->GetHandle();
2698 if (call_gl_clear) {
2699 // Clear the backbuffer.
2700 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2703 supports_post_sub_buffer_ = surface->SupportsPostSubBuffer();
2704 if (feature_info_->workarounds()
2705 .disable_post_sub_buffers_for_onscreen_surfaces &&
2706 !surface->IsOffscreen())
2707 supports_post_sub_buffer_ = false;
2709 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) {
2710 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
2713 if (feature_info_->workarounds().unbind_fbo_on_context_switch) {
2714 context_->SetUnbindFboOnMakeCurrent();
2717 // Only compositor contexts are known to use only the subset of GL
2718 // that can be safely migrated between the iGPU and the dGPU. Mark
2719 // those contexts as safe to forcibly transition between the GPUs.
2720 // http://crbug.com/180876, http://crbug.com/227228
2722 context_->SetSafeToForceGpuSwitch();
2724 async_pixel_transfer_manager_.reset(
2725 AsyncPixelTransferManager::Create(context.get()));
2726 async_pixel_transfer_manager_->Initialize(texture_manager());
2728 framebuffer_manager()->AddObserver(this);
2733 Capabilities GLES2DecoderImpl::GetCapabilities() {
2734 DCHECK(initialized());
2738 caps.egl_image_external =
2739 feature_info_->feature_flags().oes_egl_image_external;
2740 caps.texture_format_bgra8888 =
2741 feature_info_->feature_flags().ext_texture_format_bgra8888;
2742 caps.texture_format_etc1 =
2743 feature_info_->feature_flags().oes_compressed_etc1_rgb8_texture;
2744 caps.texture_format_etc1_npot =
2745 caps.texture_format_etc1 && !workarounds().etc1_power_of_two_only;
2746 caps.texture_rectangle = feature_info_->feature_flags().arb_texture_rectangle;
2747 caps.texture_usage = feature_info_->feature_flags().angle_texture_usage;
2748 caps.texture_storage = feature_info_->feature_flags().ext_texture_storage;
2749 caps.discard_framebuffer =
2750 feature_info_->feature_flags().ext_discard_framebuffer;
2751 caps.sync_query = feature_info_->feature_flags().chromium_sync_query;
2753 #if defined(OS_MACOSX)
2754 // This is unconditionally true on mac, no need to test for it at runtime.
2755 caps.iosurface = true;
2758 caps.post_sub_buffer = supports_post_sub_buffer_;
2759 caps.map_image = true;
2764 void GLES2DecoderImpl::UpdateCapabilities() {
2765 util_.set_num_compressed_texture_formats(
2766 validators_->compressed_texture_format.GetValues().size());
2767 util_.set_num_shader_binary_formats(
2768 validators_->shader_binary_format.GetValues().size());
2771 bool GLES2DecoderImpl::InitializeShaderTranslator() {
2772 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
2774 if (!use_shader_translator_) {
2777 ShBuiltInResources resources;
2778 ShInitBuiltInResources(&resources);
2779 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2780 resources.MaxVertexUniformVectors =
2781 group_->max_vertex_uniform_vectors();
2782 resources.MaxVaryingVectors = group_->max_varying_vectors();
2783 resources.MaxVertexTextureImageUnits =
2784 group_->max_vertex_texture_image_units();
2785 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2786 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2787 resources.MaxFragmentUniformVectors =
2788 group_->max_fragment_uniform_vectors();
2789 resources.MaxDrawBuffers = group_->max_draw_buffers();
2790 resources.MaxExpressionComplexity = 256;
2791 resources.MaxCallStackDepth = 256;
2793 GLint range[2] = { 0, 0 };
2794 GLint precision = 0;
2795 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
2797 resources.FragmentPrecisionHigh =
2798 PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
2800 if (force_webgl_glsl_validation_) {
2801 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
2802 resources.EXT_frag_depth = frag_depth_explicitly_enabled_;
2803 resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
2804 if (!draw_buffers_explicitly_enabled_)
2805 resources.MaxDrawBuffers = 1;
2806 resources.EXT_shader_texture_lod = shader_texture_lod_explicitly_enabled_;
2808 resources.OES_standard_derivatives =
2809 features().oes_standard_derivatives ? 1 : 0;
2810 resources.ARB_texture_rectangle =
2811 features().arb_texture_rectangle ? 1 : 0;
2812 resources.OES_EGL_image_external =
2813 features().oes_egl_image_external ? 1 : 0;
2814 resources.EXT_draw_buffers =
2815 features().ext_draw_buffers ? 1 : 0;
2816 resources.EXT_frag_depth =
2817 features().ext_frag_depth ? 1 : 0;
2818 resources.EXT_shader_texture_lod =
2819 features().ext_shader_texture_lod ? 1 : 0;
2822 ShShaderSpec shader_spec = force_webgl_glsl_validation_ ? SH_WEBGL_SPEC
2824 if (shader_spec == SH_WEBGL_SPEC && features().enable_shader_name_hashing)
2825 resources.HashFunction = &CityHash64;
2827 resources.HashFunction = NULL;
2828 ShaderTranslatorInterface::GlslImplementationType implementation_type =
2829 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
2830 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
2831 int driver_bug_workarounds = 0;
2832 if (workarounds().needs_glsl_built_in_function_emulation)
2833 driver_bug_workarounds |= SH_EMULATE_BUILT_IN_FUNCTIONS;
2834 if (workarounds().init_gl_position_in_vertex_shader)
2835 driver_bug_workarounds |= SH_INIT_GL_POSITION;
2836 if (workarounds().unfold_short_circuit_as_ternary_operation)
2837 driver_bug_workarounds |= SH_UNFOLD_SHORT_CIRCUIT;
2838 if (workarounds().init_varyings_without_static_use)
2839 driver_bug_workarounds |= SH_INIT_VARYINGS_WITHOUT_STATIC_USE;
2840 if (workarounds().unroll_for_loop_with_sampler_array_index)
2841 driver_bug_workarounds |= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX;
2842 if (workarounds().scalarize_vec_and_mat_constructor_args)
2843 driver_bug_workarounds |= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS;
2844 if (workarounds().regenerate_struct_names)
2845 driver_bug_workarounds |= SH_REGENERATE_STRUCT_NAMES;
2847 vertex_translator_ = shader_translator_cache()->GetTranslator(
2851 implementation_type,
2852 static_cast<ShCompileOptions>(driver_bug_workarounds));
2853 if (!vertex_translator_.get()) {
2854 LOG(ERROR) << "Could not initialize vertex shader translator.";
2859 fragment_translator_ = shader_translator_cache()->GetTranslator(
2863 implementation_type,
2864 static_cast<ShCompileOptions>(driver_bug_workarounds));
2865 if (!fragment_translator_.get()) {
2866 LOG(ERROR) << "Could not initialize fragment shader translator.";
2873 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
2874 for (GLsizei ii = 0; ii < n; ++ii) {
2875 if (GetBuffer(client_ids[ii])) {
2879 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2880 glGenBuffersARB(n, service_ids.get());
2881 for (GLsizei ii = 0; ii < n; ++ii) {
2882 CreateBuffer(client_ids[ii], service_ids[ii]);
2887 bool GLES2DecoderImpl::GenFramebuffersHelper(
2888 GLsizei n, const GLuint* client_ids) {
2889 for (GLsizei ii = 0; ii < n; ++ii) {
2890 if (GetFramebuffer(client_ids[ii])) {
2894 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2895 glGenFramebuffersEXT(n, service_ids.get());
2896 for (GLsizei ii = 0; ii < n; ++ii) {
2897 CreateFramebuffer(client_ids[ii], service_ids[ii]);
2902 bool GLES2DecoderImpl::GenRenderbuffersHelper(
2903 GLsizei n, const GLuint* client_ids) {
2904 for (GLsizei ii = 0; ii < n; ++ii) {
2905 if (GetRenderbuffer(client_ids[ii])) {
2909 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2910 glGenRenderbuffersEXT(n, service_ids.get());
2911 for (GLsizei ii = 0; ii < n; ++ii) {
2912 CreateRenderbuffer(client_ids[ii], service_ids[ii]);
2917 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2918 for (GLsizei ii = 0; ii < n; ++ii) {
2919 if (GetTexture(client_ids[ii])) {
2923 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2924 glGenTextures(n, service_ids.get());
2925 for (GLsizei ii = 0; ii < n; ++ii) {
2926 CreateTexture(client_ids[ii], service_ids[ii]);
2931 void GLES2DecoderImpl::DeleteBuffersHelper(
2932 GLsizei n, const GLuint* client_ids) {
2933 for (GLsizei ii = 0; ii < n; ++ii) {
2934 Buffer* buffer = GetBuffer(client_ids[ii]);
2935 if (buffer && !buffer->IsDeleted()) {
2936 state_.vertex_attrib_manager->Unbind(buffer);
2937 if (state_.bound_array_buffer.get() == buffer) {
2938 state_.bound_array_buffer = NULL;
2940 RemoveBuffer(client_ids[ii]);
2945 void GLES2DecoderImpl::DeleteFramebuffersHelper(
2946 GLsizei n, const GLuint* client_ids) {
2947 bool supports_separate_framebuffer_binds =
2948 features().chromium_framebuffer_multisample;
2950 for (GLsizei ii = 0; ii < n; ++ii) {
2951 Framebuffer* framebuffer =
2952 GetFramebuffer(client_ids[ii]);
2953 if (framebuffer && !framebuffer->IsDeleted()) {
2954 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
2955 framebuffer_state_.bound_draw_framebuffer = NULL;
2956 framebuffer_state_.clear_state_dirty = true;
2957 GLenum target = supports_separate_framebuffer_binds ?
2958 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
2959 glBindFramebufferEXT(target, GetBackbufferServiceId());
2961 if (framebuffer == framebuffer_state_.bound_read_framebuffer.get()) {
2962 framebuffer_state_.bound_read_framebuffer = NULL;
2963 GLenum target = supports_separate_framebuffer_binds ?
2964 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
2965 glBindFramebufferEXT(target, GetBackbufferServiceId());
2968 RemoveFramebuffer(client_ids[ii]);
2973 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2974 GLsizei n, const GLuint* client_ids) {
2975 bool supports_separate_framebuffer_binds =
2976 features().chromium_framebuffer_multisample;
2977 for (GLsizei ii = 0; ii < n; ++ii) {
2978 Renderbuffer* renderbuffer =
2979 GetRenderbuffer(client_ids[ii]);
2980 if (renderbuffer && !renderbuffer->IsDeleted()) {
2981 if (state_.bound_renderbuffer.get() == renderbuffer) {
2982 state_.bound_renderbuffer = NULL;
2984 // Unbind from current framebuffers.
2985 if (supports_separate_framebuffer_binds) {
2986 if (framebuffer_state_.bound_read_framebuffer.get()) {
2987 framebuffer_state_.bound_read_framebuffer
2988 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT, renderbuffer);
2990 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2991 framebuffer_state_.bound_draw_framebuffer
2992 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
2995 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2996 framebuffer_state_.bound_draw_framebuffer
2997 ->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
3000 framebuffer_state_.clear_state_dirty = true;
3001 RemoveRenderbuffer(client_ids[ii]);
3006 void GLES2DecoderImpl::DeleteTexturesHelper(
3007 GLsizei n, const GLuint* client_ids) {
3008 bool supports_separate_framebuffer_binds =
3009 features().chromium_framebuffer_multisample;
3010 for (GLsizei ii = 0; ii < n; ++ii) {
3011 TextureRef* texture_ref = GetTexture(client_ids[ii]);
3013 Texture* texture = texture_ref->texture();
3014 if (texture->IsAttachedToFramebuffer()) {
3015 framebuffer_state_.clear_state_dirty = true;
3017 // Unbind texture_ref from texture_ref units.
3018 for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) {
3019 state_.texture_units[jj].Unbind(texture_ref);
3021 // Unbind from current framebuffers.
3022 if (supports_separate_framebuffer_binds) {
3023 if (framebuffer_state_.bound_read_framebuffer.get()) {
3024 framebuffer_state_.bound_read_framebuffer
3025 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT, texture_ref);
3027 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3028 framebuffer_state_.bound_draw_framebuffer
3029 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
3032 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3033 framebuffer_state_.bound_draw_framebuffer
3034 ->UnbindTexture(GL_FRAMEBUFFER, texture_ref);
3037 #if defined(OS_MACOSX)
3038 GLuint service_id = texture->service_id();
3039 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
3040 ReleaseIOSurfaceForTexture(service_id);
3043 RemoveTexture(client_ids[ii]);
3048 // } // anonymous namespace
3050 bool GLES2DecoderImpl::MakeCurrent() {
3051 if (!context_.get())
3054 if (!context_->MakeCurrent(surface_.get()) || WasContextLost()) {
3055 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3057 // Some D3D drivers cannot recover from device lost in the GPU process
3058 // sandbox. Allow a new GPU process to launch.
3059 if (workarounds().exit_on_context_lost) {
3060 LOG(ERROR) << "Exiting GPU process because some drivers cannot reset"
3061 << " a D3D device in the Chrome GPU process sandbox.";
3063 base::win::SetShouldCrashOnProcessDetach(false);
3071 ProcessFinishedAsyncTransfers();
3073 // Rebind the FBO if it was unbound by the context.
3074 if (workarounds().unbind_fbo_on_context_switch)
3075 RestoreFramebufferBindings();
3077 framebuffer_state_.clear_state_dirty = true;
3082 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3083 ProcessPendingReadPixels();
3084 if (engine() && query_manager_.get())
3085 query_manager_->ProcessPendingTransferQueries();
3087 // TODO(epenner): Is there a better place to do this?
3088 // This needs to occur before we execute any batch of commands
3089 // from the client, as the client may have recieved an async
3090 // completion while issuing those commands.
3091 // "DidFlushStart" would be ideal if we had such a callback.
3092 async_pixel_transfer_manager_->BindCompletedAsyncTransfers();
3095 static void RebindCurrentFramebuffer(
3097 Framebuffer* framebuffer,
3098 GLuint back_buffer_service_id) {
3099 GLuint framebuffer_id = framebuffer ? framebuffer->service_id() : 0;
3101 if (framebuffer_id == 0) {
3102 framebuffer_id = back_buffer_service_id;
3105 glBindFramebufferEXT(target, framebuffer_id);
3108 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3109 framebuffer_state_.clear_state_dirty = true;
3111 if (!features().chromium_framebuffer_multisample) {
3112 RebindCurrentFramebuffer(
3114 framebuffer_state_.bound_draw_framebuffer.get(),
3115 GetBackbufferServiceId());
3117 RebindCurrentFramebuffer(
3118 GL_READ_FRAMEBUFFER_EXT,
3119 framebuffer_state_.bound_read_framebuffer.get(),
3120 GetBackbufferServiceId());
3121 RebindCurrentFramebuffer(
3122 GL_DRAW_FRAMEBUFFER_EXT,
3123 framebuffer_state_.bound_draw_framebuffer.get(),
3124 GetBackbufferServiceId());
3129 bool GLES2DecoderImpl::CheckFramebufferValid(
3130 Framebuffer* framebuffer,
3131 GLenum target, const char* func_name) {
3135 if (backbuffer_needs_clear_bits_) {
3136 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3137 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
3138 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3140 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
3141 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
3143 state_.SetDeviceDepthMask(GL_TRUE);
3144 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
3145 bool reset_draw_buffer = false;
3146 if ((backbuffer_needs_clear_bits_ | GL_COLOR_BUFFER_BIT) != 0 &&
3147 group_->draw_buffer() == GL_NONE) {
3148 reset_draw_buffer = true;
3149 GLenum buf = GL_BACK;
3150 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3151 buf = GL_COLOR_ATTACHMENT0;
3152 glDrawBuffersARB(1, &buf);
3154 glClear(backbuffer_needs_clear_bits_);
3155 if (reset_draw_buffer) {
3156 GLenum buf = GL_NONE;
3157 glDrawBuffersARB(1, &buf);
3159 backbuffer_needs_clear_bits_ = 0;
3160 RestoreClearState();
3165 if (framebuffer_manager()->IsComplete(framebuffer)) {
3169 GLenum completeness = framebuffer->IsPossiblyComplete();
3170 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
3172 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
3176 // Are all the attachments cleared?
3177 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3178 texture_manager()->HaveUnclearedMips()) {
3179 if (!framebuffer->IsCleared()) {
3180 // Can we clear them?
3181 if (framebuffer->GetStatus(texture_manager(), target) !=
3182 GL_FRAMEBUFFER_COMPLETE) {
3184 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3185 "framebuffer incomplete (clear)");
3188 ClearUnclearedAttachments(target, framebuffer);
3192 if (!framebuffer_manager()->IsComplete(framebuffer)) {
3193 if (framebuffer->GetStatus(texture_manager(), target) !=
3194 GL_FRAMEBUFFER_COMPLETE) {
3196 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3197 "framebuffer incomplete (check)");
3200 framebuffer_manager()->MarkAsComplete(framebuffer);
3203 // NOTE: At this point we don't know if the framebuffer is complete but
3204 // we DO know that everything that needs to be cleared has been cleared.
3208 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
3209 if (!features().chromium_framebuffer_multisample) {
3210 bool valid = CheckFramebufferValid(
3211 framebuffer_state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT,
3219 return CheckFramebufferValid(framebuffer_state_.bound_draw_framebuffer.get(),
3220 GL_DRAW_FRAMEBUFFER_EXT,
3222 CheckFramebufferValid(framebuffer_state_.bound_read_framebuffer.get(),
3223 GL_READ_FRAMEBUFFER_EXT,
3227 bool GLES2DecoderImpl::CheckBoundReadFramebufferColorAttachment(
3228 const char* func_name) {
3229 Framebuffer* framebuffer = features().chromium_framebuffer_multisample ?
3230 framebuffer_state_.bound_read_framebuffer.get() :
3231 framebuffer_state_.bound_draw_framebuffer.get();
3234 if (framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0) == NULL) {
3236 GL_INVALID_OPERATION, func_name, "no color image attached");
3242 gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3243 Framebuffer* framebuffer =
3244 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3245 if (framebuffer != NULL) {
3246 const Framebuffer::Attachment* attachment =
3247 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
3249 return gfx::Size(attachment->width(), attachment->height());
3251 return gfx::Size(0, 0);
3252 } else if (offscreen_target_frame_buffer_.get()) {
3253 return offscreen_size_;
3255 return surface_->GetSize();
3259 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3260 Framebuffer* framebuffer =
3261 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3262 if (framebuffer != NULL) {
3263 return framebuffer->GetColorAttachmentTextureType();
3265 return GL_UNSIGNED_BYTE;
3269 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3270 Framebuffer* framebuffer =
3271 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3272 if (framebuffer != NULL) {
3273 return framebuffer->GetColorAttachmentFormat();
3274 } else if (offscreen_target_frame_buffer_.get()) {
3275 return offscreen_target_color_format_;
3277 return back_buffer_color_format_;
3281 GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3282 Framebuffer* framebuffer =
3283 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3284 if (framebuffer != NULL) {
3285 return framebuffer->GetColorAttachmentFormat();
3286 } else if (offscreen_target_frame_buffer_.get()) {
3287 return offscreen_target_color_format_;
3289 return back_buffer_color_format_;
3293 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3294 if (!offscreen_saved_color_texture_info_.get())
3296 GLenum target = offscreen_saved_color_texture_info_->texture()->target();
3297 glBindTexture(target, offscreen_saved_color_texture_info_->service_id());
3298 texture_manager()->SetLevelInfo(
3299 offscreen_saved_color_texture_info_.get(),
3303 offscreen_size_.width(),
3304 offscreen_size_.height(),
3310 texture_manager()->SetParameteri(
3311 "UpdateParentTextureInfo",
3313 offscreen_saved_color_texture_info_.get(),
3314 GL_TEXTURE_MAG_FILTER,
3316 texture_manager()->SetParameteri(
3317 "UpdateParentTextureInfo",
3319 offscreen_saved_color_texture_info_.get(),
3320 GL_TEXTURE_MIN_FILTER,
3322 texture_manager()->SetParameteri(
3323 "UpdateParentTextureInfo",
3325 offscreen_saved_color_texture_info_.get(),
3328 texture_manager()->SetParameteri(
3329 "UpdateParentTextureInfo",
3331 offscreen_saved_color_texture_info_.get(),
3334 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
3336 glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
3339 void GLES2DecoderImpl::SetResizeCallback(
3340 const base::Callback<void(gfx::Size, float)>& callback) {
3341 resize_callback_ = callback;
3344 Logger* GLES2DecoderImpl::GetLogger() {
3348 void GLES2DecoderImpl::BeginDecoding() {
3349 gpu_tracer_->BeginDecoding();
3350 gpu_trace_commands_ = gpu_tracer_->IsTracing();
3351 gpu_debug_commands_ = log_commands() || debug() || gpu_trace_commands_ ||
3352 (*cb_command_trace_category_ != 0);
3355 void GLES2DecoderImpl::EndDecoding() {
3356 gpu_tracer_->EndDecoding();
3359 ErrorState* GLES2DecoderImpl::GetErrorState() {
3360 return state_.GetErrorState();
3363 void GLES2DecoderImpl::SetShaderCacheCallback(
3364 const ShaderCacheCallback& callback) {
3365 shader_cache_callback_ = callback;
3368 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3369 const WaitSyncPointCallback& callback) {
3370 wait_sync_point_callback_ = callback;
3373 AsyncPixelTransferManager*
3374 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3375 return async_pixel_transfer_manager_.get();
3378 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3379 async_pixel_transfer_manager_.reset();
3382 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3383 AsyncPixelTransferManager* manager) {
3384 async_pixel_transfer_manager_ = make_scoped_ptr(manager);
3387 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
3388 uint32* service_texture_id) {
3389 TextureRef* texture_ref = texture_manager()->GetTexture(client_texture_id);
3391 *service_texture_id = texture_ref->service_id();
3397 uint32 GLES2DecoderImpl::GetTextureUploadCount() {
3398 return texture_state_.texture_upload_count +
3399 async_pixel_transfer_manager_->GetTextureUploadCount();
3402 base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
3403 return texture_state_.total_texture_upload_time +
3404 async_pixel_transfer_manager_->GetTotalTextureUploadTime();
3407 base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3408 return total_processing_commands_time_;
3411 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time) {
3412 total_processing_commands_time_ += time;
3415 void GLES2DecoderImpl::Destroy(bool have_context) {
3419 DCHECK(!have_context || context_->IsCurrent(NULL));
3421 // Unbind everything.
3422 state_.vertex_attrib_manager = NULL;
3423 state_.default_vertex_attrib_manager = NULL;
3424 state_.texture_units.clear();
3425 state_.bound_array_buffer = NULL;
3426 state_.current_queries.clear();
3427 framebuffer_state_.bound_read_framebuffer = NULL;
3428 framebuffer_state_.bound_draw_framebuffer = NULL;
3429 state_.bound_renderbuffer = NULL;
3431 if (offscreen_saved_color_texture_info_.get()) {
3432 DCHECK(offscreen_target_color_texture_);
3433 DCHECK_EQ(offscreen_saved_color_texture_info_->service_id(),
3434 offscreen_saved_color_texture_->id());
3435 offscreen_saved_color_texture_->Invalidate();
3436 offscreen_saved_color_texture_info_ = NULL;
3439 if (copy_texture_CHROMIUM_.get()) {
3440 copy_texture_CHROMIUM_->Destroy();
3441 copy_texture_CHROMIUM_.reset();
3444 if (state_.current_program.get()) {
3445 program_manager()->UnuseProgram(shader_manager(),
3446 state_.current_program.get());
3449 if (attrib_0_buffer_id_) {
3450 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
3452 if (fixed_attrib_buffer_id_) {
3453 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
3456 if (validation_texture_) {
3457 glDeleteTextures(1, &validation_texture_);
3458 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_);
3459 glDeleteFramebuffersEXT(1, &validation_fbo_);
3462 if (offscreen_target_frame_buffer_.get())
3463 offscreen_target_frame_buffer_->Destroy();
3464 if (offscreen_target_color_texture_.get())
3465 offscreen_target_color_texture_->Destroy();
3466 if (offscreen_target_color_render_buffer_.get())
3467 offscreen_target_color_render_buffer_->Destroy();
3468 if (offscreen_target_depth_render_buffer_.get())
3469 offscreen_target_depth_render_buffer_->Destroy();
3470 if (offscreen_target_stencil_render_buffer_.get())
3471 offscreen_target_stencil_render_buffer_->Destroy();
3472 if (offscreen_saved_frame_buffer_.get())
3473 offscreen_saved_frame_buffer_->Destroy();
3474 if (offscreen_saved_color_texture_.get())
3475 offscreen_saved_color_texture_->Destroy();
3476 if (offscreen_resolved_frame_buffer_.get())
3477 offscreen_resolved_frame_buffer_->Destroy();
3478 if (offscreen_resolved_color_texture_.get())
3479 offscreen_resolved_color_texture_->Destroy();
3481 if (offscreen_target_frame_buffer_.get())
3482 offscreen_target_frame_buffer_->Invalidate();
3483 if (offscreen_target_color_texture_.get())
3484 offscreen_target_color_texture_->Invalidate();
3485 if (offscreen_target_color_render_buffer_.get())
3486 offscreen_target_color_render_buffer_->Invalidate();
3487 if (offscreen_target_depth_render_buffer_.get())
3488 offscreen_target_depth_render_buffer_->Invalidate();
3489 if (offscreen_target_stencil_render_buffer_.get())
3490 offscreen_target_stencil_render_buffer_->Invalidate();
3491 if (offscreen_saved_frame_buffer_.get())
3492 offscreen_saved_frame_buffer_->Invalidate();
3493 if (offscreen_saved_color_texture_.get())
3494 offscreen_saved_color_texture_->Invalidate();
3495 if (offscreen_resolved_frame_buffer_.get())
3496 offscreen_resolved_frame_buffer_->Invalidate();
3497 if (offscreen_resolved_color_texture_.get())
3498 offscreen_resolved_color_texture_->Invalidate();
3501 // Current program must be cleared after calling ProgramManager::UnuseProgram.
3502 // Otherwise, we can leak objects. http://crbug.com/258772.
3503 // state_.current_program must be reset before group_ is reset because
3504 // the later deletes the ProgramManager object that referred by
3505 // state_.current_program object.
3506 state_.current_program = NULL;
3508 copy_texture_CHROMIUM_.reset();
3510 if (query_manager_.get()) {
3511 query_manager_->Destroy(have_context);
3512 query_manager_.reset();
3515 if (vertex_array_manager_ .get()) {
3516 vertex_array_manager_->Destroy(have_context);
3517 vertex_array_manager_.reset();
3520 if (image_manager_.get()) {
3521 image_manager_->Destroy(have_context);
3522 image_manager_.reset();
3525 offscreen_target_frame_buffer_.reset();
3526 offscreen_target_color_texture_.reset();
3527 offscreen_target_color_render_buffer_.reset();
3528 offscreen_target_depth_render_buffer_.reset();
3529 offscreen_target_stencil_render_buffer_.reset();
3530 offscreen_saved_frame_buffer_.reset();
3531 offscreen_saved_color_texture_.reset();
3532 offscreen_resolved_frame_buffer_.reset();
3533 offscreen_resolved_color_texture_.reset();
3535 // Need to release these before releasing |group_| which may own the
3536 // ShaderTranslatorCache.
3537 fragment_translator_ = NULL;
3538 vertex_translator_ = NULL;
3540 // Should destroy the transfer manager before the texture manager held
3541 // by the context group.
3542 async_pixel_transfer_manager_.reset();
3545 framebuffer_manager()->RemoveObserver(this);
3546 group_->Destroy(this, have_context);
3550 if (context_.get()) {
3551 context_->ReleaseCurrent(NULL);
3555 #if defined(OS_MACOSX)
3556 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
3557 it != texture_to_io_surface_map_.end(); ++it) {
3558 CFRelease(it->second);
3560 texture_to_io_surface_map_.clear();
3564 void GLES2DecoderImpl::SetSurface(
3565 const scoped_refptr<gfx::GLSurface>& surface) {
3566 DCHECK(context_->IsCurrent(NULL));
3567 DCHECK(surface_.get());
3569 RestoreCurrentFramebufferBindings();
3572 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
3573 if (!offscreen_saved_color_texture_.get()) {
3574 LOG(ERROR) << "Called ProduceFrontBuffer on a non-offscreen context";
3577 if (!offscreen_saved_color_texture_info_.get()) {
3578 GLuint service_id = offscreen_saved_color_texture_->id();
3579 offscreen_saved_color_texture_info_ = TextureRef::Create(
3580 texture_manager(), 0, service_id);
3581 texture_manager()->SetTarget(offscreen_saved_color_texture_info_.get(),
3583 UpdateParentTextureInfo();
3585 mailbox_manager()->ProduceTexture(
3586 GL_TEXTURE_2D, mailbox, offscreen_saved_color_texture_info_->texture());
3589 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
3590 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3591 if (!is_offscreen) {
3592 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3593 << " with an onscreen framebuffer.";
3597 if (offscreen_size_ == size)
3600 offscreen_size_ = size;
3601 int w = offscreen_size_.width();
3602 int h = offscreen_size_.height();
3603 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
3604 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3605 << "to allocate storage due to excessive dimensions.";
3609 // Reallocate the offscreen target buffers.
3610 DCHECK(offscreen_target_color_format_);
3611 if (IsOffscreenBufferMultisampled()) {
3612 if (!offscreen_target_color_render_buffer_->AllocateStorage(
3613 feature_info_.get(),
3615 offscreen_target_color_format_,
3616 offscreen_target_samples_)) {
3617 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3618 << "to allocate storage for offscreen target color buffer.";
3622 if (!offscreen_target_color_texture_->AllocateStorage(
3623 offscreen_size_, offscreen_target_color_format_, false)) {
3624 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3625 << "to allocate storage for offscreen target color texture.";
3629 if (offscreen_target_depth_format_ &&
3630 !offscreen_target_depth_render_buffer_->AllocateStorage(
3631 feature_info_.get(),
3633 offscreen_target_depth_format_,
3634 offscreen_target_samples_)) {
3635 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3636 << "to allocate storage for offscreen target depth buffer.";
3639 if (offscreen_target_stencil_format_ &&
3640 !offscreen_target_stencil_render_buffer_->AllocateStorage(
3641 feature_info_.get(),
3643 offscreen_target_stencil_format_,
3644 offscreen_target_samples_)) {
3645 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3646 << "to allocate storage for offscreen target stencil buffer.";
3650 // Attach the offscreen target buffers to the target frame buffer.
3651 if (IsOffscreenBufferMultisampled()) {
3652 offscreen_target_frame_buffer_->AttachRenderBuffer(
3653 GL_COLOR_ATTACHMENT0,
3654 offscreen_target_color_render_buffer_.get());
3656 offscreen_target_frame_buffer_->AttachRenderTexture(
3657 offscreen_target_color_texture_.get());
3659 if (offscreen_target_depth_format_) {
3660 offscreen_target_frame_buffer_->AttachRenderBuffer(
3661 GL_DEPTH_ATTACHMENT,
3662 offscreen_target_depth_render_buffer_.get());
3664 const bool packed_depth_stencil =
3665 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3666 if (packed_depth_stencil) {
3667 offscreen_target_frame_buffer_->AttachRenderBuffer(
3668 GL_STENCIL_ATTACHMENT,
3669 offscreen_target_depth_render_buffer_.get());
3670 } else if (offscreen_target_stencil_format_) {
3671 offscreen_target_frame_buffer_->AttachRenderBuffer(
3672 GL_STENCIL_ATTACHMENT,
3673 offscreen_target_stencil_render_buffer_.get());
3676 if (offscreen_target_frame_buffer_->CheckStatus() !=
3677 GL_FRAMEBUFFER_COMPLETE) {
3678 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3679 << "because offscreen FBO was incomplete.";
3683 // Clear the target frame buffer.
3685 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
3686 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3687 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
3688 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3690 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
3691 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
3693 state_.SetDeviceDepthMask(GL_TRUE);
3694 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
3695 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3696 RestoreClearState();
3699 // Destroy the offscreen resolved framebuffers.
3700 if (offscreen_resolved_frame_buffer_.get())
3701 offscreen_resolved_frame_buffer_->Destroy();
3702 if (offscreen_resolved_color_texture_.get())
3703 offscreen_resolved_color_texture_->Destroy();
3704 offscreen_resolved_color_texture_.reset();
3705 offscreen_resolved_frame_buffer_.reset();
3710 error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(uint32 immediate_data_size,
3711 const void* cmd_data) {
3712 const gles2::cmds::ResizeCHROMIUM& c =
3713 *static_cast<const gles2::cmds::ResizeCHROMIUM*>(cmd_data);
3714 if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws())
3715 return error::kDeferCommandUntilLater;
3717 GLuint width = static_cast<GLuint>(c.width);
3718 GLuint height = static_cast<GLuint>(c.height);
3719 GLfloat scale_factor = c.scale_factor;
3720 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
3722 width = std::max(1U, width);
3723 height = std::max(1U, height);
3725 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3726 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
3727 // Make sure that we are done drawing to the back buffer before resizing.
3730 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3732 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
3733 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
3734 << "ResizeOffscreenFrameBuffer failed.";
3735 return error::kLostContext;
3739 if (!resize_callback_.is_null()) {
3740 resize_callback_.Run(gfx::Size(width, height), scale_factor);
3741 DCHECK(context_->IsCurrent(surface_.get()));
3742 if (!context_->IsCurrent(surface_.get())) {
3743 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
3744 << "current after resize callback.";
3745 return error::kLostContext;
3749 return error::kNoError;
3752 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
3753 if (command_id > kStartPoint && command_id < kNumCommands) {
3754 return gles2::GetCommandName(static_cast<CommandId>(command_id));
3756 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
3759 // Decode a command, and call the corresponding GL functions.
3760 // NOTE: DoCommand() is slower than calling DoCommands() on larger batches
3761 // of commands at once, and is now only used for tests that need to track
3762 // individual commands.
3763 error::Error GLES2DecoderImpl::DoCommand(unsigned int command,
3764 unsigned int arg_count,
3765 const void* cmd_data) {
3766 return DoCommands(1, cmd_data, arg_count + 1, 0);
3769 // Decode multiple commands, and call the corresponding GL functions.
3770 // NOTE: 'buffer' is a pointer to the command buffer. As such, it could be
3771 // changed by a (malicious) client at any time, so if validation has to happen,
3772 // it should operate on a copy of them.
3773 // NOTE: This is duplicating code from AsyncAPIInterface::DoCommands() in the
3774 // interest of performance in this critical execution loop.
3775 template <bool DebugImpl>
3776 error::Error GLES2DecoderImpl::DoCommandsImpl(unsigned int num_commands,
3779 int* entries_processed) {
3780 commands_to_process_ = num_commands;
3781 error::Error result = error::kNoError;
3782 const CommandBufferEntry* cmd_data =
3783 static_cast<const CommandBufferEntry*>(buffer);
3784 int process_pos = 0;
3785 unsigned int command = 0;
3787 while (process_pos < num_entries && result == error::kNoError &&
3788 commands_to_process_--) {
3789 const unsigned int size = cmd_data->value_header.size;
3790 command = cmd_data->value_header.command;
3793 result = error::kInvalidSize;
3797 if (static_cast<int>(size) + process_pos > num_entries) {
3798 result = error::kOutOfBounds;
3803 TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
3804 GetCommandName(command));
3806 if (log_commands()) {
3807 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]"
3808 << "cmd: " << GetCommandName(command);
3812 const unsigned int arg_count = size - 1;
3813 unsigned int command_index = command - kStartPoint - 1;
3814 if (command_index < arraysize(command_info)) {
3815 const CommandInfo& info = command_info[command_index];
3816 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
3817 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
3818 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
3819 bool doing_gpu_trace = false;
3820 if (DebugImpl && gpu_trace_commands_) {
3821 if (CMD_FLAG_GET_TRACE_LEVEL(info.cmd_flags) <= gpu_trace_level_) {
3822 doing_gpu_trace = true;
3823 gpu_tracer_->Begin(GetCommandName(command), kTraceDecoder);
3827 uint32 immediate_data_size = (arg_count - info_arg_count) *
3828 sizeof(CommandBufferEntry); // NOLINT
3830 result = (this->*info.cmd_handler)(immediate_data_size, cmd_data);
3832 if (DebugImpl && doing_gpu_trace)
3833 gpu_tracer_->End(kTraceDecoder);
3835 if (DebugImpl && debug()) {
3837 while ((error = glGetError()) != GL_NO_ERROR) {
3838 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
3839 << "GL ERROR: " << GLES2Util::GetStringEnum(error)
3840 << " : " << GetCommandName(command);
3841 LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
3845 result = error::kInvalidArguments;
3848 result = DoCommonCommand(command, arg_count, cmd_data);
3852 TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
3853 GetCommandName(command));
3856 if (result == error::kNoError &&
3857 current_decoder_error_ != error::kNoError) {
3858 result = current_decoder_error_;
3859 current_decoder_error_ = error::kNoError;
3862 if (result != error::kDeferCommandUntilLater) {
3863 process_pos += size;
3868 if (entries_processed)
3869 *entries_processed = process_pos;
3871 if (error::IsError(result)) {
3872 LOG(ERROR) << "Error: " << result << " for Command "
3873 << GetCommandName(command);
3879 error::Error GLES2DecoderImpl::DoCommands(unsigned int num_commands,
3882 int* entries_processed) {
3883 if (gpu_debug_commands_) {
3884 return DoCommandsImpl<true>(
3885 num_commands, buffer, num_entries, entries_processed);
3887 return DoCommandsImpl<false>(
3888 num_commands, buffer, num_entries, entries_processed);
3892 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id) {
3893 buffer_manager()->RemoveBuffer(client_id);
3896 bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
3897 if (GetProgram(client_id)) {
3900 GLuint service_id = glCreateProgram();
3901 if (service_id != 0) {
3902 CreateProgram(client_id, service_id);
3907 bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
3908 if (GetShader(client_id)) {
3911 GLuint service_id = glCreateShader(type);
3912 if (service_id != 0) {
3913 CreateShader(client_id, service_id, type);
3918 void GLES2DecoderImpl::DoFinish() {
3920 ProcessPendingReadPixels();
3921 ProcessPendingQueries();
3924 void GLES2DecoderImpl::DoFlush() {
3926 ProcessPendingQueries();
3929 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
3930 GLuint texture_index = texture_unit - GL_TEXTURE0;
3931 if (texture_index >= state_.texture_units.size()) {
3932 LOCAL_SET_GL_ERROR_INVALID_ENUM(
3933 "glActiveTexture", texture_unit, "texture_unit");
3936 state_.active_texture_unit = texture_index;
3937 glActiveTexture(texture_unit);
3940 void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
3941 Buffer* buffer = NULL;
3942 GLuint service_id = 0;
3943 if (client_id != 0) {
3944 buffer = GetBuffer(client_id);
3946 if (!group_->bind_generates_resource()) {
3947 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
3949 "id not generated by glGenBuffers");
3953 // It's a new id so make a buffer buffer for it.
3954 glGenBuffersARB(1, &service_id);
3955 CreateBuffer(client_id, service_id);
3956 buffer = GetBuffer(client_id);
3957 IdAllocatorInterface* id_allocator =
3958 group_->GetIdAllocator(id_namespaces::kBuffers);
3959 id_allocator->MarkAsUsed(client_id);
3962 LogClientServiceForInfo(buffer, client_id, "glBindBuffer");
3964 if (!buffer_manager()->SetTarget(buffer, target)) {
3966 GL_INVALID_OPERATION,
3967 "glBindBuffer", "buffer bound to more than 1 target");
3970 service_id = buffer->service_id();
3973 case GL_ARRAY_BUFFER:
3974 state_.bound_array_buffer = buffer;
3976 case GL_ELEMENT_ARRAY_BUFFER:
3977 state_.vertex_attrib_manager->SetElementArrayBuffer(buffer);
3980 NOTREACHED(); // Validation should prevent us getting here.
3983 glBindBuffer(target, service_id);
3986 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
3987 bool all_draw_buffers) {
3988 Framebuffer* framebuffer =
3989 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3990 if (!all_draw_buffers || !framebuffer) {
3991 return (GLES2Util::GetChannelsForFormat(
3992 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
3994 return framebuffer->HasAlphaMRT();
3997 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
3998 Framebuffer* framebuffer =
3999 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4001 return framebuffer->HasDepthAttachment();
4003 if (offscreen_target_frame_buffer_.get()) {
4004 return offscreen_target_depth_format_ != 0;
4006 return back_buffer_has_depth_;
4009 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
4010 Framebuffer* framebuffer =
4011 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4013 return framebuffer->HasStencilAttachment();
4015 if (offscreen_target_frame_buffer_.get()) {
4016 return offscreen_target_stencil_format_ != 0 ||
4017 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
4019 return back_buffer_has_stencil_;
4022 void GLES2DecoderImpl::ApplyDirtyState() {
4023 if (framebuffer_state_.clear_state_dirty) {
4024 bool have_alpha = BoundFramebufferHasColorAttachmentWithAlpha(true);
4025 state_.SetDeviceColorMask(state_.color_mask_red,
4026 state_.color_mask_green,
4027 state_.color_mask_blue,
4028 state_.color_mask_alpha && have_alpha);
4030 bool have_depth = BoundFramebufferHasDepthAttachment();
4031 state_.SetDeviceDepthMask(state_.depth_mask && have_depth);
4033 bool have_stencil = BoundFramebufferHasStencilAttachment();
4034 state_.SetDeviceStencilMaskSeparate(
4035 GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
4036 state_.SetDeviceStencilMaskSeparate(
4037 GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
4039 state_.SetDeviceCapabilityState(
4040 GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
4041 state_.SetDeviceCapabilityState(
4042 GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
4043 framebuffer_state_.clear_state_dirty = false;
4047 GLuint GLES2DecoderImpl::GetBackbufferServiceId() const {
4048 return (offscreen_target_frame_buffer_.get())
4049 ? offscreen_target_frame_buffer_->id()
4050 : (surface_.get() ? surface_->GetBackingFrameBufferObject() : 0);
4053 void GLES2DecoderImpl::RestoreState(const ContextState* prev_state) {
4054 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
4055 "context", logger_.GetLogPrefix());
4056 // Restore the Framebuffer first because of bugs in Intel drivers.
4057 // Intel drivers incorrectly clip the viewport settings to
4058 // the size of the current framebuffer object.
4059 RestoreFramebufferBindings();
4060 state_.RestoreState(prev_state);
4063 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
4065 framebuffer_state_.bound_draw_framebuffer.get()
4066 ? framebuffer_state_.bound_draw_framebuffer->service_id()
4067 : GetBackbufferServiceId();
4068 if (!features().chromium_framebuffer_multisample) {
4069 glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
4071 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, service_id);
4072 service_id = framebuffer_state_.bound_read_framebuffer.get()
4073 ? framebuffer_state_.bound_read_framebuffer->service_id()
4074 : GetBackbufferServiceId();
4075 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, service_id);
4080 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
4081 state_.RestoreRenderbufferBindings();
4084 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
4085 Texture* texture = texture_manager()->GetTextureForServiceId(service_id);
4087 GLenum target = texture->target();
4088 glBindTexture(target, service_id);
4090 target, GL_TEXTURE_WRAP_S, texture->wrap_s());
4092 target, GL_TEXTURE_WRAP_T, texture->wrap_t());
4094 target, GL_TEXTURE_MIN_FILTER, texture->min_filter());
4096 target, GL_TEXTURE_MAG_FILTER, texture->mag_filter());
4097 RestoreTextureUnitBindings(state_.active_texture_unit);
4101 void GLES2DecoderImpl::ClearAllAttributes() const {
4102 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
4104 if (feature_info_->feature_flags().native_vertex_array_object)
4105 glBindVertexArrayOES(0);
4107 for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i) {
4108 if (i != 0) // Never disable attribute 0
4109 glDisableVertexAttribArray(i);
4110 if(features().angle_instanced_arrays)
4111 glVertexAttribDivisorANGLE(i, 0);
4115 void GLES2DecoderImpl::RestoreAllAttributes() const {
4116 state_.RestoreVertexAttribs();
4119 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore) {
4120 state_.SetIgnoreCachedStateForTest(ignore);
4123 void GLES2DecoderImpl::OnFboChanged() const {
4124 if (workarounds().restore_scissor_on_fbo_change)
4125 state_.fbo_binding_for_scissor_workaround_dirty_ = true;
4128 // Called after the FBO is checked for completeness.
4129 void GLES2DecoderImpl::OnUseFramebuffer() const {
4130 if (state_.fbo_binding_for_scissor_workaround_dirty_) {
4131 state_.fbo_binding_for_scissor_workaround_dirty_ = false;
4132 // The driver forgets the correct scissor when modifying the FBO binding.
4133 glScissor(state_.scissor_x,
4135 state_.scissor_width,
4136 state_.scissor_height);
4138 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
4139 // it's unclear how this bug works.
4144 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
4145 Framebuffer* framebuffer = NULL;
4146 GLuint service_id = 0;
4147 if (client_id != 0) {
4148 framebuffer = GetFramebuffer(client_id);
4150 if (!group_->bind_generates_resource()) {
4151 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4152 "glBindFramebuffer",
4153 "id not generated by glGenFramebuffers");
4157 // It's a new id so make a framebuffer framebuffer for it.
4158 glGenFramebuffersEXT(1, &service_id);
4159 CreateFramebuffer(client_id, service_id);
4160 framebuffer = GetFramebuffer(client_id);
4161 IdAllocatorInterface* id_allocator =
4162 group_->GetIdAllocator(id_namespaces::kFramebuffers);
4163 id_allocator->MarkAsUsed(client_id);
4165 service_id = framebuffer->service_id();
4167 framebuffer->MarkAsValid();
4169 LogClientServiceForInfo(framebuffer, client_id, "glBindFramebuffer");
4171 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
4172 framebuffer_state_.bound_draw_framebuffer = framebuffer;
4175 // vmiura: This looks like dup code
4176 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
4177 framebuffer_state_.bound_read_framebuffer = framebuffer;
4180 framebuffer_state_.clear_state_dirty = true;
4182 // If we are rendering to the backbuffer get the FBO id for any simulated
4184 if (framebuffer == NULL) {
4185 service_id = GetBackbufferServiceId();
4188 glBindFramebufferEXT(target, service_id);
4192 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
4193 Renderbuffer* renderbuffer = NULL;
4194 GLuint service_id = 0;
4195 if (client_id != 0) {
4196 renderbuffer = GetRenderbuffer(client_id);
4197 if (!renderbuffer) {
4198 if (!group_->bind_generates_resource()) {
4199 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4200 "glBindRenderbuffer",
4201 "id not generated by glGenRenderbuffers");
4205 // It's a new id so make a renderbuffer for it.
4206 glGenRenderbuffersEXT(1, &service_id);
4207 CreateRenderbuffer(client_id, service_id);
4208 renderbuffer = GetRenderbuffer(client_id);
4209 IdAllocatorInterface* id_allocator =
4210 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
4211 id_allocator->MarkAsUsed(client_id);
4213 service_id = renderbuffer->service_id();
4215 renderbuffer->MarkAsValid();
4217 LogClientServiceForInfo(renderbuffer, client_id, "glBindRenderbuffer");
4218 state_.bound_renderbuffer = renderbuffer;
4219 state_.bound_renderbuffer_valid = true;
4220 glBindRenderbufferEXT(GL_RENDERBUFFER, service_id);
4223 void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
4224 TextureRef* texture_ref = NULL;
4225 GLuint service_id = 0;
4226 if (client_id != 0) {
4227 texture_ref = GetTexture(client_id);
4229 if (!group_->bind_generates_resource()) {
4230 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4232 "id not generated by glGenTextures");
4236 // It's a new id so make a texture texture for it.
4237 glGenTextures(1, &service_id);
4238 DCHECK_NE(0u, service_id);
4239 CreateTexture(client_id, service_id);
4240 texture_ref = GetTexture(client_id);
4241 IdAllocatorInterface* id_allocator =
4242 group_->GetIdAllocator(id_namespaces::kTextures);
4243 id_allocator->MarkAsUsed(client_id);
4246 texture_ref = texture_manager()->GetDefaultTextureInfo(target);
4249 // Check the texture exists
4251 Texture* texture = texture_ref->texture();
4252 // Check that we are not trying to bind it to a different target.
4253 if (texture->target() != 0 && texture->target() != target) {
4254 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4256 "texture bound to more than 1 target.");
4259 LogClientServiceForInfo(texture, client_id, "glBindTexture");
4260 if (texture->target() == 0) {
4261 texture_manager()->SetTarget(texture_ref, target);
4263 glBindTexture(target, texture->service_id());
4265 glBindTexture(target, 0);
4268 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4269 unit.bind_target = target;
4272 unit.bound_texture_2d = texture_ref;
4274 case GL_TEXTURE_CUBE_MAP:
4275 unit.bound_texture_cube_map = texture_ref;
4277 case GL_TEXTURE_EXTERNAL_OES:
4278 unit.bound_texture_external_oes = texture_ref;
4280 case GL_TEXTURE_RECTANGLE_ARB:
4281 unit.bound_texture_rectangle_arb = texture_ref;
4284 NOTREACHED(); // Validation should prevent us getting here.
4289 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
4290 if (state_.vertex_attrib_manager->Enable(index, false)) {
4292 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
4293 glDisableVertexAttribArray(index);
4298 "glDisableVertexAttribArray", "index out of range");
4302 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target,
4303 GLsizei numAttachments,
4304 const GLenum* attachments) {
4305 Framebuffer* framebuffer =
4306 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4308 // Validates the attachments. If one of them fails
4309 // the whole command fails.
4310 for (GLsizei i = 0; i < numAttachments; ++i) {
4312 !validators_->attachment.IsValid(attachments[i])) ||
4314 !validators_->backbuffer_attachment.IsValid(attachments[i]))) {
4315 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4316 "glDiscardFramebufferEXT", attachments[i], "attachments");
4321 // Marks each one of them as not cleared
4322 for (GLsizei i = 0; i < numAttachments; ++i) {
4324 framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
4329 switch (attachments[i]) {
4331 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
4334 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
4335 case GL_STENCIL_EXT:
4336 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
4345 // If the default framebuffer is bound but we are still rendering to an
4346 // FBO, translate attachment names that refer to default framebuffer
4347 // channels to corresponding framebuffer attachments.
4348 scoped_ptr<GLenum[]> translated_attachments(new GLenum[numAttachments]);
4349 for (GLsizei i = 0; i < numAttachments; ++i) {
4350 GLenum attachment = attachments[i];
4351 if (!framebuffer && GetBackbufferServiceId()) {
4352 switch (attachment) {
4354 attachment = GL_COLOR_ATTACHMENT0;
4357 attachment = GL_DEPTH_ATTACHMENT;
4359 case GL_STENCIL_EXT:
4360 attachment = GL_STENCIL_ATTACHMENT;
4367 translated_attachments[i] = attachment;
4370 glDiscardFramebufferEXT(target, numAttachments, translated_attachments.get());
4373 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
4374 if (state_.vertex_attrib_manager->Enable(index, true)) {
4375 glEnableVertexAttribArray(index);
4378 GL_INVALID_VALUE, "glEnableVertexAttribArray", "index out of range");
4382 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
4383 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
4386 !texture_manager()->CanGenerateMipmaps(texture_ref)) {
4388 GL_INVALID_OPERATION, "glGenerateMipmap", "Can not generate mips");
4392 if (target == GL_TEXTURE_CUBE_MAP) {
4393 for (int i = 0; i < 6; ++i) {
4394 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
4395 if (!texture_manager()->ClearTextureLevel(this, texture_ref, face, 0)) {
4397 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4402 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 0)) {
4404 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4409 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4410 // Workaround for Mac driver bug. In the large scheme of things setting
4411 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4412 // hit so there's probably no need to make this conditional. The bug appears
4413 // to be that if the filtering mode is set to something that doesn't require
4414 // mipmaps for rendering, or is never set to something other than the default,
4415 // then glGenerateMipmap misbehaves.
4416 if (workarounds().set_texture_filter_before_generating_mipmap) {
4417 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4419 glGenerateMipmapEXT(target);
4420 if (workarounds().set_texture_filter_before_generating_mipmap) {
4421 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
4422 texture_ref->texture()->min_filter());
4424 GLenum error = LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4425 if (error == GL_NO_ERROR) {
4426 texture_manager()->MarkMipmapsGenerated(texture_ref);
4430 bool GLES2DecoderImpl::GetHelper(
4431 GLenum pname, GLint* params, GLsizei* num_written) {
4432 DCHECK(num_written);
4433 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
4435 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
4437 // Return the GL implementation's preferred format and (see below type)
4438 // if we have the GL extension that exposes this. This allows the GPU
4439 // client to use the implementation's preferred format for glReadPixels
4440 // for optimisation.
4442 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4443 // case when requested on integer/floating point buffers but which is
4444 // acceptable on GLES2 and with the GL_OES_read_format extension.
4446 // Therefore if an error occurs we swallow the error and use the
4447 // internal implementation.
4449 if (context_->HasExtension("GL_OES_read_format")) {
4450 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4452 glGetIntegerv(pname, params);
4453 if (glGetError() == GL_NO_ERROR)
4456 *params = GLES2Util::GetPreferredGLReadPixelsFormat(
4457 GetBoundReadFrameBufferInternalFormat());
4460 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
4463 if (context_->HasExtension("GL_OES_read_format")) {
4464 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4466 glGetIntegerv(pname, params);
4467 if (glGetError() == GL_NO_ERROR)
4470 *params = GLES2Util::GetPreferredGLReadPixelsType(
4471 GetBoundReadFrameBufferInternalFormat(),
4472 GetBoundReadFrameBufferTextureType());
4475 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
4478 *params = group_->max_fragment_uniform_vectors();
4481 case GL_MAX_VARYING_VECTORS:
4484 *params = group_->max_varying_vectors();
4487 case GL_MAX_VERTEX_UNIFORM_VECTORS:
4490 *params = group_->max_vertex_uniform_vectors();
4496 case GL_MAX_VIEWPORT_DIMS:
4497 if (offscreen_target_frame_buffer_.get()) {
4500 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4501 params[1] = renderbuffer_manager()->max_renderbuffer_size();
4506 case GL_MAX_SAMPLES:
4509 params[0] = renderbuffer_manager()->max_samples();
4512 case GL_MAX_RENDERBUFFER_SIZE:
4515 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4518 case GL_MAX_TEXTURE_SIZE:
4521 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
4524 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
4527 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
4530 case GL_MAX_COLOR_ATTACHMENTS_EXT:
4533 params[0] = group_->max_color_attachments();
4536 case GL_MAX_DRAW_BUFFERS_ARB:
4539 params[0] = group_->max_draw_buffers();
4546 glGetIntegerv(GL_ALPHA_BITS, &v);
4547 params[0] = BoundFramebufferHasColorAttachmentWithAlpha(false) ? v : 0;
4554 glGetIntegerv(GL_DEPTH_BITS, &v);
4555 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
4558 case GL_STENCIL_BITS:
4562 glGetIntegerv(GL_STENCIL_BITS, &v);
4563 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
4566 case GL_COMPRESSED_TEXTURE_FORMATS:
4567 *num_written = validators_->compressed_texture_format.GetValues().size();
4569 for (GLint ii = 0; ii < *num_written; ++ii) {
4570 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
4574 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
4577 *params = validators_->compressed_texture_format.GetValues().size();
4580 case GL_NUM_SHADER_BINARY_FORMATS:
4583 *params = validators_->shader_binary_format.GetValues().size();
4586 case GL_SHADER_BINARY_FORMATS:
4587 *num_written = validators_->shader_binary_format.GetValues().size();
4589 for (GLint ii = 0; ii < *num_written; ++ii) {
4590 params[ii] = validators_->shader_binary_format.GetValues()[ii];
4594 case GL_SHADER_COMPILER:
4600 case GL_ARRAY_BUFFER_BINDING:
4603 if (state_.bound_array_buffer.get()) {
4604 GLuint client_id = 0;
4605 buffer_manager()->GetClientId(state_.bound_array_buffer->service_id(),
4607 *params = client_id;
4613 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
4616 if (state_.vertex_attrib_manager->element_array_buffer()) {
4617 GLuint client_id = 0;
4618 buffer_manager()->GetClientId(
4619 state_.vertex_attrib_manager->element_array_buffer()->
4620 service_id(), &client_id);
4621 *params = client_id;
4627 case GL_FRAMEBUFFER_BINDING:
4628 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
4631 Framebuffer* framebuffer =
4632 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4634 GLuint client_id = 0;
4635 framebuffer_manager()->GetClientId(
4636 framebuffer->service_id(), &client_id);
4637 *params = client_id;
4643 case GL_READ_FRAMEBUFFER_BINDING_EXT:
4646 Framebuffer* framebuffer =
4647 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
4649 GLuint client_id = 0;
4650 framebuffer_manager()->GetClientId(
4651 framebuffer->service_id(), &client_id);
4652 *params = client_id;
4658 case GL_RENDERBUFFER_BINDING:
4661 Renderbuffer* renderbuffer =
4662 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4664 *params = renderbuffer->client_id();
4670 case GL_CURRENT_PROGRAM:
4673 if (state_.current_program.get()) {
4674 GLuint client_id = 0;
4675 program_manager()->GetClientId(
4676 state_.current_program->service_id(), &client_id);
4677 *params = client_id;
4683 case GL_VERTEX_ARRAY_BINDING_OES:
4686 if (state_.vertex_attrib_manager.get() !=
4687 state_.default_vertex_attrib_manager.get()) {
4688 GLuint client_id = 0;
4689 vertex_array_manager_->GetClientId(
4690 state_.vertex_attrib_manager->service_id(), &client_id);
4691 *params = client_id;
4697 case GL_TEXTURE_BINDING_2D:
4700 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4701 if (unit.bound_texture_2d.get()) {
4702 *params = unit.bound_texture_2d->client_id();
4708 case GL_TEXTURE_BINDING_CUBE_MAP:
4711 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4712 if (unit.bound_texture_cube_map.get()) {
4713 *params = unit.bound_texture_cube_map->client_id();
4719 case GL_TEXTURE_BINDING_EXTERNAL_OES:
4722 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4723 if (unit.bound_texture_external_oes.get()) {
4724 *params = unit.bound_texture_external_oes->client_id();
4730 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
4733 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4734 if (unit.bound_texture_rectangle_arb.get()) {
4735 *params = unit.bound_texture_rectangle_arb->client_id();
4741 case GL_UNPACK_FLIP_Y_CHROMIUM:
4744 params[0] = unpack_flip_y_;
4747 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
4750 params[0] = unpack_premultiply_alpha_;
4753 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
4756 params[0] = unpack_unpremultiply_alpha_;
4759 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
4762 params[0] = group_->bind_generates_resource() ? 1 : 0;
4766 if (pname >= GL_DRAW_BUFFER0_ARB &&
4767 pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
4770 Framebuffer* framebuffer =
4771 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4773 params[0] = framebuffer->GetDrawBuffer(pname);
4774 } else { // backbuffer
4775 if (pname == GL_DRAW_BUFFER0_ARB)
4776 params[0] = group_->draw_buffer();
4778 params[0] = GL_NONE;
4783 *num_written = util_.GLGetNumValuesReturned(pname);
4788 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
4789 GLenum pname, GLsizei* num_values) {
4790 if (state_.GetStateAsGLint(pname, NULL, num_values)) {
4793 return GetHelper(pname, NULL, num_values);
4796 GLenum GLES2DecoderImpl::AdjustGetPname(GLenum pname) {
4797 if (GL_MAX_SAMPLES == pname &&
4798 features().use_img_for_multisampled_render_to_texture) {
4799 return GL_MAX_SAMPLES_IMG;
4804 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
4806 GLsizei num_written = 0;
4807 if (GetNumValuesReturnedForGLGet(pname, &num_written)) {
4808 scoped_ptr<GLint[]> values(new GLint[num_written]);
4809 if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) {
4810 GetHelper(pname, values.get(), &num_written);
4812 for (GLsizei ii = 0; ii < num_written; ++ii) {
4813 params[ii] = static_cast<GLboolean>(values[ii]);
4816 pname = AdjustGetPname(pname);
4817 glGetBooleanv(pname, params);
4821 void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
4823 GLsizei num_written = 0;
4824 if (!state_.GetStateAsGLfloat(pname, params, &num_written)) {
4825 if (GetHelper(pname, NULL, &num_written)) {
4826 scoped_ptr<GLint[]> values(new GLint[num_written]);
4827 GetHelper(pname, values.get(), &num_written);
4828 for (GLsizei ii = 0; ii < num_written; ++ii) {
4829 params[ii] = static_cast<GLfloat>(values[ii]);
4832 pname = AdjustGetPname(pname);
4833 glGetFloatv(pname, params);
4838 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
4840 GLsizei num_written;
4841 if (!state_.GetStateAsGLint(pname, params, &num_written) &&
4842 !GetHelper(pname, params, &num_written)) {
4843 pname = AdjustGetPname(pname);
4844 glGetIntegerv(pname, params);
4848 void GLES2DecoderImpl::DoGetProgramiv(
4849 GLuint program_id, GLenum pname, GLint* params) {
4850 Program* program = GetProgramInfoNotShader(program_id, "glGetProgramiv");
4854 program->GetProgramiv(pname, params);
4857 void GLES2DecoderImpl::DoGetBufferParameteriv(
4858 GLenum target, GLenum pname, GLint* params) {
4859 // Just delegate it. Some validation is actually done before this.
4860 buffer_manager()->ValidateAndDoGetBufferParameteriv(
4861 &state_, target, pname, params);
4864 void GLES2DecoderImpl::DoBindAttribLocation(
4865 GLuint program_id, GLuint index, const char* name) {
4866 if (!StringIsValidForGLES(name)) {
4868 GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
4871 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
4873 GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
4876 if (index >= group_->max_vertex_attribs()) {
4878 GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
4881 Program* program = GetProgramInfoNotShader(
4882 program_id, "glBindAttribLocation");
4886 program->SetAttribLocationBinding(name, static_cast<GLint>(index));
4887 glBindAttribLocation(program->service_id(), index, name);
4890 error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
4891 uint32 immediate_data_size,
4892 const void* cmd_data) {
4893 const gles2::cmds::BindAttribLocationBucket& c =
4894 *static_cast<const gles2::cmds::BindAttribLocationBucket*>(cmd_data);
4895 GLuint program = static_cast<GLuint>(c.program);
4896 GLuint index = static_cast<GLuint>(c.index);
4897 Bucket* bucket = GetBucket(c.name_bucket_id);
4898 if (!bucket || bucket->size() == 0) {
4899 return error::kInvalidArguments;
4901 std::string name_str;
4902 if (!bucket->GetAsString(&name_str)) {
4903 return error::kInvalidArguments;
4905 DoBindAttribLocation(program, index, name_str.c_str());
4906 return error::kNoError;
4909 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
4910 GLuint program_id, GLint location, const char* name) {
4911 if (!StringIsValidForGLES(name)) {
4914 "glBindUniformLocationCHROMIUM", "Invalid character");
4917 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
4919 GL_INVALID_OPERATION,
4920 "glBindUniformLocationCHROMIUM", "reserved prefix");
4923 if (location < 0 || static_cast<uint32>(location) >=
4924 (group_->max_fragment_uniform_vectors() +
4925 group_->max_vertex_uniform_vectors()) * 4) {
4928 "glBindUniformLocationCHROMIUM", "location out of range");
4931 Program* program = GetProgramInfoNotShader(
4932 program_id, "glBindUniformLocationCHROMIUM");
4936 if (!program->SetUniformLocationBinding(name, location)) {
4939 "glBindUniformLocationCHROMIUM", "location out of range");
4943 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
4944 uint32 immediate_data_size,
4945 const void* cmd_data) {
4946 const gles2::cmds::BindUniformLocationCHROMIUMBucket& c =
4947 *static_cast<const gles2::cmds::BindUniformLocationCHROMIUMBucket*>(
4949 GLuint program = static_cast<GLuint>(c.program);
4950 GLint location = static_cast<GLint>(c.location);
4951 Bucket* bucket = GetBucket(c.name_bucket_id);
4952 if (!bucket || bucket->size() == 0) {
4953 return error::kInvalidArguments;
4955 std::string name_str;
4956 if (!bucket->GetAsString(&name_str)) {
4957 return error::kInvalidArguments;
4959 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4960 return error::kNoError;
4963 error::Error GLES2DecoderImpl::HandleDeleteShader(uint32 immediate_data_size,
4964 const void* cmd_data) {
4965 const gles2::cmds::DeleteShader& c =
4966 *static_cast<const gles2::cmds::DeleteShader*>(cmd_data);
4967 GLuint client_id = c.shader;
4969 Shader* shader = GetShader(client_id);
4971 if (!shader->IsDeleted()) {
4972 glDeleteShader(shader->service_id());
4973 shader_manager()->MarkAsDeleted(shader);
4976 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
4979 return error::kNoError;
4982 error::Error GLES2DecoderImpl::HandleDeleteProgram(uint32 immediate_data_size,
4983 const void* cmd_data) {
4984 const gles2::cmds::DeleteProgram& c =
4985 *static_cast<const gles2::cmds::DeleteProgram*>(cmd_data);
4986 GLuint client_id = c.program;
4988 Program* program = GetProgram(client_id);
4990 if (!program->IsDeleted()) {
4991 program_manager()->MarkAsDeleted(shader_manager(), program);
4995 GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
4998 return error::kNoError;
5001 void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
5002 GLuint namespace_id, GLsizei n, const GLuint* ids) {
5003 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
5004 for (GLsizei ii = 0; ii < n; ++ii) {
5005 id_allocator->FreeID(ids[ii]);
5009 error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
5010 uint32 immediate_data_size,
5011 const void* cmd_data) {
5012 const gles2::cmds::DeleteSharedIdsCHROMIUM& c =
5013 *static_cast<const gles2::cmds::DeleteSharedIdsCHROMIUM*>(cmd_data);
5014 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
5015 GLsizei n = static_cast<GLsizei>(c.n);
5017 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
5018 return error::kOutOfBounds;
5020 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
5021 c.ids_shm_id, c.ids_shm_offset, data_size);
5023 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM", "n < 0");
5024 return error::kNoError;
5027 return error::kOutOfBounds;
5029 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
5030 return error::kNoError;
5033 void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
5034 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
5035 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
5036 if (id_offset == 0) {
5037 for (GLsizei ii = 0; ii < n; ++ii) {
5038 ids[ii] = id_allocator->AllocateID();
5041 for (GLsizei ii = 0; ii < n; ++ii) {
5042 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
5043 id_offset = ids[ii] + 1;
5048 error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
5049 uint32 immediate_data_size,
5050 const void* cmd_data) {
5051 const gles2::cmds::GenSharedIdsCHROMIUM& c =
5052 *static_cast<const gles2::cmds::GenSharedIdsCHROMIUM*>(cmd_data);
5053 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
5054 GLuint id_offset = static_cast<GLuint>(c.id_offset);
5055 GLsizei n = static_cast<GLsizei>(c.n);
5057 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
5058 return error::kOutOfBounds;
5060 GLuint* ids = GetSharedMemoryAs<GLuint*>(
5061 c.ids_shm_id, c.ids_shm_offset, data_size);
5063 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM", "n < 0");
5064 return error::kNoError;
5067 return error::kOutOfBounds;
5069 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
5070 return error::kNoError;
5073 void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
5074 GLuint namespace_id, GLsizei n, const GLuint* ids) {
5075 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
5076 for (GLsizei ii = 0; ii < n; ++ii) {
5077 if (!id_allocator->MarkAsUsed(ids[ii])) {
5078 for (GLsizei jj = 0; jj < ii; ++jj) {
5079 id_allocator->FreeID(ids[jj]);
5082 GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM",
5083 "attempt to register id that already exists");
5089 error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
5090 uint32 immediate_data_size,
5091 const void* cmd_data) {
5092 const gles2::cmds::RegisterSharedIdsCHROMIUM& c =
5093 *static_cast<const gles2::cmds::RegisterSharedIdsCHROMIUM*>(cmd_data);
5094 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
5095 GLsizei n = static_cast<GLsizei>(c.n);
5097 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
5098 return error::kOutOfBounds;
5100 GLuint* ids = GetSharedMemoryAs<GLuint*>(
5101 c.ids_shm_id, c.ids_shm_offset, data_size);
5103 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM", "n < 0");
5104 return error::kNoError;
5107 return error::kOutOfBounds;
5109 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
5110 return error::kNoError;
5113 error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
5114 DCHECK(!ShouldDeferDraws());
5115 if (CheckBoundFramebuffersValid("glClear")) {
5119 return error::kNoError;
5122 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
5123 GLenum target, GLenum attachment, GLenum renderbuffertarget,
5124 GLuint client_renderbuffer_id) {
5125 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5128 GL_INVALID_OPERATION,
5129 "glFramebufferRenderbuffer", "no framebuffer bound");
5132 GLuint service_id = 0;
5133 Renderbuffer* renderbuffer = NULL;
5134 if (client_renderbuffer_id) {
5135 renderbuffer = GetRenderbuffer(client_renderbuffer_id);
5136 if (!renderbuffer) {
5138 GL_INVALID_OPERATION,
5139 "glFramebufferRenderbuffer", "unknown renderbuffer");
5142 service_id = renderbuffer->service_id();
5144 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
5145 glFramebufferRenderbufferEXT(
5146 target, attachment, renderbuffertarget, service_id);
5147 GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
5148 if (error == GL_NO_ERROR) {
5149 framebuffer->AttachRenderbuffer(attachment, renderbuffer);
5151 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5152 framebuffer_state_.clear_state_dirty = true;
5157 void GLES2DecoderImpl::DoDisable(GLenum cap) {
5158 if (SetCapabilityState(cap, false)) {
5163 void GLES2DecoderImpl::DoEnable(GLenum cap) {
5164 if (SetCapabilityState(cap, true)) {
5169 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear, GLclampf zfar) {
5170 state_.z_near = std::min(1.0f, std::max(0.0f, znear));
5171 state_.z_far = std::min(1.0f, std::max(0.0f, zfar));
5172 glDepthRange(znear, zfar);
5175 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value, GLboolean invert) {
5176 state_.sample_coverage_value = std::min(1.0f, std::max(0.0f, value));
5177 state_.sample_coverage_invert = (invert != 0);
5178 glSampleCoverage(state_.sample_coverage_value, invert);
5181 // Assumes framebuffer is complete.
5182 void GLES2DecoderImpl::ClearUnclearedAttachments(
5183 GLenum target, Framebuffer* framebuffer) {
5184 if (target == GL_READ_FRAMEBUFFER_EXT) {
5185 // bind this to the DRAW point, clear then bind back to READ
5186 // TODO(gman): I don't think there is any guarantee that an FBO that
5187 // is complete on the READ attachment will be complete as a DRAW
5189 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
5190 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer->service_id());
5192 GLbitfield clear_bits = 0;
5193 if (framebuffer->HasUnclearedColorAttachments()) {
5196 (GLES2Util::GetChannelsForFormat(
5197 framebuffer->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f :
5199 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5200 clear_bits |= GL_COLOR_BUFFER_BIT;
5201 if (feature_info_->feature_flags().ext_draw_buffers)
5202 framebuffer->PrepareDrawBuffersForClear();
5205 if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
5206 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5208 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
5209 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
5210 clear_bits |= GL_STENCIL_BUFFER_BIT;
5213 if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
5214 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5216 state_.SetDeviceDepthMask(GL_TRUE);
5217 clear_bits |= GL_DEPTH_BUFFER_BIT;
5220 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5221 glClear(clear_bits);
5223 if ((clear_bits | GL_COLOR_BUFFER_BIT) != 0 &&
5224 feature_info_->feature_flags().ext_draw_buffers)
5225 framebuffer->RestoreDrawBuffersAfterClear();
5227 framebuffer_manager()->MarkAttachmentsAsCleared(
5228 framebuffer, renderbuffer_manager(), texture_manager());
5230 RestoreClearState();
5232 if (target == GL_READ_FRAMEBUFFER_EXT) {
5233 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer->service_id());
5234 Framebuffer* draw_framebuffer =
5235 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5236 GLuint service_id = draw_framebuffer ? draw_framebuffer->service_id() :
5237 GetBackbufferServiceId();
5238 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
5242 void GLES2DecoderImpl::RestoreClearState() {
5243 framebuffer_state_.clear_state_dirty = true;
5245 state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
5246 state_.color_clear_alpha);
5247 glClearStencil(state_.stencil_clear);
5248 glClearDepth(state_.depth_clear);
5249 if (state_.enable_flags.scissor_test) {
5250 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
5254 GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
5255 Framebuffer* framebuffer =
5256 GetFramebufferInfoForTarget(target);
5258 return GL_FRAMEBUFFER_COMPLETE;
5260 GLenum completeness = framebuffer->IsPossiblyComplete();
5261 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
5262 return completeness;
5264 return framebuffer->GetStatus(texture_manager(), target);
5267 void GLES2DecoderImpl::DoFramebufferTexture2D(
5268 GLenum target, GLenum attachment, GLenum textarget,
5269 GLuint client_texture_id, GLint level) {
5270 DoFramebufferTexture2DCommon(
5271 "glFramebufferTexture2D", target, attachment,
5272 textarget, client_texture_id, level, 0);
5275 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5276 GLenum target, GLenum attachment, GLenum textarget,
5277 GLuint client_texture_id, GLint level, GLsizei samples) {
5278 DoFramebufferTexture2DCommon(
5279 "glFramebufferTexture2DMultisample", target, attachment,
5280 textarget, client_texture_id, level, samples);
5283 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5284 const char* name, GLenum target, GLenum attachment, GLenum textarget,
5285 GLuint client_texture_id, GLint level, GLsizei samples) {
5286 if (samples > renderbuffer_manager()->max_samples()) {
5289 "glFramebufferTexture2DMultisample", "samples too large");
5292 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5295 GL_INVALID_OPERATION,
5296 name, "no framebuffer bound.");
5299 GLuint service_id = 0;
5300 TextureRef* texture_ref = NULL;
5301 if (client_texture_id) {
5302 texture_ref = GetTexture(client_texture_id);
5305 GL_INVALID_OPERATION,
5306 name, "unknown texture_ref");
5309 service_id = texture_ref->service_id();
5312 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
5315 name, "level out of range");
5320 DoWillUseTexImageIfNeeded(texture_ref->texture(), textarget);
5322 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name);
5324 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
5326 if (features().use_img_for_multisampled_render_to_texture) {
5327 glFramebufferTexture2DMultisampleIMG(target, attachment, textarget,
5328 service_id, level, samples);
5330 glFramebufferTexture2DMultisampleEXT(target, attachment, textarget,
5331 service_id, level, samples);
5334 GLenum error = LOCAL_PEEK_GL_ERROR(name);
5335 if (error == GL_NO_ERROR) {
5336 framebuffer->AttachTexture(attachment, texture_ref, textarget, level,
5339 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5340 framebuffer_state_.clear_state_dirty = true;
5344 DoDidUseTexImageIfNeeded(texture_ref->texture(), textarget);
5349 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5350 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
5351 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5354 GL_INVALID_OPERATION,
5355 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5358 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
5359 const Framebuffer::Attachment* attachment_object =
5360 framebuffer->GetAttachment(attachment);
5361 *params = attachment_object ? attachment_object->object_name() : 0;
5363 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT &&
5364 features().use_img_for_multisampled_render_to_texture) {
5365 pname = GL_TEXTURE_SAMPLES_IMG;
5367 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
5371 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5372 GLenum target, GLenum pname, GLint* params) {
5373 Renderbuffer* renderbuffer =
5374 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5375 if (!renderbuffer) {
5377 GL_INVALID_OPERATION,
5378 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5382 EnsureRenderbufferBound();
5384 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5385 *params = renderbuffer->internal_format();
5387 case GL_RENDERBUFFER_WIDTH:
5388 *params = renderbuffer->width();
5390 case GL_RENDERBUFFER_HEIGHT:
5391 *params = renderbuffer->height();
5393 case GL_RENDERBUFFER_SAMPLES_EXT:
5394 if (features().use_img_for_multisampled_render_to_texture) {
5395 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_IMG,
5398 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_EXT,
5402 glGetRenderbufferParameterivEXT(target, pname, params);
5407 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5408 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
5409 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5410 GLbitfield mask, GLenum filter) {
5411 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5413 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5417 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5418 BlitFramebufferHelper(
5419 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5420 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST,
5421 state_.enable_flags.scissor_test);
5424 void GLES2DecoderImpl::EnsureRenderbufferBound() {
5425 if (!state_.bound_renderbuffer_valid) {
5426 state_.bound_renderbuffer_valid = true;
5427 glBindRenderbufferEXT(GL_RENDERBUFFER,
5428 state_.bound_renderbuffer.get()
5429 ? state_.bound_renderbuffer->service_id()
5434 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
5435 const FeatureInfo* feature_info,
5438 GLenum internal_format,
5441 // TODO(sievers): This could be resolved at the GL binding level, but the
5442 // binding process is currently a bit too 'brute force'.
5443 if (feature_info->feature_flags().is_angle) {
5444 glRenderbufferStorageMultisampleANGLE(
5445 target, samples, internal_format, width, height);
5446 } else if (feature_info->feature_flags().use_core_framebuffer_multisample) {
5447 glRenderbufferStorageMultisample(
5448 target, samples, internal_format, width, height);
5450 glRenderbufferStorageMultisampleEXT(
5451 target, samples, internal_format, width, height);
5455 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0,
5465 // TODO(sievers): This could be resolved at the GL binding level, but the
5466 // binding process is currently a bit too 'brute force'.
5467 if (feature_info_->feature_flags().is_angle) {
5468 glBlitFramebufferANGLE(
5469 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5470 } else if (feature_info_->feature_flags().use_core_framebuffer_multisample) {
5472 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5474 glBlitFramebufferEXT(
5475 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5479 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
5481 GLenum internalformat,
5484 if (samples > renderbuffer_manager()->max_samples()) {
5487 "glRenderbufferStorageMultisample", "samples too large");
5491 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5492 height > renderbuffer_manager()->max_renderbuffer_size()) {
5495 "glRenderbufferStorageMultisample", "dimensions too large");
5499 uint32 estimated_size = 0;
5500 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5501 width, height, samples, internalformat, &estimated_size)) {
5504 "glRenderbufferStorageMultisample", "dimensions too large");
5508 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5511 "glRenderbufferStorageMultisample", "out of memory");
5518 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
5519 GLenum target, GLsizei samples, GLenum internalformat,
5520 GLsizei width, GLsizei height) {
5521 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5522 if (!renderbuffer) {
5523 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5524 "glRenderbufferStorageMultisampleCHROMIUM",
5525 "no renderbuffer bound");
5529 if (!ValidateRenderbufferStorageMultisample(
5530 samples, internalformat, width, height)) {
5534 EnsureRenderbufferBound();
5535 GLenum impl_format =
5536 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5538 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
5539 "glRenderbufferStorageMultisampleCHROMIUM");
5540 RenderbufferStorageMultisampleHelper(
5541 feature_info_.get(), target, samples, impl_format, width, height);
5543 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
5544 if (error == GL_NO_ERROR) {
5546 if (workarounds().validate_multisample_buffer_allocation) {
5547 if (!VerifyMultisampleRenderbufferIntegrity(
5548 renderbuffer->service_id(), impl_format)) {
5551 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
5556 // TODO(gman): If renderbuffers tracked which framebuffers they were
5557 // attached to we could just mark those framebuffers as not complete.
5558 framebuffer_manager()->IncFramebufferStateChangeCount();
5559 renderbuffer_manager()->SetInfo(
5560 renderbuffer, samples, internalformat, width, height);
5564 // This is the handler for multisampled_render_to_texture extensions.
5565 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
5566 GLenum target, GLsizei samples, GLenum internalformat,
5567 GLsizei width, GLsizei height) {
5568 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5569 if (!renderbuffer) {
5570 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5571 "glRenderbufferStorageMultisampleEXT",
5572 "no renderbuffer bound");
5576 if (!ValidateRenderbufferStorageMultisample(
5577 samples, internalformat, width, height)) {
5581 EnsureRenderbufferBound();
5582 GLenum impl_format =
5583 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5585 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
5586 if (features().use_img_for_multisampled_render_to_texture) {
5587 glRenderbufferStorageMultisampleIMG(
5588 target, samples, impl_format, width, height);
5590 glRenderbufferStorageMultisampleEXT(
5591 target, samples, impl_format, width, height);
5593 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
5594 if (error == GL_NO_ERROR) {
5595 // TODO(gman): If renderbuffers tracked which framebuffers they were
5596 // attached to we could just mark those framebuffers as not complete.
5597 framebuffer_manager()->IncFramebufferStateChangeCount();
5598 renderbuffer_manager()->SetInfo(
5599 renderbuffer, samples, internalformat, width, height);
5603 // This function validates the allocation of a multisampled renderbuffer
5604 // by clearing it to a key color, blitting the contents to a texture, and
5605 // reading back the color to ensure it matches the key.
5606 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
5607 GLuint renderbuffer, GLenum format) {
5609 // Only validate color buffers.
5610 // These formats have been selected because they are very common or are known
5611 // to be used by the WebGL backbuffer. If problems are observed with other
5612 // color formats they can be added here.
5623 GLint draw_framebuffer, read_framebuffer;
5625 // Cache framebuffer and texture bindings.
5626 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer);
5627 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
5629 if (!validation_texture_) {
5630 GLint bound_texture;
5631 glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture);
5633 // Create additional resources needed for the verification.
5634 glGenTextures(1, &validation_texture_);
5635 glGenFramebuffersEXT(1, &validation_fbo_multisample_);
5636 glGenFramebuffersEXT(1, &validation_fbo_);
5638 // Texture only needs to be 1x1.
5639 glBindTexture(GL_TEXTURE_2D, validation_texture_);
5640 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB,
5641 GL_UNSIGNED_BYTE, NULL);
5643 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5644 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5645 GL_TEXTURE_2D, validation_texture_, 0);
5647 glBindTexture(GL_TEXTURE_2D, bound_texture);
5650 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5651 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5652 GL_RENDERBUFFER, renderbuffer);
5654 // Cache current state and reset it to the values we require.
5655 GLboolean scissor_enabled = false;
5656 glGetBooleanv(GL_SCISSOR_TEST, &scissor_enabled);
5657 if (scissor_enabled)
5658 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5660 GLboolean color_mask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
5661 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
5662 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5664 GLfloat clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
5665 glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color);
5666 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
5668 // Clear the buffer to the desired key color.
5669 glClear(GL_COLOR_BUFFER_BIT);
5671 // Blit from the multisample buffer to a standard texture.
5672 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, validation_fbo_multisample_);
5673 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, validation_fbo_);
5675 BlitFramebufferHelper(
5676 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
5678 // Read a pixel from the buffer.
5679 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5681 unsigned char pixel[3] = {0, 0, 0};
5682 glReadPixels(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel);
5684 // Detach the renderbuffer.
5685 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5686 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5687 GL_RENDERBUFFER, 0);
5689 // Restore cached state.
5690 if (scissor_enabled)
5691 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
5693 state_.SetDeviceColorMask(
5694 color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
5695 glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
5696 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, draw_framebuffer);
5697 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_framebuffer);
5699 // Return true if the pixel matched the desired key color.
5700 return (pixel[0] == 0xFF &&
5705 void GLES2DecoderImpl::DoRenderbufferStorage(
5706 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
5707 Renderbuffer* renderbuffer =
5708 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5709 if (!renderbuffer) {
5711 GL_INVALID_OPERATION,
5712 "glRenderbufferStorage", "no renderbuffer bound");
5716 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5717 height > renderbuffer_manager()->max_renderbuffer_size()) {
5719 GL_INVALID_VALUE, "glRenderbufferStorage", "dimensions too large");
5723 uint32 estimated_size = 0;
5724 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5725 width, height, 1, internalformat, &estimated_size)) {
5727 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "dimensions too large");
5731 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5733 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "out of memory");
5737 EnsureRenderbufferBound();
5738 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
5739 glRenderbufferStorageEXT(
5741 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5745 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
5746 if (error == GL_NO_ERROR) {
5747 // TODO(gman): If tetxures tracked which framebuffers they were attached to
5748 // we could just mark those framebuffers as not complete.
5749 framebuffer_manager()->IncFramebufferStateChangeCount();
5750 renderbuffer_manager()->SetInfo(
5751 renderbuffer, 1, internalformat, width, height);
5755 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
5756 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
5757 Program* program = GetProgramInfoNotShader(
5758 program_id, "glLinkProgram");
5763 LogClientServiceForInfo(program, program_id, "glLinkProgram");
5764 ShaderTranslator* vertex_translator = NULL;
5765 ShaderTranslator* fragment_translator = NULL;
5766 if (use_shader_translator_) {
5767 vertex_translator = vertex_translator_.get();
5768 fragment_translator = fragment_translator_.get();
5770 if (program->Link(shader_manager(),
5772 fragment_translator,
5773 workarounds().count_all_in_varyings_packing ?
5774 Program::kCountAll : Program::kCountOnlyStaticallyUsed,
5775 shader_cache_callback_)) {
5776 if (program == state_.current_program.get()) {
5777 if (workarounds().use_current_program_after_successful_link)
5778 glUseProgram(program->service_id());
5779 if (workarounds().clear_uniforms_before_first_program_use)
5780 program_manager()->ClearUniforms(program);
5784 // LinkProgram can be very slow. Exit command processing to allow for
5785 // context preemption and GPU watchdog checks.
5786 ExitCommandProcessingEarly();
5789 void GLES2DecoderImpl::DoTexParameterf(
5790 GLenum target, GLenum pname, GLfloat param) {
5791 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5794 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
5798 texture_manager()->SetParameterf(
5799 "glTexParameterf", GetErrorState(), texture, pname, param);
5802 void GLES2DecoderImpl::DoTexParameteri(
5803 GLenum target, GLenum pname, GLint param) {
5804 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5807 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
5811 texture_manager()->SetParameteri(
5812 "glTexParameteri", GetErrorState(), texture, pname, param);
5815 void GLES2DecoderImpl::DoTexParameterfv(
5816 GLenum target, GLenum pname, const GLfloat* params) {
5817 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5820 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
5824 texture_manager()->SetParameterf(
5825 "glTexParameterfv", GetErrorState(), texture, pname, *params);
5828 void GLES2DecoderImpl::DoTexParameteriv(
5829 GLenum target, GLenum pname, const GLint* params) {
5830 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5834 GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
5838 texture_manager()->SetParameteri(
5839 "glTexParameteriv", GetErrorState(), texture, pname, *params);
5842 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
5843 if (!state_.current_program.get()) {
5844 // The program does not exist.
5846 GL_INVALID_OPERATION, function_name, "no program in use");
5849 if (!state_.current_program->InUse()) {
5851 GL_INVALID_OPERATION, function_name, "program not linked");
5857 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
5858 GLint location, const char* function_name) {
5859 if (!CheckCurrentProgram(function_name)) {
5862 return location != -1;
5865 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
5866 GLint fake_location,
5867 const char* function_name,
5868 Program::UniformApiType api_type,
5869 GLint* real_location,
5874 DCHECK(real_location);
5876 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
5879 GLint array_index = -1;
5880 const Program::UniformInfo* info =
5881 state_.current_program->GetUniformInfoByFakeLocation(
5882 fake_location, real_location, &array_index);
5885 GL_INVALID_OPERATION, function_name, "unknown location");
5889 if ((api_type & info->accepts_api_type) == 0) {
5891 GL_INVALID_OPERATION, function_name,
5892 "wrong uniform function for type");
5895 if (*count > 1 && !info->is_array) {
5897 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
5900 *count = std::min(info->size - array_index, *count);
5908 void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
5911 GLint real_location = -1;
5912 if (!PrepForSetUniformByLocation(fake_location,
5914 Program::kUniform1i,
5920 if (!state_.current_program->SetSamplers(
5921 state_.texture_units.size(), fake_location, 1, &v0)) {
5923 GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
5926 glUniform1i(real_location, v0);
5929 void GLES2DecoderImpl::DoUniform1iv(
5930 GLint fake_location, GLsizei count, const GLint *value) {
5932 GLint real_location = -1;
5933 if (!PrepForSetUniformByLocation(fake_location,
5935 Program::kUniform1i,
5941 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
5942 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
5943 if (!state_.current_program->SetSamplers(
5944 state_.texture_units.size(), fake_location, count, value)) {
5946 GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
5950 glUniform1iv(real_location, count, value);
5953 void GLES2DecoderImpl::DoUniform1fv(
5954 GLint fake_location, GLsizei count, const GLfloat* value) {
5956 GLint real_location = -1;
5957 if (!PrepForSetUniformByLocation(fake_location,
5959 Program::kUniform1f,
5965 if (type == GL_BOOL) {
5966 scoped_ptr<GLint[]> temp(new GLint[count]);
5967 for (GLsizei ii = 0; ii < count; ++ii) {
5968 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5970 DoUniform1iv(real_location, count, temp.get());
5972 glUniform1fv(real_location, count, value);
5976 void GLES2DecoderImpl::DoUniform2fv(
5977 GLint fake_location, GLsizei count, const GLfloat* value) {
5979 GLint real_location = -1;
5980 if (!PrepForSetUniformByLocation(fake_location,
5982 Program::kUniform2f,
5988 if (type == GL_BOOL_VEC2) {
5989 GLsizei num_values = count * 2;
5990 scoped_ptr<GLint[]> temp(new GLint[num_values]);
5991 for (GLsizei ii = 0; ii < num_values; ++ii) {
5992 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5994 glUniform2iv(real_location, count, temp.get());
5996 glUniform2fv(real_location, count, value);
6000 void GLES2DecoderImpl::DoUniform3fv(
6001 GLint fake_location, GLsizei count, const GLfloat* value) {
6003 GLint real_location = -1;
6004 if (!PrepForSetUniformByLocation(fake_location,
6006 Program::kUniform3f,
6012 if (type == GL_BOOL_VEC3) {
6013 GLsizei num_values = count * 3;
6014 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6015 for (GLsizei ii = 0; ii < num_values; ++ii) {
6016 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6018 glUniform3iv(real_location, count, temp.get());
6020 glUniform3fv(real_location, count, value);
6024 void GLES2DecoderImpl::DoUniform4fv(
6025 GLint fake_location, GLsizei count, const GLfloat* value) {
6027 GLint real_location = -1;
6028 if (!PrepForSetUniformByLocation(fake_location,
6030 Program::kUniform4f,
6036 if (type == GL_BOOL_VEC4) {
6037 GLsizei num_values = count * 4;
6038 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6039 for (GLsizei ii = 0; ii < num_values; ++ii) {
6040 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6042 glUniform4iv(real_location, count, temp.get());
6044 glUniform4fv(real_location, count, value);
6048 void GLES2DecoderImpl::DoUniform2iv(
6049 GLint fake_location, GLsizei count, const GLint* value) {
6051 GLint real_location = -1;
6052 if (!PrepForSetUniformByLocation(fake_location,
6054 Program::kUniform2i,
6060 glUniform2iv(real_location, count, value);
6063 void GLES2DecoderImpl::DoUniform3iv(
6064 GLint fake_location, GLsizei count, const GLint* value) {
6066 GLint real_location = -1;
6067 if (!PrepForSetUniformByLocation(fake_location,
6069 Program::kUniform3i,
6075 glUniform3iv(real_location, count, value);
6078 void GLES2DecoderImpl::DoUniform4iv(
6079 GLint fake_location, GLsizei count, const GLint* value) {
6081 GLint real_location = -1;
6082 if (!PrepForSetUniformByLocation(fake_location,
6084 Program::kUniform4i,
6090 glUniform4iv(real_location, count, value);
6093 void GLES2DecoderImpl::DoUniformMatrix2fv(
6094 GLint fake_location, GLsizei count, GLboolean transpose,
6095 const GLfloat* value) {
6097 GLint real_location = -1;
6098 if (!PrepForSetUniformByLocation(fake_location,
6099 "glUniformMatrix2fv",
6100 Program::kUniformMatrix2f,
6106 glUniformMatrix2fv(real_location, count, transpose, value);
6109 void GLES2DecoderImpl::DoUniformMatrix3fv(
6110 GLint fake_location, GLsizei count, GLboolean transpose,
6111 const GLfloat* value) {
6113 GLint real_location = -1;
6114 if (!PrepForSetUniformByLocation(fake_location,
6115 "glUniformMatrix3fv",
6116 Program::kUniformMatrix3f,
6122 glUniformMatrix3fv(real_location, count, transpose, value);
6125 void GLES2DecoderImpl::DoUniformMatrix4fv(
6126 GLint fake_location, GLsizei count, GLboolean transpose,
6127 const GLfloat* value) {
6129 GLint real_location = -1;
6130 if (!PrepForSetUniformByLocation(fake_location,
6131 "glUniformMatrix4fv",
6132 Program::kUniformMatrix4f,
6138 glUniformMatrix4fv(real_location, count, transpose, value);
6141 void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
6142 GLuint service_id = 0;
6143 Program* program = NULL;
6145 program = GetProgramInfoNotShader(program_id, "glUseProgram");
6149 if (!program->IsValid()) {
6150 // Program was not linked successfully. (ie, glLinkProgram)
6152 GL_INVALID_OPERATION, "glUseProgram", "program not linked");
6155 service_id = program->service_id();
6157 if (state_.current_program.get()) {
6158 program_manager()->UnuseProgram(shader_manager(),
6159 state_.current_program.get());
6161 state_.current_program = program;
6162 LogClientServiceMapping("glUseProgram", program_id, service_id);
6163 glUseProgram(service_id);
6164 if (state_.current_program.get()) {
6165 program_manager()->UseProgram(state_.current_program.get());
6166 if (workarounds().clear_uniforms_before_first_program_use)
6167 program_manager()->ClearUniforms(program);
6171 void GLES2DecoderImpl::RenderWarning(
6172 const char* filename, int line, const std::string& msg) {
6173 logger_.LogMessage(filename, line, std::string("RENDER WARNING: ") + msg);
6176 void GLES2DecoderImpl::PerformanceWarning(
6177 const char* filename, int line, const std::string& msg) {
6178 logger_.LogMessage(filename, line,
6179 std::string("PERFORMANCE WARNING: ") + msg);
6182 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
6183 Texture* texture, GLenum textarget) {
6184 // Image is already in use if texture is attached to a framebuffer.
6185 if (texture && !texture->IsAttachedToFramebuffer()) {
6186 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6188 ScopedGLErrorSuppressor suppressor(
6189 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
6191 glBindTexture(textarget, texture->service_id());
6192 image->WillUseTexImage();
6193 RestoreCurrentTextureBindings(&state_, textarget);
6198 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6199 Texture* texture, GLenum textarget) {
6200 // Image is still in use if texture is attached to a framebuffer.
6201 if (texture && !texture->IsAttachedToFramebuffer()) {
6202 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6204 ScopedGLErrorSuppressor suppressor(
6205 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6207 glBindTexture(textarget, texture->service_id());
6208 image->DidUseTexImage();
6209 RestoreCurrentTextureBindings(&state_, textarget);
6214 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6215 DCHECK(state_.current_program.get());
6216 if (!texture_manager()->HaveUnrenderableTextures() &&
6217 !texture_manager()->HaveImages()) {
6221 bool textures_set = false;
6222 const Program::SamplerIndices& sampler_indices =
6223 state_.current_program->sampler_indices();
6224 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6225 const Program::UniformInfo* uniform_info =
6226 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6227 DCHECK(uniform_info);
6228 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6229 GLuint texture_unit_index = uniform_info->texture_units[jj];
6230 if (texture_unit_index < state_.texture_units.size()) {
6231 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6232 TextureRef* texture_ref =
6233 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6234 GLenum textarget = GetBindTargetForSamplerType(uniform_info->type);
6235 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6236 textures_set = true;
6237 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6240 texture_manager()->black_texture_id(uniform_info->type));
6241 LOCAL_RENDER_WARNING(
6242 std::string("texture bound to texture unit ") +
6243 base::IntToString(texture_unit_index) +
6244 " is not renderable. It maybe non-power-of-2 and have"
6245 " incompatible texture filtering or is not"
6246 " 'texture complete'");
6250 if (textarget != GL_TEXTURE_CUBE_MAP) {
6251 Texture* texture = texture_ref->texture();
6252 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6253 if (image && !texture->IsAttachedToFramebuffer()) {
6254 ScopedGLErrorSuppressor suppressor(
6255 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6256 textures_set = true;
6257 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6258 image->WillUseTexImage();
6263 // else: should this be an error?
6266 return !textures_set;
6269 void GLES2DecoderImpl::RestoreStateForTextures() {
6270 DCHECK(state_.current_program.get());
6271 const Program::SamplerIndices& sampler_indices =
6272 state_.current_program->sampler_indices();
6273 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6274 const Program::UniformInfo* uniform_info =
6275 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6276 DCHECK(uniform_info);
6277 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6278 GLuint texture_unit_index = uniform_info->texture_units[jj];
6279 if (texture_unit_index < state_.texture_units.size()) {
6280 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6281 TextureRef* texture_ref =
6282 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6283 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6284 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6285 // Get the texture_ref info that was previously bound here.
6286 texture_ref = texture_unit.bind_target == GL_TEXTURE_2D
6287 ? texture_unit.bound_texture_2d.get()
6288 : texture_unit.bound_texture_cube_map.get();
6289 glBindTexture(texture_unit.bind_target,
6290 texture_ref ? texture_ref->service_id() : 0);
6294 if (texture_unit.bind_target != GL_TEXTURE_CUBE_MAP) {
6295 Texture* texture = texture_ref->texture();
6296 gfx::GLImage* image =
6297 texture->GetLevelImage(texture_unit.bind_target, 0);
6298 if (image && !texture->IsAttachedToFramebuffer()) {
6299 ScopedGLErrorSuppressor suppressor(
6300 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
6301 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6302 image->DidUseTexImage();
6309 // Set the active texture back to whatever the user had it as.
6310 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
6313 bool GLES2DecoderImpl::ClearUnclearedTextures() {
6314 // Only check if there are some uncleared textures.
6315 if (!texture_manager()->HaveUnsafeTextures()) {
6319 // 1: Check all textures we are about to render with.
6320 if (state_.current_program.get()) {
6321 const Program::SamplerIndices& sampler_indices =
6322 state_.current_program->sampler_indices();
6323 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6324 const Program::UniformInfo* uniform_info =
6325 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6326 DCHECK(uniform_info);
6327 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6328 GLuint texture_unit_index = uniform_info->texture_units[jj];
6329 if (texture_unit_index < state_.texture_units.size()) {
6330 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6331 TextureRef* texture_ref =
6332 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6333 if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
6334 if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
6345 bool GLES2DecoderImpl::IsDrawValid(
6346 const char* function_name, GLuint max_vertex_accessed, bool instanced,
6347 GLsizei primcount) {
6348 DCHECK(instanced || primcount == 1);
6350 // NOTE: We specifically do not check current_program->IsValid() because
6351 // it could never be invalid since glUseProgram would have failed. While
6352 // glLinkProgram could later mark the program as invalid the previous
6353 // valid program will still function if it is still the current program.
6354 if (!state_.current_program.get()) {
6355 // The program does not exist.
6356 // But GL says no ERROR.
6357 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
6361 return state_.vertex_attrib_manager
6362 ->ValidateBindings(function_name,
6364 feature_info_.get(),
6365 state_.current_program.get(),
6366 max_vertex_accessed,
6371 bool GLES2DecoderImpl::SimulateAttrib0(
6372 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
6376 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
6379 const VertexAttrib* attrib =
6380 state_.vertex_attrib_manager->GetVertexAttrib(0);
6381 // If it's enabled or it's not used then we don't need to do anything.
6382 bool attrib_0_used =
6383 state_.current_program->GetAttribInfoByLocation(0) != NULL;
6384 if (attrib->enabled() && attrib_0_used) {
6388 // Make a buffer with a single repeated vec4 value enough to
6389 // simulate the constant value that is supposed to be here.
6390 // This is required to emulate GLES2 on GL.
6391 GLuint num_vertices = max_vertex_accessed + 1;
6392 uint32 size_needed = 0;
6394 if (num_vertices == 0 ||
6395 !SafeMultiplyUint32(num_vertices, sizeof(Vec4), &size_needed) ||
6396 size_needed > 0x7FFFFFFFU) {
6397 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6401 LOCAL_PERFORMANCE_WARNING(
6402 "Attribute 0 is disabled. This has signficant performance penalty");
6404 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6405 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
6407 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
6409 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6410 GLenum error = glGetError();
6411 if (error != GL_NO_ERROR) {
6413 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6418 const Vec4& value = state_.attrib_values[0];
6421 (!attrib_0_buffer_matches_value_ ||
6422 (value.v[0] != attrib_0_value_.v[0] ||
6423 value.v[1] != attrib_0_value_.v[1] ||
6424 value.v[2] != attrib_0_value_.v[2] ||
6425 value.v[3] != attrib_0_value_.v[3])))) {
6426 std::vector<Vec4> temp(num_vertices, value);
6427 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
6428 attrib_0_buffer_matches_value_ = true;
6429 attrib_0_value_ = value;
6430 attrib_0_size_ = size_needed;
6433 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
6435 if (attrib->divisor())
6436 glVertexAttribDivisorANGLE(0, 0);
6442 void GLES2DecoderImpl::RestoreStateForAttrib(
6443 GLuint attrib_index, bool restore_array_binding) {
6444 const VertexAttrib* attrib =
6445 state_.vertex_attrib_manager->GetVertexAttrib(attrib_index);
6446 if (restore_array_binding) {
6447 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
6448 Buffer* buffer = attrib->buffer();
6449 glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
6450 glVertexAttribPointer(
6451 attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
6452 attrib->gl_stride(), ptr);
6454 if (attrib->divisor())
6455 glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
6457 GL_ARRAY_BUFFER, state_.bound_array_buffer.get() ?
6458 state_.bound_array_buffer->service_id() : 0);
6460 // Never touch vertex attribute 0's state (in particular, never
6461 // disable it) when running on desktop GL because it will never be
6463 if (attrib_index != 0 ||
6464 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
6465 if (attrib->enabled()) {
6466 glEnableVertexAttribArray(attrib_index);
6468 glDisableVertexAttribArray(attrib_index);
6473 bool GLES2DecoderImpl::SimulateFixedAttribs(
6474 const char* function_name,
6475 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
6478 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
6481 if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
6485 LOCAL_PERFORMANCE_WARNING(
6486 "GL_FIXED attributes have a signficant performance penalty");
6488 // NOTE: we could be smart and try to check if a buffer is used
6489 // twice in 2 different attribs, find the overlapping parts and therefore
6490 // duplicate the minimum amount of data but this whole code path is not meant
6491 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
6492 // tests so we just add to the buffer attrib used.
6494 GLuint elements_needed = 0;
6495 const VertexAttribManager::VertexAttribList& enabled_attribs =
6496 state_.vertex_attrib_manager->GetEnabledVertexAttribs();
6497 for (VertexAttribManager::VertexAttribList::const_iterator it =
6498 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6499 const VertexAttrib* attrib = *it;
6500 const Program::VertexAttrib* attrib_info =
6501 state_.current_program->GetAttribInfoByLocation(attrib->index());
6502 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6503 max_vertex_accessed);
6504 GLuint num_vertices = max_accessed + 1;
6505 if (num_vertices == 0) {
6507 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6511 attrib->CanAccess(max_accessed) &&
6512 attrib->type() == GL_FIXED) {
6513 uint32 elements_used = 0;
6514 if (!SafeMultiplyUint32(num_vertices, attrib->size(), &elements_used) ||
6515 !SafeAddUint32(elements_needed, elements_used, &elements_needed)) {
6517 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6523 const uint32 kSizeOfFloat = sizeof(float); // NOLINT
6524 uint32 size_needed = 0;
6525 if (!SafeMultiplyUint32(elements_needed, kSizeOfFloat, &size_needed) ||
6526 size_needed > 0x7FFFFFFFU) {
6528 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6532 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6534 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
6535 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
6536 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6537 GLenum error = glGetError();
6538 if (error != GL_NO_ERROR) {
6540 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6545 // Copy the elements and convert to float
6546 GLintptr offset = 0;
6547 for (VertexAttribManager::VertexAttribList::const_iterator it =
6548 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6549 const VertexAttrib* attrib = *it;
6550 const Program::VertexAttrib* attrib_info =
6551 state_.current_program->GetAttribInfoByLocation(attrib->index());
6552 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6553 max_vertex_accessed);
6554 GLuint num_vertices = max_accessed + 1;
6555 if (num_vertices == 0) {
6557 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6561 attrib->CanAccess(max_accessed) &&
6562 attrib->type() == GL_FIXED) {
6563 int num_elements = attrib->size() * kSizeOfFloat;
6564 int size = num_elements * num_vertices;
6565 scoped_ptr<float[]> data(new float[size]);
6566 const int32* src = reinterpret_cast<const int32 *>(
6567 attrib->buffer()->GetRange(attrib->offset(), size));
6568 const int32* end = src + num_elements;
6569 float* dst = data.get();
6570 while (src != end) {
6571 *dst++ = static_cast<float>(*src++) / 65536.0f;
6573 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
6574 glVertexAttribPointer(
6575 attrib->index(), attrib->size(), GL_FLOAT, false, 0,
6576 reinterpret_cast<GLvoid*>(offset));
6584 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
6585 // There's no need to call glVertexAttribPointer because we shadow all the
6586 // settings and passing GL_FIXED to it will not work.
6589 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
6593 error::Error GLES2DecoderImpl::DoDrawArrays(
6594 const char* function_name,
6599 GLsizei primcount) {
6600 error::Error error = WillAccessBoundFramebufferForDraw();
6601 if (error != error::kNoError)
6603 if (!validators_->draw_mode.IsValid(mode)) {
6604 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
6605 return error::kNoError;
6608 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
6609 return error::kNoError;
6611 if (primcount < 0) {
6612 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
6613 return error::kNoError;
6615 if (!CheckBoundFramebuffersValid(function_name)) {
6616 return error::kNoError;
6618 // We have to check this here because the prototype for glDrawArrays
6619 // is GLint not GLsizei.
6621 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "first < 0");
6622 return error::kNoError;
6625 if (count == 0 || primcount == 0) {
6626 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
6627 return error::kNoError;
6630 GLuint max_vertex_accessed = first + count - 1;
6631 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
6632 if (!ClearUnclearedTextures()) {
6633 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
6634 return error::kNoError;
6636 bool simulated_attrib_0 = false;
6637 if (!SimulateAttrib0(
6638 function_name, max_vertex_accessed, &simulated_attrib_0)) {
6639 return error::kNoError;
6641 bool simulated_fixed_attribs = false;
6642 if (SimulateFixedAttribs(
6643 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6645 bool textures_set = !PrepareTexturesForRender();
6647 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
6649 glDrawArrays(mode, first, count);
6651 glDrawArraysInstancedANGLE(mode, first, count, primcount);
6654 RestoreStateForTextures();
6656 if (simulated_fixed_attribs) {
6657 RestoreStateForSimulatedFixedAttribs();
6660 if (simulated_attrib_0) {
6661 // We don't have to restore attrib 0 generic data at the end of this
6662 // function even if it is simulated. This is because we will simulate
6663 // it in each draw call, and attrib 0 generic data queries use cached
6664 // values instead of passing down to the underlying driver.
6665 RestoreStateForAttrib(0, false);
6668 return error::kNoError;
6671 error::Error GLES2DecoderImpl::HandleDrawArrays(uint32 immediate_data_size,
6672 const void* cmd_data) {
6673 const cmds::DrawArrays& c = *static_cast<const cmds::DrawArrays*>(cmd_data);
6674 return DoDrawArrays("glDrawArrays",
6676 static_cast<GLenum>(c.mode),
6677 static_cast<GLint>(c.first),
6678 static_cast<GLsizei>(c.count),
6682 error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
6683 uint32 immediate_data_size,
6684 const void* cmd_data) {
6685 const gles2::cmds::DrawArraysInstancedANGLE& c =
6686 *static_cast<const gles2::cmds::DrawArraysInstancedANGLE*>(cmd_data);
6687 if (!features().angle_instanced_arrays) {
6689 GL_INVALID_OPERATION,
6690 "glDrawArraysInstancedANGLE", "function not available");
6691 return error::kNoError;
6693 return DoDrawArrays("glDrawArraysIntancedANGLE",
6695 static_cast<GLenum>(c.mode),
6696 static_cast<GLint>(c.first),
6697 static_cast<GLsizei>(c.count),
6698 static_cast<GLsizei>(c.primcount));
6701 error::Error GLES2DecoderImpl::DoDrawElements(
6702 const char* function_name,
6708 GLsizei primcount) {
6709 error::Error error = WillAccessBoundFramebufferForDraw();
6710 if (error != error::kNoError)
6712 if (!state_.vertex_attrib_manager->element_array_buffer()) {
6714 GL_INVALID_OPERATION, function_name, "No element array buffer bound");
6715 return error::kNoError;
6719 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
6720 return error::kNoError;
6723 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "offset < 0");
6724 return error::kNoError;
6726 if (!validators_->draw_mode.IsValid(mode)) {
6727 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
6728 return error::kNoError;
6730 if (!validators_->index_type.IsValid(type)) {
6731 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
6732 return error::kNoError;
6734 if (primcount < 0) {
6735 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
6736 return error::kNoError;
6739 if (!CheckBoundFramebuffersValid(function_name)) {
6740 return error::kNoError;
6743 if (count == 0 || primcount == 0) {
6744 return error::kNoError;
6747 GLuint max_vertex_accessed;
6748 Buffer* element_array_buffer =
6749 state_.vertex_attrib_manager->element_array_buffer();
6751 if (!element_array_buffer->GetMaxValueForRange(
6752 offset, count, type, &max_vertex_accessed)) {
6754 GL_INVALID_OPERATION, function_name, "range out of bounds for buffer");
6755 return error::kNoError;
6758 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
6759 if (!ClearUnclearedTextures()) {
6760 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
6761 return error::kNoError;
6763 bool simulated_attrib_0 = false;
6764 if (!SimulateAttrib0(
6765 function_name, max_vertex_accessed, &simulated_attrib_0)) {
6766 return error::kNoError;
6768 bool simulated_fixed_attribs = false;
6769 if (SimulateFixedAttribs(
6770 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6772 bool textures_set = !PrepareTexturesForRender();
6774 // TODO(gman): Refactor to hide these details in BufferManager or
6775 // VertexAttribManager.
6776 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
6777 bool used_client_side_array = false;
6778 if (element_array_buffer->IsClientSideArray()) {
6779 used_client_side_array = true;
6780 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
6781 indices = element_array_buffer->GetRange(offset, 0);
6784 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
6786 glDrawElements(mode, count, type, indices);
6788 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
6791 if (used_client_side_array) {
6792 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
6793 element_array_buffer->service_id());
6797 RestoreStateForTextures();
6799 if (simulated_fixed_attribs) {
6800 RestoreStateForSimulatedFixedAttribs();
6803 if (simulated_attrib_0) {
6804 // We don't have to restore attrib 0 generic data at the end of this
6805 // function even if it is simulated. This is because we will simulate
6806 // it in each draw call, and attrib 0 generic data queries use cached
6807 // values instead of passing down to the underlying driver.
6808 RestoreStateForAttrib(0, false);
6811 return error::kNoError;
6814 error::Error GLES2DecoderImpl::HandleDrawElements(uint32 immediate_data_size,
6815 const void* cmd_data) {
6816 const gles2::cmds::DrawElements& c =
6817 *static_cast<const gles2::cmds::DrawElements*>(cmd_data);
6818 return DoDrawElements("glDrawElements",
6820 static_cast<GLenum>(c.mode),
6821 static_cast<GLsizei>(c.count),
6822 static_cast<GLenum>(c.type),
6823 static_cast<int32>(c.index_offset),
6827 error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
6828 uint32 immediate_data_size,
6829 const void* cmd_data) {
6830 const gles2::cmds::DrawElementsInstancedANGLE& c =
6831 *static_cast<const gles2::cmds::DrawElementsInstancedANGLE*>(cmd_data);
6832 if (!features().angle_instanced_arrays) {
6834 GL_INVALID_OPERATION,
6835 "glDrawElementsInstancedANGLE", "function not available");
6836 return error::kNoError;
6838 return DoDrawElements("glDrawElementsInstancedANGLE",
6840 static_cast<GLenum>(c.mode),
6841 static_cast<GLsizei>(c.count),
6842 static_cast<GLenum>(c.type),
6843 static_cast<int32>(c.index_offset),
6844 static_cast<GLsizei>(c.primcount));
6847 GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
6848 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
6849 GLuint max_vertex_accessed = 0;
6850 Buffer* buffer = GetBuffer(buffer_id);
6852 // TODO(gman): Should this be a GL error or a command buffer error?
6854 GL_INVALID_VALUE, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
6856 if (!buffer->GetMaxValueForRange(
6857 offset, count, type, &max_vertex_accessed)) {
6858 // TODO(gman): Should this be a GL error or a command buffer error?
6860 GL_INVALID_OPERATION,
6861 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
6864 return max_vertex_accessed;
6867 // Calls glShaderSource for the various versions of the ShaderSource command.
6868 // Assumes that data / data_size points to a piece of memory that is in range
6869 // of whatever context it came from (shared memory, immediate memory, bucket
6871 error::Error GLES2DecoderImpl::ShaderSourceHelper(
6872 GLuint client_id, const char* data, uint32 data_size) {
6873 std::string str(data, data + data_size);
6874 Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
6876 return error::kNoError;
6878 // Note: We don't actually call glShaderSource here. We wait until
6879 // the call to glCompileShader.
6880 shader->set_source(str);
6881 return error::kNoError;
6884 error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
6885 uint32 immediate_data_size,
6886 const void* cmd_data) {
6887 const gles2::cmds::ShaderSourceBucket& c =
6888 *static_cast<const gles2::cmds::ShaderSourceBucket*>(cmd_data);
6889 Bucket* bucket = GetBucket(c.data_bucket_id);
6890 if (!bucket || bucket->size() == 0) {
6891 return error::kInvalidArguments;
6893 return ShaderSourceHelper(
6894 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
6895 bucket->size() - 1);
6898 void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
6899 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
6900 Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader");
6904 ShaderTranslator* translator = NULL;
6905 if (use_shader_translator_) {
6906 translator = shader->shader_type() == GL_VERTEX_SHADER ?
6907 vertex_translator_.get() : fragment_translator_.get();
6912 feature_info_->feature_flags().angle_translated_shader_source ?
6913 Shader::kANGLE : Shader::kGL);
6915 // CompileShader can be very slow. Exit command processing to allow for
6916 // context preemption and GPU watchdog checks.
6917 ExitCommandProcessingEarly();
6920 void GLES2DecoderImpl::DoGetShaderiv(
6921 GLuint shader_id, GLenum pname, GLint* params) {
6922 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderiv");
6927 case GL_SHADER_SOURCE_LENGTH:
6928 *params = shader->source().size();
6932 case GL_COMPILE_STATUS:
6933 *params = compile_shader_always_succeeds_ ? true : shader->valid();
6935 case GL_INFO_LOG_LENGTH:
6936 *params = shader->log_info().size();
6940 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
6941 *params = shader->translated_source().size();
6948 glGetShaderiv(shader->service_id(), pname, params);
6951 error::Error GLES2DecoderImpl::HandleGetShaderSource(uint32 immediate_data_size,
6952 const void* cmd_data) {
6953 const gles2::cmds::GetShaderSource& c =
6954 *static_cast<const gles2::cmds::GetShaderSource*>(cmd_data);
6955 GLuint shader_id = c.shader;
6956 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6957 Bucket* bucket = CreateBucket(bucket_id);
6958 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderSource");
6959 if (!shader || shader->source().empty()) {
6961 return error::kNoError;
6963 bucket->SetFromString(shader->source().c_str());
6964 return error::kNoError;
6967 error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
6968 uint32 immediate_data_size,
6969 const void* cmd_data) {
6970 const gles2::cmds::GetTranslatedShaderSourceANGLE& c =
6971 *static_cast<const gles2::cmds::GetTranslatedShaderSourceANGLE*>(
6973 GLuint shader_id = c.shader;
6974 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6975 Bucket* bucket = CreateBucket(bucket_id);
6976 Shader* shader = GetShaderInfoNotProgram(
6977 shader_id, "glGetTranslatedShaderSourceANGLE");
6980 return error::kNoError;
6983 bucket->SetFromString(shader->translated_source().c_str());
6984 return error::kNoError;
6987 error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
6988 uint32 immediate_data_size,
6989 const void* cmd_data) {
6990 const gles2::cmds::GetProgramInfoLog& c =
6991 *static_cast<const gles2::cmds::GetProgramInfoLog*>(cmd_data);
6992 GLuint program_id = c.program;
6993 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6994 Bucket* bucket = CreateBucket(bucket_id);
6995 Program* program = GetProgramInfoNotShader(
6996 program_id, "glGetProgramInfoLog");
6997 if (!program || !program->log_info()) {
6998 bucket->SetFromString("");
6999 return error::kNoError;
7001 bucket->SetFromString(program->log_info()->c_str());
7002 return error::kNoError;
7005 error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
7006 uint32 immediate_data_size,
7007 const void* cmd_data) {
7008 const gles2::cmds::GetShaderInfoLog& c =
7009 *static_cast<const gles2::cmds::GetShaderInfoLog*>(cmd_data);
7010 GLuint shader_id = c.shader;
7011 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7012 Bucket* bucket = CreateBucket(bucket_id);
7013 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderInfoLog");
7015 bucket->SetFromString("");
7016 return error::kNoError;
7018 bucket->SetFromString(shader->log_info().c_str());
7019 return error::kNoError;
7022 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
7023 return state_.GetEnabled(cap);
7026 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
7027 const Buffer* buffer = GetBuffer(client_id);
7028 return buffer && buffer->IsValid() && !buffer->IsDeleted();
7031 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
7032 const Framebuffer* framebuffer =
7033 GetFramebuffer(client_id);
7034 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
7037 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
7038 // IsProgram is true for programs as soon as they are created, until they are
7039 // deleted and no longer in use.
7040 const Program* program = GetProgram(client_id);
7041 return program != NULL && !program->IsDeleted();
7044 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
7045 const Renderbuffer* renderbuffer =
7046 GetRenderbuffer(client_id);
7047 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
7050 bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
7051 // IsShader is true for shaders as soon as they are created, until they
7052 // are deleted and not attached to any programs.
7053 const Shader* shader = GetShader(client_id);
7054 return shader != NULL && !shader->IsDeleted();
7057 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
7058 const TextureRef* texture_ref = GetTexture(client_id);
7059 return texture_ref && texture_ref->texture()->IsValid();
7062 void GLES2DecoderImpl::DoAttachShader(
7063 GLuint program_client_id, GLint shader_client_id) {
7064 Program* program = GetProgramInfoNotShader(
7065 program_client_id, "glAttachShader");
7069 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glAttachShader");
7073 if (!program->AttachShader(shader_manager(), shader)) {
7075 GL_INVALID_OPERATION,
7077 "can not attach more than one shader of the same type.");
7080 glAttachShader(program->service_id(), shader->service_id());
7083 void GLES2DecoderImpl::DoDetachShader(
7084 GLuint program_client_id, GLint shader_client_id) {
7085 Program* program = GetProgramInfoNotShader(
7086 program_client_id, "glDetachShader");
7090 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glDetachShader");
7094 if (!program->DetachShader(shader_manager(), shader)) {
7096 GL_INVALID_OPERATION,
7097 "glDetachShader", "shader not attached to program");
7100 glDetachShader(program->service_id(), shader->service_id());
7103 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
7104 Program* program = GetProgramInfoNotShader(
7105 program_client_id, "glValidateProgram");
7109 program->Validate();
7112 void GLES2DecoderImpl::GetVertexAttribHelper(
7113 const VertexAttrib* attrib, GLenum pname, GLint* params) {
7115 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
7116 Buffer* buffer = attrib->buffer();
7117 if (buffer && !buffer->IsDeleted()) {
7119 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
7120 *params = client_id;
7124 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
7125 *params = attrib->enabled();
7127 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
7128 *params = attrib->size();
7130 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
7131 *params = attrib->gl_stride();
7133 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
7134 *params = attrib->type();
7136 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
7137 *params = attrib->normalized();
7139 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
7140 *params = attrib->divisor();
7148 void GLES2DecoderImpl::DoGetTexParameterfv(
7149 GLenum target, GLenum pname, GLfloat* params) {
7150 InitTextureMaxAnisotropyIfNeeded(target, pname);
7151 glGetTexParameterfv(target, pname, params);
7154 void GLES2DecoderImpl::DoGetTexParameteriv(
7155 GLenum target, GLenum pname, GLint* params) {
7156 InitTextureMaxAnisotropyIfNeeded(target, pname);
7157 glGetTexParameteriv(target, pname, params);
7160 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
7161 GLenum target, GLenum pname) {
7162 if (!workarounds().init_texture_max_anisotropy)
7164 if (pname != GL_TEXTURE_MAX_ANISOTROPY_EXT ||
7165 !validators_->texture_parameter.IsValid(pname)) {
7169 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
7173 GL_INVALID_OPERATION,
7174 "glGetTexParamter{fi}v", "unknown texture for target");
7177 Texture* texture = texture_ref->texture();
7178 texture->InitTextureMaxAnisotropyIfNeeded(target);
7181 void GLES2DecoderImpl::DoGetVertexAttribfv(
7182 GLuint index, GLenum pname, GLfloat* params) {
7183 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
7186 GL_INVALID_VALUE, "glGetVertexAttribfv", "index out of range");
7190 case GL_CURRENT_VERTEX_ATTRIB: {
7191 const Vec4& value = state_.attrib_values[index];
7192 params[0] = value.v[0];
7193 params[1] = value.v[1];
7194 params[2] = value.v[2];
7195 params[3] = value.v[3];
7200 GetVertexAttribHelper(attrib, pname, &value);
7201 *params = static_cast<GLfloat>(value);
7207 void GLES2DecoderImpl::DoGetVertexAttribiv(
7208 GLuint index, GLenum pname, GLint* params) {
7209 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
7212 GL_INVALID_VALUE, "glGetVertexAttribiv", "index out of range");
7216 case GL_CURRENT_VERTEX_ATTRIB: {
7217 const Vec4& value = state_.attrib_values[index];
7218 params[0] = static_cast<GLint>(value.v[0]);
7219 params[1] = static_cast<GLint>(value.v[1]);
7220 params[2] = static_cast<GLint>(value.v[2]);
7221 params[3] = static_cast<GLint>(value.v[3]);
7225 GetVertexAttribHelper(attrib, pname, params);
7230 bool GLES2DecoderImpl::SetVertexAttribValue(
7231 const char* function_name, GLuint index, const GLfloat* value) {
7232 if (index >= state_.attrib_values.size()) {
7233 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "index out of range");
7236 Vec4& v = state_.attrib_values[index];
7244 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
7245 GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
7246 if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
7247 glVertexAttrib1f(index, v0);
7251 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
7252 GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
7253 if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
7254 glVertexAttrib2f(index, v0, v1);
7258 void GLES2DecoderImpl::DoVertexAttrib3f(
7259 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
7260 GLfloat v[4] = { v0, v1, v2, 1.0f, };
7261 if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
7262 glVertexAttrib3f(index, v0, v1, v2);
7266 void GLES2DecoderImpl::DoVertexAttrib4f(
7267 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
7268 GLfloat v[4] = { v0, v1, v2, v3, };
7269 if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
7270 glVertexAttrib4f(index, v0, v1, v2, v3);
7274 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
7275 GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
7276 if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
7277 glVertexAttrib1fv(index, v);
7281 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
7282 GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
7283 if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
7284 glVertexAttrib2fv(index, v);
7288 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
7289 GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
7290 if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
7291 glVertexAttrib3fv(index, v);
7295 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
7296 if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
7297 glVertexAttrib4fv(index, v);
7301 error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
7302 uint32 immediate_data_size,
7303 const void* cmd_data) {
7304 const gles2::cmds::VertexAttribPointer& c =
7305 *static_cast<const gles2::cmds::VertexAttribPointer*>(cmd_data);
7307 if (!state_.bound_array_buffer.get() ||
7308 state_.bound_array_buffer->IsDeleted()) {
7309 if (state_.vertex_attrib_manager.get() ==
7310 state_.default_vertex_attrib_manager.get()) {
7312 GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
7313 return error::kNoError;
7314 } else if (c.offset != 0) {
7317 "glVertexAttribPointer", "client side arrays are not allowed");
7318 return error::kNoError;
7322 GLuint indx = c.indx;
7323 GLint size = c.size;
7324 GLenum type = c.type;
7325 GLboolean normalized = c.normalized;
7326 GLsizei stride = c.stride;
7327 GLsizei offset = c.offset;
7328 const void* ptr = reinterpret_cast<const void*>(offset);
7329 if (!validators_->vertex_attrib_type.IsValid(type)) {
7330 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type, "type");
7331 return error::kNoError;
7333 if (!validators_->vertex_attrib_size.IsValid(size)) {
7335 GL_INVALID_VALUE, "glVertexAttribPointer", "size GL_INVALID_VALUE");
7336 return error::kNoError;
7338 if (indx >= group_->max_vertex_attribs()) {
7340 GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
7341 return error::kNoError;
7345 GL_INVALID_VALUE, "glVertexAttribPointer", "stride < 0");
7346 return error::kNoError;
7350 GL_INVALID_VALUE, "glVertexAttribPointer", "stride > 255");
7351 return error::kNoError;
7355 GL_INVALID_VALUE, "glVertexAttribPointer", "offset < 0");
7356 return error::kNoError;
7358 GLsizei component_size =
7359 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
7360 // component_size must be a power of two to use & as optimized modulo.
7361 DCHECK(GLES2Util::IsPOT(component_size));
7362 if (offset & (component_size - 1)) {
7364 GL_INVALID_OPERATION,
7365 "glVertexAttribPointer", "offset not valid for type");
7366 return error::kNoError;
7368 if (stride & (component_size - 1)) {
7370 GL_INVALID_OPERATION,
7371 "glVertexAttribPointer", "stride not valid for type");
7372 return error::kNoError;
7374 state_.vertex_attrib_manager
7375 ->SetAttribInfo(indx,
7376 state_.bound_array_buffer.get(),
7381 stride != 0 ? stride : component_size * size,
7383 if (type != GL_FIXED) {
7384 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
7386 return error::kNoError;
7389 void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
7391 state_.viewport_x = x;
7392 state_.viewport_y = y;
7393 state_.viewport_width = std::min(width, viewport_max_width_);
7394 state_.viewport_height = std::min(height, viewport_max_height_);
7395 glViewport(x, y, width, height);
7398 error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
7399 uint32 immediate_data_size,
7400 const void* cmd_data) {
7401 const gles2::cmds::VertexAttribDivisorANGLE& c =
7402 *static_cast<const gles2::cmds::VertexAttribDivisorANGLE*>(cmd_data);
7403 if (!features().angle_instanced_arrays) {
7405 GL_INVALID_OPERATION,
7406 "glVertexAttribDivisorANGLE", "function not available");
7407 return error::kNoError;
7409 GLuint index = c.index;
7410 GLuint divisor = c.divisor;
7411 if (index >= group_->max_vertex_attribs()) {
7414 "glVertexAttribDivisorANGLE", "index out of range");
7415 return error::kNoError;
7418 state_.vertex_attrib_manager->SetDivisor(
7421 glVertexAttribDivisorANGLE(index, divisor);
7422 return error::kNoError;
7425 template <typename pixel_data_type>
7426 static void WriteAlphaData(
7427 void *pixels, uint32 row_count, uint32 channel_count,
7428 uint32 alpha_channel_index, uint32 unpadded_row_size,
7429 uint32 padded_row_size, pixel_data_type alpha_value) {
7430 DCHECK_GT(channel_count, 0U);
7431 DCHECK_EQ(unpadded_row_size % sizeof(pixel_data_type), 0U);
7432 uint32 unpadded_row_size_in_elements =
7433 unpadded_row_size / sizeof(pixel_data_type);
7434 DCHECK_EQ(padded_row_size % sizeof(pixel_data_type), 0U);
7435 uint32 padded_row_size_in_elements =
7436 padded_row_size / sizeof(pixel_data_type);
7437 pixel_data_type* dst =
7438 static_cast<pixel_data_type*>(pixels) + alpha_channel_index;
7439 for (uint32 yy = 0; yy < row_count; ++yy) {
7440 pixel_data_type* end = dst + unpadded_row_size_in_elements;
7441 for (pixel_data_type* d = dst; d < end; d += channel_count) {
7444 dst += padded_row_size_in_elements;
7448 void GLES2DecoderImpl::FinishReadPixels(
7449 const cmds::ReadPixels& c,
7451 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
7452 GLsizei width = c.width;
7453 GLsizei height = c.height;
7454 GLenum format = c.format;
7455 GLenum type = c.type;
7456 typedef cmds::ReadPixels::Result Result;
7458 Result* result = NULL;
7459 if (c.result_shm_id != 0) {
7460 result = GetSharedMemoryAs<Result*>(
7461 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7464 glDeleteBuffersARB(1, &buffer);
7469 GLES2Util::ComputeImageDataSizes(
7470 width, height, format, type, state_.pack_alignment, &pixels_size,
7472 void* pixels = GetSharedMemoryAs<void*>(
7473 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
7476 glDeleteBuffersARB(1, &buffer);
7482 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
7484 if (features().map_buffer_range) {
7485 data = glMapBufferRange(
7486 GL_PIXEL_PACK_BUFFER_ARB, 0, pixels_size, GL_MAP_READ_BIT);
7488 data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
7490 memcpy(pixels, data, pixels_size);
7491 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
7492 // have to restore the state.
7493 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
7494 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7495 glDeleteBuffersARB(1, &buffer);
7498 if (result != NULL) {
7502 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
7503 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
7504 if ((channels_exist & 0x0008) == 0 &&
7505 workarounds().clear_alpha_in_readpixels) {
7506 // Set the alpha to 255 because some drivers are buggy in this regard.
7509 uint32 unpadded_row_size;
7510 uint32 padded_row_size;
7511 if (!GLES2Util::ComputeImageDataSizes(
7512 width, 2, format, type, state_.pack_alignment, &temp_size,
7513 &unpadded_row_size, &padded_row_size)) {
7517 uint32 channel_count = 0;
7518 uint32 alpha_channel = 0;
7531 if (channel_count > 0) {
7533 case GL_UNSIGNED_BYTE:
7534 WriteAlphaData<uint8>(
7535 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7536 padded_row_size, 0xFF);
7539 WriteAlphaData<float>(
7540 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7541 padded_row_size, 1.0f);
7544 WriteAlphaData<uint16>(
7545 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7546 padded_row_size, 0x3C00);
7553 error::Error GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size,
7554 const void* cmd_data) {
7555 const gles2::cmds::ReadPixels& c =
7556 *static_cast<const gles2::cmds::ReadPixels*>(cmd_data);
7557 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
7558 error::Error fbo_error = WillAccessBoundFramebufferForRead();
7559 if (fbo_error != error::kNoError)
7563 GLsizei width = c.width;
7564 GLsizei height = c.height;
7565 GLenum format = c.format;
7566 GLenum type = c.type;
7567 GLboolean async = c.async;
7568 if (width < 0 || height < 0) {
7569 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
7570 return error::kNoError;
7572 typedef cmds::ReadPixels::Result Result;
7574 if (!GLES2Util::ComputeImageDataSizes(
7575 width, height, format, type, state_.pack_alignment, &pixels_size,
7577 return error::kOutOfBounds;
7579 void* pixels = GetSharedMemoryAs<void*>(
7580 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
7582 return error::kOutOfBounds;
7584 Result* result = NULL;
7585 if (c.result_shm_id != 0) {
7586 result = GetSharedMemoryAs<Result*>(
7587 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7589 return error::kOutOfBounds;
7593 if (!validators_->read_pixel_format.IsValid(format)) {
7594 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format, "format");
7595 return error::kNoError;
7597 if (!validators_->read_pixel_type.IsValid(type)) {
7598 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type");
7599 return error::kNoError;
7601 if ((format != GL_RGBA && format != GL_BGRA_EXT && format != GL_RGB &&
7602 format != GL_ALPHA) || type != GL_UNSIGNED_BYTE) {
7603 // format and type are acceptable enums but not guaranteed to be supported
7604 // for this framebuffer. Have to ask gl if they are valid.
7605 GLint preferred_format = 0;
7606 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &preferred_format);
7607 GLint preferred_type = 0;
7608 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &preferred_type);
7609 if (format != static_cast<GLenum>(preferred_format) ||
7610 type != static_cast<GLenum>(preferred_type)) {
7612 GL_INVALID_OPERATION, "glReadPixels", "format and type incompatible "
7613 "with the current read framebuffer");
7614 return error::kNoError;
7617 if (width == 0 || height == 0) {
7618 return error::kNoError;
7621 // Get the size of the current fbo or backbuffer.
7622 gfx::Size max_size = GetBoundReadFrameBufferSize();
7626 if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y)) {
7628 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7629 return error::kNoError;
7632 if (!CheckBoundReadFramebufferColorAttachment("glReadPixels")) {
7633 return error::kNoError;
7636 if (!CheckBoundFramebuffersValid("glReadPixels")) {
7637 return error::kNoError;
7640 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
7642 ScopedResolvedFrameBufferBinder binder(this, false, true);
7644 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
7645 // The user requested an out of range area. Get the results 1 line
7648 uint32 unpadded_row_size;
7649 uint32 padded_row_size;
7650 if (!GLES2Util::ComputeImageDataSizes(
7651 width, 2, format, type, state_.pack_alignment, &temp_size,
7652 &unpadded_row_size, &padded_row_size)) {
7654 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7655 return error::kNoError;
7658 GLint dest_x_offset = std::max(-x, 0);
7659 uint32 dest_row_offset;
7660 if (!GLES2Util::ComputeImageDataSizes(
7661 dest_x_offset, 1, format, type, state_.pack_alignment, &dest_row_offset,
7664 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7665 return error::kNoError;
7668 // Copy each row into the larger dest rect.
7669 int8* dst = static_cast<int8*>(pixels);
7670 GLint read_x = std::max(0, x);
7671 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
7672 GLint read_width = read_end_x - read_x;
7673 for (GLint yy = 0; yy < height; ++yy) {
7677 memset(dst, 0, unpadded_row_size);
7679 // If the row is in range, copy it.
7680 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
7682 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
7684 dst += padded_row_size;
7687 if (async && features().use_async_readpixels) {
7689 glGenBuffersARB(1, &buffer);
7690 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
7691 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, GL_STREAM_READ);
7692 GLenum error = glGetError();
7693 if (error == GL_NO_ERROR) {
7694 glReadPixels(x, y, width, height, format, type, 0);
7695 pending_readpixel_fences_.push(linked_ptr<FenceCallback>(
7696 new FenceCallback()));
7697 WaitForReadPixels(base::Bind(
7698 &GLES2DecoderImpl::FinishReadPixels,
7699 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
7700 <GLES2DecoderImpl>(this),
7702 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7703 return error::kNoError;
7705 // On error, unbind pack buffer and fall through to sync readpixels
7706 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7709 glReadPixels(x, y, width, height, format, type, pixels);
7711 GLenum error = LOCAL_PEEK_GL_ERROR("glReadPixels");
7712 if (error == GL_NO_ERROR) {
7713 if (result != NULL) {
7716 FinishReadPixels(c, 0);
7719 return error::kNoError;
7722 error::Error GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size,
7723 const void* cmd_data) {
7724 const gles2::cmds::PixelStorei& c =
7725 *static_cast<const gles2::cmds::PixelStorei*>(cmd_data);
7726 GLenum pname = c.pname;
7727 GLenum param = c.param;
7728 if (!validators_->pixel_store.IsValid(pname)) {
7729 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname, "pname");
7730 return error::kNoError;
7733 case GL_PACK_ALIGNMENT:
7734 case GL_UNPACK_ALIGNMENT:
7735 if (!validators_->pixel_store_alignment.IsValid(param)) {
7737 GL_INVALID_VALUE, "glPixelStorei", "param GL_INVALID_VALUE");
7738 return error::kNoError;
7741 case GL_UNPACK_FLIP_Y_CHROMIUM:
7742 unpack_flip_y_ = (param != 0);
7743 return error::kNoError;
7744 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
7745 unpack_premultiply_alpha_ = (param != 0);
7746 return error::kNoError;
7747 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
7748 unpack_unpremultiply_alpha_ = (param != 0);
7749 return error::kNoError;
7753 glPixelStorei(pname, param);
7755 case GL_PACK_ALIGNMENT:
7756 state_.pack_alignment = param;
7758 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
7759 state_.pack_reverse_row_order = (param != 0);
7761 case GL_UNPACK_ALIGNMENT:
7762 state_.unpack_alignment = param;
7765 // Validation should have prevented us from getting here.
7769 return error::kNoError;
7772 error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
7773 uint32 immediate_data_size,
7774 const void* cmd_data) {
7775 const gles2::cmds::PostSubBufferCHROMIUM& c =
7776 *static_cast<const gles2::cmds::PostSubBufferCHROMIUM*>(cmd_data);
7777 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
7779 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
7781 if (!supports_post_sub_buffer_) {
7783 GL_INVALID_OPERATION,
7784 "glPostSubBufferCHROMIUM", "command not supported by surface");
7785 return error::kNoError;
7788 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
7791 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
7792 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
7793 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
7794 is_offscreen ? offscreen_size_ : surface_->GetSize());
7796 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height)) {
7797 return error::kNoError;
7799 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
7800 return error::kLostContext;
7804 error::Error GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
7805 uint32 immediate_data_size,
7806 const void* cmd_data) {
7807 const gles2::cmds::ScheduleOverlayPlaneCHROMIUM& c =
7808 *static_cast<const gles2::cmds::ScheduleOverlayPlaneCHROMIUM*>(cmd_data);
7809 TextureRef* ref = texture_manager()->GetTexture(c.overlay_texture_id);
7811 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
7812 "glScheduleOverlayPlaneCHROMIUM",
7814 return error::kNoError;
7816 gfx::GLImage* image =
7817 ref->texture()->GetLevelImage(ref->texture()->target(), 0);
7819 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
7820 "glScheduleOverlayPlaneCHROMIUM",
7821 "unsupported texture format");
7822 return error::kNoError;
7824 gfx::OverlayTransform transform = GetGFXOverlayTransform(c.plane_transform);
7825 if (transform == gfx::OVERLAY_TRANSFORM_INVALID) {
7826 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM,
7827 "glScheduleOverlayPlaneCHROMIUM",
7828 "invalid transform enum");
7829 return error::kNoError;
7831 if (!surface_->ScheduleOverlayPlane(
7835 gfx::Rect(c.bounds_x, c.bounds_y, c.bounds_width, c.bounds_height),
7836 gfx::RectF(c.uv_x, c.uv_y, c.uv_width, c.uv_height))) {
7837 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
7838 "glScheduleOverlayPlaneCHROMIUM",
7839 "failed to schedule overlay");
7841 return error::kNoError;
7844 error::Error GLES2DecoderImpl::GetAttribLocationHelper(
7845 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7846 const std::string& name_str) {
7847 if (!StringIsValidForGLES(name_str.c_str())) {
7849 GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
7850 return error::kNoError;
7852 Program* program = GetProgramInfoNotShader(
7853 client_id, "glGetAttribLocation");
7855 return error::kNoError;
7857 if (!program->IsValid()) {
7859 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
7860 return error::kNoError;
7862 GLint* location = GetSharedMemoryAs<GLint*>(
7863 location_shm_id, location_shm_offset, sizeof(GLint));
7865 return error::kOutOfBounds;
7867 // Require the client to init this incase the context is lost and we are no
7868 // longer executing commands.
7869 if (*location != -1) {
7870 return error::kGenericError;
7872 *location = program->GetAttribLocation(name_str);
7873 return error::kNoError;
7876 error::Error GLES2DecoderImpl::HandleGetAttribLocation(
7877 uint32 immediate_data_size,
7878 const void* cmd_data) {
7879 const gles2::cmds::GetAttribLocation& c =
7880 *static_cast<const gles2::cmds::GetAttribLocation*>(cmd_data);
7881 Bucket* bucket = GetBucket(c.name_bucket_id);
7883 return error::kInvalidArguments;
7885 std::string name_str;
7886 if (!bucket->GetAsString(&name_str)) {
7887 return error::kInvalidArguments;
7889 return GetAttribLocationHelper(
7890 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7893 error::Error GLES2DecoderImpl::GetUniformLocationHelper(
7894 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7895 const std::string& name_str) {
7896 if (!StringIsValidForGLES(name_str.c_str())) {
7898 GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
7899 return error::kNoError;
7901 Program* program = GetProgramInfoNotShader(
7902 client_id, "glGetUniformLocation");
7904 return error::kNoError;
7906 if (!program->IsValid()) {
7908 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
7909 return error::kNoError;
7911 GLint* location = GetSharedMemoryAs<GLint*>(
7912 location_shm_id, location_shm_offset, sizeof(GLint));
7914 return error::kOutOfBounds;
7916 // Require the client to init this incase the context is lost an we are no
7917 // longer executing commands.
7918 if (*location != -1) {
7919 return error::kGenericError;
7921 *location = program->GetUniformFakeLocation(name_str);
7922 return error::kNoError;
7925 error::Error GLES2DecoderImpl::HandleGetUniformLocation(
7926 uint32 immediate_data_size,
7927 const void* cmd_data) {
7928 const gles2::cmds::GetUniformLocation& c =
7929 *static_cast<const gles2::cmds::GetUniformLocation*>(cmd_data);
7930 Bucket* bucket = GetBucket(c.name_bucket_id);
7932 return error::kInvalidArguments;
7934 std::string name_str;
7935 if (!bucket->GetAsString(&name_str)) {
7936 return error::kInvalidArguments;
7938 return GetUniformLocationHelper(
7939 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7942 error::Error GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size,
7943 const void* cmd_data) {
7944 const gles2::cmds::GetString& c =
7945 *static_cast<const gles2::cmds::GetString*>(cmd_data);
7946 GLenum name = static_cast<GLenum>(c.name);
7947 if (!validators_->string_type.IsValid(name)) {
7948 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name");
7949 return error::kNoError;
7951 const char* str = reinterpret_cast<const char*>(glGetString(name));
7952 std::string extensions;
7955 str = "OpenGL ES 2.0 Chromium";
7957 case GL_SHADING_LANGUAGE_VERSION:
7958 str = "OpenGL ES GLSL ES 1.0 Chromium";
7962 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
7963 // They are used by WEBGL_debug_renderer_info.
7964 if (!force_webgl_glsl_validation_)
7969 // For WebGL contexts, strip out the OES derivatives and
7970 // EXT frag depth extensions if they have not been enabled.
7971 if (force_webgl_glsl_validation_) {
7972 extensions = feature_info_->extensions();
7973 if (!derivatives_explicitly_enabled_) {
7974 size_t offset = extensions.find(kOESDerivativeExtension);
7975 if (std::string::npos != offset) {
7976 extensions.replace(offset, arraysize(kOESDerivativeExtension),
7980 if (!frag_depth_explicitly_enabled_) {
7981 size_t offset = extensions.find(kEXTFragDepthExtension);
7982 if (std::string::npos != offset) {
7983 extensions.replace(offset, arraysize(kEXTFragDepthExtension),
7987 if (!draw_buffers_explicitly_enabled_) {
7988 size_t offset = extensions.find(kEXTDrawBuffersExtension);
7989 if (std::string::npos != offset) {
7990 extensions.replace(offset, arraysize(kEXTDrawBuffersExtension),
7994 if (!shader_texture_lod_explicitly_enabled_) {
7995 size_t offset = extensions.find(kEXTShaderTextureLodExtension);
7996 if (std::string::npos != offset) {
7997 extensions.replace(offset,
7998 arraysize(kEXTShaderTextureLodExtension),
8003 extensions = feature_info_->extensions().c_str();
8005 if (supports_post_sub_buffer_)
8006 extensions += " GL_CHROMIUM_post_sub_buffer";
8007 str = extensions.c_str();
8013 Bucket* bucket = CreateBucket(c.bucket_id);
8014 bucket->SetFromString(str);
8015 return error::kNoError;
8018 error::Error GLES2DecoderImpl::HandleBufferData(uint32 immediate_data_size,
8019 const void* cmd_data) {
8020 const gles2::cmds::BufferData& c =
8021 *static_cast<const gles2::cmds::BufferData*>(cmd_data);
8022 GLenum target = static_cast<GLenum>(c.target);
8023 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
8024 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
8025 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
8026 GLenum usage = static_cast<GLenum>(c.usage);
8027 const void* data = NULL;
8028 if (data_shm_id != 0 || data_shm_offset != 0) {
8029 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
8031 return error::kOutOfBounds;
8034 buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
8035 return error::kNoError;
8038 void GLES2DecoderImpl::DoBufferSubData(
8039 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
8040 // Just delegate it. Some validation is actually done before this.
8041 buffer_manager()->ValidateAndDoBufferSubData(
8042 &state_, target, offset, size, data);
8045 bool GLES2DecoderImpl::ClearLevel(
8046 unsigned service_id,
8047 unsigned bind_target,
8050 unsigned internal_format,
8055 bool is_texture_immutable) {
8056 uint32 channels = GLES2Util::GetChannelsForFormat(format);
8057 if (feature_info_->feature_flags().angle_depth_texture &&
8058 (channels & GLES2Util::kDepth) != 0) {
8059 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
8060 // on depth formats.
8062 glGenFramebuffersEXT(1, &fb);
8063 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
8065 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
8066 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
8067 GL_DEPTH_ATTACHMENT;
8069 glFramebufferTexture2DEXT(
8070 GL_DRAW_FRAMEBUFFER_EXT, attachment, target, service_id, level);
8071 // ANGLE promises a depth only attachment ok.
8072 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
8073 GL_FRAMEBUFFER_COMPLETE) {
8077 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
8078 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
8080 state_.SetDeviceDepthMask(GL_TRUE);
8081 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
8082 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
8084 RestoreClearState();
8086 glDeleteFramebuffersEXT(1, &fb);
8087 Framebuffer* framebuffer =
8088 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
8089 GLuint fb_service_id =
8090 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
8091 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
8095 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
8098 uint32 padded_row_size;
8099 if (!GLES2Util::ComputeImageDataSizes(
8100 width, height, format, type, state_.unpack_alignment, &size,
8101 NULL, &padded_row_size)) {
8105 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
8109 if (size > kMaxZeroSize) {
8110 if (kMaxZeroSize < padded_row_size) {
8111 // That'd be an awfully large texture.
8114 // We should never have a large total size with a zero row size.
8115 DCHECK_GT(padded_row_size, 0U);
8116 tile_height = kMaxZeroSize / padded_row_size;
8117 if (!GLES2Util::ComputeImageDataSizes(
8118 width, tile_height, format, type, state_.unpack_alignment, &size,
8123 tile_height = height;
8126 // Assumes the size has already been checked.
8127 scoped_ptr<char[]> zero(new char[size]);
8128 memset(zero.get(), 0, size);
8129 glBindTexture(bind_target, service_id);
8132 while (y < height) {
8133 GLint h = y + tile_height > height ? height - y : tile_height;
8134 if (is_texture_immutable || h != height) {
8135 glTexSubImage2D(target, level, 0, y, width, h, format, type, zero.get());
8138 target, level, internal_format, width, h, 0, format, type,
8143 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
8144 &state_, bind_target);
8145 glBindTexture(bind_target, texture ? texture->service_id() : 0);
8151 const int kS3TCBlockWidth = 4;
8152 const int kS3TCBlockHeight = 4;
8153 const int kS3TCDXT1BlockSize = 8;
8154 const int kS3TCDXT3AndDXT5BlockSize = 16;
8156 bool IsValidDXTSize(GLint level, GLsizei size) {
8157 return (size == 1) ||
8158 (size == 2) || !(size % kS3TCBlockWidth);
8161 bool IsValidPVRTCSize(GLint level, GLsizei size) {
8162 return GLES2Util::IsPOT(size);
8165 } // anonymous namespace.
8167 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
8168 const char* function_name,
8169 GLsizei width, GLsizei height, GLenum format, size_t size) {
8170 unsigned int bytes_required = 0;
8173 case GL_ATC_RGB_AMD:
8174 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
8175 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
8176 case GL_ETC1_RGB8_OES: {
8177 int num_blocks_across =
8178 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
8179 int num_blocks_down =
8180 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
8181 int num_blocks = num_blocks_across * num_blocks_down;
8182 bytes_required = num_blocks * kS3TCDXT1BlockSize;
8185 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
8186 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
8187 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
8188 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
8189 int num_blocks_across =
8190 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
8191 int num_blocks_down =
8192 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
8193 int num_blocks = num_blocks_across * num_blocks_down;
8194 bytes_required = num_blocks * kS3TCDXT3AndDXT5BlockSize;
8197 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
8198 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: {
8199 bytes_required = (std::max(width, 8) * std::max(height, 8) * 4 + 7)/8;
8202 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
8203 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
8204 bytes_required = (std::max(width, 16) * std::max(height, 8) * 2 + 7)/8;
8208 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
8212 if (size != bytes_required) {
8214 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
8221 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
8222 const char* function_name,
8223 GLint level, GLsizei width, GLsizei height, GLenum format) {
8225 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
8226 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
8227 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
8228 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
8229 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
8231 GL_INVALID_OPERATION, function_name,
8232 "width or height invalid for level");
8237 case GL_ATC_RGB_AMD:
8238 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
8239 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
8240 case GL_ETC1_RGB8_OES: {
8241 if (width <= 0 || height <= 0) {
8243 GL_INVALID_OPERATION, function_name,
8244 "width or height invalid for level");
8249 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
8250 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
8251 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
8252 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
8253 if (!IsValidPVRTCSize(level, width) ||
8254 !IsValidPVRTCSize(level, height)) {
8256 GL_INVALID_OPERATION, function_name,
8257 "width or height invalid for level");
8267 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
8268 const char* function_name,
8269 GLenum target, GLint level, GLint xoffset, GLint yoffset,
8270 GLsizei width, GLsizei height, GLenum format,
8272 if (xoffset < 0 || yoffset < 0) {
8274 GL_INVALID_VALUE, function_name, "xoffset or yoffset < 0");
8279 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
8280 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
8281 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
8282 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
8283 const int kBlockWidth = 4;
8284 const int kBlockHeight = 4;
8285 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
8287 GL_INVALID_OPERATION, function_name,
8288 "xoffset or yoffset not multiple of 4");
8291 GLsizei tex_width = 0;
8292 GLsizei tex_height = 0;
8293 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
8294 width - xoffset > tex_width ||
8295 height - yoffset > tex_height) {
8297 GL_INVALID_OPERATION, function_name, "dimensions out of range");
8300 return ValidateCompressedTexDimensions(
8301 function_name, level, width, height, format);
8303 case GL_ATC_RGB_AMD:
8304 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
8305 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: {
8307 GL_INVALID_OPERATION, function_name,
8308 "not supported for ATC textures");
8311 case GL_ETC1_RGB8_OES: {
8313 GL_INVALID_OPERATION, function_name,
8314 "not supported for ECT1_RGB8_OES textures");
8317 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
8318 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
8319 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
8320 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
8321 if ((xoffset != 0) || (yoffset != 0)) {
8323 GL_INVALID_OPERATION, function_name,
8324 "xoffset and yoffset must be zero");
8327 GLsizei tex_width = 0;
8328 GLsizei tex_height = 0;
8329 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
8330 width != tex_width ||
8331 height != tex_height) {
8333 GL_INVALID_OPERATION, function_name,
8334 "dimensions must match existing texture level dimensions");
8337 return ValidateCompressedTexDimensions(
8338 function_name, level, width, height, format);
8345 error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
8348 GLenum internal_format,
8354 // TODO(gman): Validate image_size is correct for width, height and format.
8355 if (!validators_->texture_target.IsValid(target)) {
8356 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8357 "glCompressedTexImage2D", target, "target");
8358 return error::kNoError;
8360 if (!validators_->compressed_texture_format.IsValid(
8362 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8363 "glCompressedTexImage2D", internal_format, "internal_format");
8364 return error::kNoError;
8366 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
8370 "glCompressedTexImage2D", "dimensions out of range");
8371 return error::kNoError;
8373 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8378 "glCompressedTexImage2D", "unknown texture target");
8379 return error::kNoError;
8381 Texture* texture = texture_ref->texture();
8382 if (texture->IsImmutable()) {
8384 GL_INVALID_OPERATION,
8385 "glCompressedTexImage2D", "texture is immutable");
8386 return error::kNoError;
8389 if (!ValidateCompressedTexDimensions(
8390 "glCompressedTexImage2D", level, width, height, internal_format) ||
8391 !ValidateCompressedTexFuncData(
8392 "glCompressedTexImage2D", width, height, internal_format, image_size)) {
8393 return error::kNoError;
8396 if (!EnsureGPUMemoryAvailable(image_size)) {
8398 GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory");
8399 return error::kNoError;
8402 if (texture->IsAttachedToFramebuffer()) {
8403 framebuffer_state_.clear_state_dirty = true;
8406 scoped_ptr<int8[]> zero;
8408 zero.reset(new int8[image_size]);
8409 memset(zero.get(), 0, image_size);
8412 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
8413 glCompressedTexImage2D(
8414 target, level, internal_format, width, height, border, image_size, data);
8415 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
8416 if (error == GL_NO_ERROR) {
8417 texture_manager()->SetLevelInfo(
8418 texture_ref, target, level, internal_format,
8419 width, height, 1, border, 0, 0, true);
8422 // This may be a slow command. Exit command processing to allow for
8423 // context preemption and GPU watchdog checks.
8424 ExitCommandProcessingEarly();
8425 return error::kNoError;
8428 error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
8429 uint32 immediate_data_size,
8430 const void* cmd_data) {
8431 const gles2::cmds::CompressedTexImage2D& c =
8432 *static_cast<const gles2::cmds::CompressedTexImage2D*>(cmd_data);
8433 GLenum target = static_cast<GLenum>(c.target);
8434 GLint level = static_cast<GLint>(c.level);
8435 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8436 GLsizei width = static_cast<GLsizei>(c.width);
8437 GLsizei height = static_cast<GLsizei>(c.height);
8438 GLint border = static_cast<GLint>(c.border);
8439 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
8440 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
8441 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
8442 const void* data = NULL;
8443 if (data_shm_id != 0 || data_shm_offset != 0) {
8444 data = GetSharedMemoryAs<const void*>(
8445 data_shm_id, data_shm_offset, image_size);
8447 return error::kOutOfBounds;
8450 return DoCompressedTexImage2D(
8451 target, level, internal_format, width, height, border, image_size, data);
8454 error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
8455 uint32 immediate_data_size,
8456 const void* cmd_data) {
8457 const gles2::cmds::CompressedTexImage2DBucket& c =
8458 *static_cast<const gles2::cmds::CompressedTexImage2DBucket*>(cmd_data);
8459 GLenum target = static_cast<GLenum>(c.target);
8460 GLint level = static_cast<GLint>(c.level);
8461 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8462 GLsizei width = static_cast<GLsizei>(c.width);
8463 GLsizei height = static_cast<GLsizei>(c.height);
8464 GLint border = static_cast<GLint>(c.border);
8465 Bucket* bucket = GetBucket(c.bucket_id);
8467 return error::kInvalidArguments;
8469 uint32 data_size = bucket->size();
8470 GLsizei imageSize = data_size;
8471 const void* data = bucket->GetData(0, data_size);
8473 return error::kInvalidArguments;
8475 return DoCompressedTexImage2D(
8476 target, level, internal_format, width, height, border,
8480 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
8481 uint32 immediate_data_size,
8482 const void* cmd_data) {
8483 const gles2::cmds::CompressedTexSubImage2DBucket& c =
8484 *static_cast<const gles2::cmds::CompressedTexSubImage2DBucket*>(cmd_data);
8485 GLenum target = static_cast<GLenum>(c.target);
8486 GLint level = static_cast<GLint>(c.level);
8487 GLint xoffset = static_cast<GLint>(c.xoffset);
8488 GLint yoffset = static_cast<GLint>(c.yoffset);
8489 GLsizei width = static_cast<GLsizei>(c.width);
8490 GLsizei height = static_cast<GLsizei>(c.height);
8491 GLenum format = static_cast<GLenum>(c.format);
8492 Bucket* bucket = GetBucket(c.bucket_id);
8494 return error::kInvalidArguments;
8496 uint32 data_size = bucket->size();
8497 GLsizei imageSize = data_size;
8498 const void* data = bucket->GetData(0, data_size);
8500 return error::kInvalidArguments;
8502 if (!validators_->texture_target.IsValid(target)) {
8504 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
8505 return error::kNoError;
8507 if (!validators_->compressed_texture_format.IsValid(format)) {
8508 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8509 "glCompressedTexSubImage2D", format, "format");
8510 return error::kNoError;
8514 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
8515 return error::kNoError;
8519 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
8520 return error::kNoError;
8522 if (imageSize < 0) {
8524 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
8525 return error::kNoError;
8527 DoCompressedTexSubImage2D(
8528 target, level, xoffset, yoffset, width, height, format, imageSize, data);
8529 return error::kNoError;
8532 error::Error GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size,
8533 const void* cmd_data) {
8534 const gles2::cmds::TexImage2D& c =
8535 *static_cast<const gles2::cmds::TexImage2D*>(cmd_data);
8536 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
8537 "width", c.width, "height", c.height);
8538 // Set as failed for now, but if it successed, this will be set to not failed.
8539 texture_state_.tex_image_2d_failed = true;
8540 GLenum target = static_cast<GLenum>(c.target);
8541 GLint level = static_cast<GLint>(c.level);
8542 // TODO(kloveless): Change TexImage2D command to use unsigned integer
8543 // for internalformat.
8544 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8545 GLsizei width = static_cast<GLsizei>(c.width);
8546 GLsizei height = static_cast<GLsizei>(c.height);
8547 GLint border = static_cast<GLint>(c.border);
8548 GLenum format = static_cast<GLenum>(c.format);
8549 GLenum type = static_cast<GLenum>(c.type);
8550 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
8551 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
8553 if (!GLES2Util::ComputeImageDataSizes(
8554 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
8556 return error::kOutOfBounds;
8558 const void* pixels = NULL;
8559 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
8560 pixels = GetSharedMemoryAs<const void*>(
8561 pixels_shm_id, pixels_shm_offset, pixels_size);
8563 return error::kOutOfBounds;
8567 TextureManager::DoTextImage2DArguments args = {
8568 target, level, internal_format, width, height, border, format, type,
8569 pixels, pixels_size};
8570 texture_manager()->ValidateAndDoTexImage2D(
8571 &texture_state_, &state_, &framebuffer_state_, args);
8573 // This may be a slow command. Exit command processing to allow for
8574 // context preemption and GPU watchdog checks.
8575 ExitCommandProcessingEarly();
8576 return error::kNoError;
8579 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
8588 const void * data) {
8589 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8593 GL_INVALID_OPERATION,
8594 "glCompressedTexSubImage2D", "unknown texture for target");
8597 Texture* texture = texture_ref->texture();
8599 GLenum internal_format = 0;
8600 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
8602 GL_INVALID_OPERATION,
8603 "glCompressedTexSubImage2D", "level does not exist.");
8606 if (internal_format != format) {
8608 GL_INVALID_OPERATION,
8609 "glCompressedTexSubImage2D", "format does not match internal format.");
8612 if (!texture->ValidForTexture(
8613 target, level, xoffset, yoffset, width, height, type)) {
8615 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
8619 if (!ValidateCompressedTexFuncData(
8620 "glCompressedTexSubImage2D", width, height, format, image_size) ||
8621 !ValidateCompressedTexSubDimensions(
8622 "glCompressedTexSubImage2D",
8623 target, level, xoffset, yoffset, width, height, format, texture)) {
8628 // Note: There is no need to deal with texture cleared tracking here
8629 // because the validation above means you can only get here if the level
8630 // is already a matching compressed format and in that case
8631 // CompressedTexImage2D already cleared the texture.
8632 glCompressedTexSubImage2D(
8633 target, level, xoffset, yoffset, width, height, format, image_size, data);
8635 // This may be a slow command. Exit command processing to allow for
8636 // context preemption and GPU watchdog checks.
8637 ExitCommandProcessingEarly();
8641 GLint start, GLint range, GLint sourceRange,
8642 GLint* out_start, GLint* out_range) {
8649 GLint end = start + range;
8650 if (end > sourceRange) {
8651 range -= end - sourceRange;
8657 void GLES2DecoderImpl::DoCopyTexImage2D(
8660 GLenum internal_format,
8666 DCHECK(!ShouldDeferReads());
8667 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8671 GL_INVALID_OPERATION,
8672 "glCopyTexImage2D", "unknown texture for target");
8675 Texture* texture = texture_ref->texture();
8676 if (texture->IsImmutable()) {
8678 GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
8681 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
8684 GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
8687 if (!texture_manager()->ValidateFormatAndTypeCombination(
8688 state_.GetErrorState(), "glCopyTexImage2D", internal_format,
8689 GL_UNSIGNED_BYTE)) {
8693 // Check we have compatible formats.
8694 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8695 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8696 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
8698 if ((channels_needed & channels_exist) != channels_needed) {
8700 GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
8704 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8706 GL_INVALID_OPERATION,
8707 "glCopyTexImage2D", "can not be used with depth or stencil textures");
8711 uint32 estimated_size = 0;
8712 if (!GLES2Util::ComputeImageDataSizes(
8713 width, height, internal_format, GL_UNSIGNED_BYTE, state_.unpack_alignment,
8714 &estimated_size, NULL, NULL)) {
8716 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large");
8720 if (!EnsureGPUMemoryAvailable(estimated_size)) {
8721 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory");
8725 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexImage2D")) {
8729 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
8733 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
8734 ScopedResolvedFrameBufferBinder binder(this, false, true);
8735 gfx::Size size = GetBoundReadFrameBufferSize();
8737 if (texture->IsAttachedToFramebuffer()) {
8738 framebuffer_state_.clear_state_dirty = true;
8741 // Clip to size to source dimensions
8744 GLint copyWidth = 0;
8745 GLint copyHeight = 0;
8746 Clip(x, width, size.width(), ©X, ©Width);
8747 Clip(y, height, size.height(), ©Y, ©Height);
8751 copyWidth != width ||
8752 copyHeight != height) {
8753 // some part was clipped so clear the texture.
8755 texture->service_id(), texture->target(),
8756 target, level, internal_format, internal_format, GL_UNSIGNED_BYTE,
8757 width, height, texture->IsImmutable())) {
8759 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
8762 if (copyHeight > 0 && copyWidth > 0) {
8763 GLint dx = copyX - x;
8764 GLint dy = copyY - y;
8767 ScopedModifyPixels modify(texture_ref);
8768 glCopyTexSubImage2D(target, level,
8769 destX, destY, copyX, copyY,
8770 copyWidth, copyHeight);
8773 ScopedModifyPixels modify(texture_ref);
8774 glCopyTexImage2D(target, level, internal_format,
8775 copyX, copyY, copyWidth, copyHeight, border);
8777 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
8778 if (error == GL_NO_ERROR) {
8779 texture_manager()->SetLevelInfo(
8780 texture_ref, target, level, internal_format, width, height, 1,
8781 border, internal_format, GL_UNSIGNED_BYTE, true);
8784 // This may be a slow command. Exit command processing to allow for
8785 // context preemption and GPU watchdog checks.
8786 ExitCommandProcessingEarly();
8789 void GLES2DecoderImpl::DoCopyTexSubImage2D(
8798 DCHECK(!ShouldDeferReads());
8799 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8803 GL_INVALID_OPERATION,
8804 "glCopyTexSubImage2D", "unknown texture for target");
8807 Texture* texture = texture_ref->texture();
8810 if (!texture->GetLevelType(target, level, &type, &format) ||
8811 !texture->ValidForTexture(
8812 target, level, xoffset, yoffset, width, height, type)) {
8814 GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
8817 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
8819 GL_INVALID_OPERATION,
8820 "glCopyTexSubImage2D", "async upload pending for texture");
8824 // Check we have compatible formats.
8825 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8826 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8827 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
8829 if (!channels_needed ||
8830 (channels_needed & channels_exist) != channels_needed) {
8832 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
8836 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8838 GL_INVALID_OPERATION,
8839 "glCopySubImage2D", "can not be used with depth or stencil textures");
8843 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexSubImage2D")) {
8847 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
8851 ScopedResolvedFrameBufferBinder binder(this, false, true);
8852 gfx::Size size = GetBoundReadFrameBufferSize();
8855 GLint copyWidth = 0;
8856 GLint copyHeight = 0;
8857 Clip(x, width, size.width(), ©X, ©Width);
8858 Clip(y, height, size.height(), ©Y, ©Height);
8860 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, level)) {
8862 GL_OUT_OF_MEMORY, "glCopyTexSubImage2D", "dimensions too big");
8868 copyWidth != width ||
8869 copyHeight != height) {
8870 // some part was clipped so clear the sub rect.
8871 uint32 pixels_size = 0;
8872 if (!GLES2Util::ComputeImageDataSizes(
8873 width, height, format, type, state_.unpack_alignment, &pixels_size,
8876 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
8879 scoped_ptr<char[]> zero(new char[pixels_size]);
8880 memset(zero.get(), 0, pixels_size);
8881 ScopedModifyPixels modify(texture_ref);
8883 target, level, xoffset, yoffset, width, height,
8884 format, type, zero.get());
8887 if (copyHeight > 0 && copyWidth > 0) {
8888 GLint dx = copyX - x;
8889 GLint dy = copyY - y;
8890 GLint destX = xoffset + dx;
8891 GLint destY = yoffset + dy;
8892 ScopedModifyPixels modify(texture_ref);
8893 glCopyTexSubImage2D(target, level,
8894 destX, destY, copyX, copyY,
8895 copyWidth, copyHeight);
8898 // This may be a slow command. Exit command processing to allow for
8899 // context preemption and GPU watchdog checks.
8900 ExitCommandProcessingEarly();
8903 bool GLES2DecoderImpl::ValidateTexSubImage2D(
8904 error::Error* error,
8905 const char* function_name,
8914 const void * data) {
8915 (*error) = error::kNoError;
8916 if (!validators_->texture_target.IsValid(target)) {
8917 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
8921 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
8925 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
8928 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8932 GL_INVALID_OPERATION,
8933 function_name, "unknown texture for target");
8936 Texture* texture = texture_ref->texture();
8937 GLenum current_type = 0;
8938 GLenum internal_format = 0;
8939 if (!texture->GetLevelType(target, level, ¤t_type, &internal_format)) {
8941 GL_INVALID_OPERATION, function_name, "level does not exist.");
8944 if (!texture_manager()->ValidateTextureParameters(state_.GetErrorState(),
8945 function_name, format, type, internal_format, level)) {
8948 if (type != current_type) {
8950 GL_INVALID_OPERATION,
8951 function_name, "type does not match type of texture.");
8954 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
8956 GL_INVALID_OPERATION,
8957 function_name, "async upload pending for texture");
8960 if (!texture->ValidForTexture(
8961 target, level, xoffset, yoffset, width, height, type)) {
8962 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
8965 if ((GLES2Util::GetChannelsForFormat(format) &
8966 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8968 GL_INVALID_OPERATION,
8969 function_name, "can not supply data for depth or stencil textures");
8973 (*error) = error::kOutOfBounds;
8979 error::Error GLES2DecoderImpl::DoTexSubImage2D(
8988 const void * data) {
8989 error::Error error = error::kNoError;
8990 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level,
8991 xoffset, yoffset, width, height, format, type, data)) {
8994 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8996 Texture* texture = texture_ref->texture();
8997 GLsizei tex_width = 0;
8998 GLsizei tex_height = 0;
8999 bool ok = texture->GetLevelSize(target, level, &tex_width, &tex_height);
9001 if (xoffset != 0 || yoffset != 0 ||
9002 width != tex_width || height != tex_height) {
9003 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
9006 GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big");
9007 return error::kNoError;
9009 ScopedTextureUploadTimer timer(&texture_state_);
9011 target, level, xoffset, yoffset, width, height, format, type, data);
9012 return error::kNoError;
9015 if (!texture_state_.texsubimage2d_faster_than_teximage2d &&
9016 !texture->IsImmutable()) {
9017 ScopedTextureUploadTimer timer(&texture_state_);
9018 GLenum internal_format;
9020 texture->GetLevelType(target, level, &tex_type, &internal_format);
9021 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
9024 target, level, internal_format, width, height, 0, format, type, data);
9026 ScopedTextureUploadTimer timer(&texture_state_);
9028 target, level, xoffset, yoffset, width, height, format, type, data);
9030 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
9032 // This may be a slow command. Exit command processing to allow for
9033 // context preemption and GPU watchdog checks.
9034 ExitCommandProcessingEarly();
9035 return error::kNoError;
9038 error::Error GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size,
9039 const void* cmd_data) {
9040 const gles2::cmds::TexSubImage2D& c =
9041 *static_cast<const gles2::cmds::TexSubImage2D*>(cmd_data);
9042 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
9043 "width", c.width, "height", c.height);
9044 GLboolean internal = static_cast<GLboolean>(c.internal);
9045 if (internal == GL_TRUE && texture_state_.tex_image_2d_failed)
9046 return error::kNoError;
9048 GLenum target = static_cast<GLenum>(c.target);
9049 GLint level = static_cast<GLint>(c.level);
9050 GLint xoffset = static_cast<GLint>(c.xoffset);
9051 GLint yoffset = static_cast<GLint>(c.yoffset);
9052 GLsizei width = static_cast<GLsizei>(c.width);
9053 GLsizei height = static_cast<GLsizei>(c.height);
9054 GLenum format = static_cast<GLenum>(c.format);
9055 GLenum type = static_cast<GLenum>(c.type);
9057 if (!GLES2Util::ComputeImageDataSizes(
9058 width, height, format, type, state_.unpack_alignment, &data_size,
9060 return error::kOutOfBounds;
9062 const void* pixels = GetSharedMemoryAs<const void*>(
9063 c.pixels_shm_id, c.pixels_shm_offset, data_size);
9064 return DoTexSubImage2D(
9065 target, level, xoffset, yoffset, width, height, format, type, pixels);
9068 error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
9069 uint32 immediate_data_size,
9070 const void* cmd_data) {
9071 const gles2::cmds::GetVertexAttribPointerv& c =
9072 *static_cast<const gles2::cmds::GetVertexAttribPointerv*>(cmd_data);
9073 GLuint index = static_cast<GLuint>(c.index);
9074 GLenum pname = static_cast<GLenum>(c.pname);
9075 typedef cmds::GetVertexAttribPointerv::Result Result;
9076 Result* result = GetSharedMemoryAs<Result*>(
9077 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
9079 return error::kOutOfBounds;
9081 // Check that the client initialized the result.
9082 if (result->size != 0) {
9083 return error::kInvalidArguments;
9085 if (!validators_->vertex_pointer.IsValid(pname)) {
9086 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9087 "glGetVertexAttribPointerv", pname, "pname");
9088 return error::kNoError;
9090 if (index >= group_->max_vertex_attribs()) {
9092 GL_INVALID_VALUE, "glGetVertexAttribPointerv", "index out of range.");
9093 return error::kNoError;
9095 result->SetNumResults(1);
9096 *result->GetData() =
9097 state_.vertex_attrib_manager->GetVertexAttrib(index)->offset();
9098 return error::kNoError;
9101 bool GLES2DecoderImpl::GetUniformSetup(
9102 GLuint program_id, GLint fake_location,
9103 uint32 shm_id, uint32 shm_offset,
9104 error::Error* error, GLint* real_location,
9105 GLuint* service_id, void** result_pointer, GLenum* result_type) {
9108 DCHECK(result_pointer);
9109 DCHECK(result_type);
9110 DCHECK(real_location);
9111 *error = error::kNoError;
9112 // Make sure we have enough room for the result on failure.
9113 SizedResult<GLint>* result;
9114 result = GetSharedMemoryAs<SizedResult<GLint>*>(
9115 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
9117 *error = error::kOutOfBounds;
9120 *result_pointer = result;
9121 // Set the result size to 0 so the client does not have to check for success.
9122 result->SetNumResults(0);
9123 Program* program = GetProgramInfoNotShader(program_id, "glGetUniform");
9127 if (!program->IsValid()) {
9128 // Program was not linked successfully. (ie, glLinkProgram)
9130 GL_INVALID_OPERATION, "glGetUniform", "program not linked");
9133 *service_id = program->service_id();
9134 GLint array_index = -1;
9135 const Program::UniformInfo* uniform_info =
9136 program->GetUniformInfoByFakeLocation(
9137 fake_location, real_location, &array_index);
9138 if (!uniform_info) {
9139 // No such location.
9141 GL_INVALID_OPERATION, "glGetUniform", "unknown location");
9144 GLenum type = uniform_info->type;
9145 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
9147 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
9150 result = GetSharedMemoryAs<SizedResult<GLint>*>(
9151 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
9153 *error = error::kOutOfBounds;
9156 result->size = size;
9157 *result_type = type;
9161 error::Error GLES2DecoderImpl::HandleGetUniformiv(uint32 immediate_data_size,
9162 const void* cmd_data) {
9163 const gles2::cmds::GetUniformiv& c =
9164 *static_cast<const gles2::cmds::GetUniformiv*>(cmd_data);
9165 GLuint program = c.program;
9166 GLint fake_location = c.location;
9169 GLint real_location = -1;
9172 if (GetUniformSetup(
9173 program, fake_location, c.params_shm_id, c.params_shm_offset,
9174 &error, &real_location, &service_id, &result, &result_type)) {
9176 service_id, real_location,
9177 static_cast<cmds::GetUniformiv::Result*>(result)->GetData());
9182 error::Error GLES2DecoderImpl::HandleGetUniformfv(uint32 immediate_data_size,
9183 const void* cmd_data) {
9184 const gles2::cmds::GetUniformfv& c =
9185 *static_cast<const gles2::cmds::GetUniformfv*>(cmd_data);
9186 GLuint program = c.program;
9187 GLint fake_location = c.location;
9189 GLint real_location = -1;
9191 typedef cmds::GetUniformfv::Result Result;
9194 if (GetUniformSetup(
9195 program, fake_location, c.params_shm_id, c.params_shm_offset,
9196 &error, &real_location, &service_id,
9197 reinterpret_cast<void**>(&result), &result_type)) {
9198 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
9199 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
9200 GLsizei num_values = result->GetNumResults();
9201 scoped_ptr<GLint[]> temp(new GLint[num_values]);
9202 glGetUniformiv(service_id, real_location, temp.get());
9203 GLfloat* dst = result->GetData();
9204 for (GLsizei ii = 0; ii < num_values; ++ii) {
9205 dst[ii] = (temp[ii] != 0);
9208 glGetUniformfv(service_id, real_location, result->GetData());
9214 error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
9215 uint32 immediate_data_size,
9216 const void* cmd_data) {
9217 const gles2::cmds::GetShaderPrecisionFormat& c =
9218 *static_cast<const gles2::cmds::GetShaderPrecisionFormat*>(cmd_data);
9219 GLenum shader_type = static_cast<GLenum>(c.shadertype);
9220 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
9221 typedef cmds::GetShaderPrecisionFormat::Result Result;
9222 Result* result = GetSharedMemoryAs<Result*>(
9223 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9225 return error::kOutOfBounds;
9227 // Check that the client initialized the result.
9228 if (result->success != 0) {
9229 return error::kInvalidArguments;
9231 if (!validators_->shader_type.IsValid(shader_type)) {
9232 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9233 "glGetShaderPrecisionFormat", shader_type, "shader_type");
9234 return error::kNoError;
9236 if (!validators_->shader_precision.IsValid(precision_type)) {
9237 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9238 "glGetShaderPrecisionFormat", precision_type, "precision_type");
9239 return error::kNoError;
9242 result->success = 1; // true
9244 GLint range[2] = { 0, 0 };
9245 GLint precision = 0;
9246 GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
9248 result->min_range = range[0];
9249 result->max_range = range[1];
9250 result->precision = precision;
9252 return error::kNoError;
9255 error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
9256 uint32 immediate_data_size,
9257 const void* cmd_data) {
9258 const gles2::cmds::GetAttachedShaders& c =
9259 *static_cast<const gles2::cmds::GetAttachedShaders*>(cmd_data);
9260 uint32 result_size = c.result_size;
9261 GLuint program_id = static_cast<GLuint>(c.program);
9262 Program* program = GetProgramInfoNotShader(
9263 program_id, "glGetAttachedShaders");
9265 return error::kNoError;
9267 typedef cmds::GetAttachedShaders::Result Result;
9268 uint32 max_count = Result::ComputeMaxResults(result_size);
9269 Result* result = GetSharedMemoryAs<Result*>(
9270 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
9272 return error::kOutOfBounds;
9274 // Check that the client initialized the result.
9275 if (result->size != 0) {
9276 return error::kInvalidArguments;
9279 glGetAttachedShaders(
9280 program->service_id(), max_count, &count, result->GetData());
9281 for (GLsizei ii = 0; ii < count; ++ii) {
9282 if (!shader_manager()->GetClientId(result->GetData()[ii],
9283 &result->GetData()[ii])) {
9285 return error::kGenericError;
9288 result->SetNumResults(count);
9289 return error::kNoError;
9292 error::Error GLES2DecoderImpl::HandleGetActiveUniform(
9293 uint32 immediate_data_size,
9294 const void* cmd_data) {
9295 const gles2::cmds::GetActiveUniform& c =
9296 *static_cast<const gles2::cmds::GetActiveUniform*>(cmd_data);
9297 GLuint program_id = c.program;
9298 GLuint index = c.index;
9299 uint32 name_bucket_id = c.name_bucket_id;
9300 typedef cmds::GetActiveUniform::Result Result;
9301 Result* result = GetSharedMemoryAs<Result*>(
9302 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9304 return error::kOutOfBounds;
9306 // Check that the client initialized the result.
9307 if (result->success != 0) {
9308 return error::kInvalidArguments;
9310 Program* program = GetProgramInfoNotShader(
9311 program_id, "glGetActiveUniform");
9313 return error::kNoError;
9315 const Program::UniformInfo* uniform_info =
9316 program->GetUniformInfo(index);
9317 if (!uniform_info) {
9319 GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
9320 return error::kNoError;
9322 result->success = 1; // true.
9323 result->size = uniform_info->size;
9324 result->type = uniform_info->type;
9325 Bucket* bucket = CreateBucket(name_bucket_id);
9326 bucket->SetFromString(uniform_info->name.c_str());
9327 return error::kNoError;
9330 error::Error GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size,
9331 const void* cmd_data) {
9332 const gles2::cmds::GetActiveAttrib& c =
9333 *static_cast<const gles2::cmds::GetActiveAttrib*>(cmd_data);
9334 GLuint program_id = c.program;
9335 GLuint index = c.index;
9336 uint32 name_bucket_id = c.name_bucket_id;
9337 typedef cmds::GetActiveAttrib::Result Result;
9338 Result* result = GetSharedMemoryAs<Result*>(
9339 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9341 return error::kOutOfBounds;
9343 // Check that the client initialized the result.
9344 if (result->success != 0) {
9345 return error::kInvalidArguments;
9347 Program* program = GetProgramInfoNotShader(
9348 program_id, "glGetActiveAttrib");
9350 return error::kNoError;
9352 const Program::VertexAttrib* attrib_info =
9353 program->GetAttribInfo(index);
9356 GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
9357 return error::kNoError;
9359 result->success = 1; // true.
9360 result->size = attrib_info->size;
9361 result->type = attrib_info->type;
9362 Bucket* bucket = CreateBucket(name_bucket_id);
9363 bucket->SetFromString(attrib_info->name.c_str());
9364 return error::kNoError;
9367 error::Error GLES2DecoderImpl::HandleShaderBinary(uint32 immediate_data_size,
9368 const void* cmd_data) {
9369 #if 1 // No binary shader support.
9370 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
9371 return error::kNoError;
9373 GLsizei n = static_cast<GLsizei>(c.n);
9375 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
9376 return error::kNoError;
9378 GLsizei length = static_cast<GLsizei>(c.length);
9380 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
9381 return error::kNoError;
9384 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
9385 return error::kOutOfBounds;
9387 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
9388 c.shaders_shm_id, c.shaders_shm_offset, data_size);
9389 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
9390 const void* binary = GetSharedMemoryAs<const void*>(
9391 c.binary_shm_id, c.binary_shm_offset, length);
9392 if (shaders == NULL || binary == NULL) {
9393 return error::kOutOfBounds;
9395 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
9396 for (GLsizei ii = 0; ii < n; ++ii) {
9397 Shader* shader = GetShader(shaders[ii]);
9399 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
9400 return error::kNoError;
9402 service_ids[ii] = shader->service_id();
9404 // TODO(gman): call glShaderBinary
9405 return error::kNoError;
9409 void GLES2DecoderImpl::DoSwapBuffers() {
9410 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
9412 int this_frame_number = frame_number_++;
9413 // TRACE_EVENT for gpu tests:
9414 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
9415 TRACE_EVENT_SCOPE_THREAD,
9416 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
9417 "width", (is_offscreen ? offscreen_size_.width() :
9418 surface_->GetSize().width()));
9419 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
9420 "offscreen", is_offscreen,
9421 "frame", this_frame_number);
9423 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
9427 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
9430 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
9431 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
9432 is_offscreen ? offscreen_size_ : surface_->GetSize());
9435 // If offscreen then don't actually SwapBuffers to the display. Just copy
9436 // the rendered frame to another frame buffer.
9438 TRACE_EVENT2("gpu", "Offscreen",
9439 "width", offscreen_size_.width(), "height", offscreen_size_.height());
9440 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
9441 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
9442 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
9444 if (workarounds().needs_offscreen_buffer_workaround) {
9445 offscreen_saved_frame_buffer_->Create();
9449 // Allocate the offscreen saved color texture.
9450 DCHECK(offscreen_saved_color_format_);
9451 offscreen_saved_color_texture_->AllocateStorage(
9452 offscreen_size_, offscreen_saved_color_format_, false);
9454 offscreen_saved_frame_buffer_->AttachRenderTexture(
9455 offscreen_saved_color_texture_.get());
9456 if (offscreen_size_.width() != 0 && offscreen_size_.height() != 0) {
9457 if (offscreen_saved_frame_buffer_->CheckStatus() !=
9458 GL_FRAMEBUFFER_COMPLETE) {
9459 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
9460 << "because offscreen saved FBO was incomplete.";
9461 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
9465 // Clear the offscreen color texture.
9466 // TODO(piman): Is this still necessary?
9468 ScopedFrameBufferBinder binder(this,
9469 offscreen_saved_frame_buffer_->id());
9470 glClearColor(0, 0, 0, 0);
9471 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
9472 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
9473 glClear(GL_COLOR_BUFFER_BIT);
9474 RestoreClearState();
9478 UpdateParentTextureInfo();
9481 if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
9483 ScopedGLErrorSuppressor suppressor(
9484 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
9486 if (IsOffscreenBufferMultisampled()) {
9487 // For multisampled buffers, resolve the frame buffer.
9488 ScopedResolvedFrameBufferBinder binder(this, true, false);
9490 ScopedFrameBufferBinder binder(this,
9491 offscreen_target_frame_buffer_->id());
9493 if (offscreen_target_buffer_preserved_) {
9494 // Copy the target frame buffer to the saved offscreen texture.
9495 offscreen_saved_color_texture_->Copy(
9496 offscreen_saved_color_texture_->size(),
9497 offscreen_saved_color_format_);
9499 // Flip the textures in the parent context via the texture manager.
9500 if (!!offscreen_saved_color_texture_info_.get())
9501 offscreen_saved_color_texture_info_->texture()->
9502 SetServiceId(offscreen_target_color_texture_->id());
9504 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
9505 offscreen_target_frame_buffer_->AttachRenderTexture(
9506 offscreen_target_color_texture_.get());
9509 // Ensure the side effects of the copy are visible to the parent
9510 // context. There is no need to do this for ANGLE because it uses a
9511 // single D3D device for all contexts.
9512 if (!feature_info_->feature_flags().is_angle)
9516 if (!surface_->SwapBuffers()) {
9517 LOG(ERROR) << "Context lost because SwapBuffers failed.";
9518 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
9522 // This may be a slow command. Exit command processing to allow for
9523 // context preemption and GPU watchdog checks.
9524 ExitCommandProcessingEarly();
9527 error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
9528 uint32 immediate_data_size,
9529 const void* cmd_data) {
9530 const gles2::cmds::EnableFeatureCHROMIUM& c =
9531 *static_cast<const gles2::cmds::EnableFeatureCHROMIUM*>(cmd_data);
9532 Bucket* bucket = GetBucket(c.bucket_id);
9533 if (!bucket || bucket->size() == 0) {
9534 return error::kInvalidArguments;
9536 typedef cmds::EnableFeatureCHROMIUM::Result Result;
9537 Result* result = GetSharedMemoryAs<Result*>(
9538 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9540 return error::kOutOfBounds;
9542 // Check that the client initialized the result.
9544 return error::kInvalidArguments;
9546 std::string feature_str;
9547 if (!bucket->GetAsString(&feature_str)) {
9548 return error::kInvalidArguments;
9551 // TODO(gman): make this some kind of table to function pointer thingy.
9552 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
9553 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
9554 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
9555 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
9556 // TODO(gman): decide how to remove the need for this const_cast.
9557 // I could make validators_ non const but that seems bad as this is the only
9558 // place it is needed. I could make some special friend class of validators
9559 // just to allow this to set them. That seems silly. I could refactor this
9560 // code to use the extension mechanism or the initialization attributes to
9561 // turn this feature on. Given that the only real point of this is to make
9562 // the conformance tests pass and given that there is lots of real work that
9563 // needs to be done it seems like refactoring for one to one of those
9564 // methods is a very low priority.
9565 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
9566 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
9567 force_webgl_glsl_validation_ = true;
9568 InitializeShaderTranslator();
9570 return error::kNoError;
9573 *result = 1; // true.
9574 return error::kNoError;
9577 error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
9578 uint32 immediate_data_size,
9579 const void* cmd_data) {
9580 const gles2::cmds::GetRequestableExtensionsCHROMIUM& c =
9581 *static_cast<const gles2::cmds::GetRequestableExtensionsCHROMIUM*>(
9583 Bucket* bucket = CreateBucket(c.bucket_id);
9584 scoped_refptr<FeatureInfo> info(new FeatureInfo());
9585 info->Initialize(disallowed_features_);
9586 bucket->SetFromString(info->extensions().c_str());
9587 return error::kNoError;
9590 error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
9591 uint32 immediate_data_size,
9592 const void* cmd_data) {
9593 const gles2::cmds::RequestExtensionCHROMIUM& c =
9594 *static_cast<const gles2::cmds::RequestExtensionCHROMIUM*>(cmd_data);
9595 Bucket* bucket = GetBucket(c.bucket_id);
9596 if (!bucket || bucket->size() == 0) {
9597 return error::kInvalidArguments;
9599 std::string feature_str;
9600 if (!bucket->GetAsString(&feature_str)) {
9601 return error::kInvalidArguments;
9604 bool desire_webgl_glsl_validation =
9605 feature_str.find("GL_CHROMIUM_webglsl") != std::string::npos;
9606 bool desire_standard_derivatives = false;
9607 bool desire_frag_depth = false;
9608 bool desire_draw_buffers = false;
9609 bool desire_shader_texture_lod = false;
9610 if (force_webgl_glsl_validation_) {
9611 desire_standard_derivatives =
9612 feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
9614 feature_str.find("GL_EXT_frag_depth") != std::string::npos;
9615 desire_draw_buffers =
9616 feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
9617 desire_shader_texture_lod =
9618 feature_str.find("GL_EXT_shader_texture_lod") != std::string::npos;
9621 if (desire_webgl_glsl_validation != force_webgl_glsl_validation_ ||
9622 desire_standard_derivatives != derivatives_explicitly_enabled_ ||
9623 desire_frag_depth != frag_depth_explicitly_enabled_ ||
9624 desire_draw_buffers != draw_buffers_explicitly_enabled_) {
9625 force_webgl_glsl_validation_ |= desire_webgl_glsl_validation;
9626 derivatives_explicitly_enabled_ |= desire_standard_derivatives;
9627 frag_depth_explicitly_enabled_ |= desire_frag_depth;
9628 draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
9629 shader_texture_lod_explicitly_enabled_ |= desire_shader_texture_lod;
9630 InitializeShaderTranslator();
9633 UpdateCapabilities();
9635 return error::kNoError;
9638 error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
9639 uint32 immediate_data_size,
9640 const void* cmd_data) {
9641 const gles2::cmds::GetMultipleIntegervCHROMIUM& c =
9642 *static_cast<const gles2::cmds::GetMultipleIntegervCHROMIUM*>(cmd_data);
9643 GLuint count = c.count;
9645 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
9646 return error::kOutOfBounds;
9648 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
9649 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
9650 if (pnames == NULL) {
9651 return error::kOutOfBounds;
9654 // We have to copy them since we use them twice so the client
9655 // can't change them between the time we validate them and the time we use
9657 scoped_ptr<GLenum[]> enums(new GLenum[count]);
9658 memcpy(enums.get(), pnames, pnames_size);
9660 // Count up the space needed for the result.
9661 uint32 num_results = 0;
9662 for (GLuint ii = 0; ii < count; ++ii) {
9663 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
9665 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9666 "glGetMultipleCHROMIUM", enums[ii], "pname");
9667 return error::kNoError;
9669 // Num will never be more than 4.
9671 if (!SafeAddUint32(num_results, num, &num_results)) {
9672 return error::kOutOfBounds;
9676 uint32 result_size = 0;
9677 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
9678 return error::kOutOfBounds;
9681 if (result_size != static_cast<uint32>(c.size)) {
9684 "glGetMultipleCHROMIUM", "bad size GL_INVALID_VALUE");
9685 return error::kNoError;
9688 GLint* results = GetSharedMemoryAs<GLint*>(
9689 c.results_shm_id, c.results_shm_offset, result_size);
9690 if (results == NULL) {
9691 return error::kOutOfBounds;
9694 // Check the results have been cleared in case the context was lost.
9695 for (uint32 ii = 0; ii < num_results; ++ii) {
9697 return error::kInvalidArguments;
9702 GLint* start = results;
9703 for (GLuint ii = 0; ii < count; ++ii) {
9704 GLsizei num_written = 0;
9705 if (!state_.GetStateAsGLint(enums[ii], results, &num_written) &&
9706 !GetHelper(enums[ii], results, &num_written)) {
9707 DoGetIntegerv(enums[ii], results);
9709 results += num_written;
9712 // Just to verify. Should this be a DCHECK?
9713 if (static_cast<uint32>(results - start) != num_results) {
9714 return error::kOutOfBounds;
9717 return error::kNoError;
9720 error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
9721 uint32 immediate_data_size,
9722 const void* cmd_data) {
9723 const gles2::cmds::GetProgramInfoCHROMIUM& c =
9724 *static_cast<const gles2::cmds::GetProgramInfoCHROMIUM*>(cmd_data);
9725 GLuint program_id = static_cast<GLuint>(c.program);
9726 uint32 bucket_id = c.bucket_id;
9727 Bucket* bucket = CreateBucket(bucket_id);
9728 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
9729 Program* program = NULL;
9730 program = GetProgram(program_id);
9731 if (!program || !program->IsValid()) {
9732 return error::kNoError;
9734 program->GetProgramInfo(program_manager(), bucket);
9735 return error::kNoError;
9738 error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
9739 switch (reset_status_) {
9741 // TODO(kbr): improve the precision of the error code in this case.
9742 // Consider delegating to context for error code if MakeCurrent fails.
9743 return error::kUnknown;
9744 case GL_GUILTY_CONTEXT_RESET_ARB:
9745 return error::kGuilty;
9746 case GL_INNOCENT_CONTEXT_RESET_ARB:
9747 return error::kInnocent;
9748 case GL_UNKNOWN_CONTEXT_RESET_ARB:
9749 return error::kUnknown;
9753 return error::kUnknown;
9756 bool GLES2DecoderImpl::WasContextLost() {
9757 if (reset_status_ != GL_NO_ERROR) {
9760 if (context_->WasAllocatedUsingRobustnessExtension()) {
9761 GLenum status = GL_NO_ERROR;
9762 if (has_robustness_extension_)
9763 status = glGetGraphicsResetStatusARB();
9764 if (status != GL_NO_ERROR) {
9765 // The graphics card was reset. Signal a lost context to the application.
9766 reset_status_ = status;
9767 reset_by_robustness_extension_ = true;
9768 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
9769 << " context lost via ARB/EXT_robustness. Reset status = "
9770 << GLES2Util::GetStringEnum(status);
9777 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() {
9778 return WasContextLost() && reset_by_robustness_extension_;
9781 void GLES2DecoderImpl::LoseContext(uint32 reset_status) {
9782 // Only loses the context once.
9783 if (reset_status_ != GL_NO_ERROR) {
9787 // Marks this context as lost.
9788 reset_status_ = reset_status;
9789 current_decoder_error_ = error::kLostContext;
9792 error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
9793 uint32 immediate_data_size,
9794 const void* cmd_data) {
9795 return error::kUnknownCommand;
9798 error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
9799 uint32 immediate_data_size,
9800 const void* cmd_data) {
9801 const gles2::cmds::WaitSyncPointCHROMIUM& c =
9802 *static_cast<const gles2::cmds::WaitSyncPointCHROMIUM*>(cmd_data);
9803 group_->mailbox_manager()->PullTextureUpdates();
9804 if (wait_sync_point_callback_.is_null())
9805 return error::kNoError;
9807 return wait_sync_point_callback_.Run(c.sync_point) ?
9808 error::kNoError : error::kDeferCommandUntilLater;
9811 error::Error GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
9812 uint32 immediate_data_size,
9813 const void* cmd_data) {
9814 if (surface_->DeferDraws())
9815 return error::kDeferCommandUntilLater;
9816 if (!surface_->SetBackbufferAllocation(false))
9817 return error::kLostContext;
9818 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
9819 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
9820 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
9821 return error::kNoError;
9824 bool GLES2DecoderImpl::GenQueriesEXTHelper(
9825 GLsizei n, const GLuint* client_ids) {
9826 for (GLsizei ii = 0; ii < n; ++ii) {
9827 if (query_manager_->GetQuery(client_ids[ii])) {
9831 query_manager_->GenQueries(n, client_ids);
9835 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
9836 GLsizei n, const GLuint* client_ids) {
9837 for (GLsizei ii = 0; ii < n; ++ii) {
9838 QueryManager::Query* query = query_manager_->GetQuery(client_ids[ii]);
9839 if (query && !query->IsDeleted()) {
9840 ContextState::QueryMap::iterator it =
9841 state_.current_queries.find(query->target());
9842 if (it != state_.current_queries.end())
9843 state_.current_queries.erase(it);
9845 query->Destroy(true);
9847 query_manager_->RemoveQuery(client_ids[ii]);
9851 bool GLES2DecoderImpl::ProcessPendingQueries() {
9852 if (query_manager_.get() == NULL) {
9855 if (!query_manager_->ProcessPendingQueries()) {
9856 current_decoder_error_ = error::kOutOfBounds;
9858 return query_manager_->HavePendingQueries();
9861 // Note that if there are no pending readpixels right now,
9862 // this function will call the callback immediately.
9863 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback) {
9864 if (features().use_async_readpixels && !pending_readpixel_fences_.empty()) {
9865 pending_readpixel_fences_.back()->callbacks.push_back(callback);
9871 void GLES2DecoderImpl::ProcessPendingReadPixels() {
9872 while (!pending_readpixel_fences_.empty() &&
9873 pending_readpixel_fences_.front()->fence->HasCompleted()) {
9874 std::vector<base::Closure> callbacks =
9875 pending_readpixel_fences_.front()->callbacks;
9876 pending_readpixel_fences_.pop();
9877 for (size_t i = 0; i < callbacks.size(); i++) {
9883 bool GLES2DecoderImpl::HasMoreIdleWork() {
9884 return !pending_readpixel_fences_.empty() ||
9885 async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers();
9888 void GLES2DecoderImpl::PerformIdleWork() {
9889 ProcessPendingReadPixels();
9890 if (!async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers())
9892 async_pixel_transfer_manager_->ProcessMorePendingTransfers();
9893 ProcessFinishedAsyncTransfers();
9896 error::Error GLES2DecoderImpl::HandleBeginQueryEXT(uint32 immediate_data_size,
9897 const void* cmd_data) {
9898 const gles2::cmds::BeginQueryEXT& c =
9899 *static_cast<const gles2::cmds::BeginQueryEXT*>(cmd_data);
9900 GLenum target = static_cast<GLenum>(c.target);
9901 GLuint client_id = static_cast<GLuint>(c.id);
9902 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
9903 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
9906 case GL_COMMANDS_ISSUED_CHROMIUM:
9907 case GL_LATENCY_QUERY_CHROMIUM:
9908 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM:
9909 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
9910 case GL_GET_ERROR_QUERY_CHROMIUM:
9912 case GL_COMMANDS_COMPLETED_CHROMIUM:
9913 if (!features().chromium_sync_query) {
9915 GL_INVALID_OPERATION, "glBeginQueryEXT",
9916 "not enabled for commands completed queries");
9917 return error::kNoError;
9921 if (!features().occlusion_query_boolean) {
9923 GL_INVALID_OPERATION, "glBeginQueryEXT",
9924 "not enabled for occlusion queries");
9925 return error::kNoError;
9930 if (state_.current_queries.find(target) != state_.current_queries.end()) {
9932 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
9933 return error::kNoError;
9936 if (client_id == 0) {
9937 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
9938 return error::kNoError;
9941 QueryManager::Query* query = query_manager_->GetQuery(client_id);
9943 if (!query_manager_->IsValidQuery(client_id)) {
9944 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
9946 "id not made by glGenQueriesEXT");
9947 return error::kNoError;
9949 query = query_manager_->CreateQuery(
9950 target, client_id, sync_shm_id, sync_shm_offset);
9953 if (query->target() != target) {
9955 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
9956 return error::kNoError;
9957 } else if (query->shm_id() != sync_shm_id ||
9958 query->shm_offset() != sync_shm_offset) {
9959 DLOG(ERROR) << "Shared memory used by query not the same as before";
9960 return error::kInvalidArguments;
9963 if (!query_manager_->BeginQuery(query)) {
9964 return error::kOutOfBounds;
9967 state_.current_queries[target] = query;
9968 return error::kNoError;
9971 error::Error GLES2DecoderImpl::HandleEndQueryEXT(uint32 immediate_data_size,
9972 const void* cmd_data) {
9973 const gles2::cmds::EndQueryEXT& c =
9974 *static_cast<const gles2::cmds::EndQueryEXT*>(cmd_data);
9975 GLenum target = static_cast<GLenum>(c.target);
9976 uint32 submit_count = static_cast<GLuint>(c.submit_count);
9977 ContextState::QueryMap::iterator it = state_.current_queries.find(target);
9979 if (it == state_.current_queries.end()) {
9981 GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
9982 return error::kNoError;
9985 QueryManager::Query* query = it->second.get();
9986 if (!query_manager_->EndQuery(query, submit_count)) {
9987 return error::kOutOfBounds;
9990 query_manager_->ProcessPendingTransferQueries();
9992 state_.current_queries.erase(it);
9993 return error::kNoError;
9996 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
9997 GLsizei n, const GLuint* client_ids) {
9998 for (GLsizei ii = 0; ii < n; ++ii) {
9999 if (GetVertexAttribManager(client_ids[ii])) {
10004 if (!features().native_vertex_array_object) {
10006 for (GLsizei ii = 0; ii < n; ++ii) {
10007 CreateVertexAttribManager(client_ids[ii], 0, true);
10010 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
10012 glGenVertexArraysOES(n, service_ids.get());
10013 for (GLsizei ii = 0; ii < n; ++ii) {
10014 CreateVertexAttribManager(client_ids[ii], service_ids[ii], true);
10021 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
10022 GLsizei n, const GLuint* client_ids) {
10023 for (GLsizei ii = 0; ii < n; ++ii) {
10024 VertexAttribManager* vao =
10025 GetVertexAttribManager(client_ids[ii]);
10026 if (vao && !vao->IsDeleted()) {
10027 if (state_.vertex_attrib_manager.get() == vao) {
10028 DoBindVertexArrayOES(0);
10030 RemoveVertexAttribManager(client_ids[ii]);
10035 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
10036 VertexAttribManager* vao = NULL;
10037 if (client_id != 0) {
10038 vao = GetVertexAttribManager(client_id);
10040 // Unlike most Bind* methods, the spec explicitly states that VertexArray
10041 // only allows names that have been previously generated. As such, we do
10042 // not generate new names here.
10043 LOCAL_SET_GL_ERROR(
10044 GL_INVALID_OPERATION,
10045 "glBindVertexArrayOES", "bad vertex array id.");
10046 current_decoder_error_ = error::kNoError;
10050 vao = state_.default_vertex_attrib_manager.get();
10053 // Only set the VAO state if it's changed
10054 if (state_.vertex_attrib_manager.get() != vao) {
10055 state_.vertex_attrib_manager = vao;
10056 if (!features().native_vertex_array_object) {
10057 EmulateVertexArrayState();
10059 GLuint service_id = vao->service_id();
10060 glBindVertexArrayOES(service_id);
10065 // Used when OES_vertex_array_object isn't natively supported
10066 void GLES2DecoderImpl::EmulateVertexArrayState() {
10067 // Setup the Vertex attribute state
10068 for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) {
10069 RestoreStateForAttrib(vv, true);
10072 // Setup the element buffer
10073 Buffer* element_array_buffer =
10074 state_.vertex_attrib_manager->element_array_buffer();
10075 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
10076 element_array_buffer ? element_array_buffer->service_id() : 0);
10079 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
10080 const VertexAttribManager* vao =
10081 GetVertexAttribManager(client_id);
10082 return vao && vao->IsValid() && !vao->IsDeleted();
10085 #if defined(OS_MACOSX)
10086 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
10087 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
10089 if (it != texture_to_io_surface_map_.end()) {
10090 // Found a previous IOSurface bound to this texture; release it.
10091 IOSurfaceRef surface = it->second;
10092 CFRelease(surface);
10093 texture_to_io_surface_map_.erase(it);
10098 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
10099 GLenum target, GLsizei width, GLsizei height,
10100 GLuint io_surface_id, GLuint plane) {
10101 #if defined(OS_MACOSX)
10102 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
10103 LOCAL_SET_GL_ERROR(
10104 GL_INVALID_OPERATION,
10105 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
10109 if (target != GL_TEXTURE_RECTANGLE_ARB) {
10110 // This might be supported in the future, and if we could require
10111 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
10112 // could delete a lot of code. For now, perform strict validation so we
10113 // know what's going on.
10114 LOCAL_SET_GL_ERROR(
10115 GL_INVALID_OPERATION,
10116 "glTexImageIOSurface2DCHROMIUM",
10117 "requires TEXTURE_RECTANGLE_ARB target");
10121 // Default target might be conceptually valid, but disallow it to avoid
10123 TextureRef* texture_ref =
10124 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10125 if (!texture_ref) {
10126 LOCAL_SET_GL_ERROR(
10127 GL_INVALID_OPERATION,
10128 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
10132 // Look up the new IOSurface. Note that because of asynchrony
10133 // between processes this might fail; during live resizing the
10134 // plugin process might allocate and release an IOSurface before
10135 // this process gets a chance to look it up. Hold on to any old
10136 // IOSurface in this case.
10137 IOSurfaceRef surface = IOSurfaceLookup(io_surface_id);
10139 LOCAL_SET_GL_ERROR(
10140 GL_INVALID_OPERATION,
10141 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
10145 // Release any IOSurface previously bound to this texture.
10146 ReleaseIOSurfaceForTexture(texture_ref->service_id());
10148 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
10149 texture_to_io_surface_map_.insert(
10150 std::make_pair(texture_ref->service_id(), surface));
10152 CGLContextObj context =
10153 static_cast<CGLContextObj>(context_->GetHandle());
10155 CGLError err = CGLTexImageIOSurface2D(
10162 GL_UNSIGNED_INT_8_8_8_8_REV,
10166 if (err != kCGLNoError) {
10167 LOCAL_SET_GL_ERROR(
10168 GL_INVALID_OPERATION,
10169 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
10173 texture_manager()->SetLevelInfo(
10174 texture_ref, target, 0, GL_RGBA, width, height, 1, 0,
10175 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
10178 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10179 "glTexImageIOSurface2DCHROMIUM", "not supported.");
10183 static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
10184 switch (internalformat) {
10195 case GL_LUMINANCE8_ALPHA8_EXT:
10196 return GL_LUMINANCE_ALPHA;
10197 case GL_LUMINANCE8_EXT:
10198 return GL_LUMINANCE;
10199 case GL_ALPHA8_EXT:
10201 case GL_RGBA32F_EXT:
10203 case GL_RGB32F_EXT:
10205 case GL_ALPHA32F_EXT:
10207 case GL_LUMINANCE32F_EXT:
10208 return GL_LUMINANCE;
10209 case GL_LUMINANCE_ALPHA32F_EXT:
10210 return GL_LUMINANCE_ALPHA;
10211 case GL_RGBA16F_EXT:
10213 case GL_RGB16F_EXT:
10215 case GL_ALPHA16F_EXT:
10217 case GL_LUMINANCE16F_EXT:
10218 return GL_LUMINANCE;
10219 case GL_LUMINANCE_ALPHA16F_EXT:
10220 return GL_LUMINANCE_ALPHA;
10222 return GL_BGRA_EXT;
10228 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
10229 GLenum target, GLuint source_id, GLuint dest_id, GLint level,
10230 GLenum internal_format, GLenum dest_type) {
10231 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
10233 TextureRef* dest_texture_ref = GetTexture(dest_id);
10234 TextureRef* source_texture_ref = GetTexture(source_id);
10236 if (!source_texture_ref || !dest_texture_ref) {
10237 LOCAL_SET_GL_ERROR(
10238 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "unknown texture id");
10242 if (GL_TEXTURE_2D != target) {
10243 LOCAL_SET_GL_ERROR(
10244 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "invalid texture target");
10248 Texture* source_texture = source_texture_ref->texture();
10249 Texture* dest_texture = dest_texture_ref->texture();
10250 if (dest_texture->target() != GL_TEXTURE_2D ||
10251 (source_texture->target() != GL_TEXTURE_2D &&
10252 source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
10253 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
10254 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
10255 "glCopyTextureCHROMIUM",
10256 "invalid texture target binding");
10260 int source_width, source_height, dest_width, dest_height;
10262 gfx::GLImage* image =
10263 source_texture->GetLevelImage(source_texture->target(), 0);
10265 gfx::Size size = image->GetSize();
10266 source_width = size.width();
10267 source_height = size.height();
10268 if (source_width <= 0 || source_height <= 0) {
10269 LOCAL_SET_GL_ERROR(
10271 "glCopyTextureChromium", "invalid image size");
10275 if (!source_texture->GetLevelSize(
10276 source_texture->target(), 0, &source_width, &source_height)) {
10277 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
10278 "glCopyTextureChromium",
10279 "source texture has no level 0");
10283 // Check that this type of texture is allowed.
10284 if (!texture_manager()->ValidForTarget(
10285 source_texture->target(), level, source_width, source_height, 1)) {
10286 LOCAL_SET_GL_ERROR(
10287 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "Bad dimensions");
10292 // Clear the source texture if necessary.
10293 if (!texture_manager()->ClearTextureLevel(
10294 this, source_texture_ref, source_texture->target(), 0)) {
10295 LOCAL_SET_GL_ERROR(
10296 GL_OUT_OF_MEMORY, "glCopyTextureCHROMIUM", "dimensions too big");
10300 GLenum source_type = 0;
10301 GLenum source_internal_format = 0;
10302 source_texture->GetLevelType(
10303 source_texture->target(), 0, &source_type, &source_internal_format);
10305 // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
10306 // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
10307 // renderable on some platforms.
10308 bool valid_dest_format = internal_format == GL_RGB ||
10309 internal_format == GL_RGBA ||
10310 internal_format == GL_BGRA_EXT;
10311 bool valid_source_format = source_internal_format == GL_ALPHA ||
10312 source_internal_format == GL_RGB ||
10313 source_internal_format == GL_RGBA ||
10314 source_internal_format == GL_LUMINANCE ||
10315 source_internal_format == GL_LUMINANCE_ALPHA ||
10316 source_internal_format == GL_BGRA_EXT;
10317 if (!valid_source_format || !valid_dest_format) {
10318 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10319 "glCopyTextureCHROMIUM",
10320 "invalid internal format");
10324 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
10325 // needed because it takes 10s of milliseconds to initialize.
10326 if (!copy_texture_CHROMIUM_.get()) {
10327 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
10328 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
10329 copy_texture_CHROMIUM_->Initialize(this);
10330 RestoreCurrentFramebufferBindings();
10331 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
10335 GLenum dest_type_previous = dest_type;
10336 GLenum dest_internal_format = internal_format;
10337 bool dest_level_defined = dest_texture->GetLevelSize(
10338 GL_TEXTURE_2D, level, &dest_width, &dest_height);
10340 if (dest_level_defined) {
10341 dest_texture->GetLevelType(GL_TEXTURE_2D, level, &dest_type_previous,
10342 &dest_internal_format);
10345 // Resize the destination texture to the dimensions of the source texture.
10346 if (!dest_level_defined || dest_width != source_width ||
10347 dest_height != source_height ||
10348 dest_internal_format != internal_format ||
10349 dest_type_previous != dest_type) {
10350 // Ensure that the glTexImage2D succeeds.
10351 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
10352 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
10354 GL_TEXTURE_2D, level, internal_format, source_width, source_height,
10355 0, internal_format, dest_type, NULL);
10356 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
10357 if (error != GL_NO_ERROR) {
10358 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
10362 texture_manager()->SetLevelInfo(
10363 dest_texture_ref, GL_TEXTURE_2D, level, internal_format, source_width,
10364 source_height, 1, 0, internal_format, dest_type, true);
10366 texture_manager()->SetLevelCleared(
10367 dest_texture_ref, GL_TEXTURE_2D, level, true);
10370 ScopedModifyPixels modify(dest_texture_ref);
10372 // Try using GLImage::CopyTexImage when possible.
10373 bool unpack_premultiply_alpha_change =
10374 unpack_premultiply_alpha_ ^ unpack_unpremultiply_alpha_;
10375 if (image && !unpack_flip_y_ && !unpack_premultiply_alpha_change && !level) {
10376 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
10377 if (image->CopyTexImage(GL_TEXTURE_2D))
10381 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
10383 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
10384 // before presenting.
10385 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
10386 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
10387 // instead of using default matrix crbug.com/226218.
10388 const static GLfloat default_matrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
10389 0.0f, 1.0f, 0.0f, 0.0f,
10390 0.0f, 0.0f, 1.0f, 0.0f,
10391 0.0f, 0.0f, 0.0f, 1.0f};
10392 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
10394 source_texture->target(),
10395 source_texture->service_id(),
10396 dest_texture->service_id(),
10401 unpack_premultiply_alpha_,
10402 unpack_unpremultiply_alpha_,
10405 copy_texture_CHROMIUM_->DoCopyTexture(this,
10406 source_texture->target(),
10407 source_texture->service_id(),
10408 source_internal_format,
10409 dest_texture->service_id(),
10415 unpack_premultiply_alpha_,
10416 unpack_unpremultiply_alpha_);
10419 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
10422 static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
10423 switch (internalformat) {
10425 return GL_UNSIGNED_SHORT_5_6_5;
10427 return GL_UNSIGNED_SHORT_4_4_4_4;
10429 return GL_UNSIGNED_SHORT_5_5_5_1;
10431 return GL_UNSIGNED_BYTE;
10433 return GL_UNSIGNED_BYTE;
10434 case GL_LUMINANCE8_ALPHA8_EXT:
10435 return GL_UNSIGNED_BYTE;
10436 case GL_LUMINANCE8_EXT:
10437 return GL_UNSIGNED_BYTE;
10438 case GL_ALPHA8_EXT:
10439 return GL_UNSIGNED_BYTE;
10440 case GL_RGBA32F_EXT:
10442 case GL_RGB32F_EXT:
10444 case GL_ALPHA32F_EXT:
10446 case GL_LUMINANCE32F_EXT:
10448 case GL_LUMINANCE_ALPHA32F_EXT:
10450 case GL_RGBA16F_EXT:
10451 return GL_HALF_FLOAT_OES;
10452 case GL_RGB16F_EXT:
10453 return GL_HALF_FLOAT_OES;
10454 case GL_ALPHA16F_EXT:
10455 return GL_HALF_FLOAT_OES;
10456 case GL_LUMINANCE16F_EXT:
10457 return GL_HALF_FLOAT_OES;
10458 case GL_LUMINANCE_ALPHA16F_EXT:
10459 return GL_HALF_FLOAT_OES;
10461 return GL_UNSIGNED_BYTE;
10467 void GLES2DecoderImpl::DoTexStorage2DEXT(
10470 GLenum internal_format,
10473 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
10474 "width", width, "height", height);
10475 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
10476 TextureManager::ComputeMipMapCount(target, width, height, 1) < levels) {
10477 LOCAL_SET_GL_ERROR(
10478 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
10481 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10483 if (!texture_ref) {
10484 LOCAL_SET_GL_ERROR(
10485 GL_INVALID_OPERATION,
10486 "glTexStorage2DEXT", "unknown texture for target");
10489 Texture* texture = texture_ref->texture();
10490 if (texture->IsAttachedToFramebuffer()) {
10491 framebuffer_state_.clear_state_dirty = true;
10493 if (texture->IsImmutable()) {
10494 LOCAL_SET_GL_ERROR(
10495 GL_INVALID_OPERATION,
10496 "glTexStorage2DEXT", "texture is immutable");
10500 GLenum format = ExtractFormatFromStorageFormat(internal_format);
10501 GLenum type = ExtractTypeFromStorageFormat(internal_format);
10504 GLsizei level_width = width;
10505 GLsizei level_height = height;
10506 uint32 estimated_size = 0;
10507 for (int ii = 0; ii < levels; ++ii) {
10508 uint32 level_size = 0;
10509 if (!GLES2Util::ComputeImageDataSizes(
10510 level_width, level_height, format, type, state_.unpack_alignment,
10511 &estimated_size, NULL, NULL) ||
10512 !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
10513 LOCAL_SET_GL_ERROR(
10514 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large");
10517 level_width = std::max(1, level_width >> 1);
10518 level_height = std::max(1, level_height >> 1);
10520 if (!EnsureGPUMemoryAvailable(estimated_size)) {
10521 LOCAL_SET_GL_ERROR(
10522 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory");
10527 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
10528 glTexStorage2DEXT(target, levels, internal_format, width, height);
10529 GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
10530 if (error == GL_NO_ERROR) {
10531 GLsizei level_width = width;
10532 GLsizei level_height = height;
10533 for (int ii = 0; ii < levels; ++ii) {
10534 texture_manager()->SetLevelInfo(
10535 texture_ref, target, ii, format,
10536 level_width, level_height, 1, 0, format, type, false);
10537 level_width = std::max(1, level_width >> 1);
10538 level_height = std::max(1, level_height >> 1);
10540 texture->SetImmutable(true);
10544 error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
10545 uint32 immediate_data_size,
10546 const void* cmd_data) {
10547 return error::kUnknownCommand;
10550 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
10551 const GLbyte* data) {
10552 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
10553 "context", logger_.GetLogPrefix(),
10554 "mailbox[0]", static_cast<unsigned char>(data[0]));
10556 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10558 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref, target, data);
10561 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id,
10562 GLenum target, const GLbyte* data) {
10563 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
10564 "context", logger_.GetLogPrefix(),
10565 "mailbox[0]", static_cast<unsigned char>(data[0]));
10567 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id),
10571 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name,
10572 TextureRef* texture_ref, GLenum target, const GLbyte* data) {
10573 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
10574 DLOG_IF(ERROR, !mailbox.Verify()) << func_name << " was passed a "
10575 "mailbox that was not generated by "
10576 "GenMailboxCHROMIUM.";
10578 if (!texture_ref) {
10579 LOCAL_SET_GL_ERROR(
10580 GL_INVALID_OPERATION, func_name.c_str(), "unknown texture for target");
10584 Texture* produced = texture_manager()->Produce(texture_ref);
10586 LOCAL_SET_GL_ERROR(
10587 GL_INVALID_OPERATION, func_name.c_str(), "invalid texture");
10591 if (produced->target() != target) {
10592 LOCAL_SET_GL_ERROR(
10593 GL_INVALID_OPERATION, func_name.c_str(), "invalid target");
10597 group_->mailbox_manager()->ProduceTexture(target, mailbox, produced);
10600 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
10601 const GLbyte* data) {
10602 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
10603 "context", logger_.GetLogPrefix(),
10604 "mailbox[0]", static_cast<unsigned char>(data[0]));
10605 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
10606 DLOG_IF(ERROR, !mailbox.Verify()) << "ConsumeTextureCHROMIUM was passed a "
10607 "mailbox that was not generated by "
10608 "GenMailboxCHROMIUM.";
10610 scoped_refptr<TextureRef> texture_ref =
10611 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10612 if (!texture_ref.get()) {
10613 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10614 "glConsumeTextureCHROMIUM",
10615 "unknown texture for target");
10618 GLuint client_id = texture_ref->client_id();
10620 LOCAL_SET_GL_ERROR(
10621 GL_INVALID_OPERATION,
10622 "glConsumeTextureCHROMIUM", "unknown texture for target");
10625 Texture* texture = group_->mailbox_manager()->ConsumeTexture(target, mailbox);
10627 LOCAL_SET_GL_ERROR(
10628 GL_INVALID_OPERATION,
10629 "glConsumeTextureCHROMIUM", "invalid mailbox name");
10632 if (texture->target() != target) {
10633 LOCAL_SET_GL_ERROR(
10634 GL_INVALID_OPERATION,
10635 "glConsumeTextureCHROMIUM", "invalid target");
10639 DeleteTexturesHelper(1, &client_id);
10640 texture_ref = texture_manager()->Consume(client_id, texture);
10641 glBindTexture(target, texture_ref->service_id());
10643 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
10644 unit.bind_target = target;
10646 case GL_TEXTURE_2D:
10647 unit.bound_texture_2d = texture_ref;
10649 case GL_TEXTURE_CUBE_MAP:
10650 unit.bound_texture_cube_map = texture_ref;
10652 case GL_TEXTURE_EXTERNAL_OES:
10653 unit.bound_texture_external_oes = texture_ref;
10655 case GL_TEXTURE_RECTANGLE_ARB:
10656 unit.bound_texture_rectangle_arb = texture_ref;
10659 NOTREACHED(); // Validation should prevent us getting here.
10664 error::Error GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
10665 uint32_t immediate_data_size,
10666 const void* cmd_data) {
10667 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate& c =
10669 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate*>(
10671 GLenum target = static_cast<GLenum>(c.target);
10672 uint32_t data_size;
10673 if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) {
10674 return error::kOutOfBounds;
10676 if (data_size > immediate_data_size) {
10677 return error::kOutOfBounds;
10679 const GLbyte* mailbox =
10680 GetImmediateDataAs<const GLbyte*>(c, data_size, immediate_data_size);
10681 if (!validators_->texture_bind_target.IsValid(target)) {
10682 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10683 "glCreateAndConsumeTextureCHROMIUM", target, "target");
10684 return error::kNoError;
10686 if (mailbox == NULL) {
10687 return error::kOutOfBounds;
10689 uint32_t client_id = c.client_id;
10690 DoCreateAndConsumeTextureCHROMIUM(target, mailbox, client_id);
10691 return error::kNoError;
10694 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target,
10695 const GLbyte* data, GLuint client_id) {
10696 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
10697 "context", logger_.GetLogPrefix(),
10698 "mailbox[0]", static_cast<unsigned char>(data[0]));
10699 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
10700 DLOG_IF(ERROR, !mailbox.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
10701 "passed a mailbox that was not "
10702 "generated by GenMailboxCHROMIUM.";
10704 TextureRef* texture_ref = GetTexture(client_id);
10706 LOCAL_SET_GL_ERROR(
10707 GL_INVALID_OPERATION,
10708 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
10711 Texture* texture = group_->mailbox_manager()->ConsumeTexture(target, mailbox);
10713 LOCAL_SET_GL_ERROR(
10714 GL_INVALID_OPERATION,
10715 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
10718 if (texture->target() != target) {
10719 LOCAL_SET_GL_ERROR(
10720 GL_INVALID_OPERATION,
10721 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
10725 IdAllocatorInterface* id_allocator =
10726 group_->GetIdAllocator(id_namespaces::kTextures);
10727 id_allocator->MarkAsUsed(client_id);
10729 texture_ref = texture_manager()->Consume(client_id, texture);
10732 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
10733 GLsizei length, const GLchar* marker) {
10737 debug_marker_manager_.SetMarker(
10738 length ? std::string(marker, length) : std::string(marker));
10741 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
10742 GLsizei length, const GLchar* marker) {
10746 std::string name = length ? std::string(marker, length) : std::string(marker);
10747 debug_marker_manager_.PushGroup(name);
10748 gpu_tracer_->Begin(name, kTraceGroupMarker);
10751 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
10752 debug_marker_manager_.PopGroup();
10753 gpu_tracer_->End(kTraceGroupMarker);
10756 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
10757 GLenum target, GLint image_id) {
10758 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
10760 if (target == GL_TEXTURE_CUBE_MAP) {
10761 LOCAL_SET_GL_ERROR(
10763 "glBindTexImage2DCHROMIUM", "invalid target");
10767 // Default target might be conceptually valid, but disallow it to avoid
10769 TextureRef* texture_ref =
10770 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10771 if (!texture_ref) {
10772 LOCAL_SET_GL_ERROR(
10773 GL_INVALID_OPERATION,
10774 "glBindTexImage2DCHROMIUM", "no texture bound");
10778 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
10780 LOCAL_SET_GL_ERROR(
10781 GL_INVALID_OPERATION,
10782 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
10787 ScopedGLErrorSuppressor suppressor(
10788 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
10789 if (!gl_image->BindTexImage(target)) {
10790 LOCAL_SET_GL_ERROR(
10791 GL_INVALID_OPERATION,
10792 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
10797 gfx::Size size = gl_image->GetSize();
10798 texture_manager()->SetLevelInfo(
10799 texture_ref, target, 0, GL_RGBA, size.width(), size.height(), 1, 0,
10800 GL_RGBA, GL_UNSIGNED_BYTE, true);
10801 texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image);
10804 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
10805 GLenum target, GLint image_id) {
10806 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
10808 // Default target might be conceptually valid, but disallow it to avoid
10810 TextureRef* texture_ref =
10811 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10812 if (!texture_ref) {
10813 LOCAL_SET_GL_ERROR(
10814 GL_INVALID_OPERATION,
10815 "glReleaseTexImage2DCHROMIUM", "no texture bound");
10819 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
10821 LOCAL_SET_GL_ERROR(
10822 GL_INVALID_OPERATION,
10823 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
10827 // Do nothing when image is not currently bound.
10828 if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image)
10832 ScopedGLErrorSuppressor suppressor(
10833 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
10834 gl_image->ReleaseTexImage(target);
10837 texture_manager()->SetLevelInfo(
10838 texture_ref, target, 0, GL_RGBA, 0, 0, 1, 0,
10839 GL_RGBA, GL_UNSIGNED_BYTE, false);
10842 error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
10843 uint32 immediate_data_size,
10844 const void* cmd_data) {
10845 const gles2::cmds::TraceBeginCHROMIUM& c =
10846 *static_cast<const gles2::cmds::TraceBeginCHROMIUM*>(cmd_data);
10847 Bucket* bucket = GetBucket(c.bucket_id);
10848 if (!bucket || bucket->size() == 0) {
10849 return error::kInvalidArguments;
10851 std::string command_name;
10852 if (!bucket->GetAsString(&command_name)) {
10853 return error::kInvalidArguments;
10855 TRACE_EVENT_COPY_ASYNC_BEGIN0("gpu", command_name.c_str(), this);
10856 if (!gpu_tracer_->Begin(command_name, kTraceCHROMIUM)) {
10857 LOCAL_SET_GL_ERROR(
10858 GL_INVALID_OPERATION,
10859 "glTraceBeginCHROMIUM", "unable to create begin trace");
10860 return error::kNoError;
10862 return error::kNoError;
10865 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
10866 if (gpu_tracer_->CurrentName().empty()) {
10867 LOCAL_SET_GL_ERROR(
10868 GL_INVALID_OPERATION,
10869 "glTraceEndCHROMIUM", "no trace begin found");
10872 TRACE_EVENT_COPY_ASYNC_END0("gpu", gpu_tracer_->CurrentName().c_str(), this);
10873 gpu_tracer_->End(kTraceCHROMIUM);
10876 void GLES2DecoderImpl::DoDrawBuffersEXT(
10877 GLsizei count, const GLenum* bufs) {
10878 if (count > static_cast<GLsizei>(group_->max_draw_buffers())) {
10879 LOCAL_SET_GL_ERROR(
10881 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
10885 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
10887 for (GLsizei i = 0; i < count; ++i) {
10888 if (bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i) &&
10889 bufs[i] != GL_NONE) {
10890 LOCAL_SET_GL_ERROR(
10891 GL_INVALID_OPERATION,
10892 "glDrawBuffersEXT",
10893 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
10897 glDrawBuffersARB(count, bufs);
10898 framebuffer->SetDrawBuffers(count, bufs);
10899 } else { // backbuffer
10901 (bufs[0] != GL_BACK && bufs[0] != GL_NONE)) {
10902 LOCAL_SET_GL_ERROR(
10903 GL_INVALID_OPERATION,
10904 "glDrawBuffersEXT",
10905 "more than one buffer or bufs not GL_NONE or GL_BACK");
10908 GLenum mapped_buf = bufs[0];
10909 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
10910 bufs[0] == GL_BACK) {
10911 mapped_buf = GL_COLOR_ATTACHMENT0;
10913 glDrawBuffersARB(count, &mapped_buf);
10914 group_->set_draw_buffer(bufs[0]);
10918 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current, GLenum other) {
10919 group_->LoseContexts(other);
10920 reset_status_ = current;
10921 current_decoder_error_ = error::kLostContext;
10924 void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode,
10925 const GLfloat* matrix) {
10926 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
10927 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
10928 if (!features().chromium_path_rendering) {
10929 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10930 "glMatrixLoadfCHROMIUM",
10931 "function not available");
10935 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
10936 ? state_.projection_matrix
10937 : state_.modelview_matrix;
10938 memcpy(target_matrix, matrix, sizeof(GLfloat) * 16);
10939 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
10940 // since the values of the _NV and _CHROMIUM tokens match.
10941 glMatrixLoadfEXT(matrix_mode, matrix);
10944 void GLES2DecoderImpl::DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode) {
10945 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
10946 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
10948 if (!features().chromium_path_rendering) {
10949 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10950 "glMatrixLoadIdentityCHROMIUM",
10951 "function not available");
10955 static GLfloat kIdentityMatrix[16] = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
10956 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
10957 0.0f, 0.0f, 0.0f, 1.0f};
10959 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
10960 ? state_.projection_matrix
10961 : state_.modelview_matrix;
10962 memcpy(target_matrix, kIdentityMatrix, sizeof(kIdentityMatrix));
10963 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
10964 // since the values of the _NV and _CHROMIUM tokens match.
10965 glMatrixLoadIdentityEXT(matrix_mode);
10968 bool GLES2DecoderImpl::ValidateAsyncTransfer(
10969 const char* function_name,
10970 TextureRef* texture_ref,
10973 const void * data) {
10974 // We only support async uploads to 2D textures for now.
10975 if (GL_TEXTURE_2D != target) {
10976 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
10979 // We only support uploads to level zero for now.
10981 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "level != 0");
10984 // A transfer buffer must be bound, even for asyncTexImage2D.
10985 if (data == NULL) {
10986 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "buffer == 0");
10989 // We only support one async transfer in progress.
10990 if (!texture_ref ||
10991 async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
10992 LOCAL_SET_GL_ERROR(
10993 GL_INVALID_OPERATION,
10994 function_name, "transfer already in progress");
11000 base::Closure GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
11001 uint32 async_upload_token,
11002 uint32 sync_data_shm_id,
11003 uint32 sync_data_shm_offset) {
11004 scoped_refptr<gpu::Buffer> buffer = GetSharedMemoryBuffer(sync_data_shm_id);
11005 if (!buffer.get() ||
11006 !buffer->GetDataAddress(sync_data_shm_offset, sizeof(AsyncUploadSync)))
11007 return base::Closure();
11009 AsyncMemoryParams mem_params(buffer,
11010 sync_data_shm_offset,
11011 sizeof(AsyncUploadSync));
11013 scoped_refptr<AsyncUploadTokenCompletionObserver> observer(
11014 new AsyncUploadTokenCompletionObserver(async_upload_token));
11017 &AsyncPixelTransferManager::AsyncNotifyCompletion,
11018 base::Unretained(GetAsyncPixelTransferManager()),
11023 error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
11024 uint32 immediate_data_size,
11025 const void* cmd_data) {
11026 const gles2::cmds::AsyncTexImage2DCHROMIUM& c =
11027 *static_cast<const gles2::cmds::AsyncTexImage2DCHROMIUM*>(cmd_data);
11028 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
11029 GLenum target = static_cast<GLenum>(c.target);
11030 GLint level = static_cast<GLint>(c.level);
11031 GLenum internal_format = static_cast<GLenum>(c.internalformat);
11032 GLsizei width = static_cast<GLsizei>(c.width);
11033 GLsizei height = static_cast<GLsizei>(c.height);
11034 GLint border = static_cast<GLint>(c.border);
11035 GLenum format = static_cast<GLenum>(c.format);
11036 GLenum type = static_cast<GLenum>(c.type);
11037 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
11038 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
11039 uint32 pixels_size;
11040 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
11041 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
11042 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
11044 base::ScopedClosureRunner scoped_completion_callback;
11045 if (async_upload_token) {
11046 base::Closure completion_closure =
11047 AsyncUploadTokenCompletionClosure(async_upload_token,
11049 sync_data_shm_offset);
11050 if (completion_closure.is_null())
11051 return error::kInvalidArguments;
11053 scoped_completion_callback.Reset(completion_closure);
11056 // TODO(epenner): Move this and copies of this memory validation
11057 // into ValidateTexImage2D step.
11058 if (!GLES2Util::ComputeImageDataSizes(
11059 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
11061 return error::kOutOfBounds;
11063 const void* pixels = NULL;
11064 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
11065 pixels = GetSharedMemoryAs<const void*>(
11066 pixels_shm_id, pixels_shm_offset, pixels_size);
11068 return error::kOutOfBounds;
11072 TextureManager::DoTextImage2DArguments args = {
11073 target, level, internal_format, width, height, border, format, type,
11074 pixels, pixels_size};
11075 TextureRef* texture_ref;
11076 // All the normal glTexSubImage2D validation.
11077 if (!texture_manager()->ValidateTexImage2D(
11078 &state_, "glAsyncTexImage2DCHROMIUM", args, &texture_ref)) {
11079 return error::kNoError;
11082 // Extra async validation.
11083 Texture* texture = texture_ref->texture();
11084 if (!ValidateAsyncTransfer(
11085 "glAsyncTexImage2DCHROMIUM", texture_ref, target, level, pixels))
11086 return error::kNoError;
11088 // Don't allow async redefinition of a textures.
11089 if (texture->IsDefined()) {
11090 LOCAL_SET_GL_ERROR(
11091 GL_INVALID_OPERATION,
11092 "glAsyncTexImage2DCHROMIUM", "already defined");
11093 return error::kNoError;
11096 if (!EnsureGPUMemoryAvailable(pixels_size)) {
11097 LOCAL_SET_GL_ERROR(
11098 GL_OUT_OF_MEMORY, "glAsyncTexImage2DCHROMIUM", "out of memory");
11099 return error::kNoError;
11102 // Setup the parameters.
11103 AsyncTexImage2DParams tex_params = {
11104 target, level, static_cast<GLenum>(internal_format),
11105 width, height, border, format, type};
11106 AsyncMemoryParams mem_params(
11107 GetSharedMemoryBuffer(c.pixels_shm_id), c.pixels_shm_offset, pixels_size);
11109 // Set up the async state if needed, and make the texture
11110 // immutable so the async state stays valid. The level info
11111 // is set up lazily when the transfer completes.
11112 AsyncPixelTransferDelegate* delegate =
11113 async_pixel_transfer_manager_->CreatePixelTransferDelegate(texture_ref,
11115 texture->SetImmutable(true);
11117 delegate->AsyncTexImage2D(
11120 base::Bind(&TextureManager::SetLevelInfoFromParams,
11121 // The callback is only invoked if the transfer delegate still
11122 // exists, which implies through manager->texture_ref->state
11123 // ownership that both of these pointers are valid.
11124 base::Unretained(texture_manager()),
11125 base::Unretained(texture_ref),
11127 return error::kNoError;
11130 error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
11131 uint32 immediate_data_size,
11132 const void* cmd_data) {
11133 const gles2::cmds::AsyncTexSubImage2DCHROMIUM& c =
11134 *static_cast<const gles2::cmds::AsyncTexSubImage2DCHROMIUM*>(cmd_data);
11135 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
11136 GLenum target = static_cast<GLenum>(c.target);
11137 GLint level = static_cast<GLint>(c.level);
11138 GLint xoffset = static_cast<GLint>(c.xoffset);
11139 GLint yoffset = static_cast<GLint>(c.yoffset);
11140 GLsizei width = static_cast<GLsizei>(c.width);
11141 GLsizei height = static_cast<GLsizei>(c.height);
11142 GLenum format = static_cast<GLenum>(c.format);
11143 GLenum type = static_cast<GLenum>(c.type);
11144 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
11145 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
11146 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
11148 base::ScopedClosureRunner scoped_completion_callback;
11149 if (async_upload_token) {
11150 base::Closure completion_closure =
11151 AsyncUploadTokenCompletionClosure(async_upload_token,
11153 sync_data_shm_offset);
11154 if (completion_closure.is_null())
11155 return error::kInvalidArguments;
11157 scoped_completion_callback.Reset(completion_closure);
11160 // TODO(epenner): Move this and copies of this memory validation
11161 // into ValidateTexSubImage2D step.
11163 if (!GLES2Util::ComputeImageDataSizes(
11164 width, height, format, type, state_.unpack_alignment, &data_size,
11166 return error::kOutOfBounds;
11168 const void* pixels = GetSharedMemoryAs<const void*>(
11169 c.data_shm_id, c.data_shm_offset, data_size);
11171 // All the normal glTexSubImage2D validation.
11172 error::Error error = error::kNoError;
11173 if (!ValidateTexSubImage2D(&error, "glAsyncTexSubImage2DCHROMIUM",
11174 target, level, xoffset, yoffset, width, height, format, type, pixels)) {
11178 // Extra async validation.
11179 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
11181 Texture* texture = texture_ref->texture();
11182 if (!ValidateAsyncTransfer(
11183 "glAsyncTexSubImage2DCHROMIUM", texture_ref, target, level, pixels))
11184 return error::kNoError;
11186 // Guarantee async textures are always 'cleared' as follows:
11187 // - AsyncTexImage2D can not redefine an existing texture
11188 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
11189 // - AsyncTexSubImage2D clears synchronously if not already cleared.
11190 // - Textures become immutable after an async call.
11191 // This way we know in all cases that an async texture is always clear.
11192 if (!texture->SafeToRenderFrom()) {
11193 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
11195 LOCAL_SET_GL_ERROR(
11197 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
11198 return error::kNoError;
11202 // Setup the parameters.
11203 AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset,
11204 width, height, format, type};
11205 AsyncMemoryParams mem_params(
11206 GetSharedMemoryBuffer(c.data_shm_id), c.data_shm_offset, data_size);
11207 AsyncPixelTransferDelegate* delegate =
11208 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
11210 // TODO(epenner): We may want to enforce exclusive use
11211 // of async APIs in which case this should become an error,
11212 // (the texture should have been async defined).
11213 AsyncTexImage2DParams define_params = {target, level,
11215 texture->GetLevelSize(target, level, &define_params.width,
11216 &define_params.height);
11217 texture->GetLevelType(target, level, &define_params.type,
11218 &define_params.internal_format);
11219 // Set up the async state if needed, and make the texture
11220 // immutable so the async state stays valid.
11221 delegate = async_pixel_transfer_manager_->CreatePixelTransferDelegate(
11222 texture_ref, define_params);
11223 texture->SetImmutable(true);
11226 delegate->AsyncTexSubImage2D(tex_params, mem_params);
11227 return error::kNoError;
11230 error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
11231 uint32 immediate_data_size,
11232 const void* cmd_data) {
11233 const gles2::cmds::WaitAsyncTexImage2DCHROMIUM& c =
11234 *static_cast<const gles2::cmds::WaitAsyncTexImage2DCHROMIUM*>(cmd_data);
11235 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
11236 GLenum target = static_cast<GLenum>(c.target);
11238 if (GL_TEXTURE_2D != target) {
11239 LOCAL_SET_GL_ERROR(
11240 GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target");
11241 return error::kNoError;
11243 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
11245 if (!texture_ref) {
11246 LOCAL_SET_GL_ERROR(
11247 GL_INVALID_OPERATION,
11248 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
11249 return error::kNoError;
11251 AsyncPixelTransferDelegate* delegate =
11252 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
11254 LOCAL_SET_GL_ERROR(
11255 GL_INVALID_OPERATION,
11256 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
11257 return error::kNoError;
11259 delegate->WaitForTransferCompletion();
11260 ProcessFinishedAsyncTransfers();
11261 return error::kNoError;
11264 error::Error GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
11265 uint32 immediate_data_size,
11266 const void* data) {
11267 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
11269 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
11270 ProcessFinishedAsyncTransfers();
11271 return error::kNoError;
11274 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
11275 TextureRef* texture_ref) {
11276 Texture* texture = texture_ref->texture();
11277 DoDidUseTexImageIfNeeded(texture, texture->target());
11280 void GLES2DecoderImpl::OnOutOfMemoryError() {
11281 if (lose_context_when_out_of_memory_) {
11282 group_->LoseContexts(GL_UNKNOWN_CONTEXT_RESET_ARB);
11283 LoseContext(GL_GUILTY_CONTEXT_RESET_ARB);
11287 // Include the auto-generated part of this file. We split this because it means
11288 // we can easily edit the non-auto generated parts right here in this file
11289 // instead of having to edit some template or the code generator.
11290 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
11292 } // namespace gles2