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 class ContextMtl;
22 class SurfaceMtl;
23 
24 class FramebufferMtl : public FramebufferImpl
25 {
26   public:
27     explicit FramebufferMtl(const gl::FramebufferState &state, bool flipY);
28     ~FramebufferMtl() override;
29     void destroy(const gl::Context *context) override;
30 
31     angle::Result discard(const gl::Context *context,
32                           size_t count,
33                           const GLenum *attachments) override;
34     angle::Result invalidate(const gl::Context *context,
35                              size_t count,
36                              const GLenum *attachments) override;
37     angle::Result invalidateSub(const gl::Context *context,
38                                 size_t count,
39                                 const GLenum *attachments,
40                                 const gl::Rectangle &area) override;
41 
42     angle::Result clear(const gl::Context *context, GLbitfield mask) override;
43     angle::Result clearBufferfv(const gl::Context *context,
44                                 GLenum buffer,
45                                 GLint drawbuffer,
46                                 const GLfloat *values) override;
47     angle::Result clearBufferuiv(const gl::Context *context,
48                                  GLenum buffer,
49                                  GLint drawbuffer,
50                                  const GLuint *values) override;
51     angle::Result clearBufferiv(const gl::Context *context,
52                                 GLenum buffer,
53                                 GLint drawbuffer,
54                                 const GLint *values) override;
55     angle::Result clearBufferfi(const gl::Context *context,
56                                 GLenum buffer,
57                                 GLint drawbuffer,
58                                 GLfloat depth,
59                                 GLint stencil) override;
60 
61     GLenum getImplementationColorReadFormat(const gl::Context *context) const override;
62     GLenum getImplementationColorReadType(const gl::Context *context) const override;
63     angle::Result readPixels(const gl::Context *context,
64                              const gl::Rectangle &area,
65                              GLenum format,
66                              GLenum type,
67                              void *pixels) override;
68 
69     angle::Result blit(const gl::Context *context,
70                        const gl::Rectangle &sourceArea,
71                        const gl::Rectangle &destArea,
72                        GLbitfield mask,
73                        GLenum filter) override;
74 
75     bool checkStatus(const gl::Context *context) const override;
76 
77     angle::Result syncState(const gl::Context *context,
78                             const gl::Framebuffer::DirtyBits &dirtyBits) override;
79 
80     angle::Result getSamplePosition(const gl::Context *context,
81                                     size_t index,
82                                     GLfloat *xy) const override;
83 
84     RenderTargetMtl *getColorReadRenderTarget() const;
85 
flipY()86     bool flipY() const { return mFlipY; }
87 
88     gl::Rectangle getCompleteRenderArea() const;
89 
90     const mtl::RenderPassDesc &getRenderPassDesc(ContextMtl *context);
91 
92     // Call this to notify FramebufferMtl whenever its render pass has started.
93     void onStartedDrawingToFrameBuffer(const gl::Context *context);
94 
95     // The actual area will be adjusted based on framebuffer flipping property.
96     gl::Rectangle getReadPixelArea(const gl::Rectangle &glArea);
97 
98     // NOTE: this method doesn't do the flipping of area. Caller must do it if needed before
99     // callling this. See getReadPixelsArea().
100     angle::Result readPixelsImpl(const gl::Context *context,
101                                  const gl::Rectangle &area,
102                                  const PackPixelsParams &packPixelsParams,
103                                  RenderTargetMtl *renderTarget,
104                                  uint8_t *pixels);
105 
106   private:
107     void reset();
108     angle::Result invalidateImpl(ContextMtl *contextMtl, size_t count, const GLenum *attachments);
109     angle::Result clearImpl(const gl::Context *context,
110                             gl::DrawBufferMask clearColorBuffers,
111                             mtl::ClearRectParams *clearOpts);
112 
113     angle::Result clearWithLoadOp(const gl::Context *context,
114                                   gl::DrawBufferMask clearColorBuffers,
115                                   const mtl::ClearRectParams &clearOpts);
116 
117     angle::Result clearWithDraw(const gl::Context *context,
118                                 gl::DrawBufferMask clearColorBuffers,
119                                 const mtl::ClearRectParams &clearOpts);
120 
121     angle::Result prepareRenderPass(const gl::Context *context,
122                                     gl::DrawBufferMask drawColorBuffers,
123                                     mtl::RenderPassDesc *descOut);
124 
125     void overrideClearColor(const mtl::TextureRef &texture,
126                             MTLClearColor clearColor,
127                             MTLClearColor *colorOut);
128 
129     angle::Result updateColorRenderTarget(const gl::Context *context, size_t colorIndexGL);
130     angle::Result updateDepthRenderTarget(const gl::Context *context);
131     angle::Result updateStencilRenderTarget(const gl::Context *context);
132     angle::Result updateCachedRenderTarget(const gl::Context *context,
133                                            const gl::FramebufferAttachment *attachment,
134                                            RenderTargetMtl **cachedRenderTarget);
135 
136     // NOTE: we cannot use RenderTargetCache here because it doesn't support separate
137     // depth & stencil attachments as of now. Separate depth & stencil could be useful to
138     // save spaces on iOS devices. See doc/PackedDepthStencilSupport.md.
139     std::array<RenderTargetMtl *, mtl::kMaxRenderTargets> mColorRenderTargets;
140     RenderTargetMtl *mDepthRenderTarget   = nullptr;
141     RenderTargetMtl *mStencilRenderTarget = nullptr;
142     mtl::RenderPassDesc mRenderPassDesc;
143     const bool mFlipY = false;
144 };
145 }  // namespace rx
146 
147 #endif /* LIBANGLE_RENDERER_METAL_FRAMEBUFFERMTL_H */
148