[go: nahoru, domu]

blob: 257f37d28b71be70f5b1c47281f6a6ead9bbdaa1 [file] [log] [blame]
// 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_SHARED_IMAGE_SHARED_IMAGE_REPRESENTATION_H_
#define GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_SHARED_IMAGE_REPRESENTATION_H_
#include <dawn/dawn_proc_table.h>
#include <dawn/webgpu_cpp.h>
#include <memory>
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/types/pass_key.h"
#include "build/build_config.h"
#include "gpu/command_buffer/service/shared_image/shared_image_backing.h"
#include "gpu/command_buffer/service/shared_image/shared_image_manager.h"
#include "gpu/gpu_gles2_export.h"
#include "skia/buildflags.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/gpu/GrDirectContext.h"
#include "third_party/skia/include/gpu/ganesh/SkImageGanesh.h"
#include "third_party/skia/include/gpu/graphite/BackendTexture.h"
#include "third_party/skia/include/private/chromium/GrPromiseImageTexture.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/gpu_fence.h"
#if BUILDFLAG(IS_WIN)
#include "ui/gl/dc_layer_overlay_image.h"
#endif
#if BUILDFLAG(IS_APPLE)
#include "ui/gfx/mac/io_surface.h"
#endif
#if BUILDFLAG(IS_ANDROID)
#include "base/android/scoped_hardware_buffer_fence_sync.h"
extern "C" typedef struct AHardwareBuffer AHardwareBuffer;
#endif
#if BUILDFLAG(IS_WIN)
#include <d3d11.h>
#include <wrl/client.h>
#endif
typedef unsigned int GLenum;
namespace skgpu {
class MutableTextureState;
}
namespace cc {
class PaintOpBuffer;
} // namespace cc
namespace gfx {
class NativePixmap;
} // namespace gfx
namespace media {
class VASurface;
} // namespace media
namespace gpu {
class TextureBase;
namespace gles2 {
class Texture;
class TexturePassthrough;
} // namespace gles2
enum class RepresentationAccessMode {
kNone,
kRead,
kWrite,
};
///////////////////////////////////////////////////////////////////////////////
// SharedImageRepresentation
// A representation of a SharedImageBacking for use with a specific use case /
// api.
class GPU_GLES2_EXPORT SharedImageRepresentation {
public:
using AccessMode = RepresentationAccessMode;
// Used by derived classes.
enum class AllowUnclearedAccess { kYes, kNo };
SharedImageRepresentation(SharedImageManager* manager,
SharedImageBacking* backing,
MemoryTypeTracker* tracker);
virtual ~SharedImageRepresentation();
viz::SharedImageFormat format() const { return backing_->format(); }
const gfx::Size& size() const { return backing_->size(); }
const gfx::ColorSpace& color_space() const { return backing_->color_space(); }
GrSurfaceOrigin surface_origin() const { return backing_->surface_origin(); }
SkAlphaType alpha_type() const { return backing_->alpha_type(); }
uint32_t usage() const { return backing_->usage(); }
const gpu::Mailbox& mailbox() const { return backing_->mailbox(); }
MemoryTypeTracker* tracker() { return tracker_; }
bool IsCleared() const { return backing_->IsCleared(); }
void SetCleared() { backing_->SetCleared(); }
gfx::Rect ClearedRect() const { return backing_->ClearedRect(); }
void SetClearedRect(const gfx::Rect& cleared_rect) {
backing_->SetClearedRect(cleared_rect);
}
// Indicates that the underlying graphics context has been lost, and the
// backing should be treated as destroyed.
void OnContextLost() {
has_context_ = false;
backing_->OnContextLost();
}
// Returns the number of image planes expected based on the backing format.
size_t NumPlanesExpected() const;
protected:
SharedImageManager* manager() const { return manager_; }
SharedImageBacking* backing() const { return backing_; }
bool has_context() const { return has_context_; }
// Helper class for derived classes' Scoped*Access objects. Has tracking to
// ensure a Scoped*Access does not outlive the representation it's associated
// with.
template <typename RepresentationClass>
class ScopedAccessBase {
public:
ScopedAccessBase(RepresentationClass* representation,
AccessMode access_mode)
: representation_(representation) {
CHECK_EQ(representation_->access_mode_, AccessMode::kNone);
representation_->access_mode_ = access_mode;
}
ScopedAccessBase(const ScopedAccessBase&) = delete;
ScopedAccessBase& operator=(const ScopedAccessBase&) = delete;
~ScopedAccessBase() {
CHECK_NE(representation_->access_mode_, AccessMode::kNone);
representation_->access_mode_ = AccessMode::kNone;
}
RepresentationClass* representation() { return representation_; }
const RepresentationClass* representation() const {
return representation_;
}
private:
const raw_ptr<RepresentationClass> representation_;
};
private:
const raw_ptr<SharedImageManager, DanglingUntriaged> manager_;
raw_ptr<SharedImageBacking> backing_;
const raw_ptr<MemoryTypeTracker> tracker_;
bool has_context_ = true;
AccessMode access_mode_ = AccessMode::kNone;
};
///////////////////////////////////////////////////////////////////////////////
// SharedImageRepresentationFactoryRef
class SharedImageRepresentationFactoryRef : public SharedImageRepresentation {
public:
SharedImageRepresentationFactoryRef(SharedImageManager* manager,
SharedImageBacking* backing,
MemoryTypeTracker* tracker,
bool is_primary);
~SharedImageRepresentationFactoryRef() override;
const Mailbox& mailbox() const { return backing()->mailbox(); }
void Update(std::unique_ptr<gfx::GpuFence> in_fence) {
backing()->Update(std::move(in_fence));
backing()->OnWriteSucceeded();
}
bool CopyToGpuMemoryBuffer() { return backing()->CopyToGpuMemoryBuffer(); }
void GetGpuMemoryBufferHandleInfo(gfx::GpuMemoryBufferHandle& handle,
viz::SharedImageFormat& format,
gfx::Size& size,
gfx::BufferUsage& buffer_usage) {
handle = backing()->GetGpuMemoryBufferHandle();
format = backing()->format();
size = backing()->size();
buffer_usage = backing()->buffer_usage();
}
bool PresentSwapChain() { return backing()->PresentSwapChain(); }
void RegisterImageFactory(SharedImageFactory* factory) {
DCHECK(is_primary_);
backing()->RegisterImageFactory(factory);
}
private:
const bool is_primary_;
};
///////////////////////////////////////////////////////////////////////////////
// GLTextureImageRepresentationBase
class GPU_GLES2_EXPORT GLTextureImageRepresentationBase
: public SharedImageRepresentation {
public:
static constexpr GLenum kReadAccessMode = 0x8AF6;
class ScopedAccess
: public ScopedAccessBase<GLTextureImageRepresentationBase> {
public:
ScopedAccess(base::PassKey<GLTextureImageRepresentationBase> pass_key,
GLTextureImageRepresentationBase* representation,
AccessMode access_mode)
: ScopedAccessBase(representation, access_mode) {}
~ScopedAccess() {
representation()->UpdateClearedStateOnEndAccess();
representation()->EndAccess();
}
};
GLTextureImageRepresentationBase(SharedImageManager* manager,
SharedImageBacking* backing,
MemoryTypeTracker* tracker)
: SharedImageRepresentation(manager, backing, tracker) {}
std::unique_ptr<ScopedAccess> BeginScopedAccess(
GLenum mode,
AllowUnclearedAccess allow_uncleared);
// Gets the texture associated with the `plane_index` for SharedImageFormat.
virtual gpu::TextureBase* GetTextureBase(int plane_index) = 0;
// Calls GetTextureBase with `plane_index` = 0 for single planar formats eg.
// RGB.
gpu::TextureBase* GetTextureBase();
protected:
friend class SkiaGLImageRepresentation;
friend class DawnEGLImageRepresentation;
friend class DawnGLTextureRepresentation;
friend class GLTextureGLCommonRepresentation;
// Can be overridden to handle clear state tracking when GL access begins or
// ends.
virtual void UpdateClearedStateOnBeginAccess() {}
virtual void UpdateClearedStateOnEndAccess() {}
virtual bool BeginAccess(GLenum mode) = 0;
virtual void EndAccess() = 0;
virtual bool SupportsMultipleConcurrentReadAccess();
};
///////////////////////////////////////////////////////////////////////////////
// GLTextureImageRepresentation
class GPU_GLES2_EXPORT GLTextureImageRepresentation
: public GLTextureImageRepresentationBase {
public:
GLTextureImageRepresentation(SharedImageManager* manager,
SharedImageBacking* backing,
MemoryTypeTracker* tracker)
: GLTextureImageRepresentationBase(manager, backing, tracker) {}
// Gets the texture associated with the `plane_index` for SharedImageFormat.
virtual gles2::Texture* GetTexture(int plane_index) = 0;
// Calls GetTexture with `plane_index` = 0 for single planar formats eg. RGB.
gles2::Texture* GetTexture();
gpu::TextureBase* GetTextureBase(int plane_index) override;
protected:
friend class WrappedGLTextureCompoundImageRepresentation;
void UpdateClearedStateOnBeginAccess() override;
void UpdateClearedStateOnEndAccess() override;
};
///////////////////////////////////////////////////////////////////////////////
// GLTexturePassthroughImageRepresentation
class GPU_GLES2_EXPORT GLTexturePassthroughImageRepresentation
: public GLTextureImageRepresentationBase {
public:
GLTexturePassthroughImageRepresentation(SharedImageManager* manager,
SharedImageBacking* backing,
MemoryTypeTracker* tracker)
: GLTextureImageRepresentationBase(manager, backing, tracker) {}
// Gets the passthrough texture associated with the `plane_index` for
// SharedImageFormat.
virtual const scoped_refptr<gles2::TexturePassthrough>& GetTexturePassthrough(
int plane_index) = 0;
// Calls GetTexturePassthrough with `plane_index` = 0 for single planar
// formats eg. RGB.
const scoped_refptr<gles2::TexturePassthrough>& GetTexturePassthrough();
gpu::TextureBase* GetTextureBase(int plane_index) override;
// Returns true if access must be suspended in between GL decoder tasks due to
// DXGI keyed mutex. Only implemented for D3D GL representation.
virtual bool NeedsSuspendAccessForDXGIKeyedMutex() const;
private:
friend class WrappedGLTexturePassthroughCompoundImageRepresentation;
};
///////////////////////////////////////////////////////////////////////////////
// SkiaImageRepresentation
class GPU_GLES2_EXPORT SkiaImageRepresentation
: public SharedImageRepresentation {
public:
class GPU_GLES2_EXPORT ScopedWriteAccess
: public ScopedAccessBase<SkiaImageRepresentation> {
public:
virtual ~ScopedWriteAccess();
// NOTE: All references to the returned SkSurface(s) must be destroyed
// before ScopedWriteAccess is destroyed.
SkSurface* surface() const {
// Writes do not support external sampler.
CHECK(representation()->format().is_single_plane());
return surface(0);
}
SkSurface* surface(int plane_index) const {
return surfaces_[plane_index].get();
}
GrPromiseImageTexture* promise_image_texture(int plane_index) const {
return promise_image_textures_[plane_index].get();
}
skgpu::graphite::BackendTexture graphite_texture(int plane_index) const {
return graphite_textures_[plane_index];
}
// NOTE: Implemented only for Ganesh.
// Applies the skgpu::MutableTextureState for Vulkan layout and external
// queue transitions needed for Vulkan/GL interop.
virtual void ApplyBackendSurfaceEndState() = 0;
protected:
ScopedWriteAccess(SkiaImageRepresentation* representation,
std::vector<sk_sp<SkSurface>> surfaces);
ScopedWriteAccess(
SkiaImageRepresentation* representation,
std::vector<sk_sp<GrPromiseImageTexture>> promise_image_textures);
ScopedWriteAccess(
SkiaImageRepresentation* representation,
std::vector<skgpu::graphite::BackendTexture> graphite_textures);
// A vector of surfaces, promise textures and graphite backend textures
// corresponding to the number of planes in SharedImageFormat.
std::vector<sk_sp<SkSurface>> surfaces_;
// NOTE: Used only for Ganesh.
std::vector<sk_sp<GrPromiseImageTexture>> promise_image_textures_;
// NOTE: Used only for Graphite.
std::vector<skgpu::graphite::BackendTexture> graphite_textures_;
};
class GPU_GLES2_EXPORT ScopedReadAccess
: public ScopedAccessBase<SkiaImageRepresentation> {
public:
virtual ~ScopedReadAccess();
GrPromiseImageTexture* promise_image_texture() const {
CHECK_EQ(representation()->NumPlanesExpected(), 1u);
return promise_image_texture(0);
}
GrPromiseImageTexture* promise_image_texture(int plane_index) const {
return promise_image_textures_[plane_index].get();
}
skgpu::graphite::BackendTexture graphite_texture() const {
CHECK_EQ(representation()->NumPlanesExpected(), 1u);
return graphite_texture(0);
}
skgpu::graphite::BackendTexture graphite_texture(int plane_index) const {
return graphite_textures_[plane_index];
}
// Creates an SkImage from BackendTexture for single planar formats or if
// format prefers external sampler. Creates an SkImage from
// YUVABackendTexture for multiplanar formats.
virtual sk_sp<SkImage> CreateSkImage(
SharedContextState* context_state,
SkImages::TextureReleaseProc texture_release_proc = nullptr,
SkImages::ReleaseContext release_context = nullptr) = 0;
// Creates an SkImage for the given `plane_index` for
// multiplanar formats.
virtual sk_sp<SkImage> CreateSkImageForPlane(
int plane_index,
SharedContextState* context_state) = 0;
// NOTE: Implemented only for Ganesh.
// Checks if need to apply skgpu::MutableTextureState.
virtual bool HasBackendSurfaceEndState() = 0;
// Applies the skgpu::MutableTextureState for Vulkan layout and external
// queue transitions needed for Vulkan/GL interop.
virtual void ApplyBackendSurfaceEndState() = 0;
protected:
ScopedReadAccess(
SkiaImageRepresentation* representation,
std::vector<sk_sp<GrPromiseImageTexture>> promise_image_textures);
ScopedReadAccess(
SkiaImageRepresentation* representation,
std::vector<skgpu::graphite::BackendTexture> graphite_textures);
// A vector of promise textures and graphite backend textures corresponding
// to the number of planes in SharedImageFormat. NOTE: Used only for Ganesh.
std::vector<sk_sp<GrPromiseImageTexture>> promise_image_textures_;
// NOTE: Used only for Graphite.
std::vector<skgpu::graphite::BackendTexture> graphite_textures_;
};
SkiaImageRepresentation(SharedImageManager* manager,
SharedImageBacking* backing,
MemoryTypeTracker* tracker);
~SkiaImageRepresentation() override;
// Note: See BeginWriteAccess below for a description of the semaphore
// parameters.
virtual std::unique_ptr<ScopedWriteAccess> BeginScopedWriteAccess(
int final_msaa_count,
const SkSurfaceProps& surface_props,
const gfx::Rect& update_rect,
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores,
AllowUnclearedAccess allow_uncleared,
bool use_sk_surface = true) = 0;
virtual std::unique_ptr<ScopedWriteAccess> BeginScopedWriteAccess(
int final_msaa_count,
const SkSurfaceProps& surface_props,
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores,
AllowUnclearedAccess allow_uncleared,
bool use_sk_surface = true) = 0;
virtual std::unique_ptr<ScopedWriteAccess> BeginScopedWriteAccess(
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores,
AllowUnclearedAccess allow_uncleared,
bool use_sk_surface = true) = 0;
// Note: See BeginReadAccess below for a description of the semaphore
// parameters.
virtual std::unique_ptr<ScopedReadAccess> BeginScopedReadAccess(
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores) = 0;
virtual bool SupportsMultipleConcurrentReadAccess();
protected:
virtual void EndWriteAccess() = 0;
virtual void EndReadAccess() = 0;
};
///////////////////////////////////////////////////////////////////////////////
// SkiaGaneshImageRepresentation
class GPU_GLES2_EXPORT SkiaGaneshImageRepresentation
: public SkiaImageRepresentation {
public:
class GPU_GLES2_EXPORT ScopedGaneshWriteAccess : public ScopedWriteAccess {
public:
ScopedGaneshWriteAccess(
base::PassKey<SkiaGaneshImageRepresentation> pass_key,
SkiaImageRepresentation* representation,
std::vector<sk_sp<SkSurface>> surfaces,
std::unique_ptr<skgpu::MutableTextureState> end_state);
ScopedGaneshWriteAccess(
base::PassKey<SkiaGaneshImageRepresentation> pass_key,
SkiaImageRepresentation* representation,
std::vector<sk_sp<GrPromiseImageTexture>> promise_image_textures,
std::unique_ptr<skgpu::MutableTextureState> end_state);
~ScopedGaneshWriteAccess() override;
// Applies the skgpu::MutableTextureState for Vulkan layout and external
// queue transitions needed for Vulkan/GL interop.
void ApplyBackendSurfaceEndState() override;
private:
SkiaGaneshImageRepresentation* ganesh_representation() {
return static_cast<SkiaGaneshImageRepresentation*>(representation());
}
std::unique_ptr<skgpu::MutableTextureState> end_state_;
};
class GPU_GLES2_EXPORT ScopedGaneshReadAccess : public ScopedReadAccess {
public:
ScopedGaneshReadAccess(
base::PassKey<SkiaGaneshImageRepresentation> pass_key,
SkiaImageRepresentation* representation,
std::vector<sk_sp<GrPromiseImageTexture>> promise_image_textures,
std::unique_ptr<skgpu::MutableTextureState> end_state);
~ScopedGaneshReadAccess() override;
// Creates an SkImage from GrBackendTexture for single planar formats or if
// format prefers external sampler. Creates an SkImage from
// GrYUVABackendTexture for multiplanar formats.
sk_sp<SkImage> CreateSkImage(
SharedContextState* context_state,
SkImages::TextureReleaseProc texture_release_proc = nullptr,
SkImages::ReleaseContext release_context = nullptr) override;
// Creates an SkImage for the given `plane_index` from GrBackendTexture for
// multiplanar formats.
sk_sp<SkImage> CreateSkImageForPlane(
int plane_index,
SharedContextState* context_state) override;
// Checks if need to apply skgpu::MutableTextureState.
bool HasBackendSurfaceEndState() override;
// Applies the skgpu::MutableTextureState for Vulkan layout and external
// queue transitions needed for Vulkan/GL interop.
void ApplyBackendSurfaceEndState() override;
private:
SkiaGaneshImageRepresentation* ganesh_representation() {
return static_cast<SkiaGaneshImageRepresentation*>(representation());
}
std::unique_ptr<skgpu::MutableTextureState> end_state_;
};
SkiaGaneshImageRepresentation(GrDirectContext* gr_context,
SharedImageManager* manager,
SharedImageBacking* backing,
MemoryTypeTracker* tracker);
GrDirectContext* gr_context() const { return gr_context_; }
// Note: See BeginWriteAccess below for a description of the semaphore
// parameters.
std::unique_ptr<ScopedWriteAccess> BeginScopedWriteAccess(
int final_msaa_count,
const SkSurfaceProps& surface_props,
const gfx::Rect& update_rect,
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores,
AllowUnclearedAccess allow_uncleared,
bool use_sk_surface = true) override;
std::unique_ptr<ScopedWriteAccess> BeginScopedWriteAccess(
int final_msaa_count,
const SkSurfaceProps& surface_props,
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores,
AllowUnclearedAccess allow_uncleared,
bool use_sk_surface = true) override;
std::unique_ptr<ScopedWriteAccess> BeginScopedWriteAccess(
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores,
AllowUnclearedAccess allow_uncleared,
bool use_sk_surface = true) override;
// Note: See BeginReadAccess below for a description of the semaphore
// parameters.
std::unique_ptr<ScopedReadAccess> BeginScopedReadAccess(
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores) override;
protected:
friend class WrappedSkiaGaneshCompoundImageRepresentation;
// Begin the write access.
//
// update_rect is a hint to the backend about the portion of the image that
// will be drawn to. Callers shouldn't draw outside of this area, but aren't
// required to overwrite every pixel inside it.
//
// The implementations should insert semaphores into begin_semaphores vector
// which client will wait on before writing the backing. The ownership of
// begin_semaphores is not passed to client. The implementations can also
// optionally insert semaphores into end_semaphores. If using end_semaphores,
// the client must submit them with drawing operations which use the backing.
// The ownership of end_semaphores are not passed to client. And client must
// submit the end_semaphores before calling EndWriteAccess().
//
// The backing can assign end_state, and the caller must reset backing's state
// to the end_state before calling EndWriteAccess().
// Returns an empty vector on failure.
virtual std::vector<sk_sp<SkSurface>> BeginWriteAccess(
int final_msaa_count,
const SkSurfaceProps& surface_props,
const gfx::Rect& update_rect,
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores,
std::unique_ptr<skgpu::MutableTextureState>* end_state) = 0;
virtual std::vector<sk_sp<GrPromiseImageTexture>> BeginWriteAccess(
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores,
std::unique_ptr<skgpu::MutableTextureState>* end_state) = 0;
// Begin the read access. The implementations should insert semaphores into
// begin_semaphores vector which client will wait on before reading the
// backing. The ownership of begin_semaphores is not passed to client.
// The implementations can also optionally insert semaphores into
// end_semaphores. If using end_semaphores, the client must submit them with
// drawing operations which use the backing. The ownership of end_semaphores
// are not passed to client. And client must submit the end_semaphores before
// calling EndReadAccess().
// The backing can assign end_state, and the caller must reset backing's state
// to the end_state before calling EndReadAccess().
// Returns an empty vector on failure.
virtual std::vector<sk_sp<GrPromiseImageTexture>> BeginReadAccess(
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores,
std::unique_ptr<skgpu::MutableTextureState>* end_state) = 0;
private:
raw_ptr<GrDirectContext> gr_context_ = nullptr;
};
///////////////////////////////////////////////////////////////////////////////
// SkiaGraphiteImageRepresentation
class GPU_GLES2_EXPORT SkiaGraphiteImageRepresentation
: public SkiaImageRepresentation {
public:
class GPU_GLES2_EXPORT ScopedGraphiteWriteAccess : public ScopedWriteAccess {
public:
ScopedGraphiteWriteAccess(
base::PassKey<SkiaGraphiteImageRepresentation> pass_key,
SkiaImageRepresentation* representation,
std::vector<sk_sp<SkSurface>> surfaces);
ScopedGraphiteWriteAccess(
base::PassKey<SkiaGraphiteImageRepresentation> pass_key,
SkiaImageRepresentation* representation,
std::vector<skgpu::graphite::BackendTexture> graphite_textures);
~ScopedGraphiteWriteAccess() override;
// Graphite-Dawn backend handles Vulkan transitions by itself, so nothing to
// do here.
void ApplyBackendSurfaceEndState() override;
};
class GPU_GLES2_EXPORT ScopedGraphiteReadAccess : public ScopedReadAccess {
public:
ScopedGraphiteReadAccess(
base::PassKey<SkiaGraphiteImageRepresentation> pass_key,
SkiaImageRepresentation* representation,
std::vector<skgpu::graphite::BackendTexture> graphite_textures);
~ScopedGraphiteReadAccess() override;
// Creates an SkImage from BackendTexture for single planar formats or if
// format prefers external sampler. Creates an SkImage from
// YUVABackendTexture for multiplanar formats.
sk_sp<SkImage> CreateSkImage(
SharedContextState* context_state,
SkImages::TextureReleaseProc texture_release_proc = nullptr,
SkImages::ReleaseContext release_context = nullptr) override;
// Creates an SkImage for the given `plane_index` from BackendTexture for
// multiplanar formats.
sk_sp<SkImage> CreateSkImageForPlane(
int plane_index,
SharedContextState* context_state) override;
// Graphite-Dawn backend handles Vulkan transitions by itself, so nothing to
// do here.
bool HasBackendSurfaceEndState() override;
void ApplyBackendSurfaceEndState() override;
};
SkiaGraphiteImageRepresentation(SharedImageManager* manager,
SharedImageBacking* backing,
MemoryTypeTracker* tracker);
// Note: See BeginWriteAccess below for a description of the semaphore
// parameters.
std::unique_ptr<ScopedWriteAccess> BeginScopedWriteAccess(
int final_msaa_count,
const SkSurfaceProps& surface_props,
const gfx::Rect& update_rect,
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores,
AllowUnclearedAccess allow_uncleared,
bool use_sk_surface = true) override;
std::unique_ptr<ScopedWriteAccess> BeginScopedWriteAccess(
int final_msaa_count,
const SkSurfaceProps& surface_props,
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores,
AllowUnclearedAccess allow_uncleared,
bool use_sk_surface = true) override;
std::unique_ptr<ScopedWriteAccess> BeginScopedWriteAccess(
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores,
AllowUnclearedAccess allow_uncleared,
bool use_sk_surface = true) override;
// Note: See BeginReadAccess below for a description of the semaphore
// parameters.
std::unique_ptr<ScopedReadAccess> BeginScopedReadAccess(
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores) override;
protected:
friend class WrappedSkiaGraphiteCompoundImageRepresentation;
// Begin the write access. Returns an empty vector on failure.
//
// update_rect is a hint to the backend about the portion of the image that
// will be drawn to. Callers shouldn't draw outside of this area, but aren't
// required to overwrite every pixel inside it.
virtual std::vector<sk_sp<SkSurface>> BeginWriteAccess(
const SkSurfaceProps& surface_props,
const gfx::Rect& update_rect) = 0;
virtual std::vector<skgpu::graphite::BackendTexture> BeginWriteAccess() = 0;
// Returns an empty vector on failure.
virtual std::vector<skgpu::graphite::BackendTexture> BeginReadAccess() = 0;
};
///////////////////////////////////////////////////////////////////////////////
// DawnImageRepresentation
class GPU_GLES2_EXPORT DawnImageRepresentation
: public SharedImageRepresentation {
public:
static constexpr wgpu::TextureUsage kWriteUsage =
wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment |
wgpu::TextureUsage::StorageBinding;
DawnImageRepresentation(SharedImageManager* manager,
SharedImageBacking* backing,
MemoryTypeTracker* tracker)
: SharedImageRepresentation(manager, backing, tracker) {}
class GPU_GLES2_EXPORT ScopedAccess
: public ScopedAccessBase<DawnImageRepresentation> {
public:
ScopedAccess(base::PassKey<DawnImageRepresentation> pass_key,
DawnImageRepresentation* representation,
wgpu::Texture texture,
AccessMode access_mode);
~ScopedAccess();
// Get the unowned texture handle. The caller should take a reference
// if necessary by doing wgpu::Texture texture(access->texture());
const wgpu::Texture& texture() const { return texture_; }
private:
wgpu::Texture texture_;
};
// Calls BeginAccess and returns a ScopedAccess object which will EndAccess
// when it goes out of scope. The Representation must outlive the returned
// ScopedAccess.
std::unique_ptr<ScopedAccess> BeginScopedAccess(
wgpu::TextureUsage usage,
AllowUnclearedAccess allow_uncleared);
// For write usage, the update_rect is a hint to the backend about the portion
// of the image that will be drawn to. Callers shouldn't draw outside of this
// area, but aren't required to overwrite every pixel inside it.
// For non-write usage, the update_rect can be ignored.
std::unique_ptr<ScopedAccess> BeginScopedAccess(
wgpu::TextureUsage usage,
AllowUnclearedAccess allow_uncleared,
const gfx::Rect& update_rect);
private:
friend class WrappedDawnCompoundImageRepresentation;
// This can return null in case of a Dawn validation error, for example if
// usage is invalid.
virtual wgpu::Texture BeginAccess(wgpu::TextureUsage usage) = 0;
virtual wgpu::Texture BeginAccess(wgpu::TextureUsage usage,
const gfx::Rect& update_rect);
virtual void EndAccess() = 0;
};
///////////////////////////////////////////////////////////////////////////////
// OverlayImageRepresentation
class GPU_GLES2_EXPORT OverlayImageRepresentation
: public SharedImageRepresentation {
public:
OverlayImageRepresentation(SharedImageManager* manager,
SharedImageBacking* backing,
MemoryTypeTracker* tracker)
: SharedImageRepresentation(manager, backing, tracker) {}
class GPU_GLES2_EXPORT ScopedReadAccess
: public ScopedAccessBase<OverlayImageRepresentation> {
public:
ScopedReadAccess(base::PassKey<OverlayImageRepresentation> pass_key,
OverlayImageRepresentation* representation,
gfx::GpuFenceHandle acquire_fence);
~ScopedReadAccess();
#if BUILDFLAG(IS_ANDROID)
AHardwareBuffer* GetAHardwareBuffer() {
return representation()->GetAHardwareBuffer();
}
// Deprecated. All code should use GetAHardwareBuffer() above, this function
// will be deleted when GLSurfaceEGLSurface control will be able to deliver
// fences via EndAccess.
std::unique_ptr<base::android::ScopedHardwareBufferFenceSync>
GetAHardwareBufferFenceSync() {
return representation()->GetAHardwareBufferFenceSync();
}
#elif BUILDFLAG(IS_OZONE)
scoped_refptr<gfx::NativePixmap> GetNativePixmap() {
return representation()->GetNativePixmap();
}
#elif BUILDFLAG(IS_WIN)
absl::optional<gl::DCLayerOverlayImage> GetDCLayerOverlayImage() {
return representation()->GetDCLayerOverlayImage();
}
#elif BUILDFLAG(IS_APPLE)
gfx::ScopedIOSurface GetIOSurface() const {
return representation()->GetIOSurface();
}
bool IsInUseByWindowServer() const {
return representation()->IsInUseByWindowServer();
}
#endif
gfx::GpuFenceHandle TakeAcquireFence() { return std::move(acquire_fence_); }
void SetReleaseFence(gfx::GpuFenceHandle release_fence) {
// Note: We overwrite previous fence. In case if window manager uses fence
// for each frame we schedule overlay and the same image is scheduled for
// multiple frames this will be updated after each frame. It's safe to
// wait only for the last frame's fence.
release_fence_ = std::move(release_fence);
}
private:
gfx::GpuFenceHandle acquire_fence_;
gfx::GpuFenceHandle release_fence_;
};
std::unique_ptr<ScopedReadAccess> BeginScopedReadAccess();
protected:
friend class WrappedOverlayCompoundImageRepresentation;
// Notifies the backing that an access will start. Returns false if there is a
// conflict. Otherwise, returns true and:
// - Set a gpu fence to |acquire_fence| that should be waited on before the
// SharedImage is ready to be displayed. This fence is fired when the gpu
// has finished writing.
virtual bool BeginReadAccess(gfx::GpuFenceHandle& acquire_fence) = 0;
// |release_fence| is a fence that will be signaled when the image can be
// safely re-used. Note, on some platforms window manager doesn't support
// release fences and return image when it's already safe to re-use.
// |release_fence| will be null in that case.
virtual void EndReadAccess(gfx::GpuFenceHandle release_fence) = 0;
#if BUILDFLAG(IS_ANDROID)
virtual AHardwareBuffer* GetAHardwareBuffer();
virtual std::unique_ptr<base::android::ScopedHardwareBufferFenceSync>
GetAHardwareBufferFenceSync();
#elif BUILDFLAG(IS_OZONE)
scoped_refptr<gfx::NativePixmap> GetNativePixmap();
#elif BUILDFLAG(IS_WIN)
virtual absl::optional<gl::DCLayerOverlayImage> GetDCLayerOverlayImage();
#elif BUILDFLAG(IS_APPLE)
virtual gfx::ScopedIOSurface GetIOSurface() const;
// Return true if the macOS WindowServer is currently using the underlying
// storage for the image.
virtual bool IsInUseByWindowServer() const;
#endif
};
///////////////////////////////////////////////////////////////////////////////
// LegacyOverlayImageRepresentation
#if BUILDFLAG(IS_ANDROID)
class GPU_GLES2_EXPORT LegacyOverlayImageRepresentation
: public SharedImageRepresentation {
public:
LegacyOverlayImageRepresentation(SharedImageManager* manager,
SharedImageBacking* backing,
MemoryTypeTracker* tracker)
: SharedImageRepresentation(manager, backing, tracker) {}
// Renders shared image to SurfaceView/Dialog overlay. Should only be called
// if the image already promoted to overlay.
virtual void RenderToOverlay() = 0;
// Notifies legacy overlay system about overlay promotion.
virtual void NotifyOverlayPromotion(bool promotion,
const gfx::Rect& bounds) = 0;
};
#endif
///////////////////////////////////////////////////////////////////////////////
// MemoryImageRepresentation
class GPU_GLES2_EXPORT MemoryImageRepresentation
: public SharedImageRepresentation {
public:
class GPU_GLES2_EXPORT ScopedReadAccess
: public ScopedAccessBase<MemoryImageRepresentation> {
public:
ScopedReadAccess(base::PassKey<MemoryImageRepresentation> pass_key,
MemoryImageRepresentation* representation,
SkPixmap pixmap);
~ScopedReadAccess();
SkPixmap pixmap() { return pixmap_; }
private:
SkPixmap pixmap_;
};
MemoryImageRepresentation(SharedImageManager* manager,
SharedImageBacking* backing,
MemoryTypeTracker* tracker)
: SharedImageRepresentation(manager, backing, tracker) {}
std::unique_ptr<ScopedReadAccess> BeginScopedReadAccess();
protected:
virtual SkPixmap BeginReadAccess() = 0;
};
// An interface that allows a SharedImageBacking to hold a reference to VA-API
// surface without depending on //media/gpu/vaapi targets.
class VaapiDependencies {
public:
virtual ~VaapiDependencies() = default;
virtual const media::VASurface* GetVaSurface() const = 0;
virtual bool SyncSurface() = 0;
};
// Interface that allows a SharedImageBacking to create VaapiDependencies from a
// NativePixmap without depending on //media/gpu/vaapi targets.
class VaapiDependenciesFactory {
public:
virtual ~VaapiDependenciesFactory() = default;
// Returns a VaapiDependencies or nullptr on failure.
virtual std::unique_ptr<VaapiDependencies> CreateVaapiDependencies(
scoped_refptr<gfx::NativePixmap> pixmap) = 0;
};
///////////////////////////////////////////////////////////////////////////////
// VaapiImageRepresentation
// Representation of a SharedImageBacking as a VA-API surface.
// This representation is currently only supported by OzoneImageBacking.
//
// Synchronized access is currently not required in this representation because:
//
// For reads:
// We will be using this for the destination of decoding work, so no read access
// synchronization is needed from the point of view of the VA-API.
//
// For writes:
// Because of the design of the current video pipeline, we don't start the
// decoding work until we're sure that the destination buffer is not being used
// by the rest of the pipeline. However, we still need to keep track of write
// accesses so that other representations can synchronize with the decoder.
class GPU_GLES2_EXPORT VaapiImageRepresentation
: public SharedImageRepresentation {
public:
class GPU_GLES2_EXPORT ScopedWriteAccess
: public ScopedAccessBase<VaapiImageRepresentation> {
public:
ScopedWriteAccess(base::PassKey<VaapiImageRepresentation> pass_key,
VaapiImageRepresentation* representation);
~ScopedWriteAccess();
const media::VASurface* va_surface();
};
VaapiImageRepresentation(SharedImageManager* manager,
SharedImageBacking* backing,
MemoryTypeTracker* tracker,
VaapiDependencies* vaapi_dependency);
~VaapiImageRepresentation() override;
std::unique_ptr<ScopedWriteAccess> BeginScopedWriteAccess();
private:
friend class WrappedVaapiRepresentation;
raw_ptr<VaapiDependencies> vaapi_deps_;
virtual void EndAccess() = 0;
virtual void BeginAccess() = 0;
};
///////////////////////////////////////////////////////////////////////////////
// RasterImageRepresentation
// Representation of a SharedImageBacking for raster work.
// This representation is used for raster work and compositor. The raster work
// will be converted to a cc::PaintOpBuffer and stored in the
// SharedImageBacking. And then the the compositor will access the stored
// cc::PaintOpBuffer and execute paint ops in it.
class GPU_GLES2_EXPORT RasterImageRepresentation
: public SharedImageRepresentation {
public:
class GPU_GLES2_EXPORT ScopedReadAccess
: public ScopedAccessBase<RasterImageRepresentation> {
public:
ScopedReadAccess(base::PassKey<RasterImageRepresentation> pass_key,
RasterImageRepresentation* representation,
const cc::PaintOpBuffer* paint_op_buffer,
const absl::optional<SkColor4f>& clear_color);
~ScopedReadAccess();
const cc::PaintOpBuffer* paint_op_buffer() const {
return paint_op_buffer_;
}
const absl::optional<SkColor4f>& clear_color() const {
return clear_color_;
}
private:
const raw_ptr<const cc::PaintOpBuffer> paint_op_buffer_;
absl::optional<SkColor4f> clear_color_;
};
class GPU_GLES2_EXPORT ScopedWriteAccess
: public ScopedAccessBase<RasterImageRepresentation> {
public:
ScopedWriteAccess(base::PassKey<RasterImageRepresentation> pass_key,
RasterImageRepresentation* representation,
cc::PaintOpBuffer* paint_op_buffer);
~ScopedWriteAccess();
cc::PaintOpBuffer* paint_op_buffer() { return paint_op_buffer_; }
// An optional callback which will be called when the all paint ops in the
// |paint_op_buffer_| are released.
void set_callback(base::OnceClosure callback) {
DCHECK(!callback_);
DCHECK(callback);
callback_ = std::move(callback);
}
private:
const raw_ptr<cc::PaintOpBuffer> paint_op_buffer_;
base::OnceClosure callback_;
};
RasterImageRepresentation(SharedImageManager* manager,
SharedImageBacking* backing,
MemoryTypeTracker* tracker)
: SharedImageRepresentation(manager, backing, tracker) {}
std::unique_ptr<ScopedReadAccess> BeginScopedReadAccess();
std::unique_ptr<ScopedWriteAccess> BeginScopedWriteAccess(
scoped_refptr<SharedContextState> context_state,
int final_msaa_count,
const SkSurfaceProps& surface_props,
const absl::optional<SkColor4f>& clear_color,
bool visible);
protected:
virtual cc::PaintOpBuffer* BeginReadAccess(
absl::optional<SkColor4f>& clear_color) = 0;
virtual void EndReadAccess() = 0;
virtual cc::PaintOpBuffer* BeginWriteAccess(
scoped_refptr<SharedContextState> context_state,
int final_msaa_count,
const SkSurfaceProps& surface_props,
const absl::optional<SkColor4f>& clear_color,
bool visible) = 0;
virtual void EndWriteAccess(base::OnceClosure callback) = 0;
};
///////////////////////////////////////////////////////////////////////////////
// VideoDecodeImageRepresentation
class GPU_GLES2_EXPORT VideoDecodeImageRepresentation
: public SharedImageRepresentation {
public:
class GPU_GLES2_EXPORT ScopedWriteAccess
: public ScopedAccessBase<VideoDecodeImageRepresentation> {
public:
ScopedWriteAccess(base::PassKey<VideoDecodeImageRepresentation> pass_key,
VideoDecodeImageRepresentation* representation);
~ScopedWriteAccess();
#if BUILDFLAG(IS_WIN)
Microsoft::WRL::ComPtr<ID3D11Texture2D> GetD3D11Texture() const {
return representation()->GetD3D11Texture();
}
#endif // BUILDFLAG(IS_WIN)
};
VideoDecodeImageRepresentation(SharedImageManager* manager,
SharedImageBacking* backing,
MemoryTypeTracker* tracker);
~VideoDecodeImageRepresentation() override;
virtual std::unique_ptr<ScopedWriteAccess> BeginScopedWriteAccess();
protected:
#if BUILDFLAG(IS_WIN)
virtual Microsoft::WRL::ComPtr<ID3D11Texture2D> GetD3D11Texture() const = 0;
#endif // BUILDFLAG(IS_WIN)
virtual bool BeginWriteAccess() = 0;
virtual void EndWriteAccess() = 0;
};
} // namespace gpu
#endif // GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_SHARED_IMAGE_REPRESENTATION_H_