// 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 gfx {
class ColorSpace;
}

namespace viz {

class ContextLostObserver;
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;

  // 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, at least 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,
  // at least two resource metadatas should be provided. metadatas[0] contains
  // pixels from y panel, metadatas[1] contains pixels from u and v panels. If
  // has_alpha is true, the last item in metadatas contains alpha panel.
  virtual sk_sp<SkImage> MakePromiseSkImageFromYUV(
      std::vector<ResourceMetadata> metadatas,
      SkYUVColorSpace yuv_color_space,
      bool has_alpha) = 0;

  // Release SkImage created by MakePromiseSkImage on the thread on which
  // it was fulfilled. SyncToken represents point after which SkImage is
  // released.
  virtual gpu::SyncToken QueueReleasePromiseSkImage(sk_sp<SkImage>&& image) = 0;

  // Flush all the queued releases. No-op if none were queued.
  virtual void FlushQueuedReleases() = 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 the current frame or current render pass, depends on which
  // BeginPaint function is called last. 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 SubmitPaint() = 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,
                          const gfx::ColorSpace& color_space,
                          const gfx::Rect& result_rect,
                          std::unique_ptr<CopyOutputRequest> request) = 0;

  // Add context lost observer.
  virtual void AddContextLostObserver(ContextLostObserver* observer) = 0;

  // Remove context lost observer.
  virtual void RemoveContextLostObserver(ContextLostObserver* observer) = 0;

 private:
  DISALLOW_COPY_AND_ASSIGN(SkiaOutputSurface);
};

}  // namespace viz

#endif  // COMPONENTS_VIZ_SERVICE_DISPLAY_SKIA_OUTPUT_SURFACE_H_
