// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_SKIA_OUTPUT_SURFACE_H_
#define COMPONENTS_VIZ_SERVICE_DISPLAY_SKIA_OUTPUT_SURFACE_H_

#include "components/viz/common/resources/resource_format.h"
#include "components/viz/service/display/output_surface.h"
#include "third_party/skia/include/core/SkRefCnt.h"

class SkCanvas;
class SkImage;

namespace viz {

class CopyOutputRequest;
struct ResourceMetadata;

// This class extends the OutputSurface for SkiaRenderer needs. In future, the
// SkiaRenderer will be the only renderer. When other renderers are removed,
// we will replace OutputSurface with SkiaOutputSurface, and remove all
// OutputSurface's methods which are not useful for SkiaRenderer.
class VIZ_SERVICE_EXPORT SkiaOutputSurface : public OutputSurface {
 public:
  SkiaOutputSurface();
  ~SkiaOutputSurface() override;

  // Begin painting the current frame. This method will create a
  // SkDeferredDisplayListRecorder and return a SkCanvas of it.
  // The SkiaRenderer will use this SkCanvas to paint the current
  // frame.
  // And this SkCanvas may become invalid, when FinishPaintCurrentFrame is
  // called.
  virtual SkCanvas* BeginPaintCurrentFrame() = 0;

  // Finish painting the current frame. It should be paired with
  // BeginPaintCurrentFrame. This method will schedule a GPU task to play the
  // DDL back on GPU thread on the SkSurface for the framebuffer. This method
  // returns a sync token which can be waited on in a command buffer to ensure
  // the paint operation is completed. This token is released when the GPU ops
  // from painting the current frame have been seen and processed by the GPU
  // main.
  virtual gpu::SyncToken FinishPaintCurrentFrame() = 0;

  // Make a promise SkImage from the given |metadata|. The SkiaRenderer can use
  // the image with SkCanvas returned by |GetSkCanvasForCurrentFrame|, but Skia
  // will not read the content of the resource until the sync token in the
  // |metadata| is satisfied. The SwapBuffers should take care of this by
  // scheduling a GPU task with all resource sync tokens recorded by
  // MakePromiseSkImage for the current frame.
  virtual sk_sp<SkImage> MakePromiseSkImage(ResourceMetadata metadata) = 0;

  // Make a promise SkImage from the given |metadata| and the |yuv_color_space|.
  // For YUV format, three resource metadatas should be provided. metadatas[0]
  // contains pixels from y panel, metadatas[1] contains pixels from u panel,
  // metadatas[2] contains pixels from v panel.
  // For NV12 format, two resource metadatas should be provided. metadatas[0]
  // contains pixels from y panel, metadatas[1] contains pixels from u and v
  // panels.
  virtual sk_sp<SkImage> MakePromiseSkImageFromYUV(
      std::vector<ResourceMetadata> metadatas,
      SkYUVColorSpace yuv_color_space) = 0;

  // Swaps the current backbuffer to the screen.
  virtual void SkiaSwapBuffers(OutputSurfaceFrame frame) = 0;

  // Begin painting a render pass. This method will create a
  // SkDeferredDisplayListRecorder and return a SkCanvas of it. The SkiaRenderer
  // will use this SkCanvas to paint the render pass.
  // Note: BeginPaintRenderPass cannot be called without finishing the prior
  // paint render pass.
  virtual SkCanvas* BeginPaintRenderPass(const RenderPassId& id,
                                         const gfx::Size& size,
                                         ResourceFormat format,
                                         bool mipmap) = 0;

  // Finish painting a render pass. It should be paired with
  // BeginPaintRenderPass. This method will schedule a GPU task to play the DDL
  // back on GPU thread on a cached SkSurface. This method returns a sync token
  // which can be waited on in a command buffer to ensure the paint operation is
  // completed. This token is released when the GPU ops from painting the render
  // pass have been seen and processed by the GPU main.
  virtual gpu::SyncToken FinishPaintRenderPass() = 0;

  // Make a promise SkImage from a render pass id. The render pass has been
  // painted with BeginPaintRenderPass and FinishPaintRenderPass. The format
  // and mipmap must match arguments used for BeginPaintRenderPass() to paint
  // this render pass.
  virtual sk_sp<SkImage> MakePromiseSkImageFromRenderPass(
      const RenderPassId& id,
      const gfx::Size& size,
      ResourceFormat format,
      bool mipmap) = 0;

  // Remove cached resources generated by BeginPaintRenderPass and
  // FinishPaintRenderPass.
  virtual void RemoveRenderPassResource(std::vector<RenderPassId> ids) = 0;

  // Copy the output of the current frame if the |id| is zero, otherwise copy
  // the output of a cached SkSurface for the given |id|.
  virtual void CopyOutput(RenderPassId id,
                          const gfx::Rect& copy_rect,
                          std::unique_ptr<CopyOutputRequest> request) = 0;

 private:
  DISALLOW_COPY_AND_ASSIGN(SkiaOutputSurface);
};

}  // namespace viz

#endif  // COMPONENTS_VIZ_SERVICE_DISPLAY_SKIA_OUTPUT_SURFACE_H_
