blob: 01c3309c1d1106ec7f26d809b2b20171f8175ca5 [file] [log] [blame]
/*
* Copyright 2020 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "tools/gpu/ManagedBackendTexture.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkImageInfo.h"
#include "src/core/SkMipmap.h"
#include "src/gpu/RefCntedCallback.h"
#ifdef SK_GANESH
#include "include/private/gpu/ganesh/GrTypesPriv.h"
#endif
#ifdef SK_GRAPHITE
#include "include/gpu/graphite/Recorder.h"
#include "src/gpu/graphite/Caps.h"
#endif
using Mipmapped = skgpu::Mipmapped;
using Protected = skgpu::Protected;
using Renderable = skgpu::Renderable;
#ifdef SK_GANESH
namespace {
struct Context {
GrGpuFinishedProc fWrappedProc = nullptr;
GrGpuFinishedContext fWrappedContext = nullptr;
sk_sp<sk_gpu_test::ManagedBackendTexture> fMBETs[SkYUVAInfo::kMaxPlanes];
};
} // anonymous namespace
namespace sk_gpu_test {
void ManagedBackendTexture::ReleaseProc(void* ctx) {
std::unique_ptr<Context> context(static_cast<Context*>(ctx));
if (context->fWrappedProc) {
context->fWrappedProc(context->fWrappedContext);
}
}
ManagedBackendTexture::~ManagedBackendTexture() {
if (fDContext && fTexture.isValid()) {
fDContext->deleteBackendTexture(fTexture);
}
}
void* ManagedBackendTexture::releaseContext(GrGpuFinishedProc wrappedProc,
GrGpuFinishedContext wrappedCtx) const {
// Make sure we don't get a wrapped ctx without a wrapped proc
SkASSERT(!wrappedCtx || wrappedProc);
return new Context{wrappedProc, wrappedCtx, {sk_ref_sp(this)}};
}
void* ManagedBackendTexture::MakeYUVAReleaseContext(
const sk_sp<ManagedBackendTexture> mbets[SkYUVAInfo::kMaxPlanes]) {
auto context = new Context;
for (int i = 0; i < SkYUVAInfo::kMaxPlanes; ++i) {
context->fMBETs[i] = mbets[i];
}
return context;
}
sk_sp<skgpu::RefCntedCallback> ManagedBackendTexture::refCountedCallback() const {
return skgpu::RefCntedCallback::Make(ReleaseProc, this->releaseContext());
}
void ManagedBackendTexture::wasAdopted() { fTexture = {}; }
sk_sp<ManagedBackendTexture> ManagedBackendTexture::MakeFromInfo(GrDirectContext* dContext,
const SkImageInfo& ii,
Mipmapped mipmapped,
Renderable renderable,
Protected isProtected) {
return MakeWithoutData(dContext,
ii.width(),
ii.height(),
ii.colorType(),
mipmapped,
renderable,
isProtected);
}
sk_sp<ManagedBackendTexture> ManagedBackendTexture::MakeFromBitmap(GrDirectContext* dContext,
const SkBitmap& src,
Mipmapped mipmapped,
Renderable renderable,
Protected isProtected) {
SkPixmap srcPixmap;
if (!src.peekPixels(&srcPixmap)) {
return nullptr;
}
return MakeFromPixmap(dContext, srcPixmap, mipmapped, renderable, isProtected);
}
sk_sp<ManagedBackendTexture> ManagedBackendTexture::MakeFromPixmap(GrDirectContext* dContext,
const SkPixmap& src,
Mipmapped mipmapped,
Renderable renderable,
Protected isProtected) {
std::vector<SkPixmap> levels({src});
std::unique_ptr<SkMipmap> mm;
if (mipmapped == Mipmapped::kYes) {
mm.reset(SkMipmap::Build(src, nullptr));
if (!mm) {
return nullptr;
}
for (int i = 0; i < mm->countLevels(); ++i) {
SkMipmap::Level level;
SkAssertResult(mm->getLevel(i, &level));
levels.push_back(level.fPixmap);
}
}
return MakeWithData(dContext,
levels.data(),
static_cast<int>(levels.size()),
kTopLeft_GrSurfaceOrigin,
renderable,
isProtected);
}
} // namespace sk_gpu_test
#endif // SK_GANESH
#ifdef SK_GRAPHITE
using Recorder = skgpu::graphite::Recorder;
namespace {
struct MBETContext {
MBETContext(const sk_sp<sk_gpu_test::ManagedGraphiteTexture>& tex)
: fMBETs{tex, nullptr, nullptr, nullptr} {}
MBETContext(const sk_sp<sk_gpu_test::ManagedGraphiteTexture> mbets[SkYUVAInfo::kMaxPlanes])
: fMBETs{mbets[0], mbets[1], mbets[2], mbets[3]} {}
sk_sp<sk_gpu_test::ManagedGraphiteTexture> fMBETs[SkYUVAInfo::kMaxPlanes];
};
} // anonymous namespace
namespace sk_gpu_test {
void ManagedGraphiteTexture::ReleaseProc(void* ctx) {
std::unique_ptr<MBETContext> context(static_cast<MBETContext*>(ctx));
}
void ManagedGraphiteTexture::FinishedProc(void* ctx, skgpu::CallbackResult) {
std::unique_ptr<MBETContext> context(static_cast<MBETContext*>(ctx));
}
void ManagedGraphiteTexture::ImageReleaseProc(void* ctx) {
std::unique_ptr<MBETContext> context(static_cast<MBETContext*>(ctx));
}
ManagedGraphiteTexture::~ManagedGraphiteTexture() {
if (fContext && fTexture.isValid()) {
fContext->deleteBackendTexture(fTexture);
}
}
void* ManagedGraphiteTexture::releaseContext() const {
return new MBETContext{{sk_ref_sp(this)}};
}
void* ManagedGraphiteTexture::MakeYUVAReleaseContext(
const sk_sp<ManagedGraphiteTexture> mbets[SkYUVAInfo::kMaxPlanes]) {
return new MBETContext(mbets);
}
sk_sp<skgpu::RefCntedCallback> ManagedGraphiteTexture::refCountedCallback() const {
return skgpu::RefCntedCallback::Make(FinishedProc, this->releaseContext());
}
sk_sp<ManagedGraphiteTexture> ManagedGraphiteTexture::MakeUnInit(Recorder* recorder,
const SkImageInfo& ii,
Mipmapped mipmapped,
Renderable renderable,
Protected isProtected) {
sk_sp<ManagedGraphiteTexture> mbet(new ManagedGraphiteTexture);
mbet->fContext = recorder->priv().context();
const skgpu::graphite::Caps* caps = recorder->priv().caps();
skgpu::graphite::TextureInfo info = caps->getDefaultSampledTextureInfo(ii.colorType(),
mipmapped,
isProtected,
renderable);
mbet->fTexture = recorder->createBackendTexture(ii.dimensions(), info);
if (!mbet->fTexture.isValid()) {
return nullptr;
}
recorder->addFinishInfo({mbet->releaseContext(), FinishedProc});
return mbet;
}
sk_sp<ManagedGraphiteTexture> ManagedGraphiteTexture::MakeFromPixmap(Recorder* recorder,
const SkPixmap& src,
Mipmapped mipmapped,
Renderable renderable,
Protected isProtected) {
sk_sp<ManagedGraphiteTexture> mbet = MakeUnInit(recorder, src.info(), mipmapped, renderable,
isProtected);
if (!mbet) {
return nullptr;
}
std::vector<SkPixmap> levels({src});
std::unique_ptr<SkMipmap> mm;
if (mipmapped == Mipmapped::kYes) {
mm.reset(SkMipmap::Build(src, nullptr));
if (!mm) {
return nullptr;
}
for (int i = 0; i < mm->countLevels(); ++i) {
SkMipmap::Level level;
SkAssertResult(mm->getLevel(i, &level));
levels.push_back(level.fPixmap);
}
}
if (!recorder->updateBackendTexture(mbet->fTexture,
levels.data(),
static_cast<int>(levels.size()))) {
return nullptr;
}
return mbet;
}
sk_sp<ManagedGraphiteTexture> ManagedGraphiteTexture::MakeMipmappedFromPixmaps(
Recorder* recorder,
SkSpan<const SkPixmap> levels,
skgpu::Renderable renderable,
skgpu::Protected isProtected) {
if (levels.empty()) {
return nullptr;
}
sk_sp<ManagedGraphiteTexture> mbet = MakeUnInit(recorder,
levels[0].info(),
Mipmapped::kYes,
renderable,
isProtected);
if (!recorder->updateBackendTexture(mbet->fTexture,
levels.data(),
static_cast<int>(levels.size()))) {
return nullptr;
}
return mbet;
}
sk_sp<ManagedGraphiteTexture> ManagedGraphiteTexture::MakeFromCompressedData(
Recorder* recorder,
SkISize dimensions,
SkTextureCompressionType compression,
sk_sp<SkData> src,
skgpu::Mipmapped mipmapped,
skgpu::Protected isProtected) {
sk_sp<ManagedGraphiteTexture> mbet(new ManagedGraphiteTexture);
mbet->fContext = recorder->priv().context();
const skgpu::graphite::Caps* caps = recorder->priv().caps();
skgpu::graphite::TextureInfo info = caps->getDefaultCompressedTextureInfo(compression,
mipmapped,
isProtected);
mbet->fTexture = recorder->createBackendTexture(dimensions, info);
if (!mbet->fTexture.isValid()) {
return nullptr;
}
recorder->addFinishInfo({mbet->releaseContext(), FinishedProc});
if (!recorder->updateCompressedBackendTexture(mbet->fTexture,
src->data(),
src->size())) {
return nullptr;
}
return mbet;
}
} // namespace sk_gpu_test
#endif // SK_GRAPHITE