| // 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 <stddef.h> |
| #include <stdint.h> |
| |
| #include <memory> |
| #include <unordered_map> |
| #include <vector> |
| |
| #include "base/macros.h" |
| #include "base/memory/ref_counted.h" |
| #include "gpu/command_buffer/service/context_group.h" |
| #include "gpu/command_buffer/service/gl_utils.h" |
| #include "gpu/command_buffer/service/shader_manager.h" |
| #include "gpu/gpu_gles2_export.h" |
| |
| namespace gpu { |
| namespace gles2 { |
| |
| class FeatureInfo; |
| class FramebufferCompletenessCache; |
| class FramebufferManager; |
| class Renderbuffer; |
| class RenderbufferManager; |
| class TextureRef; |
| class TextureManager; |
| |
| // Info about a particular Framebuffer. |
| class GPU_GLES2_EXPORT Framebuffer : public base::RefCounted<Framebuffer> { |
| public: |
| class Attachment : public base::RefCounted<Attachment> { |
| 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 GLint level() const = 0; |
| virtual bool cleared() const = 0; |
| virtual void SetCleared( |
| RenderbufferManager* renderbuffer_manager, |
| TextureManager* texture_manager, |
| bool cleared) = 0; |
| virtual bool IsPartiallyCleared() const = 0; |
| virtual bool IsTextureAttachment() const = 0; |
| virtual bool IsRenderbufferAttachment() const = 0; |
| virtual bool IsTexture(TextureRef* texture) const = 0; |
| virtual bool IsRenderbuffer(Renderbuffer* renderbuffer) const = 0; |
| virtual bool IsSameAttachment(const Attachment* attachment) const = 0; |
| virtual bool Is3D() const = 0; |
| |
| // If it's a 3D texture attachment, return true if |
| // FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER is smaller than the number of |
| // layers in the texture. |
| virtual bool IsLayerValid() const = 0; |
| |
| virtual bool CanRenderTo(const FeatureInfo* feature_info) const = 0; |
| virtual void DetachFromFramebuffer(Framebuffer* framebuffer, |
| GLenum attachment) 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, GLint layer) const = 0; |
| virtual bool EmulatingRGB() const = 0; |
| |
| protected: |
| friend class base::RefCounted<Attachment>; |
| virtual ~Attachment() = default; |
| }; |
| |
| Framebuffer(FramebufferManager* manager, GLuint service_id); |
| |
| GLuint service_id() const { |
| return service_id_; |
| } |
| |
| bool HasUnclearedAttachment(GLenum attachment) const; |
| bool HasUnclearedColorAttachments() const; |
| |
| bool HasSRGBAttachments() const; |
| bool HasDepthStencilFormatAttachment() const; |
| |
| void ClearUnclearedIntOr3DTexturesOrPartiallyClearedTextures( |
| GLES2Decoder* decoder, |
| TextureManager* texture_manager); |
| |
| bool HasUnclearedIntRenderbufferAttachments() const; |
| |
| void ClearUnclearedIntRenderbufferAttachments( |
| RenderbufferManager* renderbuffer_manager); |
| |
| 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; |
| |
| // Returns the max dimensions which fit inside all of the attachments. |
| // Can only be called after the framebuffer has been checked to be complete. |
| gfx::Size GetFramebufferValidSize() const; |
| |
| GLsizei GetSamples() const; |
| |
| bool IsDeleted() const { |
| return deleted_; |
| } |
| |
| void MarkAsValid() { |
| has_been_bound_ = true; |
| } |
| |
| bool IsValid() const { |
| return has_been_bound_ && !IsDeleted(); |
| } |
| |
| bool HasColorAttachment(int index) const; |
| bool HasDepthAttachment() const; |
| bool HasStencilAttachment() const; |
| bool HasActiveFloat32ColorAttachment() const; |
| GLsizei last_color_attachment_id() const { return last_color_attachment_id_; } |
| GLenum GetDepthFormat() const; |
| GLenum GetStencilFormat() const; |
| GLenum GetDrawBufferInternalFormat() const; |
| GLenum GetReadBufferInternalFormat() const; |
| // If the color attachment is a texture, returns its type; otherwise, |
| // returns 0. |
| GLenum GetReadBufferTextureType() const; |
| bool GetReadBufferIsMultisampledTexture() 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 FeatureInfo* feature_info) 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(). |
| // Return true if the DrawBuffers() is actually called. |
| bool PrepareDrawBuffersForClearingUninitializedAttachments() const; |
| |
| // Restore |adjusted_draw_buffers_|. |
| void RestoreDrawBuffers() const; |
| |
| // Checks if a draw buffer's format and its corresponding fragment shader |
| // output's type are compatible, i.e., a signed integer typed variable is |
| // incompatible with a float or unsigned integer buffer. |
| // Return false if incompaticle. |
| // Otherwise, filter out the draw buffers that are not written to but are not |
| // NONE through DrawBuffers, to be on the safe side. Return true. |
| // This is applied before a draw call. |
| bool ValidateAndAdjustDrawBuffers(uint32_t fragment_output_type_mask, |
| uint32_t fragment_output_written_mask); |
| |
| // Filter out the draw buffers that have no images attached but are not NONE |
| // through DrawBuffers, to be on the safe side. |
| // This is applied before a clear call. |
| void AdjustDrawBuffers(); |
| |
| bool ContainsActiveIntegerAttachments() const; |
| |
| // 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_; |
| } |
| |
| // See member declaration for details. |
| // The data are only valid if fbo is complete. |
| uint32_t draw_buffer_type_mask() const { |
| return draw_buffer_type_mask_; |
| } |
| uint32_t draw_buffer_bound_mask() const { |
| return draw_buffer_bound_mask_; |
| } |
| |
| void UnmarkAsComplete() { framebuffer_complete_state_count_id_ = 0; } |
| |
| private: |
| friend class FramebufferManager; |
| friend class base::RefCounted<Framebuffer>; |
| |
| ~Framebuffer(); |
| |
| // Helper function updating cached last color attachment id bound. |
| // Called when attachments_ changed |
| void OnInsertUpdateLastColorAttachmentId(GLenum attachment); |
| void OnEraseUpdateLastColorAttachmentId(GLenum attachment); |
| |
| void MarkAsDeleted(); |
| |
| void MarkAttachmentsAsCleared( |
| RenderbufferManager* renderbuffer_manager, |
| TextureManager* texture_manager, |
| bool cleared); |
| |
| void MarkAsComplete(unsigned state_id) { |
| UpdateDrawBufferMasks(); |
| framebuffer_complete_state_count_id_ = state_id; |
| } |
| |
| unsigned framebuffer_complete_state_count_id() const { |
| return framebuffer_complete_state_count_id_; |
| } |
| |
| // Cache color attachments' base type mask (FLOAT, INT, UINT) and bound mask. |
| // If an attachment point has no image, it's set as UNDEFINED_TYPE. |
| // This call is only valid on a complete fbo. |
| void UpdateDrawBufferMasks(); |
| |
| // Helper for ValidateAndAdjustDrawBuffers() and AdjustDrawBuffers(). |
| void AdjustDrawBuffersImpl(uint32_t desired_mask); |
| |
| // 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 std::unordered_map<GLenum, scoped_refptr<Attachment>> AttachmentMap; |
| AttachmentMap attachments_; |
| |
| // User's draw buffers setting through DrawBuffers() call. |
| std::unique_ptr<GLenum[]> draw_buffers_; |
| |
| // If a draw buffer does not have an image, or it has no corresponding |
| // fragment shader output variable, it might be filtered out as NONE. |
| // Note that the actually draw buffers setting sent to the driver is always |
| // consistent with |adjusted_draw_buffers_|, not |draw_buffers_|. |
| std::unique_ptr<GLenum[]> adjusted_draw_buffers_; |
| |
| // Draw buffer base types: FLOAT, INT, or UINT. |
| // We have up to 16 draw buffers, each is encoded into 2 bits, total 32 bits: |
| // the lowest 2 bits for draw buffer 0, the highest 2 bits for draw buffer 15. |
| uint32_t draw_buffer_type_mask_; |
| // Same layout as above, 0x03 if it's 32bit float color attachment, 0x00 if |
| // not |
| uint32_t draw_buffer_float32_mask_; |
| // Same layout as above, 2 bits per draw buffer, 0x03 if a draw buffer has a |
| // bound image, 0x00 if not. |
| uint32_t draw_buffer_bound_mask_; |
| // This is the mask for the actual draw buffers sent to driver. |
| uint32_t adjusted_draw_buffer_bound_mask_; |
| // The largest i of all GL_COLOR_ATTACHMENTi |
| GLsizei last_color_attachment_id_; |
| |
| 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<Framebuffer> bound_read_framebuffer; |
| scoped_refptr<Framebuffer> bound_draw_framebuffer; |
| }; |
| |
| // This class keeps track of the frambebuffers and their attached renderbuffers |
| // so we can correctly clear them. |
| class GPU_GLES2_EXPORT FramebufferManager { |
| public: |
| FramebufferManager( |
| uint32_t max_draw_buffers, |
| uint32_t max_color_attachments, |
| FramebufferCompletenessCache* 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(const Framebuffer* framebuffer); |
| |
| void IncFramebufferStateChangeCount() { |
| // make sure this is never 0. |
| framebuffer_state_change_count_ = |
| (framebuffer_state_change_count_ + 1) | 0x80000000U; |
| } |
| |
| private: |
| friend class Framebuffer; |
| |
| void StartTracking(Framebuffer* framebuffer); |
| void StopTracking(Framebuffer* framebuffer); |
| |
| FramebufferCompletenessCache* GetFramebufferComboCompleteCache() { |
| return framebuffer_combo_complete_cache_; |
| } |
| |
| // Info for each framebuffer in the system. |
| typedef std::unordered_map<GLuint, scoped_refptr<Framebuffer>> 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_; |
| |
| FramebufferCompletenessCache* framebuffer_combo_complete_cache_; |
| |
| DISALLOW_COPY_AND_ASSIGN(FramebufferManager); |
| }; |
| |
| } // namespace gles2 |
| } // namespace gpu |
| |
| #endif // GPU_COMMAND_BUFFER_SERVICE_FRAMEBUFFER_MANAGER_H_ |