chromium/gpu/command_buffer/service/image_reader_gl_owner.h

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

#ifndef GPU_COMMAND_BUFFER_SERVICE_IMAGE_READER_GL_OWNER_H_
#define GPU_COMMAND_BUFFER_SERVICE_IMAGE_READER_GL_OWNER_H_

#include <media/NdkImageReader.h>

#include <memory>

#include "base/containers/flat_map.h"
#include "base/memory/raw_ptr.h"
#include "base/threading/thread_checker.h"
#include "gpu/command_buffer/service/ref_counted_lock.h"
#include "gpu/command_buffer/service/texture_owner.h"
#include "gpu/gpu_gles2_export.h"
#include "ui/gl/gl_fence_egl.h"

namespace base {
namespace android {
class ScopedHardwareBufferFenceSync;
}  // namespace android
}  // namespace base

namespace gpu {

// This class wraps the AImageReader usage and is used to create a GL texture
// using the current platform GL context and returns a new ImageReaderGLOwner
// attached to it. The surface handle of the AImageReader is attached to
// decoded media frames. Media frames can update the attached surface handle
// with image data and this class helps to create an eglImage using that image
// data present in the surface.
class GPU_GLES2_EXPORT ImageReaderGLOwner : public TextureOwner,
                                            public RefCountedLockHelperDrDc {
 public:
  ImageReaderGLOwner(const ImageReaderGLOwner&) = delete;
  ImageReaderGLOwner& operator=(const ImageReaderGLOwner&) = delete;

  gl::GLContext* GetContext() const override;
  gl::GLSurface* GetSurface() const override;
  void SetFrameAvailableCallback(
      const base::RepeatingClosure& frame_available_cb) override;
  gl::ScopedJavaSurface CreateJavaSurface() const override;
  void UpdateTexImage() override;
  void ReleaseBackBuffers() override;
  std::unique_ptr<base::android::ScopedHardwareBufferFenceSync>
  GetAHardwareBuffer() override;
  bool GetCodedSizeAndVisibleRect(gfx::Size rotated_visible_size,
                                  gfx::Size* coded_size,
                                  gfx::Rect* visible_rect) override;

  void RunWhenBufferIsAvailable(base::OnceClosure callback) override;

  const AImageReader* image_reader_for_testing() const
      NO_THREAD_SAFETY_ANALYSIS {
    return image_reader_;
  }
  int32_t max_images_for_testing() const { return max_images_; }

  // MemoryDumpProvider:
  bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
                    base::trace_event::ProcessMemoryDump* pmd) override;

 protected:
  void ReleaseResources() override;

 private:
  friend class TextureOwner;
  friend class ImageReaderGLOwnerTest;
  class ScopedHardwareBufferImpl;

  // Manages ownership of the latest image retrieved from AImageReader and
  // ensuring synchronization of its use in GL using fences.
  class ScopedCurrentImageRef {
   public:
    ScopedCurrentImageRef(ImageReaderGLOwner* texture_owner,
                          AImage* image,
                          base::ScopedFD ready_fence);

    ScopedCurrentImageRef(const ScopedCurrentImageRef&) = delete;
    ScopedCurrentImageRef& operator=(const ScopedCurrentImageRef&) = delete;

    ~ScopedCurrentImageRef();
    AImage* image() const { return image_; }
    base::ScopedFD GetReadyFence() const;

   private:
    raw_ptr<ImageReaderGLOwner> texture_owner_;
    raw_ptr<AImage> image_;
    base::ScopedFD ready_fence_;
  };

  ImageReaderGLOwner(std::unique_ptr<AbstractTextureAndroid> texture,
                     Mode secure_mode,
                     scoped_refptr<SharedContextState> context_state,
                     scoped_refptr<RefCountedLock> drdc_lock,
                     TextureOwnerCodecType type_for_metrics);
  ~ImageReaderGLOwner() override;

  // Registers and releases a ref on the image. Once the ref-count for an image
  // goes to 0, it is released back to the AImageReader with an optional release
  // fence if needed.
  void RegisterRefOnImageLocked(AImage* image);
  void ReleaseRefOnImageLocked(AImage* image, base::ScopedFD fence_fd);

  // This method acquires |lock_| and calls ReleaseRefOnImageLocked().
  void ReleaseRefOnImage(AImage* image, base::ScopedFD fence_fd);

  gfx::Rect GetCropRectLocked();

  static void OnFrameAvailable(void* context, AImageReader* reader);

  // All members which can be concurrently accessed from multiple threads will
  // be guarded by |lock_|.
  mutable base::Lock lock_;

  // AImageReader instance.
  raw_ptr<AImageReader> image_reader_ GUARDED_BY(lock_);

  // Most recently acquired image using image reader. This works like a cached
  // image until next new image is acquired which overwrites this.
  std::optional<ScopedCurrentImageRef> current_image_ref_ GUARDED_BY(lock_);
  std::unique_ptr<AImageReader_ImageListener> listener_;

  // A map consisting of pending refs on an AImage. If an image has any refs, it
  // is automatically released once the ref-count is 0.
  struct ImageRef {
    ImageRef();

    ImageRef(const ImageRef&) = delete;
    ImageRef& operator=(const ImageRef&) = delete;

    ~ImageRef();

    ImageRef(ImageRef&& other);
    ImageRef& operator=(ImageRef&& other);

    size_t count = 0u;
    base::ScopedFD release_fence_fd;
    gfx::Size size;
    size_t estimated_size_in_bytes = 0;
  };
  using AImageRefMap = base::flat_map<AImage*, ImageRef>;
  AImageRefMap image_refs_ GUARDED_BY(lock_);
  std::atomic<size_t> total_estimated_size_in_bytes_ = 0;

  // The context and surface that were used to create |texture_id_|.
  scoped_refptr<gl::GLContext> context_;
  scoped_refptr<gl::GLSurface> surface_;
  int32_t max_images_ = 0;

  // Frame available callback handling. ImageListener registered with
  // AImageReader is notified when there is a new frame available which
  // in turns runs the callback function.
  base::RepeatingClosure frame_available_cb_;

  // Runs when free buffer is available.
  base::OnceClosure buffer_available_cb_ GUARDED_BY(lock_);

  // This class is created on gpu main thread.
  THREAD_CHECKER(gpu_main_thread_checker_);

  const TextureOwnerCodecType type_for_metrics_;
};

}  // namespace gpu

#endif  // GPU_COMMAND_BUFFER_SERVICE_IMAGE_READER_GL_OWNER_H_