• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2019 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // FrameBufferMtl.h:
7 //    Defines the class interface for FrameBufferMtl, implementing FrameBufferImpl.
8 //
9 
10 #ifndef LIBANGLE_RENDERER_METAL_FRAMEBUFFERMTL_H_
11 #define LIBANGLE_RENDERER_METAL_FRAMEBUFFERMTL_H_
12 
13 #import <Metal/Metal.h>
14 
15 #include "common/FixedVector.h"
16 #include "libANGLE/renderer/FramebufferImpl.h"
17 #include "libANGLE/renderer/metal/RenderTargetMtl.h"
18 #include "libANGLE/renderer/metal/mtl_render_utils.h"
19 
20 namespace rx
21 {
22 namespace mtl
23 {
24 class RenderCommandEncoder;
25 }  // namespace mtl
26 class ContextMtl;
27 class SurfaceMtl;
28 
29 class FramebufferMtl : public FramebufferImpl
30 {
31   public:
32     explicit FramebufferMtl(const gl::FramebufferState &state, ContextMtl *context, bool flipY);
33     ~FramebufferMtl() override;
34     void destroy(const gl::Context *context) override;
35 
36     angle::Result discard(const gl::Context *context,
37                           size_t count,
38                           const GLenum *attachments) override;
39     angle::Result invalidate(const gl::Context *context,
40                              size_t count,
41                              const GLenum *attachments) override;
42     angle::Result invalidateSub(const gl::Context *context,
43                                 size_t count,
44                                 const GLenum *attachments,
45                                 const gl::Rectangle &area) override;
46 
47     angle::Result clear(const gl::Context *context, GLbitfield mask) override;
48     angle::Result clearBufferfv(const gl::Context *context,
49                                 GLenum buffer,
50                                 GLint drawbuffer,
51                                 const GLfloat *values) override;
52     angle::Result clearBufferuiv(const gl::Context *context,
53                                  GLenum buffer,
54                                  GLint drawbuffer,
55                                  const GLuint *values) override;
56     angle::Result clearBufferiv(const gl::Context *context,
57                                 GLenum buffer,
58                                 GLint drawbuffer,
59                                 const GLint *values) override;
60     angle::Result clearBufferfi(const gl::Context *context,
61                                 GLenum buffer,
62                                 GLint drawbuffer,
63                                 GLfloat depth,
64                                 GLint stencil) override;
65 
66     const gl::InternalFormat &getImplementationColorReadFormat(
67         const gl::Context *context) const override;
68     angle::Result readPixels(const gl::Context *context,
69                              const gl::Rectangle &area,
70                              GLenum format,
71                              GLenum type,
72                              const gl::PixelPackState &pack,
73                              gl::Buffer *packBuffer,
74                              void *pixels) override;
75 
76     angle::Result blit(const gl::Context *context,
77                        const gl::Rectangle &sourceArea,
78                        const gl::Rectangle &destArea,
79                        GLbitfield mask,
80                        GLenum filter) override;
81 
82     gl::FramebufferStatus checkStatus(const gl::Context *context) const override;
83 
84     angle::Result syncState(const gl::Context *context,
85                             GLenum binding,
86                             const gl::Framebuffer::DirtyBits &dirtyBits,
87                             gl::Command command) override;
88 
89     angle::Result getSamplePosition(const gl::Context *context,
90                                     size_t index,
91                                     GLfloat *xy) const override;
92 
93     RenderTargetMtl *getColorReadRenderTarget(const gl::Context *context) const;
getDepthRenderTarget()94     RenderTargetMtl *getDepthRenderTarget() const { return mDepthRenderTarget; }
getStencilRenderTarget()95     RenderTargetMtl *getStencilRenderTarget() const { return mStencilRenderTarget; }
96 
setFlipY(bool flipY)97     void setFlipY(bool flipY) { mFlipY = flipY; }
flipY()98     bool flipY() const { return mFlipY; }
99 
100     gl::Rectangle getCompleteRenderArea() const;
101     int getSamples() const;
getAttachedBackbuffer()102     WindowSurfaceMtl *getAttachedBackbuffer() const { return mBackbuffer; }
103 
104     bool renderPassHasStarted(ContextMtl *contextMtl) const;
renderPassHasDefaultWidthOrHeight()105     bool renderPassHasDefaultWidthOrHeight() const
106     {
107         return mRenderPassDesc.defaultWidth > 0 || mRenderPassDesc.defaultHeight > 0;
108     }
109     mtl::RenderCommandEncoder *ensureRenderPassStarted(const gl::Context *context);
110 
111     // Call this to notify FramebufferMtl whenever its render pass has started.
112     void onStartedDrawingToFrameBuffer(const gl::Context *context);
113     void onFrameEnd(const gl::Context *context);
114 
115     // The actual area will be adjusted based on framebuffer flipping property.
116     gl::Rectangle getCorrectFlippedReadArea(const gl::Context *context,
117                                             const gl::Rectangle &glArea) const;
118 
119     // NOTE: this method doesn't do the flipping of area. Caller must do it if needed before
120     // callling this. See getReadPixelsArea().
121     angle::Result readPixelsImpl(const gl::Context *context,
122                                  const gl::Rectangle &area,
123                                  const PackPixelsParams &packPixelsParams,
124                                  const RenderTargetMtl *renderTarget,
125                                  uint8_t *pixels) const;
setBackbuffer(WindowSurfaceMtl * backbuffer)126     void setBackbuffer(WindowSurfaceMtl *backbuffer) { mBackbuffer = backbuffer; }
getBackbuffer()127     WindowSurfaceMtl *getBackbuffer() const { return mBackbuffer; }
128 
129   private:
130     void reset();
131     gl::FramebufferStatus checkPackedDepthStencilAttachment() const;
132     angle::Result invalidateImpl(const gl::Context *context,
133                                  size_t count,
134                                  const GLenum *attachments);
135     angle::Result blitWithDraw(const gl::Context *context,
136                                FramebufferMtl *srcFrameBuffer,
137                                bool blitColorBuffer,
138                                bool blitDepthBuffer,
139                                bool blitStencilBuffer,
140                                GLenum filter,
141                                const mtl::BlitParams &baseParams);
142     angle::Result clearImpl(const gl::Context *context,
143                             gl::DrawBufferMask clearColorBuffers,
144                             mtl::ClearRectParams *clearOpts);
145 
146     angle::Result clearWithLoadOp(const gl::Context *context,
147                                   gl::DrawBufferMask clearColorBuffers,
148                                   const mtl::ClearRectParams &clearOpts);
149 
150     angle::Result clearWithLoadOpRenderPassNotStarted(const gl::Context *context,
151                                                       gl::DrawBufferMask clearColorBuffers,
152                                                       const mtl::ClearRectParams &clearOpts);
153 
154     angle::Result clearWithLoadOpRenderPassStarted(const gl::Context *context,
155                                                    gl::DrawBufferMask clearColorBuffers,
156                                                    const mtl::ClearRectParams &clearOpts,
157                                                    mtl::RenderCommandEncoder *encoder);
158 
159     angle::Result clearWithDraw(const gl::Context *context,
160                                 gl::DrawBufferMask clearColorBuffers,
161                                 const mtl::ClearRectParams &clearOpts);
162 
163     // Initialize load store options for a render pass's first start (i.e. not render pass resuming
164     // from interruptions such as those caused by a conversion compute pass)
165     void setLoadStoreActionOnRenderPassFirstStart(mtl::RenderPassAttachmentDesc *attachmentOut,
166                                                   const bool forceDepthStencilMultisampleLoad);
167 
168     // Fill RenderPassDesc with relevant attachment's info from GL front end.
169     angle::Result prepareRenderPass(const gl::Context *context,
170                                     mtl::RenderPassDesc *descOut,
171                                     gl::Command command);
172 
173     // Check if a render pass specified by the given RenderPassDesc has started or not, if not this
174     // method will start the render pass and return its render encoder.
175     mtl::RenderCommandEncoder *ensureRenderPassStarted(const gl::Context *context,
176                                                        const mtl::RenderPassDesc &desc);
177 
178     angle::Result updateColorRenderTarget(const gl::Context *context, size_t colorIndexGL);
179     angle::Result updateDepthRenderTarget(const gl::Context *context);
180     angle::Result updateStencilRenderTarget(const gl::Context *context);
181     angle::Result updateCachedRenderTarget(const gl::Context *context,
182                                            const gl::FramebufferAttachment *attachment,
183                                            RenderTargetMtl **cachedRenderTarget);
184 
185     angle::Result readPixelsToPBO(const gl::Context *context,
186                                   const gl::Rectangle &area,
187                                   const PackPixelsParams &packPixelsParams,
188                                   const RenderTargetMtl *renderTarget) const;
189 
190     angle::Result readPixelsToBuffer(const gl::Context *context,
191                                      const gl::Rectangle &area,
192                                      const RenderTargetMtl *renderTarget,
193                                      bool reverseRowOrder,
194                                      const angle::Format &dstAngleFormat,
195                                      uint32_t dstBufferOffset,
196                                      uint32_t dstBufferRowPitch,
197                                      const mtl::BufferRef *dstBuffer) const;
198 
199     bool totalBitsUsedIsLessThanOrEqualToMaxBitsSupported(const gl::Context *context) const;
200 
201     RenderTargetMtl *getColorReadRenderTargetNoCache(const gl::Context *context) const;
202     bool prepareForUse(const gl::Context *context) const;
203 
204     // NOTE: we cannot use RenderTargetCache here because it doesn't support separate
205     // depth & stencil attachments as of now. Separate depth & stencil could be useful to
206     // save spaces on iOS devices. See doc/PackedDepthStencilSupport.md.
207     angle::FixedVector<RenderTargetMtl *, mtl::kMaxRenderTargets> mColorRenderTargets;
208     RenderTargetMtl *mDepthRenderTarget   = nullptr;
209     RenderTargetMtl *mStencilRenderTarget = nullptr;
210     mtl::RenderPassDesc mRenderPassDesc;
211 
212     const mtl::Format *mRenderPassFirstColorAttachmentFormat = nullptr;
213     bool mRenderPassAttachmentsSameColorType                 = false;
214 
215     // Flag indicating the render pass start is a clean start or a resume from interruption such
216     // as by a compute pass.
217     bool mRenderPassCleanStart = false;
218 
219     WindowSurfaceMtl *mBackbuffer = nullptr;
220     bool mFlipY                   = false;
221 
222     mtl::BufferRef mReadPixelBuffer;
223 };
224 }  // namespace rx
225 
226 #endif /* LIBANGLE_RENDERER_METAL_FRAMEBUFFERMTL_H */
227