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/memory/scoped_ptr.h"
23 #include "base/numerics/safe_math.h"
24 #include "base/strings/string_number_conversions.h"
25 #include "base/strings/string_split.h"
26 #include "build/build_config.h"
27 #define GLES2_GPU_SERVICE 1
28 #include "gpu/command_buffer/common/debug_marker_manager.h"
29 #include "gpu/command_buffer/common/gles2_cmd_format.h"
30 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
31 #include "gpu/command_buffer/common/id_allocator.h"
32 #include "gpu/command_buffer/common/mailbox.h"
33 #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
34 #include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
35 #include "gpu/command_buffer/service/buffer_manager.h"
36 #include "gpu/command_buffer/service/cmd_buffer_engine.h"
37 #include "gpu/command_buffer/service/context_group.h"
38 #include "gpu/command_buffer/service/context_state.h"
39 #include "gpu/command_buffer/service/error_state.h"
40 #include "gpu/command_buffer/service/feature_info.h"
41 #include "gpu/command_buffer/service/framebuffer_manager.h"
42 #include "gpu/command_buffer/service/gl_utils.h"
43 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
44 #include "gpu/command_buffer/service/gles2_cmd_validation.h"
45 #include "gpu/command_buffer/service/gpu_state_tracer.h"
46 #include "gpu/command_buffer/service/gpu_switches.h"
47 #include "gpu/command_buffer/service/gpu_tracer.h"
48 #include "gpu/command_buffer/service/image_manager.h"
49 #include "gpu/command_buffer/service/mailbox_manager.h"
50 #include "gpu/command_buffer/service/memory_tracking.h"
51 #include "gpu/command_buffer/service/program_manager.h"
52 #include "gpu/command_buffer/service/query_manager.h"
53 #include "gpu/command_buffer/service/renderbuffer_manager.h"
54 #include "gpu/command_buffer/service/shader_manager.h"
55 #include "gpu/command_buffer/service/shader_translator.h"
56 #include "gpu/command_buffer/service/shader_translator_cache.h"
57 #include "gpu/command_buffer/service/texture_manager.h"
58 #include "gpu/command_buffer/service/vertex_array_manager.h"
59 #include "gpu/command_buffer/service/vertex_attrib_manager.h"
60 #include "third_party/smhasher/src/City.h"
61 #include "ui/gl/gl_bindings.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 #if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
88 khronos_uint64_t CityHashForAngle(const char* name, unsigned int len) {
89 return static_cast<khronos_uint64_t>(
90 CityHash64(name, static_cast<size_t>(len)));
94 static bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin,
97 return (rangeMin >= 62) && (rangeMax >= 62) && (precision >= 16);
100 static void GetShaderPrecisionFormatImpl(GLenum shader_type,
101 GLenum precision_type,
102 GLint *range, GLint *precision) {
103 switch (precision_type) {
107 // These values are for a 32-bit twos-complement integer format.
113 case GL_MEDIUM_FLOAT:
115 // These values are for an IEEE single-precision floating-point format.
125 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
126 gfx::g_driver_gl.fn.glGetShaderPrecisionFormatFn) {
127 // This function is sometimes defined even though it's really just
128 // a stub, so we need to set range and precision as if it weren't
129 // defined before calling it.
130 // On Mac OS with some GPUs, calling this generates a
131 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
133 glGetShaderPrecisionFormat(shader_type, precision_type,
136 // TODO(brianderson): Make the following official workarounds.
138 // Some drivers have bugs where they report the ranges as a negative number.
139 // Taking the absolute value here shouldn't hurt because negative numbers
140 // aren't expected anyway.
141 range[0] = abs(range[0]);
142 range[1] = abs(range[1]);
144 // If the driver reports a precision for highp float that isn't actually
145 // highp, don't pretend like it's supported because shader compilation will
147 if (precision_type == GL_HIGH_FLOAT &&
148 !PrecisionMeetsSpecForHighpFloat(range[0], range[1], *precision)) {
158 class GLES2DecoderImpl;
160 // Local versions of the SET_GL_ERROR macros
161 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
162 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
163 #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
164 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
165 function_name, value, label)
166 #define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
167 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
168 function_name, pname)
169 #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
170 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
172 #define LOCAL_PEEK_GL_ERROR(function_name) \
173 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
174 #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
175 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
176 #define LOCAL_PERFORMANCE_WARNING(msg) \
177 PerformanceWarning(__FILE__, __LINE__, msg)
178 #define LOCAL_RENDER_WARNING(msg) \
179 RenderWarning(__FILE__, __LINE__, msg)
181 // Check that certain assumptions the code makes are true. There are places in
182 // the code where shared memory is passed direclty to GL. Example, glUniformiv,
183 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
184 // a few others) are 32bits. If they are not 32bits the code will have to change
185 // to call those GL functions with service side memory and then copy the results
186 // to shared memory, converting the sizes.
187 COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
188 GLint_not_same_size_as_uint32);
189 COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
190 GLint_not_same_size_as_uint32);
191 COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
192 GLfloat_not_same_size_as_float);
194 // TODO(kbr): the use of this anonymous namespace core dumps the
195 // linker on Mac OS X 10.6 when the symbol ordering file is used
198 // Returns the address of the first byte after a struct.
199 template <typename T>
200 const void* AddressAfterStruct(const T& pod) {
201 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
204 // Returns the address of the frst byte after the struct or NULL if size >
205 // immediate_data_size.
206 template <typename RETURN_TYPE, typename COMMAND_TYPE>
207 RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
209 uint32 immediate_data_size) {
210 return (size <= immediate_data_size) ?
211 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
215 // Computes the data size for certain gl commands like glUniform.
216 bool ComputeDataSize(
219 unsigned int elements_per_unit,
222 if (!SafeMultiplyUint32(count, size, &value)) {
225 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
232 // A struct to hold info about each command.
234 uint8 arg_flags; // How to handle the arguments for this command
235 uint8 cmd_flags; // How to handle this command
236 uint16 arg_count; // How many arguments are expected for this command.
239 // cmds::name::cmd_flags,
240 // A table of CommandInfo for all the commands.
241 const CommandInfo g_command_info[] = {
242 #define GLES2_CMD_OP(name) { \
243 cmds::name::kArgFlags, \
244 cmds::name::cmd_flags, \
245 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */
247 GLES2_COMMAND_LIST(GLES2_CMD_OP)
252 // Return true if a character belongs to the ASCII subset as defined in
253 // GLSL ES 1.0 spec section 3.1.
254 static bool CharacterIsValidForGLES(unsigned char c) {
255 // Printing characters are valid except " $ ` @ \ ' DEL.
256 if (c >= 32 && c <= 126 &&
265 // Horizontal tab, line feed, vertical tab, form feed, carriage return
267 if (c >= 9 && c <= 13) {
274 static bool StringIsValidForGLES(const char* str) {
275 for (; *str; ++str) {
276 if (!CharacterIsValidForGLES(*str)) {
283 // This class prevents any GL errors that occur when it is in scope from
284 // being reported to the client.
285 class ScopedGLErrorSuppressor {
287 explicit ScopedGLErrorSuppressor(
288 const char* function_name, ErrorState* error_state);
289 ~ScopedGLErrorSuppressor();
291 const char* function_name_;
292 ErrorState* error_state_;
293 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
296 // Temporarily changes a decoder's bound texture and restore it when this
297 // object goes out of scope. Also temporarily switches to using active texture
298 // unit zero in case the client has changed that to something invalid.
299 class ScopedTextureBinder {
301 explicit ScopedTextureBinder(ContextState* state, GLuint id, GLenum target);
302 ~ScopedTextureBinder();
305 ContextState* state_;
307 DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder);
310 // Temporarily changes a decoder's bound render buffer and restore it when this
311 // object goes out of scope.
312 class ScopedRenderBufferBinder {
314 explicit ScopedRenderBufferBinder(ContextState* state, GLuint id);
315 ~ScopedRenderBufferBinder();
318 ContextState* state_;
319 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
322 // Temporarily changes a decoder's bound frame buffer and restore it when this
323 // object goes out of scope.
324 class ScopedFrameBufferBinder {
326 explicit ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
327 ~ScopedFrameBufferBinder();
330 GLES2DecoderImpl* decoder_;
331 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
334 // Temporarily changes a decoder's bound frame buffer to a resolved version of
335 // the multisampled offscreen render buffer if that buffer is multisampled, and,
336 // if it is bound or enforce_internal_framebuffer is true. If internal is
337 // true, the resolved framebuffer is not visible to the parent.
338 class ScopedResolvedFrameBufferBinder {
340 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
341 bool enforce_internal_framebuffer,
343 ~ScopedResolvedFrameBufferBinder();
346 GLES2DecoderImpl* decoder_;
347 bool resolve_and_bind_;
348 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
351 class ScopedModifyPixels {
353 explicit ScopedModifyPixels(TextureRef* ref);
354 ~ScopedModifyPixels();
360 ScopedModifyPixels::ScopedModifyPixels(TextureRef* ref) : ref_(ref) {
362 ref_->texture()->OnWillModifyPixels();
365 ScopedModifyPixels::~ScopedModifyPixels() {
367 ref_->texture()->OnDidModifyPixels();
370 class ScopedRenderTo {
372 explicit ScopedRenderTo(Framebuffer* framebuffer);
376 const Framebuffer* framebuffer_;
379 ScopedRenderTo::ScopedRenderTo(Framebuffer* framebuffer)
380 : framebuffer_(framebuffer) {
382 framebuffer_->OnWillRenderTo();
385 ScopedRenderTo::~ScopedRenderTo() {
387 framebuffer_->OnDidRenderTo();
390 // Encapsulates an OpenGL texture.
393 explicit BackTexture(MemoryTracker* memory_tracker, ContextState* state);
396 // Create a new render texture.
399 // Set the initial size and format of a render texture or resize it.
400 bool AllocateStorage(const gfx::Size& size, GLenum format, bool zero);
402 // Copy the contents of the currently bound frame buffer.
403 void Copy(const gfx::Size& size, GLenum format);
405 // Destroy the render texture. This must be explicitly called before
406 // destroying this object.
409 // Invalidate the texture. This can be used when a context is lost and it is
410 // not possible to make it current in order to free the resource.
417 gfx::Size size() const {
422 MemoryTypeTracker memory_tracker_;
423 ContextState* state_;
424 size_t bytes_allocated_;
427 DISALLOW_COPY_AND_ASSIGN(BackTexture);
430 // Encapsulates an OpenGL render buffer of any format.
431 class BackRenderbuffer {
433 explicit BackRenderbuffer(
434 RenderbufferManager* renderbuffer_manager,
435 MemoryTracker* memory_tracker,
436 ContextState* state);
439 // Create a new render buffer.
442 // Set the initial size and format of a render buffer or resize it.
443 bool AllocateStorage(const FeatureInfo* feature_info,
444 const gfx::Size& size,
448 // Destroy the render buffer. This must be explicitly called before destroying
452 // Invalidate the render buffer. This can be used when a context is lost and
453 // it is not possible to make it current in order to free the resource.
461 RenderbufferManager* renderbuffer_manager_;
462 MemoryTypeTracker memory_tracker_;
463 ContextState* state_;
464 size_t bytes_allocated_;
466 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer);
469 // Encapsulates an OpenGL frame buffer.
470 class BackFramebuffer {
472 explicit BackFramebuffer(GLES2DecoderImpl* decoder);
475 // Create a new frame buffer.
478 // Attach a color render buffer to a frame buffer.
479 void AttachRenderTexture(BackTexture* texture);
481 // Attach a render buffer to a frame buffer. Note that this unbinds any
482 // currently bound frame buffer.
483 void AttachRenderBuffer(GLenum target, BackRenderbuffer* render_buffer);
485 // Destroy the frame buffer. This must be explicitly called before destroying
489 // Invalidate the frame buffer. This can be used when a context is lost and it
490 // is not possible to make it current in order to free the resource.
493 // See glCheckFramebufferStatusEXT.
494 GLenum CheckStatus();
501 GLES2DecoderImpl* decoder_;
503 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer);
506 struct FenceCallback {
507 explicit FenceCallback()
508 : fence(gfx::GLFence::Create()) {
511 std::vector<base::Closure> callbacks;
512 scoped_ptr<gfx::GLFence> fence;
515 class AsyncUploadTokenCompletionObserver
516 : public AsyncPixelTransferCompletionObserver {
518 explicit AsyncUploadTokenCompletionObserver(uint32 async_upload_token)
519 : async_upload_token_(async_upload_token) {
522 virtual void DidComplete(const AsyncMemoryParams& mem_params) OVERRIDE {
523 DCHECK(mem_params.buffer());
524 void* data = mem_params.GetDataAddress();
525 AsyncUploadSync* sync = static_cast<AsyncUploadSync*>(data);
526 sync->SetAsyncUploadToken(async_upload_token_);
530 virtual ~AsyncUploadTokenCompletionObserver() {
533 uint32 async_upload_token_;
535 DISALLOW_COPY_AND_ASSIGN(AsyncUploadTokenCompletionObserver);
538 // } // anonymous namespace.
540 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
541 uint32* service_texture_id) {
545 GLES2Decoder::GLES2Decoder()
546 : initialized_(false),
548 log_commands_(false) {
551 GLES2Decoder::~GLES2Decoder() {
554 void GLES2Decoder::BeginDecoding() {}
556 void GLES2Decoder::EndDecoding() {}
558 // This class implements GLES2Decoder so we don't have to expose all the GLES2
559 // cmd stuff to outside this class.
560 class GLES2DecoderImpl : public GLES2Decoder,
561 public FramebufferManager::TextureDetachObserver,
562 public ErrorStateClient {
564 explicit GLES2DecoderImpl(ContextGroup* group);
565 virtual ~GLES2DecoderImpl();
567 // Overridden from AsyncAPIInterface.
568 virtual Error DoCommand(unsigned int command,
569 unsigned int arg_count,
570 const void* args) OVERRIDE;
572 // Overridden from AsyncAPIInterface.
573 virtual const char* GetCommandName(unsigned int command_id) const OVERRIDE;
575 // Overridden from GLES2Decoder.
576 virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
577 const scoped_refptr<gfx::GLContext>& context,
579 const gfx::Size& size,
580 const DisallowedFeatures& disallowed_features,
581 const std::vector<int32>& attribs) OVERRIDE;
582 virtual void Destroy(bool have_context) OVERRIDE;
583 virtual void SetSurface(
584 const scoped_refptr<gfx::GLSurface>& surface) OVERRIDE;
585 virtual void ProduceFrontBuffer(const Mailbox& mailbox) OVERRIDE;
586 virtual bool ResizeOffscreenFrameBuffer(const gfx::Size& size) OVERRIDE;
587 void UpdateParentTextureInfo();
588 virtual bool MakeCurrent() OVERRIDE;
589 virtual GLES2Util* GetGLES2Util() OVERRIDE { return &util_; }
590 virtual gfx::GLContext* GetGLContext() OVERRIDE { return context_.get(); }
591 virtual ContextGroup* GetContextGroup() OVERRIDE { return group_.get(); }
592 virtual Capabilities GetCapabilities() OVERRIDE;
593 virtual void RestoreState(const ContextState* prev_state) const OVERRIDE;
595 virtual void RestoreActiveTexture() const OVERRIDE {
596 state_.RestoreActiveTexture();
598 virtual void RestoreAllTextureUnitBindings(
599 const ContextState* prev_state) const OVERRIDE {
600 state_.RestoreAllTextureUnitBindings(prev_state);
602 virtual void RestoreActiveTextureUnitBinding(
603 unsigned int target) const OVERRIDE {
604 state_.RestoreActiveTextureUnitBinding(target);
606 virtual void RestoreBufferBindings() const OVERRIDE {
607 state_.RestoreBufferBindings();
609 virtual void RestoreGlobalState() const OVERRIDE {
610 state_.RestoreGlobalState(NULL);
612 virtual void RestoreProgramBindings() const OVERRIDE {
613 state_.RestoreProgramBindings();
615 virtual void RestoreTextureUnitBindings(unsigned unit) const OVERRIDE {
616 state_.RestoreTextureUnitBindings(unit, NULL);
618 virtual void RestoreFramebufferBindings() const OVERRIDE;
619 virtual void RestoreTextureState(unsigned service_id) const OVERRIDE;
621 virtual void ClearAllAttributes() const OVERRIDE;
622 virtual void RestoreAllAttributes() const OVERRIDE;
624 virtual QueryManager* GetQueryManager() OVERRIDE {
625 return query_manager_.get();
627 virtual VertexArrayManager* GetVertexArrayManager() OVERRIDE {
628 return vertex_array_manager_.get();
630 virtual bool ProcessPendingQueries() OVERRIDE;
631 virtual bool HasMoreIdleWork() OVERRIDE;
632 virtual void PerformIdleWork() OVERRIDE;
634 virtual void WaitForReadPixels(base::Closure callback) OVERRIDE;
636 virtual void SetResizeCallback(
637 const base::Callback<void(gfx::Size, float)>& callback) OVERRIDE;
639 virtual Logger* GetLogger() OVERRIDE;
641 virtual void BeginDecoding() OVERRIDE;
642 virtual void EndDecoding() OVERRIDE;
644 virtual ErrorState* GetErrorState() OVERRIDE;
645 virtual const ContextState* GetContextState() OVERRIDE { return &state_; }
647 virtual void SetShaderCacheCallback(
648 const ShaderCacheCallback& callback) OVERRIDE;
649 virtual void SetWaitSyncPointCallback(
650 const WaitSyncPointCallback& callback) OVERRIDE;
652 virtual AsyncPixelTransferManager*
653 GetAsyncPixelTransferManager() OVERRIDE;
654 virtual void ResetAsyncPixelTransferManagerForTest() OVERRIDE;
655 virtual void SetAsyncPixelTransferManagerForTest(
656 AsyncPixelTransferManager* manager) OVERRIDE;
657 virtual void SetIgnoreCachedStateForTest(bool ignore) OVERRIDE;
658 void ProcessFinishedAsyncTransfers();
660 virtual bool GetServiceTextureId(uint32 client_texture_id,
661 uint32* service_texture_id) OVERRIDE;
663 virtual uint32 GetTextureUploadCount() OVERRIDE;
664 virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE;
665 virtual base::TimeDelta GetTotalProcessingCommandsTime() OVERRIDE;
666 virtual void AddProcessingCommandsTime(base::TimeDelta) OVERRIDE;
668 // Restores the current state to the user's settings.
669 void RestoreCurrentFramebufferBindings();
671 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
672 void ApplyDirtyState();
674 // These check the state of the currently bound framebuffer or the
675 // backbuffer if no framebuffer is bound.
676 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
677 // check with all attached and enabled color attachments.
678 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers);
679 bool BoundFramebufferHasDepthAttachment();
680 bool BoundFramebufferHasStencilAttachment();
682 virtual error::ContextLostReason GetContextLostReason() OVERRIDE;
684 // Overridden from FramebufferManager::TextureDetachObserver:
685 virtual void OnTextureRefDetachedFromFramebuffer(
686 TextureRef* texture) OVERRIDE;
688 // Overriden from ErrorStateClient.
689 virtual void OnOutOfMemoryError() OVERRIDE;
691 // Helpers to facilitate calling into compatible extensions.
692 static void RenderbufferStorageMultisampleHelper(
693 const FeatureInfo* feature_info,
696 GLenum internal_format,
700 void BlitFramebufferHelper(GLint srcX0,
712 friend class ScopedFrameBufferBinder;
713 friend class ScopedResolvedFrameBufferBinder;
714 friend class BackFramebuffer;
716 // Initialize or re-initialize the shader translator.
717 bool InitializeShaderTranslator();
719 void UpdateCapabilities();
721 // Helpers for the glGen and glDelete functions.
722 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
723 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
724 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
725 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
726 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
727 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
728 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
729 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
730 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
731 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
732 bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
733 void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
735 // Helper for async upload token completion notification callback.
736 base::Closure AsyncUploadTokenCompletionClosure(uint32 async_upload_token,
737 uint32 sync_data_shm_id,
738 uint32 sync_data_shm_offset);
743 void OnFboChanged() const;
744 void OnUseFramebuffer() const;
746 // TODO(gman): Cache these pointers?
747 BufferManager* buffer_manager() {
748 return group_->buffer_manager();
751 RenderbufferManager* renderbuffer_manager() {
752 return group_->renderbuffer_manager();
755 FramebufferManager* framebuffer_manager() {
756 return group_->framebuffer_manager();
759 ProgramManager* program_manager() {
760 return group_->program_manager();
763 ShaderManager* shader_manager() {
764 return group_->shader_manager();
767 ShaderTranslatorCache* shader_translator_cache() {
768 return group_->shader_translator_cache();
771 const TextureManager* texture_manager() const {
772 return group_->texture_manager();
775 TextureManager* texture_manager() {
776 return group_->texture_manager();
779 MailboxManager* mailbox_manager() {
780 return group_->mailbox_manager();
783 ImageManager* image_manager() {
784 return group_->image_manager();
787 VertexArrayManager* vertex_array_manager() {
788 return vertex_array_manager_.get();
791 MemoryTracker* memory_tracker() {
792 return group_->memory_tracker();
795 bool EnsureGPUMemoryAvailable(size_t estimated_size) {
796 MemoryTracker* tracker = memory_tracker();
798 return tracker->EnsureGPUMemoryAvailable(estimated_size);
803 bool IsOffscreenBufferMultisampled() const {
804 return offscreen_target_samples_ > 1;
807 // Creates a Texture for the given texture.
808 TextureRef* CreateTexture(
809 GLuint client_id, GLuint service_id) {
810 return texture_manager()->CreateTexture(client_id, service_id);
813 // Gets the texture info for the given texture. Returns NULL if none exists.
814 TextureRef* GetTexture(GLuint client_id) const {
815 return texture_manager()->GetTexture(client_id);
818 // Deletes the texture info for the given texture.
819 void RemoveTexture(GLuint client_id) {
820 texture_manager()->RemoveTexture(client_id);
823 // Get the size (in pixels) of the currently bound frame buffer (either FBO
824 // or regular back buffer).
825 gfx::Size GetBoundReadFrameBufferSize();
827 // Get the format of the currently bound frame buffer (either FBO or regular
829 GLenum GetBoundReadFrameBufferTextureType();
830 GLenum GetBoundReadFrameBufferInternalFormat();
831 GLenum GetBoundDrawFrameBufferInternalFormat();
833 // Wrapper for CompressedTexImage2D commands.
834 error::Error DoCompressedTexImage2D(
837 GLenum internal_format,
844 // Wrapper for CompressedTexSubImage2D.
845 void DoCompressedTexSubImage2D(
856 // Wrapper for CopyTexImage2D.
857 void DoCopyTexImage2D(
860 GLenum internal_format,
867 // Wrapper for SwapBuffers.
868 void DoSwapBuffers();
870 // Wrapper for CopyTexSubImage2D.
871 void DoCopyTexSubImage2D(
881 // Validation for TexSubImage2D.
882 bool ValidateTexSubImage2D(
884 const char* function_name,
895 // Wrapper for TexSubImage2D.
896 error::Error DoTexSubImage2D(
907 // Extra validation for async tex(Sub)Image2D.
908 bool ValidateAsyncTransfer(
909 const char* function_name,
910 TextureRef* texture_ref,
915 // Wrapper for TexImageIOSurface2DCHROMIUM.
916 void DoTexImageIOSurface2DCHROMIUM(
920 GLuint io_surface_id,
923 void DoCopyTextureCHROMIUM(
928 GLenum internal_format,
931 // Wrapper for TexStorage2DEXT.
932 void DoTexStorage2DEXT(
935 GLenum internal_format,
939 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
940 void DoProduceTextureDirectCHROMIUM(GLuint texture, GLenum target,
942 void ProduceTextureRef(std::string func_name, TextureRef* texture_ref,
943 GLenum target, const GLbyte* data);
945 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
946 void DoCreateAndConsumeTextureCHROMIUM(GLenum target, const GLbyte* key,
949 void DoBindTexImage2DCHROMIUM(
952 void DoReleaseTexImage2DCHROMIUM(
956 void DoTraceEndCHROMIUM(void);
958 void DoDrawBuffersEXT(GLsizei count, const GLenum* bufs);
960 void DoLoseContextCHROMIUM(GLenum current, GLenum other);
962 // Creates a Program for the given program.
963 Program* CreateProgram(
964 GLuint client_id, GLuint service_id) {
965 return program_manager()->CreateProgram(client_id, service_id);
968 // Gets the program info for the given program. Returns NULL if none exists.
969 Program* GetProgram(GLuint client_id) {
970 return program_manager()->GetProgram(client_id);
974 void LogClientServiceMapping(
975 const char* /* function_name */,
976 GLuint /* client_id */,
977 GLuint /* service_id */) {
980 void LogClientServiceForInfo(
981 T* /* info */, GLuint /* client_id */, const char* /* function_name */) {
984 void LogClientServiceMapping(
985 const char* function_name, GLuint client_id, GLuint service_id) {
986 if (service_logging_) {
987 VLOG(1) << "[" << logger_.GetLogPrefix() << "] " << function_name
988 << ": client_id = " << client_id
989 << ", service_id = " << service_id;
993 void LogClientServiceForInfo(
994 T* info, GLuint client_id, const char* function_name) {
996 LogClientServiceMapping(function_name, client_id, info->service_id());
1001 // Gets the program info for the given program. If it's not a program
1002 // generates a GL error. Returns NULL if not program.
1003 Program* GetProgramInfoNotShader(
1004 GLuint client_id, const char* function_name) {
1005 Program* program = GetProgram(client_id);
1007 if (GetShader(client_id)) {
1009 GL_INVALID_OPERATION, function_name, "shader passed for program");
1011 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown program");
1014 LogClientServiceForInfo(program, client_id, function_name);
1019 // Creates a Shader for the given shader.
1020 Shader* CreateShader(
1023 GLenum shader_type) {
1024 return shader_manager()->CreateShader(
1025 client_id, service_id, shader_type);
1028 // Gets the shader info for the given shader. Returns NULL if none exists.
1029 Shader* GetShader(GLuint client_id) {
1030 return shader_manager()->GetShader(client_id);
1033 // Gets the shader info for the given shader. If it's not a shader generates a
1034 // GL error. Returns NULL if not shader.
1035 Shader* GetShaderInfoNotProgram(
1036 GLuint client_id, const char* function_name) {
1037 Shader* shader = GetShader(client_id);
1039 if (GetProgram(client_id)) {
1041 GL_INVALID_OPERATION, function_name, "program passed for shader");
1044 GL_INVALID_VALUE, function_name, "unknown shader");
1047 LogClientServiceForInfo(shader, client_id, function_name);
1051 // Creates a buffer info for the given buffer.
1052 void CreateBuffer(GLuint client_id, GLuint service_id) {
1053 return buffer_manager()->CreateBuffer(client_id, service_id);
1056 // Gets the buffer info for the given buffer.
1057 Buffer* GetBuffer(GLuint client_id) {
1058 Buffer* buffer = buffer_manager()->GetBuffer(client_id);
1062 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1063 // on glDeleteBuffers so we can make sure the user does not try to render
1064 // with deleted buffers.
1065 void RemoveBuffer(GLuint client_id);
1067 // Creates a framebuffer info for the given framebuffer.
1068 void CreateFramebuffer(GLuint client_id, GLuint service_id) {
1069 return framebuffer_manager()->CreateFramebuffer(client_id, service_id);
1072 // Gets the framebuffer info for the given framebuffer.
1073 Framebuffer* GetFramebuffer(GLuint client_id) {
1074 return framebuffer_manager()->GetFramebuffer(client_id);
1077 // Removes the framebuffer info for the given framebuffer.
1078 void RemoveFramebuffer(GLuint client_id) {
1079 framebuffer_manager()->RemoveFramebuffer(client_id);
1082 // Creates a renderbuffer info for the given renderbuffer.
1083 void CreateRenderbuffer(GLuint client_id, GLuint service_id) {
1084 return renderbuffer_manager()->CreateRenderbuffer(
1085 client_id, service_id);
1088 // Gets the renderbuffer info for the given renderbuffer.
1089 Renderbuffer* GetRenderbuffer(GLuint client_id) {
1090 return renderbuffer_manager()->GetRenderbuffer(client_id);
1093 // Removes the renderbuffer info for the given renderbuffer.
1094 void RemoveRenderbuffer(GLuint client_id) {
1095 renderbuffer_manager()->RemoveRenderbuffer(client_id);
1098 // Gets the vertex attrib manager for the given vertex array.
1099 VertexAttribManager* GetVertexAttribManager(GLuint client_id) {
1100 VertexAttribManager* info =
1101 vertex_array_manager()->GetVertexAttribManager(client_id);
1105 // Removes the vertex attrib manager for the given vertex array.
1106 void RemoveVertexAttribManager(GLuint client_id) {
1107 vertex_array_manager()->RemoveVertexAttribManager(client_id);
1110 // Creates a vertex attrib manager for the given vertex array.
1111 scoped_refptr<VertexAttribManager> CreateVertexAttribManager(
1114 bool client_visible) {
1115 return vertex_array_manager()->CreateVertexAttribManager(
1116 client_id, service_id, group_->max_vertex_attribs(), client_visible);
1119 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
1120 void DoBindUniformLocationCHROMIUM(
1121 GLuint client_id, GLint location, const char* name);
1123 error::Error GetAttribLocationHelper(
1124 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1125 const std::string& name_str);
1127 error::Error GetUniformLocationHelper(
1128 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1129 const std::string& name_str);
1131 // Helper for glShaderSource.
1132 error::Error ShaderSourceHelper(
1133 GLuint client_id, const char* data, uint32 data_size);
1135 // Clear any textures used by the current program.
1136 bool ClearUnclearedTextures();
1138 // Clears any uncleared attachments attached to the given frame buffer.
1139 // Returns false if there was a generated GL error.
1140 void ClearUnclearedAttachments(GLenum target, Framebuffer* framebuffer);
1142 // overridden from GLES2Decoder
1143 virtual bool ClearLevel(unsigned service_id,
1144 unsigned bind_target,
1147 unsigned internal_format,
1152 bool is_texture_immutable) OVERRIDE;
1154 // Restore all GL state that affects clearing.
1155 void RestoreClearState();
1157 // Remembers the state of some capabilities.
1158 // Returns: true if glEnable/glDisable should actually be called.
1159 bool SetCapabilityState(GLenum cap, bool enabled);
1161 // Check that the currently bound framebuffers are valid.
1162 // Generates GL error if not.
1163 bool CheckBoundFramebuffersValid(const char* func_name);
1165 // Check if a framebuffer meets our requirements.
1166 bool CheckFramebufferValid(
1167 Framebuffer* framebuffer,
1169 const char* func_name);
1171 // Checks if the current program exists and is valid. If not generates the
1172 // appropriate GL error. Returns true if the current program is in a usable
1174 bool CheckCurrentProgram(const char* function_name);
1176 // Checks if the current program exists and is valid and that location is not
1177 // -1. If the current program is not valid generates the appropriate GL
1178 // error. Returns true if the current program is in a usable state and
1179 // location is not -1.
1180 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1182 // Gets the type of a uniform for a location in the current program. Sets GL
1183 // errors if the current program is not valid. Returns true if the current
1184 // program is valid and the location exists. Adjusts count so it
1185 // does not overflow the uniform.
1186 bool PrepForSetUniformByLocation(GLint fake_location,
1187 const char* function_name,
1188 Program::UniformApiType api_type,
1189 GLint* real_location,
1193 // Gets the service id for any simulated backbuffer fbo.
1194 GLuint GetBackbufferServiceId() const;
1196 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1197 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1199 // Helper for glGetVertexAttrib
1200 void GetVertexAttribHelper(
1201 const VertexAttrib* attrib, GLenum pname, GLint* param);
1203 // Wrapper for glCreateProgram
1204 bool CreateProgramHelper(GLuint client_id);
1206 // Wrapper for glCreateShader
1207 bool CreateShaderHelper(GLenum type, GLuint client_id);
1209 // Wrapper for glActiveTexture
1210 void DoActiveTexture(GLenum texture_unit);
1212 // Wrapper for glAttachShader
1213 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1215 // Wrapper for glBindBuffer since we need to track the current targets.
1216 void DoBindBuffer(GLenum target, GLuint buffer);
1218 // Wrapper for glBindFramebuffer since we need to track the current targets.
1219 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1221 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1222 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1224 // Wrapper for glBindTexture since we need to track the current targets.
1225 void DoBindTexture(GLenum target, GLuint texture);
1227 // Wrapper for glBindVertexArrayOES
1228 void DoBindVertexArrayOES(GLuint array);
1229 void EmulateVertexArrayState();
1231 // Wrapper for glBlitFramebufferCHROMIUM.
1232 void DoBlitFramebufferCHROMIUM(
1233 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1234 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1235 GLbitfield mask, GLenum filter);
1237 // Wrapper for glBufferSubData.
1238 void DoBufferSubData(
1239 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1241 // Wrapper for glCheckFramebufferStatus
1242 GLenum DoCheckFramebufferStatus(GLenum target);
1244 // Wrapper for glClear
1245 error::Error DoClear(GLbitfield mask);
1247 // Wrappers for various state.
1248 void DoDepthRangef(GLclampf znear, GLclampf zfar);
1249 void DoSampleCoverage(GLclampf value, GLboolean invert);
1251 // Wrapper for glCompileShader.
1252 void DoCompileShader(GLuint shader);
1254 // Helper for DeleteSharedIdsCHROMIUM commands.
1255 void DoDeleteSharedIdsCHROMIUM(
1256 GLuint namespace_id, GLsizei n, const GLuint* ids);
1258 // Wrapper for glDetachShader
1259 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1261 // Wrapper for glDisable
1262 void DoDisable(GLenum cap);
1264 // Wrapper for glDisableVertexAttribArray.
1265 void DoDisableVertexAttribArray(GLuint index);
1267 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1269 void DoDiscardFramebufferEXT(GLenum target,
1270 GLsizei numAttachments,
1271 const GLenum* attachments);
1273 // Wrapper for glEnable
1274 void DoEnable(GLenum cap);
1276 // Wrapper for glEnableVertexAttribArray.
1277 void DoEnableVertexAttribArray(GLuint index);
1279 // Wrapper for glFinish.
1282 // Wrapper for glFlush.
1285 // Wrapper for glFramebufferRenderbufffer.
1286 void DoFramebufferRenderbuffer(
1287 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1288 GLuint renderbuffer);
1290 // Wrapper for glFramebufferTexture2D.
1291 void DoFramebufferTexture2D(
1292 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1295 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1296 void DoFramebufferTexture2DMultisample(
1297 GLenum target, GLenum attachment, GLenum textarget,
1298 GLuint texture, GLint level, GLsizei samples);
1300 // Common implementation for both DoFramebufferTexture2D wrappers.
1301 void DoFramebufferTexture2DCommon(const char* name,
1302 GLenum target, GLenum attachment, GLenum textarget,
1303 GLuint texture, GLint level, GLsizei samples);
1305 // Wrapper for glGenerateMipmap
1306 void DoGenerateMipmap(GLenum target);
1308 // Helper for GenSharedIdsCHROMIUM commands.
1309 void DoGenSharedIdsCHROMIUM(
1310 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
1312 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1313 // to account for different pname values defined in different extension
1315 GLenum AdjustGetPname(GLenum pname);
1317 // Wrapper for DoGetBooleanv.
1318 void DoGetBooleanv(GLenum pname, GLboolean* params);
1320 // Wrapper for DoGetFloatv.
1321 void DoGetFloatv(GLenum pname, GLfloat* params);
1323 // Wrapper for glGetFramebufferAttachmentParameteriv.
1324 void DoGetFramebufferAttachmentParameteriv(
1325 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1327 // Wrapper for glGetIntegerv.
1328 void DoGetIntegerv(GLenum pname, GLint* params);
1330 // Gets the max value in a range in a buffer.
1331 GLuint DoGetMaxValueInBufferCHROMIUM(
1332 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1334 // Wrapper for glGetBufferParameteriv.
1335 void DoGetBufferParameteriv(
1336 GLenum target, GLenum pname, GLint* params);
1338 // Wrapper for glGetProgramiv.
1339 void DoGetProgramiv(
1340 GLuint program_id, GLenum pname, GLint* params);
1342 // Wrapper for glRenderbufferParameteriv.
1343 void DoGetRenderbufferParameteriv(
1344 GLenum target, GLenum pname, GLint* params);
1346 // Wrapper for glGetShaderiv
1347 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1349 // Wrappers for glGetTexParameter.
1350 void DoGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params);
1351 void DoGetTexParameteriv(GLenum target, GLenum pname, GLint* params);
1352 void InitTextureMaxAnisotropyIfNeeded(GLenum target, GLenum pname);
1354 // Wrappers for glGetVertexAttrib.
1355 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1356 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1358 // Wrappers for glIsXXX functions.
1359 bool DoIsEnabled(GLenum cap);
1360 bool DoIsBuffer(GLuint client_id);
1361 bool DoIsFramebuffer(GLuint client_id);
1362 bool DoIsProgram(GLuint client_id);
1363 bool DoIsRenderbuffer(GLuint client_id);
1364 bool DoIsShader(GLuint client_id);
1365 bool DoIsTexture(GLuint client_id);
1366 bool DoIsVertexArrayOES(GLuint client_id);
1368 // Wrapper for glLinkProgram
1369 void DoLinkProgram(GLuint program);
1371 // Helper for RegisterSharedIdsCHROMIUM.
1372 void DoRegisterSharedIdsCHROMIUM(
1373 GLuint namespace_id, GLsizei n, const GLuint* ids);
1375 // Wrapper for glRenderbufferStorage.
1376 void DoRenderbufferStorage(
1377 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
1379 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1380 void DoRenderbufferStorageMultisampleCHROMIUM(
1381 GLenum target, GLsizei samples, GLenum internalformat,
1382 GLsizei width, GLsizei height);
1384 // Handler for glRenderbufferStorageMultisampleEXT
1385 // (multisampled_render_to_texture).
1386 void DoRenderbufferStorageMultisampleEXT(
1387 GLenum target, GLsizei samples, GLenum internalformat,
1388 GLsizei width, GLsizei height);
1390 // Common validation for multisample extensions.
1391 bool ValidateRenderbufferStorageMultisample(GLsizei samples,
1392 GLenum internalformat,
1396 // Verifies that the currently bound multisample renderbuffer is valid
1397 // Very slow! Only done on platforms with driver bugs that return invalid
1398 // buffers under memory pressure
1399 bool VerifyMultisampleRenderbufferIntegrity(
1400 GLuint renderbuffer, GLenum format);
1402 // Wrapper for glReleaseShaderCompiler.
1403 void DoReleaseShaderCompiler() { }
1405 // Wrappers for glTexParameter functions.
1406 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1407 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1408 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1409 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1411 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1412 // spec only these 2 functions can be used to set sampler uniforms.
1413 void DoUniform1i(GLint fake_location, GLint v0);
1414 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1415 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1416 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1417 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
1419 // Wrappers for glUniformfv because some drivers don't correctly accept
1421 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1422 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1423 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1424 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
1426 void DoUniformMatrix2fv(
1427 GLint fake_location, GLsizei count, GLboolean transpose,
1428 const GLfloat* value);
1429 void DoUniformMatrix3fv(
1430 GLint fake_location, GLsizei count, GLboolean transpose,
1431 const GLfloat* value);
1432 void DoUniformMatrix4fv(
1433 GLint fake_location, GLsizei count, GLboolean transpose,
1434 const GLfloat* value);
1436 bool SetVertexAttribValue(
1437 const char* function_name, GLuint index, const GLfloat* value);
1439 // Wrappers for glVertexAttrib??
1440 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1441 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1442 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1443 void DoVertexAttrib4f(
1444 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1445 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1446 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1447 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1448 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1450 // Wrapper for glViewport
1451 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1453 // Wrapper for glUseProgram
1454 void DoUseProgram(GLuint program);
1456 // Wrapper for glValidateProgram.
1457 void DoValidateProgram(GLuint program_client_id);
1459 void DoInsertEventMarkerEXT(GLsizei length, const GLchar* marker);
1460 void DoPushGroupMarkerEXT(GLsizei length, const GLchar* group);
1461 void DoPopGroupMarkerEXT(void);
1463 // Gets the number of values that will be returned by glGetXXX. Returns
1464 // false if pname is unknown.
1465 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1467 // Checks if the current program and vertex attributes are valid for drawing.
1469 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount);
1471 // Returns true if successful, simulated will be true if attrib0 was
1473 bool SimulateAttrib0(
1474 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
1475 void RestoreStateForAttrib(GLuint attrib, bool restore_array_binding);
1477 // If an image is bound to texture, this will call Will/DidUseTexImage
1479 void DoWillUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1480 void DoDidUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1482 // Returns false if textures were replaced.
1483 bool PrepareTexturesForRender();
1484 void RestoreStateForTextures();
1486 // Returns true if GL_FIXED attribs were simulated.
1487 bool SimulateFixedAttribs(
1488 const char* function_name,
1489 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
1490 void RestoreStateForSimulatedFixedAttribs();
1492 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1493 // cases (primcount is 0 for non-instanced).
1494 error::Error DoDrawArrays(
1495 const char* function_name,
1496 bool instanced, GLenum mode, GLint first, GLsizei count,
1498 error::Error DoDrawElements(
1499 const char* function_name,
1500 bool instanced, GLenum mode, GLsizei count, GLenum type,
1501 int32 offset, GLsizei primcount);
1503 GLenum GetBindTargetForSamplerType(GLenum type) {
1504 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
1505 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1508 return GL_TEXTURE_2D;
1509 case GL_SAMPLER_CUBE:
1510 return GL_TEXTURE_CUBE_MAP;
1511 case GL_SAMPLER_EXTERNAL_OES:
1512 return GL_TEXTURE_EXTERNAL_OES;
1513 case GL_SAMPLER_2D_RECT_ARB:
1514 return GL_TEXTURE_RECTANGLE_ARB;
1521 // Gets the framebuffer info for a particular target.
1522 Framebuffer* GetFramebufferInfoForTarget(GLenum target) {
1523 Framebuffer* framebuffer = NULL;
1525 case GL_FRAMEBUFFER:
1526 case GL_DRAW_FRAMEBUFFER_EXT:
1527 framebuffer = framebuffer_state_.bound_draw_framebuffer.get();
1529 case GL_READ_FRAMEBUFFER_EXT:
1530 framebuffer = framebuffer_state_.bound_read_framebuffer.get();
1539 Renderbuffer* GetRenderbufferInfoForTarget(
1541 Renderbuffer* renderbuffer = NULL;
1543 case GL_RENDERBUFFER:
1544 renderbuffer = state_.bound_renderbuffer.get();
1550 return renderbuffer;
1553 // Validates the program and location for a glGetUniform call and returns
1554 // a SizeResult setup to receive the result. Returns true if glGetUniform
1555 // should be called.
1556 bool GetUniformSetup(
1557 GLuint program, GLint fake_location,
1558 uint32 shm_id, uint32 shm_offset,
1559 error::Error* error, GLint* real_location, GLuint* service_id,
1560 void** result, GLenum* result_type);
1562 virtual bool WasContextLost() OVERRIDE;
1563 virtual bool WasContextLostByRobustnessExtension() OVERRIDE;
1564 virtual void LoseContext(uint32 reset_status) OVERRIDE;
1566 #if defined(OS_MACOSX)
1567 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1570 bool ValidateCompressedTexDimensions(
1571 const char* function_name,
1572 GLint level, GLsizei width, GLsizei height, GLenum format);
1573 bool ValidateCompressedTexFuncData(
1574 const char* function_name,
1575 GLsizei width, GLsizei height, GLenum format, size_t size);
1576 bool ValidateCompressedTexSubDimensions(
1577 const char* function_name,
1578 GLenum target, GLint level, GLint xoffset, GLint yoffset,
1579 GLsizei width, GLsizei height, GLenum format,
1582 void RenderWarning(const char* filename, int line, const std::string& msg);
1583 void PerformanceWarning(
1584 const char* filename, int line, const std::string& msg);
1586 const FeatureInfo::FeatureFlags& features() const {
1587 return feature_info_->feature_flags();
1590 const FeatureInfo::Workarounds& workarounds() const {
1591 return feature_info_->workarounds();
1594 bool ShouldDeferDraws() {
1595 return !offscreen_target_frame_buffer_.get() &&
1596 framebuffer_state_.bound_draw_framebuffer.get() == NULL &&
1597 surface_->DeferDraws();
1600 bool ShouldDeferReads() {
1601 return !offscreen_target_frame_buffer_.get() &&
1602 framebuffer_state_.bound_read_framebuffer.get() == NULL &&
1603 surface_->DeferDraws();
1606 error::Error WillAccessBoundFramebufferForDraw() {
1607 if (ShouldDeferDraws())
1608 return error::kDeferCommandUntilLater;
1609 if (!offscreen_target_frame_buffer_.get() &&
1610 !framebuffer_state_.bound_draw_framebuffer.get() &&
1611 !surface_->SetBackbufferAllocation(true))
1612 return error::kLostContext;
1613 return error::kNoError;
1616 error::Error WillAccessBoundFramebufferForRead() {
1617 if (ShouldDeferReads())
1618 return error::kDeferCommandUntilLater;
1619 if (!offscreen_target_frame_buffer_.get() &&
1620 !framebuffer_state_.bound_read_framebuffer.get() &&
1621 !surface_->SetBackbufferAllocation(true))
1622 return error::kLostContext;
1623 return error::kNoError;
1626 void ProcessPendingReadPixels();
1627 void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
1629 // Generate a member function prototype for each command in an automated and
1631 #define GLES2_CMD_OP(name) \
1632 Error Handle ## name( \
1633 uint32 immediate_data_size, \
1634 const cmds::name& args); \
1636 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1640 // The GL context this decoder renders to on behalf of the client.
1641 scoped_refptr<gfx::GLSurface> surface_;
1642 scoped_refptr<gfx::GLContext> context_;
1644 // The ContextGroup for this decoder uses to track resources.
1645 scoped_refptr<ContextGroup> group_;
1647 DebugMarkerManager debug_marker_manager_;
1650 // All the state for this context.
1651 ContextState state_;
1653 // Current width and height of the offscreen frame buffer.
1654 gfx::Size offscreen_size_;
1656 // Util to help with GL.
1659 // unpack flip y as last set by glPixelStorei
1660 bool unpack_flip_y_;
1662 // unpack (un)premultiply alpha as last set by glPixelStorei
1663 bool unpack_premultiply_alpha_;
1664 bool unpack_unpremultiply_alpha_;
1666 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1667 GLuint attrib_0_buffer_id_;
1669 // The value currently in attrib_0.
1670 Vec4 attrib_0_value_;
1672 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1673 bool attrib_0_buffer_matches_value_;
1675 // The size of attrib 0.
1676 GLsizei attrib_0_size_;
1678 // The buffer used to simulate GL_FIXED attribs.
1679 GLuint fixed_attrib_buffer_id_;
1681 // The size of fiixed attrib buffer.
1682 GLsizei fixed_attrib_buffer_size_;
1684 // The offscreen frame buffer that the client renders to. With EGL, the
1685 // depth and stencil buffers are separate. With regular GL there is a single
1686 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1687 // offscreen_target_stencil_render_buffer_ is unused.
1688 scoped_ptr<BackFramebuffer> offscreen_target_frame_buffer_;
1689 scoped_ptr<BackTexture> offscreen_target_color_texture_;
1690 scoped_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_;
1691 scoped_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_;
1692 scoped_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_;
1693 GLenum offscreen_target_color_format_;
1694 GLenum offscreen_target_depth_format_;
1695 GLenum offscreen_target_stencil_format_;
1696 GLsizei offscreen_target_samples_;
1697 GLboolean offscreen_target_buffer_preserved_;
1699 // The copy that is saved when SwapBuffers is called.
1700 scoped_ptr<BackFramebuffer> offscreen_saved_frame_buffer_;
1701 scoped_ptr<BackTexture> offscreen_saved_color_texture_;
1702 scoped_refptr<TextureRef>
1703 offscreen_saved_color_texture_info_;
1705 // The copy that is used as the destination for multi-sample resolves.
1706 scoped_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_;
1707 scoped_ptr<BackTexture> offscreen_resolved_color_texture_;
1708 GLenum offscreen_saved_color_format_;
1710 scoped_ptr<QueryManager> query_manager_;
1712 scoped_ptr<VertexArrayManager> vertex_array_manager_;
1714 base::Callback<void(gfx::Size, float)> resize_callback_;
1716 WaitSyncPointCallback wait_sync_point_callback_;
1718 ShaderCacheCallback shader_cache_callback_;
1720 scoped_ptr<AsyncPixelTransferManager> async_pixel_transfer_manager_;
1722 // The format of the back buffer_
1723 GLenum back_buffer_color_format_;
1724 bool back_buffer_has_depth_;
1725 bool back_buffer_has_stencil_;
1727 // Backbuffer attachments that are currently undefined.
1728 uint32 backbuffer_needs_clear_bits_;
1730 // The current decoder error communicates the decoder error through command
1731 // processing functions that do not return the error value. Should be set only
1732 // if not returning an error.
1733 error::Error current_decoder_error_;
1735 bool use_shader_translator_;
1736 scoped_refptr<ShaderTranslator> vertex_translator_;
1737 scoped_refptr<ShaderTranslator> fragment_translator_;
1739 DisallowedFeatures disallowed_features_;
1741 // Cached from ContextGroup
1742 const Validators* validators_;
1743 scoped_refptr<FeatureInfo> feature_info_;
1747 bool has_robustness_extension_;
1748 GLenum reset_status_;
1749 bool reset_by_robustness_extension_;
1750 bool supports_post_sub_buffer_;
1752 // These flags are used to override the state of the shared feature_info_
1753 // member. Because the same FeatureInfo instance may be shared among many
1754 // contexts, the assumptions on the availablity of extensions in WebGL
1755 // contexts may be broken. These flags override the shared state to preserve
1757 bool force_webgl_glsl_validation_;
1758 bool derivatives_explicitly_enabled_;
1759 bool frag_depth_explicitly_enabled_;
1760 bool draw_buffers_explicitly_enabled_;
1761 bool shader_texture_lod_explicitly_enabled_;
1763 bool compile_shader_always_succeeds_;
1765 // An optional behaviour to lose the context and group when OOM.
1766 bool lose_context_when_out_of_memory_;
1769 bool service_logging_;
1771 #if defined(OS_MACOSX)
1772 typedef std::map<GLuint, IOSurfaceRef> TextureToIOSurfaceMap;
1773 TextureToIOSurfaceMap texture_to_io_surface_map_;
1776 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
1778 // Cached values of the currently assigned viewport dimensions.
1779 GLsizei viewport_max_width_;
1780 GLsizei viewport_max_height_;
1782 // Command buffer stats.
1783 base::TimeDelta total_processing_commands_time_;
1785 // States related to each manager.
1786 DecoderTextureState texture_state_;
1787 DecoderFramebufferState framebuffer_state_;
1789 scoped_ptr<GPUTracer> gpu_tracer_;
1790 scoped_ptr<GPUStateTracer> gpu_state_tracer_;
1791 int gpu_trace_level_;
1792 bool gpu_trace_commands_;
1794 std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_;
1796 // Used to validate multisample renderbuffers if needed
1797 GLuint validation_texture_;
1798 GLuint validation_fbo_multisample_;
1799 GLuint validation_fbo_;
1801 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1804 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
1805 const char* function_name, ErrorState* error_state)
1806 : function_name_(function_name),
1807 error_state_(error_state) {
1808 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_, function_name_);
1811 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1812 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_, function_name_);
1815 static void RestoreCurrentTextureBindings(ContextState* state, GLenum target) {
1816 TextureUnit& info = state->texture_units[0];
1818 scoped_refptr<TextureRef> texture_ref;
1821 texture_ref = info.bound_texture_2d;
1823 case GL_TEXTURE_CUBE_MAP:
1824 texture_ref = info.bound_texture_cube_map;
1826 case GL_TEXTURE_EXTERNAL_OES:
1827 texture_ref = info.bound_texture_external_oes;
1829 case GL_TEXTURE_RECTANGLE_ARB:
1830 texture_ref = info.bound_texture_rectangle_arb;
1836 if (texture_ref.get()) {
1837 last_id = texture_ref->service_id();
1842 glBindTexture(target, last_id);
1843 glActiveTexture(GL_TEXTURE0 + state->active_texture_unit);
1846 ScopedTextureBinder::ScopedTextureBinder(ContextState* state,
1851 ScopedGLErrorSuppressor suppressor(
1852 "ScopedTextureBinder::ctor", state_->GetErrorState());
1854 // TODO(apatrick): Check if there are any other states that need to be reset
1855 // before binding a new texture.
1856 glActiveTexture(GL_TEXTURE0);
1857 glBindTexture(target, id);
1860 ScopedTextureBinder::~ScopedTextureBinder() {
1861 ScopedGLErrorSuppressor suppressor(
1862 "ScopedTextureBinder::dtor", state_->GetErrorState());
1863 RestoreCurrentTextureBindings(state_, target_);
1866 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState* state,
1869 ScopedGLErrorSuppressor suppressor(
1870 "ScopedRenderBufferBinder::ctor", state_->GetErrorState());
1871 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1874 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1875 ScopedGLErrorSuppressor suppressor(
1876 "ScopedRenderBufferBinder::dtor", state_->GetErrorState());
1877 state_->RestoreRenderbufferBindings();
1880 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1882 : decoder_(decoder) {
1883 ScopedGLErrorSuppressor suppressor(
1884 "ScopedFrameBufferBinder::ctor", decoder_->GetErrorState());
1885 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1886 decoder->OnFboChanged();
1889 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1890 ScopedGLErrorSuppressor suppressor(
1891 "ScopedFrameBufferBinder::dtor", decoder_->GetErrorState());
1892 decoder_->RestoreCurrentFramebufferBindings();
1895 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
1896 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
1897 : decoder_(decoder) {
1898 resolve_and_bind_ = (
1899 decoder_->offscreen_target_frame_buffer_.get() &&
1900 decoder_->IsOffscreenBufferMultisampled() &&
1901 (!decoder_->framebuffer_state_.bound_read_framebuffer.get() ||
1902 enforce_internal_framebuffer));
1903 if (!resolve_and_bind_)
1906 ScopedGLErrorSuppressor suppressor(
1907 "ScopedResolvedFrameBufferBinder::ctor", decoder_->GetErrorState());
1908 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1909 decoder_->offscreen_target_frame_buffer_->id());
1912 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
1913 decoder_->offscreen_resolved_frame_buffer_.reset(
1914 new BackFramebuffer(decoder_));
1915 decoder_->offscreen_resolved_frame_buffer_->Create();
1916 decoder_->offscreen_resolved_color_texture_.reset(
1917 new BackTexture(decoder->memory_tracker(), &decoder->state_));
1918 decoder_->offscreen_resolved_color_texture_->Create();
1920 DCHECK(decoder_->offscreen_saved_color_format_);
1921 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
1922 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_,
1924 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
1925 decoder_->offscreen_resolved_color_texture_.get());
1926 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
1927 GL_FRAMEBUFFER_COMPLETE) {
1928 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
1929 << "because offscreen resolved FBO was incomplete.";
1933 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
1935 targetid = decoder_->offscreen_saved_frame_buffer_->id();
1937 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
1938 const int width = decoder_->offscreen_size_.width();
1939 const int height = decoder_->offscreen_size_.height();
1940 decoder->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
1941 decoder->BlitFramebufferHelper(0,
1949 GL_COLOR_BUFFER_BIT,
1951 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
1954 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1955 if (!resolve_and_bind_)
1958 ScopedGLErrorSuppressor suppressor(
1959 "ScopedResolvedFrameBufferBinder::dtor", decoder_->GetErrorState());
1960 decoder_->RestoreCurrentFramebufferBindings();
1961 if (decoder_->state_.enable_flags.scissor_test) {
1962 decoder_->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
1966 BackTexture::BackTexture(
1967 MemoryTracker* memory_tracker,
1968 ContextState* state)
1969 : memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
1971 bytes_allocated_(0),
1975 BackTexture::~BackTexture() {
1976 // This does not destroy the render texture because that would require that
1977 // the associated GL context was current. Just check that it was explicitly
1982 void BackTexture::Create() {
1983 ScopedGLErrorSuppressor suppressor("BackTexture::Create",
1984 state_->GetErrorState());
1986 glGenTextures(1, &id_);
1987 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
1988 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1989 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1990 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1991 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1993 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
1994 // never called on an offscreen context, no data will ever be uploaded to the
1995 // saved offscreen color texture (it is deferred until to when SwapBuffers
1996 // is called). My idea is that some nvidia drivers might have a bug where
1997 // deleting a texture that has never been populated might cause a
2000 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2002 bytes_allocated_ = 16u * 16u * 4u;
2003 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2006 bool BackTexture::AllocateStorage(
2007 const gfx::Size& size, GLenum format, bool zero) {
2009 ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage",
2010 state_->GetErrorState());
2011 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2012 uint32 image_size = 0;
2013 GLES2Util::ComputeImageDataSizes(
2014 size.width(), size.height(), format, GL_UNSIGNED_BYTE, 8, &image_size,
2017 if (!memory_tracker_.EnsureGPUMemoryAvailable(image_size)) {
2021 scoped_ptr<char[]> zero_data;
2023 zero_data.reset(new char[image_size]);
2024 memset(zero_data.get(), 0, image_size);
2027 glTexImage2D(GL_TEXTURE_2D,
2039 bool success = glGetError() == GL_NO_ERROR;
2041 memory_tracker_.TrackMemFree(bytes_allocated_);
2042 bytes_allocated_ = image_size;
2043 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2048 void BackTexture::Copy(const gfx::Size& size, GLenum format) {
2050 ScopedGLErrorSuppressor suppressor("BackTexture::Copy",
2051 state_->GetErrorState());
2052 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2053 glCopyTexImage2D(GL_TEXTURE_2D,
2062 void BackTexture::Destroy() {
2064 ScopedGLErrorSuppressor suppressor("BackTexture::Destroy",
2065 state_->GetErrorState());
2066 glDeleteTextures(1, &id_);
2069 memory_tracker_.TrackMemFree(bytes_allocated_);
2070 bytes_allocated_ = 0;
2073 void BackTexture::Invalidate() {
2077 BackRenderbuffer::BackRenderbuffer(
2078 RenderbufferManager* renderbuffer_manager,
2079 MemoryTracker* memory_tracker,
2080 ContextState* state)
2081 : renderbuffer_manager_(renderbuffer_manager),
2082 memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2084 bytes_allocated_(0),
2088 BackRenderbuffer::~BackRenderbuffer() {
2089 // This does not destroy the render buffer because that would require that
2090 // the associated GL context was current. Just check that it was explicitly
2095 void BackRenderbuffer::Create() {
2096 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create",
2097 state_->GetErrorState());
2099 glGenRenderbuffersEXT(1, &id_);
2102 bool BackRenderbuffer::AllocateStorage(const FeatureInfo* feature_info,
2103 const gfx::Size& size,
2106 ScopedGLErrorSuppressor suppressor(
2107 "BackRenderbuffer::AllocateStorage", state_->GetErrorState());
2108 ScopedRenderBufferBinder binder(state_, id_);
2110 uint32 estimated_size = 0;
2111 if (!renderbuffer_manager_->ComputeEstimatedRenderbufferSize(
2112 size.width(), size.height(), samples, format, &estimated_size)) {
2116 if (!memory_tracker_.EnsureGPUMemoryAvailable(estimated_size)) {
2121 glRenderbufferStorageEXT(GL_RENDERBUFFER,
2126 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info,
2133 bool success = glGetError() == GL_NO_ERROR;
2135 // Mark the previously allocated bytes as free.
2136 memory_tracker_.TrackMemFree(bytes_allocated_);
2137 bytes_allocated_ = estimated_size;
2138 // Track the newly allocated bytes.
2139 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2144 void BackRenderbuffer::Destroy() {
2146 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy",
2147 state_->GetErrorState());
2148 glDeleteRenderbuffersEXT(1, &id_);
2151 memory_tracker_.TrackMemFree(bytes_allocated_);
2152 bytes_allocated_ = 0;
2155 void BackRenderbuffer::Invalidate() {
2159 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl* decoder)
2160 : decoder_(decoder),
2164 BackFramebuffer::~BackFramebuffer() {
2165 // This does not destroy the frame buffer because that would require that
2166 // the associated GL context was current. Just check that it was explicitly
2171 void BackFramebuffer::Create() {
2172 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create",
2173 decoder_->GetErrorState());
2175 glGenFramebuffersEXT(1, &id_);
2178 void BackFramebuffer::AttachRenderTexture(BackTexture* texture) {
2180 ScopedGLErrorSuppressor suppressor(
2181 "BackFramebuffer::AttachRenderTexture", decoder_->GetErrorState());
2182 ScopedFrameBufferBinder binder(decoder_, id_);
2183 GLuint attach_id = texture ? texture->id() : 0;
2184 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2185 GL_COLOR_ATTACHMENT0,
2191 void BackFramebuffer::AttachRenderBuffer(GLenum target,
2192 BackRenderbuffer* render_buffer) {
2194 ScopedGLErrorSuppressor suppressor(
2195 "BackFramebuffer::AttachRenderBuffer", decoder_->GetErrorState());
2196 ScopedFrameBufferBinder binder(decoder_, id_);
2197 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
2198 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
2204 void BackFramebuffer::Destroy() {
2206 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy",
2207 decoder_->GetErrorState());
2208 glDeleteFramebuffersEXT(1, &id_);
2213 void BackFramebuffer::Invalidate() {
2217 GLenum BackFramebuffer::CheckStatus() {
2219 ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus",
2220 decoder_->GetErrorState());
2221 ScopedFrameBufferBinder binder(decoder_, id_);
2222 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
2225 GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
2226 return new GLES2DecoderImpl(group);
2229 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
2232 logger_(&debug_marker_manager_),
2233 state_(group_->feature_info(), this, &logger_),
2234 unpack_flip_y_(false),
2235 unpack_premultiply_alpha_(false),
2236 unpack_unpremultiply_alpha_(false),
2237 attrib_0_buffer_id_(0),
2238 attrib_0_buffer_matches_value_(true),
2240 fixed_attrib_buffer_id_(0),
2241 fixed_attrib_buffer_size_(0),
2242 offscreen_target_color_format_(0),
2243 offscreen_target_depth_format_(0),
2244 offscreen_target_stencil_format_(0),
2245 offscreen_target_samples_(0),
2246 offscreen_target_buffer_preserved_(true),
2247 offscreen_saved_color_format_(0),
2248 back_buffer_color_format_(0),
2249 back_buffer_has_depth_(false),
2250 back_buffer_has_stencil_(false),
2251 backbuffer_needs_clear_bits_(0),
2252 current_decoder_error_(error::kNoError),
2253 use_shader_translator_(true),
2254 validators_(group_->feature_info()->validators()),
2255 feature_info_(group_->feature_info()),
2257 has_robustness_extension_(false),
2258 reset_status_(GL_NO_ERROR),
2259 reset_by_robustness_extension_(false),
2260 supports_post_sub_buffer_(false),
2261 force_webgl_glsl_validation_(false),
2262 derivatives_explicitly_enabled_(false),
2263 frag_depth_explicitly_enabled_(false),
2264 draw_buffers_explicitly_enabled_(false),
2265 shader_texture_lod_explicitly_enabled_(false),
2266 compile_shader_always_succeeds_(false),
2267 lose_context_when_out_of_memory_(false),
2268 service_logging_(CommandLine::ForCurrentProcess()->HasSwitch(
2269 switches::kEnableGPUServiceLoggingGPU)),
2270 viewport_max_width_(0),
2271 viewport_max_height_(0),
2272 texture_state_(group_->feature_info()
2274 .texsubimage2d_faster_than_teximage2d),
2275 validation_texture_(0),
2276 validation_fbo_multisample_(0),
2277 validation_fbo_(0) {
2280 attrib_0_value_.v[0] = 0.0f;
2281 attrib_0_value_.v[1] = 0.0f;
2282 attrib_0_value_.v[2] = 0.0f;
2283 attrib_0_value_.v[3] = 1.0f;
2285 // The shader translator is used for WebGL even when running on EGL
2286 // because additional restrictions are needed (like only enabling
2287 // GL_OES_standard_derivatives on demand). It is used for the unit
2288 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2289 // the empty string to CompileShader and this is not a valid shader.
2290 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
2291 CommandLine::ForCurrentProcess()->HasSwitch(
2292 switches::kDisableGLSLTranslator)) {
2293 use_shader_translator_ = false;
2297 GLES2DecoderImpl::~GLES2DecoderImpl() {
2300 bool GLES2DecoderImpl::Initialize(
2301 const scoped_refptr<gfx::GLSurface>& surface,
2302 const scoped_refptr<gfx::GLContext>& context,
2304 const gfx::Size& size,
2305 const DisallowedFeatures& disallowed_features,
2306 const std::vector<int32>& attribs) {
2307 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2308 DCHECK(context->IsCurrent(surface.get()));
2309 DCHECK(!context_.get());
2312 gpu_tracer_ = GPUTracer::Create(this);
2313 gpu_state_tracer_ = GPUStateTracer::Create(&state_);
2314 // TODO(vmiura): Enable changing gpu_trace_level_ at runtime
2315 gpu_trace_level_ = 2;
2316 gpu_trace_commands_ = false;
2318 if (CommandLine::ForCurrentProcess()->HasSwitch(
2319 switches::kEnableGPUDebugging)) {
2323 if (CommandLine::ForCurrentProcess()->HasSwitch(
2324 switches::kEnableGPUCommandLogging)) {
2325 set_log_commands(true);
2328 compile_shader_always_succeeds_ = CommandLine::ForCurrentProcess()->HasSwitch(
2329 switches::kCompileShaderAlwaysSucceeds);
2332 // Take ownership of the context and surface. The surface can be replaced with
2337 ContextCreationAttribHelper attrib_parser;
2338 if (!attrib_parser.Parse(attribs))
2341 // Save the loseContextWhenOutOfMemory context creation attribute.
2342 lose_context_when_out_of_memory_ =
2343 attrib_parser.lose_context_when_out_of_memory_;
2345 // If the failIfMajorPerformanceCaveat context creation attribute was true
2346 // and we are using a software renderer, fail.
2347 if (attrib_parser.fail_if_major_perf_caveat_ &&
2348 feature_info_->feature_flags().is_swiftshader) {
2349 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2354 if (!group_->Initialize(this, disallowed_features)) {
2355 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
2356 << "failed to initialize.";
2357 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2363 disallowed_features_ = disallowed_features;
2365 state_.attrib_values.resize(group_->max_vertex_attribs());
2366 vertex_array_manager_.reset(new VertexArrayManager());
2368 GLuint default_vertex_attrib_service_id = 0;
2369 if (features().native_vertex_array_object) {
2370 glGenVertexArraysOES(1, &default_vertex_attrib_service_id);
2371 glBindVertexArrayOES(default_vertex_attrib_service_id);
2374 state_.default_vertex_attrib_manager =
2375 CreateVertexAttribManager(0, default_vertex_attrib_service_id, false);
2377 state_.default_vertex_attrib_manager->Initialize(
2378 group_->max_vertex_attribs(),
2379 feature_info_->workarounds().init_vertex_attributes);
2381 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2382 DoBindVertexArrayOES(0);
2384 query_manager_.reset(new QueryManager(this, feature_info_.get()));
2386 util_.set_num_compressed_texture_formats(
2387 validators_->compressed_texture_format.GetValues().size());
2389 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2390 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2391 // OpenGL ES 2.0 does not have this issue.
2392 glEnableVertexAttribArray(0);
2394 glGenBuffersARB(1, &attrib_0_buffer_id_);
2395 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2396 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2397 glBindBuffer(GL_ARRAY_BUFFER, 0);
2398 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
2400 state_.texture_units.resize(group_->max_texture_units());
2401 for (uint32 tt = 0; tt < state_.texture_units.size(); ++tt) {
2402 glActiveTexture(GL_TEXTURE0 + tt);
2403 // We want the last bind to be 2D.
2405 if (features().oes_egl_image_external) {
2406 ref = texture_manager()->GetDefaultTextureInfo(
2407 GL_TEXTURE_EXTERNAL_OES);
2408 state_.texture_units[tt].bound_texture_external_oes = ref;
2409 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref ? ref->service_id() : 0);
2411 if (features().arb_texture_rectangle) {
2412 ref = texture_manager()->GetDefaultTextureInfo(
2413 GL_TEXTURE_RECTANGLE_ARB);
2414 state_.texture_units[tt].bound_texture_rectangle_arb = ref;
2415 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref ? ref->service_id() : 0);
2417 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
2418 state_.texture_units[tt].bound_texture_cube_map = ref;
2419 glBindTexture(GL_TEXTURE_CUBE_MAP, ref ? ref->service_id() : 0);
2420 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2421 state_.texture_units[tt].bound_texture_2d = ref;
2422 glBindTexture(GL_TEXTURE_2D, ref ? ref->service_id() : 0);
2424 glActiveTexture(GL_TEXTURE0);
2428 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
2429 features().chromium_framebuffer_multisample) {
2430 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2431 // max_sample_count must be initialized to a sane value. If
2432 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2433 GLint max_sample_count = 1;
2434 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2435 offscreen_target_samples_ = std::min(attrib_parser.samples_,
2438 offscreen_target_samples_ = 1;
2440 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved_;
2442 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2443 const bool rgb8_supported =
2444 context_->HasExtension("GL_OES_rgb8_rgba8");
2445 // The only available default render buffer formats in GLES2 have very
2446 // little precision. Don't enable multisampling unless 8-bit render
2447 // buffer formats are available--instead fall back to 8-bit textures.
2448 if (rgb8_supported && offscreen_target_samples_ > 1) {
2449 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2452 offscreen_target_samples_ = 1;
2453 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2457 // ANGLE only supports packed depth/stencil formats, so use it if it is
2459 const bool depth24_stencil8_supported =
2460 feature_info_->feature_flags().packed_depth24_stencil8;
2461 VLOG(1) << "GL_OES_packed_depth_stencil "
2462 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2463 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2464 depth24_stencil8_supported) {
2465 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2466 offscreen_target_stencil_format_ = 0;
2468 // It may be the case that this depth/stencil combination is not
2469 // supported, but this will be checked later by CheckFramebufferStatus.
2470 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2471 GL_DEPTH_COMPONENT16 : 0;
2472 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2473 GL_STENCIL_INDEX8 : 0;
2476 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2479 // If depth is requested at all, use the packed depth stencil format if
2480 // it's available, as some desktop GL drivers don't support any non-packed
2481 // formats for depth attachments.
2482 const bool depth24_stencil8_supported =
2483 feature_info_->feature_flags().packed_depth24_stencil8;
2484 VLOG(1) << "GL_EXT_packed_depth_stencil "
2485 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2487 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2488 depth24_stencil8_supported) {
2489 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2490 offscreen_target_stencil_format_ = 0;
2492 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2493 GL_DEPTH_COMPONENT : 0;
2494 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2495 GL_STENCIL_INDEX : 0;
2499 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
2502 // Create the target frame buffer. This is the one that the client renders
2504 offscreen_target_frame_buffer_.reset(new BackFramebuffer(this));
2505 offscreen_target_frame_buffer_->Create();
2506 // Due to GLES2 format limitations, either the color texture (for
2507 // non-multisampling) or the color render buffer (for multisampling) will be
2508 // attached to the offscreen frame buffer. The render buffer has more
2509 // limited formats available to it, but the texture can't do multisampling.
2510 if (IsOffscreenBufferMultisampled()) {
2511 offscreen_target_color_render_buffer_.reset(new BackRenderbuffer(
2512 renderbuffer_manager(), memory_tracker(), &state_));
2513 offscreen_target_color_render_buffer_->Create();
2515 offscreen_target_color_texture_.reset(new BackTexture(
2516 memory_tracker(), &state_));
2517 offscreen_target_color_texture_->Create();
2519 offscreen_target_depth_render_buffer_.reset(new BackRenderbuffer(
2520 renderbuffer_manager(), memory_tracker(), &state_));
2521 offscreen_target_depth_render_buffer_->Create();
2522 offscreen_target_stencil_render_buffer_.reset(new BackRenderbuffer(
2523 renderbuffer_manager(), memory_tracker(), &state_));
2524 offscreen_target_stencil_render_buffer_->Create();
2526 // Create the saved offscreen texture. The target frame buffer is copied
2527 // here when SwapBuffers is called.
2528 offscreen_saved_frame_buffer_.reset(new BackFramebuffer(this));
2529 offscreen_saved_frame_buffer_->Create();
2531 offscreen_saved_color_texture_.reset(new BackTexture(
2532 memory_tracker(), &state_));
2533 offscreen_saved_color_texture_->Create();
2535 // Allocate the render buffers at their initial size and check the status
2536 // of the frame buffers is okay.
2537 if (!ResizeOffscreenFrameBuffer(size)) {
2538 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
2543 // Allocate the offscreen saved color texture.
2544 DCHECK(offscreen_saved_color_format_);
2545 offscreen_saved_color_texture_->AllocateStorage(
2546 gfx::Size(1, 1), offscreen_saved_color_format_, true);
2548 offscreen_saved_frame_buffer_->AttachRenderTexture(
2549 offscreen_saved_color_texture_.get());
2550 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2551 GL_FRAMEBUFFER_COMPLETE) {
2552 LOG(ERROR) << "Offscreen saved FBO was incomplete.";
2557 // Bind to the new default frame buffer (the offscreen target frame buffer).
2558 // This should now be associated with ID zero.
2559 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2561 glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId());
2562 // These are NOT if the back buffer has these proprorties. They are
2563 // if we want the command buffer to enforce them regardless of what
2564 // the real backbuffer is assuming the real back buffer gives us more than
2565 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2566 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2567 // can't do anything about that.
2570 glGetIntegerv(GL_ALPHA_BITS, &v);
2571 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
2572 // user requested RGB then RGB. If the user did not specify a preference
2573 // than use whatever we were given. Same for DEPTH and STENCIL.
2574 back_buffer_color_format_ =
2575 (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB;
2576 glGetIntegerv(GL_DEPTH_BITS, &v);
2577 back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0;
2578 glGetIntegerv(GL_STENCIL_BITS, &v);
2579 back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0;
2582 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2583 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2584 // isn't well documented; it was discovered in the Khronos OpenGL ES
2585 // mailing list archives. It also implicitly enables the desktop GL
2586 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2587 // variable in fragment shaders.
2588 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2589 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
2590 glEnable(GL_POINT_SPRITE);
2593 has_robustness_extension_ =
2594 context->HasExtension("GL_ARB_robustness") ||
2595 context->HasExtension("GL_EXT_robustness");
2597 if (!InitializeShaderTranslator()) {
2601 state_.viewport_width = size.width();
2602 state_.viewport_height = size.height();
2604 GLint viewport_params[4] = { 0 };
2605 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
2606 viewport_max_width_ = viewport_params[0];
2607 viewport_max_height_ = viewport_params[1];
2609 state_.scissor_width = state_.viewport_width;
2610 state_.scissor_height = state_.viewport_height;
2612 // Set all the default state because some GL drivers get it wrong.
2613 state_.InitCapabilities(NULL);
2614 state_.InitState(NULL);
2615 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
2617 DoBindBuffer(GL_ARRAY_BUFFER, 0);
2618 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2619 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2620 DoBindRenderbuffer(GL_RENDERBUFFER, 0);
2622 bool call_gl_clear = true;
2623 #if defined(OS_ANDROID)
2624 // Temporary workaround for Android WebView because this clear ignores the
2625 // clip and corrupts that external UI of the App. Not calling glClear is ok
2626 // because the system already clears the buffer before each draw. Proper
2627 // fix might be setting the scissor clip properly before initialize. See
2628 // crbug.com/259023 for details.
2629 call_gl_clear = surface_->GetHandle();
2631 if (call_gl_clear) {
2632 // Clear the backbuffer.
2633 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2636 supports_post_sub_buffer_ = surface->SupportsPostSubBuffer();
2637 if (feature_info_->workarounds()
2638 .disable_post_sub_buffers_for_onscreen_surfaces &&
2639 !surface->IsOffscreen())
2640 supports_post_sub_buffer_ = false;
2642 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) {
2643 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
2646 if (feature_info_->workarounds().unbind_fbo_on_context_switch) {
2647 context_->SetUnbindFboOnMakeCurrent();
2650 if (feature_info_->workarounds().release_image_after_use) {
2651 image_manager()->SetReleaseAfterUse();
2654 // Only compositor contexts are known to use only the subset of GL
2655 // that can be safely migrated between the iGPU and the dGPU. Mark
2656 // those contexts as safe to forcibly transition between the GPUs.
2657 // http://crbug.com/180876, http://crbug.com/227228
2659 context_->SetSafeToForceGpuSwitch();
2661 async_pixel_transfer_manager_.reset(
2662 AsyncPixelTransferManager::Create(context.get()));
2663 async_pixel_transfer_manager_->Initialize(texture_manager());
2665 framebuffer_manager()->AddObserver(this);
2670 Capabilities GLES2DecoderImpl::GetCapabilities() {
2671 DCHECK(initialized());
2675 caps.fast_npot_mo8_textures =
2676 feature_info_->workarounds().enable_chromium_fast_npot_mo8_textures;
2677 caps.egl_image_external =
2678 feature_info_->feature_flags().oes_egl_image_external;
2679 caps.texture_format_bgra8888 =
2680 feature_info_->feature_flags().ext_texture_format_bgra8888;
2681 caps.texture_format_etc1 =
2682 feature_info_->feature_flags().oes_compressed_etc1_rgb8_texture;
2683 caps.texture_rectangle = feature_info_->feature_flags().arb_texture_rectangle;
2684 caps.texture_usage = feature_info_->feature_flags().angle_texture_usage;
2685 caps.texture_storage = feature_info_->feature_flags().ext_texture_storage;
2686 caps.discard_framebuffer =
2687 feature_info_->feature_flags().ext_discard_framebuffer;
2688 caps.sync_query = feature_info_->feature_flags().chromium_sync_query;
2690 #if defined(OS_MACOSX)
2691 // This is unconditionally true on mac, no need to test for it at runtime.
2692 caps.iosurface = true;
2695 caps.post_sub_buffer = supports_post_sub_buffer_;
2696 caps.map_image = !!image_manager();
2701 void GLES2DecoderImpl::UpdateCapabilities() {
2702 util_.set_num_compressed_texture_formats(
2703 validators_->compressed_texture_format.GetValues().size());
2704 util_.set_num_shader_binary_formats(
2705 validators_->shader_binary_format.GetValues().size());
2708 bool GLES2DecoderImpl::InitializeShaderTranslator() {
2709 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
2711 if (!use_shader_translator_) {
2714 ShBuiltInResources resources;
2715 ShInitBuiltInResources(&resources);
2716 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2717 resources.MaxVertexUniformVectors =
2718 group_->max_vertex_uniform_vectors();
2719 resources.MaxVaryingVectors = group_->max_varying_vectors();
2720 resources.MaxVertexTextureImageUnits =
2721 group_->max_vertex_texture_image_units();
2722 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2723 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2724 resources.MaxFragmentUniformVectors =
2725 group_->max_fragment_uniform_vectors();
2726 resources.MaxDrawBuffers = group_->max_draw_buffers();
2727 resources.MaxExpressionComplexity = 256;
2728 resources.MaxCallStackDepth = 256;
2730 #if (ANGLE_SH_VERSION >= 110)
2731 GLint range[2] = { 0, 0 };
2732 GLint precision = 0;
2733 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
2735 resources.FragmentPrecisionHigh =
2736 PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
2739 if (force_webgl_glsl_validation_) {
2740 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
2741 resources.EXT_frag_depth = frag_depth_explicitly_enabled_;
2742 resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
2743 if (!draw_buffers_explicitly_enabled_)
2744 resources.MaxDrawBuffers = 1;
2745 #if (ANGLE_SH_VERSION >= 123)
2746 resources.EXT_shader_texture_lod = shader_texture_lod_explicitly_enabled_;
2749 resources.OES_standard_derivatives =
2750 features().oes_standard_derivatives ? 1 : 0;
2751 resources.ARB_texture_rectangle =
2752 features().arb_texture_rectangle ? 1 : 0;
2753 resources.OES_EGL_image_external =
2754 features().oes_egl_image_external ? 1 : 0;
2755 resources.EXT_draw_buffers =
2756 features().ext_draw_buffers ? 1 : 0;
2757 resources.EXT_frag_depth =
2758 features().ext_frag_depth ? 1 : 0;
2759 #if (ANGLE_SH_VERSION >= 123)
2760 resources.EXT_shader_texture_lod =
2761 features().ext_shader_texture_lod ? 1 : 0;
2765 ShShaderSpec shader_spec = force_webgl_glsl_validation_ ? SH_WEBGL_SPEC
2767 if (shader_spec == SH_WEBGL_SPEC && features().enable_shader_name_hashing)
2768 #if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
2769 resources.HashFunction = &CityHashForAngle;
2771 resources.HashFunction = &CityHash64;
2774 resources.HashFunction = NULL;
2775 ShaderTranslatorInterface::GlslImplementationType implementation_type =
2776 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
2777 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
2778 int driver_bug_workarounds = 0;
2779 if (workarounds().needs_glsl_built_in_function_emulation)
2780 driver_bug_workarounds |= SH_EMULATE_BUILT_IN_FUNCTIONS;
2781 if (workarounds().init_gl_position_in_vertex_shader)
2782 driver_bug_workarounds |= SH_INIT_GL_POSITION;
2783 if (workarounds().unfold_short_circuit_as_ternary_operation)
2784 driver_bug_workarounds |= SH_UNFOLD_SHORT_CIRCUIT;
2785 if (workarounds().init_varyings_without_static_use)
2786 driver_bug_workarounds |= SH_INIT_VARYINGS_WITHOUT_STATIC_USE;
2787 if (workarounds().unroll_for_loop_with_sampler_array_index)
2788 driver_bug_workarounds |= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX;
2790 vertex_translator_ = shader_translator_cache()->GetTranslator(
2794 implementation_type,
2795 static_cast<ShCompileOptions>(driver_bug_workarounds));
2796 if (!vertex_translator_.get()) {
2797 LOG(ERROR) << "Could not initialize vertex shader translator.";
2802 fragment_translator_ = shader_translator_cache()->GetTranslator(
2806 implementation_type,
2807 static_cast<ShCompileOptions>(driver_bug_workarounds));
2808 if (!fragment_translator_.get()) {
2809 LOG(ERROR) << "Could not initialize fragment shader translator.";
2816 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
2817 for (GLsizei ii = 0; ii < n; ++ii) {
2818 if (GetBuffer(client_ids[ii])) {
2822 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2823 glGenBuffersARB(n, service_ids.get());
2824 for (GLsizei ii = 0; ii < n; ++ii) {
2825 CreateBuffer(client_ids[ii], service_ids[ii]);
2830 bool GLES2DecoderImpl::GenFramebuffersHelper(
2831 GLsizei n, const GLuint* client_ids) {
2832 for (GLsizei ii = 0; ii < n; ++ii) {
2833 if (GetFramebuffer(client_ids[ii])) {
2837 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2838 glGenFramebuffersEXT(n, service_ids.get());
2839 for (GLsizei ii = 0; ii < n; ++ii) {
2840 CreateFramebuffer(client_ids[ii], service_ids[ii]);
2845 bool GLES2DecoderImpl::GenRenderbuffersHelper(
2846 GLsizei n, const GLuint* client_ids) {
2847 for (GLsizei ii = 0; ii < n; ++ii) {
2848 if (GetRenderbuffer(client_ids[ii])) {
2852 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2853 glGenRenderbuffersEXT(n, service_ids.get());
2854 for (GLsizei ii = 0; ii < n; ++ii) {
2855 CreateRenderbuffer(client_ids[ii], service_ids[ii]);
2860 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2861 for (GLsizei ii = 0; ii < n; ++ii) {
2862 if (GetTexture(client_ids[ii])) {
2866 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2867 glGenTextures(n, service_ids.get());
2868 for (GLsizei ii = 0; ii < n; ++ii) {
2869 CreateTexture(client_ids[ii], service_ids[ii]);
2874 void GLES2DecoderImpl::DeleteBuffersHelper(
2875 GLsizei n, const GLuint* client_ids) {
2876 for (GLsizei ii = 0; ii < n; ++ii) {
2877 Buffer* buffer = GetBuffer(client_ids[ii]);
2878 if (buffer && !buffer->IsDeleted()) {
2879 state_.vertex_attrib_manager->Unbind(buffer);
2880 if (state_.bound_array_buffer.get() == buffer) {
2881 state_.bound_array_buffer = NULL;
2883 RemoveBuffer(client_ids[ii]);
2888 void GLES2DecoderImpl::DeleteFramebuffersHelper(
2889 GLsizei n, const GLuint* client_ids) {
2890 bool supports_separate_framebuffer_binds =
2891 features().chromium_framebuffer_multisample;
2893 for (GLsizei ii = 0; ii < n; ++ii) {
2894 Framebuffer* framebuffer =
2895 GetFramebuffer(client_ids[ii]);
2896 if (framebuffer && !framebuffer->IsDeleted()) {
2897 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
2898 framebuffer_state_.bound_draw_framebuffer = NULL;
2899 framebuffer_state_.clear_state_dirty = true;
2900 GLenum target = supports_separate_framebuffer_binds ?
2901 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
2902 glBindFramebufferEXT(target, GetBackbufferServiceId());
2904 if (framebuffer == framebuffer_state_.bound_read_framebuffer.get()) {
2905 framebuffer_state_.bound_read_framebuffer = NULL;
2906 GLenum target = supports_separate_framebuffer_binds ?
2907 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
2908 glBindFramebufferEXT(target, GetBackbufferServiceId());
2911 RemoveFramebuffer(client_ids[ii]);
2916 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2917 GLsizei n, const GLuint* client_ids) {
2918 bool supports_separate_framebuffer_binds =
2919 features().chromium_framebuffer_multisample;
2920 for (GLsizei ii = 0; ii < n; ++ii) {
2921 Renderbuffer* renderbuffer =
2922 GetRenderbuffer(client_ids[ii]);
2923 if (renderbuffer && !renderbuffer->IsDeleted()) {
2924 if (state_.bound_renderbuffer.get() == renderbuffer) {
2925 state_.bound_renderbuffer = NULL;
2927 // Unbind from current framebuffers.
2928 if (supports_separate_framebuffer_binds) {
2929 if (framebuffer_state_.bound_read_framebuffer.get()) {
2930 framebuffer_state_.bound_read_framebuffer
2931 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT, renderbuffer);
2933 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2934 framebuffer_state_.bound_draw_framebuffer
2935 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
2938 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2939 framebuffer_state_.bound_draw_framebuffer
2940 ->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
2943 framebuffer_state_.clear_state_dirty = true;
2944 RemoveRenderbuffer(client_ids[ii]);
2949 void GLES2DecoderImpl::DeleteTexturesHelper(
2950 GLsizei n, const GLuint* client_ids) {
2951 bool supports_separate_framebuffer_binds =
2952 features().chromium_framebuffer_multisample;
2953 for (GLsizei ii = 0; ii < n; ++ii) {
2954 TextureRef* texture_ref = GetTexture(client_ids[ii]);
2956 Texture* texture = texture_ref->texture();
2957 if (texture->IsAttachedToFramebuffer()) {
2958 framebuffer_state_.clear_state_dirty = true;
2960 // Unbind texture_ref from texture_ref units.
2961 for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) {
2962 state_.texture_units[jj].Unbind(texture_ref);
2964 // Unbind from current framebuffers.
2965 if (supports_separate_framebuffer_binds) {
2966 if (framebuffer_state_.bound_read_framebuffer.get()) {
2967 framebuffer_state_.bound_read_framebuffer
2968 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT, texture_ref);
2970 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2971 framebuffer_state_.bound_draw_framebuffer
2972 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
2975 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2976 framebuffer_state_.bound_draw_framebuffer
2977 ->UnbindTexture(GL_FRAMEBUFFER, texture_ref);
2980 #if defined(OS_MACOSX)
2981 GLuint service_id = texture->service_id();
2982 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
2983 ReleaseIOSurfaceForTexture(service_id);
2986 RemoveTexture(client_ids[ii]);
2991 // } // anonymous namespace
2993 bool GLES2DecoderImpl::MakeCurrent() {
2994 if (!context_.get())
2997 if (!context_->MakeCurrent(surface_.get()) || WasContextLost()) {
2998 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3000 // Some D3D drivers cannot recover from device lost in the GPU process
3001 // sandbox. Allow a new GPU process to launch.
3002 if (workarounds().exit_on_context_lost) {
3003 LOG(ERROR) << "Exiting GPU process because some drivers cannot reset"
3004 << " a D3D device in the Chrome GPU process sandbox.";
3006 base::win::SetShouldCrashOnProcessDetach(false);
3014 ProcessFinishedAsyncTransfers();
3016 // Rebind the FBO if it was unbound by the context.
3017 if (workarounds().unbind_fbo_on_context_switch)
3018 RestoreFramebufferBindings();
3020 framebuffer_state_.clear_state_dirty = true;
3025 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3026 ProcessPendingReadPixels();
3027 if (engine() && query_manager_.get())
3028 query_manager_->ProcessPendingTransferQueries();
3030 // TODO(epenner): Is there a better place to do this?
3031 // This needs to occur before we execute any batch of commands
3032 // from the client, as the client may have recieved an async
3033 // completion while issuing those commands.
3034 // "DidFlushStart" would be ideal if we had such a callback.
3035 async_pixel_transfer_manager_->BindCompletedAsyncTransfers();
3038 static void RebindCurrentFramebuffer(
3040 Framebuffer* framebuffer,
3041 GLuint back_buffer_service_id) {
3042 GLuint framebuffer_id = framebuffer ? framebuffer->service_id() : 0;
3044 if (framebuffer_id == 0) {
3045 framebuffer_id = back_buffer_service_id;
3048 glBindFramebufferEXT(target, framebuffer_id);
3051 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3052 framebuffer_state_.clear_state_dirty = true;
3054 if (!features().chromium_framebuffer_multisample) {
3055 RebindCurrentFramebuffer(
3057 framebuffer_state_.bound_draw_framebuffer.get(),
3058 GetBackbufferServiceId());
3060 RebindCurrentFramebuffer(
3061 GL_READ_FRAMEBUFFER_EXT,
3062 framebuffer_state_.bound_read_framebuffer.get(),
3063 GetBackbufferServiceId());
3064 RebindCurrentFramebuffer(
3065 GL_DRAW_FRAMEBUFFER_EXT,
3066 framebuffer_state_.bound_draw_framebuffer.get(),
3067 GetBackbufferServiceId());
3072 bool GLES2DecoderImpl::CheckFramebufferValid(
3073 Framebuffer* framebuffer,
3074 GLenum target, const char* func_name) {
3076 if (backbuffer_needs_clear_bits_) {
3077 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3078 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
3079 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3081 state_.SetDeviceStencilMaskSeparate(GL_FRONT, -1);
3082 state_.SetDeviceStencilMaskSeparate(GL_BACK, -1);
3084 state_.SetDeviceDepthMask(GL_TRUE);
3085 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
3086 bool reset_draw_buffer = false;
3087 if ((backbuffer_needs_clear_bits_ | GL_COLOR_BUFFER_BIT) != 0 &&
3088 group_->draw_buffer() == GL_NONE) {
3089 reset_draw_buffer = true;
3090 GLenum buf = GL_BACK;
3091 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3092 buf = GL_COLOR_ATTACHMENT0;
3093 glDrawBuffersARB(1, &buf);
3095 glClear(backbuffer_needs_clear_bits_);
3096 if (reset_draw_buffer) {
3097 GLenum buf = GL_NONE;
3098 glDrawBuffersARB(1, &buf);
3100 backbuffer_needs_clear_bits_ = 0;
3101 RestoreClearState();
3106 if (framebuffer_manager()->IsComplete(framebuffer)) {
3110 GLenum completeness = framebuffer->IsPossiblyComplete();
3111 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
3113 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
3117 // Are all the attachments cleared?
3118 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3119 texture_manager()->HaveUnclearedMips()) {
3120 if (!framebuffer->IsCleared()) {
3121 // Can we clear them?
3122 if (framebuffer->GetStatus(texture_manager(), target) !=
3123 GL_FRAMEBUFFER_COMPLETE) {
3125 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3126 "framebuffer incomplete (clear)");
3129 ClearUnclearedAttachments(target, framebuffer);
3133 if (!framebuffer_manager()->IsComplete(framebuffer)) {
3134 if (framebuffer->GetStatus(texture_manager(), target) !=
3135 GL_FRAMEBUFFER_COMPLETE) {
3137 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3138 "framebuffer incomplete (check)");
3141 framebuffer_manager()->MarkAsComplete(framebuffer);
3144 // NOTE: At this point we don't know if the framebuffer is complete but
3145 // we DO know that everything that needs to be cleared has been cleared.
3149 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
3150 if (!features().chromium_framebuffer_multisample) {
3151 bool valid = CheckFramebufferValid(
3152 framebuffer_state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT,
3160 return CheckFramebufferValid(framebuffer_state_.bound_draw_framebuffer.get(),
3161 GL_DRAW_FRAMEBUFFER_EXT,
3163 CheckFramebufferValid(framebuffer_state_.bound_read_framebuffer.get(),
3164 GL_READ_FRAMEBUFFER_EXT,
3168 gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3169 Framebuffer* framebuffer =
3170 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3171 if (framebuffer != NULL) {
3172 const Framebuffer::Attachment* attachment =
3173 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
3175 return gfx::Size(attachment->width(), attachment->height());
3177 return gfx::Size(0, 0);
3178 } else if (offscreen_target_frame_buffer_.get()) {
3179 return offscreen_size_;
3181 return surface_->GetSize();
3185 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3186 Framebuffer* framebuffer =
3187 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3188 if (framebuffer != NULL) {
3189 return framebuffer->GetColorAttachmentTextureType();
3191 return GL_UNSIGNED_BYTE;
3195 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3196 Framebuffer* framebuffer =
3197 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3198 if (framebuffer != NULL) {
3199 return framebuffer->GetColorAttachmentFormat();
3200 } else if (offscreen_target_frame_buffer_.get()) {
3201 return offscreen_target_color_format_;
3203 return back_buffer_color_format_;
3207 GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3208 Framebuffer* framebuffer =
3209 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3210 if (framebuffer != NULL) {
3211 return framebuffer->GetColorAttachmentFormat();
3212 } else if (offscreen_target_frame_buffer_.get()) {
3213 return offscreen_target_color_format_;
3215 return back_buffer_color_format_;
3219 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3220 if (!offscreen_saved_color_texture_info_.get())
3222 GLenum target = offscreen_saved_color_texture_info_->texture()->target();
3223 glBindTexture(target, offscreen_saved_color_texture_info_->service_id());
3224 texture_manager()->SetLevelInfo(
3225 offscreen_saved_color_texture_info_.get(),
3229 offscreen_size_.width(),
3230 offscreen_size_.height(),
3236 texture_manager()->SetParameteri(
3237 "UpdateParentTextureInfo",
3239 offscreen_saved_color_texture_info_.get(),
3240 GL_TEXTURE_MAG_FILTER,
3242 texture_manager()->SetParameteri(
3243 "UpdateParentTextureInfo",
3245 offscreen_saved_color_texture_info_.get(),
3246 GL_TEXTURE_MIN_FILTER,
3248 texture_manager()->SetParameteri(
3249 "UpdateParentTextureInfo",
3251 offscreen_saved_color_texture_info_.get(),
3254 texture_manager()->SetParameteri(
3255 "UpdateParentTextureInfo",
3257 offscreen_saved_color_texture_info_.get(),
3260 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
3262 glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
3265 void GLES2DecoderImpl::SetResizeCallback(
3266 const base::Callback<void(gfx::Size, float)>& callback) {
3267 resize_callback_ = callback;
3270 Logger* GLES2DecoderImpl::GetLogger() {
3274 void GLES2DecoderImpl::BeginDecoding() {
3275 gpu_tracer_->BeginDecoding();
3276 gpu_trace_commands_ = gpu_tracer_->IsTracing();
3279 void GLES2DecoderImpl::EndDecoding() {
3280 gpu_tracer_->EndDecoding();
3283 ErrorState* GLES2DecoderImpl::GetErrorState() {
3284 return state_.GetErrorState();
3287 void GLES2DecoderImpl::SetShaderCacheCallback(
3288 const ShaderCacheCallback& callback) {
3289 shader_cache_callback_ = callback;
3292 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3293 const WaitSyncPointCallback& callback) {
3294 wait_sync_point_callback_ = callback;
3297 AsyncPixelTransferManager*
3298 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3299 return async_pixel_transfer_manager_.get();
3302 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3303 async_pixel_transfer_manager_.reset();
3306 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3307 AsyncPixelTransferManager* manager) {
3308 async_pixel_transfer_manager_ = make_scoped_ptr(manager);
3311 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
3312 uint32* service_texture_id) {
3313 TextureRef* texture_ref = texture_manager()->GetTexture(client_texture_id);
3315 *service_texture_id = texture_ref->service_id();
3321 uint32 GLES2DecoderImpl::GetTextureUploadCount() {
3322 return texture_state_.texture_upload_count +
3323 async_pixel_transfer_manager_->GetTextureUploadCount();
3326 base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
3327 return texture_state_.total_texture_upload_time +
3328 async_pixel_transfer_manager_->GetTotalTextureUploadTime();
3331 base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3332 return total_processing_commands_time_;
3335 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time) {
3336 total_processing_commands_time_ += time;
3339 void GLES2DecoderImpl::Destroy(bool have_context) {
3343 DCHECK(!have_context || context_->IsCurrent(NULL));
3345 // Unbind everything.
3346 state_.vertex_attrib_manager = NULL;
3347 state_.default_vertex_attrib_manager = NULL;
3348 state_.texture_units.clear();
3349 state_.bound_array_buffer = NULL;
3350 state_.current_queries.clear();
3351 framebuffer_state_.bound_read_framebuffer = NULL;
3352 framebuffer_state_.bound_draw_framebuffer = NULL;
3353 state_.bound_renderbuffer = NULL;
3355 if (offscreen_saved_color_texture_info_.get()) {
3356 DCHECK(offscreen_target_color_texture_);
3357 DCHECK_EQ(offscreen_saved_color_texture_info_->service_id(),
3358 offscreen_saved_color_texture_->id());
3359 offscreen_saved_color_texture_->Invalidate();
3360 offscreen_saved_color_texture_info_ = NULL;
3363 if (copy_texture_CHROMIUM_.get()) {
3364 copy_texture_CHROMIUM_->Destroy();
3365 copy_texture_CHROMIUM_.reset();
3368 if (state_.current_program.get()) {
3369 program_manager()->UnuseProgram(shader_manager(),
3370 state_.current_program.get());
3373 if (attrib_0_buffer_id_) {
3374 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
3376 if (fixed_attrib_buffer_id_) {
3377 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
3380 if (validation_texture_) {
3381 glDeleteTextures(1, &validation_texture_);
3382 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_);
3383 glDeleteFramebuffersEXT(1, &validation_fbo_);
3386 if (offscreen_target_frame_buffer_.get())
3387 offscreen_target_frame_buffer_->Destroy();
3388 if (offscreen_target_color_texture_.get())
3389 offscreen_target_color_texture_->Destroy();
3390 if (offscreen_target_color_render_buffer_.get())
3391 offscreen_target_color_render_buffer_->Destroy();
3392 if (offscreen_target_depth_render_buffer_.get())
3393 offscreen_target_depth_render_buffer_->Destroy();
3394 if (offscreen_target_stencil_render_buffer_.get())
3395 offscreen_target_stencil_render_buffer_->Destroy();
3396 if (offscreen_saved_frame_buffer_.get())
3397 offscreen_saved_frame_buffer_->Destroy();
3398 if (offscreen_saved_color_texture_.get())
3399 offscreen_saved_color_texture_->Destroy();
3400 if (offscreen_resolved_frame_buffer_.get())
3401 offscreen_resolved_frame_buffer_->Destroy();
3402 if (offscreen_resolved_color_texture_.get())
3403 offscreen_resolved_color_texture_->Destroy();
3405 if (offscreen_target_frame_buffer_.get())
3406 offscreen_target_frame_buffer_->Invalidate();
3407 if (offscreen_target_color_texture_.get())
3408 offscreen_target_color_texture_->Invalidate();
3409 if (offscreen_target_color_render_buffer_.get())
3410 offscreen_target_color_render_buffer_->Invalidate();
3411 if (offscreen_target_depth_render_buffer_.get())
3412 offscreen_target_depth_render_buffer_->Invalidate();
3413 if (offscreen_target_stencil_render_buffer_.get())
3414 offscreen_target_stencil_render_buffer_->Invalidate();
3415 if (offscreen_saved_frame_buffer_.get())
3416 offscreen_saved_frame_buffer_->Invalidate();
3417 if (offscreen_saved_color_texture_.get())
3418 offscreen_saved_color_texture_->Invalidate();
3419 if (offscreen_resolved_frame_buffer_.get())
3420 offscreen_resolved_frame_buffer_->Invalidate();
3421 if (offscreen_resolved_color_texture_.get())
3422 offscreen_resolved_color_texture_->Invalidate();
3425 // Current program must be cleared after calling ProgramManager::UnuseProgram.
3426 // Otherwise, we can leak objects. http://crbug.com/258772.
3427 // state_.current_program must be reset before group_ is reset because
3428 // the later deletes the ProgramManager object that referred by
3429 // state_.current_program object.
3430 state_.current_program = NULL;
3432 copy_texture_CHROMIUM_.reset();
3434 if (query_manager_.get()) {
3435 query_manager_->Destroy(have_context);
3436 query_manager_.reset();
3439 if (vertex_array_manager_ .get()) {
3440 vertex_array_manager_->Destroy(have_context);
3441 vertex_array_manager_.reset();
3444 offscreen_target_frame_buffer_.reset();
3445 offscreen_target_color_texture_.reset();
3446 offscreen_target_color_render_buffer_.reset();
3447 offscreen_target_depth_render_buffer_.reset();
3448 offscreen_target_stencil_render_buffer_.reset();
3449 offscreen_saved_frame_buffer_.reset();
3450 offscreen_saved_color_texture_.reset();
3451 offscreen_resolved_frame_buffer_.reset();
3452 offscreen_resolved_color_texture_.reset();
3454 // Need to release these before releasing |group_| which may own the
3455 // ShaderTranslatorCache.
3456 fragment_translator_ = NULL;
3457 vertex_translator_ = NULL;
3459 // Should destroy the transfer manager before the texture manager held
3460 // by the context group.
3461 async_pixel_transfer_manager_.reset();
3464 framebuffer_manager()->RemoveObserver(this);
3465 group_->Destroy(this, have_context);
3469 if (context_.get()) {
3470 context_->ReleaseCurrent(NULL);
3474 #if defined(OS_MACOSX)
3475 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
3476 it != texture_to_io_surface_map_.end(); ++it) {
3477 CFRelease(it->second);
3479 texture_to_io_surface_map_.clear();
3483 void GLES2DecoderImpl::SetSurface(
3484 const scoped_refptr<gfx::GLSurface>& surface) {
3485 DCHECK(context_->IsCurrent(NULL));
3486 DCHECK(surface_.get());
3488 RestoreCurrentFramebufferBindings();
3491 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
3492 if (!offscreen_saved_color_texture_.get()) {
3493 LOG(ERROR) << "Called ProduceFrontBuffer on a non-offscreen context";
3496 if (!offscreen_saved_color_texture_info_.get()) {
3497 GLuint service_id = offscreen_saved_color_texture_->id();
3498 offscreen_saved_color_texture_info_ = TextureRef::Create(
3499 texture_manager(), 0, service_id);
3500 texture_manager()->SetTarget(offscreen_saved_color_texture_info_.get(),
3502 UpdateParentTextureInfo();
3504 mailbox_manager()->ProduceTexture(
3505 GL_TEXTURE_2D, mailbox, offscreen_saved_color_texture_info_->texture());
3508 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
3509 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3510 if (!is_offscreen) {
3511 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3512 << " with an onscreen framebuffer.";
3516 if (offscreen_size_ == size)
3519 offscreen_size_ = size;
3520 int w = offscreen_size_.width();
3521 int h = offscreen_size_.height();
3522 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
3523 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3524 << "to allocate storage due to excessive dimensions.";
3528 // Reallocate the offscreen target buffers.
3529 DCHECK(offscreen_target_color_format_);
3530 if (IsOffscreenBufferMultisampled()) {
3531 if (!offscreen_target_color_render_buffer_->AllocateStorage(
3532 feature_info_, offscreen_size_, offscreen_target_color_format_,
3533 offscreen_target_samples_)) {
3534 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3535 << "to allocate storage for offscreen target color buffer.";
3539 if (!offscreen_target_color_texture_->AllocateStorage(
3540 offscreen_size_, offscreen_target_color_format_, false)) {
3541 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3542 << "to allocate storage for offscreen target color texture.";
3546 if (offscreen_target_depth_format_ &&
3547 !offscreen_target_depth_render_buffer_->AllocateStorage(
3548 feature_info_, offscreen_size_, offscreen_target_depth_format_,
3549 offscreen_target_samples_)) {
3550 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3551 << "to allocate storage for offscreen target depth buffer.";
3554 if (offscreen_target_stencil_format_ &&
3555 !offscreen_target_stencil_render_buffer_->AllocateStorage(
3556 feature_info_, offscreen_size_, offscreen_target_stencil_format_,
3557 offscreen_target_samples_)) {
3558 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3559 << "to allocate storage for offscreen target stencil buffer.";
3563 // Attach the offscreen target buffers to the target frame buffer.
3564 if (IsOffscreenBufferMultisampled()) {
3565 offscreen_target_frame_buffer_->AttachRenderBuffer(
3566 GL_COLOR_ATTACHMENT0,
3567 offscreen_target_color_render_buffer_.get());
3569 offscreen_target_frame_buffer_->AttachRenderTexture(
3570 offscreen_target_color_texture_.get());
3572 if (offscreen_target_depth_format_) {
3573 offscreen_target_frame_buffer_->AttachRenderBuffer(
3574 GL_DEPTH_ATTACHMENT,
3575 offscreen_target_depth_render_buffer_.get());
3577 const bool packed_depth_stencil =
3578 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3579 if (packed_depth_stencil) {
3580 offscreen_target_frame_buffer_->AttachRenderBuffer(
3581 GL_STENCIL_ATTACHMENT,
3582 offscreen_target_depth_render_buffer_.get());
3583 } else if (offscreen_target_stencil_format_) {
3584 offscreen_target_frame_buffer_->AttachRenderBuffer(
3585 GL_STENCIL_ATTACHMENT,
3586 offscreen_target_stencil_render_buffer_.get());
3589 if (offscreen_target_frame_buffer_->CheckStatus() !=
3590 GL_FRAMEBUFFER_COMPLETE) {
3591 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3592 << "because offscreen FBO was incomplete.";
3596 // Clear the target frame buffer.
3598 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
3599 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3600 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
3601 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3603 state_.SetDeviceStencilMaskSeparate(GL_FRONT, -1);
3604 state_.SetDeviceStencilMaskSeparate(GL_BACK, -1);
3606 state_.SetDeviceDepthMask(GL_TRUE);
3607 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
3608 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3609 RestoreClearState();
3612 // Destroy the offscreen resolved framebuffers.
3613 if (offscreen_resolved_frame_buffer_.get())
3614 offscreen_resolved_frame_buffer_->Destroy();
3615 if (offscreen_resolved_color_texture_.get())
3616 offscreen_resolved_color_texture_->Destroy();
3617 offscreen_resolved_color_texture_.reset();
3618 offscreen_resolved_frame_buffer_.reset();
3623 error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(
3624 uint32 immediate_data_size, const cmds::ResizeCHROMIUM& c) {
3625 if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws())
3626 return error::kDeferCommandUntilLater;
3628 GLuint width = static_cast<GLuint>(c.width);
3629 GLuint height = static_cast<GLuint>(c.height);
3630 GLfloat scale_factor = c.scale_factor;
3631 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
3633 width = std::max(1U, width);
3634 height = std::max(1U, height);
3636 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3637 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
3638 // Make sure that we are done drawing to the back buffer before resizing.
3641 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3643 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
3644 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
3645 << "ResizeOffscreenFrameBuffer failed.";
3646 return error::kLostContext;
3650 if (!resize_callback_.is_null()) {
3651 resize_callback_.Run(gfx::Size(width, height), scale_factor);
3652 DCHECK(context_->IsCurrent(surface_.get()));
3653 if (!context_->IsCurrent(surface_.get())) {
3654 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
3655 << "current after resize callback.";
3656 return error::kLostContext;
3660 return error::kNoError;
3663 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
3664 if (command_id > kStartPoint && command_id < kNumCommands) {
3665 return gles2::GetCommandName(static_cast<CommandId>(command_id));
3667 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
3670 // Decode command with its arguments, and call the corresponding GL function.
3671 // Note: args is a pointer to the command buffer. As such, it could be changed
3672 // by a (malicious) client at any time, so if validation has to happen, it
3673 // should operate on a copy of them.
3674 error::Error GLES2DecoderImpl::DoCommand(
3675 unsigned int command,
3676 unsigned int arg_count,
3677 const void* cmd_data) {
3678 error::Error result = error::kNoError;
3679 if (log_commands()) {
3680 // TODO(notme): Change this to a LOG/VLOG that works in release. Tried
3681 // VLOG(1), no luck.
3682 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]" << "cmd: "
3683 << GetCommandName(command);
3685 unsigned int command_index = command - kStartPoint - 1;
3686 if (command_index < arraysize(g_command_info)) {
3687 const CommandInfo& info = g_command_info[command_index];
3688 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
3689 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
3690 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
3691 bool doing_gpu_trace = false;
3692 if (gpu_trace_commands_) {
3693 if (CMD_FLAG_GET_TRACE_LEVEL(info.cmd_flags) <= gpu_trace_level_) {
3694 doing_gpu_trace = true;
3695 gpu_tracer_->Begin(GetCommandName(command), kTraceDecoder);
3699 uint32 immediate_data_size =
3700 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
3702 #define GLES2_CMD_OP(name) \
3703 case cmds::name::kCmdId: \
3704 result = Handle ## name( \
3705 immediate_data_size, \
3706 *static_cast<const gles2::cmds::name*>(cmd_data)); \
3709 GLES2_COMMAND_LIST(GLES2_CMD_OP)
3713 if (doing_gpu_trace)
3714 gpu_tracer_->End(kTraceDecoder);
3718 while ((error = glGetError()) != GL_NO_ERROR) {
3719 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
3720 << "GL ERROR: " << GLES2Util::GetStringEnum(error) << " : "
3721 << GetCommandName(command);
3722 LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
3726 result = error::kInvalidArguments;
3729 result = DoCommonCommand(command, arg_count, cmd_data);
3731 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
3732 result = current_decoder_error_;
3733 current_decoder_error_ = error::kNoError;
3738 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id) {
3739 buffer_manager()->RemoveBuffer(client_id);
3742 bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
3743 if (GetProgram(client_id)) {
3746 GLuint service_id = glCreateProgram();
3747 if (service_id != 0) {
3748 CreateProgram(client_id, service_id);
3753 bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
3754 if (GetShader(client_id)) {
3757 GLuint service_id = glCreateShader(type);
3758 if (service_id != 0) {
3759 CreateShader(client_id, service_id, type);
3764 void GLES2DecoderImpl::DoFinish() {
3766 ProcessPendingReadPixels();
3767 ProcessPendingQueries();
3770 void GLES2DecoderImpl::DoFlush() {
3772 ProcessPendingQueries();
3775 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
3776 GLuint texture_index = texture_unit - GL_TEXTURE0;
3777 if (texture_index >= state_.texture_units.size()) {
3778 LOCAL_SET_GL_ERROR_INVALID_ENUM(
3779 "glActiveTexture", texture_unit, "texture_unit");
3782 state_.active_texture_unit = texture_index;
3783 glActiveTexture(texture_unit);
3786 void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
3787 Buffer* buffer = NULL;
3788 GLuint service_id = 0;
3789 if (client_id != 0) {
3790 buffer = GetBuffer(client_id);
3792 if (!group_->bind_generates_resource()) {
3793 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
3795 "id not generated by glGenBuffers");
3799 // It's a new id so make a buffer buffer for it.
3800 glGenBuffersARB(1, &service_id);
3801 CreateBuffer(client_id, service_id);
3802 buffer = GetBuffer(client_id);
3803 IdAllocatorInterface* id_allocator =
3804 group_->GetIdAllocator(id_namespaces::kBuffers);
3805 id_allocator->MarkAsUsed(client_id);
3808 LogClientServiceForInfo(buffer, client_id, "glBindBuffer");
3810 if (!buffer_manager()->SetTarget(buffer, target)) {
3812 GL_INVALID_OPERATION,
3813 "glBindBuffer", "buffer bound to more than 1 target");
3816 service_id = buffer->service_id();
3819 case GL_ARRAY_BUFFER:
3820 state_.bound_array_buffer = buffer;
3822 case GL_ELEMENT_ARRAY_BUFFER:
3823 state_.vertex_attrib_manager->SetElementArrayBuffer(buffer);
3826 NOTREACHED(); // Validation should prevent us getting here.
3829 glBindBuffer(target, service_id);
3832 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
3833 bool all_draw_buffers) {
3834 Framebuffer* framebuffer =
3835 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3836 if (!all_draw_buffers || !framebuffer) {
3837 return (GLES2Util::GetChannelsForFormat(
3838 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
3840 return framebuffer->HasAlphaMRT();
3843 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
3844 Framebuffer* framebuffer =
3845 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3847 return framebuffer->HasDepthAttachment();
3849 if (offscreen_target_frame_buffer_.get()) {
3850 return offscreen_target_depth_format_ != 0;
3852 return back_buffer_has_depth_;
3855 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
3856 Framebuffer* framebuffer =
3857 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3859 return framebuffer->HasStencilAttachment();
3861 if (offscreen_target_frame_buffer_.get()) {
3862 return offscreen_target_stencil_format_ != 0 ||
3863 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3865 return back_buffer_has_stencil_;
3868 void GLES2DecoderImpl::ApplyDirtyState() {
3869 if (framebuffer_state_.clear_state_dirty) {
3870 bool have_alpha = BoundFramebufferHasColorAttachmentWithAlpha(true);
3871 state_.SetDeviceColorMask(state_.color_mask_red,
3872 state_.color_mask_green,
3873 state_.color_mask_blue,
3874 state_.color_mask_alpha && have_alpha);
3876 bool have_depth = BoundFramebufferHasDepthAttachment();
3877 state_.SetDeviceDepthMask(state_.depth_mask && have_depth);
3879 bool have_stencil = BoundFramebufferHasStencilAttachment();
3880 state_.SetDeviceStencilMaskSeparate(
3881 GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
3882 state_.SetDeviceStencilMaskSeparate(
3883 GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
3885 state_.SetDeviceCapabilityState(
3886 GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
3887 state_.SetDeviceCapabilityState(
3888 GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
3889 framebuffer_state_.clear_state_dirty = false;
3893 GLuint GLES2DecoderImpl::GetBackbufferServiceId() const {
3894 return (offscreen_target_frame_buffer_.get())
3895 ? offscreen_target_frame_buffer_->id()
3896 : (surface_.get() ? surface_->GetBackingFrameBufferObject() : 0);
3899 void GLES2DecoderImpl::RestoreState(const ContextState* prev_state) const {
3900 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
3901 "context", logger_.GetLogPrefix());
3902 // Restore the Framebuffer first because of bugs in Intel drivers.
3903 // Intel drivers incorrectly clip the viewport settings to
3904 // the size of the current framebuffer object.
3905 RestoreFramebufferBindings();
3906 state_.RestoreState(prev_state);
3909 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
3911 framebuffer_state_.bound_draw_framebuffer.get()
3912 ? framebuffer_state_.bound_draw_framebuffer->service_id()
3913 : GetBackbufferServiceId();
3914 if (!features().chromium_framebuffer_multisample) {
3915 glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
3917 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, service_id);
3918 service_id = framebuffer_state_.bound_read_framebuffer.get()
3919 ? framebuffer_state_.bound_read_framebuffer->service_id()
3920 : GetBackbufferServiceId();
3921 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, service_id);
3926 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
3927 Texture* texture = texture_manager()->GetTextureForServiceId(service_id);
3929 GLenum target = texture->target();
3930 glBindTexture(target, service_id);
3932 target, GL_TEXTURE_WRAP_S, texture->wrap_s());
3934 target, GL_TEXTURE_WRAP_T, texture->wrap_t());
3936 target, GL_TEXTURE_MIN_FILTER, texture->min_filter());
3938 target, GL_TEXTURE_MAG_FILTER, texture->mag_filter());
3939 RestoreTextureUnitBindings(state_.active_texture_unit);
3943 void GLES2DecoderImpl::ClearAllAttributes() const {
3944 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
3946 if (feature_info_->feature_flags().native_vertex_array_object)
3947 glBindVertexArrayOES(0);
3949 for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i) {
3950 if (i != 0) // Never disable attribute 0
3951 glDisableVertexAttribArray(i);
3952 if(features().angle_instanced_arrays)
3953 glVertexAttribDivisorANGLE(i, 0);
3957 void GLES2DecoderImpl::RestoreAllAttributes() const {
3958 state_.RestoreVertexAttribs();
3961 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore) {
3962 state_.SetIgnoreCachedStateForTest(ignore);
3965 void GLES2DecoderImpl::OnFboChanged() const {
3966 if (workarounds().restore_scissor_on_fbo_change)
3967 state_.fbo_binding_for_scissor_workaround_dirty_ = true;
3970 // Called after the FBO is checked for completeness.
3971 void GLES2DecoderImpl::OnUseFramebuffer() const {
3972 if (state_.fbo_binding_for_scissor_workaround_dirty_) {
3973 state_.fbo_binding_for_scissor_workaround_dirty_ = false;
3974 // The driver forgets the correct scissor when modifying the FBO binding.
3975 glScissor(state_.scissor_x,
3977 state_.scissor_width,
3978 state_.scissor_height);
3980 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
3981 // it's unclear how this bug works.
3986 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
3987 Framebuffer* framebuffer = NULL;
3988 GLuint service_id = 0;
3989 if (client_id != 0) {
3990 framebuffer = GetFramebuffer(client_id);
3992 if (!group_->bind_generates_resource()) {
3993 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
3994 "glBindFramebuffer",
3995 "id not generated by glGenFramebuffers");
3999 // It's a new id so make a framebuffer framebuffer for it.
4000 glGenFramebuffersEXT(1, &service_id);
4001 CreateFramebuffer(client_id, service_id);
4002 framebuffer = GetFramebuffer(client_id);
4003 IdAllocatorInterface* id_allocator =
4004 group_->GetIdAllocator(id_namespaces::kFramebuffers);
4005 id_allocator->MarkAsUsed(client_id);
4007 service_id = framebuffer->service_id();
4009 framebuffer->MarkAsValid();
4011 LogClientServiceForInfo(framebuffer, client_id, "glBindFramebuffer");
4013 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
4014 framebuffer_state_.bound_draw_framebuffer = framebuffer;
4017 // vmiura: This looks like dup code
4018 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
4019 framebuffer_state_.bound_read_framebuffer = framebuffer;
4022 framebuffer_state_.clear_state_dirty = true;
4024 // If we are rendering to the backbuffer get the FBO id for any simulated
4026 if (framebuffer == NULL) {
4027 service_id = GetBackbufferServiceId();
4030 glBindFramebufferEXT(target, service_id);
4034 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
4035 Renderbuffer* renderbuffer = NULL;
4036 GLuint service_id = 0;
4037 if (client_id != 0) {
4038 renderbuffer = GetRenderbuffer(client_id);
4039 if (!renderbuffer) {
4040 if (!group_->bind_generates_resource()) {
4041 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4042 "glBindRenderbuffer",
4043 "id not generated by glGenRenderbuffers");
4047 // It's a new id so make a renderbuffer renderbuffer for it.
4048 glGenRenderbuffersEXT(1, &service_id);
4049 CreateRenderbuffer(client_id, service_id);
4050 renderbuffer = GetRenderbuffer(client_id);
4051 IdAllocatorInterface* id_allocator =
4052 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
4053 id_allocator->MarkAsUsed(client_id);
4055 service_id = renderbuffer->service_id();
4057 renderbuffer->MarkAsValid();
4059 LogClientServiceForInfo(renderbuffer, client_id, "glBindRenderbuffer");
4060 state_.bound_renderbuffer = renderbuffer;
4061 glBindRenderbufferEXT(target, service_id);
4064 void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
4065 TextureRef* texture_ref = NULL;
4066 GLuint service_id = 0;
4067 if (client_id != 0) {
4068 texture_ref = GetTexture(client_id);
4070 if (!group_->bind_generates_resource()) {
4071 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4073 "id not generated by glGenTextures");
4077 // It's a new id so make a texture texture for it.
4078 glGenTextures(1, &service_id);
4079 DCHECK_NE(0u, service_id);
4080 CreateTexture(client_id, service_id);
4081 texture_ref = GetTexture(client_id);
4082 IdAllocatorInterface* id_allocator =
4083 group_->GetIdAllocator(id_namespaces::kTextures);
4084 id_allocator->MarkAsUsed(client_id);
4087 texture_ref = texture_manager()->GetDefaultTextureInfo(target);
4090 // Check the texture exists
4092 Texture* texture = texture_ref->texture();
4093 // Check that we are not trying to bind it to a different target.
4094 if (texture->target() != 0 && texture->target() != target) {
4095 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4097 "texture bound to more than 1 target.");
4100 LogClientServiceForInfo(texture, client_id, "glBindTexture");
4101 if (texture->target() == 0) {
4102 texture_manager()->SetTarget(texture_ref, target);
4104 glBindTexture(target, texture->service_id());
4106 glBindTexture(target, 0);
4109 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4110 unit.bind_target = target;
4113 unit.bound_texture_2d = texture_ref;
4115 case GL_TEXTURE_CUBE_MAP:
4116 unit.bound_texture_cube_map = texture_ref;
4118 case GL_TEXTURE_EXTERNAL_OES:
4119 unit.bound_texture_external_oes = texture_ref;
4121 case GL_TEXTURE_RECTANGLE_ARB:
4122 unit.bound_texture_rectangle_arb = texture_ref;
4125 NOTREACHED(); // Validation should prevent us getting here.
4130 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
4131 if (state_.vertex_attrib_manager->Enable(index, false)) {
4133 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
4134 glDisableVertexAttribArray(index);
4139 "glDisableVertexAttribArray", "index out of range");
4143 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target,
4144 GLsizei numAttachments,
4145 const GLenum* attachments) {
4146 Framebuffer* framebuffer =
4147 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4149 // Validates the attachments. If one of them fails
4150 // the whole command fails.
4151 for (GLsizei i = 0; i < numAttachments; ++i) {
4153 !validators_->attachment.IsValid(attachments[i])) ||
4155 !validators_->backbuffer_attachment.IsValid(attachments[i]))) {
4156 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4157 "glDiscardFramebufferEXT", attachments[i], "attachments");
4162 // Marks each one of them as not cleared
4163 for (GLsizei i = 0; i < numAttachments; ++i) {
4165 framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
4170 switch (attachments[i]) {
4172 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
4175 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
4176 case GL_STENCIL_EXT:
4177 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
4186 // If the default framebuffer is bound but we are still rendering to an
4187 // FBO, translate attachment names that refer to default framebuffer
4188 // channels to corresponding framebuffer attachments.
4189 scoped_ptr<GLenum[]> translated_attachments(new GLenum[numAttachments]);
4190 for (GLsizei i = 0; i < numAttachments; ++i) {
4191 GLenum attachment = attachments[i];
4192 if (!framebuffer && GetBackbufferServiceId()) {
4193 switch (attachment) {
4195 attachment = GL_COLOR_ATTACHMENT0;
4198 attachment = GL_DEPTH_ATTACHMENT;
4200 case GL_STENCIL_EXT:
4201 attachment = GL_STENCIL_ATTACHMENT;
4208 translated_attachments[i] = attachment;
4211 glDiscardFramebufferEXT(target, numAttachments, translated_attachments.get());
4214 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
4215 if (state_.vertex_attrib_manager->Enable(index, true)) {
4216 glEnableVertexAttribArray(index);
4219 GL_INVALID_VALUE, "glEnableVertexAttribArray", "index out of range");
4223 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
4224 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
4227 !texture_manager()->CanGenerateMipmaps(texture_ref)) {
4229 GL_INVALID_OPERATION, "glGenerateMipmap", "Can not generate mips");
4233 if (target == GL_TEXTURE_CUBE_MAP) {
4234 for (int i = 0; i < 6; ++i) {
4235 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
4236 if (!texture_manager()->ClearTextureLevel(this, texture_ref, face, 0)) {
4238 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4243 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 0)) {
4245 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4250 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4251 // Workaround for Mac driver bug. In the large scheme of things setting
4252 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4253 // hit so there's probably no need to make this conditional. The bug appears
4254 // to be that if the filtering mode is set to something that doesn't require
4255 // mipmaps for rendering, or is never set to something other than the default,
4256 // then glGenerateMipmap misbehaves.
4257 if (workarounds().set_texture_filter_before_generating_mipmap) {
4258 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4260 glGenerateMipmapEXT(target);
4261 if (workarounds().set_texture_filter_before_generating_mipmap) {
4262 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
4263 texture_ref->texture()->min_filter());
4265 GLenum error = LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4266 if (error == GL_NO_ERROR) {
4267 texture_manager()->MarkMipmapsGenerated(texture_ref);
4271 bool GLES2DecoderImpl::GetHelper(
4272 GLenum pname, GLint* params, GLsizei* num_written) {
4273 DCHECK(num_written);
4274 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
4276 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
4278 // Return the GL implementation's preferred format and (see below type)
4279 // if we have the GL extension that exposes this. This allows the GPU
4280 // client to use the implementation's preferred format for glReadPixels
4281 // for optimisation.
4283 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4284 // case when requested on integer/floating point buffers but which is
4285 // acceptable on GLES2 and with the GL_OES_read_format extension.
4287 // Therefore if an error occurs we swallow the error and use the
4288 // internal implementation.
4290 if (context_->HasExtension("GL_OES_read_format")) {
4291 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4293 glGetIntegerv(pname, params);
4294 if (glGetError() == GL_NO_ERROR)
4297 *params = GLES2Util::GetPreferredGLReadPixelsFormat(
4298 GetBoundReadFrameBufferInternalFormat());
4301 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
4304 if (context_->HasExtension("GL_OES_read_format")) {
4305 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4307 glGetIntegerv(pname, params);
4308 if (glGetError() == GL_NO_ERROR)
4311 *params = GLES2Util::GetPreferredGLReadPixelsType(
4312 GetBoundReadFrameBufferInternalFormat(),
4313 GetBoundReadFrameBufferTextureType());
4316 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
4319 *params = group_->max_fragment_uniform_vectors();
4322 case GL_MAX_VARYING_VECTORS:
4325 *params = group_->max_varying_vectors();
4328 case GL_MAX_VERTEX_UNIFORM_VECTORS:
4331 *params = group_->max_vertex_uniform_vectors();
4337 case GL_MAX_VIEWPORT_DIMS:
4338 if (offscreen_target_frame_buffer_.get()) {
4341 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4342 params[1] = renderbuffer_manager()->max_renderbuffer_size();
4347 case GL_MAX_SAMPLES:
4350 params[0] = renderbuffer_manager()->max_samples();
4353 case GL_MAX_RENDERBUFFER_SIZE:
4356 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4359 case GL_MAX_TEXTURE_SIZE:
4362 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
4365 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
4368 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
4371 case GL_MAX_COLOR_ATTACHMENTS_EXT:
4374 params[0] = group_->max_color_attachments();
4377 case GL_MAX_DRAW_BUFFERS_ARB:
4380 params[0] = group_->max_draw_buffers();
4387 glGetIntegerv(GL_ALPHA_BITS, &v);
4388 params[0] = BoundFramebufferHasColorAttachmentWithAlpha(false) ? v : 0;
4395 glGetIntegerv(GL_DEPTH_BITS, &v);
4396 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
4399 case GL_STENCIL_BITS:
4403 glGetIntegerv(GL_STENCIL_BITS, &v);
4404 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
4407 case GL_COMPRESSED_TEXTURE_FORMATS:
4408 *num_written = validators_->compressed_texture_format.GetValues().size();
4410 for (GLint ii = 0; ii < *num_written; ++ii) {
4411 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
4415 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
4418 *params = validators_->compressed_texture_format.GetValues().size();
4421 case GL_NUM_SHADER_BINARY_FORMATS:
4424 *params = validators_->shader_binary_format.GetValues().size();
4427 case GL_SHADER_BINARY_FORMATS:
4428 *num_written = validators_->shader_binary_format.GetValues().size();
4430 for (GLint ii = 0; ii < *num_written; ++ii) {
4431 params[ii] = validators_->shader_binary_format.GetValues()[ii];
4435 case GL_SHADER_COMPILER:
4441 case GL_ARRAY_BUFFER_BINDING:
4444 if (state_.bound_array_buffer.get()) {
4445 GLuint client_id = 0;
4446 buffer_manager()->GetClientId(state_.bound_array_buffer->service_id(),
4448 *params = client_id;
4454 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
4457 if (state_.vertex_attrib_manager->element_array_buffer()) {
4458 GLuint client_id = 0;
4459 buffer_manager()->GetClientId(
4460 state_.vertex_attrib_manager->element_array_buffer()->
4461 service_id(), &client_id);
4462 *params = client_id;
4468 case GL_FRAMEBUFFER_BINDING:
4469 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
4472 Framebuffer* framebuffer =
4473 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4475 GLuint client_id = 0;
4476 framebuffer_manager()->GetClientId(
4477 framebuffer->service_id(), &client_id);
4478 *params = client_id;
4484 case GL_READ_FRAMEBUFFER_BINDING_EXT:
4487 Framebuffer* framebuffer =
4488 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
4490 GLuint client_id = 0;
4491 framebuffer_manager()->GetClientId(
4492 framebuffer->service_id(), &client_id);
4493 *params = client_id;
4499 case GL_RENDERBUFFER_BINDING:
4502 Renderbuffer* renderbuffer =
4503 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4505 *params = renderbuffer->client_id();
4511 case GL_CURRENT_PROGRAM:
4514 if (state_.current_program.get()) {
4515 GLuint client_id = 0;
4516 program_manager()->GetClientId(
4517 state_.current_program->service_id(), &client_id);
4518 *params = client_id;
4524 case GL_VERTEX_ARRAY_BINDING_OES:
4527 if (state_.vertex_attrib_manager.get() !=
4528 state_.default_vertex_attrib_manager.get()) {
4529 GLuint client_id = 0;
4530 vertex_array_manager_->GetClientId(
4531 state_.vertex_attrib_manager->service_id(), &client_id);
4532 *params = client_id;
4538 case GL_TEXTURE_BINDING_2D:
4541 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4542 if (unit.bound_texture_2d.get()) {
4543 *params = unit.bound_texture_2d->client_id();
4549 case GL_TEXTURE_BINDING_CUBE_MAP:
4552 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4553 if (unit.bound_texture_cube_map.get()) {
4554 *params = unit.bound_texture_cube_map->client_id();
4560 case GL_TEXTURE_BINDING_EXTERNAL_OES:
4563 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4564 if (unit.bound_texture_external_oes.get()) {
4565 *params = unit.bound_texture_external_oes->client_id();
4571 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
4574 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4575 if (unit.bound_texture_rectangle_arb.get()) {
4576 *params = unit.bound_texture_rectangle_arb->client_id();
4582 case GL_UNPACK_FLIP_Y_CHROMIUM:
4585 params[0] = unpack_flip_y_;
4588 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
4591 params[0] = unpack_premultiply_alpha_;
4594 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
4597 params[0] = unpack_unpremultiply_alpha_;
4600 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
4603 params[0] = group_->bind_generates_resource() ? 1 : 0;
4607 if (pname >= GL_DRAW_BUFFER0_ARB &&
4608 pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
4611 Framebuffer* framebuffer =
4612 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4614 params[0] = framebuffer->GetDrawBuffer(pname);
4615 } else { // backbuffer
4616 if (pname == GL_DRAW_BUFFER0_ARB)
4617 params[0] = group_->draw_buffer();
4619 params[0] = GL_NONE;
4624 *num_written = util_.GLGetNumValuesReturned(pname);
4629 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
4630 GLenum pname, GLsizei* num_values) {
4631 if (state_.GetStateAsGLint(pname, NULL, num_values)) {
4634 return GetHelper(pname, NULL, num_values);
4637 GLenum GLES2DecoderImpl::AdjustGetPname(GLenum pname) {
4638 if (GL_MAX_SAMPLES == pname &&
4639 features().use_img_for_multisampled_render_to_texture) {
4640 return GL_MAX_SAMPLES_IMG;
4645 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
4647 GLsizei num_written = 0;
4648 if (GetNumValuesReturnedForGLGet(pname, &num_written)) {
4649 scoped_ptr<GLint[]> values(new GLint[num_written]);
4650 if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) {
4651 GetHelper(pname, values.get(), &num_written);
4653 for (GLsizei ii = 0; ii < num_written; ++ii) {
4654 params[ii] = static_cast<GLboolean>(values[ii]);
4657 pname = AdjustGetPname(pname);
4658 glGetBooleanv(pname, params);
4662 void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
4664 GLsizei num_written = 0;
4665 if (!state_.GetStateAsGLfloat(pname, params, &num_written)) {
4666 if (GetHelper(pname, NULL, &num_written)) {
4667 scoped_ptr<GLint[]> values(new GLint[num_written]);
4668 GetHelper(pname, values.get(), &num_written);
4669 for (GLsizei ii = 0; ii < num_written; ++ii) {
4670 params[ii] = static_cast<GLfloat>(values[ii]);
4673 pname = AdjustGetPname(pname);
4674 glGetFloatv(pname, params);
4679 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
4681 GLsizei num_written;
4682 if (!state_.GetStateAsGLint(pname, params, &num_written) &&
4683 !GetHelper(pname, params, &num_written)) {
4684 pname = AdjustGetPname(pname);
4685 glGetIntegerv(pname, params);
4689 void GLES2DecoderImpl::DoGetProgramiv(
4690 GLuint program_id, GLenum pname, GLint* params) {
4691 Program* program = GetProgramInfoNotShader(program_id, "glGetProgramiv");
4695 program->GetProgramiv(pname, params);
4698 void GLES2DecoderImpl::DoGetBufferParameteriv(
4699 GLenum target, GLenum pname, GLint* params) {
4700 // Just delegate it. Some validation is actually done before this.
4701 buffer_manager()->ValidateAndDoGetBufferParameteriv(
4702 &state_, target, pname, params);
4705 void GLES2DecoderImpl::DoBindAttribLocation(
4706 GLuint program_id, GLuint index, const char* name) {
4707 if (!StringIsValidForGLES(name)) {
4709 GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
4712 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
4714 GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
4717 if (index >= group_->max_vertex_attribs()) {
4719 GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
4722 Program* program = GetProgramInfoNotShader(
4723 program_id, "glBindAttribLocation");
4727 program->SetAttribLocationBinding(name, static_cast<GLint>(index));
4728 glBindAttribLocation(program->service_id(), index, name);
4731 error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
4732 uint32 immediate_data_size, const cmds::BindAttribLocationBucket& c) {
4733 GLuint program = static_cast<GLuint>(c.program);
4734 GLuint index = static_cast<GLuint>(c.index);
4735 Bucket* bucket = GetBucket(c.name_bucket_id);
4736 if (!bucket || bucket->size() == 0) {
4737 return error::kInvalidArguments;
4739 std::string name_str;
4740 if (!bucket->GetAsString(&name_str)) {
4741 return error::kInvalidArguments;
4743 DoBindAttribLocation(program, index, name_str.c_str());
4744 return error::kNoError;
4747 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
4748 GLuint program_id, GLint location, const char* name) {
4749 if (!StringIsValidForGLES(name)) {
4752 "glBindUniformLocationCHROMIUM", "Invalid character");
4755 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
4757 GL_INVALID_OPERATION,
4758 "glBindUniformLocationCHROMIUM", "reserved prefix");
4761 if (location < 0 || static_cast<uint32>(location) >=
4762 (group_->max_fragment_uniform_vectors() +
4763 group_->max_vertex_uniform_vectors()) * 4) {
4766 "glBindUniformLocationCHROMIUM", "location out of range");
4769 Program* program = GetProgramInfoNotShader(
4770 program_id, "glBindUniformLocationCHROMIUM");
4774 if (!program->SetUniformLocationBinding(name, location)) {
4777 "glBindUniformLocationCHROMIUM", "location out of range");
4781 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
4782 uint32 immediate_data_size,
4783 const cmds::BindUniformLocationCHROMIUMBucket& c) {
4784 GLuint program = static_cast<GLuint>(c.program);
4785 GLint location = static_cast<GLint>(c.location);
4786 Bucket* bucket = GetBucket(c.name_bucket_id);
4787 if (!bucket || bucket->size() == 0) {
4788 return error::kInvalidArguments;
4790 std::string name_str;
4791 if (!bucket->GetAsString(&name_str)) {
4792 return error::kInvalidArguments;
4794 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4795 return error::kNoError;
4798 error::Error GLES2DecoderImpl::HandleDeleteShader(
4799 uint32 immediate_data_size, const cmds::DeleteShader& c) {
4800 GLuint client_id = c.shader;
4802 Shader* shader = GetShader(client_id);
4804 if (!shader->IsDeleted()) {
4805 glDeleteShader(shader->service_id());
4806 shader_manager()->MarkAsDeleted(shader);
4809 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
4812 return error::kNoError;
4815 error::Error GLES2DecoderImpl::HandleDeleteProgram(
4816 uint32 immediate_data_size, const cmds::DeleteProgram& c) {
4817 GLuint client_id = c.program;
4819 Program* program = GetProgram(client_id);
4821 if (!program->IsDeleted()) {
4822 program_manager()->MarkAsDeleted(shader_manager(), program);
4826 GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
4829 return error::kNoError;
4832 void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
4833 GLuint namespace_id, GLsizei n, const GLuint* ids) {
4834 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4835 for (GLsizei ii = 0; ii < n; ++ii) {
4836 id_allocator->FreeID(ids[ii]);
4840 error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
4841 uint32 immediate_data_size, const cmds::DeleteSharedIdsCHROMIUM& c) {
4842 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4843 GLsizei n = static_cast<GLsizei>(c.n);
4845 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4846 return error::kOutOfBounds;
4848 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
4849 c.ids_shm_id, c.ids_shm_offset, data_size);
4851 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM", "n < 0");
4852 return error::kNoError;
4855 return error::kOutOfBounds;
4857 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
4858 return error::kNoError;
4861 void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
4862 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
4863 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4864 if (id_offset == 0) {
4865 for (GLsizei ii = 0; ii < n; ++ii) {
4866 ids[ii] = id_allocator->AllocateID();
4869 for (GLsizei ii = 0; ii < n; ++ii) {
4870 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
4871 id_offset = ids[ii] + 1;
4876 error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
4877 uint32 immediate_data_size, const cmds::GenSharedIdsCHROMIUM& c) {
4878 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4879 GLuint id_offset = static_cast<GLuint>(c.id_offset);
4880 GLsizei n = static_cast<GLsizei>(c.n);
4882 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4883 return error::kOutOfBounds;
4885 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4886 c.ids_shm_id, c.ids_shm_offset, data_size);
4888 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM", "n < 0");
4889 return error::kNoError;
4892 return error::kOutOfBounds;
4894 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
4895 return error::kNoError;
4898 void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
4899 GLuint namespace_id, GLsizei n, const GLuint* ids) {
4900 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4901 for (GLsizei ii = 0; ii < n; ++ii) {
4902 if (!id_allocator->MarkAsUsed(ids[ii])) {
4903 for (GLsizei jj = 0; jj < ii; ++jj) {
4904 id_allocator->FreeID(ids[jj]);
4907 GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM",
4908 "attempt to register id that already exists");
4914 error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
4915 uint32 immediate_data_size, const cmds::RegisterSharedIdsCHROMIUM& c) {
4916 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4917 GLsizei n = static_cast<GLsizei>(c.n);
4919 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4920 return error::kOutOfBounds;
4922 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4923 c.ids_shm_id, c.ids_shm_offset, data_size);
4925 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM", "n < 0");
4926 return error::kNoError;
4929 return error::kOutOfBounds;
4931 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
4932 return error::kNoError;
4935 error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
4936 DCHECK(!ShouldDeferDraws());
4937 if (CheckBoundFramebuffersValid("glClear")) {
4941 return error::kNoError;
4944 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
4945 GLenum target, GLenum attachment, GLenum renderbuffertarget,
4946 GLuint client_renderbuffer_id) {
4947 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
4950 GL_INVALID_OPERATION,
4951 "glFramebufferRenderbuffer", "no framebuffer bound");
4954 GLuint service_id = 0;
4955 Renderbuffer* renderbuffer = NULL;
4956 if (client_renderbuffer_id) {
4957 renderbuffer = GetRenderbuffer(client_renderbuffer_id);
4958 if (!renderbuffer) {
4960 GL_INVALID_OPERATION,
4961 "glFramebufferRenderbuffer", "unknown renderbuffer");
4964 service_id = renderbuffer->service_id();
4966 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
4967 glFramebufferRenderbufferEXT(
4968 target, attachment, renderbuffertarget, service_id);
4969 GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
4970 if (error == GL_NO_ERROR) {
4971 framebuffer->AttachRenderbuffer(attachment, renderbuffer);
4973 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
4974 framebuffer_state_.clear_state_dirty = true;
4979 void GLES2DecoderImpl::DoDisable(GLenum cap) {
4980 if (SetCapabilityState(cap, false)) {
4985 void GLES2DecoderImpl::DoEnable(GLenum cap) {
4986 if (SetCapabilityState(cap, true)) {
4991 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear, GLclampf zfar) {
4992 state_.z_near = std::min(1.0f, std::max(0.0f, znear));
4993 state_.z_far = std::min(1.0f, std::max(0.0f, zfar));
4994 glDepthRange(znear, zfar);
4997 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value, GLboolean invert) {
4998 state_.sample_coverage_value = std::min(1.0f, std::max(0.0f, value));
4999 state_.sample_coverage_invert = (invert != 0);
5000 glSampleCoverage(state_.sample_coverage_value, invert);
5003 // Assumes framebuffer is complete.
5004 void GLES2DecoderImpl::ClearUnclearedAttachments(
5005 GLenum target, Framebuffer* framebuffer) {
5006 if (target == GL_READ_FRAMEBUFFER_EXT) {
5007 // bind this to the DRAW point, clear then bind back to READ
5008 // TODO(gman): I don't think there is any guarantee that an FBO that
5009 // is complete on the READ attachment will be complete as a DRAW
5011 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
5012 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer->service_id());
5014 GLbitfield clear_bits = 0;
5015 if (framebuffer->HasUnclearedColorAttachments()) {
5018 (GLES2Util::GetChannelsForFormat(
5019 framebuffer->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f :
5021 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5022 clear_bits |= GL_COLOR_BUFFER_BIT;
5023 if (feature_info_->feature_flags().ext_draw_buffers)
5024 framebuffer->PrepareDrawBuffersForClear();
5027 if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
5028 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5030 state_.SetDeviceStencilMaskSeparate(GL_FRONT, -1);
5031 state_.SetDeviceStencilMaskSeparate(GL_BACK, -1);
5032 clear_bits |= GL_STENCIL_BUFFER_BIT;
5035 if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
5036 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5038 state_.SetDeviceDepthMask(GL_TRUE);
5039 clear_bits |= GL_DEPTH_BUFFER_BIT;
5042 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5043 glClear(clear_bits);
5045 if ((clear_bits | GL_COLOR_BUFFER_BIT) != 0 &&
5046 feature_info_->feature_flags().ext_draw_buffers)
5047 framebuffer->RestoreDrawBuffersAfterClear();
5049 framebuffer_manager()->MarkAttachmentsAsCleared(
5050 framebuffer, renderbuffer_manager(), texture_manager());
5052 RestoreClearState();
5054 if (target == GL_READ_FRAMEBUFFER_EXT) {
5055 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer->service_id());
5056 Framebuffer* draw_framebuffer =
5057 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5058 GLuint service_id = draw_framebuffer ? draw_framebuffer->service_id() :
5059 GetBackbufferServiceId();
5060 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
5064 void GLES2DecoderImpl::RestoreClearState() {
5065 framebuffer_state_.clear_state_dirty = true;
5067 state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
5068 state_.color_clear_alpha);
5069 glClearStencil(state_.stencil_clear);
5070 glClearDepth(state_.depth_clear);
5071 if (state_.enable_flags.scissor_test) {
5072 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
5076 GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
5077 Framebuffer* framebuffer =
5078 GetFramebufferInfoForTarget(target);
5080 return GL_FRAMEBUFFER_COMPLETE;
5082 GLenum completeness = framebuffer->IsPossiblyComplete();
5083 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
5084 return completeness;
5086 return framebuffer->GetStatus(texture_manager(), target);
5089 void GLES2DecoderImpl::DoFramebufferTexture2D(
5090 GLenum target, GLenum attachment, GLenum textarget,
5091 GLuint client_texture_id, GLint level) {
5092 DoFramebufferTexture2DCommon(
5093 "glFramebufferTexture2D", target, attachment,
5094 textarget, client_texture_id, level, 0);
5097 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5098 GLenum target, GLenum attachment, GLenum textarget,
5099 GLuint client_texture_id, GLint level, GLsizei samples) {
5100 DoFramebufferTexture2DCommon(
5101 "glFramebufferTexture2DMultisample", target, attachment,
5102 textarget, client_texture_id, level, samples);
5105 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5106 const char* name, GLenum target, GLenum attachment, GLenum textarget,
5107 GLuint client_texture_id, GLint level, GLsizei samples) {
5108 if (samples > renderbuffer_manager()->max_samples()) {
5111 "glFramebufferTexture2DMultisample", "samples too large");
5114 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5117 GL_INVALID_OPERATION,
5118 name, "no framebuffer bound.");
5121 GLuint service_id = 0;
5122 TextureRef* texture_ref = NULL;
5123 if (client_texture_id) {
5124 texture_ref = GetTexture(client_texture_id);
5127 GL_INVALID_OPERATION,
5128 name, "unknown texture_ref");
5131 service_id = texture_ref->service_id();
5134 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
5137 name, "level out of range");
5142 DoWillUseTexImageIfNeeded(texture_ref->texture(), textarget);
5144 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name);
5146 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
5148 if (features().use_img_for_multisampled_render_to_texture) {
5149 glFramebufferTexture2DMultisampleIMG(target, attachment, textarget,
5150 service_id, level, samples);
5152 glFramebufferTexture2DMultisampleEXT(target, attachment, textarget,
5153 service_id, level, samples);
5156 GLenum error = LOCAL_PEEK_GL_ERROR(name);
5157 if (error == GL_NO_ERROR) {
5158 framebuffer->AttachTexture(attachment, texture_ref, textarget, level,
5161 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5162 framebuffer_state_.clear_state_dirty = true;
5166 DoDidUseTexImageIfNeeded(texture_ref->texture(), textarget);
5171 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5172 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
5173 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5176 GL_INVALID_OPERATION,
5177 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5180 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
5181 const Framebuffer::Attachment* attachment_object =
5182 framebuffer->GetAttachment(attachment);
5183 *params = attachment_object ? attachment_object->object_name() : 0;
5185 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT &&
5186 features().use_img_for_multisampled_render_to_texture) {
5187 pname = GL_TEXTURE_SAMPLES_IMG;
5189 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
5193 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5194 GLenum target, GLenum pname, GLint* params) {
5195 Renderbuffer* renderbuffer =
5196 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5197 if (!renderbuffer) {
5199 GL_INVALID_OPERATION,
5200 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5204 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5205 *params = renderbuffer->internal_format();
5207 case GL_RENDERBUFFER_WIDTH:
5208 *params = renderbuffer->width();
5210 case GL_RENDERBUFFER_HEIGHT:
5211 *params = renderbuffer->height();
5213 case GL_RENDERBUFFER_SAMPLES_EXT:
5214 if (features().use_img_for_multisampled_render_to_texture) {
5215 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_IMG,
5218 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_EXT,
5222 glGetRenderbufferParameterivEXT(target, pname, params);
5227 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5228 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
5229 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5230 GLbitfield mask, GLenum filter) {
5231 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5233 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5237 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5238 BlitFramebufferHelper(
5239 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5240 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST,
5241 state_.enable_flags.scissor_test);
5244 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
5245 const FeatureInfo* feature_info,
5248 GLenum internal_format,
5251 // TODO(sievers): This could be resolved at the GL binding level, but the
5252 // binding process is currently a bit too 'brute force'.
5253 if (feature_info->feature_flags().is_angle) {
5254 glRenderbufferStorageMultisampleANGLE(
5255 target, samples, internal_format, width, height);
5256 } else if (feature_info->feature_flags().use_core_framebuffer_multisample) {
5257 glRenderbufferStorageMultisample(
5258 target, samples, internal_format, width, height);
5260 glRenderbufferStorageMultisampleEXT(
5261 target, samples, internal_format, width, height);
5265 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0,
5275 // TODO(sievers): This could be resolved at the GL binding level, but the
5276 // binding process is currently a bit too 'brute force'.
5277 if (feature_info_->feature_flags().is_angle) {
5278 glBlitFramebufferANGLE(
5279 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5280 } else if (feature_info_->feature_flags().use_core_framebuffer_multisample) {
5282 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5284 glBlitFramebufferEXT(
5285 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5289 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
5291 GLenum internalformat,
5294 if (samples > renderbuffer_manager()->max_samples()) {
5297 "glRenderbufferStorageMultisample", "samples too large");
5301 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5302 height > renderbuffer_manager()->max_renderbuffer_size()) {
5305 "glRenderbufferStorageMultisample", "dimensions too large");
5309 uint32 estimated_size = 0;
5310 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5311 width, height, samples, internalformat, &estimated_size)) {
5314 "glRenderbufferStorageMultisample", "dimensions too large");
5318 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5321 "glRenderbufferStorageMultisample", "out of memory");
5328 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
5329 GLenum target, GLsizei samples, GLenum internalformat,
5330 GLsizei width, GLsizei height) {
5331 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5332 if (!renderbuffer) {
5333 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5334 "glRenderbufferStorageMultisampleCHROMIUM",
5335 "no renderbuffer bound");
5339 if (!ValidateRenderbufferStorageMultisample(
5340 samples, internalformat, width, height)) {
5344 GLenum impl_format =
5345 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5347 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
5348 "glRenderbufferStorageMultisampleCHROMIUM");
5349 RenderbufferStorageMultisampleHelper(
5350 feature_info_, target, samples, impl_format, width, height);
5352 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
5353 if (error == GL_NO_ERROR) {
5355 if (workarounds().validate_multisample_buffer_allocation) {
5356 if (!VerifyMultisampleRenderbufferIntegrity(
5357 renderbuffer->service_id(), impl_format)) {
5360 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
5365 // TODO(gman): If renderbuffers tracked which framebuffers they were
5366 // attached to we could just mark those framebuffers as not complete.
5367 framebuffer_manager()->IncFramebufferStateChangeCount();
5368 renderbuffer_manager()->SetInfo(
5369 renderbuffer, samples, internalformat, width, height);
5373 // This is the handler for multisampled_render_to_texture extensions.
5374 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
5375 GLenum target, GLsizei samples, GLenum internalformat,
5376 GLsizei width, GLsizei height) {
5377 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5378 if (!renderbuffer) {
5379 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5380 "glRenderbufferStorageMultisampleEXT",
5381 "no renderbuffer bound");
5385 if (!ValidateRenderbufferStorageMultisample(
5386 samples, internalformat, width, height)) {
5390 GLenum impl_format =
5391 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5393 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
5394 if (features().use_img_for_multisampled_render_to_texture) {
5395 glRenderbufferStorageMultisampleIMG(
5396 target, samples, impl_format, width, height);
5398 glRenderbufferStorageMultisampleEXT(
5399 target, samples, impl_format, width, height);
5401 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
5402 if (error == GL_NO_ERROR) {
5403 // TODO(gman): If renderbuffers tracked which framebuffers they were
5404 // attached to we could just mark those framebuffers as not complete.
5405 framebuffer_manager()->IncFramebufferStateChangeCount();
5406 renderbuffer_manager()->SetInfo(
5407 renderbuffer, samples, internalformat, width, height);
5411 // This function validates the allocation of a multisampled renderbuffer
5412 // by clearing it to a key color, blitting the contents to a texture, and
5413 // reading back the color to ensure it matches the key.
5414 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
5415 GLuint renderbuffer, GLenum format) {
5417 // Only validate color buffers.
5418 // These formats have been selected because they are very common or are known
5419 // to be used by the WebGL backbuffer. If problems are observed with other
5420 // color formats they can be added here.
5431 GLint draw_framebuffer, read_framebuffer;
5433 // Cache framebuffer and texture bindings.
5434 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer);
5435 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
5437 if (!validation_texture_) {
5438 GLint bound_texture;
5439 glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture);
5441 // Create additional resources needed for the verification.
5442 glGenTextures(1, &validation_texture_);
5443 glGenFramebuffersEXT(1, &validation_fbo_multisample_);
5444 glGenFramebuffersEXT(1, &validation_fbo_);
5446 // Texture only needs to be 1x1.
5447 glBindTexture(GL_TEXTURE_2D, validation_texture_);
5448 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB,
5449 GL_UNSIGNED_BYTE, NULL);
5451 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5452 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5453 GL_TEXTURE_2D, validation_texture_, 0);
5455 glBindTexture(GL_TEXTURE_2D, bound_texture);
5458 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5459 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5460 GL_RENDERBUFFER, renderbuffer);
5462 // Cache current state and reset it to the values we require.
5463 GLboolean scissor_enabled = false;
5464 glGetBooleanv(GL_SCISSOR_TEST, &scissor_enabled);
5465 if (scissor_enabled)
5466 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5468 GLboolean color_mask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
5469 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
5470 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5472 GLfloat clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
5473 glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color);
5474 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
5476 // Clear the buffer to the desired key color.
5477 glClear(GL_COLOR_BUFFER_BIT);
5479 // Blit from the multisample buffer to a standard texture.
5480 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, validation_fbo_multisample_);
5481 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, validation_fbo_);
5483 BlitFramebufferHelper(
5484 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
5486 // Read a pixel from the buffer.
5487 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5489 unsigned char pixel[3] = {0, 0, 0};
5490 glReadPixels(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel);
5492 // Detach the renderbuffer.
5493 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5494 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5495 GL_RENDERBUFFER, 0);
5497 // Restore cached state.
5498 if (scissor_enabled)
5499 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
5501 state_.SetDeviceColorMask(
5502 color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
5503 glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
5504 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, draw_framebuffer);
5505 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_framebuffer);
5507 // Return true if the pixel matched the desired key color.
5508 return (pixel[0] == 0xFF &&
5513 void GLES2DecoderImpl::DoRenderbufferStorage(
5514 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
5515 Renderbuffer* renderbuffer =
5516 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5517 if (!renderbuffer) {
5519 GL_INVALID_OPERATION,
5520 "glRenderbufferStorage", "no renderbuffer bound");
5524 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5525 height > renderbuffer_manager()->max_renderbuffer_size()) {
5527 GL_INVALID_VALUE, "glRenderbufferStorage", "dimensions too large");
5531 uint32 estimated_size = 0;
5532 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5533 width, height, 1, internalformat, &estimated_size)) {
5535 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "dimensions too large");
5539 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5541 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "out of memory");
5545 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
5546 glRenderbufferStorageEXT(
5548 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5552 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
5553 if (error == GL_NO_ERROR) {
5554 // TODO(gman): If tetxures tracked which framebuffers they were attached to
5555 // we could just mark those framebuffers as not complete.
5556 framebuffer_manager()->IncFramebufferStateChangeCount();
5557 renderbuffer_manager()->SetInfo(
5558 renderbuffer, 1, internalformat, width, height);
5562 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
5563 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
5564 Program* program = GetProgramInfoNotShader(
5565 program_id, "glLinkProgram");
5570 LogClientServiceForInfo(program, program_id, "glLinkProgram");
5571 ShaderTranslator* vertex_translator = NULL;
5572 ShaderTranslator* fragment_translator = NULL;
5573 if (use_shader_translator_) {
5574 vertex_translator = vertex_translator_.get();
5575 fragment_translator = fragment_translator_.get();
5577 if (program->Link(shader_manager(),
5579 fragment_translator,
5580 workarounds().count_all_in_varyings_packing ?
5581 Program::kCountAll : Program::kCountOnlyStaticallyUsed,
5582 shader_cache_callback_)) {
5583 if (program == state_.current_program.get()) {
5584 if (workarounds().use_current_program_after_successful_link)
5585 glUseProgram(program->service_id());
5586 if (workarounds().clear_uniforms_before_first_program_use)
5587 program_manager()->ClearUniforms(program);
5592 void GLES2DecoderImpl::DoTexParameterf(
5593 GLenum target, GLenum pname, GLfloat param) {
5594 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5597 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
5601 texture_manager()->SetParameterf(
5602 "glTexParameterf", GetErrorState(), texture, pname, param);
5605 void GLES2DecoderImpl::DoTexParameteri(
5606 GLenum target, GLenum pname, GLint param) {
5607 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5610 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
5614 texture_manager()->SetParameteri(
5615 "glTexParameteri", GetErrorState(), texture, pname, param);
5618 void GLES2DecoderImpl::DoTexParameterfv(
5619 GLenum target, GLenum pname, const GLfloat* params) {
5620 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5623 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
5627 texture_manager()->SetParameterf(
5628 "glTexParameterfv", GetErrorState(), texture, pname, *params);
5631 void GLES2DecoderImpl::DoTexParameteriv(
5632 GLenum target, GLenum pname, const GLint* params) {
5633 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5637 GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
5641 texture_manager()->SetParameteri(
5642 "glTexParameteriv", GetErrorState(), texture, pname, *params);
5645 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
5646 if (!state_.current_program.get()) {
5647 // The program does not exist.
5649 GL_INVALID_OPERATION, function_name, "no program in use");
5652 if (!state_.current_program->InUse()) {
5654 GL_INVALID_OPERATION, function_name, "program not linked");
5660 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
5661 GLint location, const char* function_name) {
5662 if (!CheckCurrentProgram(function_name)) {
5665 return location != -1;
5668 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
5669 GLint fake_location,
5670 const char* function_name,
5671 Program::UniformApiType api_type,
5672 GLint* real_location,
5677 DCHECK(real_location);
5679 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
5682 GLint array_index = -1;
5683 const Program::UniformInfo* info =
5684 state_.current_program->GetUniformInfoByFakeLocation(
5685 fake_location, real_location, &array_index);
5688 GL_INVALID_OPERATION, function_name, "unknown location");
5692 if ((api_type & info->accepts_api_type) == 0) {
5694 GL_INVALID_OPERATION, function_name,
5695 "wrong uniform function for type");
5698 if (*count > 1 && !info->is_array) {
5700 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
5703 *count = std::min(info->size - array_index, *count);
5711 void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
5714 GLint real_location = -1;
5715 if (!PrepForSetUniformByLocation(fake_location,
5717 Program::kUniform1i,
5723 if (!state_.current_program->SetSamplers(
5724 state_.texture_units.size(), fake_location, 1, &v0)) {
5726 GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
5729 glUniform1i(real_location, v0);
5732 void GLES2DecoderImpl::DoUniform1iv(
5733 GLint fake_location, GLsizei count, const GLint *value) {
5735 GLint real_location = -1;
5736 if (!PrepForSetUniformByLocation(fake_location,
5738 Program::kUniform1i,
5744 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
5745 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
5746 if (!state_.current_program->SetSamplers(
5747 state_.texture_units.size(), fake_location, count, value)) {
5749 GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
5753 glUniform1iv(real_location, count, value);
5756 void GLES2DecoderImpl::DoUniform1fv(
5757 GLint fake_location, GLsizei count, const GLfloat* value) {
5759 GLint real_location = -1;
5760 if (!PrepForSetUniformByLocation(fake_location,
5762 Program::kUniform1f,
5768 if (type == GL_BOOL) {
5769 scoped_ptr<GLint[]> temp(new GLint[count]);
5770 for (GLsizei ii = 0; ii < count; ++ii) {
5771 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5773 DoUniform1iv(real_location, count, temp.get());
5775 glUniform1fv(real_location, count, value);
5779 void GLES2DecoderImpl::DoUniform2fv(
5780 GLint fake_location, GLsizei count, const GLfloat* value) {
5782 GLint real_location = -1;
5783 if (!PrepForSetUniformByLocation(fake_location,
5785 Program::kUniform2f,
5791 if (type == GL_BOOL_VEC2) {
5792 GLsizei num_values = count * 2;
5793 scoped_ptr<GLint[]> temp(new GLint[num_values]);
5794 for (GLsizei ii = 0; ii < num_values; ++ii) {
5795 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5797 glUniform2iv(real_location, count, temp.get());
5799 glUniform2fv(real_location, count, value);
5803 void GLES2DecoderImpl::DoUniform3fv(
5804 GLint fake_location, GLsizei count, const GLfloat* value) {
5806 GLint real_location = -1;
5807 if (!PrepForSetUniformByLocation(fake_location,
5809 Program::kUniform3f,
5815 if (type == GL_BOOL_VEC3) {
5816 GLsizei num_values = count * 3;
5817 scoped_ptr<GLint[]> temp(new GLint[num_values]);
5818 for (GLsizei ii = 0; ii < num_values; ++ii) {
5819 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5821 glUniform3iv(real_location, count, temp.get());
5823 glUniform3fv(real_location, count, value);
5827 void GLES2DecoderImpl::DoUniform4fv(
5828 GLint fake_location, GLsizei count, const GLfloat* value) {
5830 GLint real_location = -1;
5831 if (!PrepForSetUniformByLocation(fake_location,
5833 Program::kUniform4f,
5839 if (type == GL_BOOL_VEC4) {
5840 GLsizei num_values = count * 4;
5841 scoped_ptr<GLint[]> temp(new GLint[num_values]);
5842 for (GLsizei ii = 0; ii < num_values; ++ii) {
5843 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5845 glUniform4iv(real_location, count, temp.get());
5847 glUniform4fv(real_location, count, value);
5851 void GLES2DecoderImpl::DoUniform2iv(
5852 GLint fake_location, GLsizei count, const GLint* value) {
5854 GLint real_location = -1;
5855 if (!PrepForSetUniformByLocation(fake_location,
5857 Program::kUniform2i,
5863 glUniform2iv(real_location, count, value);
5866 void GLES2DecoderImpl::DoUniform3iv(
5867 GLint fake_location, GLsizei count, const GLint* value) {
5869 GLint real_location = -1;
5870 if (!PrepForSetUniformByLocation(fake_location,
5872 Program::kUniform3i,
5878 glUniform3iv(real_location, count, value);
5881 void GLES2DecoderImpl::DoUniform4iv(
5882 GLint fake_location, GLsizei count, const GLint* value) {
5884 GLint real_location = -1;
5885 if (!PrepForSetUniformByLocation(fake_location,
5887 Program::kUniform4i,
5893 glUniform4iv(real_location, count, value);
5896 void GLES2DecoderImpl::DoUniformMatrix2fv(
5897 GLint fake_location, GLsizei count, GLboolean transpose,
5898 const GLfloat* value) {
5900 GLint real_location = -1;
5901 if (!PrepForSetUniformByLocation(fake_location,
5902 "glUniformMatrix2fv",
5903 Program::kUniformMatrix2f,
5909 glUniformMatrix2fv(real_location, count, transpose, value);
5912 void GLES2DecoderImpl::DoUniformMatrix3fv(
5913 GLint fake_location, GLsizei count, GLboolean transpose,
5914 const GLfloat* value) {
5916 GLint real_location = -1;
5917 if (!PrepForSetUniformByLocation(fake_location,
5918 "glUniformMatrix3fv",
5919 Program::kUniformMatrix3f,
5925 glUniformMatrix3fv(real_location, count, transpose, value);
5928 void GLES2DecoderImpl::DoUniformMatrix4fv(
5929 GLint fake_location, GLsizei count, GLboolean transpose,
5930 const GLfloat* value) {
5932 GLint real_location = -1;
5933 if (!PrepForSetUniformByLocation(fake_location,
5934 "glUniformMatrix4fv",
5935 Program::kUniformMatrix4f,
5941 glUniformMatrix4fv(real_location, count, transpose, value);
5944 void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
5945 GLuint service_id = 0;
5946 Program* program = NULL;
5948 program = GetProgramInfoNotShader(program_id, "glUseProgram");
5952 if (!program->IsValid()) {
5953 // Program was not linked successfully. (ie, glLinkProgram)
5955 GL_INVALID_OPERATION, "glUseProgram", "program not linked");
5958 service_id = program->service_id();
5960 if (state_.current_program.get()) {
5961 program_manager()->UnuseProgram(shader_manager(),
5962 state_.current_program.get());
5964 state_.current_program = program;
5965 LogClientServiceMapping("glUseProgram", program_id, service_id);
5966 glUseProgram(service_id);
5967 if (state_.current_program.get()) {
5968 program_manager()->UseProgram(state_.current_program.get());
5969 if (workarounds().clear_uniforms_before_first_program_use)
5970 program_manager()->ClearUniforms(program);
5974 void GLES2DecoderImpl::RenderWarning(
5975 const char* filename, int line, const std::string& msg) {
5976 logger_.LogMessage(filename, line, std::string("RENDER WARNING: ") + msg);
5979 void GLES2DecoderImpl::PerformanceWarning(
5980 const char* filename, int line, const std::string& msg) {
5981 logger_.LogMessage(filename, line,
5982 std::string("PERFORMANCE WARNING: ") + msg);
5985 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
5986 Texture* texture, GLenum textarget) {
5987 // Image is already in use if texture is attached to a framebuffer.
5988 if (texture && !texture->IsAttachedToFramebuffer()) {
5989 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
5991 ScopedGLErrorSuppressor suppressor(
5992 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
5994 glBindTexture(textarget, texture->service_id());
5995 image->WillUseTexImage();
5996 RestoreCurrentTextureBindings(&state_, textarget);
6001 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6002 Texture* texture, GLenum textarget) {
6003 // Image is still in use if texture is attached to a framebuffer.
6004 if (texture && !texture->IsAttachedToFramebuffer()) {
6005 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6007 ScopedGLErrorSuppressor suppressor(
6008 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6010 glBindTexture(textarget, texture->service_id());
6011 image->DidUseTexImage();
6012 RestoreCurrentTextureBindings(&state_, textarget);
6017 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6018 DCHECK(state_.current_program.get());
6019 if (!texture_manager()->HaveUnrenderableTextures() &&
6020 !texture_manager()->HaveImages()) {
6024 bool textures_set = false;
6025 const Program::SamplerIndices& sampler_indices =
6026 state_.current_program->sampler_indices();
6027 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6028 const Program::UniformInfo* uniform_info =
6029 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6030 DCHECK(uniform_info);
6031 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6032 GLuint texture_unit_index = uniform_info->texture_units[jj];
6033 if (texture_unit_index < state_.texture_units.size()) {
6034 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6035 TextureRef* texture_ref =
6036 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6037 GLenum textarget = GetBindTargetForSamplerType(uniform_info->type);
6038 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6039 textures_set = true;
6040 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6043 texture_manager()->black_texture_id(uniform_info->type));
6044 LOCAL_RENDER_WARNING(
6045 std::string("texture bound to texture unit ") +
6046 base::IntToString(texture_unit_index) +
6047 " is not renderable. It maybe non-power-of-2 and have"
6048 " incompatible texture filtering or is not"
6049 " 'texture complete'");
6053 if (textarget != GL_TEXTURE_CUBE_MAP) {
6054 Texture* texture = texture_ref->texture();
6055 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6056 if (image && !texture->IsAttachedToFramebuffer()) {
6057 ScopedGLErrorSuppressor suppressor(
6058 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6059 textures_set = true;
6060 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6061 image->WillUseTexImage();
6066 // else: should this be an error?
6069 return !textures_set;
6072 void GLES2DecoderImpl::RestoreStateForTextures() {
6073 DCHECK(state_.current_program.get());
6074 const Program::SamplerIndices& sampler_indices =
6075 state_.current_program->sampler_indices();
6076 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6077 const Program::UniformInfo* uniform_info =
6078 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6079 DCHECK(uniform_info);
6080 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6081 GLuint texture_unit_index = uniform_info->texture_units[jj];
6082 if (texture_unit_index < state_.texture_units.size()) {
6083 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6084 TextureRef* texture_ref =
6085 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6086 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6087 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6088 // Get the texture_ref info that was previously bound here.
6089 texture_ref = texture_unit.bind_target == GL_TEXTURE_2D
6090 ? texture_unit.bound_texture_2d.get()
6091 : texture_unit.bound_texture_cube_map.get();
6092 glBindTexture(texture_unit.bind_target,
6093 texture_ref ? texture_ref->service_id() : 0);
6097 if (texture_unit.bind_target != GL_TEXTURE_CUBE_MAP) {
6098 Texture* texture = texture_ref->texture();
6099 gfx::GLImage* image =
6100 texture->GetLevelImage(texture_unit.bind_target, 0);
6101 if (image && !texture->IsAttachedToFramebuffer()) {
6102 ScopedGLErrorSuppressor suppressor(
6103 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
6104 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6105 image->DidUseTexImage();
6112 // Set the active texture back to whatever the user had it as.
6113 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
6116 bool GLES2DecoderImpl::ClearUnclearedTextures() {
6117 // Only check if there are some uncleared textures.
6118 if (!texture_manager()->HaveUnsafeTextures()) {
6122 // 1: Check all textures we are about to render with.
6123 if (state_.current_program.get()) {
6124 const Program::SamplerIndices& sampler_indices =
6125 state_.current_program->sampler_indices();
6126 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6127 const Program::UniformInfo* uniform_info =
6128 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6129 DCHECK(uniform_info);
6130 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6131 GLuint texture_unit_index = uniform_info->texture_units[jj];
6132 if (texture_unit_index < state_.texture_units.size()) {
6133 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6134 TextureRef* texture_ref =
6135 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6136 if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
6137 if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
6148 bool GLES2DecoderImpl::IsDrawValid(
6149 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount) {
6150 // NOTE: We specifically do not check current_program->IsValid() because
6151 // it could never be invalid since glUseProgram would have failed. While
6152 // glLinkProgram could later mark the program as invalid the previous
6153 // valid program will still function if it is still the current program.
6154 if (!state_.current_program.get()) {
6155 // The program does not exist.
6156 // But GL says no ERROR.
6157 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
6161 return state_.vertex_attrib_manager
6162 ->ValidateBindings(function_name,
6164 feature_info_.get(),
6165 state_.current_program.get(),
6166 max_vertex_accessed,
6170 bool GLES2DecoderImpl::SimulateAttrib0(
6171 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
6175 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
6178 const VertexAttrib* attrib =
6179 state_.vertex_attrib_manager->GetVertexAttrib(0);
6180 // If it's enabled or it's not used then we don't need to do anything.
6181 bool attrib_0_used =
6182 state_.current_program->GetAttribInfoByLocation(0) != NULL;
6183 if (attrib->enabled() && attrib_0_used) {
6187 // Make a buffer with a single repeated vec4 value enough to
6188 // simulate the constant value that is supposed to be here.
6189 // This is required to emulate GLES2 on GL.
6190 GLuint num_vertices = max_vertex_accessed + 1;
6191 uint32 size_needed = 0;
6193 if (num_vertices == 0 ||
6194 !SafeMultiplyUint32(num_vertices, sizeof(Vec4), &size_needed) ||
6195 size_needed > 0x7FFFFFFFU) {
6196 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6200 LOCAL_PERFORMANCE_WARNING(
6201 "Attribute 0 is disabled. This has signficant performance penalty");
6203 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6204 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
6206 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
6208 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6209 GLenum error = glGetError();
6210 if (error != GL_NO_ERROR) {
6212 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6217 const Vec4& value = state_.attrib_values[0];
6220 (!attrib_0_buffer_matches_value_ ||
6221 (value.v[0] != attrib_0_value_.v[0] ||
6222 value.v[1] != attrib_0_value_.v[1] ||
6223 value.v[2] != attrib_0_value_.v[2] ||
6224 value.v[3] != attrib_0_value_.v[3])))) {
6225 std::vector<Vec4> temp(num_vertices, value);
6226 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
6227 attrib_0_buffer_matches_value_ = true;
6228 attrib_0_value_ = value;
6229 attrib_0_size_ = size_needed;
6232 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
6234 if (attrib->divisor())
6235 glVertexAttribDivisorANGLE(0, 0);
6241 void GLES2DecoderImpl::RestoreStateForAttrib(
6242 GLuint attrib_index, bool restore_array_binding) {
6243 const VertexAttrib* attrib =
6244 state_.vertex_attrib_manager->GetVertexAttrib(attrib_index);
6245 if (restore_array_binding) {
6246 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
6247 Buffer* buffer = attrib->buffer();
6248 glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
6249 glVertexAttribPointer(
6250 attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
6251 attrib->gl_stride(), ptr);
6253 if (attrib->divisor())
6254 glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
6256 GL_ARRAY_BUFFER, state_.bound_array_buffer.get() ?
6257 state_.bound_array_buffer->service_id() : 0);
6259 // Never touch vertex attribute 0's state (in particular, never
6260 // disable it) when running on desktop GL because it will never be
6262 if (attrib_index != 0 ||
6263 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
6264 if (attrib->enabled()) {
6265 glEnableVertexAttribArray(attrib_index);
6267 glDisableVertexAttribArray(attrib_index);
6272 bool GLES2DecoderImpl::SimulateFixedAttribs(
6273 const char* function_name,
6274 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
6277 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
6280 if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
6284 LOCAL_PERFORMANCE_WARNING(
6285 "GL_FIXED attributes have a signficant performance penalty");
6287 // NOTE: we could be smart and try to check if a buffer is used
6288 // twice in 2 different attribs, find the overlapping parts and therefore
6289 // duplicate the minimum amount of data but this whole code path is not meant
6290 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
6291 // tests so we just add to the buffer attrib used.
6293 GLuint elements_needed = 0;
6294 const VertexAttribManager::VertexAttribList& enabled_attribs =
6295 state_.vertex_attrib_manager->GetEnabledVertexAttribs();
6296 for (VertexAttribManager::VertexAttribList::const_iterator it =
6297 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6298 const VertexAttrib* attrib = *it;
6299 const Program::VertexAttrib* attrib_info =
6300 state_.current_program->GetAttribInfoByLocation(attrib->index());
6301 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6302 max_vertex_accessed);
6303 GLuint num_vertices = max_accessed + 1;
6304 if (num_vertices == 0) {
6306 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6310 attrib->CanAccess(max_accessed) &&
6311 attrib->type() == GL_FIXED) {
6312 uint32 elements_used = 0;
6313 if (!SafeMultiplyUint32(num_vertices, attrib->size(), &elements_used) ||
6314 !SafeAddUint32(elements_needed, elements_used, &elements_needed)) {
6316 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6322 const uint32 kSizeOfFloat = sizeof(float); // NOLINT
6323 uint32 size_needed = 0;
6324 if (!SafeMultiplyUint32(elements_needed, kSizeOfFloat, &size_needed) ||
6325 size_needed > 0x7FFFFFFFU) {
6327 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6331 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6333 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
6334 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
6335 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6336 GLenum error = glGetError();
6337 if (error != GL_NO_ERROR) {
6339 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6344 // Copy the elements and convert to float
6345 GLintptr offset = 0;
6346 for (VertexAttribManager::VertexAttribList::const_iterator it =
6347 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6348 const VertexAttrib* attrib = *it;
6349 const Program::VertexAttrib* attrib_info =
6350 state_.current_program->GetAttribInfoByLocation(attrib->index());
6351 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6352 max_vertex_accessed);
6353 GLuint num_vertices = max_accessed + 1;
6354 if (num_vertices == 0) {
6356 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6360 attrib->CanAccess(max_accessed) &&
6361 attrib->type() == GL_FIXED) {
6362 int num_elements = attrib->size() * kSizeOfFloat;
6363 int size = num_elements * num_vertices;
6364 scoped_ptr<float[]> data(new float[size]);
6365 const int32* src = reinterpret_cast<const int32 *>(
6366 attrib->buffer()->GetRange(attrib->offset(), size));
6367 const int32* end = src + num_elements;
6368 float* dst = data.get();
6369 while (src != end) {
6370 *dst++ = static_cast<float>(*src++) / 65536.0f;
6372 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
6373 glVertexAttribPointer(
6374 attrib->index(), attrib->size(), GL_FLOAT, false, 0,
6375 reinterpret_cast<GLvoid*>(offset));
6383 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
6384 // There's no need to call glVertexAttribPointer because we shadow all the
6385 // settings and passing GL_FIXED to it will not work.
6388 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
6392 error::Error GLES2DecoderImpl::DoDrawArrays(
6393 const char* function_name,
6398 GLsizei primcount) {
6399 error::Error error = WillAccessBoundFramebufferForDraw();
6400 if (error != error::kNoError)
6402 if (!validators_->draw_mode.IsValid(mode)) {
6403 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
6404 return error::kNoError;
6407 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
6408 return error::kNoError;
6410 if (primcount < 0) {
6411 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
6412 return error::kNoError;
6414 if (!CheckBoundFramebuffersValid(function_name)) {
6415 return error::kNoError;
6417 // We have to check this here because the prototype for glDrawArrays
6418 // is GLint not GLsizei.
6420 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "first < 0");
6421 return error::kNoError;
6424 if (count == 0 || (instanced && primcount == 0)) {
6425 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
6426 return error::kNoError;
6429 GLuint max_vertex_accessed = first + count - 1;
6430 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
6431 if (!ClearUnclearedTextures()) {
6432 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
6433 return error::kNoError;
6435 bool simulated_attrib_0 = false;
6436 if (!SimulateAttrib0(
6437 function_name, max_vertex_accessed, &simulated_attrib_0)) {
6438 return error::kNoError;
6440 bool simulated_fixed_attribs = false;
6441 if (SimulateFixedAttribs(
6442 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6444 bool textures_set = !PrepareTexturesForRender();
6446 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
6448 glDrawArrays(mode, first, count);
6450 glDrawArraysInstancedANGLE(mode, first, count, primcount);
6453 RestoreStateForTextures();
6455 if (simulated_fixed_attribs) {
6456 RestoreStateForSimulatedFixedAttribs();
6459 if (simulated_attrib_0) {
6460 // We don't have to restore attrib 0 generic data at the end of this
6461 // function even if it is simulated. This is because we will simulate
6462 // it in each draw call, and attrib 0 generic data queries use cached
6463 // values instead of passing down to the underlying driver.
6464 RestoreStateForAttrib(0, false);
6467 return error::kNoError;
6470 error::Error GLES2DecoderImpl::HandleDrawArrays(
6471 uint32 immediate_data_size, const cmds::DrawArrays& c) {
6472 return DoDrawArrays("glDrawArrays",
6474 static_cast<GLenum>(c.mode),
6475 static_cast<GLint>(c.first),
6476 static_cast<GLsizei>(c.count),
6480 error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
6481 uint32 immediate_data_size, const cmds::DrawArraysInstancedANGLE& c) {
6482 if (!features().angle_instanced_arrays) {
6484 GL_INVALID_OPERATION,
6485 "glDrawArraysInstancedANGLE", "function not available");
6486 return error::kNoError;
6488 return DoDrawArrays("glDrawArraysIntancedANGLE",
6490 static_cast<GLenum>(c.mode),
6491 static_cast<GLint>(c.first),
6492 static_cast<GLsizei>(c.count),
6493 static_cast<GLsizei>(c.primcount));
6496 error::Error GLES2DecoderImpl::DoDrawElements(
6497 const char* function_name,
6503 GLsizei primcount) {
6504 error::Error error = WillAccessBoundFramebufferForDraw();
6505 if (error != error::kNoError)
6507 if (!state_.vertex_attrib_manager->element_array_buffer()) {
6509 GL_INVALID_OPERATION, function_name, "No element array buffer bound");
6510 return error::kNoError;
6514 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
6515 return error::kNoError;
6518 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "offset < 0");
6519 return error::kNoError;
6521 if (!validators_->draw_mode.IsValid(mode)) {
6522 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
6523 return error::kNoError;
6525 if (!validators_->index_type.IsValid(type)) {
6526 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
6527 return error::kNoError;
6529 if (primcount < 0) {
6530 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
6531 return error::kNoError;
6534 if (!CheckBoundFramebuffersValid(function_name)) {
6535 return error::kNoError;
6538 if (count == 0 || (instanced && primcount == 0)) {
6539 return error::kNoError;
6542 GLuint max_vertex_accessed;
6543 Buffer* element_array_buffer =
6544 state_.vertex_attrib_manager->element_array_buffer();
6546 if (!element_array_buffer->GetMaxValueForRange(
6547 offset, count, type, &max_vertex_accessed)) {
6549 GL_INVALID_OPERATION, function_name, "range out of bounds for buffer");
6550 return error::kNoError;
6553 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
6554 if (!ClearUnclearedTextures()) {
6555 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
6556 return error::kNoError;
6558 bool simulated_attrib_0 = false;
6559 if (!SimulateAttrib0(
6560 function_name, max_vertex_accessed, &simulated_attrib_0)) {
6561 return error::kNoError;
6563 bool simulated_fixed_attribs = false;
6564 if (SimulateFixedAttribs(
6565 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6567 bool textures_set = !PrepareTexturesForRender();
6569 // TODO(gman): Refactor to hide these details in BufferManager or
6570 // VertexAttribManager.
6571 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
6572 bool used_client_side_array = false;
6573 if (element_array_buffer->IsClientSideArray()) {
6574 used_client_side_array = true;
6575 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
6576 indices = element_array_buffer->GetRange(offset, 0);
6579 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
6581 glDrawElements(mode, count, type, indices);
6583 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
6586 if (used_client_side_array) {
6587 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
6588 element_array_buffer->service_id());
6592 RestoreStateForTextures();
6594 if (simulated_fixed_attribs) {
6595 RestoreStateForSimulatedFixedAttribs();
6598 if (simulated_attrib_0) {
6599 // We don't have to restore attrib 0 generic data at the end of this
6600 // function even if it is simulated. This is because we will simulate
6601 // it in each draw call, and attrib 0 generic data queries use cached
6602 // values instead of passing down to the underlying driver.
6603 RestoreStateForAttrib(0, false);
6606 return error::kNoError;
6609 error::Error GLES2DecoderImpl::HandleDrawElements(
6610 uint32 immediate_data_size, const cmds::DrawElements& c) {
6611 return DoDrawElements("glDrawElements",
6613 static_cast<GLenum>(c.mode),
6614 static_cast<GLsizei>(c.count),
6615 static_cast<GLenum>(c.type),
6616 static_cast<int32>(c.index_offset),
6620 error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
6621 uint32 immediate_data_size, const cmds::DrawElementsInstancedANGLE& c) {
6622 if (!features().angle_instanced_arrays) {
6624 GL_INVALID_OPERATION,
6625 "glDrawElementsInstancedANGLE", "function not available");
6626 return error::kNoError;
6628 return DoDrawElements("glDrawElementsInstancedANGLE",
6630 static_cast<GLenum>(c.mode),
6631 static_cast<GLsizei>(c.count),
6632 static_cast<GLenum>(c.type),
6633 static_cast<int32>(c.index_offset),
6634 static_cast<GLsizei>(c.primcount));
6637 GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
6638 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
6639 GLuint max_vertex_accessed = 0;
6640 Buffer* buffer = GetBuffer(buffer_id);
6642 // TODO(gman): Should this be a GL error or a command buffer error?
6644 GL_INVALID_VALUE, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
6646 if (!buffer->GetMaxValueForRange(
6647 offset, count, type, &max_vertex_accessed)) {
6648 // TODO(gman): Should this be a GL error or a command buffer error?
6650 GL_INVALID_OPERATION,
6651 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
6654 return max_vertex_accessed;
6657 // Calls glShaderSource for the various versions of the ShaderSource command.
6658 // Assumes that data / data_size points to a piece of memory that is in range
6659 // of whatever context it came from (shared memory, immediate memory, bucket
6661 error::Error GLES2DecoderImpl::ShaderSourceHelper(
6662 GLuint client_id, const char* data, uint32 data_size) {
6663 std::string str(data, data + data_size);
6664 Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
6666 return error::kNoError;
6668 // Note: We don't actually call glShaderSource here. We wait until
6669 // the call to glCompileShader.
6670 shader->UpdateSource(str.c_str());
6671 return error::kNoError;
6674 error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
6675 uint32 immediate_data_size, const cmds::ShaderSourceBucket& c) {
6676 Bucket* bucket = GetBucket(c.data_bucket_id);
6677 if (!bucket || bucket->size() == 0) {
6678 return error::kInvalidArguments;
6680 return ShaderSourceHelper(
6681 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
6682 bucket->size() - 1);
6685 void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
6686 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
6687 Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader");
6691 ShaderTranslator* translator = NULL;
6692 if (use_shader_translator_) {
6693 translator = shader->shader_type() == GL_VERTEX_SHADER ?
6694 vertex_translator_.get() : fragment_translator_.get();
6697 program_manager()->DoCompileShader(
6700 feature_info_->feature_flags().angle_translated_shader_source ?
6701 ProgramManager::kANGLE : ProgramManager::kGL);
6704 void GLES2DecoderImpl::DoGetShaderiv(
6705 GLuint shader_id, GLenum pname, GLint* params) {
6706 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderiv");
6711 case GL_SHADER_SOURCE_LENGTH:
6712 *params = shader->source() ? shader->source()->size() + 1 : 0;
6714 case GL_COMPILE_STATUS:
6715 *params = compile_shader_always_succeeds_ ? true : shader->IsValid();
6717 case GL_INFO_LOG_LENGTH:
6718 *params = shader->log_info() ? shader->log_info()->size() + 1 : 0;
6720 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
6721 *params = shader->translated_source() ?
6722 shader->translated_source()->size() + 1 : 0;
6727 glGetShaderiv(shader->service_id(), pname, params);
6730 error::Error GLES2DecoderImpl::HandleGetShaderSource(
6731 uint32 immediate_data_size, const cmds::GetShaderSource& c) {
6732 GLuint shader_id = c.shader;
6733 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6734 Bucket* bucket = CreateBucket(bucket_id);
6735 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderSource");
6736 if (!shader || !shader->source()) {
6738 return error::kNoError;
6740 bucket->SetFromString(shader->source()->c_str());
6741 return error::kNoError;
6744 error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
6745 uint32 immediate_data_size,
6746 const cmds::GetTranslatedShaderSourceANGLE& c) {
6747 GLuint shader_id = c.shader;
6748 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6749 Bucket* bucket = CreateBucket(bucket_id);
6750 Shader* shader = GetShaderInfoNotProgram(
6751 shader_id, "glGetTranslatedShaderSourceANGLE");
6754 return error::kNoError;
6757 bucket->SetFromString(shader->translated_source() ?
6758 shader->translated_source()->c_str() : NULL);
6759 return error::kNoError;
6762 error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
6763 uint32 immediate_data_size, const cmds::GetProgramInfoLog& c) {
6764 GLuint program_id = c.program;
6765 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6766 Bucket* bucket = CreateBucket(bucket_id);
6767 Program* program = GetProgramInfoNotShader(
6768 program_id, "glGetProgramInfoLog");
6769 if (!program || !program->log_info()) {
6770 bucket->SetFromString("");
6771 return error::kNoError;
6773 bucket->SetFromString(program->log_info()->c_str());
6774 return error::kNoError;
6777 error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
6778 uint32 immediate_data_size, const cmds::GetShaderInfoLog& c) {
6779 GLuint shader_id = c.shader;
6780 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6781 Bucket* bucket = CreateBucket(bucket_id);
6782 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderInfoLog");
6783 if (!shader || !shader->log_info()) {
6784 bucket->SetFromString("");
6785 return error::kNoError;
6787 bucket->SetFromString(shader->log_info()->c_str());
6788 return error::kNoError;
6791 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
6792 return state_.GetEnabled(cap);
6795 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
6796 const Buffer* buffer = GetBuffer(client_id);
6797 return buffer && buffer->IsValid() && !buffer->IsDeleted();
6800 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
6801 const Framebuffer* framebuffer =
6802 GetFramebuffer(client_id);
6803 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
6806 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
6807 // IsProgram is true for programs as soon as they are created, until they are
6808 // deleted and no longer in use.
6809 const Program* program = GetProgram(client_id);
6810 return program != NULL && !program->IsDeleted();
6813 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
6814 const Renderbuffer* renderbuffer =
6815 GetRenderbuffer(client_id);
6816 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
6819 bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
6820 // IsShader is true for shaders as soon as they are created, until they
6821 // are deleted and not attached to any programs.
6822 const Shader* shader = GetShader(client_id);
6823 return shader != NULL && !shader->IsDeleted();
6826 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
6827 const TextureRef* texture_ref = GetTexture(client_id);
6828 return texture_ref && texture_ref->texture()->IsValid();
6831 void GLES2DecoderImpl::DoAttachShader(
6832 GLuint program_client_id, GLint shader_client_id) {
6833 Program* program = GetProgramInfoNotShader(
6834 program_client_id, "glAttachShader");
6838 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glAttachShader");
6842 if (!program->AttachShader(shader_manager(), shader)) {
6844 GL_INVALID_OPERATION,
6846 "can not attach more than one shader of the same type.");
6849 glAttachShader(program->service_id(), shader->service_id());
6852 void GLES2DecoderImpl::DoDetachShader(
6853 GLuint program_client_id, GLint shader_client_id) {
6854 Program* program = GetProgramInfoNotShader(
6855 program_client_id, "glDetachShader");
6859 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glDetachShader");
6863 if (!program->DetachShader(shader_manager(), shader)) {
6865 GL_INVALID_OPERATION,
6866 "glDetachShader", "shader not attached to program");
6869 glDetachShader(program->service_id(), shader->service_id());
6872 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
6873 Program* program = GetProgramInfoNotShader(
6874 program_client_id, "glValidateProgram");
6878 program->Validate();
6881 void GLES2DecoderImpl::GetVertexAttribHelper(
6882 const VertexAttrib* attrib, GLenum pname, GLint* params) {
6884 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
6885 Buffer* buffer = attrib->buffer();
6886 if (buffer && !buffer->IsDeleted()) {
6888 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
6889 *params = client_id;
6893 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
6894 *params = attrib->enabled();
6896 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
6897 *params = attrib->size();
6899 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
6900 *params = attrib->gl_stride();
6902 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
6903 *params = attrib->type();
6905 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
6906 *params = attrib->normalized();
6908 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
6909 *params = attrib->divisor();
6917 void GLES2DecoderImpl::DoGetTexParameterfv(
6918 GLenum target, GLenum pname, GLfloat* params) {
6919 InitTextureMaxAnisotropyIfNeeded(target, pname);
6920 glGetTexParameterfv(target, pname, params);
6923 void GLES2DecoderImpl::DoGetTexParameteriv(
6924 GLenum target, GLenum pname, GLint* params) {
6925 InitTextureMaxAnisotropyIfNeeded(target, pname);
6926 glGetTexParameteriv(target, pname, params);
6929 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
6930 GLenum target, GLenum pname) {
6931 if (!workarounds().init_texture_max_anisotropy)
6933 if (pname != GL_TEXTURE_MAX_ANISOTROPY_EXT ||
6934 !validators_->texture_parameter.IsValid(pname)) {
6938 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
6942 GL_INVALID_OPERATION,
6943 "glGetTexParamter{fi}v", "unknown texture for target");
6946 Texture* texture = texture_ref->texture();
6947 texture->InitTextureMaxAnisotropyIfNeeded(target);
6950 void GLES2DecoderImpl::DoGetVertexAttribfv(
6951 GLuint index, GLenum pname, GLfloat* params) {
6952 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
6955 GL_INVALID_VALUE, "glGetVertexAttribfv", "index out of range");
6959 case GL_CURRENT_VERTEX_ATTRIB: {
6960 const Vec4& value = state_.attrib_values[index];
6961 params[0] = value.v[0];
6962 params[1] = value.v[1];
6963 params[2] = value.v[2];
6964 params[3] = value.v[3];
6969 GetVertexAttribHelper(attrib, pname, &value);
6970 *params = static_cast<GLfloat>(value);
6976 void GLES2DecoderImpl::DoGetVertexAttribiv(
6977 GLuint index, GLenum pname, GLint* params) {
6978 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
6981 GL_INVALID_VALUE, "glGetVertexAttribiv", "index out of range");
6985 case GL_CURRENT_VERTEX_ATTRIB: {
6986 const Vec4& value = state_.attrib_values[index];
6987 params[0] = static_cast<GLint>(value.v[0]);
6988 params[1] = static_cast<GLint>(value.v[1]);
6989 params[2] = static_cast<GLint>(value.v[2]);
6990 params[3] = static_cast<GLint>(value.v[3]);
6994 GetVertexAttribHelper(attrib, pname, params);
6999 bool GLES2DecoderImpl::SetVertexAttribValue(
7000 const char* function_name, GLuint index, const GLfloat* value) {
7001 if (index >= state_.attrib_values.size()) {
7002 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "index out of range");
7005 Vec4& v = state_.attrib_values[index];
7013 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
7014 GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
7015 if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
7016 glVertexAttrib1f(index, v0);
7020 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
7021 GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
7022 if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
7023 glVertexAttrib2f(index, v0, v1);
7027 void GLES2DecoderImpl::DoVertexAttrib3f(
7028 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
7029 GLfloat v[4] = { v0, v1, v2, 1.0f, };
7030 if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
7031 glVertexAttrib3f(index, v0, v1, v2);
7035 void GLES2DecoderImpl::DoVertexAttrib4f(
7036 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
7037 GLfloat v[4] = { v0, v1, v2, v3, };
7038 if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
7039 glVertexAttrib4f(index, v0, v1, v2, v3);
7043 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
7044 GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
7045 if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
7046 glVertexAttrib1fv(index, v);
7050 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
7051 GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
7052 if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
7053 glVertexAttrib2fv(index, v);
7057 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
7058 GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
7059 if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
7060 glVertexAttrib3fv(index, v);
7064 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
7065 if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
7066 glVertexAttrib4fv(index, v);
7070 error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
7071 uint32 immediate_data_size, const cmds::VertexAttribPointer& c) {
7073 if (!state_.bound_array_buffer.get() ||
7074 state_.bound_array_buffer->IsDeleted()) {
7075 if (state_.vertex_attrib_manager.get() ==
7076 state_.default_vertex_attrib_manager.get()) {
7078 GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
7079 return error::kNoError;
7080 } else if (c.offset != 0) {
7083 "glVertexAttribPointer", "client side arrays are not allowed");
7084 return error::kNoError;
7088 GLuint indx = c.indx;
7089 GLint size = c.size;
7090 GLenum type = c.type;
7091 GLboolean normalized = c.normalized;
7092 GLsizei stride = c.stride;
7093 GLsizei offset = c.offset;
7094 const void* ptr = reinterpret_cast<const void*>(offset);
7095 if (!validators_->vertex_attrib_type.IsValid(type)) {
7096 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type, "type");
7097 return error::kNoError;
7099 if (!validators_->vertex_attrib_size.IsValid(size)) {
7101 GL_INVALID_VALUE, "glVertexAttribPointer", "size GL_INVALID_VALUE");
7102 return error::kNoError;
7104 if (indx >= group_->max_vertex_attribs()) {
7106 GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
7107 return error::kNoError;
7111 GL_INVALID_VALUE, "glVertexAttribPointer", "stride < 0");
7112 return error::kNoError;
7116 GL_INVALID_VALUE, "glVertexAttribPointer", "stride > 255");
7117 return error::kNoError;
7121 GL_INVALID_VALUE, "glVertexAttribPointer", "offset < 0");
7122 return error::kNoError;
7124 GLsizei component_size =
7125 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
7126 if (offset % component_size > 0) {
7128 GL_INVALID_OPERATION,
7129 "glVertexAttribPointer", "offset not valid for type");
7130 return error::kNoError;
7132 if (stride % component_size > 0) {
7134 GL_INVALID_OPERATION,
7135 "glVertexAttribPointer", "stride not valid for type");
7136 return error::kNoError;
7138 state_.vertex_attrib_manager
7139 ->SetAttribInfo(indx,
7140 state_.bound_array_buffer.get(),
7145 stride != 0 ? stride : component_size * size,
7147 if (type != GL_FIXED) {
7148 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
7150 return error::kNoError;
7153 void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
7155 state_.viewport_x = x;
7156 state_.viewport_y = y;
7157 state_.viewport_width = std::min(width, viewport_max_width_);
7158 state_.viewport_height = std::min(height, viewport_max_height_);
7159 glViewport(x, y, width, height);
7162 error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
7163 uint32 immediate_data_size, const cmds::VertexAttribDivisorANGLE& c) {
7164 if (!features().angle_instanced_arrays) {
7166 GL_INVALID_OPERATION,
7167 "glVertexAttribDivisorANGLE", "function not available");
7168 return error::kNoError;
7170 GLuint index = c.index;
7171 GLuint divisor = c.divisor;
7172 if (index >= group_->max_vertex_attribs()) {
7175 "glVertexAttribDivisorANGLE", "index out of range");
7176 return error::kNoError;
7179 state_.vertex_attrib_manager->SetDivisor(
7182 glVertexAttribDivisorANGLE(index, divisor);
7183 return error::kNoError;
7186 template <typename pixel_data_type>
7187 static void WriteAlphaData(
7188 void *pixels, uint32 row_count, uint32 channel_count,
7189 uint32 alpha_channel_index, uint32 unpadded_row_size,
7190 uint32 padded_row_size, pixel_data_type alpha_value) {
7191 DCHECK_GT(channel_count, 0U);
7192 DCHECK_EQ(unpadded_row_size % sizeof(pixel_data_type), 0U);
7193 uint32 unpadded_row_size_in_elements =
7194 unpadded_row_size / sizeof(pixel_data_type);
7195 DCHECK_EQ(padded_row_size % sizeof(pixel_data_type), 0U);
7196 uint32 padded_row_size_in_elements =
7197 padded_row_size / sizeof(pixel_data_type);
7198 pixel_data_type* dst =
7199 static_cast<pixel_data_type*>(pixels) + alpha_channel_index;
7200 for (uint32 yy = 0; yy < row_count; ++yy) {
7201 pixel_data_type* end = dst + unpadded_row_size_in_elements;
7202 for (pixel_data_type* d = dst; d < end; d += channel_count) {
7205 dst += padded_row_size_in_elements;
7209 void GLES2DecoderImpl::FinishReadPixels(
7210 const cmds::ReadPixels& c,
7212 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
7213 GLsizei width = c.width;
7214 GLsizei height = c.height;
7215 GLenum format = c.format;
7216 GLenum type = c.type;
7217 typedef cmds::ReadPixels::Result Result;
7219 Result* result = NULL;
7220 if (c.result_shm_id != 0) {
7221 result = GetSharedMemoryAs<Result*>(
7222 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7225 glDeleteBuffersARB(1, &buffer);
7230 GLES2Util::ComputeImageDataSizes(
7231 width, height, format, type, state_.pack_alignment, &pixels_size,
7233 void* pixels = GetSharedMemoryAs<void*>(
7234 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
7237 glDeleteBuffersARB(1, &buffer);
7243 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
7245 if (features().map_buffer_range) {
7246 data = glMapBufferRange(
7247 GL_PIXEL_PACK_BUFFER_ARB, 0, pixels_size, GL_MAP_READ_BIT);
7249 data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
7251 memcpy(pixels, data, pixels_size);
7252 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
7253 // have to restore the state.
7254 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
7255 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7256 glDeleteBuffersARB(1, &buffer);
7259 if (result != NULL) {
7263 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
7264 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
7265 if ((channels_exist & 0x0008) == 0 &&
7266 workarounds().clear_alpha_in_readpixels) {
7267 // Set the alpha to 255 because some drivers are buggy in this regard.
7270 uint32 unpadded_row_size;
7271 uint32 padded_row_size;
7272 if (!GLES2Util::ComputeImageDataSizes(
7273 width, 2, format, type, state_.pack_alignment, &temp_size,
7274 &unpadded_row_size, &padded_row_size)) {
7278 uint32 channel_count = 0;
7279 uint32 alpha_channel = 0;
7292 if (channel_count > 0) {
7294 case GL_UNSIGNED_BYTE:
7295 WriteAlphaData<uint8>(
7296 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7297 padded_row_size, 0xFF);
7300 WriteAlphaData<float>(
7301 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7302 padded_row_size, 1.0f);
7305 WriteAlphaData<uint16>(
7306 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7307 padded_row_size, 0x3C00);
7315 error::Error GLES2DecoderImpl::HandleReadPixels(
7316 uint32 immediate_data_size, const cmds::ReadPixels& c) {
7317 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
7318 error::Error fbo_error = WillAccessBoundFramebufferForRead();
7319 if (fbo_error != error::kNoError)
7323 GLsizei width = c.width;
7324 GLsizei height = c.height;
7325 GLenum format = c.format;
7326 GLenum type = c.type;
7327 GLboolean async = c.async;
7328 if (width < 0 || height < 0) {
7329 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
7330 return error::kNoError;
7332 typedef cmds::ReadPixels::Result Result;
7334 if (!GLES2Util::ComputeImageDataSizes(
7335 width, height, format, type, state_.pack_alignment, &pixels_size,
7337 return error::kOutOfBounds;
7339 void* pixels = GetSharedMemoryAs<void*>(
7340 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
7342 return error::kOutOfBounds;
7344 Result* result = NULL;
7345 if (c.result_shm_id != 0) {
7346 result = GetSharedMemoryAs<Result*>(
7347 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7349 return error::kOutOfBounds;
7353 if (!validators_->read_pixel_format.IsValid(format)) {
7354 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format, "format");
7355 return error::kNoError;
7357 if (!validators_->read_pixel_type.IsValid(type)) {
7358 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type");
7359 return error::kNoError;
7361 if ((format != GL_RGBA && format != GL_BGRA_EXT && format != GL_RGB &&
7362 format != GL_ALPHA) || type != GL_UNSIGNED_BYTE) {
7363 // format and type are acceptable enums but not guaranteed to be supported
7364 // for this framebuffer. Have to ask gl if they are valid.
7365 GLint preferred_format = 0;
7366 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &preferred_format);
7367 GLint preferred_type = 0;
7368 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &preferred_type);
7369 if (format != static_cast<GLenum>(preferred_format) ||
7370 type != static_cast<GLenum>(preferred_type)) {
7372 GL_INVALID_OPERATION, "glReadPixels", "format and type incompatible "
7373 "with the current read framebuffer");
7374 return error::kNoError;
7377 if (width == 0 || height == 0) {
7378 return error::kNoError;
7381 // Get the size of the current fbo or backbuffer.
7382 gfx::Size max_size = GetBoundReadFrameBufferSize();
7386 if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y)) {
7388 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7389 return error::kNoError;
7392 if (!CheckBoundFramebuffersValid("glReadPixels")) {
7393 return error::kNoError;
7396 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
7398 ScopedResolvedFrameBufferBinder binder(this, false, true);
7400 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
7401 // The user requested an out of range area. Get the results 1 line
7404 uint32 unpadded_row_size;
7405 uint32 padded_row_size;
7406 if (!GLES2Util::ComputeImageDataSizes(
7407 width, 2, format, type, state_.pack_alignment, &temp_size,
7408 &unpadded_row_size, &padded_row_size)) {
7410 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7411 return error::kNoError;
7414 GLint dest_x_offset = std::max(-x, 0);
7415 uint32 dest_row_offset;
7416 if (!GLES2Util::ComputeImageDataSizes(
7417 dest_x_offset, 1, format, type, state_.pack_alignment, &dest_row_offset,
7420 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7421 return error::kNoError;
7424 // Copy each row into the larger dest rect.
7425 int8* dst = static_cast<int8*>(pixels);
7426 GLint read_x = std::max(0, x);
7427 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
7428 GLint read_width = read_end_x - read_x;
7429 for (GLint yy = 0; yy < height; ++yy) {
7433 memset(dst, 0, unpadded_row_size);
7435 // If the row is in range, copy it.
7436 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
7438 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
7440 dst += padded_row_size;
7443 if (async && features().use_async_readpixels) {
7445 glGenBuffersARB(1, &buffer);
7446 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
7447 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, GL_STREAM_READ);
7448 GLenum error = glGetError();
7449 if (error == GL_NO_ERROR) {
7450 glReadPixels(x, y, width, height, format, type, 0);
7451 pending_readpixel_fences_.push(linked_ptr<FenceCallback>(
7452 new FenceCallback()));
7453 WaitForReadPixels(base::Bind(
7454 &GLES2DecoderImpl::FinishReadPixels,
7455 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
7456 <GLES2DecoderImpl>(this),
7458 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7459 return error::kNoError;
7461 // On error, unbind pack buffer and fall through to sync readpixels
7462 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7465 glReadPixels(x, y, width, height, format, type, pixels);
7467 GLenum error = LOCAL_PEEK_GL_ERROR("glReadPixels");
7468 if (error == GL_NO_ERROR) {
7469 if (result != NULL) {
7472 FinishReadPixels(c, 0);
7475 return error::kNoError;
7478 error::Error GLES2DecoderImpl::HandlePixelStorei(
7479 uint32 immediate_data_size, const cmds::PixelStorei& c) {
7480 GLenum pname = c.pname;
7481 GLenum param = c.param;
7482 if (!validators_->pixel_store.IsValid(pname)) {
7483 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname, "pname");
7484 return error::kNoError;
7487 case GL_PACK_ALIGNMENT:
7488 case GL_UNPACK_ALIGNMENT:
7489 if (!validators_->pixel_store_alignment.IsValid(param)) {
7491 GL_INVALID_VALUE, "glPixelStorei", "param GL_INVALID_VALUE");
7492 return error::kNoError;
7495 case GL_UNPACK_FLIP_Y_CHROMIUM:
7496 unpack_flip_y_ = (param != 0);
7497 return error::kNoError;
7498 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
7499 unpack_premultiply_alpha_ = (param != 0);
7500 return error::kNoError;
7501 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
7502 unpack_unpremultiply_alpha_ = (param != 0);
7503 return error::kNoError;
7507 glPixelStorei(pname, param);
7509 case GL_PACK_ALIGNMENT:
7510 state_.pack_alignment = param;
7512 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
7513 state_.pack_reverse_row_order = (param != 0);
7515 case GL_UNPACK_ALIGNMENT:
7516 state_.unpack_alignment = param;
7519 // Validation should have prevented us from getting here.
7523 return error::kNoError;
7526 error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
7527 uint32 immediate_data_size, const cmds::PostSubBufferCHROMIUM& c) {
7528 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
7530 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
7532 if (!supports_post_sub_buffer_) {
7534 GL_INVALID_OPERATION,
7535 "glPostSubBufferCHROMIUM", "command not supported by surface");
7536 return error::kNoError;
7539 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
7542 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
7543 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
7544 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
7545 is_offscreen ? offscreen_size_ : surface_->GetSize());
7547 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height)) {
7548 return error::kNoError;
7550 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
7551 return error::kLostContext;
7555 error::Error GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
7556 uint32 immediate_data_size,
7557 const cmds::ScheduleOverlayPlaneCHROMIUM& c) {
7558 NOTIMPLEMENTED() << "Overlay supported isn't finished.";
7559 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
7560 "glScheduleOverlayPlaneCHROMIUM",
7561 "function not implemented");
7562 return error::kNoError;
7565 error::Error GLES2DecoderImpl::GetAttribLocationHelper(
7566 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7567 const std::string& name_str) {
7568 if (!StringIsValidForGLES(name_str.c_str())) {
7570 GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
7571 return error::kNoError;
7573 Program* program = GetProgramInfoNotShader(
7574 client_id, "glGetAttribLocation");
7576 return error::kNoError;
7578 if (!program->IsValid()) {
7580 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
7581 return error::kNoError;
7583 GLint* location = GetSharedMemoryAs<GLint*>(
7584 location_shm_id, location_shm_offset, sizeof(GLint));
7586 return error::kOutOfBounds;
7588 // Require the client to init this incase the context is lost and we are no
7589 // longer executing commands.
7590 if (*location != -1) {
7591 return error::kGenericError;
7593 *location = program->GetAttribLocation(name_str);
7594 return error::kNoError;
7597 error::Error GLES2DecoderImpl::HandleGetAttribLocation(
7598 uint32 immediate_data_size, const cmds::GetAttribLocation& c) {
7599 Bucket* bucket = GetBucket(c.name_bucket_id);
7601 return error::kInvalidArguments;
7603 std::string name_str;
7604 if (!bucket->GetAsString(&name_str)) {
7605 return error::kInvalidArguments;
7607 return GetAttribLocationHelper(
7608 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7611 error::Error GLES2DecoderImpl::GetUniformLocationHelper(
7612 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7613 const std::string& name_str) {
7614 if (!StringIsValidForGLES(name_str.c_str())) {
7616 GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
7617 return error::kNoError;
7619 Program* program = GetProgramInfoNotShader(
7620 client_id, "glGetUniformLocation");
7622 return error::kNoError;
7624 if (!program->IsValid()) {
7626 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
7627 return error::kNoError;
7629 GLint* location = GetSharedMemoryAs<GLint*>(
7630 location_shm_id, location_shm_offset, sizeof(GLint));
7632 return error::kOutOfBounds;
7634 // Require the client to init this incase the context is lost an we are no
7635 // longer executing commands.
7636 if (*location != -1) {
7637 return error::kGenericError;
7639 *location = program->GetUniformFakeLocation(name_str);
7640 return error::kNoError;
7643 error::Error GLES2DecoderImpl::HandleGetUniformLocation(
7644 uint32 immediate_data_size, const cmds::GetUniformLocation& c) {
7645 Bucket* bucket = GetBucket(c.name_bucket_id);
7647 return error::kInvalidArguments;
7649 std::string name_str;
7650 if (!bucket->GetAsString(&name_str)) {
7651 return error::kInvalidArguments;
7653 return GetUniformLocationHelper(
7654 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7657 error::Error GLES2DecoderImpl::HandleGetString(
7658 uint32 immediate_data_size, const cmds::GetString& c) {
7659 GLenum name = static_cast<GLenum>(c.name);
7660 if (!validators_->string_type.IsValid(name)) {
7661 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name");
7662 return error::kNoError;
7664 const char* str = reinterpret_cast<const char*>(glGetString(name));
7665 std::string extensions;
7668 str = "OpenGL ES 2.0 Chromium";
7670 case GL_SHADING_LANGUAGE_VERSION:
7671 str = "OpenGL ES GLSL ES 1.0 Chromium";
7675 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
7676 // They are used by WEBGL_debug_renderer_info.
7677 if (!force_webgl_glsl_validation_)
7682 // For WebGL contexts, strip out the OES derivatives and
7683 // EXT frag depth extensions if they have not been enabled.
7684 if (force_webgl_glsl_validation_) {
7685 extensions = feature_info_->extensions();
7686 if (!derivatives_explicitly_enabled_) {
7687 size_t offset = extensions.find(kOESDerivativeExtension);
7688 if (std::string::npos != offset) {
7689 extensions.replace(offset, arraysize(kOESDerivativeExtension),
7693 if (!frag_depth_explicitly_enabled_) {
7694 size_t offset = extensions.find(kEXTFragDepthExtension);
7695 if (std::string::npos != offset) {
7696 extensions.replace(offset, arraysize(kEXTFragDepthExtension),
7700 if (!draw_buffers_explicitly_enabled_) {
7701 size_t offset = extensions.find(kEXTDrawBuffersExtension);
7702 if (std::string::npos != offset) {
7703 extensions.replace(offset, arraysize(kEXTDrawBuffersExtension),
7707 if (!shader_texture_lod_explicitly_enabled_) {
7708 size_t offset = extensions.find(kEXTShaderTextureLodExtension);
7709 if (std::string::npos != offset) {
7710 extensions.replace(offset,
7711 arraysize(kEXTShaderTextureLodExtension),
7716 extensions = feature_info_->extensions().c_str();
7718 if (supports_post_sub_buffer_)
7719 extensions += " GL_CHROMIUM_post_sub_buffer";
7720 str = extensions.c_str();
7726 Bucket* bucket = CreateBucket(c.bucket_id);
7727 bucket->SetFromString(str);
7728 return error::kNoError;
7731 error::Error GLES2DecoderImpl::HandleBufferData(
7732 uint32 immediate_data_size, const cmds::BufferData& c) {
7733 GLenum target = static_cast<GLenum>(c.target);
7734 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
7735 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
7736 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
7737 GLenum usage = static_cast<GLenum>(c.usage);
7738 const void* data = NULL;
7739 if (data_shm_id != 0 || data_shm_offset != 0) {
7740 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
7742 return error::kOutOfBounds;
7745 buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
7746 return error::kNoError;
7749 void GLES2DecoderImpl::DoBufferSubData(
7750 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
7751 // Just delegate it. Some validation is actually done before this.
7752 buffer_manager()->ValidateAndDoBufferSubData(
7753 &state_, target, offset, size, data);
7756 bool GLES2DecoderImpl::ClearLevel(
7757 unsigned service_id,
7758 unsigned bind_target,
7761 unsigned internal_format,
7766 bool is_texture_immutable) {
7767 uint32 channels = GLES2Util::GetChannelsForFormat(format);
7768 if (feature_info_->feature_flags().angle_depth_texture &&
7769 (channels & GLES2Util::kDepth) != 0) {
7770 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
7771 // on depth formats.
7773 glGenFramebuffersEXT(1, &fb);
7774 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
7776 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
7777 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
7778 GL_DEPTH_ATTACHMENT;
7780 glFramebufferTexture2DEXT(
7781 GL_DRAW_FRAMEBUFFER_EXT, attachment, target, service_id, level);
7782 // ANGLE promises a depth only attachment ok.
7783 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
7784 GL_FRAMEBUFFER_COMPLETE) {
7788 state_.SetDeviceStencilMaskSeparate(GL_FRONT, -1);
7789 state_.SetDeviceStencilMaskSeparate(GL_BACK, -1);
7791 state_.SetDeviceDepthMask(GL_TRUE);
7792 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
7793 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
7795 RestoreClearState();
7797 glDeleteFramebuffersEXT(1, &fb);
7798 Framebuffer* framebuffer =
7799 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
7800 GLuint fb_service_id =
7801 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
7802 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
7806 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
7809 uint32 padded_row_size;
7810 if (!GLES2Util::ComputeImageDataSizes(
7811 width, height, format, type, state_.unpack_alignment, &size,
7812 NULL, &padded_row_size)) {
7816 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
7820 if (size > kMaxZeroSize) {
7821 if (kMaxZeroSize < padded_row_size) {
7822 // That'd be an awfully large texture.
7825 // We should never have a large total size with a zero row size.
7826 DCHECK_GT(padded_row_size, 0U);
7827 tile_height = kMaxZeroSize / padded_row_size;
7828 if (!GLES2Util::ComputeImageDataSizes(
7829 width, tile_height, format, type, state_.unpack_alignment, &size,
7834 tile_height = height;
7837 // Assumes the size has already been checked.
7838 scoped_ptr<char[]> zero(new char[size]);
7839 memset(zero.get(), 0, size);
7840 glBindTexture(bind_target, service_id);
7843 while (y < height) {
7844 GLint h = y + tile_height > height ? height - y : tile_height;
7845 if (is_texture_immutable || h != height) {
7846 glTexSubImage2D(target, level, 0, y, width, h, format, type, zero.get());
7849 target, level, internal_format, width, h, 0, format, type,
7854 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
7855 &state_, bind_target);
7856 glBindTexture(bind_target, texture ? texture->service_id() : 0);
7862 const int kS3TCBlockWidth = 4;
7863 const int kS3TCBlockHeight = 4;
7864 const int kS3TCDXT1BlockSize = 8;
7865 const int kS3TCDXT3AndDXT5BlockSize = 16;
7867 bool IsValidDXTSize(GLint level, GLsizei size) {
7868 return (size == 1) ||
7869 (size == 2) || !(size % kS3TCBlockWidth);
7872 bool IsValidPVRTCSize(GLint level, GLsizei size) {
7873 // Ensure that the size is a power of two
7874 return (size & (size - 1)) == 0;
7877 } // anonymous namespace.
7879 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
7880 const char* function_name,
7881 GLsizei width, GLsizei height, GLenum format, size_t size) {
7882 unsigned int bytes_required = 0;
7885 case GL_ATC_RGB_AMD:
7886 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7887 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
7888 case GL_ETC1_RGB8_OES: {
7889 int num_blocks_across =
7890 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
7891 int num_blocks_down =
7892 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
7893 int num_blocks = num_blocks_across * num_blocks_down;
7894 bytes_required = num_blocks * kS3TCDXT1BlockSize;
7897 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
7898 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
7899 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7900 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7901 int num_blocks_across =
7902 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
7903 int num_blocks_down =
7904 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
7905 int num_blocks = num_blocks_across * num_blocks_down;
7906 bytes_required = num_blocks * kS3TCDXT3AndDXT5BlockSize;
7909 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
7910 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: {
7911 bytes_required = (std::max(width, 8) * std::max(height, 8) * 4 + 7)/8;
7914 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
7915 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
7916 bytes_required = (std::max(width, 16) * std::max(height, 8) * 2 + 7)/8;
7920 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
7924 if (size != bytes_required) {
7926 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
7933 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
7934 const char* function_name,
7935 GLint level, GLsizei width, GLsizei height, GLenum format) {
7937 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7938 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
7939 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7940 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7941 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
7943 GL_INVALID_OPERATION, function_name,
7944 "width or height invalid for level");
7949 case GL_ATC_RGB_AMD:
7950 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
7951 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
7952 case GL_ETC1_RGB8_OES: {
7953 if (width <= 0 || height <= 0) {
7955 GL_INVALID_OPERATION, function_name,
7956 "width or height invalid for level");
7961 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
7962 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
7963 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
7964 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
7965 if (!IsValidPVRTCSize(level, width) ||
7966 !IsValidPVRTCSize(level, height)) {
7968 GL_INVALID_OPERATION, function_name,
7969 "width or height invalid for level");
7979 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
7980 const char* function_name,
7981 GLenum target, GLint level, GLint xoffset, GLint yoffset,
7982 GLsizei width, GLsizei height, GLenum format,
7984 if (xoffset < 0 || yoffset < 0) {
7986 GL_INVALID_VALUE, function_name, "xoffset or yoffset < 0");
7991 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7992 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
7993 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7994 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7995 const int kBlockWidth = 4;
7996 const int kBlockHeight = 4;
7997 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
7999 GL_INVALID_OPERATION, function_name,
8000 "xoffset or yoffset not multiple of 4");
8003 GLsizei tex_width = 0;
8004 GLsizei tex_height = 0;
8005 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
8006 width - xoffset > tex_width ||
8007 height - yoffset > tex_height) {
8009 GL_INVALID_OPERATION, function_name, "dimensions out of range");
8012 return ValidateCompressedTexDimensions(
8013 function_name, level, width, height, format);
8015 case GL_ATC_RGB_AMD:
8016 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
8017 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: {
8019 GL_INVALID_OPERATION, function_name,
8020 "not supported for ATC textures");
8023 case GL_ETC1_RGB8_OES: {
8025 GL_INVALID_OPERATION, function_name,
8026 "not supported for ECT1_RGB8_OES textures");
8029 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
8030 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
8031 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
8032 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
8033 if ((xoffset != 0) || (yoffset != 0)) {
8035 GL_INVALID_OPERATION, function_name,
8036 "xoffset and yoffset must be zero");
8039 GLsizei tex_width = 0;
8040 GLsizei tex_height = 0;
8041 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
8042 width != tex_width ||
8043 height != tex_height) {
8045 GL_INVALID_OPERATION, function_name,
8046 "dimensions must match existing texture level dimensions");
8049 return ValidateCompressedTexDimensions(
8050 function_name, level, width, height, format);
8057 error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
8060 GLenum internal_format,
8066 // TODO(gman): Validate image_size is correct for width, height and format.
8067 if (!validators_->texture_target.IsValid(target)) {
8068 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8069 "glCompressedTexImage2D", target, "target");
8070 return error::kNoError;
8072 if (!validators_->compressed_texture_format.IsValid(
8074 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8075 "glCompressedTexImage2D", internal_format, "internal_format");
8076 return error::kNoError;
8078 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
8082 "glCompressedTexImage2D", "dimensions out of range");
8083 return error::kNoError;
8085 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8090 "glCompressedTexImage2D", "unknown texture target");
8091 return error::kNoError;
8093 Texture* texture = texture_ref->texture();
8094 if (texture->IsImmutable()) {
8096 GL_INVALID_OPERATION,
8097 "glCompressedTexImage2D", "texture is immutable");
8098 return error::kNoError;
8101 if (!ValidateCompressedTexDimensions(
8102 "glCompressedTexImage2D", level, width, height, internal_format) ||
8103 !ValidateCompressedTexFuncData(
8104 "glCompressedTexImage2D", width, height, internal_format, image_size)) {
8105 return error::kNoError;
8108 if (!EnsureGPUMemoryAvailable(image_size)) {
8110 GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory");
8111 return error::kNoError;
8114 if (texture->IsAttachedToFramebuffer()) {
8115 framebuffer_state_.clear_state_dirty = true;
8118 scoped_ptr<int8[]> zero;
8120 zero.reset(new int8[image_size]);
8121 memset(zero.get(), 0, image_size);
8124 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
8125 glCompressedTexImage2D(
8126 target, level, internal_format, width, height, border, image_size, data);
8127 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
8128 if (error == GL_NO_ERROR) {
8129 texture_manager()->SetLevelInfo(
8130 texture_ref, target, level, internal_format,
8131 width, height, 1, border, 0, 0, true);
8133 return error::kNoError;
8136 error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
8137 uint32 immediate_data_size, const cmds::CompressedTexImage2D& c) {
8138 GLenum target = static_cast<GLenum>(c.target);
8139 GLint level = static_cast<GLint>(c.level);
8140 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8141 GLsizei width = static_cast<GLsizei>(c.width);
8142 GLsizei height = static_cast<GLsizei>(c.height);
8143 GLint border = static_cast<GLint>(c.border);
8144 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
8145 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
8146 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
8147 const void* data = NULL;
8148 if (data_shm_id != 0 || data_shm_offset != 0) {
8149 data = GetSharedMemoryAs<const void*>(
8150 data_shm_id, data_shm_offset, image_size);
8152 return error::kOutOfBounds;
8155 return DoCompressedTexImage2D(
8156 target, level, internal_format, width, height, border, image_size, data);
8159 error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
8160 uint32 immediate_data_size, const cmds::CompressedTexImage2DBucket& c) {
8161 GLenum target = static_cast<GLenum>(c.target);
8162 GLint level = static_cast<GLint>(c.level);
8163 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8164 GLsizei width = static_cast<GLsizei>(c.width);
8165 GLsizei height = static_cast<GLsizei>(c.height);
8166 GLint border = static_cast<GLint>(c.border);
8167 Bucket* bucket = GetBucket(c.bucket_id);
8169 return error::kInvalidArguments;
8171 uint32 data_size = bucket->size();
8172 GLsizei imageSize = data_size;
8173 const void* data = bucket->GetData(0, data_size);
8175 return error::kInvalidArguments;
8177 return DoCompressedTexImage2D(
8178 target, level, internal_format, width, height, border,
8182 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
8183 uint32 immediate_data_size,
8184 const cmds::CompressedTexSubImage2DBucket& c) {
8185 GLenum target = static_cast<GLenum>(c.target);
8186 GLint level = static_cast<GLint>(c.level);
8187 GLint xoffset = static_cast<GLint>(c.xoffset);
8188 GLint yoffset = static_cast<GLint>(c.yoffset);
8189 GLsizei width = static_cast<GLsizei>(c.width);
8190 GLsizei height = static_cast<GLsizei>(c.height);
8191 GLenum format = static_cast<GLenum>(c.format);
8192 Bucket* bucket = GetBucket(c.bucket_id);
8194 return error::kInvalidArguments;
8196 uint32 data_size = bucket->size();
8197 GLsizei imageSize = data_size;
8198 const void* data = bucket->GetData(0, data_size);
8200 return error::kInvalidArguments;
8202 if (!validators_->texture_target.IsValid(target)) {
8204 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
8205 return error::kNoError;
8207 if (!validators_->compressed_texture_format.IsValid(format)) {
8208 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8209 "glCompressedTexSubImage2D", format, "format");
8210 return error::kNoError;
8214 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
8215 return error::kNoError;
8219 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
8220 return error::kNoError;
8222 if (imageSize < 0) {
8224 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
8225 return error::kNoError;
8227 DoCompressedTexSubImage2D(
8228 target, level, xoffset, yoffset, width, height, format, imageSize, data);
8229 return error::kNoError;
8232 error::Error GLES2DecoderImpl::HandleTexImage2D(
8233 uint32 immediate_data_size, const cmds::TexImage2D& c) {
8234 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
8235 "width", c.width, "height", c.height);
8236 // Set as failed for now, but if it successed, this will be set to not failed.
8237 texture_state_.tex_image_2d_failed = true;
8238 GLenum target = static_cast<GLenum>(c.target);
8239 GLint level = static_cast<GLint>(c.level);
8240 // TODO(kloveless): Change TexImage2D command to use unsigned integer
8241 // for internalformat.
8242 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8243 GLsizei width = static_cast<GLsizei>(c.width);
8244 GLsizei height = static_cast<GLsizei>(c.height);
8245 GLint border = static_cast<GLint>(c.border);
8246 GLenum format = static_cast<GLenum>(c.format);
8247 GLenum type = static_cast<GLenum>(c.type);
8248 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
8249 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
8251 if (!GLES2Util::ComputeImageDataSizes(
8252 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
8254 return error::kOutOfBounds;
8256 const void* pixels = NULL;
8257 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
8258 pixels = GetSharedMemoryAs<const void*>(
8259 pixels_shm_id, pixels_shm_offset, pixels_size);
8261 return error::kOutOfBounds;
8265 TextureManager::DoTextImage2DArguments args = {
8266 target, level, internal_format, width, height, border, format, type,
8267 pixels, pixels_size};
8268 texture_manager()->ValidateAndDoTexImage2D(
8269 &texture_state_, &state_, &framebuffer_state_, args);
8270 return error::kNoError;
8273 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
8282 const void * data) {
8283 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8287 GL_INVALID_OPERATION,
8288 "glCompressedTexSubImage2D", "unknown texture for target");
8291 Texture* texture = texture_ref->texture();
8293 GLenum internal_format = 0;
8294 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
8296 GL_INVALID_OPERATION,
8297 "glCompressedTexSubImage2D", "level does not exist.");
8300 if (internal_format != format) {
8302 GL_INVALID_OPERATION,
8303 "glCompressedTexSubImage2D", "format does not match internal format.");
8306 if (!texture->ValidForTexture(
8307 target, level, xoffset, yoffset, width, height, type)) {
8309 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
8313 if (!ValidateCompressedTexFuncData(
8314 "glCompressedTexSubImage2D", width, height, format, image_size) ||
8315 !ValidateCompressedTexSubDimensions(
8316 "glCompressedTexSubImage2D",
8317 target, level, xoffset, yoffset, width, height, format, texture)) {
8322 // Note: There is no need to deal with texture cleared tracking here
8323 // because the validation above means you can only get here if the level
8324 // is already a matching compressed format and in that case
8325 // CompressedTexImage2D already cleared the texture.
8326 glCompressedTexSubImage2D(
8327 target, level, xoffset, yoffset, width, height, format, image_size, data);
8331 GLint start, GLint range, GLint sourceRange,
8332 GLint* out_start, GLint* out_range) {
8339 GLint end = start + range;
8340 if (end > sourceRange) {
8341 range -= end - sourceRange;
8347 void GLES2DecoderImpl::DoCopyTexImage2D(
8350 GLenum internal_format,
8356 DCHECK(!ShouldDeferReads());
8357 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8361 GL_INVALID_OPERATION,
8362 "glCopyTexImage2D", "unknown texture for target");
8365 Texture* texture = texture_ref->texture();
8366 if (texture->IsImmutable()) {
8368 GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
8371 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
8374 GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
8377 if (!texture_manager()->ValidateFormatAndTypeCombination(
8378 state_.GetErrorState(), "glCopyTexImage2D", internal_format,
8379 GL_UNSIGNED_BYTE)) {
8383 // Check we have compatible formats.
8384 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8385 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8386 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
8388 if ((channels_needed & channels_exist) != channels_needed) {
8390 GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
8394 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8396 GL_INVALID_OPERATION,
8397 "glCopyTexImage2D", "can not be used with depth or stencil textures");
8401 uint32 estimated_size = 0;
8402 if (!GLES2Util::ComputeImageDataSizes(
8403 width, height, internal_format, GL_UNSIGNED_BYTE, state_.unpack_alignment,
8404 &estimated_size, NULL, NULL)) {
8406 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large");
8410 if (!EnsureGPUMemoryAvailable(estimated_size)) {
8411 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory");
8415 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
8419 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
8420 ScopedResolvedFrameBufferBinder binder(this, false, true);
8421 gfx::Size size = GetBoundReadFrameBufferSize();
8423 if (texture->IsAttachedToFramebuffer()) {
8424 framebuffer_state_.clear_state_dirty = true;
8427 // Clip to size to source dimensions
8430 GLint copyWidth = 0;
8431 GLint copyHeight = 0;
8432 Clip(x, width, size.width(), ©X, ©Width);
8433 Clip(y, height, size.height(), ©Y, ©Height);
8437 copyWidth != width ||
8438 copyHeight != height) {
8439 // some part was clipped so clear the texture.
8441 texture->service_id(), texture->target(),
8442 target, level, internal_format, internal_format, GL_UNSIGNED_BYTE,
8443 width, height, texture->IsImmutable())) {
8445 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
8448 if (copyHeight > 0 && copyWidth > 0) {
8449 GLint dx = copyX - x;
8450 GLint dy = copyY - y;
8453 ScopedModifyPixels modify(texture_ref);
8454 glCopyTexSubImage2D(target, level,
8455 destX, destY, copyX, copyY,
8456 copyWidth, copyHeight);
8459 ScopedModifyPixels modify(texture_ref);
8460 glCopyTexImage2D(target, level, internal_format,
8461 copyX, copyY, copyWidth, copyHeight, border);
8463 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
8464 if (error == GL_NO_ERROR) {
8465 texture_manager()->SetLevelInfo(
8466 texture_ref, target, level, internal_format, width, height, 1,
8467 border, internal_format, GL_UNSIGNED_BYTE, true);
8471 void GLES2DecoderImpl::DoCopyTexSubImage2D(
8480 DCHECK(!ShouldDeferReads());
8481 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8485 GL_INVALID_OPERATION,
8486 "glCopyTexSubImage2D", "unknown texture for target");
8489 Texture* texture = texture_ref->texture();
8492 if (!texture->GetLevelType(target, level, &type, &format) ||
8493 !texture->ValidForTexture(
8494 target, level, xoffset, yoffset, width, height, type)) {
8496 GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
8499 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
8501 GL_INVALID_OPERATION,
8502 "glCopyTexSubImage2D", "async upload pending for texture");
8506 // Check we have compatible formats.
8507 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8508 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8509 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
8511 if (!channels_needed ||
8512 (channels_needed & channels_exist) != channels_needed) {
8514 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
8518 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8520 GL_INVALID_OPERATION,
8521 "glCopySubImage2D", "can not be used with depth or stencil textures");
8525 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
8529 ScopedResolvedFrameBufferBinder binder(this, false, true);
8530 gfx::Size size = GetBoundReadFrameBufferSize();
8533 GLint copyWidth = 0;
8534 GLint copyHeight = 0;
8535 Clip(x, width, size.width(), ©X, ©Width);
8536 Clip(y, height, size.height(), ©Y, ©Height);
8538 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, level)) {
8540 GL_OUT_OF_MEMORY, "glCopyTexSubImage2D", "dimensions too big");
8546 copyWidth != width ||
8547 copyHeight != height) {
8548 // some part was clipped so clear the sub rect.
8549 uint32 pixels_size = 0;
8550 if (!GLES2Util::ComputeImageDataSizes(
8551 width, height, format, type, state_.unpack_alignment, &pixels_size,
8554 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
8557 scoped_ptr<char[]> zero(new char[pixels_size]);
8558 memset(zero.get(), 0, pixels_size);
8559 ScopedModifyPixels modify(texture_ref);
8561 target, level, xoffset, yoffset, width, height,
8562 format, type, zero.get());
8565 if (copyHeight > 0 && copyWidth > 0) {
8566 GLint dx = copyX - x;
8567 GLint dy = copyY - y;
8568 GLint destX = xoffset + dx;
8569 GLint destY = yoffset + dy;
8570 ScopedModifyPixels modify(texture_ref);
8571 glCopyTexSubImage2D(target, level,
8572 destX, destY, copyX, copyY,
8573 copyWidth, copyHeight);
8577 bool GLES2DecoderImpl::ValidateTexSubImage2D(
8578 error::Error* error,
8579 const char* function_name,
8588 const void * data) {
8589 (*error) = error::kNoError;
8590 if (!validators_->texture_target.IsValid(target)) {
8591 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
8595 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
8599 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
8602 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8606 GL_INVALID_OPERATION,
8607 function_name, "unknown texture for target");
8610 Texture* texture = texture_ref->texture();
8611 GLenum current_type = 0;
8612 GLenum internal_format = 0;
8613 if (!texture->GetLevelType(target, level, ¤t_type, &internal_format)) {
8615 GL_INVALID_OPERATION, function_name, "level does not exist.");
8618 if (!texture_manager()->ValidateTextureParameters(state_.GetErrorState(),
8619 function_name, format, type, internal_format, level)) {
8622 if (type != current_type) {
8624 GL_INVALID_OPERATION,
8625 function_name, "type does not match type of texture.");
8628 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
8630 GL_INVALID_OPERATION,
8631 function_name, "async upload pending for texture");
8634 if (!texture->ValidForTexture(
8635 target, level, xoffset, yoffset, width, height, type)) {
8636 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
8639 if ((GLES2Util::GetChannelsForFormat(format) &
8640 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8642 GL_INVALID_OPERATION,
8643 function_name, "can not supply data for depth or stencil textures");
8647 (*error) = error::kOutOfBounds;
8653 error::Error GLES2DecoderImpl::DoTexSubImage2D(
8662 const void * data) {
8663 error::Error error = error::kNoError;
8664 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level,
8665 xoffset, yoffset, width, height, format, type, data)) {
8668 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8670 Texture* texture = texture_ref->texture();
8671 GLsizei tex_width = 0;
8672 GLsizei tex_height = 0;
8673 bool ok = texture->GetLevelSize(target, level, &tex_width, &tex_height);
8675 if (xoffset != 0 || yoffset != 0 ||
8676 width != tex_width || height != tex_height) {
8677 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
8680 GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big");
8681 return error::kNoError;
8683 ScopedTextureUploadTimer timer(&texture_state_);
8685 target, level, xoffset, yoffset, width, height, format, type, data);
8686 return error::kNoError;
8689 if (!texture_state_.texsubimage2d_faster_than_teximage2d &&
8690 !texture->IsImmutable()) {
8691 ScopedTextureUploadTimer timer(&texture_state_);
8692 GLenum internal_format;
8694 texture->GetLevelType(target, level, &tex_type, &internal_format);
8695 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
8698 target, level, internal_format, width, height, 0, format, type, data);
8700 ScopedTextureUploadTimer timer(&texture_state_);
8702 target, level, xoffset, yoffset, width, height, format, type, data);
8704 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
8705 return error::kNoError;
8708 error::Error GLES2DecoderImpl::HandleTexSubImage2D(
8709 uint32 immediate_data_size, const cmds::TexSubImage2D& c) {
8710 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
8711 "width", c.width, "height", c.height);
8712 GLboolean internal = static_cast<GLboolean>(c.internal);
8713 if (internal == GL_TRUE && texture_state_.tex_image_2d_failed)
8714 return error::kNoError;
8716 GLenum target = static_cast<GLenum>(c.target);
8717 GLint level = static_cast<GLint>(c.level);
8718 GLint xoffset = static_cast<GLint>(c.xoffset);
8719 GLint yoffset = static_cast<GLint>(c.yoffset);
8720 GLsizei width = static_cast<GLsizei>(c.width);
8721 GLsizei height = static_cast<GLsizei>(c.height);
8722 GLenum format = static_cast<GLenum>(c.format);
8723 GLenum type = static_cast<GLenum>(c.type);
8725 if (!GLES2Util::ComputeImageDataSizes(
8726 width, height, format, type, state_.unpack_alignment, &data_size,
8728 return error::kOutOfBounds;
8730 const void* pixels = GetSharedMemoryAs<const void*>(
8731 c.pixels_shm_id, c.pixels_shm_offset, data_size);
8732 return DoTexSubImage2D(
8733 target, level, xoffset, yoffset, width, height, format, type, pixels);
8736 error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
8737 uint32 immediate_data_size, const cmds::GetVertexAttribPointerv& c) {
8738 GLuint index = static_cast<GLuint>(c.index);
8739 GLenum pname = static_cast<GLenum>(c.pname);
8740 typedef cmds::GetVertexAttribPointerv::Result Result;
8741 Result* result = GetSharedMemoryAs<Result*>(
8742 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
8744 return error::kOutOfBounds;
8746 // Check that the client initialized the result.
8747 if (result->size != 0) {
8748 return error::kInvalidArguments;
8750 if (!validators_->vertex_pointer.IsValid(pname)) {
8751 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8752 "glGetVertexAttribPointerv", pname, "pname");
8753 return error::kNoError;
8755 if (index >= group_->max_vertex_attribs()) {
8757 GL_INVALID_VALUE, "glGetVertexAttribPointerv", "index out of range.");
8758 return error::kNoError;
8760 result->SetNumResults(1);
8761 *result->GetData() =
8762 state_.vertex_attrib_manager->GetVertexAttrib(index)->offset();
8763 return error::kNoError;
8766 bool GLES2DecoderImpl::GetUniformSetup(
8767 GLuint program_id, GLint fake_location,
8768 uint32 shm_id, uint32 shm_offset,
8769 error::Error* error, GLint* real_location,
8770 GLuint* service_id, void** result_pointer, GLenum* result_type) {
8773 DCHECK(result_pointer);
8774 DCHECK(result_type);
8775 DCHECK(real_location);
8776 *error = error::kNoError;
8777 // Make sure we have enough room for the result on failure.
8778 SizedResult<GLint>* result;
8779 result = GetSharedMemoryAs<SizedResult<GLint>*>(
8780 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
8782 *error = error::kOutOfBounds;
8785 *result_pointer = result;
8786 // Set the result size to 0 so the client does not have to check for success.
8787 result->SetNumResults(0);
8788 Program* program = GetProgramInfoNotShader(program_id, "glGetUniform");
8792 if (!program->IsValid()) {
8793 // Program was not linked successfully. (ie, glLinkProgram)
8795 GL_INVALID_OPERATION, "glGetUniform", "program not linked");
8798 *service_id = program->service_id();
8799 GLint array_index = -1;
8800 const Program::UniformInfo* uniform_info =
8801 program->GetUniformInfoByFakeLocation(
8802 fake_location, real_location, &array_index);
8803 if (!uniform_info) {
8804 // No such location.
8806 GL_INVALID_OPERATION, "glGetUniform", "unknown location");
8809 GLenum type = uniform_info->type;
8810 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
8812 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
8815 result = GetSharedMemoryAs<SizedResult<GLint>*>(
8816 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
8818 *error = error::kOutOfBounds;
8821 result->size = size;
8822 *result_type = type;
8826 error::Error GLES2DecoderImpl::HandleGetUniformiv(
8827 uint32 immediate_data_size, const cmds::GetUniformiv& c) {
8828 GLuint program = c.program;
8829 GLint fake_location = c.location;
8832 GLint real_location = -1;
8835 if (GetUniformSetup(
8836 program, fake_location, c.params_shm_id, c.params_shm_offset,
8837 &error, &real_location, &service_id, &result, &result_type)) {
8839 service_id, real_location,
8840 static_cast<cmds::GetUniformiv::Result*>(result)->GetData());
8845 error::Error GLES2DecoderImpl::HandleGetUniformfv(
8846 uint32 immediate_data_size, const cmds::GetUniformfv& c) {
8847 GLuint program = c.program;
8848 GLint fake_location = c.location;
8850 GLint real_location = -1;
8852 typedef cmds::GetUniformfv::Result Result;
8855 if (GetUniformSetup(
8856 program, fake_location, c.params_shm_id, c.params_shm_offset,
8857 &error, &real_location, &service_id,
8858 reinterpret_cast<void**>(&result), &result_type)) {
8859 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
8860 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
8861 GLsizei num_values = result->GetNumResults();
8862 scoped_ptr<GLint[]> temp(new GLint[num_values]);
8863 glGetUniformiv(service_id, real_location, temp.get());
8864 GLfloat* dst = result->GetData();
8865 for (GLsizei ii = 0; ii < num_values; ++ii) {
8866 dst[ii] = (temp[ii] != 0);
8869 glGetUniformfv(service_id, real_location, result->GetData());
8875 error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
8876 uint32 immediate_data_size, const cmds::GetShaderPrecisionFormat& c) {
8877 GLenum shader_type = static_cast<GLenum>(c.shadertype);
8878 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
8879 typedef cmds::GetShaderPrecisionFormat::Result Result;
8880 Result* result = GetSharedMemoryAs<Result*>(
8881 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8883 return error::kOutOfBounds;
8885 // Check that the client initialized the result.
8886 if (result->success != 0) {
8887 return error::kInvalidArguments;
8889 if (!validators_->shader_type.IsValid(shader_type)) {
8890 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8891 "glGetShaderPrecisionFormat", shader_type, "shader_type");
8892 return error::kNoError;
8894 if (!validators_->shader_precision.IsValid(precision_type)) {
8895 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8896 "glGetShaderPrecisionFormat", precision_type, "precision_type");
8897 return error::kNoError;
8900 result->success = 1; // true
8902 GLint range[2] = { 0, 0 };
8903 GLint precision = 0;
8904 GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
8906 result->min_range = range[0];
8907 result->max_range = range[1];
8908 result->precision = precision;
8910 return error::kNoError;
8913 error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
8914 uint32 immediate_data_size, const cmds::GetAttachedShaders& c) {
8915 uint32 result_size = c.result_size;
8916 GLuint program_id = static_cast<GLuint>(c.program);
8917 Program* program = GetProgramInfoNotShader(
8918 program_id, "glGetAttachedShaders");
8920 return error::kNoError;
8922 typedef cmds::GetAttachedShaders::Result Result;
8923 uint32 max_count = Result::ComputeMaxResults(result_size);
8924 Result* result = GetSharedMemoryAs<Result*>(
8925 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
8927 return error::kOutOfBounds;
8929 // Check that the client initialized the result.
8930 if (result->size != 0) {
8931 return error::kInvalidArguments;
8934 glGetAttachedShaders(
8935 program->service_id(), max_count, &count, result->GetData());
8936 for (GLsizei ii = 0; ii < count; ++ii) {
8937 if (!shader_manager()->GetClientId(result->GetData()[ii],
8938 &result->GetData()[ii])) {
8940 return error::kGenericError;
8943 result->SetNumResults(count);
8944 return error::kNoError;
8947 error::Error GLES2DecoderImpl::HandleGetActiveUniform(
8948 uint32 immediate_data_size, const cmds::GetActiveUniform& c) {
8949 GLuint program_id = c.program;
8950 GLuint index = c.index;
8951 uint32 name_bucket_id = c.name_bucket_id;
8952 typedef cmds::GetActiveUniform::Result Result;
8953 Result* result = GetSharedMemoryAs<Result*>(
8954 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8956 return error::kOutOfBounds;
8958 // Check that the client initialized the result.
8959 if (result->success != 0) {
8960 return error::kInvalidArguments;
8962 Program* program = GetProgramInfoNotShader(
8963 program_id, "glGetActiveUniform");
8965 return error::kNoError;
8967 const Program::UniformInfo* uniform_info =
8968 program->GetUniformInfo(index);
8969 if (!uniform_info) {
8971 GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
8972 return error::kNoError;
8974 result->success = 1; // true.
8975 result->size = uniform_info->size;
8976 result->type = uniform_info->type;
8977 Bucket* bucket = CreateBucket(name_bucket_id);
8978 bucket->SetFromString(uniform_info->name.c_str());
8979 return error::kNoError;
8982 error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
8983 uint32 immediate_data_size, const cmds::GetActiveAttrib& c) {
8984 GLuint program_id = c.program;
8985 GLuint index = c.index;
8986 uint32 name_bucket_id = c.name_bucket_id;
8987 typedef cmds::GetActiveAttrib::Result Result;
8988 Result* result = GetSharedMemoryAs<Result*>(
8989 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8991 return error::kOutOfBounds;
8993 // Check that the client initialized the result.
8994 if (result->success != 0) {
8995 return error::kInvalidArguments;
8997 Program* program = GetProgramInfoNotShader(
8998 program_id, "glGetActiveAttrib");
9000 return error::kNoError;
9002 const Program::VertexAttrib* attrib_info =
9003 program->GetAttribInfo(index);
9006 GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
9007 return error::kNoError;
9009 result->success = 1; // true.
9010 result->size = attrib_info->size;
9011 result->type = attrib_info->type;
9012 Bucket* bucket = CreateBucket(name_bucket_id);
9013 bucket->SetFromString(attrib_info->name.c_str());
9014 return error::kNoError;
9017 error::Error GLES2DecoderImpl::HandleShaderBinary(
9018 uint32 immediate_data_size, const cmds::ShaderBinary& c) {
9019 #if 1 // No binary shader support.
9020 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
9021 return error::kNoError;
9023 GLsizei n = static_cast<GLsizei>(c.n);
9025 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
9026 return error::kNoError;
9028 GLsizei length = static_cast<GLsizei>(c.length);
9030 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
9031 return error::kNoError;
9034 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
9035 return error::kOutOfBounds;
9037 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
9038 c.shaders_shm_id, c.shaders_shm_offset, data_size);
9039 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
9040 const void* binary = GetSharedMemoryAs<const void*>(
9041 c.binary_shm_id, c.binary_shm_offset, length);
9042 if (shaders == NULL || binary == NULL) {
9043 return error::kOutOfBounds;
9045 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
9046 for (GLsizei ii = 0; ii < n; ++ii) {
9047 Shader* shader = GetShader(shaders[ii]);
9049 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
9050 return error::kNoError;
9052 service_ids[ii] = shader->service_id();
9054 // TODO(gman): call glShaderBinary
9055 return error::kNoError;
9059 void GLES2DecoderImpl::DoSwapBuffers() {
9060 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
9062 int this_frame_number = frame_number_++;
9063 // TRACE_EVENT for gpu tests:
9064 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
9065 TRACE_EVENT_SCOPE_THREAD,
9066 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
9067 "width", (is_offscreen ? offscreen_size_.width() :
9068 surface_->GetSize().width()));
9069 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
9070 "offscreen", is_offscreen,
9071 "frame", this_frame_number);
9073 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
9077 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
9080 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
9081 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
9082 is_offscreen ? offscreen_size_ : surface_->GetSize());
9085 // If offscreen then don't actually SwapBuffers to the display. Just copy
9086 // the rendered frame to another frame buffer.
9088 TRACE_EVENT2("gpu", "Offscreen",
9089 "width", offscreen_size_.width(), "height", offscreen_size_.height());
9090 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
9091 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
9092 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
9094 if (workarounds().needs_offscreen_buffer_workaround) {
9095 offscreen_saved_frame_buffer_->Create();
9099 // Allocate the offscreen saved color texture.
9100 DCHECK(offscreen_saved_color_format_);
9101 offscreen_saved_color_texture_->AllocateStorage(
9102 offscreen_size_, offscreen_saved_color_format_, false);
9104 offscreen_saved_frame_buffer_->AttachRenderTexture(
9105 offscreen_saved_color_texture_.get());
9106 if (offscreen_size_.width() != 0 && offscreen_size_.height() != 0) {
9107 if (offscreen_saved_frame_buffer_->CheckStatus() !=
9108 GL_FRAMEBUFFER_COMPLETE) {
9109 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
9110 << "because offscreen saved FBO was incomplete.";
9111 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
9115 // Clear the offscreen color texture.
9116 // TODO(piman): Is this still necessary?
9118 ScopedFrameBufferBinder binder(this,
9119 offscreen_saved_frame_buffer_->id());
9120 glClearColor(0, 0, 0, 0);
9121 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
9122 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
9123 glClear(GL_COLOR_BUFFER_BIT);
9124 RestoreClearState();
9128 UpdateParentTextureInfo();
9131 if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
9133 ScopedGLErrorSuppressor suppressor(
9134 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
9136 if (IsOffscreenBufferMultisampled()) {
9137 // For multisampled buffers, resolve the frame buffer.
9138 ScopedResolvedFrameBufferBinder binder(this, true, false);
9140 ScopedFrameBufferBinder binder(this,
9141 offscreen_target_frame_buffer_->id());
9143 if (offscreen_target_buffer_preserved_) {
9144 // Copy the target frame buffer to the saved offscreen texture.
9145 offscreen_saved_color_texture_->Copy(
9146 offscreen_saved_color_texture_->size(),
9147 offscreen_saved_color_format_);
9149 // Flip the textures in the parent context via the texture manager.
9150 if (!!offscreen_saved_color_texture_info_.get())
9151 offscreen_saved_color_texture_info_->texture()->
9152 SetServiceId(offscreen_target_color_texture_->id());
9154 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
9155 offscreen_target_frame_buffer_->AttachRenderTexture(
9156 offscreen_target_color_texture_.get());
9159 // Ensure the side effects of the copy are visible to the parent
9160 // context. There is no need to do this for ANGLE because it uses a
9161 // single D3D device for all contexts.
9162 if (!feature_info_->feature_flags().is_angle)
9166 if (!surface_->SwapBuffers()) {
9167 LOG(ERROR) << "Context lost because SwapBuffers failed.";
9168 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
9173 error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
9174 uint32 immediate_data_size, const cmds::EnableFeatureCHROMIUM& c) {
9175 Bucket* bucket = GetBucket(c.bucket_id);
9176 if (!bucket || bucket->size() == 0) {
9177 return error::kInvalidArguments;
9179 typedef cmds::EnableFeatureCHROMIUM::Result Result;
9180 Result* result = GetSharedMemoryAs<Result*>(
9181 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9183 return error::kOutOfBounds;
9185 // Check that the client initialized the result.
9187 return error::kInvalidArguments;
9189 std::string feature_str;
9190 if (!bucket->GetAsString(&feature_str)) {
9191 return error::kInvalidArguments;
9194 // TODO(gman): make this some kind of table to function pointer thingy.
9195 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
9196 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
9197 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
9198 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
9199 // TODO(gman): decide how to remove the need for this const_cast.
9200 // I could make validators_ non const but that seems bad as this is the only
9201 // place it is needed. I could make some special friend class of validators
9202 // just to allow this to set them. That seems silly. I could refactor this
9203 // code to use the extension mechanism or the initialization attributes to
9204 // turn this feature on. Given that the only real point of this is to make
9205 // the conformance tests pass and given that there is lots of real work that
9206 // needs to be done it seems like refactoring for one to one of those
9207 // methods is a very low priority.
9208 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
9209 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
9210 force_webgl_glsl_validation_ = true;
9211 InitializeShaderTranslator();
9213 return error::kNoError;
9216 *result = 1; // true.
9217 return error::kNoError;
9220 error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
9221 uint32 immediate_data_size,
9222 const cmds::GetRequestableExtensionsCHROMIUM& c) {
9223 Bucket* bucket = CreateBucket(c.bucket_id);
9224 scoped_refptr<FeatureInfo> info(new FeatureInfo());
9225 info->Initialize(disallowed_features_);
9226 bucket->SetFromString(info->extensions().c_str());
9227 return error::kNoError;
9230 error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
9231 uint32 immediate_data_size, const cmds::RequestExtensionCHROMIUM& c) {
9232 Bucket* bucket = GetBucket(c.bucket_id);
9233 if (!bucket || bucket->size() == 0) {
9234 return error::kInvalidArguments;
9236 std::string feature_str;
9237 if (!bucket->GetAsString(&feature_str)) {
9238 return error::kInvalidArguments;
9241 bool desire_webgl_glsl_validation =
9242 feature_str.find("GL_CHROMIUM_webglsl") != std::string::npos;
9243 bool desire_standard_derivatives = false;
9244 bool desire_frag_depth = false;
9245 bool desire_draw_buffers = false;
9246 bool desire_shader_texture_lod = false;
9247 if (force_webgl_glsl_validation_) {
9248 desire_standard_derivatives =
9249 feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
9251 feature_str.find("GL_EXT_frag_depth") != std::string::npos;
9252 desire_draw_buffers =
9253 feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
9254 desire_shader_texture_lod =
9255 feature_str.find("GL_EXT_shader_texture_lod") != std::string::npos;
9258 if (desire_webgl_glsl_validation != force_webgl_glsl_validation_ ||
9259 desire_standard_derivatives != derivatives_explicitly_enabled_ ||
9260 desire_frag_depth != frag_depth_explicitly_enabled_ ||
9261 desire_draw_buffers != draw_buffers_explicitly_enabled_) {
9262 force_webgl_glsl_validation_ |= desire_webgl_glsl_validation;
9263 derivatives_explicitly_enabled_ |= desire_standard_derivatives;
9264 frag_depth_explicitly_enabled_ |= desire_frag_depth;
9265 draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
9266 shader_texture_lod_explicitly_enabled_ |= desire_shader_texture_lod;
9267 InitializeShaderTranslator();
9270 UpdateCapabilities();
9272 return error::kNoError;
9275 error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
9276 uint32 immediate_data_size, const cmds::GetMultipleIntegervCHROMIUM& c) {
9277 GLuint count = c.count;
9279 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
9280 return error::kOutOfBounds;
9282 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
9283 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
9284 if (pnames == NULL) {
9285 return error::kOutOfBounds;
9288 // We have to copy them since we use them twice so the client
9289 // can't change them between the time we validate them and the time we use
9291 scoped_ptr<GLenum[]> enums(new GLenum[count]);
9292 memcpy(enums.get(), pnames, pnames_size);
9294 // Count up the space needed for the result.
9295 uint32 num_results = 0;
9296 for (GLuint ii = 0; ii < count; ++ii) {
9297 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
9299 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9300 "glGetMultipleCHROMIUM", enums[ii], "pname");
9301 return error::kNoError;
9303 // Num will never be more than 4.
9305 if (!SafeAddUint32(num_results, num, &num_results)) {
9306 return error::kOutOfBounds;
9310 uint32 result_size = 0;
9311 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
9312 return error::kOutOfBounds;
9315 if (result_size != static_cast<uint32>(c.size)) {
9318 "glGetMultipleCHROMIUM", "bad size GL_INVALID_VALUE");
9319 return error::kNoError;
9322 GLint* results = GetSharedMemoryAs<GLint*>(
9323 c.results_shm_id, c.results_shm_offset, result_size);
9324 if (results == NULL) {
9325 return error::kOutOfBounds;
9328 // Check the results have been cleared in case the context was lost.
9329 for (uint32 ii = 0; ii < num_results; ++ii) {
9331 return error::kInvalidArguments;
9336 GLint* start = results;
9337 for (GLuint ii = 0; ii < count; ++ii) {
9338 GLsizei num_written = 0;
9339 if (!state_.GetStateAsGLint(enums[ii], results, &num_written) &&
9340 !GetHelper(enums[ii], results, &num_written)) {
9341 DoGetIntegerv(enums[ii], results);
9343 results += num_written;
9346 // Just to verify. Should this be a DCHECK?
9347 if (static_cast<uint32>(results - start) != num_results) {
9348 return error::kOutOfBounds;
9351 return error::kNoError;
9354 error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
9355 uint32 immediate_data_size, const cmds::GetProgramInfoCHROMIUM& c) {
9356 GLuint program_id = static_cast<GLuint>(c.program);
9357 uint32 bucket_id = c.bucket_id;
9358 Bucket* bucket = CreateBucket(bucket_id);
9359 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
9360 Program* program = NULL;
9361 program = GetProgram(program_id);
9362 if (!program || !program->IsValid()) {
9363 return error::kNoError;
9365 program->GetProgramInfo(program_manager(), bucket);
9366 return error::kNoError;
9369 error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
9370 switch (reset_status_) {
9372 // TODO(kbr): improve the precision of the error code in this case.
9373 // Consider delegating to context for error code if MakeCurrent fails.
9374 return error::kUnknown;
9375 case GL_GUILTY_CONTEXT_RESET_ARB:
9376 return error::kGuilty;
9377 case GL_INNOCENT_CONTEXT_RESET_ARB:
9378 return error::kInnocent;
9379 case GL_UNKNOWN_CONTEXT_RESET_ARB:
9380 return error::kUnknown;
9384 return error::kUnknown;
9387 bool GLES2DecoderImpl::WasContextLost() {
9388 if (reset_status_ != GL_NO_ERROR) {
9391 if (context_->WasAllocatedUsingRobustnessExtension()) {
9392 GLenum status = GL_NO_ERROR;
9393 if (has_robustness_extension_)
9394 status = glGetGraphicsResetStatusARB();
9395 if (status != GL_NO_ERROR) {
9396 // The graphics card was reset. Signal a lost context to the application.
9397 reset_status_ = status;
9398 reset_by_robustness_extension_ = true;
9399 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
9400 << " context lost via ARB/EXT_robustness. Reset status = "
9401 << GLES2Util::GetStringEnum(status);
9408 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() {
9409 return WasContextLost() && reset_by_robustness_extension_;
9412 void GLES2DecoderImpl::LoseContext(uint32 reset_status) {
9413 // Only loses the context once.
9414 if (reset_status_ != GL_NO_ERROR) {
9418 // Marks this context as lost.
9419 reset_status_ = reset_status;
9420 current_decoder_error_ = error::kLostContext;
9423 error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
9424 uint32 immediate_data_size, const cmds::InsertSyncPointCHROMIUM& c) {
9425 return error::kUnknownCommand;
9428 error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
9429 uint32 immediate_data_size, const cmds::WaitSyncPointCHROMIUM& c) {
9430 group_->mailbox_manager()->PullTextureUpdates();
9431 if (wait_sync_point_callback_.is_null())
9432 return error::kNoError;
9434 return wait_sync_point_callback_.Run(c.sync_point) ?
9435 error::kNoError : error::kDeferCommandUntilLater;
9438 error::Error GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
9439 uint32 immediate_data_size, const cmds::DiscardBackbufferCHROMIUM& c) {
9440 if (surface_->DeferDraws())
9441 return error::kDeferCommandUntilLater;
9442 if (!surface_->SetBackbufferAllocation(false))
9443 return error::kLostContext;
9444 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
9445 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
9446 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
9447 return error::kNoError;
9450 bool GLES2DecoderImpl::GenQueriesEXTHelper(
9451 GLsizei n, const GLuint* client_ids) {
9452 for (GLsizei ii = 0; ii < n; ++ii) {
9453 if (query_manager_->GetQuery(client_ids[ii])) {
9457 query_manager_->GenQueries(n, client_ids);
9461 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
9462 GLsizei n, const GLuint* client_ids) {
9463 for (GLsizei ii = 0; ii < n; ++ii) {
9464 QueryManager::Query* query = query_manager_->GetQuery(client_ids[ii]);
9465 if (query && !query->IsDeleted()) {
9466 ContextState::QueryMap::iterator it =
9467 state_.current_queries.find(query->target());
9468 if (it != state_.current_queries.end())
9469 state_.current_queries.erase(it);
9471 query->Destroy(true);
9473 query_manager_->RemoveQuery(client_ids[ii]);
9477 bool GLES2DecoderImpl::ProcessPendingQueries() {
9478 if (query_manager_.get() == NULL) {
9481 if (!query_manager_->ProcessPendingQueries()) {
9482 current_decoder_error_ = error::kOutOfBounds;
9484 return query_manager_->HavePendingQueries();
9487 // Note that if there are no pending readpixels right now,
9488 // this function will call the callback immediately.
9489 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback) {
9490 if (features().use_async_readpixels && !pending_readpixel_fences_.empty()) {
9491 pending_readpixel_fences_.back()->callbacks.push_back(callback);
9497 void GLES2DecoderImpl::ProcessPendingReadPixels() {
9498 while (!pending_readpixel_fences_.empty() &&
9499 pending_readpixel_fences_.front()->fence->HasCompleted()) {
9500 std::vector<base::Closure> callbacks =
9501 pending_readpixel_fences_.front()->callbacks;
9502 pending_readpixel_fences_.pop();
9503 for (size_t i = 0; i < callbacks.size(); i++) {
9509 bool GLES2DecoderImpl::HasMoreIdleWork() {
9510 return !pending_readpixel_fences_.empty() ||
9511 async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers();
9514 void GLES2DecoderImpl::PerformIdleWork() {
9515 ProcessPendingReadPixels();
9516 if (!async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers())
9518 async_pixel_transfer_manager_->ProcessMorePendingTransfers();
9519 ProcessFinishedAsyncTransfers();
9522 error::Error GLES2DecoderImpl::HandleBeginQueryEXT(
9523 uint32 immediate_data_size, const cmds::BeginQueryEXT& c) {
9524 GLenum target = static_cast<GLenum>(c.target);
9525 GLuint client_id = static_cast<GLuint>(c.id);
9526 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
9527 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
9530 case GL_COMMANDS_ISSUED_CHROMIUM:
9531 case GL_LATENCY_QUERY_CHROMIUM:
9532 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM:
9533 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
9534 case GL_GET_ERROR_QUERY_CHROMIUM:
9536 case GL_COMMANDS_COMPLETED_CHROMIUM:
9537 if (!features().chromium_sync_query) {
9539 GL_INVALID_OPERATION, "glBeginQueryEXT",
9540 "not enabled for commands completed queries");
9541 return error::kNoError;
9545 if (!features().occlusion_query_boolean) {
9547 GL_INVALID_OPERATION, "glBeginQueryEXT",
9548 "not enabled for occlusion queries");
9549 return error::kNoError;
9554 if (state_.current_queries.find(target) != state_.current_queries.end()) {
9556 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
9557 return error::kNoError;
9560 if (client_id == 0) {
9561 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
9562 return error::kNoError;
9565 QueryManager::Query* query = query_manager_->GetQuery(client_id);
9567 if (!query_manager_->IsValidQuery(client_id)) {
9568 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
9570 "id not made by glGenQueriesEXT");
9571 return error::kNoError;
9573 query = query_manager_->CreateQuery(
9574 target, client_id, sync_shm_id, sync_shm_offset);
9577 if (query->target() != target) {
9579 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
9580 return error::kNoError;
9581 } else if (query->shm_id() != sync_shm_id ||
9582 query->shm_offset() != sync_shm_offset) {
9583 DLOG(ERROR) << "Shared memory used by query not the same as before";
9584 return error::kInvalidArguments;
9587 if (!query_manager_->BeginQuery(query)) {
9588 return error::kOutOfBounds;
9591 state_.current_queries[target] = query;
9592 return error::kNoError;
9595 error::Error GLES2DecoderImpl::HandleEndQueryEXT(
9596 uint32 immediate_data_size, const cmds::EndQueryEXT& c) {
9597 GLenum target = static_cast<GLenum>(c.target);
9598 uint32 submit_count = static_cast<GLuint>(c.submit_count);
9599 ContextState::QueryMap::iterator it = state_.current_queries.find(target);
9601 if (it == state_.current_queries.end()) {
9603 GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
9604 return error::kNoError;
9607 QueryManager::Query* query = it->second.get();
9608 if (!query_manager_->EndQuery(query, submit_count)) {
9609 return error::kOutOfBounds;
9612 query_manager_->ProcessPendingTransferQueries();
9614 state_.current_queries.erase(it);
9615 return error::kNoError;
9618 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
9619 GLsizei n, const GLuint* client_ids) {
9620 for (GLsizei ii = 0; ii < n; ++ii) {
9621 if (GetVertexAttribManager(client_ids[ii])) {
9626 if (!features().native_vertex_array_object) {
9628 for (GLsizei ii = 0; ii < n; ++ii) {
9629 CreateVertexAttribManager(client_ids[ii], 0, true);
9632 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
9634 glGenVertexArraysOES(n, service_ids.get());
9635 for (GLsizei ii = 0; ii < n; ++ii) {
9636 CreateVertexAttribManager(client_ids[ii], service_ids[ii], true);
9643 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
9644 GLsizei n, const GLuint* client_ids) {
9645 for (GLsizei ii = 0; ii < n; ++ii) {
9646 VertexAttribManager* vao =
9647 GetVertexAttribManager(client_ids[ii]);
9648 if (vao && !vao->IsDeleted()) {
9649 if (state_.vertex_attrib_manager.get() == vao) {
9650 DoBindVertexArrayOES(0);
9652 RemoveVertexAttribManager(client_ids[ii]);
9657 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
9658 VertexAttribManager* vao = NULL;
9659 if (client_id != 0) {
9660 vao = GetVertexAttribManager(client_id);
9662 // Unlike most Bind* methods, the spec explicitly states that VertexArray
9663 // only allows names that have been previously generated. As such, we do
9664 // not generate new names here.
9666 GL_INVALID_OPERATION,
9667 "glBindVertexArrayOES", "bad vertex array id.");
9668 current_decoder_error_ = error::kNoError;
9672 vao = state_.default_vertex_attrib_manager.get();
9675 // Only set the VAO state if it's changed
9676 if (state_.vertex_attrib_manager.get() != vao) {
9677 state_.vertex_attrib_manager = vao;
9678 if (!features().native_vertex_array_object) {
9679 EmulateVertexArrayState();
9681 GLuint service_id = vao->service_id();
9682 glBindVertexArrayOES(service_id);
9687 // Used when OES_vertex_array_object isn't natively supported
9688 void GLES2DecoderImpl::EmulateVertexArrayState() {
9689 // Setup the Vertex attribute state
9690 for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) {
9691 RestoreStateForAttrib(vv, true);
9694 // Setup the element buffer
9695 Buffer* element_array_buffer =
9696 state_.vertex_attrib_manager->element_array_buffer();
9697 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
9698 element_array_buffer ? element_array_buffer->service_id() : 0);
9701 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
9702 const VertexAttribManager* vao =
9703 GetVertexAttribManager(client_id);
9704 return vao && vao->IsValid() && !vao->IsDeleted();
9707 #if defined(OS_MACOSX)
9708 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
9709 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
9711 if (it != texture_to_io_surface_map_.end()) {
9712 // Found a previous IOSurface bound to this texture; release it.
9713 IOSurfaceRef surface = it->second;
9715 texture_to_io_surface_map_.erase(it);
9720 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
9721 GLenum target, GLsizei width, GLsizei height,
9722 GLuint io_surface_id, GLuint plane) {
9723 #if defined(OS_MACOSX)
9724 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
9726 GL_INVALID_OPERATION,
9727 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
9731 if (target != GL_TEXTURE_RECTANGLE_ARB) {
9732 // This might be supported in the future, and if we could require
9733 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
9734 // could delete a lot of code. For now, perform strict validation so we
9735 // know what's going on.
9737 GL_INVALID_OPERATION,
9738 "glTexImageIOSurface2DCHROMIUM",
9739 "requires TEXTURE_RECTANGLE_ARB target");
9743 // Default target might be conceptually valid, but disallow it to avoid
9745 TextureRef* texture_ref =
9746 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
9749 GL_INVALID_OPERATION,
9750 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
9754 // Look up the new IOSurface. Note that because of asynchrony
9755 // between processes this might fail; during live resizing the
9756 // plugin process might allocate and release an IOSurface before
9757 // this process gets a chance to look it up. Hold on to any old
9758 // IOSurface in this case.
9759 IOSurfaceRef surface = IOSurfaceLookup(io_surface_id);
9762 GL_INVALID_OPERATION,
9763 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
9767 // Release any IOSurface previously bound to this texture.
9768 ReleaseIOSurfaceForTexture(texture_ref->service_id());
9770 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
9771 texture_to_io_surface_map_.insert(
9772 std::make_pair(texture_ref->service_id(), surface));
9774 CGLContextObj context =
9775 static_cast<CGLContextObj>(context_->GetHandle());
9777 CGLError err = CGLTexImageIOSurface2D(
9784 GL_UNSIGNED_INT_8_8_8_8_REV,
9788 if (err != kCGLNoError) {
9790 GL_INVALID_OPERATION,
9791 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
9795 texture_manager()->SetLevelInfo(
9796 texture_ref, target, 0, GL_RGBA, width, height, 1, 0,
9797 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
9800 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
9801 "glTexImageIOSurface2DCHROMIUM", "not supported.");
9805 static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
9806 switch (internalformat) {
9817 case GL_LUMINANCE8_ALPHA8_EXT:
9818 return GL_LUMINANCE_ALPHA;
9819 case GL_LUMINANCE8_EXT:
9820 return GL_LUMINANCE;
9823 case GL_RGBA32F_EXT:
9827 case GL_ALPHA32F_EXT:
9829 case GL_LUMINANCE32F_EXT:
9830 return GL_LUMINANCE;
9831 case GL_LUMINANCE_ALPHA32F_EXT:
9832 return GL_LUMINANCE_ALPHA;
9833 case GL_RGBA16F_EXT:
9837 case GL_ALPHA16F_EXT:
9839 case GL_LUMINANCE16F_EXT:
9840 return GL_LUMINANCE;
9841 case GL_LUMINANCE_ALPHA16F_EXT:
9842 return GL_LUMINANCE_ALPHA;
9850 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
9851 GLenum target, GLuint source_id, GLuint dest_id, GLint level,
9852 GLenum internal_format, GLenum dest_type) {
9853 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
9855 TextureRef* dest_texture_ref = GetTexture(dest_id);
9856 TextureRef* source_texture_ref = GetTexture(source_id);
9858 if (!source_texture_ref || !dest_texture_ref) {
9860 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "unknown texture id");
9864 if (GL_TEXTURE_2D != target) {
9866 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "invalid texture target");
9870 Texture* source_texture = source_texture_ref->texture();
9871 Texture* dest_texture = dest_texture_ref->texture();
9872 if (dest_texture->target() != GL_TEXTURE_2D ||
9873 (source_texture->target() != GL_TEXTURE_2D &&
9874 source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
9875 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
9876 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
9877 "glCopyTextureCHROMIUM",
9878 "invalid texture target binding");
9882 int source_width, source_height, dest_width, dest_height;
9884 gfx::GLImage* image =
9885 source_texture->GetLevelImage(source_texture->target(), 0);
9887 gfx::Size size = image->GetSize();
9888 source_width = size.width();
9889 source_height = size.height();
9890 if (source_width <= 0 || source_height <= 0) {
9893 "glCopyTextureChromium", "invalid image size");
9897 if (!source_texture->GetLevelSize(
9898 source_texture->target(), 0, &source_width, &source_height)) {
9899 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
9900 "glCopyTextureChromium",
9901 "source texture has no level 0");
9905 // Check that this type of texture is allowed.
9906 if (!texture_manager()->ValidForTarget(
9907 source_texture->target(), level, source_width, source_height, 1)) {
9909 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "Bad dimensions");
9914 // Clear the source texture if necessary.
9915 if (!texture_manager()->ClearTextureLevel(
9916 this, source_texture_ref, source_texture->target(), 0)) {
9918 GL_OUT_OF_MEMORY, "glCopyTextureCHROMIUM", "dimensions too big");
9922 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
9923 // needed because it takes 10s of milliseconds to initialize.
9924 if (!copy_texture_CHROMIUM_.get()) {
9925 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
9926 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
9927 copy_texture_CHROMIUM_->Initialize(this);
9928 RestoreCurrentFramebufferBindings();
9929 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
9933 GLenum dest_type_previous;
9934 GLenum dest_internal_format;
9935 bool dest_level_defined = dest_texture->GetLevelSize(
9936 GL_TEXTURE_2D, level, &dest_width, &dest_height);
9938 if (dest_level_defined) {
9939 dest_texture->GetLevelType(GL_TEXTURE_2D, level, &dest_type_previous,
9940 &dest_internal_format);
9943 // Resize the destination texture to the dimensions of the source texture.
9944 if (!dest_level_defined || dest_width != source_width ||
9945 dest_height != source_height ||
9946 dest_internal_format != internal_format ||
9947 dest_type_previous != dest_type) {
9948 // Ensure that the glTexImage2D succeeds.
9949 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
9950 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
9952 GL_TEXTURE_2D, level, internal_format, source_width, source_height,
9953 0, internal_format, dest_type, NULL);
9954 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
9955 if (error != GL_NO_ERROR) {
9956 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
9960 texture_manager()->SetLevelInfo(
9961 dest_texture_ref, GL_TEXTURE_2D, level, internal_format, source_width,
9962 source_height, 1, 0, internal_format, dest_type, true);
9964 texture_manager()->SetLevelCleared(
9965 dest_texture_ref, GL_TEXTURE_2D, level, true);
9968 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
9969 ScopedModifyPixels modify(dest_texture_ref);
9971 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
9972 // before presenting.
9973 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
9974 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
9975 // instead of using default matrix crbug.com/226218.
9976 const static GLfloat default_matrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
9977 0.0f, 1.0f, 0.0f, 0.0f,
9978 0.0f, 0.0f, 1.0f, 0.0f,
9979 0.0f, 0.0f, 0.0f, 1.0f};
9980 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
9982 source_texture->target(),
9983 dest_texture->target(),
9984 source_texture->service_id(),
9985 dest_texture->service_id(), level,
9986 source_width, source_height,
9988 unpack_premultiply_alpha_,
9989 unpack_unpremultiply_alpha_,
9992 copy_texture_CHROMIUM_->DoCopyTexture(
9994 source_texture->target(),
9995 dest_texture->target(),
9996 source_texture->service_id(),
9997 dest_texture->service_id(), level,
9998 source_width, source_height,
10000 unpack_premultiply_alpha_,
10001 unpack_unpremultiply_alpha_);
10004 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
10007 static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
10008 switch (internalformat) {
10010 return GL_UNSIGNED_SHORT_5_6_5;
10012 return GL_UNSIGNED_SHORT_4_4_4_4;
10014 return GL_UNSIGNED_SHORT_5_5_5_1;
10016 return GL_UNSIGNED_BYTE;
10018 return GL_UNSIGNED_BYTE;
10019 case GL_LUMINANCE8_ALPHA8_EXT:
10020 return GL_UNSIGNED_BYTE;
10021 case GL_LUMINANCE8_EXT:
10022 return GL_UNSIGNED_BYTE;
10023 case GL_ALPHA8_EXT:
10024 return GL_UNSIGNED_BYTE;
10025 case GL_RGBA32F_EXT:
10027 case GL_RGB32F_EXT:
10029 case GL_ALPHA32F_EXT:
10031 case GL_LUMINANCE32F_EXT:
10033 case GL_LUMINANCE_ALPHA32F_EXT:
10035 case GL_RGBA16F_EXT:
10036 return GL_HALF_FLOAT_OES;
10037 case GL_RGB16F_EXT:
10038 return GL_HALF_FLOAT_OES;
10039 case GL_ALPHA16F_EXT:
10040 return GL_HALF_FLOAT_OES;
10041 case GL_LUMINANCE16F_EXT:
10042 return GL_HALF_FLOAT_OES;
10043 case GL_LUMINANCE_ALPHA16F_EXT:
10044 return GL_HALF_FLOAT_OES;
10046 return GL_UNSIGNED_BYTE;
10052 void GLES2DecoderImpl::DoTexStorage2DEXT(
10055 GLenum internal_format,
10058 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
10059 "width", width, "height", height);
10060 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
10061 TextureManager::ComputeMipMapCount(target, width, height, 1) < levels) {
10062 LOCAL_SET_GL_ERROR(
10063 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
10066 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10068 if (!texture_ref) {
10069 LOCAL_SET_GL_ERROR(
10070 GL_INVALID_OPERATION,
10071 "glTexStorage2DEXT", "unknown texture for target");
10074 Texture* texture = texture_ref->texture();
10075 if (texture->IsAttachedToFramebuffer()) {
10076 framebuffer_state_.clear_state_dirty = true;
10078 if (texture->IsImmutable()) {
10079 LOCAL_SET_GL_ERROR(
10080 GL_INVALID_OPERATION,
10081 "glTexStorage2DEXT", "texture is immutable");
10085 GLenum format = ExtractFormatFromStorageFormat(internal_format);
10086 GLenum type = ExtractTypeFromStorageFormat(internal_format);
10089 GLsizei level_width = width;
10090 GLsizei level_height = height;
10091 uint32 estimated_size = 0;
10092 for (int ii = 0; ii < levels; ++ii) {
10093 uint32 level_size = 0;
10094 if (!GLES2Util::ComputeImageDataSizes(
10095 level_width, level_height, format, type, state_.unpack_alignment,
10096 &estimated_size, NULL, NULL) ||
10097 !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
10098 LOCAL_SET_GL_ERROR(
10099 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large");
10102 level_width = std::max(1, level_width >> 1);
10103 level_height = std::max(1, level_height >> 1);
10105 if (!EnsureGPUMemoryAvailable(estimated_size)) {
10106 LOCAL_SET_GL_ERROR(
10107 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory");
10112 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
10113 glTexStorage2DEXT(target, levels, internal_format, width, height);
10114 GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
10115 if (error == GL_NO_ERROR) {
10116 GLsizei level_width = width;
10117 GLsizei level_height = height;
10118 for (int ii = 0; ii < levels; ++ii) {
10119 texture_manager()->SetLevelInfo(
10120 texture_ref, target, ii, format,
10121 level_width, level_height, 1, 0, format, type, false);
10122 level_width = std::max(1, level_width >> 1);
10123 level_height = std::max(1, level_height >> 1);
10125 texture->SetImmutable(true);
10129 error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
10130 uint32 immediate_data_size, const cmds::GenMailboxCHROMIUM& c) {
10131 return error::kUnknownCommand;
10134 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
10135 const GLbyte* data) {
10136 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
10137 "context", logger_.GetLogPrefix(),
10138 "mailbox[0]", static_cast<unsigned char>(data[0]));
10140 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10142 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref, target, data);
10145 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id,
10146 GLenum target, const GLbyte* data) {
10147 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
10148 "context", logger_.GetLogPrefix(),
10149 "mailbox[0]", static_cast<unsigned char>(data[0]));
10151 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id),
10155 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name,
10156 TextureRef* texture_ref, GLenum target, const GLbyte* data) {
10157 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
10158 DLOG_IF(ERROR, !mailbox.Verify()) << func_name << " was passed a "
10159 "mailbox that was not generated by "
10160 "GenMailboxCHROMIUM.";
10162 if (!texture_ref) {
10163 LOCAL_SET_GL_ERROR(
10164 GL_INVALID_OPERATION, func_name.c_str(), "unknown texture for target");
10168 Texture* produced = texture_manager()->Produce(texture_ref);
10170 LOCAL_SET_GL_ERROR(
10171 GL_INVALID_OPERATION, func_name.c_str(), "invalid texture");
10175 if (produced->target() != target) {
10176 LOCAL_SET_GL_ERROR(
10177 GL_INVALID_OPERATION, func_name.c_str(), "invalid target");
10181 group_->mailbox_manager()->ProduceTexture(target, mailbox, produced);
10184 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
10185 const GLbyte* data) {
10186 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
10187 "context", logger_.GetLogPrefix(),
10188 "mailbox[0]", static_cast<unsigned char>(data[0]));
10189 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
10190 DLOG_IF(ERROR, !mailbox.Verify()) << "ConsumeTextureCHROMIUM was passed a "
10191 "mailbox that was not generated by "
10192 "GenMailboxCHROMIUM.";
10194 scoped_refptr<TextureRef> texture_ref =
10195 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10196 if (!texture_ref.get()) {
10197 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10198 "glConsumeTextureCHROMIUM",
10199 "unknown texture for target");
10202 GLuint client_id = texture_ref->client_id();
10204 LOCAL_SET_GL_ERROR(
10205 GL_INVALID_OPERATION,
10206 "glConsumeTextureCHROMIUM", "unknown texture for target");
10209 Texture* texture = group_->mailbox_manager()->ConsumeTexture(target, mailbox);
10211 LOCAL_SET_GL_ERROR(
10212 GL_INVALID_OPERATION,
10213 "glConsumeTextureCHROMIUM", "invalid mailbox name");
10216 if (texture->target() != target) {
10217 LOCAL_SET_GL_ERROR(
10218 GL_INVALID_OPERATION,
10219 "glConsumeTextureCHROMIUM", "invalid target");
10223 DeleteTexturesHelper(1, &client_id);
10224 texture_ref = texture_manager()->Consume(client_id, texture);
10225 glBindTexture(target, texture_ref->service_id());
10227 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
10228 unit.bind_target = target;
10230 case GL_TEXTURE_2D:
10231 unit.bound_texture_2d = texture_ref;
10233 case GL_TEXTURE_CUBE_MAP:
10234 unit.bound_texture_cube_map = texture_ref;
10236 case GL_TEXTURE_EXTERNAL_OES:
10237 unit.bound_texture_external_oes = texture_ref;
10239 case GL_TEXTURE_RECTANGLE_ARB:
10240 unit.bound_texture_rectangle_arb = texture_ref;
10243 NOTREACHED(); // Validation should prevent us getting here.
10248 error::Error GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
10249 uint32_t immediate_data_size,
10250 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate& c) {
10251 GLenum target = static_cast<GLenum>(c.target);
10252 uint32_t data_size;
10253 if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) {
10254 return error::kOutOfBounds;
10256 if (data_size > immediate_data_size) {
10257 return error::kOutOfBounds;
10259 const GLbyte* mailbox =
10260 GetImmediateDataAs<const GLbyte*>(c, data_size, immediate_data_size);
10261 if (!validators_->texture_bind_target.IsValid(target)) {
10262 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10263 "glCreateAndConsumeTextureCHROMIUM", target, "target");
10264 return error::kNoError;
10266 if (mailbox == NULL) {
10267 return error::kOutOfBounds;
10269 uint32_t client_id = c.client_id;
10270 DoCreateAndConsumeTextureCHROMIUM(target, mailbox, client_id);
10271 return error::kNoError;
10274 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target,
10275 const GLbyte* data, GLuint client_id) {
10276 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
10277 "context", logger_.GetLogPrefix(),
10278 "mailbox[0]", static_cast<unsigned char>(data[0]));
10279 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
10280 DLOG_IF(ERROR, !mailbox.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
10281 "passed a mailbox that was not "
10282 "generated by GenMailboxCHROMIUM.";
10284 TextureRef* texture_ref = GetTexture(client_id);
10286 LOCAL_SET_GL_ERROR(
10287 GL_INVALID_OPERATION,
10288 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
10291 Texture* texture = group_->mailbox_manager()->ConsumeTexture(target, mailbox);
10293 LOCAL_SET_GL_ERROR(
10294 GL_INVALID_OPERATION,
10295 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
10298 if (texture->target() != target) {
10299 LOCAL_SET_GL_ERROR(
10300 GL_INVALID_OPERATION,
10301 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
10305 IdAllocatorInterface* id_allocator =
10306 group_->GetIdAllocator(id_namespaces::kTextures);
10307 id_allocator->MarkAsUsed(client_id);
10309 texture_ref = texture_manager()->Consume(client_id, texture);
10312 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
10313 GLsizei length, const GLchar* marker) {
10317 debug_marker_manager_.SetMarker(
10318 length ? std::string(marker, length) : std::string(marker));
10321 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
10322 GLsizei length, const GLchar* marker) {
10326 std::string name = length ? std::string(marker, length) : std::string(marker);
10327 debug_marker_manager_.PushGroup(name);
10328 gpu_tracer_->Begin(name, kTraceGroupMarker);
10331 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
10332 debug_marker_manager_.PopGroup();
10333 gpu_tracer_->End(kTraceGroupMarker);
10336 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
10337 GLenum target, GLint image_id) {
10338 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
10340 if (target == GL_TEXTURE_CUBE_MAP) {
10341 LOCAL_SET_GL_ERROR(
10343 "glBindTexImage2DCHROMIUM", "invalid target");
10347 // Default target might be conceptually valid, but disallow it to avoid
10349 TextureRef* texture_ref =
10350 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10351 if (!texture_ref) {
10352 LOCAL_SET_GL_ERROR(
10353 GL_INVALID_OPERATION,
10354 "glBindTexImage2DCHROMIUM", "no texture bound");
10358 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
10360 LOCAL_SET_GL_ERROR(
10361 GL_INVALID_OPERATION,
10362 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
10367 ScopedGLErrorSuppressor suppressor(
10368 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
10369 if (!gl_image->BindTexImage(target)) {
10370 LOCAL_SET_GL_ERROR(
10371 GL_INVALID_OPERATION,
10372 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
10377 gfx::Size size = gl_image->GetSize();
10378 texture_manager()->SetLevelInfo(
10379 texture_ref, target, 0, GL_RGBA, size.width(), size.height(), 1, 0,
10380 GL_RGBA, GL_UNSIGNED_BYTE, true);
10381 texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image);
10384 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
10385 GLenum target, GLint image_id) {
10386 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
10388 // Default target might be conceptually valid, but disallow it to avoid
10390 TextureRef* texture_ref =
10391 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10392 if (!texture_ref) {
10393 LOCAL_SET_GL_ERROR(
10394 GL_INVALID_OPERATION,
10395 "glReleaseTexImage2DCHROMIUM", "no texture bound");
10399 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
10401 LOCAL_SET_GL_ERROR(
10402 GL_INVALID_OPERATION,
10403 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
10407 // Do nothing when image is not currently bound.
10408 if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image)
10412 ScopedGLErrorSuppressor suppressor(
10413 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
10414 gl_image->ReleaseTexImage(target);
10417 texture_manager()->SetLevelInfo(
10418 texture_ref, target, 0, GL_RGBA, 0, 0, 1, 0,
10419 GL_RGBA, GL_UNSIGNED_BYTE, false);
10422 error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
10423 uint32 immediate_data_size, const cmds::TraceBeginCHROMIUM& c) {
10424 Bucket* bucket = GetBucket(c.bucket_id);
10425 if (!bucket || bucket->size() == 0) {
10426 return error::kInvalidArguments;
10428 std::string command_name;
10429 if (!bucket->GetAsString(&command_name)) {
10430 return error::kInvalidArguments;
10432 TRACE_EVENT_COPY_ASYNC_BEGIN0("gpu", command_name.c_str(), this);
10433 if (!gpu_tracer_->Begin(command_name, kTraceCHROMIUM)) {
10434 LOCAL_SET_GL_ERROR(
10435 GL_INVALID_OPERATION,
10436 "glTraceBeginCHROMIUM", "unable to create begin trace");
10437 return error::kNoError;
10439 return error::kNoError;
10442 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
10443 if (gpu_tracer_->CurrentName().empty()) {
10444 LOCAL_SET_GL_ERROR(
10445 GL_INVALID_OPERATION,
10446 "glTraceEndCHROMIUM", "no trace begin found");
10449 TRACE_EVENT_COPY_ASYNC_END0("gpu", gpu_tracer_->CurrentName().c_str(), this);
10450 gpu_tracer_->End(kTraceCHROMIUM);
10453 void GLES2DecoderImpl::DoDrawBuffersEXT(
10454 GLsizei count, const GLenum* bufs) {
10455 if (count > static_cast<GLsizei>(group_->max_draw_buffers())) {
10456 LOCAL_SET_GL_ERROR(
10458 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
10462 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
10464 for (GLsizei i = 0; i < count; ++i) {
10465 if (bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i) &&
10466 bufs[i] != GL_NONE) {
10467 LOCAL_SET_GL_ERROR(
10468 GL_INVALID_OPERATION,
10469 "glDrawBuffersEXT",
10470 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
10474 glDrawBuffersARB(count, bufs);
10475 framebuffer->SetDrawBuffers(count, bufs);
10476 } else { // backbuffer
10478 (bufs[0] != GL_BACK && bufs[0] != GL_NONE)) {
10479 LOCAL_SET_GL_ERROR(
10480 GL_INVALID_OPERATION,
10481 "glDrawBuffersEXT",
10482 "more than one buffer or bufs not GL_NONE or GL_BACK");
10485 GLenum mapped_buf = bufs[0];
10486 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
10487 bufs[0] == GL_BACK) {
10488 mapped_buf = GL_COLOR_ATTACHMENT0;
10490 glDrawBuffersARB(count, &mapped_buf);
10491 group_->set_draw_buffer(bufs[0]);
10495 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current, GLenum other) {
10496 group_->LoseContexts(other);
10497 reset_status_ = current;
10498 current_decoder_error_ = error::kLostContext;
10501 bool GLES2DecoderImpl::ValidateAsyncTransfer(
10502 const char* function_name,
10503 TextureRef* texture_ref,
10506 const void * data) {
10507 // We only support async uploads to 2D textures for now.
10508 if (GL_TEXTURE_2D != target) {
10509 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
10512 // We only support uploads to level zero for now.
10514 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "level != 0");
10517 // A transfer buffer must be bound, even for asyncTexImage2D.
10518 if (data == NULL) {
10519 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "buffer == 0");
10522 // We only support one async transfer in progress.
10523 if (!texture_ref ||
10524 async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
10525 LOCAL_SET_GL_ERROR(
10526 GL_INVALID_OPERATION,
10527 function_name, "transfer already in progress");
10533 base::Closure GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
10534 uint32 async_upload_token,
10535 uint32 sync_data_shm_id,
10536 uint32 sync_data_shm_offset) {
10537 scoped_refptr<gpu::Buffer> buffer = GetSharedMemoryBuffer(sync_data_shm_id);
10538 if (!buffer || !buffer->GetDataAddress(sync_data_shm_offset,
10539 sizeof(AsyncUploadSync)))
10540 return base::Closure();
10542 AsyncMemoryParams mem_params(buffer,
10543 sync_data_shm_offset,
10544 sizeof(AsyncUploadSync));
10546 scoped_refptr<AsyncUploadTokenCompletionObserver> observer(
10547 new AsyncUploadTokenCompletionObserver(async_upload_token));
10550 &AsyncPixelTransferManager::AsyncNotifyCompletion,
10551 base::Unretained(GetAsyncPixelTransferManager()),
10556 error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
10557 uint32 immediate_data_size, const cmds::AsyncTexImage2DCHROMIUM& c) {
10558 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
10559 GLenum target = static_cast<GLenum>(c.target);
10560 GLint level = static_cast<GLint>(c.level);
10561 GLenum internal_format = static_cast<GLenum>(c.internalformat);
10562 GLsizei width = static_cast<GLsizei>(c.width);
10563 GLsizei height = static_cast<GLsizei>(c.height);
10564 GLint border = static_cast<GLint>(c.border);
10565 GLenum format = static_cast<GLenum>(c.format);
10566 GLenum type = static_cast<GLenum>(c.type);
10567 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
10568 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
10569 uint32 pixels_size;
10570 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
10571 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
10572 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
10574 base::ScopedClosureRunner scoped_completion_callback;
10575 if (async_upload_token) {
10576 base::Closure completion_closure =
10577 AsyncUploadTokenCompletionClosure(async_upload_token,
10579 sync_data_shm_offset);
10580 if (completion_closure.is_null())
10581 return error::kInvalidArguments;
10583 scoped_completion_callback.Reset(completion_closure);
10586 // TODO(epenner): Move this and copies of this memory validation
10587 // into ValidateTexImage2D step.
10588 if (!GLES2Util::ComputeImageDataSizes(
10589 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
10591 return error::kOutOfBounds;
10593 const void* pixels = NULL;
10594 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
10595 pixels = GetSharedMemoryAs<const void*>(
10596 pixels_shm_id, pixels_shm_offset, pixels_size);
10598 return error::kOutOfBounds;
10602 TextureManager::DoTextImage2DArguments args = {
10603 target, level, internal_format, width, height, border, format, type,
10604 pixels, pixels_size};
10605 TextureRef* texture_ref;
10606 // All the normal glTexSubImage2D validation.
10607 if (!texture_manager()->ValidateTexImage2D(
10608 &state_, "glAsyncTexImage2DCHROMIUM", args, &texture_ref)) {
10609 return error::kNoError;
10612 // Extra async validation.
10613 Texture* texture = texture_ref->texture();
10614 if (!ValidateAsyncTransfer(
10615 "glAsyncTexImage2DCHROMIUM", texture_ref, target, level, pixels))
10616 return error::kNoError;
10618 // Don't allow async redefinition of a textures.
10619 if (texture->IsDefined()) {
10620 LOCAL_SET_GL_ERROR(
10621 GL_INVALID_OPERATION,
10622 "glAsyncTexImage2DCHROMIUM", "already defined");
10623 return error::kNoError;
10626 if (!EnsureGPUMemoryAvailable(pixels_size)) {
10627 LOCAL_SET_GL_ERROR(
10628 GL_OUT_OF_MEMORY, "glAsyncTexImage2DCHROMIUM", "out of memory");
10629 return error::kNoError;
10632 // Setup the parameters.
10633 AsyncTexImage2DParams tex_params = {
10634 target, level, static_cast<GLenum>(internal_format),
10635 width, height, border, format, type};
10636 AsyncMemoryParams mem_params(
10637 GetSharedMemoryBuffer(c.pixels_shm_id), c.pixels_shm_offset, pixels_size);
10639 // Set up the async state if needed, and make the texture
10640 // immutable so the async state stays valid. The level info
10641 // is set up lazily when the transfer completes.
10642 AsyncPixelTransferDelegate* delegate =
10643 async_pixel_transfer_manager_->CreatePixelTransferDelegate(texture_ref,
10645 texture->SetImmutable(true);
10647 delegate->AsyncTexImage2D(
10650 base::Bind(&TextureManager::SetLevelInfoFromParams,
10651 // The callback is only invoked if the transfer delegate still
10652 // exists, which implies through manager->texture_ref->state
10653 // ownership that both of these pointers are valid.
10654 base::Unretained(texture_manager()),
10655 base::Unretained(texture_ref),
10657 return error::kNoError;
10660 error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
10661 uint32 immediate_data_size, const cmds::AsyncTexSubImage2DCHROMIUM& c) {
10662 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
10663 GLenum target = static_cast<GLenum>(c.target);
10664 GLint level = static_cast<GLint>(c.level);
10665 GLint xoffset = static_cast<GLint>(c.xoffset);
10666 GLint yoffset = static_cast<GLint>(c.yoffset);
10667 GLsizei width = static_cast<GLsizei>(c.width);
10668 GLsizei height = static_cast<GLsizei>(c.height);
10669 GLenum format = static_cast<GLenum>(c.format);
10670 GLenum type = static_cast<GLenum>(c.type);
10671 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
10672 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
10673 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
10675 base::ScopedClosureRunner scoped_completion_callback;
10676 if (async_upload_token) {
10677 base::Closure completion_closure =
10678 AsyncUploadTokenCompletionClosure(async_upload_token,
10680 sync_data_shm_offset);
10681 if (completion_closure.is_null())
10682 return error::kInvalidArguments;
10684 scoped_completion_callback.Reset(completion_closure);
10687 // TODO(epenner): Move this and copies of this memory validation
10688 // into ValidateTexSubImage2D step.
10690 if (!GLES2Util::ComputeImageDataSizes(
10691 width, height, format, type, state_.unpack_alignment, &data_size,
10693 return error::kOutOfBounds;
10695 const void* pixels = GetSharedMemoryAs<const void*>(
10696 c.data_shm_id, c.data_shm_offset, data_size);
10698 // All the normal glTexSubImage2D validation.
10699 error::Error error = error::kNoError;
10700 if (!ValidateTexSubImage2D(&error, "glAsyncTexSubImage2DCHROMIUM",
10701 target, level, xoffset, yoffset, width, height, format, type, pixels)) {
10705 // Extra async validation.
10706 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10708 Texture* texture = texture_ref->texture();
10709 if (!ValidateAsyncTransfer(
10710 "glAsyncTexSubImage2DCHROMIUM", texture_ref, target, level, pixels))
10711 return error::kNoError;
10713 // Guarantee async textures are always 'cleared' as follows:
10714 // - AsyncTexImage2D can not redefine an existing texture
10715 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
10716 // - AsyncTexSubImage2D clears synchronously if not already cleared.
10717 // - Textures become immutable after an async call.
10718 // This way we know in all cases that an async texture is always clear.
10719 if (!texture->SafeToRenderFrom()) {
10720 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
10722 LOCAL_SET_GL_ERROR(
10724 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
10725 return error::kNoError;
10729 // Setup the parameters.
10730 AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset,
10731 width, height, format, type};
10732 AsyncMemoryParams mem_params(
10733 GetSharedMemoryBuffer(c.data_shm_id), c.data_shm_offset, data_size);
10734 AsyncPixelTransferDelegate* delegate =
10735 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
10737 // TODO(epenner): We may want to enforce exclusive use
10738 // of async APIs in which case this should become an error,
10739 // (the texture should have been async defined).
10740 AsyncTexImage2DParams define_params = {target, level,
10742 texture->GetLevelSize(target, level, &define_params.width,
10743 &define_params.height);
10744 texture->GetLevelType(target, level, &define_params.type,
10745 &define_params.internal_format);
10746 // Set up the async state if needed, and make the texture
10747 // immutable so the async state stays valid.
10748 delegate = async_pixel_transfer_manager_->CreatePixelTransferDelegate(
10749 texture_ref, define_params);
10750 texture->SetImmutable(true);
10753 delegate->AsyncTexSubImage2D(tex_params, mem_params);
10754 return error::kNoError;
10757 error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
10758 uint32 immediate_data_size, const cmds::WaitAsyncTexImage2DCHROMIUM& c) {
10759 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
10760 GLenum target = static_cast<GLenum>(c.target);
10762 if (GL_TEXTURE_2D != target) {
10763 LOCAL_SET_GL_ERROR(
10764 GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target");
10765 return error::kNoError;
10767 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10769 if (!texture_ref) {
10770 LOCAL_SET_GL_ERROR(
10771 GL_INVALID_OPERATION,
10772 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
10773 return error::kNoError;
10775 AsyncPixelTransferDelegate* delegate =
10776 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
10778 LOCAL_SET_GL_ERROR(
10779 GL_INVALID_OPERATION,
10780 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
10781 return error::kNoError;
10783 delegate->WaitForTransferCompletion();
10784 ProcessFinishedAsyncTransfers();
10785 return error::kNoError;
10788 error::Error GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
10789 uint32 immediate_data_size, const cmds::WaitAllAsyncTexImage2DCHROMIUM& c) {
10790 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
10792 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
10793 ProcessFinishedAsyncTransfers();
10794 return error::kNoError;
10797 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
10798 TextureRef* texture_ref) {
10799 Texture* texture = texture_ref->texture();
10800 DoDidUseTexImageIfNeeded(texture, texture->target());
10803 void GLES2DecoderImpl::OnOutOfMemoryError() {
10804 if (lose_context_when_out_of_memory_) {
10805 group_->LoseContexts(GL_UNKNOWN_CONTEXT_RESET_ARB);
10806 LoseContext(GL_GUILTY_CONTEXT_RESET_ARB);
10810 // Include the auto-generated part of this file. We split this because it means
10811 // we can easily edit the non-auto generated parts right here in this file
10812 // instead of having to edit some template or the code generator.
10813 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
10815 } // namespace gles2