blob: 5fca8bd7d1a169750466c03c67462fbcc36049ac [file] [log] [blame]
// 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.
#include "gpu/command_buffer/service/shared_image_representation.h"
#include "base/strings/stringprintf.h"
#include "components/viz/common/resources/resource_format_utils.h"
#include "gpu/command_buffer/service/texture_manager.h"
#include "third_party/skia/include/core/SkPromiseImageTexture.h"
#include "third_party/skia/include/gpu/GrDirectContext.h"
#include "ui/gl/gl_fence.h"
#if defined(OS_ANDROID)
#include "base/android/scoped_hardware_buffer_fence_sync.h"
#endif
namespace gpu {
SharedImageRepresentation::SharedImageRepresentation(
SharedImageManager* manager,
SharedImageBacking* backing,
MemoryTypeTracker* owning_tracker)
: manager_(manager), backing_(backing), tracker_(owning_tracker) {
DCHECK(tracker_);
// TODO(hitawala): Rewrite the reference counting so that
// SharedImageRepresentation does not need manager and manager attaches to
// backing in Register().
if (manager_) {
backing_->AddRef(this);
}
}
SharedImageRepresentation::~SharedImageRepresentation() {
// CHECK here as we'll crash later anyway, and this makes it clearer what the
// error is.
CHECK(!has_scoped_access_) << "Destroying a SharedImageRepresentation with "
"outstanding Scoped*Access objects.";
if (manager_) {
manager_->OnRepresentationDestroyed(backing_->mailbox(), this);
}
}
std::unique_ptr<SharedImageRepresentationGLTexture::ScopedAccess>
SharedImageRepresentationGLTextureBase::BeginScopedAccess(
GLenum mode,
AllowUnclearedAccess allow_uncleared) {
if (allow_uncleared != AllowUnclearedAccess::kYes && !IsCleared()) {
LOG(ERROR) << "Attempt to access an uninitialized SharedImage";
return nullptr;
}
if (!BeginAccess(mode))
return nullptr;
UpdateClearedStateOnBeginAccess();
constexpr GLenum kReadAccess = 0x8AF6;
if (mode == kReadAccess)
backing()->OnReadSucceeded();
else
backing()->OnWriteSucceeded();
return std::make_unique<ScopedAccess>(
base::PassKey<SharedImageRepresentationGLTextureBase>(), this);
}
bool SharedImageRepresentationGLTextureBase::BeginAccess(GLenum mode) {
return true;
}
bool SharedImageRepresentationGLTextureBase::
SupportsMultipleConcurrentReadAccess() {
return false;
}
gpu::TextureBase* SharedImageRepresentationGLTexture::GetTextureBase() {
return GetTexture();
}
void SharedImageRepresentationGLTexture::UpdateClearedStateOnEndAccess() {
auto* texture = GetTexture();
// Operations on the gles2::Texture may have cleared or uncleared it. Make
// sure this state is reflected back in the SharedImage.
gfx::Rect cleared_rect = texture->GetLevelClearedRect(texture->target(), 0);
if (cleared_rect != ClearedRect())
SetClearedRect(cleared_rect);
}
void SharedImageRepresentationGLTexture::UpdateClearedStateOnBeginAccess() {
auto* texture = GetTexture();
// Operations outside of the gles2::Texture may have cleared or uncleared it.
// Make sure this state is reflected back in gles2::Texture.
gfx::Rect cleared_rect = ClearedRect();
if (cleared_rect != texture->GetLevelClearedRect(texture->target(), 0))
texture->SetLevelClearedRect(texture->target(), 0, cleared_rect);
}
gpu::TextureBase*
SharedImageRepresentationGLTexturePassthrough::GetTextureBase() {
return GetTexturePassthrough().get();
}
bool SharedImageRepresentationSkia::SupportsMultipleConcurrentReadAccess() {
return false;
}
SharedImageRepresentationSkia::ScopedWriteAccess::ScopedWriteAccess(
base::PassKey<SharedImageRepresentationSkia> /* pass_key */,
SharedImageRepresentationSkia* representation,
sk_sp<SkSurface> surface,
std::unique_ptr<GrBackendSurfaceMutableState> end_state)
: ScopedAccessBase(representation),
surface_(std::move(surface)),
end_state_(std::move(end_state)) {}
SharedImageRepresentationSkia::ScopedWriteAccess::ScopedWriteAccess(
base::PassKey<SharedImageRepresentationSkia> /* pass_key */,
SharedImageRepresentationSkia* representation,
sk_sp<SkPromiseImageTexture> promise_image_texture,
std::unique_ptr<GrBackendSurfaceMutableState> end_state)
: ScopedAccessBase(representation),
promise_image_texture_(std::move(promise_image_texture)),
end_state_(std::move(end_state)) {}
SharedImageRepresentationSkia::ScopedWriteAccess::~ScopedWriteAccess() {
representation()->EndWriteAccess(std::move(surface_));
}
std::unique_ptr<SharedImageRepresentationSkia::ScopedWriteAccess>
SharedImageRepresentationSkia::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) {
if (allow_uncleared != AllowUnclearedAccess::kYes && !IsCleared()) {
LOG(ERROR) << "Attempt to write to an uninitialized SharedImage";
return nullptr;
}
std::unique_ptr<GrBackendSurfaceMutableState> end_state;
if (use_sk_surface) {
sk_sp<SkSurface> surface =
BeginWriteAccess(final_msaa_count, surface_props, begin_semaphores,
end_semaphores, &end_state);
if (!surface) {
LOG(ERROR) << "Unable to initialize SkSurface";
return nullptr;
}
backing()->OnWriteSucceeded();
return std::make_unique<ScopedWriteAccess>(
base::PassKey<SharedImageRepresentationSkia>(), this,
std::move(surface), std::move(end_state));
}
sk_sp<SkPromiseImageTexture> promise_image_texture =
BeginWriteAccess(begin_semaphores, end_semaphores, &end_state);
if (!promise_image_texture) {
LOG(ERROR) << "Unable to initialize SkPromiseImageTexture";
return nullptr;
}
backing()->OnWriteSucceeded();
return std::make_unique<ScopedWriteAccess>(
base::PassKey<SharedImageRepresentationSkia>(), this,
std::move(promise_image_texture), std::move(end_state));
}
std::unique_ptr<SharedImageRepresentationSkia::ScopedWriteAccess>
SharedImageRepresentationSkia::BeginScopedWriteAccess(
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores,
AllowUnclearedAccess allow_uncleared,
bool use_sk_surface) {
return BeginScopedWriteAccess(
0 /* final_msaa_count */,
SkSurfaceProps(0 /* flags */, kUnknown_SkPixelGeometry), begin_semaphores,
end_semaphores, allow_uncleared, use_sk_surface);
}
SharedImageRepresentationSkia::ScopedReadAccess::ScopedReadAccess(
base::PassKey<SharedImageRepresentationSkia> /* pass_key */,
SharedImageRepresentationSkia* representation,
sk_sp<SkPromiseImageTexture> promise_image_texture,
std::unique_ptr<GrBackendSurfaceMutableState> end_state)
: ScopedAccessBase(representation),
promise_image_texture_(std::move(promise_image_texture)),
end_state_(std::move(end_state)) {}
SharedImageRepresentationSkia::ScopedReadAccess::~ScopedReadAccess() {
representation()->EndReadAccess();
}
sk_sp<SkImage> SharedImageRepresentationSkia::ScopedReadAccess::CreateSkImage(
GrDirectContext* context) const {
auto surface_origin = representation()->surface_origin();
auto color_type =
viz::ResourceFormatToClosestSkColorType(true, representation()->format());
auto alpha_type = representation()->alpha_type();
auto sk_color_space = representation()->color_space().ToSkColorSpace();
return SkImage::MakeFromTexture(
context, promise_image_texture_->backendTexture(), surface_origin,
color_type, alpha_type, sk_color_space);
}
std::unique_ptr<SharedImageRepresentationSkia::ScopedReadAccess>
SharedImageRepresentationSkia::BeginScopedReadAccess(
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores) {
if (!IsCleared()) {
auto cr = ClearedRect();
LOG(ERROR) << base::StringPrintf(
"Attempt to read from an uninitialized SharedImage. "
"Initialized region: (%d, %d, %d, %d) Size: (%d, %d)",
cr.x(), cr.y(), cr.width(), cr.height(), size().width(),
size().height());
return nullptr;
}
std::unique_ptr<GrBackendSurfaceMutableState> end_state;
sk_sp<SkPromiseImageTexture> promise_image_texture =
BeginReadAccess(begin_semaphores, end_semaphores, &end_state);
if (!promise_image_texture)
return nullptr;
backing()->OnReadSucceeded();
return std::make_unique<ScopedReadAccess>(
base::PassKey<SharedImageRepresentationSkia>(), this,
std::move(promise_image_texture), std::move(end_state));
}
sk_sp<SkSurface> SharedImageRepresentationSkia::BeginWriteAccess(
int final_msaa_count,
const SkSurfaceProps& surface_props,
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores,
std::unique_ptr<GrBackendSurfaceMutableState>* end_state) {
return BeginWriteAccess(final_msaa_count, surface_props, begin_semaphores,
end_semaphores);
}
sk_sp<SkSurface> SharedImageRepresentationSkia::BeginWriteAccess(
int final_msaa_count,
const SkSurfaceProps& surface_props,
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores) {
return nullptr;
}
sk_sp<SkPromiseImageTexture> SharedImageRepresentationSkia::BeginReadAccess(
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores,
std::unique_ptr<GrBackendSurfaceMutableState>* end_state) {
return BeginReadAccess(begin_semaphores, end_semaphores);
}
sk_sp<SkPromiseImageTexture> SharedImageRepresentationSkia::BeginReadAccess(
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores) {
return nullptr;
}
#if defined(OS_ANDROID)
AHardwareBuffer* SharedImageRepresentationOverlay::GetAHardwareBuffer() {
NOTREACHED();
return nullptr;
}
#endif
SharedImageRepresentationOverlay::ScopedReadAccess::ScopedReadAccess(
base::PassKey<SharedImageRepresentationOverlay> pass_key,
SharedImageRepresentationOverlay* representation,
gl::GLImage* gl_image,
std::vector<gfx::GpuFence> acquire_fences)
: ScopedAccessBase(representation),
gl_image_(gl_image),
acquire_fences_(std::move(acquire_fences)) {}
SharedImageRepresentationOverlay::ScopedReadAccess::~ScopedReadAccess() {
representation()->EndReadAccess(std::move(release_fence_));
}
std::unique_ptr<SharedImageRepresentationOverlay::ScopedReadAccess>
SharedImageRepresentationOverlay::BeginScopedReadAccess(bool needs_gl_image) {
if (!IsCleared()) {
LOG(ERROR) << "Attempt to read from an uninitialized SharedImage";
return nullptr;
}
std::vector<gfx::GpuFence> acquire_fences;
if (!BeginReadAccess(&acquire_fences))
return nullptr;
backing()->OnReadSucceeded();
return std::make_unique<ScopedReadAccess>(
base::PassKey<SharedImageRepresentationOverlay>(), this,
needs_gl_image ? GetGLImage() : nullptr, std::move(acquire_fences));
}
SharedImageRepresentationDawn::ScopedAccess::ScopedAccess(
base::PassKey<SharedImageRepresentationDawn> /* pass_key */,
SharedImageRepresentationDawn* representation,
WGPUTexture texture)
: ScopedAccessBase(representation), texture_(texture) {}
SharedImageRepresentationDawn::ScopedAccess::~ScopedAccess() {
representation()->EndAccess();
}
std::unique_ptr<SharedImageRepresentationDawn::ScopedAccess>
SharedImageRepresentationDawn::BeginScopedAccess(
WGPUTextureUsage usage,
AllowUnclearedAccess allow_uncleared) {
if (allow_uncleared != AllowUnclearedAccess::kYes && !IsCleared()) {
LOG(ERROR) << "Attempt to access an uninitialized SharedImage";
return nullptr;
}
WGPUTexture texture = BeginAccess(usage);
if (!texture)
return nullptr;
constexpr auto kWriteUsage =
WGPUTextureUsage_CopyDst | WGPUTextureUsage_RenderAttachment;
if (usage & kWriteUsage) {
backing()->OnWriteSucceeded();
} else {
backing()->OnReadSucceeded();
}
return std::make_unique<ScopedAccess>(
base::PassKey<SharedImageRepresentationDawn>(), this, texture);
}
SharedImageRepresentationFactoryRef::~SharedImageRepresentationFactoryRef() {
backing()->UnregisterImageFactory();
backing()->MarkForDestruction();
}
#if defined(OS_ANDROID)
std::unique_ptr<base::android::ScopedHardwareBufferFenceSync>
SharedImageRepresentationFactoryRef::GetAHardwareBuffer() {
return backing()->GetAHardwareBuffer();
}
#endif
SharedImageRepresentationVaapi::SharedImageRepresentationVaapi(
SharedImageManager* manager,
SharedImageBacking* backing,
MemoryTypeTracker* tracker,
VaapiDependencies* vaapi_deps)
: SharedImageRepresentation(manager, backing, tracker),
vaapi_deps_(vaapi_deps) {}
SharedImageRepresentationVaapi::~SharedImageRepresentationVaapi() = default;
SharedImageRepresentationVaapi::ScopedWriteAccess::ScopedWriteAccess(
base::PassKey<SharedImageRepresentationVaapi> /* pass_key */,
SharedImageRepresentationVaapi* representation)
: ScopedAccessBase(representation) {}
SharedImageRepresentationVaapi::ScopedWriteAccess::~ScopedWriteAccess() {
representation()->EndAccess();
}
const media::VASurface*
SharedImageRepresentationVaapi::ScopedWriteAccess::va_surface() {
return representation()->vaapi_deps_->GetVaSurface();
}
std::unique_ptr<SharedImageRepresentationVaapi::ScopedWriteAccess>
SharedImageRepresentationVaapi::BeginScopedWriteAccess() {
return std::make_unique<ScopedWriteAccess>(
base::PassKey<SharedImageRepresentationVaapi>(), this);
}
SharedImageRepresentationMemory::ScopedReadAccess::ScopedReadAccess(
base::PassKey<SharedImageRepresentationMemory> pass_key,
SharedImageRepresentationMemory* representation,
SkPixmap pixmap)
: ScopedAccessBase(representation), pixmap_(pixmap) {}
SharedImageRepresentationMemory::ScopedReadAccess::~ScopedReadAccess() =
default;
std::unique_ptr<SharedImageRepresentationMemory::ScopedReadAccess>
SharedImageRepresentationMemory::BeginScopedReadAccess() {
return std::make_unique<ScopedReadAccess>(
base::PassKey<SharedImageRepresentationMemory>(), this,
BeginReadAccess());
}
SharedImageRepresentationRaster::ScopedReadAccess::ScopedReadAccess(
base::PassKey<SharedImageRepresentationRaster> pass_key,
SharedImageRepresentationRaster* representation,
const cc::PaintOpBuffer* paint_op_buffer,
const absl::optional<SkColor>& clear_color)
: ScopedAccessBase(representation),
paint_op_buffer_(paint_op_buffer),
clear_color_(clear_color) {}
SharedImageRepresentationRaster::ScopedReadAccess::~ScopedReadAccess() {
representation()->EndReadAccess();
}
SharedImageRepresentationRaster::ScopedWriteAccess::ScopedWriteAccess(
base::PassKey<SharedImageRepresentationRaster> pass_key,
SharedImageRepresentationRaster* representation,
cc::PaintOpBuffer* paint_op_buffer)
: ScopedAccessBase(representation), paint_op_buffer_(paint_op_buffer) {}
SharedImageRepresentationRaster::ScopedWriteAccess::~ScopedWriteAccess() {
representation()->EndWriteAccess(std::move(callback_));
}
std::unique_ptr<SharedImageRepresentationRaster::ScopedReadAccess>
SharedImageRepresentationRaster::BeginScopedReadAccess() {
absl::optional<SkColor> clear_color;
auto* paint_op_buffer = BeginReadAccess(clear_color);
if (!paint_op_buffer)
return nullptr;
return std::make_unique<ScopedReadAccess>(
base::PassKey<SharedImageRepresentationRaster>(), this, paint_op_buffer,
clear_color);
}
std::unique_ptr<SharedImageRepresentationRaster::ScopedWriteAccess>
SharedImageRepresentationRaster::BeginScopedWriteAccess(
int final_msaa_count,
const SkSurfaceProps& surface_props,
const absl::optional<SkColor>& clear_color) {
return std::make_unique<ScopedWriteAccess>(
base::PassKey<SharedImageRepresentationRaster>(), this,
BeginWriteAccess(final_msaa_count, surface_props, clear_color));
}
} // namespace gpu