// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef GPU_COMMAND_BUFFER_SERVICE_FRAMEBUFFER_MANAGER_H_ #define GPU_COMMAND_BUFFER_SERVICE_FRAMEBUFFER_MANAGER_H_ #include #include #include #include "base/containers/hash_tables.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "gpu/command_buffer/service/context_group.h" #include "gpu/command_buffer/service/gl_utils.h" #include "gpu/gpu_export.h" namespace gpu { namespace gles2 { class FramebufferCompletenessCache; class FramebufferManager; class Renderbuffer; class RenderbufferManager; class Texture; class TextureRef; class TextureManager; // Info about a particular Framebuffer. class GPU_EXPORT Framebuffer : public base::RefCounted { public: class Attachment : public base::RefCounted { public: virtual GLsizei width() const = 0; virtual GLsizei height() const = 0; virtual GLenum internal_format() const = 0; virtual GLenum texture_type() const = 0; virtual GLsizei samples() const = 0; virtual GLuint object_name() const = 0; virtual bool cleared() const = 0; virtual void SetCleared( RenderbufferManager* renderbuffer_manager, TextureManager* texture_manager, bool cleared) = 0; virtual bool IsTexture(TextureRef* texture) const = 0; virtual bool IsRenderbuffer( Renderbuffer* renderbuffer) const = 0; virtual bool CanRenderTo() const = 0; virtual void DetachFromFramebuffer(Framebuffer* framebuffer) const = 0; virtual bool ValidForAttachmentType(GLenum attachment_type, uint32_t max_color_attachments) = 0; virtual size_t GetSignatureSize(TextureManager* texture_manager) const = 0; virtual void AddToSignature( TextureManager* texture_manager, std::string* signature) const = 0; virtual bool FormsFeedbackLoop(TextureRef* texture, GLint level) const = 0; protected: friend class base::RefCounted; virtual ~Attachment() {} }; Framebuffer(FramebufferManager* manager, GLuint service_id); GLuint service_id() const { return service_id_; } bool HasUnclearedAttachment(GLenum attachment) const; bool HasUnclearedColorAttachments() const; void MarkAttachmentAsCleared( RenderbufferManager* renderbuffer_manager, TextureManager* texture_manager, GLenum attachment, bool cleared); // Unbinds all attachments from this framebuffer for workaround // 'unbind_attachments_on_bound_render_fbo_delete'. The Framebuffer must be // bound when calling this. void DoUnbindGLAttachmentsForWorkaround(GLenum target); // Attaches a renderbuffer to a particlar attachment. // Pass null to detach. void AttachRenderbuffer( GLenum attachment, Renderbuffer* renderbuffer); // Attaches a texture to a particlar attachment. Pass null to detach. void AttachTexture( GLenum attachment, TextureRef* texture_ref, GLenum target, GLint level, GLsizei samples); void AttachTextureLayer( GLenum attachment, TextureRef* texture_ref, GLenum target, GLint level, GLint layer); // Unbinds the given renderbuffer if it is bound. void UnbindRenderbuffer( GLenum target, Renderbuffer* renderbuffer); // Unbinds the given texture if it is bound. void UnbindTexture( GLenum target, TextureRef* texture_ref); const Attachment* GetAttachment(GLenum attachment) const; const Attachment* GetReadBufferAttachment() const; bool IsDeleted() const { return deleted_; } void MarkAsValid() { has_been_bound_ = true; } bool IsValid() const { return has_been_bound_ && !IsDeleted(); } bool HasDepthAttachment() const; bool HasStencilAttachment() const; GLenum GetDrawBufferInternalFormat() const; GLenum GetReadBufferInternalFormat() const; // If the color attachment is a texture, returns its type; otherwise, // returns 0. GLenum GetReadBufferTextureType() const; // Verify all the rules in OpenGL ES 2.0.25 4.4.5 are followed. // Returns GL_FRAMEBUFFER_COMPLETE if there are no reasons we know we can't // use this combination of attachments. Otherwise returns the value // that glCheckFramebufferStatus should return for this set of attachments. // Note that receiving GL_FRAMEBUFFER_COMPLETE from this function does // not mean the real OpenGL will consider it framebuffer complete. It just // means it passed our tests. GLenum IsPossiblyComplete() const; // Implements optimized glGetFramebufferStatus. GLenum GetStatus(TextureManager* texture_manager, GLenum target) const; // Check all attachments are cleared bool IsCleared() const; GLenum GetDrawBuffer(GLenum draw_buffer) const; void SetDrawBuffers(GLsizei n, const GLenum* bufs); // If a color buffer is attached to GL_COLOR_ATTACHMENTi, enable that // draw buffer for glClear(). void PrepareDrawBuffersForClear() const; // Restore draw buffers states that have been changed in // PrepareDrawBuffersForClear(). void RestoreDrawBuffersAfterClear() const; // Clear all the active INT or UINT type color buffers to (0, 0, 0, 0). void ClearIntegerBuffers(); // Return true if any draw buffers has an alpha channel. bool HasAlphaMRT() const; // Return false if any two active color attachments have different internal // formats. bool HasSameInternalFormatsMRT() const; void set_read_buffer(GLenum read_buffer) { read_buffer_ = read_buffer; } GLenum read_buffer() const { return read_buffer_; } private: friend class FramebufferManager; friend class base::RefCounted; ~Framebuffer(); void MarkAsDeleted(); void MarkAttachmentsAsCleared( RenderbufferManager* renderbuffer_manager, TextureManager* texture_manager, bool cleared); void MarkAsComplete(unsigned state_id) { framebuffer_complete_state_count_id_ = state_id; } unsigned framebuffer_complete_state_count_id() const { return framebuffer_complete_state_count_id_; } // Helper function for PrepareDrawBuffersForClear() and // RestoreDrawBuffersAfterClear(). void ChangeDrawBuffersHelper(bool recover) const; // The managers that owns this. FramebufferManager* manager_; bool deleted_; // Service side framebuffer id. GLuint service_id_; // Whether this framebuffer has ever been bound. bool has_been_bound_; // state count when this framebuffer was last checked for completeness. unsigned framebuffer_complete_state_count_id_; // A map of attachments. typedef base::hash_map > AttachmentMap; AttachmentMap attachments_; scoped_ptr draw_buffers_; GLenum read_buffer_; DISALLOW_COPY_AND_ASSIGN(Framebuffer); }; struct DecoderFramebufferState { DecoderFramebufferState(); ~DecoderFramebufferState(); // State saved for clearing so we can clear render buffers and then // restore to these values. bool clear_state_dirty; // The currently bound framebuffers scoped_refptr bound_read_framebuffer; scoped_refptr bound_draw_framebuffer; }; // This class keeps track of the frambebuffers and their attached renderbuffers // so we can correctly clear them. class GPU_EXPORT FramebufferManager { public: FramebufferManager(uint32_t max_draw_buffers, uint32_t max_color_attachments, ContextType context_type, const scoped_refptr& framebuffer_combo_complete_cache); ~FramebufferManager(); // Must call before destruction. void Destroy(bool have_context); // Creates a Framebuffer for the given framebuffer. void CreateFramebuffer(GLuint client_id, GLuint service_id); // Gets the framebuffer info for the given framebuffer. Framebuffer* GetFramebuffer(GLuint client_id); // Removes a framebuffer info for the given framebuffer. void RemoveFramebuffer(GLuint client_id); // Gets a client id for a given service id. bool GetClientId(GLuint service_id, GLuint* client_id) const; void MarkAttachmentsAsCleared( Framebuffer* framebuffer, RenderbufferManager* renderbuffer_manager, TextureManager* texture_manager); void MarkAsComplete(Framebuffer* framebuffer); bool IsComplete(Framebuffer* framebuffer); void IncFramebufferStateChangeCount() { // make sure this is never 0. framebuffer_state_change_count_ = (framebuffer_state_change_count_ + 1) | 0x80000000U; } ContextType context_type() const { return context_type_; } private: friend class Framebuffer; void StartTracking(Framebuffer* framebuffer); void StopTracking(Framebuffer* framebuffer); FramebufferCompletenessCache* GetFramebufferComboCompleteCache() { return framebuffer_combo_complete_cache_.get(); } // Info for each framebuffer in the system. typedef base::hash_map > FramebufferMap; FramebufferMap framebuffers_; // Incremented anytime anything changes that might effect framebuffer // state. unsigned framebuffer_state_change_count_; // Counts the number of Framebuffer allocated with 'this' as its manager. // Allows to check no Framebuffer will outlive this. unsigned int framebuffer_count_; bool have_context_; uint32_t max_draw_buffers_; uint32_t max_color_attachments_; ContextType context_type_; scoped_refptr framebuffer_combo_complete_cache_; DISALLOW_COPY_AND_ASSIGN(FramebufferManager); }; } // namespace gles2 } // namespace gpu #endif // GPU_COMMAND_BUFFER_SERVICE_FRAMEBUFFER_MANAGER_H_