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 angle::Result ensureRenderPassStarted(const gl::Context *context, 110 mtl::RenderCommandEncoder **encoderOut); 111 112 // Call this to notify FramebufferMtl whenever its render pass has started. 113 void onStartedDrawingToFrameBuffer(const gl::Context *context); 114 void onFrameEnd(const gl::Context *context); 115 116 // The actual area will be adjusted based on framebuffer flipping property. 117 gl::Rectangle getCorrectFlippedReadArea(const gl::Context *context, 118 const gl::Rectangle &glArea) const; 119 120 // NOTE: this method doesn't do the flipping of area. Caller must do it if needed before 121 // callling this. See getReadPixelsArea(). 122 angle::Result readPixelsImpl(const gl::Context *context, 123 const gl::Rectangle &area, 124 const PackPixelsParams &packPixelsParams, 125 const RenderTargetMtl *renderTarget, 126 uint8_t *pixels) const; setBackbuffer(WindowSurfaceMtl * backbuffer)127 void setBackbuffer(WindowSurfaceMtl *backbuffer) { mBackbuffer = backbuffer; } getBackbuffer()128 WindowSurfaceMtl *getBackbuffer() const { return mBackbuffer; } 129 130 private: 131 void reset(); 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 angle::Result ensureRenderPassStarted(const gl::Context *context, 176 const mtl::RenderPassDesc &desc, 177 mtl::RenderCommandEncoder **encoderOut); 178 179 angle::Result updateColorRenderTarget(const gl::Context *context, size_t colorIndexGL); 180 angle::Result updateDepthRenderTarget(const gl::Context *context); 181 angle::Result updateStencilRenderTarget(const gl::Context *context); 182 angle::Result updateCachedRenderTarget(const gl::Context *context, 183 const gl::FramebufferAttachment *attachment, 184 RenderTargetMtl **cachedRenderTarget); 185 186 angle::Result readPixelsToPBO(const gl::Context *context, 187 const gl::Rectangle &area, 188 const PackPixelsParams &packPixelsParams, 189 const RenderTargetMtl *renderTarget) const; 190 191 angle::Result readPixelsToBuffer(const gl::Context *context, 192 const gl::Rectangle &area, 193 const RenderTargetMtl *renderTarget, 194 bool reverseRowOrder, 195 const angle::Format &dstAngleFormat, 196 uint32_t dstBufferOffset, 197 uint32_t dstBufferRowPitch, 198 const mtl::BufferRef *dstBuffer) const; 199 200 bool totalBitsUsedIsLessThanOrEqualToMaxBitsSupported(const gl::Context *context) const; 201 202 RenderTargetMtl *getColorReadRenderTargetNoCache(const gl::Context *context) const; 203 angle::Result prepareForUse(const gl::Context *context) const; 204 205 // Perform unresolve step for loading into memoryless MS attachments. 206 angle::Result unresolveIfNeeded(const gl::Context *context, mtl::RenderCommandEncoder *encoder); 207 208 // NOTE: we cannot use RenderTargetCache here because it doesn't support separate 209 // depth & stencil attachments as of now. Separate depth & stencil could be useful to 210 // save spaces on iOS devices. See doc/PackedDepthStencilSupport.md. 211 angle::FixedVector<RenderTargetMtl *, mtl::kMaxRenderTargets> mColorRenderTargets; 212 RenderTargetMtl *mDepthRenderTarget = nullptr; 213 RenderTargetMtl *mStencilRenderTarget = nullptr; 214 mtl::RenderPassDesc mRenderPassDesc; 215 216 const mtl::Format *mRenderPassFirstColorAttachmentFormat = nullptr; 217 bool mRenderPassAttachmentsSameColorType = false; 218 219 // Flag indicating the render pass start is a clean start or a resume from interruption such 220 // as by a compute pass. 221 bool mRenderPassCleanStart = false; 222 223 WindowSurfaceMtl *mBackbuffer = nullptr; 224 bool mFlipY = false; 225 226 mtl::BufferRef mReadPixelBuffer; 227 228 uint64_t mStartedRenderEncoderSerial = 0; 229 }; 230 } // namespace rx 231 232 #endif /* LIBANGLE_RENDERER_METAL_FRAMEBUFFERMTL_H */ 233