// 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 "base/basictypes.h" #include "base/containers/hash_tables.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "gpu/command_buffer/service/gl_utils.h" #include "gpu/gpu_export.h" namespace gpu { namespace gles2 { 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 max_color_attachments) = 0; virtual void AddToSignature( TextureManager* texture_manager, std::string* signature) const = 0; virtual void OnWillRenderTo() const = 0; virtual void OnDidRenderTo() 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; void MarkAttachmentAsCleared( RenderbufferManager* renderbuffer_manager, TextureManager* texture_manager, GLenum attachment, bool cleared); // 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); // 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; 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 GetColorAttachmentFormat() const; // If the color attachment is a texture, returns its type; otherwise, // returns 0. GLenum GetColorAttachmentTextureType() 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); // Return true if any draw buffers has an alpha channel. bool HasAlphaMRT() const; static void ClearFramebufferCompleteComboMap(); static bool AllowFramebufferComboCompleteMapForTesting() { return allow_framebuffer_combo_complete_map_; } void OnTextureRefDetached(TextureRef* texture); void OnWillRenderTo() const; void OnDidRenderTo() const; 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_; } // 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_; // A map of successful frame buffer combos. If it's in the map // it should be FRAMEBUFFER_COMPLETE. typedef base::hash_map FramebufferComboCompleteMap; static FramebufferComboCompleteMap* framebuffer_combo_complete_map_; static bool allow_framebuffer_combo_complete_map_; scoped_ptr draw_buffers_; 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: class GPU_EXPORT TextureDetachObserver { public: TextureDetachObserver(); virtual ~TextureDetachObserver(); virtual void OnTextureRefDetachedFromFramebuffer(TextureRef* texture) = 0; private: DISALLOW_COPY_AND_ASSIGN(TextureDetachObserver); }; FramebufferManager(uint32 max_draw_buffers, uint32 max_color_attachments); ~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; } void AddObserver(TextureDetachObserver* observer) { texture_detach_observers_.push_back(observer); } void RemoveObserver(TextureDetachObserver* observer) { texture_detach_observers_.erase( std::remove(texture_detach_observers_.begin(), texture_detach_observers_.end(), observer), texture_detach_observers_.end()); } private: friend class Framebuffer; void StartTracking(Framebuffer* framebuffer); void StopTracking(Framebuffer* framebuffer); void OnTextureRefDetached(TextureRef* texture); // 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 max_draw_buffers_; uint32 max_color_attachments_; typedef std::vector TextureDetachObserverVector; TextureDetachObserverVector texture_detach_observers_; DISALLOW_COPY_AND_ASSIGN(FramebufferManager); }; } // namespace gles2 } // namespace gpu #endif // GPU_COMMAND_BUFFER_SERVICE_FRAMEBUFFER_MANAGER_H_