text: //
  // Copyright 2019 The ANGLE Project Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  //
  // FrameBufferMtl.h:
  //    Defines the class interface for FrameBufferMtl, implementing FrameBufferImpl.
  //
  
  #ifndef LIBANGLE_RENDERER_METAL_FRAMEBUFFERMTL_H_
  #define LIBANGLE_RENDERER_METAL_FRAMEBUFFERMTL_H_
  
  #import <Metal/Metal.h>
  
  #include "libANGLE/renderer/FramebufferImpl.h"
  #include "libANGLE/renderer/metal/RenderTargetMtl.h"
  #include "libANGLE/renderer/metal/mtl_render_utils.h"
  
  namespace rx
  {
  class ContextMtl;
  class SurfaceMtl;
  
  class FramebufferMtl : public FramebufferImpl
  {
    public:
      explicit FramebufferMtl(const gl::FramebufferState &state, bool flipY);
      ~FramebufferMtl() override;
      void destroy(const gl::Context *context) override;
  
      angle::Result discard(const gl::Context *context,
                            size_t count,
                            const GLenum *attachments) override;
      angle::Result invalidate(const gl::Context *context,
                               size_t count,
                               const GLenum *attachments) override;
      angle::Result invalidateSub(const gl::Context *context,
                                  size_t count,
                                  const GLenum *attachments,
                                  const gl::Rectangle &area) override;
  
      angle::Result clear(const gl::Context *context, GLbitfield mask) override;
      angle::Result clearBufferfv(const gl::Context *context,
                                  GLenum buffer,
                                  GLint drawbuffer,
                                  const GLfloat *values) override;
      angle::Result clearBufferuiv(const gl::Context *context,
                                   GLenum buffer,
                                   GLint drawbuffer,
                                   const GLuint *values) override;
      angle::Result clearBufferiv(const gl::Context *context,
                                  GLenum buffer,
                                  GLint drawbuffer,
                                  const GLint *values) override;
      angle::Result clearBufferfi(const gl::Context *context,
                                  GLenum buffer,
                                  GLint drawbuffer,
                                  GLfloat depth,
                                  GLint stencil) override;
  
      const gl::InternalFormat &getImplementationColorReadFormat(
          const gl::Context *context) const override;
      angle::Result readPixels(const gl::Context *context,
                               const gl::Rectangle &area,
                               GLenum format,
                               GLenum type,
                               void *pixels) override;
  
      angle::Result blit(const gl::Context *context,
                         const gl::Rectangle &sourceArea,
                         const gl::Rectangle &destArea,
                         GLbitfield mask,
                         GLenum filter) override;
  
      bool checkStatus(const gl::Context *context) const override;
  
      angle::Result syncState(const gl::Context *context,
                              GLenum binding,
                              const gl::Framebuffer::DirtyBits &dirtyBits) override;
  
      angle::Result getSamplePosition(const gl::Context *context,
                                      size_t index,
                                      GLfloat *xy) const override;
  
      RenderTargetMtl *getColorReadRenderTarget() const;
  
      bool flipY() const { return mFlipY; }
  
      gl::Rectangle getCompleteRenderArea() const;
  
      const mtl::RenderPassDesc &getRenderPassDesc(ContextMtl *context);
  
      // Call this to notify FramebufferMtl whenever its render pass has started.
      void onStartedDrawingToFrameBuffer(const gl::Context *context);
  
      // The actual area will be adjusted based on framebuffer flipping property.
      gl::Rectangle getReadPixelArea(const gl::Rectangle &glArea);
  
      // NOTE: this method doesn't do the flipping of area. Caller must do it if needed before
      // callling this. See getReadPixelsArea().
      angle::Result readPixelsImpl(const gl::Context *context,
                                   const gl::Rectangle &area,
                                   const PackPixelsParams &packPixelsParams,
                                   RenderTargetMtl *renderTarget,
                                   uint8_t *pixels);
  
    private:
      void reset();
      angle::Result invalidateImpl(ContextMtl *contextMtl, size_t count, const GLenum *attachments);
      angle::Result clearImpl(const gl::Context *context,
                              gl::DrawBufferMask clearColorBuffers,
                              mtl::ClearRectParams *clearOpts);
  
      angle::Result clearWithLoadOp(const gl::Context *context,
                                    gl::DrawBufferMask clearColorBuffers,
                                    const mtl::ClearRectParams &clearOpts);
  
      angle::Result clearWithDraw(const gl::Context *context,
                                  gl::DrawBufferMask clearColorBuffers,
                                  const mtl::ClearRectParams &clearOpts);
  
      angle::Result prepareRenderPass(const gl::Context *context,
                                      gl::DrawBufferMask drawColorBuffers,
                                      mtl::RenderPassDesc *descOut);
  
      void overrideClearColor(const mtl::TextureRef &texture,
                              MTLClearColor clearColor,
                              MTLClearColor *colorOut);
  
      angle::Result updateColorRenderTarget(const gl::Context *context, size_t colorIndexGL);
      angle::Result updateDepthRenderTarget(const gl::Context *context);
      angle::Result updateStencilRenderTarget(const gl::Context *context);
      angle::Result updateCachedRenderTarget(const gl::Context *context,
                                             const gl::FramebufferAttachment *attachment,
                                             RenderTargetMtl **cachedRenderTarget);
  
      // NOTE: we cannot use RenderTargetCache here because it doesn't support separate
      // depth & stencil attachments as of now. Separate depth & stencil could be useful to
      // save spaces on iOS devices. See doc/PackedDepthStencilSupport.md.
      std::array<RenderTargetMtl *, mtl::kMaxRenderTargets> mColorRenderTargets;
      RenderTargetMtl *mDepthRenderTarget   = nullptr;
      RenderTargetMtl *mStencilRenderTarget = nullptr;
      mtl::RenderPassDesc mRenderPassDesc;
      const bool mFlipY = false;
  };
  }  // namespace rx
  
  #endif /* LIBANGLE_RENDERER_METAL_FRAMEBUFFERMTL_H */
  