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.
4
5#ifndef GPU_COMMAND_BUFFER_SERVICE_FRAMEBUFFER_MANAGER_H_
6#define GPU_COMMAND_BUFFER_SERVICE_FRAMEBUFFER_MANAGER_H_
7
8#include <vector>
9
10#include "base/basictypes.h"
11#include "base/containers/hash_tables.h"
12#include "base/memory/ref_counted.h"
13#include "base/memory/scoped_ptr.h"
14#include "gpu/command_buffer/service/gl_utils.h"
15#include "gpu/gpu_export.h"
16
17namespace gpu {
18namespace gles2 {
19
20class FramebufferManager;
21class Renderbuffer;
22class RenderbufferManager;
23class Texture;
24class TextureRef;
25class TextureManager;
26
27// Info about a particular Framebuffer.
28class GPU_EXPORT Framebuffer : public base::RefCounted<Framebuffer> {
29 public:
30  class Attachment : public base::RefCounted<Attachment> {
31   public:
32    virtual GLsizei width() const = 0;
33    virtual GLsizei height() const = 0;
34    virtual GLenum internal_format() const = 0;
35    virtual GLenum texture_type() const = 0;
36    virtual GLsizei samples() const = 0;
37    virtual GLuint object_name() const = 0;
38    virtual bool cleared() const = 0;
39    virtual void SetCleared(
40        RenderbufferManager* renderbuffer_manager,
41        TextureManager* texture_manager,
42        bool cleared) = 0;
43    virtual bool IsTexture(TextureRef* texture) const = 0;
44    virtual bool IsRenderbuffer(
45        Renderbuffer* renderbuffer) const = 0;
46    virtual bool CanRenderTo() const = 0;
47    virtual void DetachFromFramebuffer(Framebuffer* framebuffer) const = 0;
48    virtual bool ValidForAttachmentType(
49        GLenum attachment_type, uint32 max_color_attachments) = 0;
50    virtual void AddToSignature(
51        TextureManager* texture_manager, std::string* signature) const = 0;
52    virtual void OnWillRenderTo() const = 0;
53    virtual void OnDidRenderTo() const = 0;
54
55   protected:
56    friend class base::RefCounted<Attachment>;
57    virtual ~Attachment() {}
58  };
59
60  Framebuffer(FramebufferManager* manager, GLuint service_id);
61
62  GLuint service_id() const {
63    return service_id_;
64  }
65
66  bool HasUnclearedAttachment(GLenum attachment) const;
67  bool HasUnclearedColorAttachments() const;
68
69  void MarkAttachmentAsCleared(
70    RenderbufferManager* renderbuffer_manager,
71    TextureManager* texture_manager,
72    GLenum attachment,
73    bool cleared);
74
75  // Attaches a renderbuffer to a particlar attachment.
76  // Pass null to detach.
77  void AttachRenderbuffer(
78      GLenum attachment, Renderbuffer* renderbuffer);
79
80  // Attaches a texture to a particlar attachment. Pass null to detach.
81  void AttachTexture(
82      GLenum attachment, TextureRef* texture_ref, GLenum target,
83      GLint level, GLsizei samples);
84
85  // Unbinds the given renderbuffer if it is bound.
86  void UnbindRenderbuffer(
87      GLenum target, Renderbuffer* renderbuffer);
88
89  // Unbinds the given texture if it is bound.
90  void UnbindTexture(
91      GLenum target, TextureRef* texture_ref);
92
93  const Attachment* GetAttachment(GLenum attachment) const;
94
95  bool IsDeleted() const {
96    return deleted_;
97  }
98
99  void MarkAsValid() {
100    has_been_bound_ = true;
101  }
102
103  bool IsValid() const {
104    return has_been_bound_ && !IsDeleted();
105  }
106
107  bool HasDepthAttachment() const;
108  bool HasStencilAttachment() const;
109  GLenum GetColorAttachmentFormat() const;
110  // If the color attachment is a texture, returns its type; otherwise,
111  // returns 0.
112  GLenum GetColorAttachmentTextureType() const;
113
114  // Verify all the rules in OpenGL ES 2.0.25 4.4.5 are followed.
115  // Returns GL_FRAMEBUFFER_COMPLETE if there are no reasons we know we can't
116  // use this combination of attachments. Otherwise returns the value
117  // that glCheckFramebufferStatus should return for this set of attachments.
118  // Note that receiving GL_FRAMEBUFFER_COMPLETE from this function does
119  // not mean the real OpenGL will consider it framebuffer complete. It just
120  // means it passed our tests.
121  GLenum IsPossiblyComplete() const;
122
123  // Implements optimized glGetFramebufferStatus.
124  GLenum GetStatus(TextureManager* texture_manager, GLenum target) const;
125
126  // Check all attachments are cleared
127  bool IsCleared() const;
128
129  GLenum GetDrawBuffer(GLenum draw_buffer) const;
130
131  void SetDrawBuffers(GLsizei n, const GLenum* bufs);
132
133  // If a color buffer is attached to GL_COLOR_ATTACHMENTi, enable that
134  // draw buffer for glClear().
135  void PrepareDrawBuffersForClear() const;
136
137  // Restore draw buffers states that have been changed in
138  // PrepareDrawBuffersForClear().
139  void RestoreDrawBuffersAfterClear() const;
140
141  // Return true if any draw buffers has an alpha channel.
142  bool HasAlphaMRT() const;
143
144  static void ClearFramebufferCompleteComboMap();
145
146  static bool AllowFramebufferComboCompleteMapForTesting() {
147    return allow_framebuffer_combo_complete_map_;
148  }
149
150  void OnTextureRefDetached(TextureRef* texture);
151  void OnWillRenderTo() const;
152  void OnDidRenderTo() const;
153
154 private:
155  friend class FramebufferManager;
156  friend class base::RefCounted<Framebuffer>;
157
158  ~Framebuffer();
159
160  void MarkAsDeleted();
161
162  void MarkAttachmentsAsCleared(
163    RenderbufferManager* renderbuffer_manager,
164    TextureManager* texture_manager,
165    bool cleared);
166
167  void MarkAsComplete(unsigned state_id) {
168    framebuffer_complete_state_count_id_ = state_id;
169  }
170
171  unsigned framebuffer_complete_state_count_id() const {
172    return framebuffer_complete_state_count_id_;
173  }
174
175  // Helper function for PrepareDrawBuffersForClear() and
176  // RestoreDrawBuffersAfterClear().
177  void ChangeDrawBuffersHelper(bool recover) const;
178
179  // The managers that owns this.
180  FramebufferManager* manager_;
181
182  bool deleted_;
183
184  // Service side framebuffer id.
185  GLuint service_id_;
186
187  // Whether this framebuffer has ever been bound.
188  bool has_been_bound_;
189
190  // state count when this framebuffer was last checked for completeness.
191  unsigned framebuffer_complete_state_count_id_;
192
193  // A map of attachments.
194  typedef base::hash_map<GLenum, scoped_refptr<Attachment> > AttachmentMap;
195  AttachmentMap attachments_;
196
197  // A map of successful frame buffer combos. If it's in the map
198  // it should be FRAMEBUFFER_COMPLETE.
199  typedef base::hash_map<std::string, bool> FramebufferComboCompleteMap;
200  static FramebufferComboCompleteMap* framebuffer_combo_complete_map_;
201  static bool allow_framebuffer_combo_complete_map_;
202
203  scoped_ptr<GLenum[]> draw_buffers_;
204
205  DISALLOW_COPY_AND_ASSIGN(Framebuffer);
206};
207
208struct DecoderFramebufferState {
209  DecoderFramebufferState();
210  ~DecoderFramebufferState();
211
212  // State saved for clearing so we can clear render buffers and then
213  // restore to these values.
214  bool clear_state_dirty;
215
216  // The currently bound framebuffers
217  scoped_refptr<Framebuffer> bound_read_framebuffer;
218  scoped_refptr<Framebuffer> bound_draw_framebuffer;
219};
220
221// This class keeps track of the frambebuffers and their attached renderbuffers
222// so we can correctly clear them.
223class GPU_EXPORT FramebufferManager {
224 public:
225  class GPU_EXPORT TextureDetachObserver {
226   public:
227    TextureDetachObserver();
228    virtual ~TextureDetachObserver();
229
230    virtual void OnTextureRefDetachedFromFramebuffer(TextureRef* texture) = 0;
231
232   private:
233    DISALLOW_COPY_AND_ASSIGN(TextureDetachObserver);
234  };
235
236  FramebufferManager(uint32 max_draw_buffers, uint32 max_color_attachments);
237  ~FramebufferManager();
238
239  // Must call before destruction.
240  void Destroy(bool have_context);
241
242  // Creates a Framebuffer for the given framebuffer.
243  void CreateFramebuffer(GLuint client_id, GLuint service_id);
244
245  // Gets the framebuffer info for the given framebuffer.
246  Framebuffer* GetFramebuffer(GLuint client_id);
247
248  // Removes a framebuffer info for the given framebuffer.
249  void RemoveFramebuffer(GLuint client_id);
250
251  // Gets a client id for a given service id.
252  bool GetClientId(GLuint service_id, GLuint* client_id) const;
253
254  void MarkAttachmentsAsCleared(
255    Framebuffer* framebuffer,
256    RenderbufferManager* renderbuffer_manager,
257    TextureManager* texture_manager);
258
259  void MarkAsComplete(Framebuffer* framebuffer);
260
261  bool IsComplete(Framebuffer* framebuffer);
262
263  void IncFramebufferStateChangeCount() {
264    // make sure this is never 0.
265    framebuffer_state_change_count_ =
266        (framebuffer_state_change_count_ + 1) | 0x80000000U;
267  }
268
269  void AddObserver(TextureDetachObserver* observer) {
270    texture_detach_observers_.push_back(observer);
271  }
272
273  void RemoveObserver(TextureDetachObserver* observer) {
274    texture_detach_observers_.erase(
275        std::remove(texture_detach_observers_.begin(),
276                    texture_detach_observers_.end(),
277                    observer),
278        texture_detach_observers_.end());
279  }
280
281 private:
282  friend class Framebuffer;
283
284  void StartTracking(Framebuffer* framebuffer);
285  void StopTracking(Framebuffer* framebuffer);
286
287  void OnTextureRefDetached(TextureRef* texture);
288
289  // Info for each framebuffer in the system.
290  typedef base::hash_map<GLuint, scoped_refptr<Framebuffer> >
291      FramebufferMap;
292  FramebufferMap framebuffers_;
293
294  // Incremented anytime anything changes that might effect framebuffer
295  // state.
296  unsigned framebuffer_state_change_count_;
297
298  // Counts the number of Framebuffer allocated with 'this' as its manager.
299  // Allows to check no Framebuffer will outlive this.
300  unsigned int framebuffer_count_;
301
302  bool have_context_;
303
304  uint32 max_draw_buffers_;
305  uint32 max_color_attachments_;
306
307  typedef std::vector<TextureDetachObserver*> TextureDetachObserverVector;
308  TextureDetachObserverVector texture_detach_observers_;
309
310  DISALLOW_COPY_AND_ASSIGN(FramebufferManager);
311};
312
313}  // namespace gles2
314}  // namespace gpu
315
316#endif  // GPU_COMMAND_BUFFER_SERVICE_FRAMEBUFFER_MANAGER_H_
317