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/command_line.h"
19 #include "base/debug/trace_event.h"
20 #include "base/debug/trace_event_synthetic_delay.h"
21 #include "base/memory/scoped_ptr.h"
22 #include "base/strings/string_number_conversions.h"
23 #include "base/strings/string_split.h"
24 #include "build/build_config.h"
25 #define GLES2_GPU_SERVICE 1
26 #include "gpu/command_buffer/common/debug_marker_manager.h"
27 #include "gpu/command_buffer/common/gles2_cmd_format.h"
28 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
29 #include "gpu/command_buffer/common/id_allocator.h"
30 #include "gpu/command_buffer/common/mailbox.h"
31 #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
32 #include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
33 #include "gpu/command_buffer/service/buffer_manager.h"
34 #include "gpu/command_buffer/service/cmd_buffer_engine.h"
35 #include "gpu/command_buffer/service/context_group.h"
36 #include "gpu/command_buffer/service/context_state.h"
37 #include "gpu/command_buffer/service/error_state.h"
38 #include "gpu/command_buffer/service/feature_info.h"
39 #include "gpu/command_buffer/service/framebuffer_manager.h"
40 #include "gpu/command_buffer/service/gl_utils.h"
41 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
42 #include "gpu/command_buffer/service/gles2_cmd_validation.h"
43 #include "gpu/command_buffer/service/gpu_state_tracer.h"
44 #include "gpu/command_buffer/service/gpu_switches.h"
45 #include "gpu/command_buffer/service/gpu_tracer.h"
46 #include "gpu/command_buffer/service/image_manager.h"
47 #include "gpu/command_buffer/service/mailbox_manager.h"
48 #include "gpu/command_buffer/service/memory_tracking.h"
49 #include "gpu/command_buffer/service/program_manager.h"
50 #include "gpu/command_buffer/service/query_manager.h"
51 #include "gpu/command_buffer/service/renderbuffer_manager.h"
52 #include "gpu/command_buffer/service/shader_manager.h"
53 #include "gpu/command_buffer/service/shader_translator.h"
54 #include "gpu/command_buffer/service/shader_translator_cache.h"
55 #include "gpu/command_buffer/service/texture_manager.h"
56 #include "gpu/command_buffer/service/vertex_array_manager.h"
57 #include "gpu/command_buffer/service/vertex_attrib_manager.h"
58 #include "ui/gl/gl_bindings.h"
59 #include "ui/gl/gl_fence.h"
60 #include "ui/gl/gl_image.h"
61 #include "ui/gl/gl_implementation.h"
62 #include "ui/gl/gl_surface.h"
64 #if defined(OS_MACOSX)
65 #include "ui/gl/io_surface_support_mac.h"
69 #include "base/win/win_util.h"
72 // TODO(zmo): we can't include "City.h" due to type def conflicts.
73 extern uint64 CityHash64(const char*, size_t);
80 static const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
81 static const char kEXTFragDepthExtension[] = "GL_EXT_frag_depth";
82 static const char kEXTDrawBuffersExtension[] = "GL_EXT_draw_buffers";
84 #if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
85 khronos_uint64_t CityHashForAngle(const char* name, unsigned int len) {
86 return static_cast<khronos_uint64_t>(
87 CityHash64(name, static_cast<size_t>(len)));
91 static bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin,
94 return (rangeMin >= 62) && (rangeMax >= 62) && (precision >= 16);
97 static void GetShaderPrecisionFormatImpl(GLenum shader_type,
98 GLenum precision_type,
99 GLint *range, GLint *precision) {
100 switch (precision_type) {
104 // These values are for a 32-bit twos-complement integer format.
110 case GL_MEDIUM_FLOAT:
112 // These values are for an IEEE single-precision floating-point format.
122 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
123 gfx::g_driver_gl.fn.glGetShaderPrecisionFormatFn) {
124 // This function is sometimes defined even though it's really just
125 // a stub, so we need to set range and precision as if it weren't
126 // defined before calling it.
127 // On Mac OS with some GPUs, calling this generates a
128 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
130 glGetShaderPrecisionFormat(shader_type, precision_type,
133 // TODO(brianderson): Make the following official workarounds.
135 // Some drivers have bugs where they report the ranges as a negative number.
136 // Taking the absolute value here shouldn't hurt because negative numbers
137 // aren't expected anyway.
138 range[0] = abs(range[0]);
139 range[1] = abs(range[1]);
141 // If the driver reports a precision for highp float that isn't actually
142 // highp, don't pretend like it's supported because shader compilation will
144 if (precision_type == GL_HIGH_FLOAT &&
145 !PrecisionMeetsSpecForHighpFloat(range[0], range[1], *precision)) {
155 class GLES2DecoderImpl;
157 // Local versions of the SET_GL_ERROR macros
158 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
159 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
160 #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
161 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
162 function_name, value, label)
163 #define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
164 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
165 function_name, pname)
166 #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
167 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
169 #define LOCAL_PEEK_GL_ERROR(function_name) \
170 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
171 #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
172 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
173 #define LOCAL_PERFORMANCE_WARNING(msg) \
174 PerformanceWarning(__FILE__, __LINE__, msg)
175 #define LOCAL_RENDER_WARNING(msg) \
176 RenderWarning(__FILE__, __LINE__, msg)
178 // Check that certain assumptions the code makes are true. There are places in
179 // the code where shared memory is passed direclty to GL. Example, glUniformiv,
180 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
181 // a few others) are 32bits. If they are not 32bits the code will have to change
182 // to call those GL functions with service side memory and then copy the results
183 // to shared memory, converting the sizes.
184 COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
185 GLint_not_same_size_as_uint32);
186 COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
187 GLint_not_same_size_as_uint32);
188 COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
189 GLfloat_not_same_size_as_float);
191 // TODO(kbr): the use of this anonymous namespace core dumps the
192 // linker on Mac OS X 10.6 when the symbol ordering file is used
195 // Returns the address of the first byte after a struct.
196 template <typename T>
197 const void* AddressAfterStruct(const T& pod) {
198 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
201 // Returns the address of the frst byte after the struct or NULL if size >
202 // immediate_data_size.
203 template <typename RETURN_TYPE, typename COMMAND_TYPE>
204 RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
206 uint32 immediate_data_size) {
207 return (size <= immediate_data_size) ?
208 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
212 // Computes the data size for certain gl commands like glUniform.
213 bool ComputeDataSize(
216 unsigned int elements_per_unit,
219 if (!SafeMultiplyUint32(count, size, &value)) {
222 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
229 // A struct to hold info about each command.
231 uint8 arg_flags; // How to handle the arguments for this command
232 uint8 cmd_flags; // How to handle this command
233 uint16 arg_count; // How many arguments are expected for this command.
236 // cmds::name::cmd_flags,
237 // A table of CommandInfo for all the commands.
238 const CommandInfo g_command_info[] = {
239 #define GLES2_CMD_OP(name) { \
240 cmds::name::kArgFlags, \
241 cmds::name::cmd_flags, \
242 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */
244 GLES2_COMMAND_LIST(GLES2_CMD_OP)
249 // Return true if a character belongs to the ASCII subset as defined in
250 // GLSL ES 1.0 spec section 3.1.
251 static bool CharacterIsValidForGLES(unsigned char c) {
252 // Printing characters are valid except " $ ` @ \ ' DEL.
253 if (c >= 32 && c <= 126 &&
262 // Horizontal tab, line feed, vertical tab, form feed, carriage return
264 if (c >= 9 && c <= 13) {
271 static bool StringIsValidForGLES(const char* str) {
272 for (; *str; ++str) {
273 if (!CharacterIsValidForGLES(*str)) {
280 // Wrapper for glEnable/glDisable that doesn't suck.
281 static void EnableDisable(GLenum pname, bool enable) {
289 // This class prevents any GL errors that occur when it is in scope from
290 // being reported to the client.
291 class ScopedGLErrorSuppressor {
293 explicit ScopedGLErrorSuppressor(
294 const char* function_name, ErrorState* error_state);
295 ~ScopedGLErrorSuppressor();
297 const char* function_name_;
298 ErrorState* error_state_;
299 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
302 // Temporarily changes a decoder's bound texture and restore it when this
303 // object goes out of scope. Also temporarily switches to using active texture
304 // unit zero in case the client has changed that to something invalid.
305 class ScopedTextureBinder {
307 explicit ScopedTextureBinder(ContextState* state, GLuint id, GLenum target);
308 ~ScopedTextureBinder();
311 ContextState* state_;
313 DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder);
316 // Temporarily changes a decoder's bound render buffer and restore it when this
317 // object goes out of scope.
318 class ScopedRenderBufferBinder {
320 explicit ScopedRenderBufferBinder(ContextState* state, GLuint id);
321 ~ScopedRenderBufferBinder();
324 ContextState* state_;
325 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
328 // Temporarily changes a decoder's bound frame buffer and restore it when this
329 // object goes out of scope.
330 class ScopedFrameBufferBinder {
332 explicit ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
333 ~ScopedFrameBufferBinder();
336 GLES2DecoderImpl* decoder_;
337 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
340 // Temporarily changes a decoder's bound frame buffer to a resolved version of
341 // the multisampled offscreen render buffer if that buffer is multisampled, and,
342 // if it is bound or enforce_internal_framebuffer is true. If internal is
343 // true, the resolved framebuffer is not visible to the parent.
344 class ScopedResolvedFrameBufferBinder {
346 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
347 bool enforce_internal_framebuffer,
349 ~ScopedResolvedFrameBufferBinder();
352 GLES2DecoderImpl* decoder_;
353 bool resolve_and_bind_;
354 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
357 class ScopedModifyPixels {
359 explicit ScopedModifyPixels(TextureRef* ref);
360 ~ScopedModifyPixels();
366 ScopedModifyPixels::ScopedModifyPixels(TextureRef* ref) : ref_(ref) {
368 ref_->texture()->OnWillModifyPixels();
371 ScopedModifyPixels::~ScopedModifyPixels() {
373 ref_->texture()->OnDidModifyPixels();
376 class ScopedRenderTo {
378 explicit ScopedRenderTo(Framebuffer* framebuffer);
382 const Framebuffer* framebuffer_;
385 ScopedRenderTo::ScopedRenderTo(Framebuffer* framebuffer)
386 : framebuffer_(framebuffer) {
388 framebuffer_->OnWillRenderTo();
391 ScopedRenderTo::~ScopedRenderTo() {
393 framebuffer_->OnDidRenderTo();
396 // Encapsulates an OpenGL texture.
399 explicit BackTexture(MemoryTracker* memory_tracker, ContextState* state);
402 // Create a new render texture.
405 // Set the initial size and format of a render texture or resize it.
406 bool AllocateStorage(const gfx::Size& size, GLenum format, bool zero);
408 // Copy the contents of the currently bound frame buffer.
409 void Copy(const gfx::Size& size, GLenum format);
411 // Destroy the render texture. This must be explicitly called before
412 // destroying this object.
415 // Invalidate the texture. This can be used when a context is lost and it is
416 // not possible to make it current in order to free the resource.
423 gfx::Size size() const {
428 MemoryTypeTracker memory_tracker_;
429 ContextState* state_;
430 size_t bytes_allocated_;
433 DISALLOW_COPY_AND_ASSIGN(BackTexture);
436 // Encapsulates an OpenGL render buffer of any format.
437 class BackRenderbuffer {
439 explicit BackRenderbuffer(
440 RenderbufferManager* renderbuffer_manager,
441 MemoryTracker* memory_tracker,
442 ContextState* state);
445 // Create a new render buffer.
448 // Set the initial size and format of a render buffer or resize it.
449 bool AllocateStorage(const FeatureInfo* feature_info,
450 const gfx::Size& size,
454 // Destroy the render buffer. This must be explicitly called before destroying
458 // Invalidate the render buffer. This can be used when a context is lost and
459 // it is not possible to make it current in order to free the resource.
467 RenderbufferManager* renderbuffer_manager_;
468 MemoryTypeTracker memory_tracker_;
469 ContextState* state_;
470 size_t bytes_allocated_;
472 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer);
475 // Encapsulates an OpenGL frame buffer.
476 class BackFramebuffer {
478 explicit BackFramebuffer(GLES2DecoderImpl* decoder);
481 // Create a new frame buffer.
484 // Attach a color render buffer to a frame buffer.
485 void AttachRenderTexture(BackTexture* texture);
487 // Attach a render buffer to a frame buffer. Note that this unbinds any
488 // currently bound frame buffer.
489 void AttachRenderBuffer(GLenum target, BackRenderbuffer* render_buffer);
491 // Destroy the frame buffer. This must be explicitly called before destroying
495 // Invalidate the frame buffer. This can be used when a context is lost and it
496 // is not possible to make it current in order to free the resource.
499 // See glCheckFramebufferStatusEXT.
500 GLenum CheckStatus();
507 GLES2DecoderImpl* decoder_;
509 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer);
512 struct FenceCallback {
513 explicit FenceCallback()
514 : fence(gfx::GLFence::Create()) {
517 std::vector<base::Closure> callbacks;
518 scoped_ptr<gfx::GLFence> fence;
521 // } // anonymous namespace.
523 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
524 uint32* service_texture_id) {
528 GLES2Decoder::GLES2Decoder()
529 : initialized_(false),
531 log_commands_(false) {
534 GLES2Decoder::~GLES2Decoder() {
537 void GLES2Decoder::BeginDecoding() {}
539 void GLES2Decoder::EndDecoding() {}
541 // This class implements GLES2Decoder so we don't have to expose all the GLES2
542 // cmd stuff to outside this class.
543 class GLES2DecoderImpl : public GLES2Decoder,
544 public FramebufferManager::TextureDetachObserver,
545 public ErrorStateClient {
547 explicit GLES2DecoderImpl(ContextGroup* group);
548 virtual ~GLES2DecoderImpl();
550 // Overridden from AsyncAPIInterface.
551 virtual Error DoCommand(unsigned int command,
552 unsigned int arg_count,
553 const void* args) OVERRIDE;
555 // Overridden from AsyncAPIInterface.
556 virtual const char* GetCommandName(unsigned int command_id) const OVERRIDE;
558 // Overridden from GLES2Decoder.
559 virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
560 const scoped_refptr<gfx::GLContext>& context,
562 const gfx::Size& size,
563 const DisallowedFeatures& disallowed_features,
564 const std::vector<int32>& attribs) OVERRIDE;
565 virtual void Destroy(bool have_context) OVERRIDE;
566 virtual void SetSurface(
567 const scoped_refptr<gfx::GLSurface>& surface) OVERRIDE;
568 virtual void ProduceFrontBuffer(const Mailbox& mailbox) OVERRIDE;
569 virtual bool ResizeOffscreenFrameBuffer(const gfx::Size& size) OVERRIDE;
570 void UpdateParentTextureInfo();
571 virtual bool MakeCurrent() OVERRIDE;
572 virtual GLES2Util* GetGLES2Util() OVERRIDE { return &util_; }
573 virtual gfx::GLContext* GetGLContext() OVERRIDE { return context_.get(); }
574 virtual ContextGroup* GetContextGroup() OVERRIDE { return group_.get(); }
575 virtual Capabilities GetCapabilities() OVERRIDE;
576 virtual void RestoreState(const ContextState* prev_state) const OVERRIDE;
578 virtual void RestoreActiveTexture() const OVERRIDE {
579 state_.RestoreActiveTexture();
581 virtual void RestoreAllTextureUnitBindings(
582 const ContextState* prev_state) const OVERRIDE {
583 state_.RestoreAllTextureUnitBindings(prev_state);
585 virtual void RestoreActiveTextureUnitBinding(
586 unsigned int target) const OVERRIDE {
587 state_.RestoreActiveTextureUnitBinding(target);
589 virtual void RestoreAttribute(unsigned index) const OVERRIDE {
590 state_.RestoreAttribute(index);
592 virtual void RestoreBufferBindings() const OVERRIDE {
593 state_.RestoreBufferBindings();
595 virtual void RestoreGlobalState() const OVERRIDE {
596 state_.RestoreGlobalState();
598 virtual void RestoreProgramBindings() const OVERRIDE {
599 state_.RestoreProgramBindings();
601 virtual void RestoreTextureUnitBindings(unsigned unit) const OVERRIDE {
602 state_.RestoreTextureUnitBindings(unit, NULL);
604 virtual void RestoreFramebufferBindings() const OVERRIDE;
605 virtual void RestoreTextureState(unsigned service_id) const OVERRIDE;
607 virtual void ClearAllAttributes() const OVERRIDE;
608 virtual void RestoreAllAttributes() const OVERRIDE;
610 virtual QueryManager* GetQueryManager() OVERRIDE {
611 return query_manager_.get();
613 virtual VertexArrayManager* GetVertexArrayManager() OVERRIDE {
614 return vertex_array_manager_.get();
616 virtual bool ProcessPendingQueries() OVERRIDE;
617 virtual bool HasMoreIdleWork() OVERRIDE;
618 virtual void PerformIdleWork() OVERRIDE;
620 virtual void WaitForReadPixels(base::Closure callback) OVERRIDE;
622 virtual void SetResizeCallback(
623 const base::Callback<void(gfx::Size, float)>& callback) OVERRIDE;
625 virtual Logger* GetLogger() OVERRIDE;
627 virtual void BeginDecoding() OVERRIDE;
628 virtual void EndDecoding() OVERRIDE;
630 virtual ErrorState* GetErrorState() OVERRIDE;
631 virtual const ContextState* GetContextState() OVERRIDE { return &state_; }
633 virtual void SetShaderCacheCallback(
634 const ShaderCacheCallback& callback) OVERRIDE;
635 virtual void SetWaitSyncPointCallback(
636 const WaitSyncPointCallback& callback) OVERRIDE;
638 virtual AsyncPixelTransferManager*
639 GetAsyncPixelTransferManager() OVERRIDE;
640 virtual void ResetAsyncPixelTransferManagerForTest() OVERRIDE;
641 virtual void SetAsyncPixelTransferManagerForTest(
642 AsyncPixelTransferManager* manager) OVERRIDE;
643 void ProcessFinishedAsyncTransfers();
645 virtual bool GetServiceTextureId(uint32 client_texture_id,
646 uint32* service_texture_id) OVERRIDE;
648 virtual uint32 GetTextureUploadCount() OVERRIDE;
649 virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE;
650 virtual base::TimeDelta GetTotalProcessingCommandsTime() OVERRIDE;
651 virtual void AddProcessingCommandsTime(base::TimeDelta) OVERRIDE;
653 // Restores the current state to the user's settings.
654 void RestoreCurrentFramebufferBindings();
656 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
657 void ApplyDirtyState();
659 // These check the state of the currently bound framebuffer or the
660 // backbuffer if no framebuffer is bound.
661 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
662 // check with all attached and enabled color attachments.
663 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers);
664 bool BoundFramebufferHasDepthAttachment();
665 bool BoundFramebufferHasStencilAttachment();
667 virtual error::ContextLostReason GetContextLostReason() OVERRIDE;
669 // Overridden from FramebufferManager::TextureDetachObserver:
670 virtual void OnTextureRefDetachedFromFramebuffer(
671 TextureRef* texture) OVERRIDE;
673 // Overriden from ErrorStateClient.
674 virtual void OnOutOfMemoryError() OVERRIDE;
676 // Helpers to facilitate calling into compatible extensions.
677 static void RenderbufferStorageMultisampleHelper(
678 const FeatureInfo* feature_info,
681 GLenum internal_format,
685 void BlitFramebufferHelper(GLint srcX0,
697 friend class ScopedFrameBufferBinder;
698 friend class ScopedResolvedFrameBufferBinder;
699 friend class BackFramebuffer;
701 // Initialize or re-initialize the shader translator.
702 bool InitializeShaderTranslator();
704 void UpdateCapabilities();
706 // Helpers for the glGen and glDelete functions.
707 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
708 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
709 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
710 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
711 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
712 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
713 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
714 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
715 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
716 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
717 bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
718 void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
721 void OnFboChanged() const;
722 void OnUseFramebuffer() const;
724 // TODO(gman): Cache these pointers?
725 BufferManager* buffer_manager() {
726 return group_->buffer_manager();
729 RenderbufferManager* renderbuffer_manager() {
730 return group_->renderbuffer_manager();
733 FramebufferManager* framebuffer_manager() {
734 return group_->framebuffer_manager();
737 ProgramManager* program_manager() {
738 return group_->program_manager();
741 ShaderManager* shader_manager() {
742 return group_->shader_manager();
745 const TextureManager* texture_manager() const {
746 return group_->texture_manager();
749 TextureManager* texture_manager() {
750 return group_->texture_manager();
753 MailboxManager* mailbox_manager() {
754 return group_->mailbox_manager();
757 ImageManager* image_manager() {
758 return group_->image_manager();
761 VertexArrayManager* vertex_array_manager() {
762 return vertex_array_manager_.get();
765 MemoryTracker* memory_tracker() {
766 return group_->memory_tracker();
769 bool EnsureGPUMemoryAvailable(size_t estimated_size) {
770 MemoryTracker* tracker = memory_tracker();
772 return tracker->EnsureGPUMemoryAvailable(estimated_size);
777 bool IsOffscreenBufferMultisampled() const {
778 return offscreen_target_samples_ > 1;
781 // Creates a Texture for the given texture.
782 TextureRef* CreateTexture(
783 GLuint client_id, GLuint service_id) {
784 return texture_manager()->CreateTexture(client_id, service_id);
787 // Gets the texture info for the given texture. Returns NULL if none exists.
788 TextureRef* GetTexture(GLuint client_id) const {
789 return texture_manager()->GetTexture(client_id);
792 // Deletes the texture info for the given texture.
793 void RemoveTexture(GLuint client_id) {
794 texture_manager()->RemoveTexture(client_id);
797 // Get the size (in pixels) of the currently bound frame buffer (either FBO
798 // or regular back buffer).
799 gfx::Size GetBoundReadFrameBufferSize();
801 // Get the format of the currently bound frame buffer (either FBO or regular
803 GLenum GetBoundReadFrameBufferTextureType();
804 GLenum GetBoundReadFrameBufferInternalFormat();
805 GLenum GetBoundDrawFrameBufferInternalFormat();
807 // Wrapper for CompressedTexImage2D commands.
808 error::Error DoCompressedTexImage2D(
811 GLenum internal_format,
818 // Wrapper for CompressedTexSubImage2D.
819 void DoCompressedTexSubImage2D(
830 // Wrapper for CopyTexImage2D.
831 void DoCopyTexImage2D(
834 GLenum internal_format,
841 // Wrapper for SwapBuffers.
842 void DoSwapBuffers();
844 // Wrapper for CopyTexSubImage2D.
845 void DoCopyTexSubImage2D(
855 // Validation for TexSubImage2D.
856 bool ValidateTexSubImage2D(
858 const char* function_name,
869 // Wrapper for TexSubImage2D.
870 error::Error DoTexSubImage2D(
881 // Extra validation for async tex(Sub)Image2D.
882 bool ValidateAsyncTransfer(
883 const char* function_name,
884 TextureRef* texture_ref,
889 // Wrapper for TexImageIOSurface2DCHROMIUM.
890 void DoTexImageIOSurface2DCHROMIUM(
894 GLuint io_surface_id,
897 void DoCopyTextureCHROMIUM(
902 GLenum internal_format,
905 // Wrapper for TexStorage2DEXT.
906 void DoTexStorage2DEXT(
909 GLenum internal_format,
913 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
914 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
916 void DoBindTexImage2DCHROMIUM(
919 void DoReleaseTexImage2DCHROMIUM(
923 void DoTraceEndCHROMIUM(void);
925 void DoDrawBuffersEXT(GLsizei count, const GLenum* bufs);
927 // Creates a Program for the given program.
928 Program* CreateProgram(
929 GLuint client_id, GLuint service_id) {
930 return program_manager()->CreateProgram(client_id, service_id);
933 // Gets the program info for the given program. Returns NULL if none exists.
934 Program* GetProgram(GLuint client_id) {
935 return program_manager()->GetProgram(client_id);
939 void LogClientServiceMapping(
940 const char* /* function_name */,
941 GLuint /* client_id */,
942 GLuint /* service_id */) {
945 void LogClientServiceForInfo(
946 T* /* info */, GLuint /* client_id */, const char* /* function_name */) {
949 void LogClientServiceMapping(
950 const char* function_name, GLuint client_id, GLuint service_id) {
951 if (service_logging_) {
952 VLOG(1) << "[" << logger_.GetLogPrefix() << "] " << function_name
953 << ": client_id = " << client_id
954 << ", service_id = " << service_id;
958 void LogClientServiceForInfo(
959 T* info, GLuint client_id, const char* function_name) {
961 LogClientServiceMapping(function_name, client_id, info->service_id());
966 // Gets the program info for the given program. If it's not a program
967 // generates a GL error. Returns NULL if not program.
968 Program* GetProgramInfoNotShader(
969 GLuint client_id, const char* function_name) {
970 Program* program = GetProgram(client_id);
972 if (GetShader(client_id)) {
974 GL_INVALID_OPERATION, function_name, "shader passed for program");
976 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown program");
979 LogClientServiceForInfo(program, client_id, function_name);
984 // Creates a Shader for the given shader.
985 Shader* CreateShader(
988 GLenum shader_type) {
989 return shader_manager()->CreateShader(
990 client_id, service_id, shader_type);
993 // Gets the shader info for the given shader. Returns NULL if none exists.
994 Shader* GetShader(GLuint client_id) {
995 return shader_manager()->GetShader(client_id);
998 // Gets the shader info for the given shader. If it's not a shader generates a
999 // GL error. Returns NULL if not shader.
1000 Shader* GetShaderInfoNotProgram(
1001 GLuint client_id, const char* function_name) {
1002 Shader* shader = GetShader(client_id);
1004 if (GetProgram(client_id)) {
1006 GL_INVALID_OPERATION, function_name, "program passed for shader");
1009 GL_INVALID_VALUE, function_name, "unknown shader");
1012 LogClientServiceForInfo(shader, client_id, function_name);
1016 // Creates a buffer info for the given buffer.
1017 void CreateBuffer(GLuint client_id, GLuint service_id) {
1018 return buffer_manager()->CreateBuffer(client_id, service_id);
1021 // Gets the buffer info for the given buffer.
1022 Buffer* GetBuffer(GLuint client_id) {
1023 Buffer* buffer = buffer_manager()->GetBuffer(client_id);
1027 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1028 // on glDeleteBuffers so we can make sure the user does not try to render
1029 // with deleted buffers.
1030 void RemoveBuffer(GLuint client_id);
1032 // Creates a framebuffer info for the given framebuffer.
1033 void CreateFramebuffer(GLuint client_id, GLuint service_id) {
1034 return framebuffer_manager()->CreateFramebuffer(client_id, service_id);
1037 // Gets the framebuffer info for the given framebuffer.
1038 Framebuffer* GetFramebuffer(GLuint client_id) {
1039 return framebuffer_manager()->GetFramebuffer(client_id);
1042 // Removes the framebuffer info for the given framebuffer.
1043 void RemoveFramebuffer(GLuint client_id) {
1044 framebuffer_manager()->RemoveFramebuffer(client_id);
1047 // Creates a renderbuffer info for the given renderbuffer.
1048 void CreateRenderbuffer(GLuint client_id, GLuint service_id) {
1049 return renderbuffer_manager()->CreateRenderbuffer(
1050 client_id, service_id);
1053 // Gets the renderbuffer info for the given renderbuffer.
1054 Renderbuffer* GetRenderbuffer(GLuint client_id) {
1055 return renderbuffer_manager()->GetRenderbuffer(client_id);
1058 // Removes the renderbuffer info for the given renderbuffer.
1059 void RemoveRenderbuffer(GLuint client_id) {
1060 renderbuffer_manager()->RemoveRenderbuffer(client_id);
1063 // Gets the vertex attrib manager for the given vertex array.
1064 VertexAttribManager* GetVertexAttribManager(GLuint client_id) {
1065 VertexAttribManager* info =
1066 vertex_array_manager()->GetVertexAttribManager(client_id);
1070 // Removes the vertex attrib manager for the given vertex array.
1071 void RemoveVertexAttribManager(GLuint client_id) {
1072 vertex_array_manager()->RemoveVertexAttribManager(client_id);
1075 // Creates a vertex attrib manager for the given vertex array.
1076 void CreateVertexAttribManager(GLuint client_id, GLuint service_id) {
1077 return vertex_array_manager()->CreateVertexAttribManager(
1078 client_id, service_id, group_->max_vertex_attribs());
1081 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
1082 void DoBindUniformLocationCHROMIUM(
1083 GLuint client_id, GLint location, const char* name);
1085 error::Error GetAttribLocationHelper(
1086 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1087 const std::string& name_str);
1089 error::Error GetUniformLocationHelper(
1090 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1091 const std::string& name_str);
1093 // Helper for glShaderSource.
1094 error::Error ShaderSourceHelper(
1095 GLuint client_id, const char* data, uint32 data_size);
1097 // Clear any textures used by the current program.
1098 bool ClearUnclearedTextures();
1100 // Clears any uncleared attachments attached to the given frame buffer.
1101 // Returns false if there was a generated GL error.
1102 void ClearUnclearedAttachments(GLenum target, Framebuffer* framebuffer);
1104 // overridden from GLES2Decoder
1105 virtual bool ClearLevel(unsigned service_id,
1106 unsigned bind_target,
1109 unsigned internal_format,
1114 bool is_texture_immutable) OVERRIDE;
1116 // Restore all GL state that affects clearing.
1117 void RestoreClearState();
1119 // Remembers the state of some capabilities.
1120 // Returns: true if glEnable/glDisable should actually be called.
1121 bool SetCapabilityState(GLenum cap, bool enabled);
1123 // Check that the currently bound framebuffers are valid.
1124 // Generates GL error if not.
1125 bool CheckBoundFramebuffersValid(const char* func_name);
1127 // Check if a framebuffer meets our requirements.
1128 bool CheckFramebufferValid(
1129 Framebuffer* framebuffer,
1131 const char* func_name);
1133 // Checks if the current program exists and is valid. If not generates the
1134 // appropriate GL error. Returns true if the current program is in a usable
1136 bool CheckCurrentProgram(const char* function_name);
1138 // Checks if the current program exists and is valid and that location is not
1139 // -1. If the current program is not valid generates the appropriate GL
1140 // error. Returns true if the current program is in a usable state and
1141 // location is not -1.
1142 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1144 // Gets the type of a uniform for a location in the current program. Sets GL
1145 // errors if the current program is not valid. Returns true if the current
1146 // program is valid and the location exists. Adjusts count so it
1147 // does not overflow the uniform.
1148 bool PrepForSetUniformByLocation(GLint fake_location,
1149 const char* function_name,
1150 Program::UniformApiType api_type,
1151 GLint* real_location,
1155 // Gets the service id for any simulated backbuffer fbo.
1156 GLuint GetBackbufferServiceId() const;
1158 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1159 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1161 // Helper for glGetVertexAttrib
1162 void GetVertexAttribHelper(
1163 const VertexAttrib* attrib, GLenum pname, GLint* param);
1165 // Wrapper for glCreateProgram
1166 bool CreateProgramHelper(GLuint client_id);
1168 // Wrapper for glCreateShader
1169 bool CreateShaderHelper(GLenum type, GLuint client_id);
1171 // Wrapper for glActiveTexture
1172 void DoActiveTexture(GLenum texture_unit);
1174 // Wrapper for glAttachShader
1175 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1177 // Wrapper for glBindBuffer since we need to track the current targets.
1178 void DoBindBuffer(GLenum target, GLuint buffer);
1180 // Wrapper for glBindFramebuffer since we need to track the current targets.
1181 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1183 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1184 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1186 // Wrapper for glBindTexture since we need to track the current targets.
1187 void DoBindTexture(GLenum target, GLuint texture);
1189 // Wrapper for glBindVertexArrayOES
1190 void DoBindVertexArrayOES(GLuint array);
1191 void EmulateVertexArrayState();
1193 // Wrapper for glBlitFramebufferCHROMIUM.
1194 void DoBlitFramebufferCHROMIUM(
1195 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1196 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1197 GLbitfield mask, GLenum filter);
1199 // Wrapper for glBufferSubData.
1200 void DoBufferSubData(
1201 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1203 // Wrapper for glCheckFramebufferStatus
1204 GLenum DoCheckFramebufferStatus(GLenum target);
1206 // Wrapper for glClear
1207 error::Error DoClear(GLbitfield mask);
1209 // Wrappers for various state.
1210 void DoDepthRangef(GLclampf znear, GLclampf zfar);
1211 void DoSampleCoverage(GLclampf value, GLboolean invert);
1213 // Wrapper for glCompileShader.
1214 void DoCompileShader(GLuint shader);
1216 // Helper for DeleteSharedIdsCHROMIUM commands.
1217 void DoDeleteSharedIdsCHROMIUM(
1218 GLuint namespace_id, GLsizei n, const GLuint* ids);
1220 // Wrapper for glDetachShader
1221 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1223 // Wrapper for glDisable
1224 void DoDisable(GLenum cap);
1226 // Wrapper for glDisableVertexAttribArray.
1227 void DoDisableVertexAttribArray(GLuint index);
1229 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1231 void DoDiscardFramebufferEXT(GLenum target,
1232 GLsizei numAttachments,
1233 const GLenum* attachments);
1235 // Wrapper for glEnable
1236 void DoEnable(GLenum cap);
1238 // Wrapper for glEnableVertexAttribArray.
1239 void DoEnableVertexAttribArray(GLuint index);
1241 // Wrapper for glFinish.
1244 // Wrapper for glFlush.
1247 // Wrapper for glFramebufferRenderbufffer.
1248 void DoFramebufferRenderbuffer(
1249 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1250 GLuint renderbuffer);
1252 // Wrapper for glFramebufferTexture2D.
1253 void DoFramebufferTexture2D(
1254 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1257 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1258 void DoFramebufferTexture2DMultisample(
1259 GLenum target, GLenum attachment, GLenum textarget,
1260 GLuint texture, GLint level, GLsizei samples);
1262 // Common implementation for both DoFramebufferTexture2D wrappers.
1263 void DoFramebufferTexture2DCommon(const char* name,
1264 GLenum target, GLenum attachment, GLenum textarget,
1265 GLuint texture, GLint level, GLsizei samples);
1267 // Wrapper for glGenerateMipmap
1268 void DoGenerateMipmap(GLenum target);
1270 // Helper for GenSharedIdsCHROMIUM commands.
1271 void DoGenSharedIdsCHROMIUM(
1272 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
1274 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1275 // to account for different pname values defined in different extension
1277 GLenum AdjustGetPname(GLenum pname);
1279 // Wrapper for DoGetBooleanv.
1280 void DoGetBooleanv(GLenum pname, GLboolean* params);
1282 // Wrapper for DoGetFloatv.
1283 void DoGetFloatv(GLenum pname, GLfloat* params);
1285 // Wrapper for glGetFramebufferAttachmentParameteriv.
1286 void DoGetFramebufferAttachmentParameteriv(
1287 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1289 // Wrapper for glGetIntegerv.
1290 void DoGetIntegerv(GLenum pname, GLint* params);
1292 // Gets the max value in a range in a buffer.
1293 GLuint DoGetMaxValueInBufferCHROMIUM(
1294 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1296 // Wrapper for glGetBufferParameteriv.
1297 void DoGetBufferParameteriv(
1298 GLenum target, GLenum pname, GLint* params);
1300 // Wrapper for glGetProgramiv.
1301 void DoGetProgramiv(
1302 GLuint program_id, GLenum pname, GLint* params);
1304 // Wrapper for glRenderbufferParameteriv.
1305 void DoGetRenderbufferParameteriv(
1306 GLenum target, GLenum pname, GLint* params);
1308 // Wrapper for glGetShaderiv
1309 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1311 // Wrappers for glGetTexParameter.
1312 void DoGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params);
1313 void DoGetTexParameteriv(GLenum target, GLenum pname, GLint* params);
1314 void InitTextureMaxAnisotropyIfNeeded(GLenum target, GLenum pname);
1316 // Wrappers for glGetVertexAttrib.
1317 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1318 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1320 // Wrappers for glIsXXX functions.
1321 bool DoIsEnabled(GLenum cap);
1322 bool DoIsBuffer(GLuint client_id);
1323 bool DoIsFramebuffer(GLuint client_id);
1324 bool DoIsProgram(GLuint client_id);
1325 bool DoIsRenderbuffer(GLuint client_id);
1326 bool DoIsShader(GLuint client_id);
1327 bool DoIsTexture(GLuint client_id);
1328 bool DoIsVertexArrayOES(GLuint client_id);
1330 // Wrapper for glLinkProgram
1331 void DoLinkProgram(GLuint program);
1333 // Helper for RegisterSharedIdsCHROMIUM.
1334 void DoRegisterSharedIdsCHROMIUM(
1335 GLuint namespace_id, GLsizei n, const GLuint* ids);
1337 // Wrapper for glRenderbufferStorage.
1338 void DoRenderbufferStorage(
1339 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
1341 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1342 void DoRenderbufferStorageMultisampleCHROMIUM(
1343 GLenum target, GLsizei samples, GLenum internalformat,
1344 GLsizei width, GLsizei height);
1346 // Handler for glRenderbufferStorageMultisampleEXT
1347 // (multisampled_render_to_texture).
1348 void DoRenderbufferStorageMultisampleEXT(
1349 GLenum target, GLsizei samples, GLenum internalformat,
1350 GLsizei width, GLsizei height);
1352 // Common validation for multisample extensions.
1353 bool ValidateRenderbufferStorageMultisample(GLsizei samples,
1354 GLenum internalformat,
1358 // Verifies that the currently bound multisample renderbuffer is valid
1359 // Very slow! Only done on platforms with driver bugs that return invalid
1360 // buffers under memory pressure
1361 bool VerifyMultisampleRenderbufferIntegrity(
1362 GLuint renderbuffer, GLenum format);
1364 // Wrapper for glReleaseShaderCompiler.
1365 void DoReleaseShaderCompiler() { }
1367 // Wrappers for glTexParameter functions.
1368 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1369 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1370 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1371 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1373 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1374 // spec only these 2 functions can be used to set sampler uniforms.
1375 void DoUniform1i(GLint fake_location, GLint v0);
1376 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1377 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1378 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1379 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
1381 // Wrappers for glUniformfv because some drivers don't correctly accept
1383 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1384 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1385 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1386 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
1388 void DoUniformMatrix2fv(
1389 GLint fake_location, GLsizei count, GLboolean transpose,
1390 const GLfloat* value);
1391 void DoUniformMatrix3fv(
1392 GLint fake_location, GLsizei count, GLboolean transpose,
1393 const GLfloat* value);
1394 void DoUniformMatrix4fv(
1395 GLint fake_location, GLsizei count, GLboolean transpose,
1396 const GLfloat* value);
1398 bool SetVertexAttribValue(
1399 const char* function_name, GLuint index, const GLfloat* value);
1401 // Wrappers for glVertexAttrib??
1402 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1403 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1404 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1405 void DoVertexAttrib4f(
1406 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1407 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1408 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1409 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1410 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1412 // Wrapper for glViewport
1413 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1415 // Wrapper for glUseProgram
1416 void DoUseProgram(GLuint program);
1418 // Wrapper for glValidateProgram.
1419 void DoValidateProgram(GLuint program_client_id);
1421 void DoInsertEventMarkerEXT(GLsizei length, const GLchar* marker);
1422 void DoPushGroupMarkerEXT(GLsizei length, const GLchar* group);
1423 void DoPopGroupMarkerEXT(void);
1425 // Gets the number of values that will be returned by glGetXXX. Returns
1426 // false if pname is unknown.
1427 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1429 // Checks if the current program and vertex attributes are valid for drawing.
1431 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount);
1433 // Returns true if successful, simulated will be true if attrib0 was
1435 bool SimulateAttrib0(
1436 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
1437 void RestoreStateForAttrib(GLuint attrib);
1439 // If an image is bound to texture, this will call Will/DidUseTexImage
1441 void DoWillUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1442 void DoDidUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1444 // Returns false if textures were replaced.
1445 bool PrepareTexturesForRender();
1446 void RestoreStateForTextures();
1448 // Returns true if GL_FIXED attribs were simulated.
1449 bool SimulateFixedAttribs(
1450 const char* function_name,
1451 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
1452 void RestoreStateForSimulatedFixedAttribs();
1454 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1455 // cases (primcount is 0 for non-instanced).
1456 error::Error DoDrawArrays(
1457 const char* function_name,
1458 bool instanced, GLenum mode, GLint first, GLsizei count,
1460 error::Error DoDrawElements(
1461 const char* function_name,
1462 bool instanced, GLenum mode, GLsizei count, GLenum type,
1463 int32 offset, GLsizei primcount);
1465 GLenum GetBindTargetForSamplerType(GLenum type) {
1466 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
1467 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1470 return GL_TEXTURE_2D;
1471 case GL_SAMPLER_CUBE:
1472 return GL_TEXTURE_CUBE_MAP;
1473 case GL_SAMPLER_EXTERNAL_OES:
1474 return GL_TEXTURE_EXTERNAL_OES;
1475 case GL_SAMPLER_2D_RECT_ARB:
1476 return GL_TEXTURE_RECTANGLE_ARB;
1483 // Gets the framebuffer info for a particular target.
1484 Framebuffer* GetFramebufferInfoForTarget(GLenum target) {
1485 Framebuffer* framebuffer = NULL;
1487 case GL_FRAMEBUFFER:
1488 case GL_DRAW_FRAMEBUFFER_EXT:
1489 framebuffer = framebuffer_state_.bound_draw_framebuffer.get();
1491 case GL_READ_FRAMEBUFFER_EXT:
1492 framebuffer = framebuffer_state_.bound_read_framebuffer.get();
1501 Renderbuffer* GetRenderbufferInfoForTarget(
1503 Renderbuffer* renderbuffer = NULL;
1505 case GL_RENDERBUFFER:
1506 renderbuffer = state_.bound_renderbuffer.get();
1512 return renderbuffer;
1515 // Validates the program and location for a glGetUniform call and returns
1516 // a SizeResult setup to receive the result. Returns true if glGetUniform
1517 // should be called.
1518 bool GetUniformSetup(
1519 GLuint program, GLint fake_location,
1520 uint32 shm_id, uint32 shm_offset,
1521 error::Error* error, GLint* real_location, GLuint* service_id,
1522 void** result, GLenum* result_type);
1524 virtual bool WasContextLost() OVERRIDE;
1525 virtual bool WasContextLostByRobustnessExtension() OVERRIDE;
1526 virtual void LoseContext(uint32 reset_status) OVERRIDE;
1528 #if defined(OS_MACOSX)
1529 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1532 bool ValidateCompressedTexDimensions(
1533 const char* function_name,
1534 GLint level, GLsizei width, GLsizei height, GLenum format);
1535 bool ValidateCompressedTexFuncData(
1536 const char* function_name,
1537 GLsizei width, GLsizei height, GLenum format, size_t size);
1538 bool ValidateCompressedTexSubDimensions(
1539 const char* function_name,
1540 GLenum target, GLint level, GLint xoffset, GLint yoffset,
1541 GLsizei width, GLsizei height, GLenum format,
1544 void RenderWarning(const char* filename, int line, const std::string& msg);
1545 void PerformanceWarning(
1546 const char* filename, int line, const std::string& msg);
1548 const FeatureInfo::FeatureFlags& features() const {
1549 return feature_info_->feature_flags();
1552 const FeatureInfo::Workarounds& workarounds() const {
1553 return feature_info_->workarounds();
1556 bool ShouldDeferDraws() {
1557 return !offscreen_target_frame_buffer_.get() &&
1558 framebuffer_state_.bound_draw_framebuffer.get() == NULL &&
1559 surface_->DeferDraws();
1562 bool ShouldDeferReads() {
1563 return !offscreen_target_frame_buffer_.get() &&
1564 framebuffer_state_.bound_read_framebuffer.get() == NULL &&
1565 surface_->DeferDraws();
1568 error::Error WillAccessBoundFramebufferForDraw() {
1569 if (ShouldDeferDraws())
1570 return error::kDeferCommandUntilLater;
1571 if (!offscreen_target_frame_buffer_.get() &&
1572 !framebuffer_state_.bound_draw_framebuffer.get() &&
1573 !surface_->SetBackbufferAllocation(true))
1574 return error::kLostContext;
1575 return error::kNoError;
1578 error::Error WillAccessBoundFramebufferForRead() {
1579 if (ShouldDeferReads())
1580 return error::kDeferCommandUntilLater;
1581 if (!offscreen_target_frame_buffer_.get() &&
1582 !framebuffer_state_.bound_read_framebuffer.get() &&
1583 !surface_->SetBackbufferAllocation(true))
1584 return error::kLostContext;
1585 return error::kNoError;
1588 void ProcessPendingReadPixels();
1589 void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
1591 // Generate a member function prototype for each command in an automated and
1593 #define GLES2_CMD_OP(name) \
1594 Error Handle ## name( \
1595 uint32 immediate_data_size, \
1596 const cmds::name& args); \
1598 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1602 // The GL context this decoder renders to on behalf of the client.
1603 scoped_refptr<gfx::GLSurface> surface_;
1604 scoped_refptr<gfx::GLContext> context_;
1606 // The ContextGroup for this decoder uses to track resources.
1607 scoped_refptr<ContextGroup> group_;
1609 DebugMarkerManager debug_marker_manager_;
1612 // All the state for this context.
1613 ContextState state_;
1615 // Current width and height of the offscreen frame buffer.
1616 gfx::Size offscreen_size_;
1618 // Util to help with GL.
1621 // unpack flip y as last set by glPixelStorei
1622 bool unpack_flip_y_;
1624 // unpack (un)premultiply alpha as last set by glPixelStorei
1625 bool unpack_premultiply_alpha_;
1626 bool unpack_unpremultiply_alpha_;
1628 // Default vertex attribs manager, used when no VAOs are bound.
1629 scoped_refptr<VertexAttribManager> default_vertex_attrib_manager_;
1631 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1632 GLuint attrib_0_buffer_id_;
1634 // The value currently in attrib_0.
1635 Vec4 attrib_0_value_;
1637 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1638 bool attrib_0_buffer_matches_value_;
1640 // The size of attrib 0.
1641 GLsizei attrib_0_size_;
1643 // The buffer used to simulate GL_FIXED attribs.
1644 GLuint fixed_attrib_buffer_id_;
1646 // The size of fiixed attrib buffer.
1647 GLsizei fixed_attrib_buffer_size_;
1649 // The offscreen frame buffer that the client renders to. With EGL, the
1650 // depth and stencil buffers are separate. With regular GL there is a single
1651 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1652 // offscreen_target_stencil_render_buffer_ is unused.
1653 scoped_ptr<BackFramebuffer> offscreen_target_frame_buffer_;
1654 scoped_ptr<BackTexture> offscreen_target_color_texture_;
1655 scoped_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_;
1656 scoped_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_;
1657 scoped_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_;
1658 GLenum offscreen_target_color_format_;
1659 GLenum offscreen_target_depth_format_;
1660 GLenum offscreen_target_stencil_format_;
1661 GLsizei offscreen_target_samples_;
1662 GLboolean offscreen_target_buffer_preserved_;
1664 // The copy that is saved when SwapBuffers is called.
1665 scoped_ptr<BackFramebuffer> offscreen_saved_frame_buffer_;
1666 scoped_ptr<BackTexture> offscreen_saved_color_texture_;
1667 scoped_refptr<TextureRef>
1668 offscreen_saved_color_texture_info_;
1670 // The copy that is used as the destination for multi-sample resolves.
1671 scoped_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_;
1672 scoped_ptr<BackTexture> offscreen_resolved_color_texture_;
1673 GLenum offscreen_saved_color_format_;
1675 scoped_ptr<QueryManager> query_manager_;
1677 scoped_ptr<VertexArrayManager> vertex_array_manager_;
1679 base::Callback<void(gfx::Size, float)> resize_callback_;
1681 WaitSyncPointCallback wait_sync_point_callback_;
1683 ShaderCacheCallback shader_cache_callback_;
1685 scoped_ptr<AsyncPixelTransferManager> async_pixel_transfer_manager_;
1687 // The format of the back buffer_
1688 GLenum back_buffer_color_format_;
1689 bool back_buffer_has_depth_;
1690 bool back_buffer_has_stencil_;
1692 // Backbuffer attachments that are currently undefined.
1693 uint32 backbuffer_needs_clear_bits_;
1695 // The current decoder error.
1696 error::Error current_decoder_error_;
1698 bool use_shader_translator_;
1699 scoped_refptr<ShaderTranslator> vertex_translator_;
1700 scoped_refptr<ShaderTranslator> fragment_translator_;
1702 DisallowedFeatures disallowed_features_;
1704 // Cached from ContextGroup
1705 const Validators* validators_;
1706 scoped_refptr<FeatureInfo> feature_info_;
1710 bool has_robustness_extension_;
1711 GLenum reset_status_;
1712 bool reset_by_robustness_extension_;
1713 bool supports_post_sub_buffer_;
1715 // These flags are used to override the state of the shared feature_info_
1716 // member. Because the same FeatureInfo instance may be shared among many
1717 // contexts, the assumptions on the availablity of extensions in WebGL
1718 // contexts may be broken. These flags override the shared state to preserve
1720 bool force_webgl_glsl_validation_;
1721 bool derivatives_explicitly_enabled_;
1722 bool frag_depth_explicitly_enabled_;
1723 bool draw_buffers_explicitly_enabled_;
1725 bool compile_shader_always_succeeds_;
1727 // An optional behaviour to lose the context and group when OOM.
1728 bool lose_context_when_out_of_memory_;
1731 bool service_logging_;
1733 #if defined(OS_MACOSX)
1734 typedef std::map<GLuint, CFTypeRef> TextureToIOSurfaceMap;
1735 TextureToIOSurfaceMap texture_to_io_surface_map_;
1738 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
1740 // Cached values of the currently assigned viewport dimensions.
1741 GLsizei viewport_max_width_;
1742 GLsizei viewport_max_height_;
1744 // Command buffer stats.
1745 base::TimeDelta total_processing_commands_time_;
1747 // States related to each manager.
1748 DecoderTextureState texture_state_;
1749 DecoderFramebufferState framebuffer_state_;
1751 scoped_ptr<GPUTracer> gpu_tracer_;
1752 scoped_ptr<GPUStateTracer> gpu_state_tracer_;
1753 int gpu_trace_level_;
1754 bool gpu_trace_commands_;
1756 std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_;
1758 // Used to validate multisample renderbuffers if needed
1759 GLuint validation_texture_;
1760 GLuint validation_fbo_multisample_;
1761 GLuint validation_fbo_;
1763 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1766 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
1767 const char* function_name, ErrorState* error_state)
1768 : function_name_(function_name),
1769 error_state_(error_state) {
1770 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_, function_name_);
1773 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1774 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_, function_name_);
1777 static void RestoreCurrentTextureBindings(ContextState* state, GLenum target) {
1778 TextureUnit& info = state->texture_units[0];
1780 scoped_refptr<TextureRef> texture_ref;
1783 texture_ref = info.bound_texture_2d;
1785 case GL_TEXTURE_CUBE_MAP:
1786 texture_ref = info.bound_texture_cube_map;
1788 case GL_TEXTURE_EXTERNAL_OES:
1789 texture_ref = info.bound_texture_external_oes;
1791 case GL_TEXTURE_RECTANGLE_ARB:
1792 texture_ref = info.bound_texture_rectangle_arb;
1798 if (texture_ref.get()) {
1799 last_id = texture_ref->service_id();
1804 glBindTexture(target, last_id);
1805 glActiveTexture(GL_TEXTURE0 + state->active_texture_unit);
1808 ScopedTextureBinder::ScopedTextureBinder(ContextState* state,
1813 ScopedGLErrorSuppressor suppressor(
1814 "ScopedTextureBinder::ctor", state_->GetErrorState());
1816 // TODO(apatrick): Check if there are any other states that need to be reset
1817 // before binding a new texture.
1818 glActiveTexture(GL_TEXTURE0);
1819 glBindTexture(target, id);
1822 ScopedTextureBinder::~ScopedTextureBinder() {
1823 ScopedGLErrorSuppressor suppressor(
1824 "ScopedTextureBinder::dtor", state_->GetErrorState());
1825 RestoreCurrentTextureBindings(state_, target_);
1828 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState* state,
1831 ScopedGLErrorSuppressor suppressor(
1832 "ScopedRenderBufferBinder::ctor", state_->GetErrorState());
1833 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1836 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1837 ScopedGLErrorSuppressor suppressor(
1838 "ScopedRenderBufferBinder::dtor", state_->GetErrorState());
1839 state_->RestoreRenderbufferBindings();
1842 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1844 : decoder_(decoder) {
1845 ScopedGLErrorSuppressor suppressor(
1846 "ScopedFrameBufferBinder::ctor", decoder_->GetErrorState());
1847 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1848 decoder->OnFboChanged();
1851 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1852 ScopedGLErrorSuppressor suppressor(
1853 "ScopedFrameBufferBinder::dtor", decoder_->GetErrorState());
1854 decoder_->RestoreCurrentFramebufferBindings();
1857 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
1858 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
1859 : decoder_(decoder) {
1860 resolve_and_bind_ = (
1861 decoder_->offscreen_target_frame_buffer_.get() &&
1862 decoder_->IsOffscreenBufferMultisampled() &&
1863 (!decoder_->framebuffer_state_.bound_read_framebuffer.get() ||
1864 enforce_internal_framebuffer));
1865 if (!resolve_and_bind_)
1868 ScopedGLErrorSuppressor suppressor(
1869 "ScopedResolvedFrameBufferBinder::ctor", decoder_->GetErrorState());
1870 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1871 decoder_->offscreen_target_frame_buffer_->id());
1874 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
1875 decoder_->offscreen_resolved_frame_buffer_.reset(
1876 new BackFramebuffer(decoder_));
1877 decoder_->offscreen_resolved_frame_buffer_->Create();
1878 decoder_->offscreen_resolved_color_texture_.reset(
1879 new BackTexture(decoder->memory_tracker(), &decoder->state_));
1880 decoder_->offscreen_resolved_color_texture_->Create();
1882 DCHECK(decoder_->offscreen_saved_color_format_);
1883 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
1884 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_,
1886 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
1887 decoder_->offscreen_resolved_color_texture_.get());
1888 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
1889 GL_FRAMEBUFFER_COMPLETE) {
1890 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
1891 << "because offscreen resolved FBO was incomplete.";
1895 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
1897 targetid = decoder_->offscreen_saved_frame_buffer_->id();
1899 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
1900 const int width = decoder_->offscreen_size_.width();
1901 const int height = decoder_->offscreen_size_.height();
1902 glDisable(GL_SCISSOR_TEST);
1903 decoder->BlitFramebufferHelper(0,
1911 GL_COLOR_BUFFER_BIT,
1913 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
1916 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1917 if (!resolve_and_bind_)
1920 ScopedGLErrorSuppressor suppressor(
1921 "ScopedResolvedFrameBufferBinder::dtor", decoder_->GetErrorState());
1922 decoder_->RestoreCurrentFramebufferBindings();
1923 if (decoder_->state_.enable_flags.scissor_test) {
1924 glEnable(GL_SCISSOR_TEST);
1928 BackTexture::BackTexture(
1929 MemoryTracker* memory_tracker,
1930 ContextState* state)
1931 : memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
1933 bytes_allocated_(0),
1937 BackTexture::~BackTexture() {
1938 // This does not destroy the render texture because that would require that
1939 // the associated GL context was current. Just check that it was explicitly
1944 void BackTexture::Create() {
1945 ScopedGLErrorSuppressor suppressor("BackTexture::Create",
1946 state_->GetErrorState());
1948 glGenTextures(1, &id_);
1949 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
1950 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1951 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1952 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1953 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1955 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
1956 // never called on an offscreen context, no data will ever be uploaded to the
1957 // saved offscreen color texture (it is deferred until to when SwapBuffers
1958 // is called). My idea is that some nvidia drivers might have a bug where
1959 // deleting a texture that has never been populated might cause a
1962 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
1964 bytes_allocated_ = 16u * 16u * 4u;
1965 memory_tracker_.TrackMemAlloc(bytes_allocated_);
1968 bool BackTexture::AllocateStorage(
1969 const gfx::Size& size, GLenum format, bool zero) {
1971 ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage",
1972 state_->GetErrorState());
1973 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
1974 uint32 image_size = 0;
1975 GLES2Util::ComputeImageDataSizes(
1976 size.width(), size.height(), format, GL_UNSIGNED_BYTE, 8, &image_size,
1979 if (!memory_tracker_.EnsureGPUMemoryAvailable(image_size)) {
1983 scoped_ptr<char[]> zero_data;
1985 zero_data.reset(new char[image_size]);
1986 memset(zero_data.get(), 0, image_size);
1989 glTexImage2D(GL_TEXTURE_2D,
2001 bool success = glGetError() == GL_NO_ERROR;
2003 memory_tracker_.TrackMemFree(bytes_allocated_);
2004 bytes_allocated_ = image_size;
2005 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2010 void BackTexture::Copy(const gfx::Size& size, GLenum format) {
2012 ScopedGLErrorSuppressor suppressor("BackTexture::Copy",
2013 state_->GetErrorState());
2014 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2015 glCopyTexImage2D(GL_TEXTURE_2D,
2024 void BackTexture::Destroy() {
2026 ScopedGLErrorSuppressor suppressor("BackTexture::Destroy",
2027 state_->GetErrorState());
2028 glDeleteTextures(1, &id_);
2031 memory_tracker_.TrackMemFree(bytes_allocated_);
2032 bytes_allocated_ = 0;
2035 void BackTexture::Invalidate() {
2039 BackRenderbuffer::BackRenderbuffer(
2040 RenderbufferManager* renderbuffer_manager,
2041 MemoryTracker* memory_tracker,
2042 ContextState* state)
2043 : renderbuffer_manager_(renderbuffer_manager),
2044 memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2046 bytes_allocated_(0),
2050 BackRenderbuffer::~BackRenderbuffer() {
2051 // This does not destroy the render buffer because that would require that
2052 // the associated GL context was current. Just check that it was explicitly
2057 void BackRenderbuffer::Create() {
2058 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create",
2059 state_->GetErrorState());
2061 glGenRenderbuffersEXT(1, &id_);
2064 bool BackRenderbuffer::AllocateStorage(const FeatureInfo* feature_info,
2065 const gfx::Size& size,
2068 ScopedGLErrorSuppressor suppressor(
2069 "BackRenderbuffer::AllocateStorage", state_->GetErrorState());
2070 ScopedRenderBufferBinder binder(state_, id_);
2072 uint32 estimated_size = 0;
2073 if (!renderbuffer_manager_->ComputeEstimatedRenderbufferSize(
2074 size.width(), size.height(), samples, format, &estimated_size)) {
2078 if (!memory_tracker_.EnsureGPUMemoryAvailable(estimated_size)) {
2083 glRenderbufferStorageEXT(GL_RENDERBUFFER,
2088 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info,
2095 bool success = glGetError() == GL_NO_ERROR;
2097 // Mark the previously allocated bytes as free.
2098 memory_tracker_.TrackMemFree(bytes_allocated_);
2099 bytes_allocated_ = estimated_size;
2100 // Track the newly allocated bytes.
2101 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2106 void BackRenderbuffer::Destroy() {
2108 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy",
2109 state_->GetErrorState());
2110 glDeleteRenderbuffersEXT(1, &id_);
2113 memory_tracker_.TrackMemFree(bytes_allocated_);
2114 bytes_allocated_ = 0;
2117 void BackRenderbuffer::Invalidate() {
2121 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl* decoder)
2122 : decoder_(decoder),
2126 BackFramebuffer::~BackFramebuffer() {
2127 // This does not destroy the frame buffer because that would require that
2128 // the associated GL context was current. Just check that it was explicitly
2133 void BackFramebuffer::Create() {
2134 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create",
2135 decoder_->GetErrorState());
2137 glGenFramebuffersEXT(1, &id_);
2140 void BackFramebuffer::AttachRenderTexture(BackTexture* texture) {
2142 ScopedGLErrorSuppressor suppressor(
2143 "BackFramebuffer::AttachRenderTexture", decoder_->GetErrorState());
2144 ScopedFrameBufferBinder binder(decoder_, id_);
2145 GLuint attach_id = texture ? texture->id() : 0;
2146 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2147 GL_COLOR_ATTACHMENT0,
2153 void BackFramebuffer::AttachRenderBuffer(GLenum target,
2154 BackRenderbuffer* render_buffer) {
2156 ScopedGLErrorSuppressor suppressor(
2157 "BackFramebuffer::AttachRenderBuffer", decoder_->GetErrorState());
2158 ScopedFrameBufferBinder binder(decoder_, id_);
2159 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
2160 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
2166 void BackFramebuffer::Destroy() {
2168 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy",
2169 decoder_->GetErrorState());
2170 glDeleteFramebuffersEXT(1, &id_);
2175 void BackFramebuffer::Invalidate() {
2179 GLenum BackFramebuffer::CheckStatus() {
2181 ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus",
2182 decoder_->GetErrorState());
2183 ScopedFrameBufferBinder binder(decoder_, id_);
2184 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
2187 GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
2188 return new GLES2DecoderImpl(group);
2191 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
2194 logger_(&debug_marker_manager_),
2195 state_(group_->feature_info(), this, &logger_),
2196 unpack_flip_y_(false),
2197 unpack_premultiply_alpha_(false),
2198 unpack_unpremultiply_alpha_(false),
2199 attrib_0_buffer_id_(0),
2200 attrib_0_buffer_matches_value_(true),
2202 fixed_attrib_buffer_id_(0),
2203 fixed_attrib_buffer_size_(0),
2204 offscreen_target_color_format_(0),
2205 offscreen_target_depth_format_(0),
2206 offscreen_target_stencil_format_(0),
2207 offscreen_target_samples_(0),
2208 offscreen_target_buffer_preserved_(true),
2209 offscreen_saved_color_format_(0),
2210 back_buffer_color_format_(0),
2211 back_buffer_has_depth_(false),
2212 back_buffer_has_stencil_(false),
2213 backbuffer_needs_clear_bits_(0),
2214 current_decoder_error_(error::kNoError),
2215 use_shader_translator_(true),
2216 validators_(group_->feature_info()->validators()),
2217 feature_info_(group_->feature_info()),
2219 has_robustness_extension_(false),
2220 reset_status_(GL_NO_ERROR),
2221 reset_by_robustness_extension_(false),
2222 supports_post_sub_buffer_(false),
2223 force_webgl_glsl_validation_(false),
2224 derivatives_explicitly_enabled_(false),
2225 frag_depth_explicitly_enabled_(false),
2226 draw_buffers_explicitly_enabled_(false),
2227 compile_shader_always_succeeds_(false),
2228 lose_context_when_out_of_memory_(false),
2229 service_logging_(CommandLine::ForCurrentProcess()->HasSwitch(
2230 switches::kEnableGPUServiceLoggingGPU)),
2231 viewport_max_width_(0),
2232 viewport_max_height_(0),
2233 texture_state_(group_->feature_info()
2235 .texsubimage2d_faster_than_teximage2d),
2236 validation_texture_(0),
2237 validation_fbo_multisample_(0),
2238 validation_fbo_(0) {
2241 attrib_0_value_.v[0] = 0.0f;
2242 attrib_0_value_.v[1] = 0.0f;
2243 attrib_0_value_.v[2] = 0.0f;
2244 attrib_0_value_.v[3] = 1.0f;
2246 // The shader translator is used for WebGL even when running on EGL
2247 // because additional restrictions are needed (like only enabling
2248 // GL_OES_standard_derivatives on demand). It is used for the unit
2249 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2250 // the empty string to CompileShader and this is not a valid shader.
2251 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
2252 CommandLine::ForCurrentProcess()->HasSwitch(
2253 switches::kDisableGLSLTranslator)) {
2254 use_shader_translator_ = false;
2258 GLES2DecoderImpl::~GLES2DecoderImpl() {
2261 bool GLES2DecoderImpl::Initialize(
2262 const scoped_refptr<gfx::GLSurface>& surface,
2263 const scoped_refptr<gfx::GLContext>& context,
2265 const gfx::Size& size,
2266 const DisallowedFeatures& disallowed_features,
2267 const std::vector<int32>& attribs) {
2268 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2269 DCHECK(context->IsCurrent(surface.get()));
2270 DCHECK(!context_.get());
2273 gpu_tracer_ = GPUTracer::Create(this);
2274 gpu_state_tracer_ = GPUStateTracer::Create(&state_);
2275 // TODO(vmiura): Enable changing gpu_trace_level_ at runtime
2276 gpu_trace_level_ = 2;
2277 gpu_trace_commands_ = false;
2279 if (CommandLine::ForCurrentProcess()->HasSwitch(
2280 switches::kEnableGPUDebugging)) {
2284 if (CommandLine::ForCurrentProcess()->HasSwitch(
2285 switches::kEnableGPUCommandLogging)) {
2286 set_log_commands(true);
2289 compile_shader_always_succeeds_ = CommandLine::ForCurrentProcess()->HasSwitch(
2290 switches::kCompileShaderAlwaysSucceeds);
2293 // Take ownership of the context and surface. The surface can be replaced with
2298 ContextCreationAttribHelper attrib_parser;
2299 if (!attrib_parser.Parse(attribs))
2302 // Save the loseContextWhenOutOfMemory context creation attribute.
2303 lose_context_when_out_of_memory_ =
2304 attrib_parser.lose_context_when_out_of_memory_;
2306 // If the failIfMajorPerformanceCaveat context creation attribute was true
2307 // and we are using a software renderer, fail.
2308 if (attrib_parser.fail_if_major_perf_caveat_ &&
2309 feature_info_->feature_flags().is_swiftshader) {
2310 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2315 if (!group_->Initialize(this, disallowed_features)) {
2316 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
2317 << "failed to initialize.";
2318 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2324 disallowed_features_ = disallowed_features;
2326 state_.attrib_values.resize(group_->max_vertex_attribs());
2327 default_vertex_attrib_manager_ = new VertexAttribManager();
2328 default_vertex_attrib_manager_->Initialize(
2329 group_->max_vertex_attribs(),
2330 feature_info_->workarounds().init_vertex_attributes);
2332 // vertex_attrib_manager is set to default_vertex_attrib_manager_ by this call
2333 DoBindVertexArrayOES(0);
2335 query_manager_.reset(new QueryManager(this, feature_info_.get()));
2336 vertex_array_manager_.reset(new VertexArrayManager());
2338 util_.set_num_compressed_texture_formats(
2339 validators_->compressed_texture_format.GetValues().size());
2341 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2342 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2343 // OpenGL ES 2.0 does not have this issue.
2344 glEnableVertexAttribArray(0);
2346 glGenBuffersARB(1, &attrib_0_buffer_id_);
2347 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2348 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2349 glBindBuffer(GL_ARRAY_BUFFER, 0);
2350 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
2352 state_.texture_units.resize(group_->max_texture_units());
2353 for (uint32 tt = 0; tt < state_.texture_units.size(); ++tt) {
2354 glActiveTexture(GL_TEXTURE0 + tt);
2355 // We want the last bind to be 2D.
2357 if (features().oes_egl_image_external) {
2358 ref = texture_manager()->GetDefaultTextureInfo(
2359 GL_TEXTURE_EXTERNAL_OES);
2360 state_.texture_units[tt].bound_texture_external_oes = ref;
2361 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref->service_id());
2363 if (features().arb_texture_rectangle) {
2364 ref = texture_manager()->GetDefaultTextureInfo(
2365 GL_TEXTURE_RECTANGLE_ARB);
2366 state_.texture_units[tt].bound_texture_rectangle_arb = ref;
2367 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref->service_id());
2369 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
2370 state_.texture_units[tt].bound_texture_cube_map = ref;
2371 glBindTexture(GL_TEXTURE_CUBE_MAP, ref->service_id());
2372 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2373 state_.texture_units[tt].bound_texture_2d = ref;
2374 glBindTexture(GL_TEXTURE_2D, ref->service_id());
2376 glActiveTexture(GL_TEXTURE0);
2380 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
2381 features().chromium_framebuffer_multisample) {
2382 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2383 // max_sample_count must be initialized to a sane value. If
2384 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2385 GLint max_sample_count = 1;
2386 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2387 offscreen_target_samples_ = std::min(attrib_parser.samples_,
2390 offscreen_target_samples_ = 1;
2392 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved_;
2394 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2395 const bool rgb8_supported =
2396 context_->HasExtension("GL_OES_rgb8_rgba8");
2397 // The only available default render buffer formats in GLES2 have very
2398 // little precision. Don't enable multisampling unless 8-bit render
2399 // buffer formats are available--instead fall back to 8-bit textures.
2400 if (rgb8_supported && offscreen_target_samples_ > 1) {
2401 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2404 offscreen_target_samples_ = 1;
2405 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2409 // ANGLE only supports packed depth/stencil formats, so use it if it is
2411 const bool depth24_stencil8_supported =
2412 feature_info_->feature_flags().packed_depth24_stencil8;
2413 VLOG(1) << "GL_OES_packed_depth_stencil "
2414 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2415 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2416 depth24_stencil8_supported) {
2417 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2418 offscreen_target_stencil_format_ = 0;
2420 // It may be the case that this depth/stencil combination is not
2421 // supported, but this will be checked later by CheckFramebufferStatus.
2422 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2423 GL_DEPTH_COMPONENT16 : 0;
2424 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2425 GL_STENCIL_INDEX8 : 0;
2428 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2431 // If depth is requested at all, use the packed depth stencil format if
2432 // it's available, as some desktop GL drivers don't support any non-packed
2433 // formats for depth attachments.
2434 const bool depth24_stencil8_supported =
2435 feature_info_->feature_flags().packed_depth24_stencil8;
2436 VLOG(1) << "GL_EXT_packed_depth_stencil "
2437 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2439 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2440 depth24_stencil8_supported) {
2441 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2442 offscreen_target_stencil_format_ = 0;
2444 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2445 GL_DEPTH_COMPONENT : 0;
2446 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2447 GL_STENCIL_INDEX : 0;
2451 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
2454 // Create the target frame buffer. This is the one that the client renders
2456 offscreen_target_frame_buffer_.reset(new BackFramebuffer(this));
2457 offscreen_target_frame_buffer_->Create();
2458 // Due to GLES2 format limitations, either the color texture (for
2459 // non-multisampling) or the color render buffer (for multisampling) will be
2460 // attached to the offscreen frame buffer. The render buffer has more
2461 // limited formats available to it, but the texture can't do multisampling.
2462 if (IsOffscreenBufferMultisampled()) {
2463 offscreen_target_color_render_buffer_.reset(new BackRenderbuffer(
2464 renderbuffer_manager(), memory_tracker(), &state_));
2465 offscreen_target_color_render_buffer_->Create();
2467 offscreen_target_color_texture_.reset(new BackTexture(
2468 memory_tracker(), &state_));
2469 offscreen_target_color_texture_->Create();
2471 offscreen_target_depth_render_buffer_.reset(new BackRenderbuffer(
2472 renderbuffer_manager(), memory_tracker(), &state_));
2473 offscreen_target_depth_render_buffer_->Create();
2474 offscreen_target_stencil_render_buffer_.reset(new BackRenderbuffer(
2475 renderbuffer_manager(), memory_tracker(), &state_));
2476 offscreen_target_stencil_render_buffer_->Create();
2478 // Create the saved offscreen texture. The target frame buffer is copied
2479 // here when SwapBuffers is called.
2480 offscreen_saved_frame_buffer_.reset(new BackFramebuffer(this));
2481 offscreen_saved_frame_buffer_->Create();
2483 offscreen_saved_color_texture_.reset(new BackTexture(
2484 memory_tracker(), &state_));
2485 offscreen_saved_color_texture_->Create();
2487 // Allocate the render buffers at their initial size and check the status
2488 // of the frame buffers is okay.
2489 if (!ResizeOffscreenFrameBuffer(size)) {
2490 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
2495 // Allocate the offscreen saved color texture.
2496 DCHECK(offscreen_saved_color_format_);
2497 offscreen_saved_color_texture_->AllocateStorage(
2498 gfx::Size(1, 1), offscreen_saved_color_format_, true);
2500 offscreen_saved_frame_buffer_->AttachRenderTexture(
2501 offscreen_saved_color_texture_.get());
2502 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2503 GL_FRAMEBUFFER_COMPLETE) {
2504 LOG(ERROR) << "Offscreen saved FBO was incomplete.";
2509 // Bind to the new default frame buffer (the offscreen target frame buffer).
2510 // This should now be associated with ID zero.
2511 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2513 glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId());
2514 // These are NOT if the back buffer has these proprorties. They are
2515 // if we want the command buffer to enforce them regardless of what
2516 // the real backbuffer is assuming the real back buffer gives us more than
2517 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2518 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2519 // can't do anything about that.
2522 glGetIntegerv(GL_ALPHA_BITS, &v);
2523 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
2524 // user requested RGB then RGB. If the user did not specify a preference
2525 // than use whatever we were given. Same for DEPTH and STENCIL.
2526 back_buffer_color_format_ =
2527 (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB;
2528 glGetIntegerv(GL_DEPTH_BITS, &v);
2529 back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0;
2530 glGetIntegerv(GL_STENCIL_BITS, &v);
2531 back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0;
2534 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2535 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2536 // isn't well documented; it was discovered in the Khronos OpenGL ES
2537 // mailing list archives. It also implicitly enables the desktop GL
2538 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2539 // variable in fragment shaders.
2540 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2541 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
2542 glEnable(GL_POINT_SPRITE);
2545 has_robustness_extension_ =
2546 context->HasExtension("GL_ARB_robustness") ||
2547 context->HasExtension("GL_EXT_robustness");
2549 if (!InitializeShaderTranslator()) {
2553 state_.viewport_width = size.width();
2554 state_.viewport_height = size.height();
2556 GLint viewport_params[4] = { 0 };
2557 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
2558 viewport_max_width_ = viewport_params[0];
2559 viewport_max_height_ = viewport_params[1];
2561 state_.scissor_width = state_.viewport_width;
2562 state_.scissor_height = state_.viewport_height;
2564 // Set all the default state because some GL drivers get it wrong.
2565 state_.InitCapabilities();
2567 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
2569 DoBindBuffer(GL_ARRAY_BUFFER, 0);
2570 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2571 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2572 DoBindRenderbuffer(GL_RENDERBUFFER, 0);
2574 bool call_gl_clear = true;
2575 #if defined(OS_ANDROID)
2576 // Temporary workaround for Android WebView because this clear ignores the
2577 // clip and corrupts that external UI of the App. Not calling glClear is ok
2578 // because the system already clears the buffer before each draw. Proper
2579 // fix might be setting the scissor clip properly before initialize. See
2580 // crbug.com/259023 for details.
2581 call_gl_clear = surface_->GetHandle();
2583 if (call_gl_clear) {
2584 // Clear the backbuffer.
2585 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2588 supports_post_sub_buffer_ = surface->SupportsPostSubBuffer();
2589 if (feature_info_->workarounds()
2590 .disable_post_sub_buffers_for_onscreen_surfaces &&
2591 !surface->IsOffscreen())
2592 supports_post_sub_buffer_ = false;
2594 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) {
2595 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
2598 if (feature_info_->workarounds().unbind_fbo_on_context_switch) {
2599 context_->SetUnbindFboOnMakeCurrent();
2602 if (feature_info_->workarounds().release_image_after_use) {
2603 image_manager()->SetReleaseAfterUse();
2606 // Only compositor contexts are known to use only the subset of GL
2607 // that can be safely migrated between the iGPU and the dGPU. Mark
2608 // those contexts as safe to forcibly transition between the GPUs.
2609 // http://crbug.com/180876, http://crbug.com/227228
2611 context_->SetSafeToForceGpuSwitch();
2613 async_pixel_transfer_manager_.reset(
2614 AsyncPixelTransferManager::Create(context.get()));
2615 async_pixel_transfer_manager_->Initialize(texture_manager());
2617 framebuffer_manager()->AddObserver(this);
2622 Capabilities GLES2DecoderImpl::GetCapabilities() {
2623 DCHECK(initialized());
2627 caps.fast_npot_mo8_textures =
2628 feature_info_->workarounds().enable_chromium_fast_npot_mo8_textures;
2629 caps.egl_image_external =
2630 feature_info_->feature_flags().oes_egl_image_external;
2631 caps.texture_format_bgra8888 =
2632 feature_info_->feature_flags().ext_texture_format_bgra8888;
2633 caps.texture_format_etc1 =
2634 feature_info_->feature_flags().oes_compressed_etc1_rgb8_texture;
2635 caps.texture_rectangle = feature_info_->feature_flags().arb_texture_rectangle;
2636 caps.texture_usage = feature_info_->feature_flags().angle_texture_usage;
2637 caps.texture_storage = feature_info_->feature_flags().ext_texture_storage;
2638 caps.discard_framebuffer =
2639 feature_info_->feature_flags().ext_discard_framebuffer;
2641 #if defined(OS_MACOSX)
2642 // This is unconditionally true on mac, no need to test for it at runtime.
2643 caps.iosurface = true;
2646 caps.post_sub_buffer = supports_post_sub_buffer_;
2651 void GLES2DecoderImpl::UpdateCapabilities() {
2652 util_.set_num_compressed_texture_formats(
2653 validators_->compressed_texture_format.GetValues().size());
2654 util_.set_num_shader_binary_formats(
2655 validators_->shader_binary_format.GetValues().size());
2658 bool GLES2DecoderImpl::InitializeShaderTranslator() {
2659 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
2661 if (!use_shader_translator_) {
2664 ShBuiltInResources resources;
2665 ShInitBuiltInResources(&resources);
2666 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2667 resources.MaxVertexUniformVectors =
2668 group_->max_vertex_uniform_vectors();
2669 resources.MaxVaryingVectors = group_->max_varying_vectors();
2670 resources.MaxVertexTextureImageUnits =
2671 group_->max_vertex_texture_image_units();
2672 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2673 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2674 resources.MaxFragmentUniformVectors =
2675 group_->max_fragment_uniform_vectors();
2676 resources.MaxDrawBuffers = group_->max_draw_buffers();
2677 resources.MaxExpressionComplexity = 256;
2678 resources.MaxCallStackDepth = 256;
2680 #if (ANGLE_SH_VERSION >= 110)
2681 GLint range[2] = { 0, 0 };
2682 GLint precision = 0;
2683 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
2685 resources.FragmentPrecisionHigh =
2686 PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
2689 if (force_webgl_glsl_validation_) {
2690 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
2691 resources.EXT_frag_depth = frag_depth_explicitly_enabled_;
2692 resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
2693 if (!draw_buffers_explicitly_enabled_)
2694 resources.MaxDrawBuffers = 1;
2696 resources.OES_standard_derivatives =
2697 features().oes_standard_derivatives ? 1 : 0;
2698 resources.ARB_texture_rectangle =
2699 features().arb_texture_rectangle ? 1 : 0;
2700 resources.OES_EGL_image_external =
2701 features().oes_egl_image_external ? 1 : 0;
2702 resources.EXT_draw_buffers =
2703 features().ext_draw_buffers ? 1 : 0;
2704 resources.EXT_frag_depth =
2705 features().ext_frag_depth ? 1 : 0;
2708 ShShaderSpec shader_spec = force_webgl_glsl_validation_ ? SH_WEBGL_SPEC
2710 if (shader_spec == SH_WEBGL_SPEC && features().enable_shader_name_hashing)
2711 #if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
2712 resources.HashFunction = &CityHashForAngle;
2714 resources.HashFunction = &CityHash64;
2717 resources.HashFunction = NULL;
2718 ShaderTranslatorInterface::GlslImplementationType implementation_type =
2719 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
2720 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
2721 int driver_bug_workarounds = 0;
2722 if (workarounds().needs_glsl_built_in_function_emulation)
2723 driver_bug_workarounds |= SH_EMULATE_BUILT_IN_FUNCTIONS;
2724 if (workarounds().init_gl_position_in_vertex_shader)
2725 driver_bug_workarounds |= SH_INIT_GL_POSITION;
2726 if (workarounds().unfold_short_circuit_as_ternary_operation)
2727 driver_bug_workarounds |= SH_UNFOLD_SHORT_CIRCUIT;
2728 if (workarounds().init_varyings_without_static_use)
2729 driver_bug_workarounds |= SH_INIT_VARYINGS_WITHOUT_STATIC_USE;
2730 if (workarounds().unroll_for_loop_with_sampler_array_index)
2731 driver_bug_workarounds |= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX;
2733 ShaderTranslatorCache* cache = ShaderTranslatorCache::GetInstance();
2734 vertex_translator_ = cache->GetTranslator(
2735 SH_VERTEX_SHADER, shader_spec, &resources,
2736 implementation_type,
2737 static_cast<ShCompileOptions>(driver_bug_workarounds));
2738 if (!vertex_translator_.get()) {
2739 LOG(ERROR) << "Could not initialize vertex shader translator.";
2744 fragment_translator_ = cache->GetTranslator(
2745 SH_FRAGMENT_SHADER, shader_spec, &resources,
2746 implementation_type,
2747 static_cast<ShCompileOptions>(driver_bug_workarounds));
2748 if (!fragment_translator_.get()) {
2749 LOG(ERROR) << "Could not initialize fragment shader translator.";
2756 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
2757 for (GLsizei ii = 0; ii < n; ++ii) {
2758 if (GetBuffer(client_ids[ii])) {
2762 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2763 glGenBuffersARB(n, service_ids.get());
2764 for (GLsizei ii = 0; ii < n; ++ii) {
2765 CreateBuffer(client_ids[ii], service_ids[ii]);
2770 bool GLES2DecoderImpl::GenFramebuffersHelper(
2771 GLsizei n, const GLuint* client_ids) {
2772 for (GLsizei ii = 0; ii < n; ++ii) {
2773 if (GetFramebuffer(client_ids[ii])) {
2777 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2778 glGenFramebuffersEXT(n, service_ids.get());
2779 for (GLsizei ii = 0; ii < n; ++ii) {
2780 CreateFramebuffer(client_ids[ii], service_ids[ii]);
2785 bool GLES2DecoderImpl::GenRenderbuffersHelper(
2786 GLsizei n, const GLuint* client_ids) {
2787 for (GLsizei ii = 0; ii < n; ++ii) {
2788 if (GetRenderbuffer(client_ids[ii])) {
2792 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2793 glGenRenderbuffersEXT(n, service_ids.get());
2794 for (GLsizei ii = 0; ii < n; ++ii) {
2795 CreateRenderbuffer(client_ids[ii], service_ids[ii]);
2800 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2801 for (GLsizei ii = 0; ii < n; ++ii) {
2802 if (GetTexture(client_ids[ii])) {
2806 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2807 glGenTextures(n, service_ids.get());
2808 for (GLsizei ii = 0; ii < n; ++ii) {
2809 CreateTexture(client_ids[ii], service_ids[ii]);
2814 void GLES2DecoderImpl::DeleteBuffersHelper(
2815 GLsizei n, const GLuint* client_ids) {
2816 for (GLsizei ii = 0; ii < n; ++ii) {
2817 Buffer* buffer = GetBuffer(client_ids[ii]);
2818 if (buffer && !buffer->IsDeleted()) {
2819 state_.vertex_attrib_manager->Unbind(buffer);
2820 if (state_.bound_array_buffer.get() == buffer) {
2821 state_.bound_array_buffer = NULL;
2823 RemoveBuffer(client_ids[ii]);
2828 void GLES2DecoderImpl::DeleteFramebuffersHelper(
2829 GLsizei n, const GLuint* client_ids) {
2830 bool supports_separate_framebuffer_binds =
2831 features().chromium_framebuffer_multisample;
2833 for (GLsizei ii = 0; ii < n; ++ii) {
2834 Framebuffer* framebuffer =
2835 GetFramebuffer(client_ids[ii]);
2836 if (framebuffer && !framebuffer->IsDeleted()) {
2837 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
2838 framebuffer_state_.bound_draw_framebuffer = NULL;
2839 framebuffer_state_.clear_state_dirty = true;
2840 GLenum target = supports_separate_framebuffer_binds ?
2841 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
2842 glBindFramebufferEXT(target, GetBackbufferServiceId());
2844 if (framebuffer == framebuffer_state_.bound_read_framebuffer.get()) {
2845 framebuffer_state_.bound_read_framebuffer = NULL;
2846 GLenum target = supports_separate_framebuffer_binds ?
2847 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
2848 glBindFramebufferEXT(target, GetBackbufferServiceId());
2851 RemoveFramebuffer(client_ids[ii]);
2856 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2857 GLsizei n, const GLuint* client_ids) {
2858 bool supports_separate_framebuffer_binds =
2859 features().chromium_framebuffer_multisample;
2860 for (GLsizei ii = 0; ii < n; ++ii) {
2861 Renderbuffer* renderbuffer =
2862 GetRenderbuffer(client_ids[ii]);
2863 if (renderbuffer && !renderbuffer->IsDeleted()) {
2864 if (state_.bound_renderbuffer.get() == renderbuffer) {
2865 state_.bound_renderbuffer = NULL;
2867 // Unbind from current framebuffers.
2868 if (supports_separate_framebuffer_binds) {
2869 if (framebuffer_state_.bound_read_framebuffer.get()) {
2870 framebuffer_state_.bound_read_framebuffer
2871 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT, renderbuffer);
2873 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2874 framebuffer_state_.bound_draw_framebuffer
2875 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
2878 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2879 framebuffer_state_.bound_draw_framebuffer
2880 ->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
2883 framebuffer_state_.clear_state_dirty = true;
2884 RemoveRenderbuffer(client_ids[ii]);
2889 void GLES2DecoderImpl::DeleteTexturesHelper(
2890 GLsizei n, const GLuint* client_ids) {
2891 bool supports_separate_framebuffer_binds =
2892 features().chromium_framebuffer_multisample;
2893 for (GLsizei ii = 0; ii < n; ++ii) {
2894 TextureRef* texture_ref = GetTexture(client_ids[ii]);
2896 Texture* texture = texture_ref->texture();
2897 if (texture->IsAttachedToFramebuffer()) {
2898 framebuffer_state_.clear_state_dirty = true;
2900 // Unbind texture_ref from texture_ref units.
2901 for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) {
2902 state_.texture_units[jj].Unbind(texture_ref);
2904 // Unbind from current framebuffers.
2905 if (supports_separate_framebuffer_binds) {
2906 if (framebuffer_state_.bound_read_framebuffer.get()) {
2907 framebuffer_state_.bound_read_framebuffer
2908 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT, texture_ref);
2910 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2911 framebuffer_state_.bound_draw_framebuffer
2912 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
2915 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2916 framebuffer_state_.bound_draw_framebuffer
2917 ->UnbindTexture(GL_FRAMEBUFFER, texture_ref);
2920 #if defined(OS_MACOSX)
2921 GLuint service_id = texture->service_id();
2922 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
2923 ReleaseIOSurfaceForTexture(service_id);
2926 RemoveTexture(client_ids[ii]);
2931 // } // anonymous namespace
2933 bool GLES2DecoderImpl::MakeCurrent() {
2934 if (!context_.get())
2937 if (!context_->MakeCurrent(surface_.get()) || WasContextLost()) {
2938 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
2940 // Some D3D drivers cannot recover from device lost in the GPU process
2941 // sandbox. Allow a new GPU process to launch.
2942 if (workarounds().exit_on_context_lost) {
2943 LOG(ERROR) << "Exiting GPU process because some drivers cannot reset"
2944 << " a D3D device in the Chrome GPU process sandbox.";
2946 base::win::SetShouldCrashOnProcessDetach(false);
2954 ProcessFinishedAsyncTransfers();
2956 // Rebind the FBO if it was unbound by the context.
2957 if (workarounds().unbind_fbo_on_context_switch)
2958 RestoreFramebufferBindings();
2960 framebuffer_state_.clear_state_dirty = true;
2965 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
2966 ProcessPendingReadPixels();
2967 if (engine() && query_manager_.get())
2968 query_manager_->ProcessPendingTransferQueries();
2970 // TODO(epenner): Is there a better place to do this?
2971 // This needs to occur before we execute any batch of commands
2972 // from the client, as the client may have recieved an async
2973 // completion while issuing those commands.
2974 // "DidFlushStart" would be ideal if we had such a callback.
2975 async_pixel_transfer_manager_->BindCompletedAsyncTransfers();
2978 static void RebindCurrentFramebuffer(
2980 Framebuffer* framebuffer,
2981 GLuint back_buffer_service_id) {
2982 GLuint framebuffer_id = framebuffer ? framebuffer->service_id() : 0;
2984 if (framebuffer_id == 0) {
2985 framebuffer_id = back_buffer_service_id;
2988 glBindFramebufferEXT(target, framebuffer_id);
2991 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
2992 framebuffer_state_.clear_state_dirty = true;
2994 if (!features().chromium_framebuffer_multisample) {
2995 RebindCurrentFramebuffer(
2997 framebuffer_state_.bound_draw_framebuffer.get(),
2998 GetBackbufferServiceId());
3000 RebindCurrentFramebuffer(
3001 GL_READ_FRAMEBUFFER_EXT,
3002 framebuffer_state_.bound_read_framebuffer.get(),
3003 GetBackbufferServiceId());
3004 RebindCurrentFramebuffer(
3005 GL_DRAW_FRAMEBUFFER_EXT,
3006 framebuffer_state_.bound_draw_framebuffer.get(),
3007 GetBackbufferServiceId());
3012 bool GLES2DecoderImpl::CheckFramebufferValid(
3013 Framebuffer* framebuffer,
3014 GLenum target, const char* func_name) {
3016 if (backbuffer_needs_clear_bits_) {
3017 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3018 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
3019 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3024 glDisable(GL_SCISSOR_TEST);
3025 glClear(backbuffer_needs_clear_bits_);
3026 backbuffer_needs_clear_bits_ = 0;
3027 RestoreClearState();
3032 if (framebuffer_manager()->IsComplete(framebuffer)) {
3036 GLenum completeness = framebuffer->IsPossiblyComplete();
3037 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
3039 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
3043 // Are all the attachments cleared?
3044 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3045 texture_manager()->HaveUnclearedMips()) {
3046 if (!framebuffer->IsCleared()) {
3047 // Can we clear them?
3048 if (framebuffer->GetStatus(texture_manager(), target) !=
3049 GL_FRAMEBUFFER_COMPLETE) {
3051 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3052 "framebuffer incomplete (clear)");
3055 ClearUnclearedAttachments(target, framebuffer);
3059 if (!framebuffer_manager()->IsComplete(framebuffer)) {
3060 if (framebuffer->GetStatus(texture_manager(), target) !=
3061 GL_FRAMEBUFFER_COMPLETE) {
3063 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3064 "framebuffer incomplete (check)");
3067 framebuffer_manager()->MarkAsComplete(framebuffer);
3070 // NOTE: At this point we don't know if the framebuffer is complete but
3071 // we DO know that everything that needs to be cleared has been cleared.
3075 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
3076 if (!features().chromium_framebuffer_multisample) {
3077 bool valid = CheckFramebufferValid(
3078 framebuffer_state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT,
3086 return CheckFramebufferValid(framebuffer_state_.bound_draw_framebuffer.get(),
3087 GL_DRAW_FRAMEBUFFER_EXT,
3089 CheckFramebufferValid(framebuffer_state_.bound_read_framebuffer.get(),
3090 GL_READ_FRAMEBUFFER_EXT,
3094 gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3095 Framebuffer* framebuffer =
3096 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3097 if (framebuffer != NULL) {
3098 const Framebuffer::Attachment* attachment =
3099 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
3101 return gfx::Size(attachment->width(), attachment->height());
3103 return gfx::Size(0, 0);
3104 } else if (offscreen_target_frame_buffer_.get()) {
3105 return offscreen_size_;
3107 return surface_->GetSize();
3111 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3112 Framebuffer* framebuffer =
3113 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3114 if (framebuffer != NULL) {
3115 return framebuffer->GetColorAttachmentTextureType();
3117 return GL_UNSIGNED_BYTE;
3121 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3122 Framebuffer* framebuffer =
3123 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3124 if (framebuffer != NULL) {
3125 return framebuffer->GetColorAttachmentFormat();
3126 } else if (offscreen_target_frame_buffer_.get()) {
3127 return offscreen_target_color_format_;
3129 return back_buffer_color_format_;
3133 GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3134 Framebuffer* framebuffer =
3135 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3136 if (framebuffer != NULL) {
3137 return framebuffer->GetColorAttachmentFormat();
3138 } else if (offscreen_target_frame_buffer_.get()) {
3139 return offscreen_target_color_format_;
3141 return back_buffer_color_format_;
3145 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3146 if (!offscreen_saved_color_texture_info_.get())
3148 GLenum target = offscreen_saved_color_texture_info_->texture()->target();
3149 glBindTexture(target, offscreen_saved_color_texture_info_->service_id());
3150 texture_manager()->SetLevelInfo(
3151 offscreen_saved_color_texture_info_.get(),
3155 offscreen_size_.width(),
3156 offscreen_size_.height(),
3162 texture_manager()->SetParameteri(
3163 "UpdateParentTextureInfo",
3165 offscreen_saved_color_texture_info_.get(),
3166 GL_TEXTURE_MAG_FILTER,
3168 texture_manager()->SetParameteri(
3169 "UpdateParentTextureInfo",
3171 offscreen_saved_color_texture_info_.get(),
3172 GL_TEXTURE_MIN_FILTER,
3174 texture_manager()->SetParameteri(
3175 "UpdateParentTextureInfo",
3177 offscreen_saved_color_texture_info_.get(),
3180 texture_manager()->SetParameteri(
3181 "UpdateParentTextureInfo",
3183 offscreen_saved_color_texture_info_.get(),
3186 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
3188 glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
3191 void GLES2DecoderImpl::SetResizeCallback(
3192 const base::Callback<void(gfx::Size, float)>& callback) {
3193 resize_callback_ = callback;
3196 Logger* GLES2DecoderImpl::GetLogger() {
3200 void GLES2DecoderImpl::BeginDecoding() {
3201 gpu_tracer_->BeginDecoding();
3202 gpu_trace_commands_ = gpu_tracer_->IsTracing();
3205 void GLES2DecoderImpl::EndDecoding() {
3206 gpu_tracer_->EndDecoding();
3209 ErrorState* GLES2DecoderImpl::GetErrorState() {
3210 return state_.GetErrorState();
3213 void GLES2DecoderImpl::SetShaderCacheCallback(
3214 const ShaderCacheCallback& callback) {
3215 shader_cache_callback_ = callback;
3218 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3219 const WaitSyncPointCallback& callback) {
3220 wait_sync_point_callback_ = callback;
3223 AsyncPixelTransferManager*
3224 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3225 return async_pixel_transfer_manager_.get();
3228 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3229 async_pixel_transfer_manager_.reset();
3232 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3233 AsyncPixelTransferManager* manager) {
3234 async_pixel_transfer_manager_ = make_scoped_ptr(manager);
3237 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
3238 uint32* service_texture_id) {
3239 TextureRef* texture_ref = texture_manager()->GetTexture(client_texture_id);
3241 *service_texture_id = texture_ref->service_id();
3247 uint32 GLES2DecoderImpl::GetTextureUploadCount() {
3248 return texture_state_.texture_upload_count +
3249 async_pixel_transfer_manager_->GetTextureUploadCount();
3252 base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
3253 return texture_state_.total_texture_upload_time +
3254 async_pixel_transfer_manager_->GetTotalTextureUploadTime();
3257 base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3258 return total_processing_commands_time_;
3261 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time) {
3262 total_processing_commands_time_ += time;
3265 void GLES2DecoderImpl::Destroy(bool have_context) {
3269 DCHECK(!have_context || context_->IsCurrent(NULL));
3271 // Unbind everything.
3272 state_.vertex_attrib_manager = NULL;
3273 default_vertex_attrib_manager_ = NULL;
3274 state_.texture_units.clear();
3275 state_.bound_array_buffer = NULL;
3276 state_.current_queries.clear();
3277 framebuffer_state_.bound_read_framebuffer = NULL;
3278 framebuffer_state_.bound_draw_framebuffer = NULL;
3279 state_.bound_renderbuffer = NULL;
3281 if (offscreen_saved_color_texture_info_.get()) {
3282 DCHECK(offscreen_target_color_texture_);
3283 DCHECK_EQ(offscreen_saved_color_texture_info_->service_id(),
3284 offscreen_saved_color_texture_->id());
3285 offscreen_saved_color_texture_->Invalidate();
3286 offscreen_saved_color_texture_info_ = NULL;
3289 if (copy_texture_CHROMIUM_.get()) {
3290 copy_texture_CHROMIUM_->Destroy();
3291 copy_texture_CHROMIUM_.reset();
3294 if (state_.current_program.get()) {
3295 program_manager()->UnuseProgram(shader_manager(),
3296 state_.current_program.get());
3299 if (attrib_0_buffer_id_) {
3300 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
3302 if (fixed_attrib_buffer_id_) {
3303 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
3306 if (validation_texture_) {
3307 glDeleteTextures(1, &validation_texture_);
3308 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_);
3309 glDeleteFramebuffersEXT(1, &validation_fbo_);
3312 if (offscreen_target_frame_buffer_.get())
3313 offscreen_target_frame_buffer_->Destroy();
3314 if (offscreen_target_color_texture_.get())
3315 offscreen_target_color_texture_->Destroy();
3316 if (offscreen_target_color_render_buffer_.get())
3317 offscreen_target_color_render_buffer_->Destroy();
3318 if (offscreen_target_depth_render_buffer_.get())
3319 offscreen_target_depth_render_buffer_->Destroy();
3320 if (offscreen_target_stencil_render_buffer_.get())
3321 offscreen_target_stencil_render_buffer_->Destroy();
3322 if (offscreen_saved_frame_buffer_.get())
3323 offscreen_saved_frame_buffer_->Destroy();
3324 if (offscreen_saved_color_texture_.get())
3325 offscreen_saved_color_texture_->Destroy();
3326 if (offscreen_resolved_frame_buffer_.get())
3327 offscreen_resolved_frame_buffer_->Destroy();
3328 if (offscreen_resolved_color_texture_.get())
3329 offscreen_resolved_color_texture_->Destroy();
3331 if (offscreen_target_frame_buffer_.get())
3332 offscreen_target_frame_buffer_->Invalidate();
3333 if (offscreen_target_color_texture_.get())
3334 offscreen_target_color_texture_->Invalidate();
3335 if (offscreen_target_color_render_buffer_.get())
3336 offscreen_target_color_render_buffer_->Invalidate();
3337 if (offscreen_target_depth_render_buffer_.get())
3338 offscreen_target_depth_render_buffer_->Invalidate();
3339 if (offscreen_target_stencil_render_buffer_.get())
3340 offscreen_target_stencil_render_buffer_->Invalidate();
3341 if (offscreen_saved_frame_buffer_.get())
3342 offscreen_saved_frame_buffer_->Invalidate();
3343 if (offscreen_saved_color_texture_.get())
3344 offscreen_saved_color_texture_->Invalidate();
3345 if (offscreen_resolved_frame_buffer_.get())
3346 offscreen_resolved_frame_buffer_->Invalidate();
3347 if (offscreen_resolved_color_texture_.get())
3348 offscreen_resolved_color_texture_->Invalidate();
3351 // Current program must be cleared after calling ProgramManager::UnuseProgram.
3352 // Otherwise, we can leak objects. http://crbug.com/258772.
3353 // state_.current_program must be reset before group_ is reset because
3354 // the later deletes the ProgramManager object that referred by
3355 // state_.current_program object.
3356 state_.current_program = NULL;
3358 copy_texture_CHROMIUM_.reset();
3360 if (query_manager_.get()) {
3361 query_manager_->Destroy(have_context);
3362 query_manager_.reset();
3365 if (vertex_array_manager_ .get()) {
3366 vertex_array_manager_->Destroy(have_context);
3367 vertex_array_manager_.reset();
3370 offscreen_target_frame_buffer_.reset();
3371 offscreen_target_color_texture_.reset();
3372 offscreen_target_color_render_buffer_.reset();
3373 offscreen_target_depth_render_buffer_.reset();
3374 offscreen_target_stencil_render_buffer_.reset();
3375 offscreen_saved_frame_buffer_.reset();
3376 offscreen_saved_color_texture_.reset();
3377 offscreen_resolved_frame_buffer_.reset();
3378 offscreen_resolved_color_texture_.reset();
3380 // Should destroy the transfer manager before the texture manager held
3381 // by the context group.
3382 async_pixel_transfer_manager_.reset();
3385 framebuffer_manager()->RemoveObserver(this);
3386 group_->Destroy(this, have_context);
3390 if (context_.get()) {
3391 context_->ReleaseCurrent(NULL);
3395 #if defined(OS_MACOSX)
3396 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
3397 it != texture_to_io_surface_map_.end(); ++it) {
3398 CFRelease(it->second);
3400 texture_to_io_surface_map_.clear();
3404 void GLES2DecoderImpl::SetSurface(
3405 const scoped_refptr<gfx::GLSurface>& surface) {
3406 DCHECK(context_->IsCurrent(NULL));
3407 DCHECK(surface_.get());
3409 RestoreCurrentFramebufferBindings();
3412 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
3413 if (!offscreen_saved_color_texture_.get()) {
3414 LOG(ERROR) << "Called ProduceFrontBuffer on a non-offscreen context";
3417 if (!offscreen_saved_color_texture_info_.get()) {
3418 GLuint service_id = offscreen_saved_color_texture_->id();
3419 offscreen_saved_color_texture_info_ = TextureRef::Create(
3420 texture_manager(), 0, service_id);
3421 texture_manager()->SetTarget(offscreen_saved_color_texture_info_.get(),
3423 UpdateParentTextureInfo();
3425 mailbox_manager()->ProduceTexture(
3426 GL_TEXTURE_2D, mailbox, offscreen_saved_color_texture_info_->texture());
3429 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
3430 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3431 if (!is_offscreen) {
3432 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3433 << " with an onscreen framebuffer.";
3437 if (offscreen_size_ == size)
3440 offscreen_size_ = size;
3441 int w = offscreen_size_.width();
3442 int h = offscreen_size_.height();
3443 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
3444 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3445 << "to allocate storage due to excessive dimensions.";
3449 // Reallocate the offscreen target buffers.
3450 DCHECK(offscreen_target_color_format_);
3451 if (IsOffscreenBufferMultisampled()) {
3452 if (!offscreen_target_color_render_buffer_->AllocateStorage(
3453 feature_info_, offscreen_size_, offscreen_target_color_format_,
3454 offscreen_target_samples_)) {
3455 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3456 << "to allocate storage for offscreen target color buffer.";
3460 if (!offscreen_target_color_texture_->AllocateStorage(
3461 offscreen_size_, offscreen_target_color_format_, false)) {
3462 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3463 << "to allocate storage for offscreen target color texture.";
3467 if (offscreen_target_depth_format_ &&
3468 !offscreen_target_depth_render_buffer_->AllocateStorage(
3469 feature_info_, offscreen_size_, offscreen_target_depth_format_,
3470 offscreen_target_samples_)) {
3471 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3472 << "to allocate storage for offscreen target depth buffer.";
3475 if (offscreen_target_stencil_format_ &&
3476 !offscreen_target_stencil_render_buffer_->AllocateStorage(
3477 feature_info_, offscreen_size_, offscreen_target_stencil_format_,
3478 offscreen_target_samples_)) {
3479 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3480 << "to allocate storage for offscreen target stencil buffer.";
3484 // Attach the offscreen target buffers to the target frame buffer.
3485 if (IsOffscreenBufferMultisampled()) {
3486 offscreen_target_frame_buffer_->AttachRenderBuffer(
3487 GL_COLOR_ATTACHMENT0,
3488 offscreen_target_color_render_buffer_.get());
3490 offscreen_target_frame_buffer_->AttachRenderTexture(
3491 offscreen_target_color_texture_.get());
3493 if (offscreen_target_depth_format_) {
3494 offscreen_target_frame_buffer_->AttachRenderBuffer(
3495 GL_DEPTH_ATTACHMENT,
3496 offscreen_target_depth_render_buffer_.get());
3498 const bool packed_depth_stencil =
3499 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3500 if (packed_depth_stencil) {
3501 offscreen_target_frame_buffer_->AttachRenderBuffer(
3502 GL_STENCIL_ATTACHMENT,
3503 offscreen_target_depth_render_buffer_.get());
3504 } else if (offscreen_target_stencil_format_) {
3505 offscreen_target_frame_buffer_->AttachRenderBuffer(
3506 GL_STENCIL_ATTACHMENT,
3507 offscreen_target_stencil_render_buffer_.get());
3510 if (offscreen_target_frame_buffer_->CheckStatus() !=
3511 GL_FRAMEBUFFER_COMPLETE) {
3512 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3513 << "because offscreen FBO was incomplete.";
3517 // Clear the target frame buffer.
3519 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
3520 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3521 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
3522 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3524 glStencilMaskSeparate(GL_FRONT, -1);
3525 glStencilMaskSeparate(GL_BACK, -1);
3527 glDepthMask(GL_TRUE);
3528 glDisable(GL_SCISSOR_TEST);
3529 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3530 RestoreClearState();
3533 // Destroy the offscreen resolved framebuffers.
3534 if (offscreen_resolved_frame_buffer_.get())
3535 offscreen_resolved_frame_buffer_->Destroy();
3536 if (offscreen_resolved_color_texture_.get())
3537 offscreen_resolved_color_texture_->Destroy();
3538 offscreen_resolved_color_texture_.reset();
3539 offscreen_resolved_frame_buffer_.reset();
3544 error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(
3545 uint32 immediate_data_size, const cmds::ResizeCHROMIUM& c) {
3546 if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws())
3547 return error::kDeferCommandUntilLater;
3549 GLuint width = static_cast<GLuint>(c.width);
3550 GLuint height = static_cast<GLuint>(c.height);
3551 GLfloat scale_factor = c.scale_factor;
3552 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
3554 width = std::max(1U, width);
3555 height = std::max(1U, height);
3557 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3558 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
3559 // Make sure that we are done drawing to the back buffer before resizing.
3562 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3564 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
3565 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
3566 << "ResizeOffscreenFrameBuffer failed.";
3567 return error::kLostContext;
3571 if (!resize_callback_.is_null()) {
3572 resize_callback_.Run(gfx::Size(width, height), scale_factor);
3573 DCHECK(context_->IsCurrent(surface_.get()));
3574 if (!context_->IsCurrent(surface_.get())) {
3575 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
3576 << "current after resize callback.";
3577 return error::kLostContext;
3581 return error::kNoError;
3584 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
3585 if (command_id > kStartPoint && command_id < kNumCommands) {
3586 return gles2::GetCommandName(static_cast<CommandId>(command_id));
3588 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
3591 // Decode command with its arguments, and call the corresponding GL function.
3592 // Note: args is a pointer to the command buffer. As such, it could be changed
3593 // by a (malicious) client at any time, so if validation has to happen, it
3594 // should operate on a copy of them.
3595 error::Error GLES2DecoderImpl::DoCommand(
3596 unsigned int command,
3597 unsigned int arg_count,
3598 const void* cmd_data) {
3599 error::Error result = error::kNoError;
3600 if (log_commands()) {
3601 // TODO(notme): Change this to a LOG/VLOG that works in release. Tried
3602 // VLOG(1), no luck.
3603 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]" << "cmd: "
3604 << GetCommandName(command);
3606 unsigned int command_index = command - kStartPoint - 1;
3607 if (command_index < arraysize(g_command_info)) {
3608 const CommandInfo& info = g_command_info[command_index];
3609 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
3610 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
3611 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
3612 bool doing_gpu_trace = false;
3613 if (gpu_trace_commands_) {
3614 if (CMD_FLAG_GET_TRACE_LEVEL(info.cmd_flags) <= gpu_trace_level_) {
3615 doing_gpu_trace = true;
3616 gpu_tracer_->Begin(GetCommandName(command), kTraceDecoder);
3620 uint32 immediate_data_size =
3621 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
3623 #define GLES2_CMD_OP(name) \
3624 case cmds::name::kCmdId: \
3625 result = Handle ## name( \
3626 immediate_data_size, \
3627 *static_cast<const gles2::cmds::name*>(cmd_data)); \
3630 GLES2_COMMAND_LIST(GLES2_CMD_OP)
3634 if (doing_gpu_trace)
3635 gpu_tracer_->End(kTraceDecoder);
3639 while ((error = glGetError()) != GL_NO_ERROR) {
3640 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
3641 << "GL ERROR: " << GLES2Util::GetStringEnum(error) << " : "
3642 << GetCommandName(command);
3643 LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
3647 result = error::kInvalidArguments;
3650 result = DoCommonCommand(command, arg_count, cmd_data);
3652 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
3653 result = current_decoder_error_;
3654 current_decoder_error_ = error::kNoError;
3659 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id) {
3660 buffer_manager()->RemoveBuffer(client_id);
3663 bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
3664 if (GetProgram(client_id)) {
3667 GLuint service_id = glCreateProgram();
3668 if (service_id != 0) {
3669 CreateProgram(client_id, service_id);
3674 bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
3675 if (GetShader(client_id)) {
3678 GLuint service_id = glCreateShader(type);
3679 if (service_id != 0) {
3680 CreateShader(client_id, service_id, type);
3685 void GLES2DecoderImpl::DoFinish() {
3687 ProcessPendingReadPixels();
3688 ProcessPendingQueries();
3691 void GLES2DecoderImpl::DoFlush() {
3693 ProcessPendingQueries();
3696 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
3697 GLuint texture_index = texture_unit - GL_TEXTURE0;
3698 if (texture_index >= state_.texture_units.size()) {
3699 LOCAL_SET_GL_ERROR_INVALID_ENUM(
3700 "glActiveTexture", texture_unit, "texture_unit");
3703 state_.active_texture_unit = texture_index;
3704 glActiveTexture(texture_unit);
3707 void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
3708 Buffer* buffer = NULL;
3709 GLuint service_id = 0;
3710 if (client_id != 0) {
3711 buffer = GetBuffer(client_id);
3713 if (!group_->bind_generates_resource()) {
3714 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
3716 "id not generated by glGenBuffers");
3720 // It's a new id so make a buffer buffer for it.
3721 glGenBuffersARB(1, &service_id);
3722 CreateBuffer(client_id, service_id);
3723 buffer = GetBuffer(client_id);
3724 IdAllocatorInterface* id_allocator =
3725 group_->GetIdAllocator(id_namespaces::kBuffers);
3726 id_allocator->MarkAsUsed(client_id);
3729 LogClientServiceForInfo(buffer, client_id, "glBindBuffer");
3731 if (!buffer_manager()->SetTarget(buffer, target)) {
3733 GL_INVALID_OPERATION,
3734 "glBindBuffer", "buffer bound to more than 1 target");
3737 service_id = buffer->service_id();
3740 case GL_ARRAY_BUFFER:
3741 state_.bound_array_buffer = buffer;
3743 case GL_ELEMENT_ARRAY_BUFFER:
3744 state_.vertex_attrib_manager->SetElementArrayBuffer(buffer);
3747 NOTREACHED(); // Validation should prevent us getting here.
3750 glBindBuffer(target, service_id);
3753 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
3754 bool all_draw_buffers) {
3755 Framebuffer* framebuffer =
3756 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3757 if (!all_draw_buffers || !framebuffer) {
3758 return (GLES2Util::GetChannelsForFormat(
3759 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
3761 return framebuffer->HasAlphaMRT();
3764 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
3765 Framebuffer* framebuffer =
3766 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3768 return framebuffer->HasDepthAttachment();
3770 if (offscreen_target_frame_buffer_.get()) {
3771 return offscreen_target_depth_format_ != 0;
3773 return back_buffer_has_depth_;
3776 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
3777 Framebuffer* framebuffer =
3778 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3780 return framebuffer->HasStencilAttachment();
3782 if (offscreen_target_frame_buffer_.get()) {
3783 return offscreen_target_stencil_format_ != 0 ||
3784 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3786 return back_buffer_has_stencil_;
3789 void GLES2DecoderImpl::ApplyDirtyState() {
3790 if (framebuffer_state_.clear_state_dirty) {
3792 state_.color_mask_red, state_.color_mask_green, state_.color_mask_blue,
3793 state_.color_mask_alpha &&
3794 BoundFramebufferHasColorAttachmentWithAlpha(true));
3795 bool have_depth = BoundFramebufferHasDepthAttachment();
3796 glDepthMask(state_.depth_mask && have_depth);
3797 EnableDisable(GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
3798 bool have_stencil = BoundFramebufferHasStencilAttachment();
3799 glStencilMaskSeparate(
3800 GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
3801 glStencilMaskSeparate(
3802 GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
3804 GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
3805 EnableDisable(GL_CULL_FACE, state_.enable_flags.cull_face);
3806 EnableDisable(GL_SCISSOR_TEST, state_.enable_flags.scissor_test);
3807 EnableDisable(GL_BLEND, state_.enable_flags.blend);
3808 framebuffer_state_.clear_state_dirty = false;
3812 GLuint GLES2DecoderImpl::GetBackbufferServiceId() const {
3813 return (offscreen_target_frame_buffer_.get())
3814 ? offscreen_target_frame_buffer_->id()
3815 : (surface_.get() ? surface_->GetBackingFrameBufferObject() : 0);
3818 void GLES2DecoderImpl::RestoreState(const ContextState* prev_state) const {
3819 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
3820 "context", logger_.GetLogPrefix());
3821 // Restore the Framebuffer first because of bugs in Intel drivers.
3822 // Intel drivers incorrectly clip the viewport settings to
3823 // the size of the current framebuffer object.
3824 RestoreFramebufferBindings();
3825 state_.RestoreState(prev_state);
3828 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
3830 framebuffer_state_.bound_draw_framebuffer.get()
3831 ? framebuffer_state_.bound_draw_framebuffer->service_id()
3832 : GetBackbufferServiceId();
3833 if (!features().chromium_framebuffer_multisample) {
3834 glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
3836 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, service_id);
3837 service_id = framebuffer_state_.bound_read_framebuffer.get()
3838 ? framebuffer_state_.bound_read_framebuffer->service_id()
3839 : GetBackbufferServiceId();
3840 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, service_id);
3845 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
3846 Texture* texture = texture_manager()->GetTextureForServiceId(service_id);
3848 GLenum target = texture->target();
3849 glBindTexture(target, service_id);
3851 target, GL_TEXTURE_WRAP_S, texture->wrap_s());
3853 target, GL_TEXTURE_WRAP_T, texture->wrap_t());
3855 target, GL_TEXTURE_MIN_FILTER, texture->min_filter());
3857 target, GL_TEXTURE_MAG_FILTER, texture->mag_filter());
3858 RestoreTextureUnitBindings(state_.active_texture_unit);
3862 void GLES2DecoderImpl::ClearAllAttributes() const {
3863 for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i) {
3864 if (i != 0) // Never disable attribute 0
3865 glDisableVertexAttribArray(i);
3866 if(features().angle_instanced_arrays)
3867 glVertexAttribDivisorANGLE(i, 0);
3871 void GLES2DecoderImpl::RestoreAllAttributes() const {
3872 for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i)
3873 RestoreAttribute(i);
3876 void GLES2DecoderImpl::OnFboChanged() const {
3877 if (workarounds().restore_scissor_on_fbo_change)
3878 state_.fbo_binding_for_scissor_workaround_dirty_ = true;
3881 // Called after the FBO is checked for completeness.
3882 void GLES2DecoderImpl::OnUseFramebuffer() const {
3883 if (state_.fbo_binding_for_scissor_workaround_dirty_) {
3884 state_.fbo_binding_for_scissor_workaround_dirty_ = false;
3885 // The driver forgets the correct scissor when modifying the FBO binding.
3886 glScissor(state_.scissor_x,
3888 state_.scissor_width,
3889 state_.scissor_height);
3891 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
3892 // it's unclear how this bug works.
3897 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
3898 Framebuffer* framebuffer = NULL;
3899 GLuint service_id = 0;
3900 if (client_id != 0) {
3901 framebuffer = GetFramebuffer(client_id);
3903 if (!group_->bind_generates_resource()) {
3904 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
3905 "glBindFramebuffer",
3906 "id not generated by glGenFramebuffers");
3910 // It's a new id so make a framebuffer framebuffer for it.
3911 glGenFramebuffersEXT(1, &service_id);
3912 CreateFramebuffer(client_id, service_id);
3913 framebuffer = GetFramebuffer(client_id);
3914 IdAllocatorInterface* id_allocator =
3915 group_->GetIdAllocator(id_namespaces::kFramebuffers);
3916 id_allocator->MarkAsUsed(client_id);
3918 service_id = framebuffer->service_id();
3920 framebuffer->MarkAsValid();
3922 LogClientServiceForInfo(framebuffer, client_id, "glBindFramebuffer");
3924 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
3925 framebuffer_state_.bound_draw_framebuffer = framebuffer;
3928 // vmiura: This looks like dup code
3929 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
3930 framebuffer_state_.bound_read_framebuffer = framebuffer;
3933 framebuffer_state_.clear_state_dirty = true;
3935 // If we are rendering to the backbuffer get the FBO id for any simulated
3937 if (framebuffer == NULL) {
3938 service_id = GetBackbufferServiceId();
3941 glBindFramebufferEXT(target, service_id);
3945 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
3946 Renderbuffer* renderbuffer = NULL;
3947 GLuint service_id = 0;
3948 if (client_id != 0) {
3949 renderbuffer = GetRenderbuffer(client_id);
3950 if (!renderbuffer) {
3951 if (!group_->bind_generates_resource()) {
3952 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
3953 "glBindRenderbuffer",
3954 "id not generated by glGenRenderbuffers");
3958 // It's a new id so make a renderbuffer renderbuffer for it.
3959 glGenRenderbuffersEXT(1, &service_id);
3960 CreateRenderbuffer(client_id, service_id);
3961 renderbuffer = GetRenderbuffer(client_id);
3962 IdAllocatorInterface* id_allocator =
3963 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
3964 id_allocator->MarkAsUsed(client_id);
3966 service_id = renderbuffer->service_id();
3968 renderbuffer->MarkAsValid();
3970 LogClientServiceForInfo(renderbuffer, client_id, "glBindRenderbuffer");
3971 state_.bound_renderbuffer = renderbuffer;
3972 glBindRenderbufferEXT(target, service_id);
3975 void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
3976 TextureRef* texture_ref = NULL;
3977 GLuint service_id = 0;
3978 if (client_id != 0) {
3979 texture_ref = GetTexture(client_id);
3981 if (!group_->bind_generates_resource()) {
3982 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
3984 "id not generated by glGenTextures");
3988 // It's a new id so make a texture texture for it.
3989 glGenTextures(1, &service_id);
3990 DCHECK_NE(0u, service_id);
3991 CreateTexture(client_id, service_id);
3992 texture_ref = GetTexture(client_id);
3993 IdAllocatorInterface* id_allocator =
3994 group_->GetIdAllocator(id_namespaces::kTextures);
3995 id_allocator->MarkAsUsed(client_id);
3998 texture_ref = texture_manager()->GetDefaultTextureInfo(target);
4000 Texture* texture = texture_ref->texture();
4002 // Check the texture exists
4003 // Check that we are not trying to bind it to a different target.
4004 if (texture->target() != 0 && texture->target() != target) {
4006 GL_INVALID_OPERATION,
4007 "glBindTexture", "texture bound to more than 1 target.");
4010 LogClientServiceForInfo(texture, client_id, "glBindTexture");
4011 if (texture->target() == 0) {
4012 texture_manager()->SetTarget(texture_ref, target);
4014 glBindTexture(target, texture->service_id());
4016 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4017 unit.bind_target = target;
4020 unit.bound_texture_2d = texture_ref;
4022 case GL_TEXTURE_CUBE_MAP:
4023 unit.bound_texture_cube_map = texture_ref;
4025 case GL_TEXTURE_EXTERNAL_OES:
4026 unit.bound_texture_external_oes = texture_ref;
4028 case GL_TEXTURE_RECTANGLE_ARB:
4029 unit.bound_texture_rectangle_arb = texture_ref;
4032 NOTREACHED(); // Validation should prevent us getting here.
4037 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
4038 if (state_.vertex_attrib_manager->Enable(index, false)) {
4040 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
4041 glDisableVertexAttribArray(index);
4046 "glDisableVertexAttribArray", "index out of range");
4050 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target,
4051 GLsizei numAttachments,
4052 const GLenum* attachments) {
4053 if (!features().ext_discard_framebuffer) {
4054 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4055 "glDiscardFramebufferEXT",
4056 "function not available");
4060 Framebuffer* framebuffer =
4061 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4063 // Validates the attachments. If one of them fails
4064 // the whole command fails.
4065 for (GLsizei i = 0; i < numAttachments; ++i) {
4067 !validators_->attachment.IsValid(attachments[i])) ||
4069 !validators_->backbuffer_attachment.IsValid(attachments[i]))) {
4070 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4071 "glDiscardFramebufferEXT", attachments[i], "attachments");
4076 // Marks each one of them as not cleared
4077 for (GLsizei i = 0; i < numAttachments; ++i) {
4079 framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
4084 switch (attachments[i]) {
4086 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
4089 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
4090 case GL_STENCIL_EXT:
4091 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
4100 // If the default framebuffer is bound but we are still rendering to an
4101 // FBO, translate attachment names that refer to default framebuffer
4102 // channels to corresponding framebuffer attachments.
4103 scoped_ptr<GLenum[]> translated_attachments(new GLenum[numAttachments]);
4104 for (GLsizei i = 0; i < numAttachments; ++i) {
4105 GLenum attachment = attachments[i];
4106 if (!framebuffer && GetBackbufferServiceId()) {
4107 switch (attachment) {
4109 attachment = GL_COLOR_ATTACHMENT0;
4112 attachment = GL_DEPTH_ATTACHMENT;
4114 case GL_STENCIL_EXT:
4115 attachment = GL_STENCIL_ATTACHMENT;
4122 translated_attachments[i] = attachment;
4125 glDiscardFramebufferEXT(target, numAttachments, translated_attachments.get());
4128 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
4129 if (state_.vertex_attrib_manager->Enable(index, true)) {
4130 glEnableVertexAttribArray(index);
4133 GL_INVALID_VALUE, "glEnableVertexAttribArray", "index out of range");
4137 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
4138 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
4141 !texture_manager()->CanGenerateMipmaps(texture_ref)) {
4143 GL_INVALID_OPERATION, "glGenerateMipmap", "Can not generate mips");
4147 if (target == GL_TEXTURE_CUBE_MAP) {
4148 for (int i = 0; i < 6; ++i) {
4149 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
4150 if (!texture_manager()->ClearTextureLevel(this, texture_ref, face, 0)) {
4152 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4157 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 0)) {
4159 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4164 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4165 // Workaround for Mac driver bug. In the large scheme of things setting
4166 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4167 // hit so there's probably no need to make this conditional. The bug appears
4168 // to be that if the filtering mode is set to something that doesn't require
4169 // mipmaps for rendering, or is never set to something other than the default,
4170 // then glGenerateMipmap misbehaves.
4171 if (workarounds().set_texture_filter_before_generating_mipmap) {
4172 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4174 glGenerateMipmapEXT(target);
4175 if (workarounds().set_texture_filter_before_generating_mipmap) {
4176 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
4177 texture_ref->texture()->min_filter());
4179 GLenum error = LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4180 if (error == GL_NO_ERROR) {
4181 texture_manager()->MarkMipmapsGenerated(texture_ref);
4185 bool GLES2DecoderImpl::GetHelper(
4186 GLenum pname, GLint* params, GLsizei* num_written) {
4187 DCHECK(num_written);
4188 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
4190 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
4192 // Return the GL implementation's preferred format and (see below type)
4193 // if we have the GL extension that exposes this. This allows the GPU
4194 // client to use the implementation's preferred format for glReadPixels
4195 // for optimisation.
4197 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4198 // case when requested on integer/floating point buffers but which is
4199 // acceptable on GLES2 and with the GL_OES_read_format extension.
4201 // Therefore if an error occurs we swallow the error and use the
4202 // internal implementation.
4204 if (context_->HasExtension("GL_OES_read_format")) {
4205 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4207 glGetIntegerv(pname, params);
4208 if (glGetError() == GL_NO_ERROR)
4211 *params = GLES2Util::GetPreferredGLReadPixelsFormat(
4212 GetBoundReadFrameBufferInternalFormat());
4215 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
4218 if (context_->HasExtension("GL_OES_read_format")) {
4219 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4221 glGetIntegerv(pname, params);
4222 if (glGetError() == GL_NO_ERROR)
4225 *params = GLES2Util::GetPreferredGLReadPixelsType(
4226 GetBoundReadFrameBufferInternalFormat(),
4227 GetBoundReadFrameBufferTextureType());
4230 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
4233 *params = group_->max_fragment_uniform_vectors();
4236 case GL_MAX_VARYING_VECTORS:
4239 *params = group_->max_varying_vectors();
4242 case GL_MAX_VERTEX_UNIFORM_VECTORS:
4245 *params = group_->max_vertex_uniform_vectors();
4251 case GL_MAX_VIEWPORT_DIMS:
4252 if (offscreen_target_frame_buffer_.get()) {
4255 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4256 params[1] = renderbuffer_manager()->max_renderbuffer_size();
4261 case GL_MAX_SAMPLES:
4264 params[0] = renderbuffer_manager()->max_samples();
4267 case GL_MAX_RENDERBUFFER_SIZE:
4270 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4273 case GL_MAX_TEXTURE_SIZE:
4276 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
4279 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
4282 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
4285 case GL_MAX_COLOR_ATTACHMENTS_EXT:
4288 params[0] = group_->max_color_attachments();
4291 case GL_MAX_DRAW_BUFFERS_ARB:
4294 params[0] = group_->max_draw_buffers();
4301 glGetIntegerv(GL_ALPHA_BITS, &v);
4302 params[0] = BoundFramebufferHasColorAttachmentWithAlpha(false) ? v : 0;
4309 glGetIntegerv(GL_DEPTH_BITS, &v);
4310 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
4313 case GL_STENCIL_BITS:
4317 glGetIntegerv(GL_STENCIL_BITS, &v);
4318 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
4321 case GL_COMPRESSED_TEXTURE_FORMATS:
4322 *num_written = validators_->compressed_texture_format.GetValues().size();
4324 for (GLint ii = 0; ii < *num_written; ++ii) {
4325 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
4329 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
4332 *params = validators_->compressed_texture_format.GetValues().size();
4335 case GL_NUM_SHADER_BINARY_FORMATS:
4338 *params = validators_->shader_binary_format.GetValues().size();
4341 case GL_SHADER_BINARY_FORMATS:
4342 *num_written = validators_->shader_binary_format.GetValues().size();
4344 for (GLint ii = 0; ii < *num_written; ++ii) {
4345 params[ii] = validators_->shader_binary_format.GetValues()[ii];
4349 case GL_SHADER_COMPILER:
4355 case GL_ARRAY_BUFFER_BINDING:
4358 if (state_.bound_array_buffer.get()) {
4359 GLuint client_id = 0;
4360 buffer_manager()->GetClientId(state_.bound_array_buffer->service_id(),
4362 *params = client_id;
4368 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
4371 if (state_.vertex_attrib_manager->element_array_buffer()) {
4372 GLuint client_id = 0;
4373 buffer_manager()->GetClientId(
4374 state_.vertex_attrib_manager->element_array_buffer()->
4375 service_id(), &client_id);
4376 *params = client_id;
4382 case GL_FRAMEBUFFER_BINDING:
4383 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
4386 Framebuffer* framebuffer =
4387 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4389 GLuint client_id = 0;
4390 framebuffer_manager()->GetClientId(
4391 framebuffer->service_id(), &client_id);
4392 *params = client_id;
4398 case GL_READ_FRAMEBUFFER_BINDING_EXT:
4401 Framebuffer* framebuffer =
4402 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
4404 GLuint client_id = 0;
4405 framebuffer_manager()->GetClientId(
4406 framebuffer->service_id(), &client_id);
4407 *params = client_id;
4413 case GL_RENDERBUFFER_BINDING:
4416 Renderbuffer* renderbuffer =
4417 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4419 *params = renderbuffer->client_id();
4425 case GL_CURRENT_PROGRAM:
4428 if (state_.current_program.get()) {
4429 GLuint client_id = 0;
4430 program_manager()->GetClientId(
4431 state_.current_program->service_id(), &client_id);
4432 *params = client_id;
4438 case GL_VERTEX_ARRAY_BINDING_OES:
4441 if (state_.vertex_attrib_manager.get() !=
4442 default_vertex_attrib_manager_.get()) {
4443 GLuint client_id = 0;
4444 vertex_array_manager_->GetClientId(
4445 state_.vertex_attrib_manager->service_id(), &client_id);
4446 *params = client_id;
4452 case GL_TEXTURE_BINDING_2D:
4455 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4456 if (unit.bound_texture_2d.get()) {
4457 *params = unit.bound_texture_2d->client_id();
4463 case GL_TEXTURE_BINDING_CUBE_MAP:
4466 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4467 if (unit.bound_texture_cube_map.get()) {
4468 *params = unit.bound_texture_cube_map->client_id();
4474 case GL_TEXTURE_BINDING_EXTERNAL_OES:
4477 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4478 if (unit.bound_texture_external_oes.get()) {
4479 *params = unit.bound_texture_external_oes->client_id();
4485 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
4488 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4489 if (unit.bound_texture_rectangle_arb.get()) {
4490 *params = unit.bound_texture_rectangle_arb->client_id();
4496 case GL_UNPACK_FLIP_Y_CHROMIUM:
4499 params[0] = unpack_flip_y_;
4502 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
4505 params[0] = unpack_premultiply_alpha_;
4508 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
4511 params[0] = unpack_unpremultiply_alpha_;
4514 #if defined(OS_CHROMEOS)
4515 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
4518 params[0] = group_->bind_generates_resource() ? 1 : 0;
4523 if (pname >= GL_DRAW_BUFFER0_ARB &&
4524 pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
4527 Framebuffer* framebuffer =
4528 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4530 params[0] = framebuffer->GetDrawBuffer(pname);
4531 } else { // backbuffer
4532 if (pname == GL_DRAW_BUFFER0_ARB)
4533 params[0] = group_->draw_buffer();
4535 params[0] = GL_NONE;
4540 *num_written = util_.GLGetNumValuesReturned(pname);
4545 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
4546 GLenum pname, GLsizei* num_values) {
4547 if (state_.GetStateAsGLint(pname, NULL, num_values)) {
4550 return GetHelper(pname, NULL, num_values);
4553 GLenum GLES2DecoderImpl::AdjustGetPname(GLenum pname) {
4554 if (GL_MAX_SAMPLES == pname &&
4555 features().use_img_for_multisampled_render_to_texture) {
4556 return GL_MAX_SAMPLES_IMG;
4561 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
4563 GLsizei num_written = 0;
4564 if (GetNumValuesReturnedForGLGet(pname, &num_written)) {
4565 scoped_ptr<GLint[]> values(new GLint[num_written]);
4566 if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) {
4567 GetHelper(pname, values.get(), &num_written);
4569 for (GLsizei ii = 0; ii < num_written; ++ii) {
4570 params[ii] = static_cast<GLboolean>(values[ii]);
4573 pname = AdjustGetPname(pname);
4574 glGetBooleanv(pname, params);
4578 void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
4580 GLsizei num_written = 0;
4581 if (!state_.GetStateAsGLfloat(pname, params, &num_written)) {
4582 if (GetHelper(pname, NULL, &num_written)) {
4583 scoped_ptr<GLint[]> values(new GLint[num_written]);
4584 GetHelper(pname, values.get(), &num_written);
4585 for (GLsizei ii = 0; ii < num_written; ++ii) {
4586 params[ii] = static_cast<GLfloat>(values[ii]);
4589 pname = AdjustGetPname(pname);
4590 glGetFloatv(pname, params);
4595 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
4597 GLsizei num_written;
4598 if (!state_.GetStateAsGLint(pname, params, &num_written) &&
4599 !GetHelper(pname, params, &num_written)) {
4600 pname = AdjustGetPname(pname);
4601 glGetIntegerv(pname, params);
4605 void GLES2DecoderImpl::DoGetProgramiv(
4606 GLuint program_id, GLenum pname, GLint* params) {
4607 Program* program = GetProgramInfoNotShader(program_id, "glGetProgramiv");
4611 program->GetProgramiv(pname, params);
4614 void GLES2DecoderImpl::DoGetBufferParameteriv(
4615 GLenum target, GLenum pname, GLint* params) {
4616 // Just delegate it. Some validation is actually done before this.
4617 buffer_manager()->ValidateAndDoGetBufferParameteriv(
4618 &state_, target, pname, params);
4621 void GLES2DecoderImpl::DoBindAttribLocation(
4622 GLuint program_id, GLuint index, const char* name) {
4623 if (!StringIsValidForGLES(name)) {
4625 GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
4628 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
4630 GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
4633 if (index >= group_->max_vertex_attribs()) {
4635 GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
4638 Program* program = GetProgramInfoNotShader(
4639 program_id, "glBindAttribLocation");
4643 program->SetAttribLocationBinding(name, static_cast<GLint>(index));
4644 glBindAttribLocation(program->service_id(), index, name);
4647 error::Error GLES2DecoderImpl::HandleBindAttribLocation(
4648 uint32 immediate_data_size, const cmds::BindAttribLocation& c) {
4649 GLuint program = static_cast<GLuint>(c.program);
4650 GLuint index = static_cast<GLuint>(c.index);
4651 uint32 name_size = c.data_size;
4652 const char* name = GetSharedMemoryAs<const char*>(
4653 c.name_shm_id, c.name_shm_offset, name_size);
4655 return error::kOutOfBounds;
4657 String name_str(name, name_size);
4658 DoBindAttribLocation(program, index, name_str.c_str());
4659 return error::kNoError;
4662 error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
4663 uint32 immediate_data_size, const cmds::BindAttribLocationBucket& c) {
4664 GLuint program = static_cast<GLuint>(c.program);
4665 GLuint index = static_cast<GLuint>(c.index);
4666 Bucket* bucket = GetBucket(c.name_bucket_id);
4667 if (!bucket || bucket->size() == 0) {
4668 return error::kInvalidArguments;
4670 std::string name_str;
4671 if (!bucket->GetAsString(&name_str)) {
4672 return error::kInvalidArguments;
4674 DoBindAttribLocation(program, index, name_str.c_str());
4675 return error::kNoError;
4678 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
4679 GLuint program_id, GLint location, const char* name) {
4680 if (!StringIsValidForGLES(name)) {
4683 "glBindUniformLocationCHROMIUM", "Invalid character");
4686 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
4688 GL_INVALID_OPERATION,
4689 "glBindUniformLocationCHROMIUM", "reserved prefix");
4692 if (location < 0 || static_cast<uint32>(location) >=
4693 (group_->max_fragment_uniform_vectors() +
4694 group_->max_vertex_uniform_vectors()) * 4) {
4697 "glBindUniformLocationCHROMIUM", "location out of range");
4700 Program* program = GetProgramInfoNotShader(
4701 program_id, "glBindUniformLocationCHROMIUM");
4705 if (!program->SetUniformLocationBinding(name, location)) {
4708 "glBindUniformLocationCHROMIUM", "location out of range");
4712 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUM(
4713 uint32 immediate_data_size, const cmds::BindUniformLocationCHROMIUM& c) {
4714 GLuint program = static_cast<GLuint>(c.program);
4715 GLint location = static_cast<GLint>(c.location);
4716 uint32 name_size = c.data_size;
4717 const char* name = GetSharedMemoryAs<const char*>(
4718 c.name_shm_id, c.name_shm_offset, name_size);
4720 return error::kOutOfBounds;
4722 String name_str(name, name_size);
4723 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4724 return error::kNoError;
4727 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
4728 uint32 immediate_data_size,
4729 const cmds::BindUniformLocationCHROMIUMBucket& c) {
4730 GLuint program = static_cast<GLuint>(c.program);
4731 GLint location = static_cast<GLint>(c.location);
4732 Bucket* bucket = GetBucket(c.name_bucket_id);
4733 if (!bucket || bucket->size() == 0) {
4734 return error::kInvalidArguments;
4736 std::string name_str;
4737 if (!bucket->GetAsString(&name_str)) {
4738 return error::kInvalidArguments;
4740 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4741 return error::kNoError;
4744 error::Error GLES2DecoderImpl::HandleDeleteShader(
4745 uint32 immediate_data_size, const cmds::DeleteShader& c) {
4746 GLuint client_id = c.shader;
4748 Shader* shader = GetShader(client_id);
4750 if (!shader->IsDeleted()) {
4751 glDeleteShader(shader->service_id());
4752 shader_manager()->MarkAsDeleted(shader);
4755 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
4758 return error::kNoError;
4761 error::Error GLES2DecoderImpl::HandleDeleteProgram(
4762 uint32 immediate_data_size, const cmds::DeleteProgram& c) {
4763 GLuint client_id = c.program;
4765 Program* program = GetProgram(client_id);
4767 if (!program->IsDeleted()) {
4768 program_manager()->MarkAsDeleted(shader_manager(), program);
4772 GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
4775 return error::kNoError;
4778 void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
4779 GLuint namespace_id, GLsizei n, const GLuint* ids) {
4780 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4781 for (GLsizei ii = 0; ii < n; ++ii) {
4782 id_allocator->FreeID(ids[ii]);
4786 error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
4787 uint32 immediate_data_size, const cmds::DeleteSharedIdsCHROMIUM& c) {
4788 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4789 GLsizei n = static_cast<GLsizei>(c.n);
4791 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4792 return error::kOutOfBounds;
4794 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
4795 c.ids_shm_id, c.ids_shm_offset, data_size);
4797 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM", "n < 0");
4798 return error::kNoError;
4801 return error::kOutOfBounds;
4803 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
4804 return error::kNoError;
4807 void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
4808 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
4809 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4810 if (id_offset == 0) {
4811 for (GLsizei ii = 0; ii < n; ++ii) {
4812 ids[ii] = id_allocator->AllocateID();
4815 for (GLsizei ii = 0; ii < n; ++ii) {
4816 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
4817 id_offset = ids[ii] + 1;
4822 error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
4823 uint32 immediate_data_size, const cmds::GenSharedIdsCHROMIUM& c) {
4824 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4825 GLuint id_offset = static_cast<GLuint>(c.id_offset);
4826 GLsizei n = static_cast<GLsizei>(c.n);
4828 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4829 return error::kOutOfBounds;
4831 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4832 c.ids_shm_id, c.ids_shm_offset, data_size);
4834 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM", "n < 0");
4835 return error::kNoError;
4838 return error::kOutOfBounds;
4840 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
4841 return error::kNoError;
4844 void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
4845 GLuint namespace_id, GLsizei n, const GLuint* ids) {
4846 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4847 for (GLsizei ii = 0; ii < n; ++ii) {
4848 if (!id_allocator->MarkAsUsed(ids[ii])) {
4849 for (GLsizei jj = 0; jj < ii; ++jj) {
4850 id_allocator->FreeID(ids[jj]);
4853 GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM",
4854 "attempt to register id that already exists");
4860 error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
4861 uint32 immediate_data_size, const cmds::RegisterSharedIdsCHROMIUM& c) {
4862 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4863 GLsizei n = static_cast<GLsizei>(c.n);
4865 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4866 return error::kOutOfBounds;
4868 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4869 c.ids_shm_id, c.ids_shm_offset, data_size);
4871 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM", "n < 0");
4872 return error::kNoError;
4875 return error::kOutOfBounds;
4877 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
4878 return error::kNoError;
4881 error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
4882 DCHECK(!ShouldDeferDraws());
4883 if (CheckBoundFramebuffersValid("glClear")) {
4887 return error::kNoError;
4890 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
4891 GLenum target, GLenum attachment, GLenum renderbuffertarget,
4892 GLuint client_renderbuffer_id) {
4893 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
4896 GL_INVALID_OPERATION,
4897 "glFramebufferRenderbuffer", "no framebuffer bound");
4900 GLuint service_id = 0;
4901 Renderbuffer* renderbuffer = NULL;
4902 if (client_renderbuffer_id) {
4903 renderbuffer = GetRenderbuffer(client_renderbuffer_id);
4904 if (!renderbuffer) {
4906 GL_INVALID_OPERATION,
4907 "glFramebufferRenderbuffer", "unknown renderbuffer");
4910 service_id = renderbuffer->service_id();
4912 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
4913 glFramebufferRenderbufferEXT(
4914 target, attachment, renderbuffertarget, service_id);
4915 GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
4916 if (error == GL_NO_ERROR) {
4917 framebuffer->AttachRenderbuffer(attachment, renderbuffer);
4919 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
4920 framebuffer_state_.clear_state_dirty = true;
4925 void GLES2DecoderImpl::DoDisable(GLenum cap) {
4926 if (SetCapabilityState(cap, false)) {
4931 void GLES2DecoderImpl::DoEnable(GLenum cap) {
4932 if (SetCapabilityState(cap, true)) {
4937 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear, GLclampf zfar) {
4938 state_.z_near = std::min(1.0f, std::max(0.0f, znear));
4939 state_.z_far = std::min(1.0f, std::max(0.0f, zfar));
4940 glDepthRange(znear, zfar);
4943 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value, GLboolean invert) {
4944 state_.sample_coverage_value = std::min(1.0f, std::max(0.0f, value));
4945 state_.sample_coverage_invert = (invert != 0);
4946 glSampleCoverage(state_.sample_coverage_value, invert);
4949 // Assumes framebuffer is complete.
4950 void GLES2DecoderImpl::ClearUnclearedAttachments(
4951 GLenum target, Framebuffer* framebuffer) {
4952 if (target == GL_READ_FRAMEBUFFER_EXT) {
4953 // bind this to the DRAW point, clear then bind back to READ
4954 // TODO(gman): I don't think there is any guarantee that an FBO that
4955 // is complete on the READ attachment will be complete as a DRAW
4957 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
4958 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer->service_id());
4960 GLbitfield clear_bits = 0;
4961 if (framebuffer->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
4964 (GLES2Util::GetChannelsForFormat(
4965 framebuffer->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f :
4967 glColorMask(true, true, true, true);
4968 clear_bits |= GL_COLOR_BUFFER_BIT;
4971 if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
4972 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
4975 clear_bits |= GL_STENCIL_BUFFER_BIT;
4978 if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
4979 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
4982 clear_bits |= GL_DEPTH_BUFFER_BIT;
4985 glDisable(GL_SCISSOR_TEST);
4986 glClear(clear_bits);
4988 framebuffer_manager()->MarkAttachmentsAsCleared(
4989 framebuffer, renderbuffer_manager(), texture_manager());
4991 RestoreClearState();
4993 if (target == GL_READ_FRAMEBUFFER_EXT) {
4994 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer->service_id());
4995 Framebuffer* draw_framebuffer =
4996 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4997 GLuint service_id = draw_framebuffer ? draw_framebuffer->service_id() :
4998 GetBackbufferServiceId();
4999 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
5003 void GLES2DecoderImpl::RestoreClearState() {
5004 framebuffer_state_.clear_state_dirty = true;
5006 state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
5007 state_.color_clear_alpha);
5008 glClearStencil(state_.stencil_clear);
5009 glClearDepth(state_.depth_clear);
5010 if (state_.enable_flags.scissor_test) {
5011 glEnable(GL_SCISSOR_TEST);
5015 GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
5016 Framebuffer* framebuffer =
5017 GetFramebufferInfoForTarget(target);
5019 return GL_FRAMEBUFFER_COMPLETE;
5021 GLenum completeness = framebuffer->IsPossiblyComplete();
5022 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
5023 return completeness;
5025 return framebuffer->GetStatus(texture_manager(), target);
5028 void GLES2DecoderImpl::DoFramebufferTexture2D(
5029 GLenum target, GLenum attachment, GLenum textarget,
5030 GLuint client_texture_id, GLint level) {
5031 DoFramebufferTexture2DCommon(
5032 "glFramebufferTexture2D", target, attachment,
5033 textarget, client_texture_id, level, 0);
5036 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5037 GLenum target, GLenum attachment, GLenum textarget,
5038 GLuint client_texture_id, GLint level, GLsizei samples) {
5039 if (!features().multisampled_render_to_texture) {
5041 GL_INVALID_OPERATION,
5042 "glFramebufferTexture2DMultisample", "function not available");
5045 DoFramebufferTexture2DCommon(
5046 "glFramebufferTexture2DMultisample", target, attachment,
5047 textarget, client_texture_id, level, samples);
5050 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5051 const char* name, GLenum target, GLenum attachment, GLenum textarget,
5052 GLuint client_texture_id, GLint level, GLsizei samples) {
5053 if (samples > renderbuffer_manager()->max_samples()) {
5056 "glFramebufferTexture2DMultisample", "samples too large");
5059 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5062 GL_INVALID_OPERATION,
5063 name, "no framebuffer bound.");
5066 GLuint service_id = 0;
5067 TextureRef* texture_ref = NULL;
5068 if (client_texture_id) {
5069 texture_ref = GetTexture(client_texture_id);
5072 GL_INVALID_OPERATION,
5073 name, "unknown texture_ref");
5076 service_id = texture_ref->service_id();
5079 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
5082 name, "level out of range");
5087 DoWillUseTexImageIfNeeded(texture_ref->texture(), textarget);
5089 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name);
5091 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
5093 if (features().use_img_for_multisampled_render_to_texture) {
5094 glFramebufferTexture2DMultisampleIMG(target, attachment, textarget,
5095 service_id, level, samples);
5097 glFramebufferTexture2DMultisampleEXT(target, attachment, textarget,
5098 service_id, level, samples);
5101 GLenum error = LOCAL_PEEK_GL_ERROR(name);
5102 if (error == GL_NO_ERROR) {
5103 framebuffer->AttachTexture(attachment, texture_ref, textarget, level,
5106 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5107 framebuffer_state_.clear_state_dirty = true;
5111 DoDidUseTexImageIfNeeded(texture_ref->texture(), textarget);
5116 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5117 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
5118 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5121 GL_INVALID_OPERATION,
5122 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5125 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
5126 const Framebuffer::Attachment* attachment_object =
5127 framebuffer->GetAttachment(attachment);
5128 *params = attachment_object ? attachment_object->object_name() : 0;
5130 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT &&
5131 features().use_img_for_multisampled_render_to_texture) {
5132 pname = GL_TEXTURE_SAMPLES_IMG;
5134 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
5138 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5139 GLenum target, GLenum pname, GLint* params) {
5140 Renderbuffer* renderbuffer =
5141 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5142 if (!renderbuffer) {
5144 GL_INVALID_OPERATION,
5145 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5149 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5150 *params = renderbuffer->internal_format();
5152 case GL_RENDERBUFFER_WIDTH:
5153 *params = renderbuffer->width();
5155 case GL_RENDERBUFFER_HEIGHT:
5156 *params = renderbuffer->height();
5158 case GL_RENDERBUFFER_SAMPLES_EXT:
5159 if (features().use_img_for_multisampled_render_to_texture) {
5160 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_IMG,
5163 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_EXT,
5167 glGetRenderbufferParameterivEXT(target, pname, params);
5172 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5173 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
5174 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5175 GLbitfield mask, GLenum filter) {
5176 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5177 if (!features().chromium_framebuffer_multisample) {
5179 GL_INVALID_OPERATION,
5180 "glBlitFramebufferCHROMIUM", "function not available");
5184 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5188 glDisable(GL_SCISSOR_TEST);
5189 BlitFramebufferHelper(
5190 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5191 EnableDisable(GL_SCISSOR_TEST, state_.enable_flags.scissor_test);
5194 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
5195 const FeatureInfo* feature_info,
5198 GLenum internal_format,
5201 // TODO(sievers): This could be resolved at the GL binding level, but the
5202 // binding process is currently a bit too 'brute force'.
5203 if (feature_info->feature_flags().is_angle) {
5204 glRenderbufferStorageMultisampleANGLE(
5205 target, samples, internal_format, width, height);
5206 } else if (feature_info->feature_flags().use_core_framebuffer_multisample) {
5207 glRenderbufferStorageMultisample(
5208 target, samples, internal_format, width, height);
5210 glRenderbufferStorageMultisampleEXT(
5211 target, samples, internal_format, width, height);
5215 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0,
5225 // TODO(sievers): This could be resolved at the GL binding level, but the
5226 // binding process is currently a bit too 'brute force'.
5227 if (feature_info_->feature_flags().is_angle) {
5228 glBlitFramebufferANGLE(
5229 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5230 } else if (feature_info_->feature_flags().use_core_framebuffer_multisample) {
5232 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5234 glBlitFramebufferEXT(
5235 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5239 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
5241 GLenum internalformat,
5244 if (samples > renderbuffer_manager()->max_samples()) {
5247 "glRenderbufferStorageMultisample", "samples too large");
5251 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5252 height > renderbuffer_manager()->max_renderbuffer_size()) {
5255 "glRenderbufferStorageMultisample", "dimensions too large");
5259 uint32 estimated_size = 0;
5260 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5261 width, height, samples, internalformat, &estimated_size)) {
5264 "glRenderbufferStorageMultisample", "dimensions too large");
5268 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5271 "glRenderbufferStorageMultisample", "out of memory");
5278 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
5279 GLenum target, GLsizei samples, GLenum internalformat,
5280 GLsizei width, GLsizei height) {
5281 if (!features().chromium_framebuffer_multisample) {
5282 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5283 "glRenderbufferStorageMultisampleCHROMIUM",
5284 "function not available");
5288 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5289 if (!renderbuffer) {
5290 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5291 "glRenderbufferStorageMultisampleCHROMIUM",
5292 "no renderbuffer bound");
5296 if (!ValidateRenderbufferStorageMultisample(
5297 samples, internalformat, width, height)) {
5301 GLenum impl_format =
5302 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5304 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
5305 "glRenderbufferStorageMultisampleCHROMIUM");
5306 RenderbufferStorageMultisampleHelper(
5307 feature_info_, target, samples, impl_format, width, height);
5309 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
5310 if (error == GL_NO_ERROR) {
5312 if (workarounds().validate_multisample_buffer_allocation) {
5313 if (!VerifyMultisampleRenderbufferIntegrity(
5314 renderbuffer->service_id(), impl_format)) {
5317 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
5322 // TODO(gman): If renderbuffers tracked which framebuffers they were
5323 // attached to we could just mark those framebuffers as not complete.
5324 framebuffer_manager()->IncFramebufferStateChangeCount();
5325 renderbuffer_manager()->SetInfo(
5326 renderbuffer, samples, internalformat, width, height);
5330 // This is the handler for multisampled_render_to_texture extensions.
5331 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
5332 GLenum target, GLsizei samples, GLenum internalformat,
5333 GLsizei width, GLsizei height) {
5334 if (!features().multisampled_render_to_texture) {
5336 GL_INVALID_OPERATION,
5337 "glRenderbufferStorageMultisampleEXT", "function not available");
5341 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5342 if (!renderbuffer) {
5343 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5344 "glRenderbufferStorageMultisampleEXT",
5345 "no renderbuffer bound");
5349 if (!ValidateRenderbufferStorageMultisample(
5350 samples, internalformat, width, height)) {
5354 GLenum impl_format =
5355 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5357 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
5358 if (features().use_img_for_multisampled_render_to_texture) {
5359 glRenderbufferStorageMultisampleIMG(
5360 target, samples, impl_format, width, height);
5362 glRenderbufferStorageMultisampleEXT(
5363 target, samples, impl_format, width, height);
5365 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
5366 if (error == GL_NO_ERROR) {
5367 // TODO(gman): If renderbuffers tracked which framebuffers they were
5368 // attached to we could just mark those framebuffers as not complete.
5369 framebuffer_manager()->IncFramebufferStateChangeCount();
5370 renderbuffer_manager()->SetInfo(
5371 renderbuffer, samples, internalformat, width, height);
5375 // This function validates the allocation of a multisampled renderbuffer
5376 // by clearing it to a key color, blitting the contents to a texture, and
5377 // reading back the color to ensure it matches the key.
5378 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
5379 GLuint renderbuffer, GLenum format) {
5381 // Only validate color buffers.
5382 // These formats have been selected because they are very common or are known
5383 // to be used by the WebGL backbuffer. If problems are observed with other
5384 // color formats they can be added here.
5395 GLint draw_framebuffer, read_framebuffer;
5397 // Cache framebuffer and texture bindings.
5398 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer);
5399 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
5401 if (!validation_texture_) {
5402 GLint bound_texture;
5403 glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture);
5405 // Create additional resources needed for the verification.
5406 glGenTextures(1, &validation_texture_);
5407 glGenFramebuffersEXT(1, &validation_fbo_multisample_);
5408 glGenFramebuffersEXT(1, &validation_fbo_);
5410 // Texture only needs to be 1x1.
5411 glBindTexture(GL_TEXTURE_2D, validation_texture_);
5412 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB,
5413 GL_UNSIGNED_BYTE, NULL);
5415 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5416 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5417 GL_TEXTURE_2D, validation_texture_, 0);
5419 glBindTexture(GL_TEXTURE_2D, bound_texture);
5422 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5423 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5424 GL_RENDERBUFFER, renderbuffer);
5426 // Cache current state and reset it to the values we require.
5427 GLboolean scissor_enabled = false;
5428 glGetBooleanv(GL_SCISSOR_TEST, &scissor_enabled);
5429 if (scissor_enabled)
5430 glDisable(GL_SCISSOR_TEST);
5432 GLboolean color_mask[4] = {true, true, true, true};
5433 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
5434 glColorMask(true, true, true, true);
5436 GLfloat clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
5437 glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color);
5438 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
5440 // Clear the buffer to the desired key color.
5441 glClear(GL_COLOR_BUFFER_BIT);
5443 // Blit from the multisample buffer to a standard texture.
5444 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, validation_fbo_multisample_);
5445 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, validation_fbo_);
5447 BlitFramebufferHelper(
5448 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
5450 // Read a pixel from the buffer.
5451 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5453 unsigned char pixel[3] = {0, 0, 0};
5454 glReadPixels(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel);
5456 // Detach the renderbuffer.
5457 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5458 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5459 GL_RENDERBUFFER, 0);
5461 // Restore cached state.
5462 if (scissor_enabled)
5463 glEnable(GL_SCISSOR_TEST);
5465 glColorMask(color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
5466 glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
5467 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, draw_framebuffer);
5468 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_framebuffer);
5470 // Return true if the pixel matched the desired key color.
5471 return (pixel[0] == 0xFF &&
5476 void GLES2DecoderImpl::DoRenderbufferStorage(
5477 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
5478 Renderbuffer* renderbuffer =
5479 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5480 if (!renderbuffer) {
5482 GL_INVALID_OPERATION,
5483 "glRenderbufferStorage", "no renderbuffer bound");
5487 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5488 height > renderbuffer_manager()->max_renderbuffer_size()) {
5490 GL_INVALID_VALUE, "glRenderbufferStorage", "dimensions too large");
5494 uint32 estimated_size = 0;
5495 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5496 width, height, 1, internalformat, &estimated_size)) {
5498 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "dimensions too large");
5502 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5504 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "out of memory");
5508 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
5509 glRenderbufferStorageEXT(
5511 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5515 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
5516 if (error == GL_NO_ERROR) {
5517 // TODO(gman): If tetxures tracked which framebuffers they were attached to
5518 // we could just mark those framebuffers as not complete.
5519 framebuffer_manager()->IncFramebufferStateChangeCount();
5520 renderbuffer_manager()->SetInfo(
5521 renderbuffer, 1, internalformat, width, height);
5525 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
5526 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
5527 Program* program = GetProgramInfoNotShader(
5528 program_id, "glLinkProgram");
5533 LogClientServiceForInfo(program, program_id, "glLinkProgram");
5534 ShaderTranslator* vertex_translator = NULL;
5535 ShaderTranslator* fragment_translator = NULL;
5536 if (use_shader_translator_) {
5537 vertex_translator = vertex_translator_.get();
5538 fragment_translator = fragment_translator_.get();
5540 if (program->Link(shader_manager(),
5542 fragment_translator,
5543 workarounds().count_all_in_varyings_packing ?
5544 Program::kCountAll : Program::kCountOnlyStaticallyUsed,
5545 shader_cache_callback_)) {
5546 if (program == state_.current_program.get()) {
5547 if (workarounds().use_current_program_after_successful_link)
5548 glUseProgram(program->service_id());
5549 if (workarounds().clear_uniforms_before_first_program_use)
5550 program_manager()->ClearUniforms(program);
5555 void GLES2DecoderImpl::DoTexParameterf(
5556 GLenum target, GLenum pname, GLfloat param) {
5557 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5560 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
5564 texture_manager()->SetParameterf(
5565 "glTexParameterf", GetErrorState(), texture, pname, param);
5568 void GLES2DecoderImpl::DoTexParameteri(
5569 GLenum target, GLenum pname, GLint param) {
5570 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5573 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
5577 texture_manager()->SetParameteri(
5578 "glTexParameteri", GetErrorState(), texture, pname, param);
5581 void GLES2DecoderImpl::DoTexParameterfv(
5582 GLenum target, GLenum pname, const GLfloat* params) {
5583 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5586 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
5590 texture_manager()->SetParameterf(
5591 "glTexParameterfv", GetErrorState(), texture, pname, *params);
5594 void GLES2DecoderImpl::DoTexParameteriv(
5595 GLenum target, GLenum pname, const GLint* params) {
5596 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5600 GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
5604 texture_manager()->SetParameteri(
5605 "glTexParameteriv", GetErrorState(), texture, pname, *params);
5608 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
5609 if (!state_.current_program.get()) {
5610 // The program does not exist.
5612 GL_INVALID_OPERATION, function_name, "no program in use");
5615 if (!state_.current_program->InUse()) {
5617 GL_INVALID_OPERATION, function_name, "program not linked");
5623 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
5624 GLint location, const char* function_name) {
5625 if (!CheckCurrentProgram(function_name)) {
5628 return location != -1;
5631 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
5632 GLint fake_location,
5633 const char* function_name,
5634 Program::UniformApiType api_type,
5635 GLint* real_location,
5640 DCHECK(real_location);
5642 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
5645 GLint array_index = -1;
5646 const Program::UniformInfo* info =
5647 state_.current_program->GetUniformInfoByFakeLocation(
5648 fake_location, real_location, &array_index);
5651 GL_INVALID_OPERATION, function_name, "unknown location");
5655 if ((api_type & info->accepts_api_type) == 0) {
5657 GL_INVALID_OPERATION, function_name,
5658 "wrong uniform function for type");
5661 if (*count > 1 && !info->is_array) {
5663 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
5666 *count = std::min(info->size - array_index, *count);
5674 void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
5677 GLint real_location = -1;
5678 if (!PrepForSetUniformByLocation(fake_location,
5680 Program::kUniform1i,
5686 if (!state_.current_program->SetSamplers(
5687 state_.texture_units.size(), fake_location, 1, &v0)) {
5689 GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
5692 glUniform1i(real_location, v0);
5695 void GLES2DecoderImpl::DoUniform1iv(
5696 GLint fake_location, GLsizei count, const GLint *value) {
5698 GLint real_location = -1;
5699 if (!PrepForSetUniformByLocation(fake_location,
5701 Program::kUniform1i,
5707 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
5708 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
5709 if (!state_.current_program->SetSamplers(
5710 state_.texture_units.size(), fake_location, count, value)) {
5712 GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
5716 glUniform1iv(real_location, count, value);
5719 void GLES2DecoderImpl::DoUniform1fv(
5720 GLint fake_location, GLsizei count, const GLfloat* value) {
5722 GLint real_location = -1;
5723 if (!PrepForSetUniformByLocation(fake_location,
5725 Program::kUniform1f,
5731 if (type == GL_BOOL) {
5732 scoped_ptr<GLint[]> temp(new GLint[count]);
5733 for (GLsizei ii = 0; ii < count; ++ii) {
5734 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5736 DoUniform1iv(real_location, count, temp.get());
5738 glUniform1fv(real_location, count, value);
5742 void GLES2DecoderImpl::DoUniform2fv(
5743 GLint fake_location, GLsizei count, const GLfloat* value) {
5745 GLint real_location = -1;
5746 if (!PrepForSetUniformByLocation(fake_location,
5748 Program::kUniform2f,
5754 if (type == GL_BOOL_VEC2) {
5755 GLsizei num_values = count * 2;
5756 scoped_ptr<GLint[]> temp(new GLint[num_values]);
5757 for (GLsizei ii = 0; ii < num_values; ++ii) {
5758 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5760 glUniform2iv(real_location, count, temp.get());
5762 glUniform2fv(real_location, count, value);
5766 void GLES2DecoderImpl::DoUniform3fv(
5767 GLint fake_location, GLsizei count, const GLfloat* value) {
5769 GLint real_location = -1;
5770 if (!PrepForSetUniformByLocation(fake_location,
5772 Program::kUniform3f,
5778 if (type == GL_BOOL_VEC3) {
5779 GLsizei num_values = count * 3;
5780 scoped_ptr<GLint[]> temp(new GLint[num_values]);
5781 for (GLsizei ii = 0; ii < num_values; ++ii) {
5782 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5784 glUniform3iv(real_location, count, temp.get());
5786 glUniform3fv(real_location, count, value);
5790 void GLES2DecoderImpl::DoUniform4fv(
5791 GLint fake_location, GLsizei count, const GLfloat* value) {
5793 GLint real_location = -1;
5794 if (!PrepForSetUniformByLocation(fake_location,
5796 Program::kUniform4f,
5802 if (type == GL_BOOL_VEC4) {
5803 GLsizei num_values = count * 4;
5804 scoped_ptr<GLint[]> temp(new GLint[num_values]);
5805 for (GLsizei ii = 0; ii < num_values; ++ii) {
5806 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5808 glUniform4iv(real_location, count, temp.get());
5810 glUniform4fv(real_location, count, value);
5814 void GLES2DecoderImpl::DoUniform2iv(
5815 GLint fake_location, GLsizei count, const GLint* value) {
5817 GLint real_location = -1;
5818 if (!PrepForSetUniformByLocation(fake_location,
5820 Program::kUniform2i,
5826 glUniform2iv(real_location, count, value);
5829 void GLES2DecoderImpl::DoUniform3iv(
5830 GLint fake_location, GLsizei count, const GLint* value) {
5832 GLint real_location = -1;
5833 if (!PrepForSetUniformByLocation(fake_location,
5835 Program::kUniform3i,
5841 glUniform3iv(real_location, count, value);
5844 void GLES2DecoderImpl::DoUniform4iv(
5845 GLint fake_location, GLsizei count, const GLint* value) {
5847 GLint real_location = -1;
5848 if (!PrepForSetUniformByLocation(fake_location,
5850 Program::kUniform4i,
5856 glUniform4iv(real_location, count, value);
5859 void GLES2DecoderImpl::DoUniformMatrix2fv(
5860 GLint fake_location, GLsizei count, GLboolean transpose,
5861 const GLfloat* value) {
5863 GLint real_location = -1;
5864 if (!PrepForSetUniformByLocation(fake_location,
5865 "glUniformMatrix2fv",
5866 Program::kUniformMatrix2f,
5872 glUniformMatrix2fv(real_location, count, transpose, value);
5875 void GLES2DecoderImpl::DoUniformMatrix3fv(
5876 GLint fake_location, GLsizei count, GLboolean transpose,
5877 const GLfloat* value) {
5879 GLint real_location = -1;
5880 if (!PrepForSetUniformByLocation(fake_location,
5881 "glUniformMatrix3fv",
5882 Program::kUniformMatrix3f,
5888 glUniformMatrix3fv(real_location, count, transpose, value);
5891 void GLES2DecoderImpl::DoUniformMatrix4fv(
5892 GLint fake_location, GLsizei count, GLboolean transpose,
5893 const GLfloat* value) {
5895 GLint real_location = -1;
5896 if (!PrepForSetUniformByLocation(fake_location,
5897 "glUniformMatrix4fv",
5898 Program::kUniformMatrix4f,
5904 glUniformMatrix4fv(real_location, count, transpose, value);
5907 void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
5908 GLuint service_id = 0;
5909 Program* program = NULL;
5911 program = GetProgramInfoNotShader(program_id, "glUseProgram");
5915 if (!program->IsValid()) {
5916 // Program was not linked successfully. (ie, glLinkProgram)
5918 GL_INVALID_OPERATION, "glUseProgram", "program not linked");
5921 service_id = program->service_id();
5923 if (state_.current_program.get()) {
5924 program_manager()->UnuseProgram(shader_manager(),
5925 state_.current_program.get());
5927 state_.current_program = program;
5928 LogClientServiceMapping("glUseProgram", program_id, service_id);
5929 glUseProgram(service_id);
5930 if (state_.current_program.get()) {
5931 program_manager()->UseProgram(state_.current_program.get());
5932 if (workarounds().clear_uniforms_before_first_program_use)
5933 program_manager()->ClearUniforms(program);
5937 void GLES2DecoderImpl::RenderWarning(
5938 const char* filename, int line, const std::string& msg) {
5939 logger_.LogMessage(filename, line, std::string("RENDER WARNING: ") + msg);
5942 void GLES2DecoderImpl::PerformanceWarning(
5943 const char* filename, int line, const std::string& msg) {
5944 logger_.LogMessage(filename, line,
5945 std::string("PERFORMANCE WARNING: ") + msg);
5948 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
5949 Texture* texture, GLenum textarget) {
5950 // Image is already in use if texture is attached to a framebuffer.
5951 if (texture && !texture->IsAttachedToFramebuffer()) {
5952 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
5954 ScopedGLErrorSuppressor suppressor(
5955 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
5957 glBindTexture(textarget, texture->service_id());
5958 image->WillUseTexImage();
5959 RestoreCurrentTextureBindings(&state_, textarget);
5964 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
5965 Texture* texture, GLenum textarget) {
5966 // Image is still in use if texture is attached to a framebuffer.
5967 if (texture && !texture->IsAttachedToFramebuffer()) {
5968 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
5970 ScopedGLErrorSuppressor suppressor(
5971 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
5973 glBindTexture(textarget, texture->service_id());
5974 image->DidUseTexImage();
5975 RestoreCurrentTextureBindings(&state_, textarget);
5980 bool GLES2DecoderImpl::PrepareTexturesForRender() {
5981 DCHECK(state_.current_program.get());
5982 if (!texture_manager()->HaveUnrenderableTextures() &&
5983 !texture_manager()->HaveImages()) {
5987 bool textures_set = false;
5988 const Program::SamplerIndices& sampler_indices =
5989 state_.current_program->sampler_indices();
5990 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
5991 const Program::UniformInfo* uniform_info =
5992 state_.current_program->GetUniformInfo(sampler_indices[ii]);
5993 DCHECK(uniform_info);
5994 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5995 GLuint texture_unit_index = uniform_info->texture_units[jj];
5996 if (texture_unit_index < state_.texture_units.size()) {
5997 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
5998 TextureRef* texture_ref =
5999 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6000 GLenum textarget = GetBindTargetForSamplerType(uniform_info->type);
6001 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6002 textures_set = true;
6003 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6006 texture_manager()->black_texture_id(uniform_info->type));
6007 LOCAL_RENDER_WARNING(
6008 std::string("texture bound to texture unit ") +
6009 base::IntToString(texture_unit_index) +
6010 " is not renderable. It maybe non-power-of-2 and have"
6011 " incompatible texture filtering or is not"
6012 " 'texture complete'");
6016 if (textarget != GL_TEXTURE_CUBE_MAP) {
6017 Texture* texture = texture_ref->texture();
6018 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6019 if (image && !texture->IsAttachedToFramebuffer()) {
6020 ScopedGLErrorSuppressor suppressor(
6021 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6022 textures_set = true;
6023 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6024 image->WillUseTexImage();
6029 // else: should this be an error?
6032 return !textures_set;
6035 void GLES2DecoderImpl::RestoreStateForTextures() {
6036 DCHECK(state_.current_program.get());
6037 const Program::SamplerIndices& sampler_indices =
6038 state_.current_program->sampler_indices();
6039 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6040 const Program::UniformInfo* uniform_info =
6041 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6042 DCHECK(uniform_info);
6043 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6044 GLuint texture_unit_index = uniform_info->texture_units[jj];
6045 if (texture_unit_index < state_.texture_units.size()) {
6046 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6047 TextureRef* texture_ref =
6048 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6049 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6050 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6051 // Get the texture_ref info that was previously bound here.
6052 texture_ref = texture_unit.bind_target == GL_TEXTURE_2D
6053 ? texture_unit.bound_texture_2d.get()
6054 : texture_unit.bound_texture_cube_map.get();
6055 glBindTexture(texture_unit.bind_target,
6056 texture_ref ? texture_ref->service_id() : 0);
6060 if (texture_unit.bind_target != GL_TEXTURE_CUBE_MAP) {
6061 Texture* texture = texture_ref->texture();
6062 gfx::GLImage* image =
6063 texture->GetLevelImage(texture_unit.bind_target, 0);
6064 if (image && !texture->IsAttachedToFramebuffer()) {
6065 ScopedGLErrorSuppressor suppressor(
6066 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
6067 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6068 image->DidUseTexImage();
6075 // Set the active texture back to whatever the user had it as.
6076 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
6079 bool GLES2DecoderImpl::ClearUnclearedTextures() {
6080 // Only check if there are some uncleared textures.
6081 if (!texture_manager()->HaveUnsafeTextures()) {
6085 // 1: Check all textures we are about to render with.
6086 if (state_.current_program.get()) {
6087 const Program::SamplerIndices& sampler_indices =
6088 state_.current_program->sampler_indices();
6089 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6090 const Program::UniformInfo* uniform_info =
6091 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6092 DCHECK(uniform_info);
6093 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6094 GLuint texture_unit_index = uniform_info->texture_units[jj];
6095 if (texture_unit_index < state_.texture_units.size()) {
6096 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6097 TextureRef* texture_ref =
6098 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6099 if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
6100 if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
6111 bool GLES2DecoderImpl::IsDrawValid(
6112 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount) {
6113 // NOTE: We specifically do not check current_program->IsValid() because
6114 // it could never be invalid since glUseProgram would have failed. While
6115 // glLinkProgram could later mark the program as invalid the previous
6116 // valid program will still function if it is still the current program.
6117 if (!state_.current_program.get()) {
6118 // The program does not exist.
6119 // But GL says no ERROR.
6120 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
6124 return state_.vertex_attrib_manager
6125 ->ValidateBindings(function_name,
6127 feature_info_.get(),
6128 state_.current_program.get(),
6129 max_vertex_accessed,
6133 bool GLES2DecoderImpl::SimulateAttrib0(
6134 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
6138 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
6141 const VertexAttrib* attrib =
6142 state_.vertex_attrib_manager->GetVertexAttrib(0);
6143 // If it's enabled or it's not used then we don't need to do anything.
6144 bool attrib_0_used =
6145 state_.current_program->GetAttribInfoByLocation(0) != NULL;
6146 if (attrib->enabled() && attrib_0_used) {
6150 // Make a buffer with a single repeated vec4 value enough to
6151 // simulate the constant value that is supposed to be here.
6152 // This is required to emulate GLES2 on GL.
6153 GLuint num_vertices = max_vertex_accessed + 1;
6154 uint32 size_needed = 0;
6156 if (num_vertices == 0 ||
6157 !SafeMultiplyUint32(num_vertices, sizeof(Vec4), &size_needed) ||
6158 size_needed > 0x7FFFFFFFU) {
6159 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6163 LOCAL_PERFORMANCE_WARNING(
6164 "Attribute 0 is disabled. This has signficant performance penalty");
6166 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6167 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
6169 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
6171 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6172 GLenum error = glGetError();
6173 if (error != GL_NO_ERROR) {
6175 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6180 const Vec4& value = state_.attrib_values[0];
6183 (!attrib_0_buffer_matches_value_ ||
6184 (value.v[0] != attrib_0_value_.v[0] ||
6185 value.v[1] != attrib_0_value_.v[1] ||
6186 value.v[2] != attrib_0_value_.v[2] ||
6187 value.v[3] != attrib_0_value_.v[3])))) {
6188 std::vector<Vec4> temp(num_vertices, value);
6189 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
6190 attrib_0_buffer_matches_value_ = true;
6191 attrib_0_value_ = value;
6192 attrib_0_size_ = size_needed;
6195 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
6197 if (attrib->divisor())
6198 glVertexAttribDivisorANGLE(0, 0);
6204 void GLES2DecoderImpl::RestoreStateForAttrib(GLuint attrib_index) {
6205 const VertexAttrib* attrib =
6206 state_.vertex_attrib_manager->GetVertexAttrib(attrib_index);
6207 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
6208 Buffer* buffer = attrib->buffer();
6209 glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
6210 glVertexAttribPointer(
6211 attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
6212 attrib->gl_stride(), ptr);
6213 if (attrib->divisor())
6214 glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
6217 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
6220 // Never touch vertex attribute 0's state (in particular, never
6221 // disable it) when running on desktop GL because it will never be
6223 if (attrib_index != 0 ||
6224 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
6225 if (attrib->enabled()) {
6226 glEnableVertexAttribArray(attrib_index);
6228 glDisableVertexAttribArray(attrib_index);
6233 bool GLES2DecoderImpl::SimulateFixedAttribs(
6234 const char* function_name,
6235 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
6238 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
6241 if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
6245 LOCAL_PERFORMANCE_WARNING(
6246 "GL_FIXED attributes have a signficant performance penalty");
6248 // NOTE: we could be smart and try to check if a buffer is used
6249 // twice in 2 different attribs, find the overlapping parts and therefore
6250 // duplicate the minimum amount of data but this whole code path is not meant
6251 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
6252 // tests so we just add to the buffer attrib used.
6254 GLuint elements_needed = 0;
6255 const VertexAttribManager::VertexAttribList& enabled_attribs =
6256 state_.vertex_attrib_manager->GetEnabledVertexAttribs();
6257 for (VertexAttribManager::VertexAttribList::const_iterator it =
6258 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6259 const VertexAttrib* attrib = *it;
6260 const Program::VertexAttrib* attrib_info =
6261 state_.current_program->GetAttribInfoByLocation(attrib->index());
6262 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6263 max_vertex_accessed);
6264 GLuint num_vertices = max_accessed + 1;
6265 if (num_vertices == 0) {
6267 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6271 attrib->CanAccess(max_accessed) &&
6272 attrib->type() == GL_FIXED) {
6273 uint32 elements_used = 0;
6274 if (!SafeMultiplyUint32(num_vertices, attrib->size(), &elements_used) ||
6275 !SafeAddUint32(elements_needed, elements_used, &elements_needed)) {
6277 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6283 const uint32 kSizeOfFloat = sizeof(float); // NOLINT
6284 uint32 size_needed = 0;
6285 if (!SafeMultiplyUint32(elements_needed, kSizeOfFloat, &size_needed) ||
6286 size_needed > 0x7FFFFFFFU) {
6288 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6292 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6294 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
6295 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
6296 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6297 GLenum error = glGetError();
6298 if (error != GL_NO_ERROR) {
6300 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6305 // Copy the elements and convert to float
6306 GLintptr offset = 0;
6307 for (VertexAttribManager::VertexAttribList::const_iterator it =
6308 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6309 const VertexAttrib* attrib = *it;
6310 const Program::VertexAttrib* attrib_info =
6311 state_.current_program->GetAttribInfoByLocation(attrib->index());
6312 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6313 max_vertex_accessed);
6314 GLuint num_vertices = max_accessed + 1;
6315 if (num_vertices == 0) {
6317 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6321 attrib->CanAccess(max_accessed) &&
6322 attrib->type() == GL_FIXED) {
6323 int num_elements = attrib->size() * kSizeOfFloat;
6324 int size = num_elements * num_vertices;
6325 scoped_ptr<float[]> data(new float[size]);
6326 const int32* src = reinterpret_cast<const int32 *>(
6327 attrib->buffer()->GetRange(attrib->offset(), size));
6328 const int32* end = src + num_elements;
6329 float* dst = data.get();
6330 while (src != end) {
6331 *dst++ = static_cast<float>(*src++) / 65536.0f;
6333 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
6334 glVertexAttribPointer(
6335 attrib->index(), attrib->size(), GL_FLOAT, false, 0,
6336 reinterpret_cast<GLvoid*>(offset));
6344 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
6345 // There's no need to call glVertexAttribPointer because we shadow all the
6346 // settings and passing GL_FIXED to it will not work.
6349 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
6353 error::Error GLES2DecoderImpl::DoDrawArrays(
6354 const char* function_name,
6359 GLsizei primcount) {
6360 error::Error error = WillAccessBoundFramebufferForDraw();
6361 if (error != error::kNoError)
6363 if (!validators_->draw_mode.IsValid(mode)) {
6364 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
6365 return error::kNoError;
6368 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
6369 return error::kNoError;
6371 if (primcount < 0) {
6372 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
6373 return error::kNoError;
6375 if (!CheckBoundFramebuffersValid(function_name)) {
6376 return error::kNoError;
6378 // We have to check this here because the prototype for glDrawArrays
6379 // is GLint not GLsizei.
6381 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "first < 0");
6382 return error::kNoError;
6385 if (count == 0 || (instanced && primcount == 0)) {
6386 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
6387 return error::kNoError;
6390 GLuint max_vertex_accessed = first + count - 1;
6391 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
6392 if (!ClearUnclearedTextures()) {
6393 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
6394 return error::kNoError;
6396 bool simulated_attrib_0 = false;
6397 if (!SimulateAttrib0(
6398 function_name, max_vertex_accessed, &simulated_attrib_0)) {
6399 return error::kNoError;
6401 bool simulated_fixed_attribs = false;
6402 if (SimulateFixedAttribs(
6403 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6405 bool textures_set = !PrepareTexturesForRender();
6407 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
6409 glDrawArrays(mode, first, count);
6411 glDrawArraysInstancedANGLE(mode, first, count, primcount);
6413 ProcessPendingQueries();
6415 RestoreStateForTextures();
6417 if (simulated_fixed_attribs) {
6418 RestoreStateForSimulatedFixedAttribs();
6421 if (simulated_attrib_0) {
6422 RestoreStateForAttrib(0);
6425 return error::kNoError;
6428 error::Error GLES2DecoderImpl::HandleDrawArrays(
6429 uint32 immediate_data_size, const cmds::DrawArrays& c) {
6430 return DoDrawArrays("glDrawArrays",
6432 static_cast<GLenum>(c.mode),
6433 static_cast<GLint>(c.first),
6434 static_cast<GLsizei>(c.count),
6438 error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
6439 uint32 immediate_data_size, const cmds::DrawArraysInstancedANGLE& c) {
6440 if (!features().angle_instanced_arrays) {
6442 GL_INVALID_OPERATION,
6443 "glDrawArraysInstancedANGLE", "function not available");
6444 return error::kNoError;
6446 return DoDrawArrays("glDrawArraysIntancedANGLE",
6448 static_cast<GLenum>(c.mode),
6449 static_cast<GLint>(c.first),
6450 static_cast<GLsizei>(c.count),
6451 static_cast<GLsizei>(c.primcount));
6454 error::Error GLES2DecoderImpl::DoDrawElements(
6455 const char* function_name,
6461 GLsizei primcount) {
6462 error::Error error = WillAccessBoundFramebufferForDraw();
6463 if (error != error::kNoError)
6465 if (!state_.vertex_attrib_manager->element_array_buffer()) {
6467 GL_INVALID_OPERATION, function_name, "No element array buffer bound");
6468 return error::kNoError;
6472 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
6473 return error::kNoError;
6476 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "offset < 0");
6477 return error::kNoError;
6479 if (!validators_->draw_mode.IsValid(mode)) {
6480 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
6481 return error::kNoError;
6483 if (!validators_->index_type.IsValid(type)) {
6484 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
6485 return error::kNoError;
6487 if (primcount < 0) {
6488 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
6489 return error::kNoError;
6492 if (!CheckBoundFramebuffersValid(function_name)) {
6493 return error::kNoError;
6496 if (count == 0 || (instanced && primcount == 0)) {
6497 return error::kNoError;
6500 GLuint max_vertex_accessed;
6501 Buffer* element_array_buffer =
6502 state_.vertex_attrib_manager->element_array_buffer();
6504 if (!element_array_buffer->GetMaxValueForRange(
6505 offset, count, type, &max_vertex_accessed)) {
6507 GL_INVALID_OPERATION, function_name, "range out of bounds for buffer");
6508 return error::kNoError;
6511 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
6512 if (!ClearUnclearedTextures()) {
6513 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
6514 return error::kNoError;
6516 bool simulated_attrib_0 = false;
6517 if (!SimulateAttrib0(
6518 function_name, max_vertex_accessed, &simulated_attrib_0)) {
6519 return error::kNoError;
6521 bool simulated_fixed_attribs = false;
6522 if (SimulateFixedAttribs(
6523 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6525 bool textures_set = !PrepareTexturesForRender();
6527 // TODO(gman): Refactor to hide these details in BufferManager or
6528 // VertexAttribManager.
6529 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
6530 bool used_client_side_array = false;
6531 if (element_array_buffer->IsClientSideArray()) {
6532 used_client_side_array = true;
6533 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
6534 indices = element_array_buffer->GetRange(offset, 0);
6537 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
6539 glDrawElements(mode, count, type, indices);
6541 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
6544 if (used_client_side_array) {
6545 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
6546 element_array_buffer->service_id());
6549 ProcessPendingQueries();
6551 RestoreStateForTextures();
6553 if (simulated_fixed_attribs) {
6554 RestoreStateForSimulatedFixedAttribs();
6557 if (simulated_attrib_0) {
6558 RestoreStateForAttrib(0);
6561 return error::kNoError;
6564 error::Error GLES2DecoderImpl::HandleDrawElements(
6565 uint32 immediate_data_size, const cmds::DrawElements& c) {
6566 return DoDrawElements("glDrawElements",
6568 static_cast<GLenum>(c.mode),
6569 static_cast<GLsizei>(c.count),
6570 static_cast<GLenum>(c.type),
6571 static_cast<int32>(c.index_offset),
6575 error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
6576 uint32 immediate_data_size, const cmds::DrawElementsInstancedANGLE& c) {
6577 if (!features().angle_instanced_arrays) {
6579 GL_INVALID_OPERATION,
6580 "glDrawElementsInstancedANGLE", "function not available");
6581 return error::kNoError;
6583 return DoDrawElements("glDrawElementsInstancedANGLE",
6585 static_cast<GLenum>(c.mode),
6586 static_cast<GLsizei>(c.count),
6587 static_cast<GLenum>(c.type),
6588 static_cast<int32>(c.index_offset),
6589 static_cast<GLsizei>(c.primcount));
6592 GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
6593 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
6594 GLuint max_vertex_accessed = 0;
6595 Buffer* buffer = GetBuffer(buffer_id);
6597 // TODO(gman): Should this be a GL error or a command buffer error?
6599 GL_INVALID_VALUE, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
6601 if (!buffer->GetMaxValueForRange(
6602 offset, count, type, &max_vertex_accessed)) {
6603 // TODO(gman): Should this be a GL error or a command buffer error?
6605 GL_INVALID_OPERATION,
6606 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
6609 return max_vertex_accessed;
6612 // Calls glShaderSource for the various versions of the ShaderSource command.
6613 // Assumes that data / data_size points to a piece of memory that is in range
6614 // of whatever context it came from (shared memory, immediate memory, bucket
6616 error::Error GLES2DecoderImpl::ShaderSourceHelper(
6617 GLuint client_id, const char* data, uint32 data_size) {
6618 std::string str(data, data + data_size);
6619 Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
6621 return error::kNoError;
6623 // Note: We don't actually call glShaderSource here. We wait until
6624 // the call to glCompileShader.
6625 shader->UpdateSource(str.c_str());
6626 return error::kNoError;
6629 error::Error GLES2DecoderImpl::HandleShaderSource(
6630 uint32 immediate_data_size, const cmds::ShaderSource& c) {
6631 uint32 data_size = c.data_size;
6632 const char* data = GetSharedMemoryAs<const char*>(
6633 c.data_shm_id, c.data_shm_offset, data_size);
6635 return error::kOutOfBounds;
6637 return ShaderSourceHelper(c.shader, data, data_size);
6640 error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
6641 uint32 immediate_data_size, const cmds::ShaderSourceBucket& c) {
6642 Bucket* bucket = GetBucket(c.data_bucket_id);
6643 if (!bucket || bucket->size() == 0) {
6644 return error::kInvalidArguments;
6646 return ShaderSourceHelper(
6647 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
6648 bucket->size() - 1);
6651 void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
6652 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
6653 Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader");
6657 ShaderTranslator* translator = NULL;
6658 if (use_shader_translator_) {
6659 translator = shader->shader_type() == GL_VERTEX_SHADER ?
6660 vertex_translator_.get() : fragment_translator_.get();
6663 program_manager()->DoCompileShader(
6666 feature_info_->feature_flags().angle_translated_shader_source ?
6667 ProgramManager::kANGLE : ProgramManager::kGL);
6670 void GLES2DecoderImpl::DoGetShaderiv(
6671 GLuint shader_id, GLenum pname, GLint* params) {
6672 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderiv");
6677 case GL_SHADER_SOURCE_LENGTH:
6678 *params = shader->source() ? shader->source()->size() + 1 : 0;
6680 case GL_COMPILE_STATUS:
6681 *params = compile_shader_always_succeeds_ ? true : shader->IsValid();
6683 case GL_INFO_LOG_LENGTH:
6684 *params = shader->log_info() ? shader->log_info()->size() + 1 : 0;
6686 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
6687 *params = shader->translated_source() ?
6688 shader->translated_source()->size() + 1 : 0;
6693 glGetShaderiv(shader->service_id(), pname, params);
6696 error::Error GLES2DecoderImpl::HandleGetShaderSource(
6697 uint32 immediate_data_size, const cmds::GetShaderSource& c) {
6698 GLuint shader_id = c.shader;
6699 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6700 Bucket* bucket = CreateBucket(bucket_id);
6701 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderSource");
6702 if (!shader || !shader->source()) {
6704 return error::kNoError;
6706 bucket->SetFromString(shader->source()->c_str());
6707 return error::kNoError;
6710 error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
6711 uint32 immediate_data_size,
6712 const cmds::GetTranslatedShaderSourceANGLE& c) {
6713 GLuint shader_id = c.shader;
6714 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6715 Bucket* bucket = CreateBucket(bucket_id);
6716 Shader* shader = GetShaderInfoNotProgram(
6717 shader_id, "glGetTranslatedShaderSourceANGLE");
6720 return error::kNoError;
6723 bucket->SetFromString(shader->translated_source() ?
6724 shader->translated_source()->c_str() : NULL);
6725 return error::kNoError;
6728 error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
6729 uint32 immediate_data_size, const cmds::GetProgramInfoLog& c) {
6730 GLuint program_id = c.program;
6731 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6732 Bucket* bucket = CreateBucket(bucket_id);
6733 Program* program = GetProgramInfoNotShader(
6734 program_id, "glGetProgramInfoLog");
6735 if (!program || !program->log_info()) {
6736 bucket->SetFromString("");
6737 return error::kNoError;
6739 bucket->SetFromString(program->log_info()->c_str());
6740 return error::kNoError;
6743 error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
6744 uint32 immediate_data_size, const cmds::GetShaderInfoLog& c) {
6745 GLuint shader_id = c.shader;
6746 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6747 Bucket* bucket = CreateBucket(bucket_id);
6748 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderInfoLog");
6749 if (!shader || !shader->log_info()) {
6750 bucket->SetFromString("");
6751 return error::kNoError;
6753 bucket->SetFromString(shader->log_info()->c_str());
6754 return error::kNoError;
6757 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
6758 return state_.GetEnabled(cap);
6761 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
6762 const Buffer* buffer = GetBuffer(client_id);
6763 return buffer && buffer->IsValid() && !buffer->IsDeleted();
6766 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
6767 const Framebuffer* framebuffer =
6768 GetFramebuffer(client_id);
6769 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
6772 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
6773 // IsProgram is true for programs as soon as they are created, until they are
6774 // deleted and no longer in use.
6775 const Program* program = GetProgram(client_id);
6776 return program != NULL && !program->IsDeleted();
6779 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
6780 const Renderbuffer* renderbuffer =
6781 GetRenderbuffer(client_id);
6782 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
6785 bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
6786 // IsShader is true for shaders as soon as they are created, until they
6787 // are deleted and not attached to any programs.
6788 const Shader* shader = GetShader(client_id);
6789 return shader != NULL && !shader->IsDeleted();
6792 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
6793 const TextureRef* texture_ref = GetTexture(client_id);
6794 return texture_ref && texture_ref->texture()->IsValid();
6797 void GLES2DecoderImpl::DoAttachShader(
6798 GLuint program_client_id, GLint shader_client_id) {
6799 Program* program = GetProgramInfoNotShader(
6800 program_client_id, "glAttachShader");
6804 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glAttachShader");
6808 if (!program->AttachShader(shader_manager(), shader)) {
6810 GL_INVALID_OPERATION,
6812 "can not attach more than one shader of the same type.");
6815 glAttachShader(program->service_id(), shader->service_id());
6818 void GLES2DecoderImpl::DoDetachShader(
6819 GLuint program_client_id, GLint shader_client_id) {
6820 Program* program = GetProgramInfoNotShader(
6821 program_client_id, "glDetachShader");
6825 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glDetachShader");
6829 if (!program->DetachShader(shader_manager(), shader)) {
6831 GL_INVALID_OPERATION,
6832 "glDetachShader", "shader not attached to program");
6835 glDetachShader(program->service_id(), shader->service_id());
6838 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
6839 Program* program = GetProgramInfoNotShader(
6840 program_client_id, "glValidateProgram");
6844 program->Validate();
6847 void GLES2DecoderImpl::GetVertexAttribHelper(
6848 const VertexAttrib* attrib, GLenum pname, GLint* params) {
6850 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
6851 Buffer* buffer = attrib->buffer();
6852 if (buffer && !buffer->IsDeleted()) {
6854 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
6855 *params = client_id;
6859 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
6860 *params = attrib->enabled();
6862 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
6863 *params = attrib->size();
6865 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
6866 *params = attrib->gl_stride();
6868 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
6869 *params = attrib->type();
6871 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
6872 *params = attrib->normalized();
6874 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
6875 *params = attrib->divisor();
6883 void GLES2DecoderImpl::DoGetTexParameterfv(
6884 GLenum target, GLenum pname, GLfloat* params) {
6885 InitTextureMaxAnisotropyIfNeeded(target, pname);
6886 glGetTexParameterfv(target, pname, params);
6889 void GLES2DecoderImpl::DoGetTexParameteriv(
6890 GLenum target, GLenum pname, GLint* params) {
6891 InitTextureMaxAnisotropyIfNeeded(target, pname);
6892 glGetTexParameteriv(target, pname, params);
6895 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
6896 GLenum target, GLenum pname) {
6897 if (!workarounds().init_texture_max_anisotropy)
6899 if (pname != GL_TEXTURE_MAX_ANISOTROPY_EXT ||
6900 !validators_->texture_parameter.IsValid(pname)) {
6904 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
6908 GL_INVALID_OPERATION,
6909 "glGetTexParamter{fi}v", "unknown texture for target");
6912 Texture* texture = texture_ref->texture();
6913 texture->InitTextureMaxAnisotropyIfNeeded(target);
6916 void GLES2DecoderImpl::DoGetVertexAttribfv(
6917 GLuint index, GLenum pname, GLfloat* params) {
6918 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
6921 GL_INVALID_VALUE, "glGetVertexAttribfv", "index out of range");
6925 case GL_CURRENT_VERTEX_ATTRIB: {
6926 const Vec4& value = state_.attrib_values[index];
6927 params[0] = value.v[0];
6928 params[1] = value.v[1];
6929 params[2] = value.v[2];
6930 params[3] = value.v[3];
6935 GetVertexAttribHelper(attrib, pname, &value);
6936 *params = static_cast<GLfloat>(value);
6942 void GLES2DecoderImpl::DoGetVertexAttribiv(
6943 GLuint index, GLenum pname, GLint* params) {
6944 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
6947 GL_INVALID_VALUE, "glGetVertexAttribiv", "index out of range");
6951 case GL_CURRENT_VERTEX_ATTRIB: {
6952 const Vec4& value = state_.attrib_values[index];
6953 params[0] = static_cast<GLint>(value.v[0]);
6954 params[1] = static_cast<GLint>(value.v[1]);
6955 params[2] = static_cast<GLint>(value.v[2]);
6956 params[3] = static_cast<GLint>(value.v[3]);
6960 GetVertexAttribHelper(attrib, pname, params);
6965 bool GLES2DecoderImpl::SetVertexAttribValue(
6966 const char* function_name, GLuint index, const GLfloat* value) {
6967 if (index >= state_.attrib_values.size()) {
6968 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "index out of range");
6971 Vec4& v = state_.attrib_values[index];
6979 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
6980 GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
6981 if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
6982 glVertexAttrib1f(index, v0);
6986 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
6987 GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
6988 if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
6989 glVertexAttrib2f(index, v0, v1);
6993 void GLES2DecoderImpl::DoVertexAttrib3f(
6994 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
6995 GLfloat v[4] = { v0, v1, v2, 1.0f, };
6996 if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
6997 glVertexAttrib3f(index, v0, v1, v2);
7001 void GLES2DecoderImpl::DoVertexAttrib4f(
7002 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
7003 GLfloat v[4] = { v0, v1, v2, v3, };
7004 if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
7005 glVertexAttrib4f(index, v0, v1, v2, v3);
7009 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
7010 GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
7011 if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
7012 glVertexAttrib1fv(index, v);
7016 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
7017 GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
7018 if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
7019 glVertexAttrib2fv(index, v);
7023 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
7024 GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
7025 if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
7026 glVertexAttrib3fv(index, v);
7030 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
7031 if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
7032 glVertexAttrib4fv(index, v);
7036 error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
7037 uint32 immediate_data_size, const cmds::VertexAttribPointer& c) {
7039 if (!state_.bound_array_buffer.get() ||
7040 state_.bound_array_buffer->IsDeleted()) {
7041 if (state_.vertex_attrib_manager.get() ==
7042 default_vertex_attrib_manager_.get()) {
7044 GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
7045 return error::kNoError;
7046 } else if (c.offset != 0) {
7049 "glVertexAttribPointer", "client side arrays are not allowed");
7050 return error::kNoError;
7054 GLuint indx = c.indx;
7055 GLint size = c.size;
7056 GLenum type = c.type;
7057 GLboolean normalized = c.normalized;
7058 GLsizei stride = c.stride;
7059 GLsizei offset = c.offset;
7060 const void* ptr = reinterpret_cast<const void*>(offset);
7061 if (!validators_->vertex_attrib_type.IsValid(type)) {
7062 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type, "type");
7063 return error::kNoError;
7065 if (!validators_->vertex_attrib_size.IsValid(size)) {
7067 GL_INVALID_VALUE, "glVertexAttribPointer", "size GL_INVALID_VALUE");
7068 return error::kNoError;
7070 if (indx >= group_->max_vertex_attribs()) {
7072 GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
7073 return error::kNoError;
7077 GL_INVALID_VALUE, "glVertexAttribPointer", "stride < 0");
7078 return error::kNoError;
7082 GL_INVALID_VALUE, "glVertexAttribPointer", "stride > 255");
7083 return error::kNoError;
7087 GL_INVALID_VALUE, "glVertexAttribPointer", "offset < 0");
7088 return error::kNoError;
7090 GLsizei component_size =
7091 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
7092 if (offset % component_size > 0) {
7094 GL_INVALID_OPERATION,
7095 "glVertexAttribPointer", "offset not valid for type");
7096 return error::kNoError;
7098 if (stride % component_size > 0) {
7100 GL_INVALID_OPERATION,
7101 "glVertexAttribPointer", "stride not valid for type");
7102 return error::kNoError;
7104 state_.vertex_attrib_manager
7105 ->SetAttribInfo(indx,
7106 state_.bound_array_buffer.get(),
7111 stride != 0 ? stride : component_size * size,
7113 if (type != GL_FIXED) {
7114 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
7116 return error::kNoError;
7119 void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
7121 state_.viewport_x = x;
7122 state_.viewport_y = y;
7123 state_.viewport_width = std::min(width, viewport_max_width_);
7124 state_.viewport_height = std::min(height, viewport_max_height_);
7125 glViewport(x, y, width, height);
7128 error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
7129 uint32 immediate_data_size, const cmds::VertexAttribDivisorANGLE& c) {
7130 if (!features().angle_instanced_arrays) {
7132 GL_INVALID_OPERATION,
7133 "glVertexAttribDivisorANGLE", "function not available");
7135 GLuint index = c.index;
7136 GLuint divisor = c.divisor;
7137 if (index >= group_->max_vertex_attribs()) {
7140 "glVertexAttribDivisorANGLE", "index out of range");
7141 return error::kNoError;
7144 state_.vertex_attrib_manager->SetDivisor(
7147 glVertexAttribDivisorANGLE(index, divisor);
7148 return error::kNoError;
7151 template <typename pixel_data_type>
7152 static void WriteAlphaData(
7153 void *pixels, uint32 row_count, uint32 channel_count,
7154 uint32 alpha_channel_index, uint32 unpadded_row_size,
7155 uint32 padded_row_size, pixel_data_type alpha_value) {
7156 DCHECK_GT(channel_count, 0U);
7157 DCHECK_EQ(unpadded_row_size % sizeof(pixel_data_type), 0U);
7158 uint32 unpadded_row_size_in_elements =
7159 unpadded_row_size / sizeof(pixel_data_type);
7160 DCHECK_EQ(padded_row_size % sizeof(pixel_data_type), 0U);
7161 uint32 padded_row_size_in_elements =
7162 padded_row_size / sizeof(pixel_data_type);
7163 pixel_data_type* dst =
7164 static_cast<pixel_data_type*>(pixels) + alpha_channel_index;
7165 for (uint32 yy = 0; yy < row_count; ++yy) {
7166 pixel_data_type* end = dst + unpadded_row_size_in_elements;
7167 for (pixel_data_type* d = dst; d < end; d += channel_count) {
7170 dst += padded_row_size_in_elements;
7174 void GLES2DecoderImpl::FinishReadPixels(
7175 const cmds::ReadPixels& c,
7177 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
7178 GLsizei width = c.width;
7179 GLsizei height = c.height;
7180 GLenum format = c.format;
7181 GLenum type = c.type;
7182 typedef cmds::ReadPixels::Result Result;
7184 Result* result = NULL;
7185 if (c.result_shm_id != 0) {
7186 result = GetSharedMemoryAs<Result*>(
7187 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7190 glDeleteBuffersARB(1, &buffer);
7195 GLES2Util::ComputeImageDataSizes(
7196 width, height, format, type, state_.pack_alignment, &pixels_size,
7198 void* pixels = GetSharedMemoryAs<void*>(
7199 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
7202 glDeleteBuffersARB(1, &buffer);
7208 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
7210 if (features().map_buffer_range) {
7211 data = glMapBufferRange(
7212 GL_PIXEL_PACK_BUFFER_ARB, 0, pixels_size, GL_MAP_READ_BIT);
7214 data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
7216 memcpy(pixels, data, pixels_size);
7217 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
7218 // have to restore the state.
7219 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
7220 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7221 glDeleteBuffersARB(1, &buffer);
7224 if (result != NULL) {
7228 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
7229 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
7230 if ((channels_exist & 0x0008) == 0 &&
7231 workarounds().clear_alpha_in_readpixels) {
7232 // Set the alpha to 255 because some drivers are buggy in this regard.
7235 uint32 unpadded_row_size;
7236 uint32 padded_row_size;
7237 if (!GLES2Util::ComputeImageDataSizes(
7238 width, 2, format, type, state_.pack_alignment, &temp_size,
7239 &unpadded_row_size, &padded_row_size)) {
7243 uint32 channel_count = 0;
7244 uint32 alpha_channel = 0;
7257 if (channel_count > 0) {
7259 case GL_UNSIGNED_BYTE:
7260 WriteAlphaData<uint8>(
7261 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7262 padded_row_size, 0xFF);
7265 WriteAlphaData<float>(
7266 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7267 padded_row_size, 1.0f);
7270 WriteAlphaData<uint16>(
7271 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7272 padded_row_size, 0x3C00);
7280 error::Error GLES2DecoderImpl::HandleReadPixels(
7281 uint32 immediate_data_size, const cmds::ReadPixels& c) {
7282 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
7283 error::Error fbo_error = WillAccessBoundFramebufferForRead();
7284 if (fbo_error != error::kNoError)
7288 GLsizei width = c.width;
7289 GLsizei height = c.height;
7290 GLenum format = c.format;
7291 GLenum type = c.type;
7292 GLboolean async = c.async;
7293 if (width < 0 || height < 0) {
7294 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
7295 return error::kNoError;
7297 typedef cmds::ReadPixels::Result Result;
7299 if (!GLES2Util::ComputeImageDataSizes(
7300 width, height, format, type, state_.pack_alignment, &pixels_size,
7302 return error::kOutOfBounds;
7304 void* pixels = GetSharedMemoryAs<void*>(
7305 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
7307 return error::kOutOfBounds;
7309 Result* result = NULL;
7310 if (c.result_shm_id != 0) {
7311 result = GetSharedMemoryAs<Result*>(
7312 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7314 return error::kOutOfBounds;
7318 if (!validators_->read_pixel_format.IsValid(format)) {
7319 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format, "format");
7320 return error::kNoError;
7322 if (!validators_->read_pixel_type.IsValid(type)) {
7323 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type");
7324 return error::kNoError;
7326 if ((format != GL_RGBA && format != GL_BGRA_EXT && format != GL_RGB &&
7327 format != GL_ALPHA) || type != GL_UNSIGNED_BYTE) {
7328 // format and type are acceptable enums but not guaranteed to be supported
7329 // for this framebuffer. Have to ask gl if they are valid.
7330 GLint preferred_format = 0;
7331 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &preferred_format);
7332 GLint preferred_type = 0;
7333 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &preferred_type);
7334 if (format != static_cast<GLenum>(preferred_format) ||
7335 type != static_cast<GLenum>(preferred_type)) {
7337 GL_INVALID_OPERATION, "glReadPixels", "format and type incompatible "
7338 "with the current read framebuffer");
7339 return error::kNoError;
7342 if (width == 0 || height == 0) {
7343 return error::kNoError;
7346 // Get the size of the current fbo or backbuffer.
7347 gfx::Size max_size = GetBoundReadFrameBufferSize();
7351 if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y)) {
7353 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7354 return error::kNoError;
7357 if (!CheckBoundFramebuffersValid("glReadPixels")) {
7358 return error::kNoError;
7361 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
7363 ScopedResolvedFrameBufferBinder binder(this, false, true);
7365 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
7366 // The user requested an out of range area. Get the results 1 line
7369 uint32 unpadded_row_size;
7370 uint32 padded_row_size;
7371 if (!GLES2Util::ComputeImageDataSizes(
7372 width, 2, format, type, state_.pack_alignment, &temp_size,
7373 &unpadded_row_size, &padded_row_size)) {
7375 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7376 return error::kNoError;
7379 GLint dest_x_offset = std::max(-x, 0);
7380 uint32 dest_row_offset;
7381 if (!GLES2Util::ComputeImageDataSizes(
7382 dest_x_offset, 1, format, type, state_.pack_alignment, &dest_row_offset,
7385 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7386 return error::kNoError;
7389 // Copy each row into the larger dest rect.
7390 int8* dst = static_cast<int8*>(pixels);
7391 GLint read_x = std::max(0, x);
7392 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
7393 GLint read_width = read_end_x - read_x;
7394 for (GLint yy = 0; yy < height; ++yy) {
7398 memset(dst, 0, unpadded_row_size);
7400 // If the row is in range, copy it.
7401 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
7403 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
7405 dst += padded_row_size;
7408 if (async && features().use_async_readpixels) {
7410 glGenBuffersARB(1, &buffer);
7411 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
7412 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, GL_STREAM_READ);
7413 GLenum error = glGetError();
7414 if (error == GL_NO_ERROR) {
7415 glReadPixels(x, y, width, height, format, type, 0);
7416 pending_readpixel_fences_.push(linked_ptr<FenceCallback>(
7417 new FenceCallback()));
7418 WaitForReadPixels(base::Bind(
7419 &GLES2DecoderImpl::FinishReadPixels,
7420 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
7421 <GLES2DecoderImpl>(this),
7423 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7424 return error::kNoError;
7426 // On error, unbind pack buffer and fall through to sync readpixels
7427 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7430 glReadPixels(x, y, width, height, format, type, pixels);
7432 GLenum error = LOCAL_PEEK_GL_ERROR("glReadPixels");
7433 if (error == GL_NO_ERROR) {
7434 if (result != NULL) {
7437 FinishReadPixels(c, 0);
7440 return error::kNoError;
7443 error::Error GLES2DecoderImpl::HandlePixelStorei(
7444 uint32 immediate_data_size, const cmds::PixelStorei& c) {
7445 GLenum pname = c.pname;
7446 GLenum param = c.param;
7447 if (!validators_->pixel_store.IsValid(pname)) {
7448 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname, "pname");
7449 return error::kNoError;
7452 case GL_PACK_ALIGNMENT:
7453 case GL_UNPACK_ALIGNMENT:
7454 if (!validators_->pixel_store_alignment.IsValid(param)) {
7456 GL_INVALID_VALUE, "glPixelStorei", "param GL_INVALID_VALUE");
7457 return error::kNoError;
7460 case GL_UNPACK_FLIP_Y_CHROMIUM:
7461 unpack_flip_y_ = (param != 0);
7462 return error::kNoError;
7463 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
7464 unpack_premultiply_alpha_ = (param != 0);
7465 return error::kNoError;
7466 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
7467 unpack_unpremultiply_alpha_ = (param != 0);
7468 return error::kNoError;
7472 glPixelStorei(pname, param);
7474 case GL_PACK_ALIGNMENT:
7475 state_.pack_alignment = param;
7477 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
7478 state_.pack_reverse_row_order = (param != 0);
7480 case GL_UNPACK_ALIGNMENT:
7481 state_.unpack_alignment = param;
7484 // Validation should have prevented us from getting here.
7488 return error::kNoError;
7491 error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
7492 uint32 immediate_data_size, const cmds::PostSubBufferCHROMIUM& c) {
7493 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
7494 if (!supports_post_sub_buffer_) {
7496 GL_INVALID_OPERATION,
7497 "glPostSubBufferCHROMIUM", "command not supported by surface");
7498 return error::kNoError;
7501 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
7504 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
7505 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
7506 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
7507 is_offscreen ? offscreen_size_ : surface_->GetSize());
7509 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height)) {
7510 return error::kNoError;
7512 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
7513 return error::kLostContext;
7517 error::Error GLES2DecoderImpl::GetAttribLocationHelper(
7518 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7519 const std::string& name_str) {
7520 if (!StringIsValidForGLES(name_str.c_str())) {
7522 GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
7523 return error::kNoError;
7525 Program* program = GetProgramInfoNotShader(
7526 client_id, "glGetAttribLocation");
7528 return error::kNoError;
7530 if (!program->IsValid()) {
7532 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
7533 return error::kNoError;
7535 GLint* location = GetSharedMemoryAs<GLint*>(
7536 location_shm_id, location_shm_offset, sizeof(GLint));
7538 return error::kOutOfBounds;
7540 // Require the client to init this incase the context is lost and we are no
7541 // longer executing commands.
7542 if (*location != -1) {
7543 return error::kGenericError;
7545 *location = program->GetAttribLocation(name_str);
7546 return error::kNoError;
7549 error::Error GLES2DecoderImpl::HandleGetAttribLocation(
7550 uint32 immediate_data_size, const cmds::GetAttribLocation& c) {
7551 uint32 name_size = c.data_size;
7552 const char* name = GetSharedMemoryAs<const char*>(
7553 c.name_shm_id, c.name_shm_offset, name_size);
7555 return error::kOutOfBounds;
7557 String name_str(name, name_size);
7558 return GetAttribLocationHelper(
7559 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7562 error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
7563 uint32 immediate_data_size, const cmds::GetAttribLocationBucket& c) {
7564 Bucket* bucket = GetBucket(c.name_bucket_id);
7566 return error::kInvalidArguments;
7568 std::string name_str;
7569 if (!bucket->GetAsString(&name_str)) {
7570 return error::kInvalidArguments;
7572 return GetAttribLocationHelper(
7573 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7576 error::Error GLES2DecoderImpl::GetUniformLocationHelper(
7577 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7578 const std::string& name_str) {
7579 if (!StringIsValidForGLES(name_str.c_str())) {
7581 GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
7582 return error::kNoError;
7584 Program* program = GetProgramInfoNotShader(
7585 client_id, "glGetUniformLocation");
7587 return error::kNoError;
7589 if (!program->IsValid()) {
7591 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
7592 return error::kNoError;
7594 GLint* location = GetSharedMemoryAs<GLint*>(
7595 location_shm_id, location_shm_offset, sizeof(GLint));
7597 return error::kOutOfBounds;
7599 // Require the client to init this incase the context is lost an we are no
7600 // longer executing commands.
7601 if (*location != -1) {
7602 return error::kGenericError;
7604 *location = program->GetUniformFakeLocation(name_str);
7605 return error::kNoError;
7608 error::Error GLES2DecoderImpl::HandleGetUniformLocation(
7609 uint32 immediate_data_size, const cmds::GetUniformLocation& c) {
7610 uint32 name_size = c.data_size;
7611 const char* name = GetSharedMemoryAs<const char*>(
7612 c.name_shm_id, c.name_shm_offset, name_size);
7614 return error::kOutOfBounds;
7616 String name_str(name, name_size);
7617 return GetUniformLocationHelper(
7618 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7621 error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
7622 uint32 immediate_data_size, const cmds::GetUniformLocationBucket& c) {
7623 Bucket* bucket = GetBucket(c.name_bucket_id);
7625 return error::kInvalidArguments;
7627 std::string name_str;
7628 if (!bucket->GetAsString(&name_str)) {
7629 return error::kInvalidArguments;
7631 return GetUniformLocationHelper(
7632 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7635 error::Error GLES2DecoderImpl::HandleGetString(
7636 uint32 immediate_data_size, const cmds::GetString& c) {
7637 GLenum name = static_cast<GLenum>(c.name);
7638 if (!validators_->string_type.IsValid(name)) {
7639 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name");
7640 return error::kNoError;
7642 const char* str = reinterpret_cast<const char*>(glGetString(name));
7643 std::string extensions;
7646 str = "OpenGL ES 2.0 Chromium";
7648 case GL_SHADING_LANGUAGE_VERSION:
7649 str = "OpenGL ES GLSL ES 1.0 Chromium";
7653 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
7654 // They are used by WEBGL_debug_renderer_info.
7655 if (!force_webgl_glsl_validation_)
7660 // For WebGL contexts, strip out the OES derivatives and
7661 // EXT frag depth extensions if they have not been enabled.
7662 if (force_webgl_glsl_validation_) {
7663 extensions = feature_info_->extensions();
7664 if (!derivatives_explicitly_enabled_) {
7665 size_t offset = extensions.find(kOESDerivativeExtension);
7666 if (std::string::npos != offset) {
7667 extensions.replace(offset, arraysize(kOESDerivativeExtension),
7671 if (!frag_depth_explicitly_enabled_) {
7672 size_t offset = extensions.find(kEXTFragDepthExtension);
7673 if (std::string::npos != offset) {
7674 extensions.replace(offset, arraysize(kEXTFragDepthExtension),
7678 if (!draw_buffers_explicitly_enabled_) {
7679 size_t offset = extensions.find(kEXTDrawBuffersExtension);
7680 if (std::string::npos != offset) {
7681 extensions.replace(offset, arraysize(kEXTDrawBuffersExtension),
7686 extensions = feature_info_->extensions().c_str();
7688 if (supports_post_sub_buffer_)
7689 extensions += " GL_CHROMIUM_post_sub_buffer";
7690 str = extensions.c_str();
7696 Bucket* bucket = CreateBucket(c.bucket_id);
7697 bucket->SetFromString(str);
7698 return error::kNoError;
7701 error::Error GLES2DecoderImpl::HandleBufferData(
7702 uint32 immediate_data_size, const cmds::BufferData& c) {
7703 GLenum target = static_cast<GLenum>(c.target);
7704 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
7705 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
7706 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
7707 GLenum usage = static_cast<GLenum>(c.usage);
7708 const void* data = NULL;
7709 if (data_shm_id != 0 || data_shm_offset != 0) {
7710 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
7712 return error::kOutOfBounds;
7715 buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
7716 return error::kNoError;
7719 void GLES2DecoderImpl::DoBufferSubData(
7720 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
7721 // Just delegate it. Some validation is actually done before this.
7722 buffer_manager()->ValidateAndDoBufferSubData(
7723 &state_, target, offset, size, data);
7726 bool GLES2DecoderImpl::ClearLevel(
7727 unsigned service_id,
7728 unsigned bind_target,
7731 unsigned internal_format,
7736 bool is_texture_immutable) {
7737 uint32 channels = GLES2Util::GetChannelsForFormat(format);
7738 if (feature_info_->feature_flags().angle_depth_texture &&
7739 (channels & GLES2Util::kDepth) != 0) {
7740 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
7741 // on depth formats.
7743 glGenFramebuffersEXT(1, &fb);
7744 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
7746 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
7747 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
7748 GL_DEPTH_ATTACHMENT;
7750 glFramebufferTexture2DEXT(
7751 GL_DRAW_FRAMEBUFFER_EXT, attachment, target, service_id, level);
7752 // ANGLE promises a depth only attachment ok.
7753 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
7754 GL_FRAMEBUFFER_COMPLETE) {
7761 glDisable(GL_SCISSOR_TEST);
7762 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
7764 RestoreClearState();
7766 glDeleteFramebuffersEXT(1, &fb);
7767 Framebuffer* framebuffer =
7768 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
7769 GLuint fb_service_id =
7770 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
7771 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
7775 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
7778 uint32 padded_row_size;
7779 if (!GLES2Util::ComputeImageDataSizes(
7780 width, height, format, type, state_.unpack_alignment, &size,
7781 NULL, &padded_row_size)) {
7785 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
7789 if (size > kMaxZeroSize) {
7790 if (kMaxZeroSize < padded_row_size) {
7791 // That'd be an awfully large texture.
7794 // We should never have a large total size with a zero row size.
7795 DCHECK_GT(padded_row_size, 0U);
7796 tile_height = kMaxZeroSize / padded_row_size;
7797 if (!GLES2Util::ComputeImageDataSizes(
7798 width, tile_height, format, type, state_.unpack_alignment, &size,
7803 tile_height = height;
7806 // Assumes the size has already been checked.
7807 scoped_ptr<char[]> zero(new char[size]);
7808 memset(zero.get(), 0, size);
7809 glBindTexture(bind_target, service_id);
7812 while (y < height) {
7813 GLint h = y + tile_height > height ? height - y : tile_height;
7814 if (is_texture_immutable || h != height) {
7815 glTexSubImage2D(target, level, 0, y, width, h, format, type, zero.get());
7818 target, level, internal_format, width, h, 0, format, type,
7823 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
7824 &state_, bind_target);
7825 glBindTexture(bind_target, texture ? texture->service_id() : 0);
7831 const int kS3TCBlockWidth = 4;
7832 const int kS3TCBlockHeight = 4;
7833 const int kS3TCDXT1BlockSize = 8;
7834 const int kS3TCDXT3AndDXT5BlockSize = 16;
7835 const int kETC1BlockWidth = 4;
7836 const int kETC1BlockHeight = 4;
7837 const int kETC1BlockSize = 8;
7839 bool IsValidDXTSize(GLint level, GLsizei size) {
7840 return (size == 1) ||
7841 (size == 2) || !(size % kS3TCBlockWidth);
7844 } // anonymous namespace.
7846 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
7847 const char* function_name,
7848 GLsizei width, GLsizei height, GLenum format, size_t size) {
7849 unsigned int bytes_required = 0;
7852 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7853 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: {
7854 int num_blocks_across =
7855 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
7856 int num_blocks_down =
7857 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
7858 int num_blocks = num_blocks_across * num_blocks_down;
7859 bytes_required = num_blocks * kS3TCDXT1BlockSize;
7862 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7863 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7864 int num_blocks_across =
7865 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
7866 int num_blocks_down =
7867 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
7868 int num_blocks = num_blocks_across * num_blocks_down;
7869 bytes_required = num_blocks * kS3TCDXT3AndDXT5BlockSize;
7872 case GL_ETC1_RGB8_OES: {
7873 int num_blocks_across =
7874 (width + kETC1BlockWidth - 1) / kETC1BlockWidth;
7875 int num_blocks_down =
7876 (height + kETC1BlockHeight - 1) / kETC1BlockHeight;
7877 int num_blocks = num_blocks_across * num_blocks_down;
7878 bytes_required = num_blocks * kETC1BlockSize;
7882 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
7886 if (size != bytes_required) {
7888 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
7895 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
7896 const char* function_name,
7897 GLint level, GLsizei width, GLsizei height, GLenum format) {
7899 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7900 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
7901 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7902 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7903 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
7905 GL_INVALID_OPERATION, function_name,
7906 "width or height invalid for level");
7911 case GL_ETC1_RGB8_OES:
7912 if (width <= 0 || height <= 0) {
7914 GL_INVALID_OPERATION, function_name,
7915 "width or height invalid for level");
7924 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
7925 const char* function_name,
7926 GLenum target, GLint level, GLint xoffset, GLint yoffset,
7927 GLsizei width, GLsizei height, GLenum format,
7929 if (xoffset < 0 || yoffset < 0) {
7931 GL_INVALID_VALUE, function_name, "xoffset or yoffset < 0");
7936 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7937 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
7938 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7939 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7940 const int kBlockWidth = 4;
7941 const int kBlockHeight = 4;
7942 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
7944 GL_INVALID_OPERATION, function_name,
7945 "xoffset or yoffset not multiple of 4");
7948 GLsizei tex_width = 0;
7949 GLsizei tex_height = 0;
7950 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
7951 width - xoffset > tex_width ||
7952 height - yoffset > tex_height) {
7954 GL_INVALID_OPERATION, function_name, "dimensions out of range");
7957 return ValidateCompressedTexDimensions(
7958 function_name, level, width, height, format);
7960 case GL_ETC1_RGB8_OES: {
7962 GL_INVALID_OPERATION, function_name,
7963 "not supported for ECT1_RGB8_OES textures");
7971 error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
7974 GLenum internal_format,
7980 // TODO(gman): Validate image_size is correct for width, height and format.
7981 if (!validators_->texture_target.IsValid(target)) {
7982 LOCAL_SET_GL_ERROR_INVALID_ENUM(
7983 "glCompressedTexImage2D", target, "target");
7984 return error::kNoError;
7986 if (!validators_->compressed_texture_format.IsValid(
7988 LOCAL_SET_GL_ERROR_INVALID_ENUM(
7989 "glCompressedTexImage2D", internal_format, "internal_format");
7990 return error::kNoError;
7992 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
7996 "glCompressedTexImage2D", "dimensions out of range");
7997 return error::kNoError;
7999 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8004 "glCompressedTexImage2D", "unknown texture target");
8005 return error::kNoError;
8007 Texture* texture = texture_ref->texture();
8008 if (texture->IsImmutable()) {
8010 GL_INVALID_OPERATION,
8011 "glCompressedTexImage2D", "texture is immutable");
8012 return error::kNoError;
8015 if (!ValidateCompressedTexDimensions(
8016 "glCompressedTexImage2D", level, width, height, internal_format) ||
8017 !ValidateCompressedTexFuncData(
8018 "glCompressedTexImage2D", width, height, internal_format, image_size)) {
8019 return error::kNoError;
8022 if (!EnsureGPUMemoryAvailable(image_size)) {
8024 GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory");
8025 return error::kNoError;
8028 if (texture->IsAttachedToFramebuffer()) {
8029 framebuffer_state_.clear_state_dirty = true;
8032 scoped_ptr<int8[]> zero;
8034 zero.reset(new int8[image_size]);
8035 memset(zero.get(), 0, image_size);
8038 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
8039 glCompressedTexImage2D(
8040 target, level, internal_format, width, height, border, image_size, data);
8041 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
8042 if (error == GL_NO_ERROR) {
8043 texture_manager()->SetLevelInfo(
8044 texture_ref, target, level, internal_format,
8045 width, height, 1, border, 0, 0, true);
8047 return error::kNoError;
8050 error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
8051 uint32 immediate_data_size, const cmds::CompressedTexImage2D& c) {
8052 GLenum target = static_cast<GLenum>(c.target);
8053 GLint level = static_cast<GLint>(c.level);
8054 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8055 GLsizei width = static_cast<GLsizei>(c.width);
8056 GLsizei height = static_cast<GLsizei>(c.height);
8057 GLint border = static_cast<GLint>(c.border);
8058 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
8059 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
8060 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
8061 const void* data = NULL;
8062 if (data_shm_id != 0 || data_shm_offset != 0) {
8063 data = GetSharedMemoryAs<const void*>(
8064 data_shm_id, data_shm_offset, image_size);
8066 return error::kOutOfBounds;
8069 return DoCompressedTexImage2D(
8070 target, level, internal_format, width, height, border, image_size, data);
8073 error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
8074 uint32 immediate_data_size, const cmds::CompressedTexImage2DBucket& c) {
8075 GLenum target = static_cast<GLenum>(c.target);
8076 GLint level = static_cast<GLint>(c.level);
8077 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8078 GLsizei width = static_cast<GLsizei>(c.width);
8079 GLsizei height = static_cast<GLsizei>(c.height);
8080 GLint border = static_cast<GLint>(c.border);
8081 Bucket* bucket = GetBucket(c.bucket_id);
8083 return error::kInvalidArguments;
8085 uint32 data_size = bucket->size();
8086 GLsizei imageSize = data_size;
8087 const void* data = bucket->GetData(0, data_size);
8089 return error::kInvalidArguments;
8091 return DoCompressedTexImage2D(
8092 target, level, internal_format, width, height, border,
8096 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
8097 uint32 immediate_data_size,
8098 const cmds::CompressedTexSubImage2DBucket& c) {
8099 GLenum target = static_cast<GLenum>(c.target);
8100 GLint level = static_cast<GLint>(c.level);
8101 GLint xoffset = static_cast<GLint>(c.xoffset);
8102 GLint yoffset = static_cast<GLint>(c.yoffset);
8103 GLsizei width = static_cast<GLsizei>(c.width);
8104 GLsizei height = static_cast<GLsizei>(c.height);
8105 GLenum format = static_cast<GLenum>(c.format);
8106 Bucket* bucket = GetBucket(c.bucket_id);
8108 return error::kInvalidArguments;
8110 uint32 data_size = bucket->size();
8111 GLsizei imageSize = data_size;
8112 const void* data = bucket->GetData(0, data_size);
8114 return error::kInvalidArguments;
8116 if (!validators_->texture_target.IsValid(target)) {
8118 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
8119 return error::kNoError;
8121 if (!validators_->compressed_texture_format.IsValid(format)) {
8122 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8123 "glCompressedTexSubImage2D", format, "format");
8124 return error::kNoError;
8128 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
8129 return error::kNoError;
8133 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
8134 return error::kNoError;
8136 if (imageSize < 0) {
8138 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
8139 return error::kNoError;
8141 DoCompressedTexSubImage2D(
8142 target, level, xoffset, yoffset, width, height, format, imageSize, data);
8143 return error::kNoError;
8146 error::Error GLES2DecoderImpl::HandleTexImage2D(
8147 uint32 immediate_data_size, const cmds::TexImage2D& c) {
8148 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexImage2D");
8149 // Set as failed for now, but if it successed, this will be set to not failed.
8150 texture_state_.tex_image_2d_failed = true;
8151 GLenum target = static_cast<GLenum>(c.target);
8152 GLint level = static_cast<GLint>(c.level);
8153 // TODO(kloveless): Change TexImage2D command to use unsigned integer
8154 // for internalformat.
8155 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8156 GLsizei width = static_cast<GLsizei>(c.width);
8157 GLsizei height = static_cast<GLsizei>(c.height);
8158 GLint border = static_cast<GLint>(c.border);
8159 GLenum format = static_cast<GLenum>(c.format);
8160 GLenum type = static_cast<GLenum>(c.type);
8161 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
8162 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
8164 if (!GLES2Util::ComputeImageDataSizes(
8165 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
8167 return error::kOutOfBounds;
8169 const void* pixels = NULL;
8170 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
8171 pixels = GetSharedMemoryAs<const void*>(
8172 pixels_shm_id, pixels_shm_offset, pixels_size);
8174 return error::kOutOfBounds;
8178 TextureManager::DoTextImage2DArguments args = {
8179 target, level, internal_format, width, height, border, format, type,
8180 pixels, pixels_size};
8181 texture_manager()->ValidateAndDoTexImage2D(
8182 &texture_state_, &state_, &framebuffer_state_, args);
8183 return error::kNoError;
8186 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
8195 const void * data) {
8196 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8200 GL_INVALID_OPERATION,
8201 "glCompressedTexSubImage2D", "unknown texture for target");
8204 Texture* texture = texture_ref->texture();
8206 GLenum internal_format = 0;
8207 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
8209 GL_INVALID_OPERATION,
8210 "glCompressedTexSubImage2D", "level does not exist.");
8213 if (internal_format != format) {
8215 GL_INVALID_OPERATION,
8216 "glCompressedTexSubImage2D", "format does not match internal format.");
8219 if (!texture->ValidForTexture(
8220 target, level, xoffset, yoffset, width, height, type)) {
8222 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
8226 if (!ValidateCompressedTexFuncData(
8227 "glCompressedTexSubImage2D", width, height, format, image_size) ||
8228 !ValidateCompressedTexSubDimensions(
8229 "glCompressedTexSubImage2D",
8230 target, level, xoffset, yoffset, width, height, format, texture)) {
8235 // Note: There is no need to deal with texture cleared tracking here
8236 // because the validation above means you can only get here if the level
8237 // is already a matching compressed format and in that case
8238 // CompressedTexImage2D already cleared the texture.
8239 glCompressedTexSubImage2D(
8240 target, level, xoffset, yoffset, width, height, format, image_size, data);
8244 GLint start, GLint range, GLint sourceRange,
8245 GLint* out_start, GLint* out_range) {
8252 GLint end = start + range;
8253 if (end > sourceRange) {
8254 range -= end - sourceRange;
8260 void GLES2DecoderImpl::DoCopyTexImage2D(
8263 GLenum internal_format,
8269 DCHECK(!ShouldDeferReads());
8270 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8274 GL_INVALID_OPERATION,
8275 "glCopyTexImage2D", "unknown texture for target");
8278 Texture* texture = texture_ref->texture();
8279 if (texture->IsImmutable()) {
8281 GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
8283 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
8286 GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
8289 if (!texture_manager()->ValidateFormatAndTypeCombination(
8290 state_.GetErrorState(), "glCopyTexImage2D", internal_format,
8291 GL_UNSIGNED_BYTE)) {
8295 // Check we have compatible formats.
8296 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8297 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8298 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
8300 if ((channels_needed & channels_exist) != channels_needed) {
8302 GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
8306 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8308 GL_INVALID_OPERATION,
8309 "glCopyTexImage2D", "can not be used with depth or stencil textures");
8313 uint32 estimated_size = 0;
8314 if (!GLES2Util::ComputeImageDataSizes(
8315 width, height, internal_format, GL_UNSIGNED_BYTE, state_.unpack_alignment,
8316 &estimated_size, NULL, NULL)) {
8318 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large");
8322 if (!EnsureGPUMemoryAvailable(estimated_size)) {
8323 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory");
8327 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
8331 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
8332 ScopedResolvedFrameBufferBinder binder(this, false, true);
8333 gfx::Size size = GetBoundReadFrameBufferSize();
8335 if (texture->IsAttachedToFramebuffer()) {
8336 framebuffer_state_.clear_state_dirty = true;
8339 // Clip to size to source dimensions
8342 GLint copyWidth = 0;
8343 GLint copyHeight = 0;
8344 Clip(x, width, size.width(), ©X, ©Width);
8345 Clip(y, height, size.height(), ©Y, ©Height);
8349 copyWidth != width ||
8350 copyHeight != height) {
8351 // some part was clipped so clear the texture.
8353 texture->service_id(), texture->target(),
8354 target, level, internal_format, internal_format, GL_UNSIGNED_BYTE,
8355 width, height, texture->IsImmutable())) {
8357 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
8360 if (copyHeight > 0 && copyWidth > 0) {
8361 GLint dx = copyX - x;
8362 GLint dy = copyY - y;
8365 ScopedModifyPixels modify(texture_ref);
8366 glCopyTexSubImage2D(target, level,
8367 destX, destY, copyX, copyY,
8368 copyWidth, copyHeight);
8371 ScopedModifyPixels modify(texture_ref);
8372 glCopyTexImage2D(target, level, internal_format,
8373 copyX, copyY, copyWidth, copyHeight, border);
8375 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
8376 if (error == GL_NO_ERROR) {
8377 texture_manager()->SetLevelInfo(
8378 texture_ref, target, level, internal_format, width, height, 1,
8379 border, internal_format, GL_UNSIGNED_BYTE, true);
8383 void GLES2DecoderImpl::DoCopyTexSubImage2D(
8392 DCHECK(!ShouldDeferReads());
8393 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8397 GL_INVALID_OPERATION,
8398 "glCopyTexSubImage2D", "unknown texture for target");
8401 Texture* texture = texture_ref->texture();
8404 if (!texture->GetLevelType(target, level, &type, &format) ||
8405 !texture->ValidForTexture(
8406 target, level, xoffset, yoffset, width, height, type)) {
8408 GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
8411 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
8413 GL_INVALID_OPERATION,
8414 "glCopyTexSubImage2D", "async upload pending for texture");
8418 // Check we have compatible formats.
8419 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8420 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8421 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
8423 if (!channels_needed ||
8424 (channels_needed & channels_exist) != channels_needed) {
8426 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
8430 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8432 GL_INVALID_OPERATION,
8433 "glCopySubImage2D", "can not be used with depth or stencil textures");
8437 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
8441 ScopedResolvedFrameBufferBinder binder(this, false, true);
8442 gfx::Size size = GetBoundReadFrameBufferSize();
8445 GLint copyWidth = 0;
8446 GLint copyHeight = 0;
8447 Clip(x, width, size.width(), ©X, ©Width);
8448 Clip(y, height, size.height(), ©Y, ©Height);
8450 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, level)) {
8452 GL_OUT_OF_MEMORY, "glCopyTexSubImage2D", "dimensions too big");
8458 copyWidth != width ||
8459 copyHeight != height) {
8460 // some part was clipped so clear the sub rect.
8461 uint32 pixels_size = 0;
8462 if (!GLES2Util::ComputeImageDataSizes(
8463 width, height, format, type, state_.unpack_alignment, &pixels_size,
8466 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
8469 scoped_ptr<char[]> zero(new char[pixels_size]);
8470 memset(zero.get(), 0, pixels_size);
8471 ScopedModifyPixels modify(texture_ref);
8473 target, level, xoffset, yoffset, width, height,
8474 format, type, zero.get());
8477 if (copyHeight > 0 && copyWidth > 0) {
8478 GLint dx = copyX - x;
8479 GLint dy = copyY - y;
8480 GLint destX = xoffset + dx;
8481 GLint destY = yoffset + dy;
8482 ScopedModifyPixels modify(texture_ref);
8483 glCopyTexSubImage2D(target, level,
8484 destX, destY, copyX, copyY,
8485 copyWidth, copyHeight);
8489 bool GLES2DecoderImpl::ValidateTexSubImage2D(
8490 error::Error* error,
8491 const char* function_name,
8500 const void * data) {
8501 (*error) = error::kNoError;
8502 if (!validators_->texture_target.IsValid(target)) {
8503 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
8507 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
8511 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
8514 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8518 GL_INVALID_OPERATION,
8519 function_name, "unknown texture for target");
8522 Texture* texture = texture_ref->texture();
8523 GLenum current_type = 0;
8524 GLenum internal_format = 0;
8525 if (!texture->GetLevelType(target, level, ¤t_type, &internal_format)) {
8527 GL_INVALID_OPERATION, function_name, "level does not exist.");
8530 if (!texture_manager()->ValidateTextureParameters(state_.GetErrorState(),
8531 function_name, format, type, internal_format, level)) {
8534 if (type != current_type) {
8536 GL_INVALID_OPERATION,
8537 function_name, "type does not match type of texture.");
8540 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
8542 GL_INVALID_OPERATION,
8543 function_name, "async upload pending for texture");
8546 if (!texture->ValidForTexture(
8547 target, level, xoffset, yoffset, width, height, type)) {
8548 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
8551 if ((GLES2Util::GetChannelsForFormat(format) &
8552 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8554 GL_INVALID_OPERATION,
8555 function_name, "can not supply data for depth or stencil textures");
8559 (*error) = error::kOutOfBounds;
8565 error::Error GLES2DecoderImpl::DoTexSubImage2D(
8574 const void * data) {
8575 error::Error error = error::kNoError;
8576 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level,
8577 xoffset, yoffset, width, height, format, type, data)) {
8580 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8582 Texture* texture = texture_ref->texture();
8583 GLsizei tex_width = 0;
8584 GLsizei tex_height = 0;
8585 bool ok = texture->GetLevelSize(target, level, &tex_width, &tex_height);
8587 if (xoffset != 0 || yoffset != 0 ||
8588 width != tex_width || height != tex_height) {
8589 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
8592 GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big");
8593 return error::kNoError;
8595 ScopedTextureUploadTimer timer(&texture_state_);
8597 target, level, xoffset, yoffset, width, height, format, type, data);
8598 return error::kNoError;
8601 if (!texture_state_.texsubimage2d_faster_than_teximage2d &&
8602 !texture->IsImmutable()) {
8603 ScopedTextureUploadTimer timer(&texture_state_);
8604 GLenum internal_format;
8606 texture->GetLevelType(target, level, &tex_type, &internal_format);
8607 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
8610 target, level, internal_format, width, height, 0, format, type, data);
8612 ScopedTextureUploadTimer timer(&texture_state_);
8614 target, level, xoffset, yoffset, width, height, format, type, data);
8616 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
8617 return error::kNoError;
8620 error::Error GLES2DecoderImpl::HandleTexSubImage2D(
8621 uint32 immediate_data_size, const cmds::TexSubImage2D& c) {
8622 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexSubImage2D");
8623 GLboolean internal = static_cast<GLboolean>(c.internal);
8624 if (internal == GL_TRUE && texture_state_.tex_image_2d_failed)
8625 return error::kNoError;
8627 GLenum target = static_cast<GLenum>(c.target);
8628 GLint level = static_cast<GLint>(c.level);
8629 GLint xoffset = static_cast<GLint>(c.xoffset);
8630 GLint yoffset = static_cast<GLint>(c.yoffset);
8631 GLsizei width = static_cast<GLsizei>(c.width);
8632 GLsizei height = static_cast<GLsizei>(c.height);
8633 GLenum format = static_cast<GLenum>(c.format);
8634 GLenum type = static_cast<GLenum>(c.type);
8636 if (!GLES2Util::ComputeImageDataSizes(
8637 width, height, format, type, state_.unpack_alignment, &data_size,
8639 return error::kOutOfBounds;
8641 const void* pixels = GetSharedMemoryAs<const void*>(
8642 c.pixels_shm_id, c.pixels_shm_offset, data_size);
8643 return DoTexSubImage2D(
8644 target, level, xoffset, yoffset, width, height, format, type, pixels);
8647 error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
8648 uint32 immediate_data_size, const cmds::GetVertexAttribPointerv& c) {
8649 GLuint index = static_cast<GLuint>(c.index);
8650 GLenum pname = static_cast<GLenum>(c.pname);
8651 typedef cmds::GetVertexAttribPointerv::Result Result;
8652 Result* result = GetSharedMemoryAs<Result*>(
8653 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
8655 return error::kOutOfBounds;
8657 // Check that the client initialized the result.
8658 if (result->size != 0) {
8659 return error::kInvalidArguments;
8661 if (!validators_->vertex_pointer.IsValid(pname)) {
8662 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8663 "glGetVertexAttribPointerv", pname, "pname");
8664 return error::kNoError;
8666 if (index >= group_->max_vertex_attribs()) {
8668 GL_INVALID_VALUE, "glGetVertexAttribPointerv", "index out of range.");
8669 return error::kNoError;
8671 result->SetNumResults(1);
8672 *result->GetData() =
8673 state_.vertex_attrib_manager->GetVertexAttrib(index)->offset();
8674 return error::kNoError;
8677 bool GLES2DecoderImpl::GetUniformSetup(
8678 GLuint program_id, GLint fake_location,
8679 uint32 shm_id, uint32 shm_offset,
8680 error::Error* error, GLint* real_location,
8681 GLuint* service_id, void** result_pointer, GLenum* result_type) {
8684 DCHECK(result_pointer);
8685 DCHECK(result_type);
8686 DCHECK(real_location);
8687 *error = error::kNoError;
8688 // Make sure we have enough room for the result on failure.
8689 SizedResult<GLint>* result;
8690 result = GetSharedMemoryAs<SizedResult<GLint>*>(
8691 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
8693 *error = error::kOutOfBounds;
8696 *result_pointer = result;
8697 // Set the result size to 0 so the client does not have to check for success.
8698 result->SetNumResults(0);
8699 Program* program = GetProgramInfoNotShader(program_id, "glGetUniform");
8703 if (!program->IsValid()) {
8704 // Program was not linked successfully. (ie, glLinkProgram)
8706 GL_INVALID_OPERATION, "glGetUniform", "program not linked");
8709 *service_id = program->service_id();
8710 GLint array_index = -1;
8711 const Program::UniformInfo* uniform_info =
8712 program->GetUniformInfoByFakeLocation(
8713 fake_location, real_location, &array_index);
8714 if (!uniform_info) {
8715 // No such location.
8717 GL_INVALID_OPERATION, "glGetUniform", "unknown location");
8720 GLenum type = uniform_info->type;
8721 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
8723 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
8726 result = GetSharedMemoryAs<SizedResult<GLint>*>(
8727 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
8729 *error = error::kOutOfBounds;
8732 result->size = size;
8733 *result_type = type;
8737 error::Error GLES2DecoderImpl::HandleGetUniformiv(
8738 uint32 immediate_data_size, const cmds::GetUniformiv& c) {
8739 GLuint program = c.program;
8740 GLint fake_location = c.location;
8743 GLint real_location = -1;
8746 if (GetUniformSetup(
8747 program, fake_location, c.params_shm_id, c.params_shm_offset,
8748 &error, &real_location, &service_id, &result, &result_type)) {
8750 service_id, real_location,
8751 static_cast<cmds::GetUniformiv::Result*>(result)->GetData());
8756 error::Error GLES2DecoderImpl::HandleGetUniformfv(
8757 uint32 immediate_data_size, const cmds::GetUniformfv& c) {
8758 GLuint program = c.program;
8759 GLint fake_location = c.location;
8761 GLint real_location = -1;
8763 typedef cmds::GetUniformfv::Result Result;
8766 if (GetUniformSetup(
8767 program, fake_location, c.params_shm_id, c.params_shm_offset,
8768 &error, &real_location, &service_id,
8769 reinterpret_cast<void**>(&result), &result_type)) {
8770 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
8771 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
8772 GLsizei num_values = result->GetNumResults();
8773 scoped_ptr<GLint[]> temp(new GLint[num_values]);
8774 glGetUniformiv(service_id, real_location, temp.get());
8775 GLfloat* dst = result->GetData();
8776 for (GLsizei ii = 0; ii < num_values; ++ii) {
8777 dst[ii] = (temp[ii] != 0);
8780 glGetUniformfv(service_id, real_location, result->GetData());
8786 error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
8787 uint32 immediate_data_size, const cmds::GetShaderPrecisionFormat& c) {
8788 GLenum shader_type = static_cast<GLenum>(c.shadertype);
8789 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
8790 typedef cmds::GetShaderPrecisionFormat::Result Result;
8791 Result* result = GetSharedMemoryAs<Result*>(
8792 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8794 return error::kOutOfBounds;
8796 // Check that the client initialized the result.
8797 if (result->success != 0) {
8798 return error::kInvalidArguments;
8800 if (!validators_->shader_type.IsValid(shader_type)) {
8801 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8802 "glGetShaderPrecisionFormat", shader_type, "shader_type");
8803 return error::kNoError;
8805 if (!validators_->shader_precision.IsValid(precision_type)) {
8806 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8807 "glGetShaderPrecisionFormat", precision_type, "precision_type");
8808 return error::kNoError;
8811 result->success = 1; // true
8813 GLint range[2] = { 0, 0 };
8814 GLint precision = 0;
8815 GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
8817 result->min_range = range[0];
8818 result->max_range = range[1];
8819 result->precision = precision;
8821 return error::kNoError;
8824 error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
8825 uint32 immediate_data_size, const cmds::GetAttachedShaders& c) {
8826 uint32 result_size = c.result_size;
8827 GLuint program_id = static_cast<GLuint>(c.program);
8828 Program* program = GetProgramInfoNotShader(
8829 program_id, "glGetAttachedShaders");
8831 return error::kNoError;
8833 typedef cmds::GetAttachedShaders::Result Result;
8834 uint32 max_count = Result::ComputeMaxResults(result_size);
8835 Result* result = GetSharedMemoryAs<Result*>(
8836 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
8838 return error::kOutOfBounds;
8840 // Check that the client initialized the result.
8841 if (result->size != 0) {
8842 return error::kInvalidArguments;
8845 glGetAttachedShaders(
8846 program->service_id(), max_count, &count, result->GetData());
8847 for (GLsizei ii = 0; ii < count; ++ii) {
8848 if (!shader_manager()->GetClientId(result->GetData()[ii],
8849 &result->GetData()[ii])) {
8851 return error::kGenericError;
8854 result->SetNumResults(count);
8855 return error::kNoError;
8858 error::Error GLES2DecoderImpl::HandleGetActiveUniform(
8859 uint32 immediate_data_size, const cmds::GetActiveUniform& c) {
8860 GLuint program_id = c.program;
8861 GLuint index = c.index;
8862 uint32 name_bucket_id = c.name_bucket_id;
8863 typedef cmds::GetActiveUniform::Result Result;
8864 Result* result = GetSharedMemoryAs<Result*>(
8865 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8867 return error::kOutOfBounds;
8869 // Check that the client initialized the result.
8870 if (result->success != 0) {
8871 return error::kInvalidArguments;
8873 Program* program = GetProgramInfoNotShader(
8874 program_id, "glGetActiveUniform");
8876 return error::kNoError;
8878 const Program::UniformInfo* uniform_info =
8879 program->GetUniformInfo(index);
8880 if (!uniform_info) {
8882 GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
8883 return error::kNoError;
8885 result->success = 1; // true.
8886 result->size = uniform_info->size;
8887 result->type = uniform_info->type;
8888 Bucket* bucket = CreateBucket(name_bucket_id);
8889 bucket->SetFromString(uniform_info->name.c_str());
8890 return error::kNoError;
8893 error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
8894 uint32 immediate_data_size, const cmds::GetActiveAttrib& c) {
8895 GLuint program_id = c.program;
8896 GLuint index = c.index;
8897 uint32 name_bucket_id = c.name_bucket_id;
8898 typedef cmds::GetActiveAttrib::Result Result;
8899 Result* result = GetSharedMemoryAs<Result*>(
8900 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8902 return error::kOutOfBounds;
8904 // Check that the client initialized the result.
8905 if (result->success != 0) {
8906 return error::kInvalidArguments;
8908 Program* program = GetProgramInfoNotShader(
8909 program_id, "glGetActiveAttrib");
8911 return error::kNoError;
8913 const Program::VertexAttrib* attrib_info =
8914 program->GetAttribInfo(index);
8917 GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
8918 return error::kNoError;
8920 result->success = 1; // true.
8921 result->size = attrib_info->size;
8922 result->type = attrib_info->type;
8923 Bucket* bucket = CreateBucket(name_bucket_id);
8924 bucket->SetFromString(attrib_info->name.c_str());
8925 return error::kNoError;
8928 error::Error GLES2DecoderImpl::HandleShaderBinary(
8929 uint32 immediate_data_size, const cmds::ShaderBinary& c) {
8930 #if 1 // No binary shader support.
8931 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
8932 return error::kNoError;
8934 GLsizei n = static_cast<GLsizei>(c.n);
8936 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
8937 return error::kNoError;
8939 GLsizei length = static_cast<GLsizei>(c.length);
8941 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
8942 return error::kNoError;
8945 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
8946 return error::kOutOfBounds;
8948 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
8949 c.shaders_shm_id, c.shaders_shm_offset, data_size);
8950 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
8951 const void* binary = GetSharedMemoryAs<const void*>(
8952 c.binary_shm_id, c.binary_shm_offset, length);
8953 if (shaders == NULL || binary == NULL) {
8954 return error::kOutOfBounds;
8956 scoped_array<GLuint> service_ids(new GLuint[n]);
8957 for (GLsizei ii = 0; ii < n; ++ii) {
8958 Shader* shader = GetShader(shaders[ii]);
8960 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
8961 return error::kNoError;
8963 service_ids[ii] = shader->service_id();
8965 // TODO(gman): call glShaderBinary
8966 return error::kNoError;
8970 void GLES2DecoderImpl::DoSwapBuffers() {
8971 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
8973 int this_frame_number = frame_number_++;
8974 // TRACE_EVENT for gpu tests:
8975 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
8976 TRACE_EVENT_SCOPE_THREAD,
8977 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
8978 "width", (is_offscreen ? offscreen_size_.width() :
8979 surface_->GetSize().width()));
8980 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
8981 "offscreen", is_offscreen,
8982 "frame", this_frame_number);
8984 TRACE_EVENT_SYNTHETIC_DELAY("gpu.SwapBuffers");
8988 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
8991 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
8992 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
8993 is_offscreen ? offscreen_size_ : surface_->GetSize());
8996 // If offscreen then don't actually SwapBuffers to the display. Just copy
8997 // the rendered frame to another frame buffer.
8999 TRACE_EVENT2("gpu", "Offscreen",
9000 "width", offscreen_size_.width(), "height", offscreen_size_.height());
9001 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
9002 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
9003 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
9005 if (workarounds().needs_offscreen_buffer_workaround) {
9006 offscreen_saved_frame_buffer_->Create();
9010 // Allocate the offscreen saved color texture.
9011 DCHECK(offscreen_saved_color_format_);
9012 offscreen_saved_color_texture_->AllocateStorage(
9013 offscreen_size_, offscreen_saved_color_format_, false);
9015 offscreen_saved_frame_buffer_->AttachRenderTexture(
9016 offscreen_saved_color_texture_.get());
9017 if (offscreen_size_.width() != 0 && offscreen_size_.height() != 0) {
9018 if (offscreen_saved_frame_buffer_->CheckStatus() !=
9019 GL_FRAMEBUFFER_COMPLETE) {
9020 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
9021 << "because offscreen saved FBO was incomplete.";
9022 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
9026 // Clear the offscreen color texture.
9027 // TODO(piman): Is this still necessary?
9029 ScopedFrameBufferBinder binder(this,
9030 offscreen_saved_frame_buffer_->id());
9031 glClearColor(0, 0, 0, 0);
9032 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
9033 glDisable(GL_SCISSOR_TEST);
9034 glClear(GL_COLOR_BUFFER_BIT);
9035 RestoreClearState();
9039 UpdateParentTextureInfo();
9042 if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
9044 ScopedGLErrorSuppressor suppressor(
9045 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
9047 if (IsOffscreenBufferMultisampled()) {
9048 // For multisampled buffers, resolve the frame buffer.
9049 ScopedResolvedFrameBufferBinder binder(this, true, false);
9051 ScopedFrameBufferBinder binder(this,
9052 offscreen_target_frame_buffer_->id());
9054 if (offscreen_target_buffer_preserved_) {
9055 // Copy the target frame buffer to the saved offscreen texture.
9056 offscreen_saved_color_texture_->Copy(
9057 offscreen_saved_color_texture_->size(),
9058 offscreen_saved_color_format_);
9060 // Flip the textures in the parent context via the texture manager.
9061 if (!!offscreen_saved_color_texture_info_.get())
9062 offscreen_saved_color_texture_info_->texture()->
9063 SetServiceId(offscreen_target_color_texture_->id());
9065 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
9066 offscreen_target_frame_buffer_->AttachRenderTexture(
9067 offscreen_target_color_texture_.get());
9070 // Ensure the side effects of the copy are visible to the parent
9071 // context. There is no need to do this for ANGLE because it uses a
9072 // single D3D device for all contexts.
9073 if (!feature_info_->feature_flags().is_angle)
9077 if (!surface_->SwapBuffers()) {
9078 LOG(ERROR) << "Context lost because SwapBuffers failed.";
9079 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
9084 error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
9085 uint32 immediate_data_size, const cmds::EnableFeatureCHROMIUM& c) {
9086 Bucket* bucket = GetBucket(c.bucket_id);
9087 if (!bucket || bucket->size() == 0) {
9088 return error::kInvalidArguments;
9090 typedef cmds::EnableFeatureCHROMIUM::Result Result;
9091 Result* result = GetSharedMemoryAs<Result*>(
9092 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9094 return error::kOutOfBounds;
9096 // Check that the client initialized the result.
9098 return error::kInvalidArguments;
9100 std::string feature_str;
9101 if (!bucket->GetAsString(&feature_str)) {
9102 return error::kInvalidArguments;
9105 // TODO(gman): make this some kind of table to function pointer thingy.
9106 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
9107 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
9108 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
9109 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
9110 // TODO(gman): decide how to remove the need for this const_cast.
9111 // I could make validators_ non const but that seems bad as this is the only
9112 // place it is needed. I could make some special friend class of validators
9113 // just to allow this to set them. That seems silly. I could refactor this
9114 // code to use the extension mechanism or the initialization attributes to
9115 // turn this feature on. Given that the only real point of this is to make
9116 // the conformance tests pass and given that there is lots of real work that
9117 // needs to be done it seems like refactoring for one to one of those
9118 // methods is a very low priority.
9119 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
9120 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
9121 force_webgl_glsl_validation_ = true;
9122 InitializeShaderTranslator();
9124 return error::kNoError;
9127 *result = 1; // true.
9128 return error::kNoError;
9131 error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
9132 uint32 immediate_data_size,
9133 const cmds::GetRequestableExtensionsCHROMIUM& c) {
9134 Bucket* bucket = CreateBucket(c.bucket_id);
9135 scoped_refptr<FeatureInfo> info(new FeatureInfo());
9136 info->Initialize(disallowed_features_);
9137 bucket->SetFromString(info->extensions().c_str());
9138 return error::kNoError;
9141 error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
9142 uint32 immediate_data_size, const cmds::RequestExtensionCHROMIUM& c) {
9143 Bucket* bucket = GetBucket(c.bucket_id);
9144 if (!bucket || bucket->size() == 0) {
9145 return error::kInvalidArguments;
9147 std::string feature_str;
9148 if (!bucket->GetAsString(&feature_str)) {
9149 return error::kInvalidArguments;
9152 bool desire_webgl_glsl_validation =
9153 feature_str.find("GL_CHROMIUM_webglsl") != std::string::npos;
9154 bool desire_standard_derivatives = false;
9155 bool desire_frag_depth = false;
9156 bool desire_draw_buffers = false;
9157 if (force_webgl_glsl_validation_) {
9158 desire_standard_derivatives =
9159 feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
9161 feature_str.find("GL_EXT_frag_depth") != std::string::npos;
9162 desire_draw_buffers =
9163 feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
9166 if (desire_webgl_glsl_validation != force_webgl_glsl_validation_ ||
9167 desire_standard_derivatives != derivatives_explicitly_enabled_ ||
9168 desire_frag_depth != frag_depth_explicitly_enabled_ ||
9169 desire_draw_buffers != draw_buffers_explicitly_enabled_) {
9170 force_webgl_glsl_validation_ |= desire_webgl_glsl_validation;
9171 derivatives_explicitly_enabled_ |= desire_standard_derivatives;
9172 frag_depth_explicitly_enabled_ |= desire_frag_depth;
9173 draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
9174 InitializeShaderTranslator();
9177 UpdateCapabilities();
9179 return error::kNoError;
9182 error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
9183 uint32 immediate_data_size, const cmds::GetMultipleIntegervCHROMIUM& c) {
9184 GLuint count = c.count;
9186 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
9187 return error::kOutOfBounds;
9189 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
9190 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
9191 if (pnames == NULL) {
9192 return error::kOutOfBounds;
9195 // We have to copy them since we use them twice so the client
9196 // can't change them between the time we validate them and the time we use
9198 scoped_ptr<GLenum[]> enums(new GLenum[count]);
9199 memcpy(enums.get(), pnames, pnames_size);
9201 // Count up the space needed for the result.
9202 uint32 num_results = 0;
9203 for (GLuint ii = 0; ii < count; ++ii) {
9204 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
9206 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9207 "glGetMultipleCHROMIUM", enums[ii], "pname");
9208 return error::kNoError;
9210 // Num will never be more than 4.
9212 if (!SafeAddUint32(num_results, num, &num_results)) {
9213 return error::kOutOfBounds;
9217 uint32 result_size = 0;
9218 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
9219 return error::kOutOfBounds;
9222 if (result_size != static_cast<uint32>(c.size)) {
9225 "glGetMultipleCHROMIUM", "bad size GL_INVALID_VALUE");
9226 return error::kNoError;
9229 GLint* results = GetSharedMemoryAs<GLint*>(
9230 c.results_shm_id, c.results_shm_offset, result_size);
9231 if (results == NULL) {
9232 return error::kOutOfBounds;
9235 // Check the results have been cleared in case the context was lost.
9236 for (uint32 ii = 0; ii < num_results; ++ii) {
9238 return error::kInvalidArguments;
9243 GLint* start = results;
9244 for (GLuint ii = 0; ii < count; ++ii) {
9245 GLsizei num_written = 0;
9246 if (!state_.GetStateAsGLint(enums[ii], results, &num_written) &&
9247 !GetHelper(enums[ii], results, &num_written)) {
9248 DoGetIntegerv(enums[ii], results);
9250 results += num_written;
9253 // Just to verify. Should this be a DCHECK?
9254 if (static_cast<uint32>(results - start) != num_results) {
9255 return error::kOutOfBounds;
9258 return error::kNoError;
9261 error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
9262 uint32 immediate_data_size, const cmds::GetProgramInfoCHROMIUM& c) {
9263 GLuint program_id = static_cast<GLuint>(c.program);
9264 uint32 bucket_id = c.bucket_id;
9265 Bucket* bucket = CreateBucket(bucket_id);
9266 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
9267 Program* program = NULL;
9268 program = GetProgram(program_id);
9269 if (!program || !program->IsValid()) {
9270 return error::kNoError;
9272 program->GetProgramInfo(program_manager(), bucket);
9273 return error::kNoError;
9276 error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
9277 switch (reset_status_) {
9279 // TODO(kbr): improve the precision of the error code in this case.
9280 // Consider delegating to context for error code if MakeCurrent fails.
9281 return error::kUnknown;
9282 case GL_GUILTY_CONTEXT_RESET_ARB:
9283 return error::kGuilty;
9284 case GL_INNOCENT_CONTEXT_RESET_ARB:
9285 return error::kInnocent;
9286 case GL_UNKNOWN_CONTEXT_RESET_ARB:
9287 return error::kUnknown;
9291 return error::kUnknown;
9294 bool GLES2DecoderImpl::WasContextLost() {
9295 if (reset_status_ != GL_NO_ERROR) {
9298 if (context_->WasAllocatedUsingRobustnessExtension()) {
9299 GLenum status = GL_NO_ERROR;
9300 if (has_robustness_extension_)
9301 status = glGetGraphicsResetStatusARB();
9302 if (status != GL_NO_ERROR) {
9303 // The graphics card was reset. Signal a lost context to the application.
9304 reset_status_ = status;
9305 reset_by_robustness_extension_ = true;
9306 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
9307 << " context lost via ARB/EXT_robustness. Reset status = "
9308 << GLES2Util::GetStringEnum(status);
9315 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() {
9316 return WasContextLost() && reset_by_robustness_extension_;
9319 void GLES2DecoderImpl::LoseContext(uint32 reset_status) {
9320 // Only loses the context once.
9321 if (reset_status_ != GL_NO_ERROR) {
9325 // Marks this context as lost.
9326 reset_status_ = reset_status;
9327 current_decoder_error_ = error::kLostContext;
9330 error::Error GLES2DecoderImpl::HandleLoseContextCHROMIUM(
9331 uint32 immediate_data_size, const cmds::LoseContextCHROMIUM& c) {
9332 GLenum current = static_cast<GLenum>(c.current);
9333 GLenum other = static_cast<GLenum>(c.other);
9334 if (!validators_->reset_status.IsValid(current)) {
9335 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9336 "glLoseContextCHROMIUM", current, "current");
9338 if (!validators_->reset_status.IsValid(other)) {
9339 LOCAL_SET_GL_ERROR_INVALID_ENUM("glLoseContextCHROMIUM", other, "other");
9341 group_->LoseContexts(other);
9342 reset_status_ = current;
9343 current_decoder_error_ = error::kLostContext;
9344 return error::kLostContext;
9347 error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
9348 uint32 immediate_data_size, const cmds::InsertSyncPointCHROMIUM& c) {
9349 return error::kUnknownCommand;
9352 error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
9353 uint32 immediate_data_size, const cmds::WaitSyncPointCHROMIUM& c) {
9354 group_->mailbox_manager()->PullTextureUpdates();
9355 if (wait_sync_point_callback_.is_null())
9356 return error::kNoError;
9358 return wait_sync_point_callback_.Run(c.sync_point) ?
9359 error::kNoError : error::kDeferCommandUntilLater;
9362 error::Error GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
9363 uint32 immediate_data_size, const cmds::DiscardBackbufferCHROMIUM& c) {
9364 if (surface_->DeferDraws())
9365 return error::kDeferCommandUntilLater;
9366 if (!surface_->SetBackbufferAllocation(false))
9367 return error::kLostContext;
9368 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
9369 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
9370 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
9371 return error::kNoError;
9374 bool GLES2DecoderImpl::GenQueriesEXTHelper(
9375 GLsizei n, const GLuint* client_ids) {
9376 for (GLsizei ii = 0; ii < n; ++ii) {
9377 if (query_manager_->GetQuery(client_ids[ii])) {
9381 // NOTE: We don't generate Query objects here. Only in BeginQueryEXT
9385 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
9386 GLsizei n, const GLuint* client_ids) {
9387 for (GLsizei ii = 0; ii < n; ++ii) {
9388 QueryManager::Query* query = query_manager_->GetQuery(client_ids[ii]);
9389 if (query && !query->IsDeleted()) {
9390 ContextState::QueryMap::iterator it =
9391 state_.current_queries.find(query->target());
9392 if (it != state_.current_queries.end())
9393 state_.current_queries.erase(it);
9395 query->Destroy(true);
9396 query_manager_->RemoveQuery(client_ids[ii]);
9401 bool GLES2DecoderImpl::ProcessPendingQueries() {
9402 if (query_manager_.get() == NULL) {
9405 if (!query_manager_->ProcessPendingQueries()) {
9406 current_decoder_error_ = error::kOutOfBounds;
9408 return query_manager_->HavePendingQueries();
9411 // Note that if there are no pending readpixels right now,
9412 // this function will call the callback immediately.
9413 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback) {
9414 if (features().use_async_readpixels && !pending_readpixel_fences_.empty()) {
9415 pending_readpixel_fences_.back()->callbacks.push_back(callback);
9421 void GLES2DecoderImpl::ProcessPendingReadPixels() {
9422 while (!pending_readpixel_fences_.empty() &&
9423 pending_readpixel_fences_.front()->fence->HasCompleted()) {
9424 std::vector<base::Closure> callbacks =
9425 pending_readpixel_fences_.front()->callbacks;
9426 pending_readpixel_fences_.pop();
9427 for (size_t i = 0; i < callbacks.size(); i++) {
9433 bool GLES2DecoderImpl::HasMoreIdleWork() {
9434 return !pending_readpixel_fences_.empty() ||
9435 async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers();
9438 void GLES2DecoderImpl::PerformIdleWork() {
9439 ProcessPendingReadPixels();
9440 if (!async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers())
9442 async_pixel_transfer_manager_->ProcessMorePendingTransfers();
9443 ProcessFinishedAsyncTransfers();
9446 error::Error GLES2DecoderImpl::HandleBeginQueryEXT(
9447 uint32 immediate_data_size, const cmds::BeginQueryEXT& c) {
9448 GLenum target = static_cast<GLenum>(c.target);
9449 GLuint client_id = static_cast<GLuint>(c.id);
9450 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
9451 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
9454 case GL_COMMANDS_ISSUED_CHROMIUM:
9455 case GL_LATENCY_QUERY_CHROMIUM:
9456 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM:
9457 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
9458 case GL_GET_ERROR_QUERY_CHROMIUM:
9461 if (!features().occlusion_query_boolean) {
9463 GL_INVALID_OPERATION, "glBeginQueryEXT",
9464 "not enabled for occlusion queries");
9465 return error::kNoError;
9470 if (state_.current_queries.find(target) != state_.current_queries.end()) {
9472 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
9473 return error::kNoError;
9476 if (client_id == 0) {
9477 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
9478 return error::kNoError;
9481 QueryManager::Query* query = query_manager_->GetQuery(client_id);
9483 // TODO(gman): Decide if we need this check.
9485 // Checks id was made by glGenQueries
9487 // From the POV of OpenGL ES 2.0 you need to call glGenQueriesEXT
9488 // for all Query ids but from the POV of the command buffer service maybe
9491 // The client can enforce this. I don't think the service cares.
9493 // IdAllocatorInterface* id_allocator =
9494 // group_->GetIdAllocator(id_namespaces::kQueries);
9495 // if (!id_allocator->InUse(client_id)) {
9496 // LOCAL_SET_GL_ERROR(
9497 // GL_INVALID_OPERATION,
9498 // "glBeginQueryEXT", "id not made by glGenQueriesEXT");
9499 // return error::kNoError;
9501 query = query_manager_->CreateQuery(
9502 target, client_id, sync_shm_id, sync_shm_offset);
9505 if (query->target() != target) {
9507 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
9508 return error::kNoError;
9509 } else if (query->shm_id() != sync_shm_id ||
9510 query->shm_offset() != sync_shm_offset) {
9511 DLOG(ERROR) << "Shared memory used by query not the same as before";
9512 return error::kInvalidArguments;
9515 if (!query_manager_->BeginQuery(query)) {
9516 return error::kOutOfBounds;
9519 state_.current_queries[target] = query;
9520 return error::kNoError;
9523 error::Error GLES2DecoderImpl::HandleEndQueryEXT(
9524 uint32 immediate_data_size, const cmds::EndQueryEXT& c) {
9525 GLenum target = static_cast<GLenum>(c.target);
9526 uint32 submit_count = static_cast<GLuint>(c.submit_count);
9527 ContextState::QueryMap::iterator it = state_.current_queries.find(target);
9529 if (it == state_.current_queries.end()) {
9531 GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
9532 return error::kNoError;
9535 QueryManager::Query* query = it->second.get();
9536 if (!query_manager_->EndQuery(query, submit_count)) {
9537 return error::kOutOfBounds;
9540 query_manager_->ProcessPendingTransferQueries();
9542 state_.current_queries.erase(it);
9543 return error::kNoError;
9546 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
9547 GLsizei n, const GLuint* client_ids) {
9548 for (GLsizei ii = 0; ii < n; ++ii) {
9549 if (GetVertexAttribManager(client_ids[ii])) {
9554 if (!features().native_vertex_array_object) {
9556 for (GLsizei ii = 0; ii < n; ++ii) {
9557 CreateVertexAttribManager(client_ids[ii], 0);
9560 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
9562 glGenVertexArraysOES(n, service_ids.get());
9563 for (GLsizei ii = 0; ii < n; ++ii) {
9564 CreateVertexAttribManager(client_ids[ii], service_ids[ii]);
9571 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
9572 GLsizei n, const GLuint* client_ids) {
9573 for (GLsizei ii = 0; ii < n; ++ii) {
9574 VertexAttribManager* vao =
9575 GetVertexAttribManager(client_ids[ii]);
9576 if (vao && !vao->IsDeleted()) {
9577 if (state_.vertex_attrib_manager.get() == vao) {
9578 state_.vertex_attrib_manager = default_vertex_attrib_manager_;
9580 RemoveVertexAttribManager(client_ids[ii]);
9585 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
9586 VertexAttribManager* vao = NULL;
9587 GLuint service_id = 0;
9588 if (client_id != 0) {
9589 vao = GetVertexAttribManager(client_id);
9591 // Unlike most Bind* methods, the spec explicitly states that VertexArray
9592 // only allows names that have been previously generated. As such, we do
9593 // not generate new names here.
9595 GL_INVALID_OPERATION,
9596 "glBindVertexArrayOES", "bad vertex array id.");
9597 current_decoder_error_ = error::kNoError;
9600 service_id = vao->service_id();
9603 vao = default_vertex_attrib_manager_.get();
9606 // Only set the VAO state if it's changed
9607 if (state_.vertex_attrib_manager.get() != vao) {
9608 state_.vertex_attrib_manager = vao;
9609 if (!features().native_vertex_array_object) {
9610 EmulateVertexArrayState();
9612 glBindVertexArrayOES(service_id);
9617 // Used when OES_vertex_array_object isn't natively supported
9618 void GLES2DecoderImpl::EmulateVertexArrayState() {
9619 // Setup the Vertex attribute state
9620 for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) {
9621 RestoreStateForAttrib(vv);
9624 // Setup the element buffer
9625 Buffer* element_array_buffer =
9626 state_.vertex_attrib_manager->element_array_buffer();
9627 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
9628 element_array_buffer ? element_array_buffer->service_id() : 0);
9631 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
9632 const VertexAttribManager* vao =
9633 GetVertexAttribManager(client_id);
9634 return vao && vao->IsValid() && !vao->IsDeleted();
9637 #if defined(OS_MACOSX)
9638 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
9639 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
9641 if (it != texture_to_io_surface_map_.end()) {
9642 // Found a previous IOSurface bound to this texture; release it.
9643 CFTypeRef surface = it->second;
9645 texture_to_io_surface_map_.erase(it);
9650 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
9651 GLenum target, GLsizei width, GLsizei height,
9652 GLuint io_surface_id, GLuint plane) {
9653 #if defined(OS_MACOSX)
9654 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
9656 GL_INVALID_OPERATION,
9657 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
9661 IOSurfaceSupport* surface_support = IOSurfaceSupport::Initialize();
9662 if (!surface_support) {
9664 GL_INVALID_OPERATION,
9665 "glTexImageIOSurface2DCHROMIUM", "only supported on 10.6.");
9669 if (target != GL_TEXTURE_RECTANGLE_ARB) {
9670 // This might be supported in the future, and if we could require
9671 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
9672 // could delete a lot of code. For now, perform strict validation so we
9673 // know what's going on.
9675 GL_INVALID_OPERATION,
9676 "glTexImageIOSurface2DCHROMIUM",
9677 "requires TEXTURE_RECTANGLE_ARB target");
9681 // Default target might be conceptually valid, but disallow it to avoid
9683 TextureRef* texture_ref =
9684 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
9687 GL_INVALID_OPERATION,
9688 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
9692 // Look up the new IOSurface. Note that because of asynchrony
9693 // between processes this might fail; during live resizing the
9694 // plugin process might allocate and release an IOSurface before
9695 // this process gets a chance to look it up. Hold on to any old
9696 // IOSurface in this case.
9697 CFTypeRef surface = surface_support->IOSurfaceLookup(io_surface_id);
9700 GL_INVALID_OPERATION,
9701 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
9705 // Release any IOSurface previously bound to this texture.
9706 ReleaseIOSurfaceForTexture(texture_ref->service_id());
9708 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
9709 texture_to_io_surface_map_.insert(
9710 std::make_pair(texture_ref->service_id(), surface));
9712 CGLContextObj context =
9713 static_cast<CGLContextObj>(context_->GetHandle());
9715 CGLError err = surface_support->CGLTexImageIOSurface2D(
9722 GL_UNSIGNED_INT_8_8_8_8_REV,
9726 if (err != kCGLNoError) {
9728 GL_INVALID_OPERATION,
9729 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
9733 texture_manager()->SetLevelInfo(
9734 texture_ref, target, 0, GL_RGBA, width, height, 1, 0,
9735 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
9738 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
9739 "glTexImageIOSurface2DCHROMIUM", "not supported.");
9743 static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
9744 switch (internalformat) {
9755 case GL_LUMINANCE8_ALPHA8_EXT:
9756 return GL_LUMINANCE_ALPHA;
9757 case GL_LUMINANCE8_EXT:
9758 return GL_LUMINANCE;
9761 case GL_RGBA32F_EXT:
9765 case GL_ALPHA32F_EXT:
9767 case GL_LUMINANCE32F_EXT:
9768 return GL_LUMINANCE;
9769 case GL_LUMINANCE_ALPHA32F_EXT:
9770 return GL_LUMINANCE_ALPHA;
9771 case GL_RGBA16F_EXT:
9775 case GL_ALPHA16F_EXT:
9777 case GL_LUMINANCE16F_EXT:
9778 return GL_LUMINANCE;
9779 case GL_LUMINANCE_ALPHA16F_EXT:
9780 return GL_LUMINANCE_ALPHA;
9788 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
9789 GLenum target, GLuint source_id, GLuint dest_id, GLint level,
9790 GLenum internal_format, GLenum dest_type) {
9791 TextureRef* dest_texture_ref = GetTexture(dest_id);
9792 TextureRef* source_texture_ref = GetTexture(source_id);
9794 if (!source_texture_ref || !dest_texture_ref) {
9796 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "unknown texture id");
9800 if (GL_TEXTURE_2D != target) {
9802 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "invalid texture target");
9806 Texture* source_texture = source_texture_ref->texture();
9807 Texture* dest_texture = dest_texture_ref->texture();
9808 if (dest_texture->target() != GL_TEXTURE_2D ||
9809 (source_texture->target() != GL_TEXTURE_2D &&
9810 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
9811 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
9812 "glCopyTextureCHROMIUM",
9813 "invalid texture target binding");
9817 int source_width, source_height, dest_width, dest_height;
9819 gfx::GLImage* image =
9820 source_texture->GetLevelImage(source_texture->target(), 0);
9822 gfx::Size size = image->GetSize();
9823 source_width = size.width();
9824 source_height = size.height();
9825 if (source_width <= 0 || source_height <= 0) {
9828 "glCopyTextureChromium", "invalid image size");
9832 if (!source_texture->GetLevelSize(
9833 source_texture->target(), 0, &source_width, &source_height)) {
9834 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
9835 "glCopyTextureChromium",
9836 "source texture has no level 0");
9840 // Check that this type of texture is allowed.
9841 if (!texture_manager()->ValidForTarget(
9842 source_texture->target(), level, source_width, source_height, 1)) {
9844 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "Bad dimensions");
9849 // Clear the source texture if necessary.
9850 if (!texture_manager()->ClearTextureLevel(
9851 this, source_texture_ref, source_texture->target(), 0)) {
9853 GL_OUT_OF_MEMORY, "glCopyTextureCHROMIUM", "dimensions too big");
9857 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
9858 // needed because it takes 10s of milliseconds to initialize.
9859 if (!copy_texture_CHROMIUM_.get()) {
9860 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
9861 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
9862 copy_texture_CHROMIUM_->Initialize(this);
9863 RestoreCurrentFramebufferBindings();
9864 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
9868 GLenum dest_type_previous;
9869 GLenum dest_internal_format;
9870 bool dest_level_defined = dest_texture->GetLevelSize(
9871 GL_TEXTURE_2D, level, &dest_width, &dest_height);
9873 if (dest_level_defined) {
9874 dest_texture->GetLevelType(GL_TEXTURE_2D, level, &dest_type_previous,
9875 &dest_internal_format);
9878 // Resize the destination texture to the dimensions of the source texture.
9879 if (!dest_level_defined || dest_width != source_width ||
9880 dest_height != source_height ||
9881 dest_internal_format != internal_format ||
9882 dest_type_previous != dest_type) {
9883 // Ensure that the glTexImage2D succeeds.
9884 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
9885 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
9887 GL_TEXTURE_2D, level, internal_format, source_width, source_height,
9888 0, internal_format, dest_type, NULL);
9889 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
9890 if (error != GL_NO_ERROR) {
9891 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
9895 texture_manager()->SetLevelInfo(
9896 dest_texture_ref, GL_TEXTURE_2D, level, internal_format, source_width,
9897 source_height, 1, 0, internal_format, dest_type, true);
9899 texture_manager()->SetLevelCleared(
9900 dest_texture_ref, GL_TEXTURE_2D, level, true);
9903 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
9904 ScopedModifyPixels modify(dest_texture_ref);
9906 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
9907 // before presenting.
9908 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
9909 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
9910 // instead of using default matrix crbug.com/226218.
9911 const static GLfloat default_matrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
9912 0.0f, 1.0f, 0.0f, 0.0f,
9913 0.0f, 0.0f, 1.0f, 0.0f,
9914 0.0f, 0.0f, 0.0f, 1.0f};
9915 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
9917 source_texture->target(),
9918 dest_texture->target(),
9919 source_texture->service_id(),
9920 dest_texture->service_id(), level,
9921 source_width, source_height,
9923 unpack_premultiply_alpha_,
9924 unpack_unpremultiply_alpha_,
9927 copy_texture_CHROMIUM_->DoCopyTexture(
9929 source_texture->target(),
9930 dest_texture->target(),
9931 source_texture->service_id(),
9932 dest_texture->service_id(), level,
9933 source_width, source_height,
9935 unpack_premultiply_alpha_,
9936 unpack_unpremultiply_alpha_);
9939 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
9942 static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
9943 switch (internalformat) {
9945 return GL_UNSIGNED_SHORT_5_6_5;
9947 return GL_UNSIGNED_SHORT_4_4_4_4;
9949 return GL_UNSIGNED_SHORT_5_5_5_1;
9951 return GL_UNSIGNED_BYTE;
9953 return GL_UNSIGNED_BYTE;
9954 case GL_LUMINANCE8_ALPHA8_EXT:
9955 return GL_UNSIGNED_BYTE;
9956 case GL_LUMINANCE8_EXT:
9957 return GL_UNSIGNED_BYTE;
9959 return GL_UNSIGNED_BYTE;
9960 case GL_RGBA32F_EXT:
9964 case GL_ALPHA32F_EXT:
9966 case GL_LUMINANCE32F_EXT:
9968 case GL_LUMINANCE_ALPHA32F_EXT:
9970 case GL_RGBA16F_EXT:
9971 return GL_HALF_FLOAT_OES;
9973 return GL_HALF_FLOAT_OES;
9974 case GL_ALPHA16F_EXT:
9975 return GL_HALF_FLOAT_OES;
9976 case GL_LUMINANCE16F_EXT:
9977 return GL_HALF_FLOAT_OES;
9978 case GL_LUMINANCE_ALPHA16F_EXT:
9979 return GL_HALF_FLOAT_OES;
9981 return GL_UNSIGNED_BYTE;
9987 void GLES2DecoderImpl::DoTexStorage2DEXT(
9990 GLenum internal_format,
9993 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT");
9994 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
9995 TextureManager::ComputeMipMapCount(target, width, height, 1) < levels) {
9997 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
10000 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10002 if (!texture_ref) {
10003 LOCAL_SET_GL_ERROR(
10004 GL_INVALID_OPERATION,
10005 "glTexStorage2DEXT", "unknown texture for target");
10008 Texture* texture = texture_ref->texture();
10009 if (texture->IsAttachedToFramebuffer()) {
10010 framebuffer_state_.clear_state_dirty = true;
10012 if (texture->IsImmutable()) {
10013 LOCAL_SET_GL_ERROR(
10014 GL_INVALID_OPERATION,
10015 "glTexStorage2DEXT", "texture is immutable");
10019 GLenum format = ExtractFormatFromStorageFormat(internal_format);
10020 GLenum type = ExtractTypeFromStorageFormat(internal_format);
10023 GLsizei level_width = width;
10024 GLsizei level_height = height;
10025 uint32 estimated_size = 0;
10026 for (int ii = 0; ii < levels; ++ii) {
10027 uint32 level_size = 0;
10028 if (!GLES2Util::ComputeImageDataSizes(
10029 level_width, level_height, format, type, state_.unpack_alignment,
10030 &estimated_size, NULL, NULL) ||
10031 !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
10032 LOCAL_SET_GL_ERROR(
10033 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large");
10036 level_width = std::max(1, level_width >> 1);
10037 level_height = std::max(1, level_height >> 1);
10039 if (!EnsureGPUMemoryAvailable(estimated_size)) {
10040 LOCAL_SET_GL_ERROR(
10041 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory");
10046 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
10047 glTexStorage2DEXT(target, levels, internal_format, width, height);
10048 GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
10049 if (error == GL_NO_ERROR) {
10050 GLsizei level_width = width;
10051 GLsizei level_height = height;
10052 for (int ii = 0; ii < levels; ++ii) {
10053 texture_manager()->SetLevelInfo(
10054 texture_ref, target, ii, format,
10055 level_width, level_height, 1, 0, format, type, false);
10056 level_width = std::max(1, level_width >> 1);
10057 level_height = std::max(1, level_height >> 1);
10059 texture->SetImmutable(true);
10063 error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
10064 uint32 immediate_data_size, const cmds::GenMailboxCHROMIUM& c) {
10065 return error::kUnknownCommand;
10068 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
10069 const GLbyte* data) {
10070 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
10071 "context", logger_.GetLogPrefix(),
10072 "mailbox[0]", static_cast<unsigned char>(data[0]));
10074 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
10075 DLOG_IF(ERROR, !mailbox.Verify()) << "ProduceTextureCHROMIUM was passed a "
10076 "mailbox that was not generated by "
10077 "GenMailboxCHROMIUM.";
10079 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10081 if (!texture_ref) {
10082 LOCAL_SET_GL_ERROR(
10083 GL_INVALID_OPERATION,
10084 "glProduceTextureCHROMIUM", "unknown texture for target");
10088 Texture* produced = texture_manager()->Produce(texture_ref);
10090 LOCAL_SET_GL_ERROR(
10091 GL_INVALID_OPERATION,
10092 "glProduceTextureCHROMIUM", "invalid texture");
10096 group_->mailbox_manager()->ProduceTexture(target, mailbox, produced);
10099 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
10100 const GLbyte* data) {
10101 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
10102 "context", logger_.GetLogPrefix(),
10103 "mailbox[0]", static_cast<unsigned char>(data[0]));
10104 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
10105 DLOG_IF(ERROR, !mailbox.Verify()) << "ConsumeTextureCHROMIUM was passed a "
10106 "mailbox that was not generated by "
10107 "GenMailboxCHROMIUM.";
10109 scoped_refptr<TextureRef> texture_ref =
10110 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10111 if (!texture_ref.get()) {
10112 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10113 "glConsumeTextureCHROMIUM",
10114 "unknown texture for target");
10117 GLuint client_id = texture_ref->client_id();
10119 LOCAL_SET_GL_ERROR(
10120 GL_INVALID_OPERATION,
10121 "glConsumeTextureCHROMIUM", "unknown texture for target");
10124 Texture* texture = group_->mailbox_manager()->ConsumeTexture(target, mailbox);
10126 LOCAL_SET_GL_ERROR(
10127 GL_INVALID_OPERATION,
10128 "glConsumeTextureCHROMIUM", "invalid mailbox name");
10131 if (texture->target() != target) {
10132 LOCAL_SET_GL_ERROR(
10133 GL_INVALID_OPERATION,
10134 "glConsumeTextureCHROMIUM", "invalid target");
10138 DeleteTexturesHelper(1, &client_id);
10139 texture_ref = texture_manager()->Consume(client_id, texture);
10140 glBindTexture(target, texture_ref->service_id());
10142 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
10143 unit.bind_target = target;
10145 case GL_TEXTURE_2D:
10146 unit.bound_texture_2d = texture_ref;
10148 case GL_TEXTURE_CUBE_MAP:
10149 unit.bound_texture_cube_map = texture_ref;
10151 case GL_TEXTURE_EXTERNAL_OES:
10152 unit.bound_texture_external_oes = texture_ref;
10154 case GL_TEXTURE_RECTANGLE_ARB:
10155 unit.bound_texture_rectangle_arb = texture_ref;
10158 NOTREACHED(); // Validation should prevent us getting here.
10163 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
10164 GLsizei length, const GLchar* marker) {
10168 debug_marker_manager_.SetMarker(
10169 length ? std::string(marker, length) : std::string(marker));
10172 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
10173 GLsizei length, const GLchar* marker) {
10177 std::string name = length ? std::string(marker, length) : std::string(marker);
10178 debug_marker_manager_.PushGroup(name);
10179 gpu_tracer_->Begin(name, kTraceGroupMarker);
10182 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
10183 debug_marker_manager_.PopGroup();
10184 gpu_tracer_->End(kTraceGroupMarker);
10187 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
10188 GLenum target, GLint image_id) {
10189 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
10191 if (target == GL_TEXTURE_CUBE_MAP) {
10192 LOCAL_SET_GL_ERROR(
10194 "glBindTexImage2DCHROMIUM", "invalid target");
10198 // Default target might be conceptually valid, but disallow it to avoid
10200 TextureRef* texture_ref =
10201 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10202 if (!texture_ref) {
10203 LOCAL_SET_GL_ERROR(
10204 GL_INVALID_OPERATION,
10205 "glBindTexImage2DCHROMIUM", "no texture bound");
10209 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
10211 LOCAL_SET_GL_ERROR(
10212 GL_INVALID_OPERATION,
10213 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
10218 ScopedGLErrorSuppressor suppressor(
10219 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
10220 if (!gl_image->BindTexImage(target)) {
10221 LOCAL_SET_GL_ERROR(
10222 GL_INVALID_OPERATION,
10223 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
10228 gfx::Size size = gl_image->GetSize();
10229 texture_manager()->SetLevelInfo(
10230 texture_ref, target, 0, GL_RGBA, size.width(), size.height(), 1, 0,
10231 GL_RGBA, GL_UNSIGNED_BYTE, true);
10232 texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image);
10235 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
10236 GLenum target, GLint image_id) {
10237 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
10239 // Default target might be conceptually valid, but disallow it to avoid
10241 TextureRef* texture_ref =
10242 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10243 if (!texture_ref) {
10244 LOCAL_SET_GL_ERROR(
10245 GL_INVALID_OPERATION,
10246 "glReleaseTexImage2DCHROMIUM", "no texture bound");
10250 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
10252 LOCAL_SET_GL_ERROR(
10253 GL_INVALID_OPERATION,
10254 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
10258 // Do nothing when image is not currently bound.
10259 if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image)
10263 ScopedGLErrorSuppressor suppressor(
10264 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
10265 gl_image->ReleaseTexImage(target);
10268 texture_manager()->SetLevelInfo(
10269 texture_ref, target, 0, GL_RGBA, 0, 0, 1, 0,
10270 GL_RGBA, GL_UNSIGNED_BYTE, false);
10273 error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
10274 uint32 immediate_data_size, const cmds::TraceBeginCHROMIUM& c) {
10275 Bucket* bucket = GetBucket(c.bucket_id);
10276 if (!bucket || bucket->size() == 0) {
10277 return error::kInvalidArguments;
10279 std::string command_name;
10280 if (!bucket->GetAsString(&command_name)) {
10281 return error::kInvalidArguments;
10283 TRACE_EVENT_COPY_ASYNC_BEGIN0("gpu", command_name.c_str(), this);
10284 if (!gpu_tracer_->Begin(command_name, kTraceCHROMIUM)) {
10285 LOCAL_SET_GL_ERROR(
10286 GL_INVALID_OPERATION,
10287 "glTraceBeginCHROMIUM", "unable to create begin trace");
10288 return error::kNoError;
10290 return error::kNoError;
10293 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
10294 if (gpu_tracer_->CurrentName().empty()) {
10295 LOCAL_SET_GL_ERROR(
10296 GL_INVALID_OPERATION,
10297 "glTraceEndCHROMIUM", "no trace begin found");
10300 TRACE_EVENT_COPY_ASYNC_END0("gpu", gpu_tracer_->CurrentName().c_str(), this);
10301 gpu_tracer_->End(kTraceCHROMIUM);
10304 void GLES2DecoderImpl::DoDrawBuffersEXT(
10305 GLsizei count, const GLenum* bufs) {
10306 if (count > static_cast<GLsizei>(group_->max_draw_buffers())) {
10307 LOCAL_SET_GL_ERROR(
10309 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
10313 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
10315 for (GLsizei i = 0; i < count; ++i) {
10316 if (bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i) &&
10317 bufs[i] != GL_NONE) {
10318 LOCAL_SET_GL_ERROR(
10319 GL_INVALID_OPERATION,
10320 "glDrawBuffersEXT",
10321 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
10325 glDrawBuffersARB(count, bufs);
10326 framebuffer->SetDrawBuffers(count, bufs);
10327 } else { // backbuffer
10329 (bufs[0] != GL_BACK && bufs[0] != GL_NONE)) {
10330 LOCAL_SET_GL_ERROR(
10331 GL_INVALID_OPERATION,
10332 "glDrawBuffersEXT",
10333 "more than one buffer or bufs not GL_NONE or GL_BACK");
10336 GLenum mapped_buf = bufs[0];
10337 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
10338 bufs[0] == GL_BACK) {
10339 mapped_buf = GL_COLOR_ATTACHMENT0;
10341 glDrawBuffersARB(count, &mapped_buf);
10342 group_->set_draw_buffer(bufs[0]);
10346 bool GLES2DecoderImpl::ValidateAsyncTransfer(
10347 const char* function_name,
10348 TextureRef* texture_ref,
10351 const void * data) {
10352 // We only support async uploads to 2D textures for now.
10353 if (GL_TEXTURE_2D != target) {
10354 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
10357 // We only support uploads to level zero for now.
10359 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "level != 0");
10362 // A transfer buffer must be bound, even for asyncTexImage2D.
10363 if (data == NULL) {
10364 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "buffer == 0");
10367 // We only support one async transfer in progress.
10368 if (!texture_ref ||
10369 async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
10370 LOCAL_SET_GL_ERROR(
10371 GL_INVALID_OPERATION,
10372 function_name, "transfer already in progress");
10378 error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
10379 uint32 immediate_data_size, const cmds::AsyncTexImage2DCHROMIUM& c) {
10380 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
10381 GLenum target = static_cast<GLenum>(c.target);
10382 GLint level = static_cast<GLint>(c.level);
10383 // TODO(kloveless): Change HandleAsyncTexImage2DCHROMIUM command to use
10384 // unsigned integer for internalformat.
10385 GLenum internal_format = static_cast<GLenum>(c.internalformat);
10386 GLsizei width = static_cast<GLsizei>(c.width);
10387 GLsizei height = static_cast<GLsizei>(c.height);
10388 GLint border = static_cast<GLint>(c.border);
10389 GLenum format = static_cast<GLenum>(c.format);
10390 GLenum type = static_cast<GLenum>(c.type);
10391 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
10392 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
10393 uint32 pixels_size;
10395 // TODO(epenner): Move this and copies of this memory validation
10396 // into ValidateTexImage2D step.
10397 if (!GLES2Util::ComputeImageDataSizes(
10398 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
10400 return error::kOutOfBounds;
10402 const void* pixels = NULL;
10403 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
10404 pixels = GetSharedMemoryAs<const void*>(
10405 pixels_shm_id, pixels_shm_offset, pixels_size);
10407 return error::kOutOfBounds;
10411 TextureManager::DoTextImage2DArguments args = {
10412 target, level, internal_format, width, height, border, format, type,
10413 pixels, pixels_size};
10414 TextureRef* texture_ref;
10415 // All the normal glTexSubImage2D validation.
10416 if (!texture_manager()->ValidateTexImage2D(
10417 &state_, "glAsyncTexImage2DCHROMIUM", args, &texture_ref)) {
10418 return error::kNoError;
10421 // Extra async validation.
10422 Texture* texture = texture_ref->texture();
10423 if (!ValidateAsyncTransfer(
10424 "glAsyncTexImage2DCHROMIUM", texture_ref, target, level, pixels))
10425 return error::kNoError;
10427 // Don't allow async redefinition of a textures.
10428 if (texture->IsDefined()) {
10429 LOCAL_SET_GL_ERROR(
10430 GL_INVALID_OPERATION,
10431 "glAsyncTexImage2DCHROMIUM", "already defined");
10432 return error::kNoError;
10435 if (!EnsureGPUMemoryAvailable(pixels_size)) {
10436 LOCAL_SET_GL_ERROR(
10437 GL_OUT_OF_MEMORY, "glAsyncTexImage2DCHROMIUM", "out of memory");
10438 return error::kNoError;
10441 // Setup the parameters.
10442 AsyncTexImage2DParams tex_params = {
10443 target, level, static_cast<GLenum>(internal_format),
10444 width, height, border, format, type};
10445 AsyncMemoryParams mem_params(
10446 GetSharedMemoryBuffer(c.pixels_shm_id), c.pixels_shm_offset, pixels_size);
10448 // Set up the async state if needed, and make the texture
10449 // immutable so the async state stays valid. The level info
10450 // is set up lazily when the transfer completes.
10451 AsyncPixelTransferDelegate* delegate =
10452 async_pixel_transfer_manager_->CreatePixelTransferDelegate(texture_ref,
10454 texture->SetImmutable(true);
10456 delegate->AsyncTexImage2D(
10459 base::Bind(&TextureManager::SetLevelInfoFromParams,
10460 // The callback is only invoked if the transfer delegate still
10461 // exists, which implies through manager->texture_ref->state
10462 // ownership that both of these pointers are valid.
10463 base::Unretained(texture_manager()),
10464 base::Unretained(texture_ref),
10466 return error::kNoError;
10469 error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
10470 uint32 immediate_data_size, const cmds::AsyncTexSubImage2DCHROMIUM& c) {
10471 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
10472 GLenum target = static_cast<GLenum>(c.target);
10473 GLint level = static_cast<GLint>(c.level);
10474 GLint xoffset = static_cast<GLint>(c.xoffset);
10475 GLint yoffset = static_cast<GLint>(c.yoffset);
10476 GLsizei width = static_cast<GLsizei>(c.width);
10477 GLsizei height = static_cast<GLsizei>(c.height);
10478 GLenum format = static_cast<GLenum>(c.format);
10479 GLenum type = static_cast<GLenum>(c.type);
10481 // TODO(epenner): Move this and copies of this memory validation
10482 // into ValidateTexSubImage2D step.
10484 if (!GLES2Util::ComputeImageDataSizes(
10485 width, height, format, type, state_.unpack_alignment, &data_size,
10487 return error::kOutOfBounds;
10489 const void* pixels = GetSharedMemoryAs<const void*>(
10490 c.data_shm_id, c.data_shm_offset, data_size);
10492 // All the normal glTexSubImage2D validation.
10493 error::Error error = error::kNoError;
10494 if (!ValidateTexSubImage2D(&error, "glAsyncTexSubImage2DCHROMIUM",
10495 target, level, xoffset, yoffset, width, height, format, type, pixels)) {
10499 // Extra async validation.
10500 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10502 Texture* texture = texture_ref->texture();
10503 if (!ValidateAsyncTransfer(
10504 "glAsyncTexSubImage2DCHROMIUM", texture_ref, target, level, pixels))
10505 return error::kNoError;
10507 // Guarantee async textures are always 'cleared' as follows:
10508 // - AsyncTexImage2D can not redefine an existing texture
10509 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
10510 // - AsyncTexSubImage2D clears synchronously if not already cleared.
10511 // - Textures become immutable after an async call.
10512 // This way we know in all cases that an async texture is always clear.
10513 if (!texture->SafeToRenderFrom()) {
10514 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
10516 LOCAL_SET_GL_ERROR(
10518 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
10519 return error::kNoError;
10523 // Setup the parameters.
10524 AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset,
10525 width, height, format, type};
10526 AsyncMemoryParams mem_params(
10527 GetSharedMemoryBuffer(c.data_shm_id), c.data_shm_offset, data_size);
10528 AsyncPixelTransferDelegate* delegate =
10529 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
10531 // TODO(epenner): We may want to enforce exclusive use
10532 // of async APIs in which case this should become an error,
10533 // (the texture should have been async defined).
10534 AsyncTexImage2DParams define_params = {target, level,
10536 texture->GetLevelSize(target, level, &define_params.width,
10537 &define_params.height);
10538 texture->GetLevelType(target, level, &define_params.type,
10539 &define_params.internal_format);
10540 // Set up the async state if needed, and make the texture
10541 // immutable so the async state stays valid.
10542 delegate = async_pixel_transfer_manager_->CreatePixelTransferDelegate(
10543 texture_ref, define_params);
10544 texture->SetImmutable(true);
10547 delegate->AsyncTexSubImage2D(tex_params, mem_params);
10548 return error::kNoError;
10551 error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
10552 uint32 immediate_data_size, const cmds::WaitAsyncTexImage2DCHROMIUM& c) {
10553 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
10554 GLenum target = static_cast<GLenum>(c.target);
10556 if (GL_TEXTURE_2D != target) {
10557 LOCAL_SET_GL_ERROR(
10558 GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target");
10559 return error::kNoError;
10561 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10563 if (!texture_ref) {
10564 LOCAL_SET_GL_ERROR(
10565 GL_INVALID_OPERATION,
10566 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
10567 return error::kNoError;
10569 AsyncPixelTransferDelegate* delegate =
10570 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
10572 LOCAL_SET_GL_ERROR(
10573 GL_INVALID_OPERATION,
10574 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
10575 return error::kNoError;
10577 delegate->WaitForTransferCompletion();
10578 ProcessFinishedAsyncTransfers();
10579 return error::kNoError;
10582 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
10583 TextureRef* texture_ref) {
10584 Texture* texture = texture_ref->texture();
10585 DoDidUseTexImageIfNeeded(texture, texture->target());
10588 void GLES2DecoderImpl::OnOutOfMemoryError() {
10589 if (lose_context_when_out_of_memory_) {
10590 group_->LoseContexts(GL_UNKNOWN_CONTEXT_RESET_ARB);
10591 LoseContext(GL_GUILTY_CONTEXT_RESET_ARB);
10595 // Include the auto-generated part of this file. We split this because it means
10596 // we can easily edit the non-auto generated parts right here in this file
10597 // instead of having to edit some template or the code generator.
10598 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
10600 } // namespace gles2