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