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