Expose ManagedBackendTexture from BackendTextureImageFactory.

Add helper to create self-managed BackendTexture-backed SkSurface for
tests using MBET.

GrGpu::createTestingOnlyBackendRenderTarget supports protected.

Make SkSurfaceCharacterization tests use self-managed SkSurface
factories and a use case of MakeFromBackendTextureAsRenderTarget is
removed.

Use self-managed BackendTexture-backed SkSurface factory in DM sinks and
in fm.

Bug: skia:9832

Change-Id: I0c1dc49697f8b3c942864e18b9112a3552f431ba
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/323559
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Brian Salomon 2020-10-08 16:00:14 -04:00 committed by Skia Commit-Bot
parent a96e080962
commit f9b0042423
26 changed files with 391 additions and 368 deletions

View File

@ -1606,6 +1606,8 @@ if (skia_enable_tools) {
"tools/gpu/FlushFinishTracker.h",
"tools/gpu/GrContextFactory.cpp",
"tools/gpu/GrTest.cpp",
"tools/gpu/ManagedBackendTexture.cpp",
"tools/gpu/ManagedBackendTexture.h",
"tools/gpu/MemoryCache.cpp",
"tools/gpu/MemoryCache.h",
"tools/gpu/ProxyUtils.cpp",

View File

@ -1468,9 +1468,7 @@ Result GPUSink::draw(const Src& src, SkBitmap* dst, SkWStream* dstStream, SkStri
return this->onDraw(src, dst, dstStream, log, fBaseContextOptions);
}
sk_sp<SkSurface> GPUSink::createDstSurface(GrDirectContext* context,
SkISize size,
GrBackendTexture* backendTexture) const {
sk_sp<SkSurface> GPUSink::createDstSurface(GrDirectContext* context, SkISize size) const {
sk_sp<SkSurface> surface;
SkImageInfo info = SkImageInfo::Make(size, fColorType, fAlphaType, fColorSpace);
@ -1483,21 +1481,25 @@ sk_sp<SkSurface> GPUSink::createDstSurface(GrDirectContext* context,
&props);
break;
case SkCommandLineConfigGpu::SurfType::kBackendTexture:
CreateBackendTexture(context, backendTexture, info.width(), info.height(),
info.colorType(), SkColors::kTransparent, GrMipmapped::kNo,
GrRenderable::kYes, GrProtected::kNo);
surface = SkSurface::MakeFromBackendTexture(context, *backendTexture,
kTopLeft_GrSurfaceOrigin, fSampleCount,
fColorType, info.refColorSpace(), &props);
surface = sk_gpu_test::MakeBackendTextureSurface(context,
info.dimensions(),
kTopLeft_GrSurfaceOrigin,
fSampleCount,
info.colorType(),
info.refColorSpace(),
GrMipmapped::kNo,
GrProtected::kNo,
&props);
break;
case SkCommandLineConfigGpu::SurfType::kBackendRenderTarget:
surface = MakeBackendRenderTargetSurface(context,
info.dimensions(),
fSampleCount,
kBottomLeft_GrSurfaceOrigin,
info.colorType(),
info.refColorSpace(),
&props);
surface = sk_gpu_test::MakeBackendRenderTargetSurface(context,
info.dimensions(),
kBottomLeft_GrSurfaceOrigin,
fSampleCount,
info.colorType(),
info.refColorSpace(),
GrProtected::kNo,
&props);
break;
}
@ -1536,8 +1538,7 @@ Result GPUSink::onDraw(const Src& src, SkBitmap* dst, SkWStream*, SkString* log,
return Result::Skip("Src too large to create a texture.\n");
}
GrBackendTexture backendTexture;
sk_sp<SkSurface> surface = this->createDstSurface(direct, src.size(), &backendTexture);
sk_sp<SkSurface> surface = this->createDstSurface(direct, src.size());
if (!surface) {
return Result::Fatal("Could not create a surface.");
}
@ -1563,12 +1564,7 @@ Result GPUSink::onDraw(const Src& src, SkBitmap* dst, SkWStream*, SkString* log,
} else if (FLAGS_releaseAndAbandonGpuContext) {
factory.releaseResourcesAndAbandonContexts();
}
if (!direct->abandoned()) {
surface.reset();
if (backendTexture.isValid()) {
direct->deleteBackendTexture(backendTexture);
}
}
if (grOptions.fPersistentCache) {
direct->storeVkPipelineCacheData();
}
@ -1743,8 +1739,7 @@ Result GPUOOPRSink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString* lo
SkASSERT(context->priv().getGpu());
GrBackendTexture backendTexture;
sk_sp<SkSurface> surface = this->createDstSurface(context, src.size(), &backendTexture);
sk_sp<SkSurface> surface = this->createDstSurface(context, src.size());
if (!surface) {
return Result::Fatal("Could not create a surface.");
}
@ -1764,11 +1759,6 @@ Result GPUOOPRSink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString* lo
return Result::Fatal("Could not readback from surface.");
}
surface.reset();
if (backendTexture.isValid()) {
context->deleteBackendTexture(backendTexture);
}
return Result::Ok();
}
@ -1918,8 +1908,7 @@ Result GPUDDLSink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString* log
// Make sure 'mainCtx' is current
mainTestCtx->makeCurrent();
GrBackendTexture backendTexture;
sk_sp<SkSurface> surface = this->createDstSurface(mainCtx, src.size(), &backendTexture);
sk_sp<SkSurface> surface = this->createDstSurface(mainCtx, src.size());
if (!surface) {
return Result::Fatal("Could not create a surface.");
}
@ -1949,11 +1938,6 @@ Result GPUDDLSink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString* log
return Result::Fatal("Could not readback from surface.");
}
surface.reset();
if (backendTexture.isValid()) {
mainCtx->deleteBackendTexture(backendTexture);
}
return Result::Ok();
}

View File

@ -407,7 +407,7 @@ public:
}
protected:
sk_sp<SkSurface> createDstSurface(GrDirectContext*, SkISize size, GrBackendTexture*) const;
sk_sp<SkSurface> createDstSurface(GrDirectContext*, SkISize size) const;
bool readBack(SkSurface*, SkBitmap* dst) const;
private:

View File

@ -673,9 +673,11 @@ public:
* buffer for resolving. If the color is non-null the backing store should be cleared to the
* passed in color.
*/
virtual GrBackendRenderTarget createTestingOnlyBackendRenderTarget(SkISize,
GrColorType,
int sampleCount = 1) = 0;
virtual GrBackendRenderTarget createTestingOnlyBackendRenderTarget(
SkISize dimensions,
GrColorType,
int sampleCount = 1,
GrProtected = GrProtected::kNo) = 0;
/**
* Deletes a GrBackendRenderTarget allocated with the above. Synchronization to make this safe

View File

@ -1259,7 +1259,8 @@ bool GrD3DGpu::isTestingOnlyBackendTexture(const GrBackendTexture& tex) const {
GrBackendRenderTarget GrD3DGpu::createTestingOnlyBackendRenderTarget(SkISize dimensions,
GrColorType colorType,
int sampleCnt) {
int sampleCnt,
GrProtected isProtected) {
this->handleDirtyContext();
if (dimensions.width() > this->caps()->maxRenderTargetSize() ||
@ -1272,7 +1273,7 @@ GrBackendRenderTarget GrD3DGpu::createTestingOnlyBackendRenderTarget(SkISize dim
GrD3DTextureResourceInfo info;
if (!this->createTextureResourceForBackendSurface(dxgiFormat, dimensions, GrTexturable::kNo,
GrRenderable::kYes, GrMipmapped::kNo,
sampleCnt, &info, GrProtected::kNo)) {
sampleCnt, &info, isProtected)) {
return {};
}

View File

@ -65,9 +65,10 @@ public:
#if GR_TEST_UTILS
bool isTestingOnlyBackendTexture(const GrBackendTexture&) const override;
GrBackendRenderTarget createTestingOnlyBackendRenderTarget(SkISize,
GrBackendRenderTarget createTestingOnlyBackendRenderTarget(SkISize dimensions,
GrColorType,
int sampleCnt) override;
int sampleCnt,
GrProtected) override;
void deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) override;
void testingOnly_flushGpuAndSync() override;

View File

@ -493,7 +493,8 @@ bool GrDawnGpu::isTestingOnlyBackendTexture(const GrBackendTexture& tex) const {
GrBackendRenderTarget GrDawnGpu::createTestingOnlyBackendRenderTarget(SkISize dimensions,
GrColorType colorType,
int sampleCnt) {
int sampleCnt,
GrProtected isProtected) {
if (dimensions.width() > this->caps()->maxTextureSize() ||
dimensions.height() > this->caps()->maxTextureSize()) {
return {};
@ -504,6 +505,10 @@ GrBackendRenderTarget GrDawnGpu::createTestingOnlyBackendRenderTarget(SkISize di
return {};
}
if (isProtected == GrProtected::kYes) {
return {};
}
wgpu::TextureFormat format;
if (!GrColorTypeToDawnFormat(colorType, &format)) {
return {};

View File

@ -53,9 +53,10 @@ public:
#if GR_TEST_UTILS
bool isTestingOnlyBackendTexture(const GrBackendTexture&) const override;
GrBackendRenderTarget createTestingOnlyBackendRenderTarget(SkISize,
GrBackendRenderTarget createTestingOnlyBackendRenderTarget(SkISize dimensions,
GrColorType,
int sampleCnt) override;
int sampleCnt,
GrProtected) override;
void deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) override;
void testingOnly_flushGpuAndSync() override;

View File

@ -3704,11 +3704,16 @@ bool GrGLGpu::isTestingOnlyBackendTexture(const GrBackendTexture& tex) const {
GrBackendRenderTarget GrGLGpu::createTestingOnlyBackendRenderTarget(SkISize dimensions,
GrColorType colorType,
int sampleCnt) {
int sampleCnt,
GrProtected isProtected) {
if (dimensions.width() > this->caps()->maxRenderTargetSize() ||
dimensions.height() > this->caps()->maxRenderTargetSize()) {
return {};
}
if (isProtected == GrProtected::kYes) {
return {};
}
this->handleDirtyContext();
auto format = this->glCaps().getFormatFromColorType(colorType);
sampleCnt = this->glCaps().getRenderTargetSampleCount(sampleCnt, format);

View File

@ -146,9 +146,10 @@ public:
#if GR_TEST_UTILS
bool isTestingOnlyBackendTexture(const GrBackendTexture&) const override;
GrBackendRenderTarget createTestingOnlyBackendRenderTarget(SkISize,
GrBackendRenderTarget createTestingOnlyBackendRenderTarget(SkISize dimensions,
GrColorType,
int sampleCnt) override;
int sampleCnt,
GrProtected) override;
void deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) override;
const GrGLContext* glContextForTesting() const override { return &this->glContext(); }

View File

@ -341,7 +341,8 @@ bool GrMockGpu::isTestingOnlyBackendTexture(const GrBackendTexture& tex) const {
GrBackendRenderTarget GrMockGpu::createTestingOnlyBackendRenderTarget(SkISize dimensions,
GrColorType colorType,
int sampleCnt) {
int sampleCnt,
GrProtected) {
GrMockRenderTargetInfo info(colorType, NextExternalRenderTargetID());
static constexpr int kStencilBits = 8;
return GrBackendRenderTarget(dimensions.width(), dimensions.height(), sampleCnt, kStencilBits,

View File

@ -179,7 +179,8 @@ private:
GrBackendRenderTarget createTestingOnlyBackendRenderTarget(SkISize dimensions,
GrColorType,
int sampleCnt) override;
int sampleCnt,
GrProtected) override;
void deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) override;
void testingOnly_flushGpuAndSync() override {}

View File

@ -65,9 +65,10 @@ public:
#if GR_TEST_UTILS
bool isTestingOnlyBackendTexture(const GrBackendTexture&) const override;
GrBackendRenderTarget createTestingOnlyBackendRenderTarget(SkISize,
GrBackendRenderTarget createTestingOnlyBackendRenderTarget(SkISize dimensions,
GrColorType,
int sampleCnt) override;
int sampleCnt,
GrProtected) override;
void deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) override;
void testingOnly_flushGpuAndSync() override;

View File

@ -1101,11 +1101,15 @@ bool GrMtlGpu::isTestingOnlyBackendTexture(const GrBackendTexture& tex) const {
GrBackendRenderTarget GrMtlGpu::createTestingOnlyBackendRenderTarget(SkISize dimensions,
GrColorType ct,
int sampleCnt) {
int sampleCnt,
GrProtected isProtected) {
if (dimensions.width() > this->caps()->maxRenderTargetSize() ||
dimensions.height() > this->caps()->maxRenderTargetSize()) {
return {};
}
if (isProtected == GrProtected::kYes) {
return {};
}
MTLPixelFormat format = this->mtlCaps().getFormatFromColorType(ct);
sampleCnt = this->mtlCaps().getRenderTargetSampleCount(sampleCnt, format);

View File

@ -2025,7 +2025,8 @@ bool GrVkGpu::isTestingOnlyBackendTexture(const GrBackendTexture& tex) const {
GrBackendRenderTarget GrVkGpu::createTestingOnlyBackendRenderTarget(SkISize dimensions,
GrColorType ct,
int sampleCnt) {
int sampleCnt,
GrProtected isProtected) {
this->handleDirtyContext();
if (dimensions.width() > this->caps()->maxRenderTargetSize() ||
@ -2038,7 +2039,7 @@ GrBackendRenderTarget GrVkGpu::createTestingOnlyBackendRenderTarget(SkISize dime
GrVkImageInfo info;
if (!this->createVkImageForBackendSurface(vkFormat, dimensions, sampleCnt, GrTexturable::kNo,
GrRenderable::kYes, GrMipmapped::kNo, &info,
GrProtected::kNo)) {
isProtected)) {
return {};
}
return GrBackendRenderTarget(dimensions.width(), dimensions.height(), 0, info);

View File

@ -94,9 +94,10 @@ public:
#if GR_TEST_UTILS
bool isTestingOnlyBackendTexture(const GrBackendTexture&) const override;
GrBackendRenderTarget createTestingOnlyBackendRenderTarget(SkISize,
GrBackendRenderTarget createTestingOnlyBackendRenderTarget(SkISize dimensions,
GrColorType,
int sampleCnt) override;
int sampleCnt,
GrProtected) override;
void deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) override;
void testingOnly_flushGpuAndSync() override;

View File

@ -124,8 +124,11 @@ DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(ES2BlendWithNoTexture, reporter, ctxInfo)
GrSurfaceOrigin origin = testCase.fOrigin;
// BGRA forces a framebuffer blit on ES2.
sk_sp<SkSurface> surface =
MakeBackendRenderTargetSurface(context, kDimensions, sampleCnt, origin, kColorType);
sk_sp<SkSurface> surface = sk_gpu_test::MakeBackendRenderTargetSurface(context,
kDimensions,
origin,
sampleCnt,
kColorType);
if (!surface && sampleCnt > 1) {
// Some platforms don't support MSAA.

View File

@ -42,6 +42,7 @@
#include "src/image/SkSurface_Gpu.h"
#include "tests/Test.h"
#include "tests/TestUtils.h"
#include "tools/gpu/BackendSurfaceFactory.h"
#include "tools/gpu/GrContextFactory.h"
#include <initializer_list>
@ -55,13 +56,11 @@
class SurfaceParameters {
public:
static const int kNumParams = 12;
static const int kSampleCount = 5;
static const int kMipMipCount = 8;
static const int kFBO0Count = 9;
static const int kProtectedCount = 11;
SurfaceParameters(GrRecordingContext* rContext)
: fBackend(rContext->backend())
, fCanBeProtected(false)
, fWidth(64)
, fHeight(64)
, fOrigin(kTopLeft_GrSurfaceOrigin)
@ -75,12 +74,17 @@ public:
, fIsProtected(GrProtected::kNo)
, fVkRTSupportsInputAttachment(false) {
#ifdef SK_VULKAN
if (GrBackendApi::kVulkan == rContext->backend()) {
const GrVkCaps* vkCaps = (const GrVkCaps*) rContext->priv().caps();
fIsProtected = GrProtected(vkCaps->supportsProtectedMemory());
if (rContext->backend() == GrBackendApi::kVulkan) {
auto vkCaps = static_cast<const GrVkCaps*>(rContext->priv().caps());
fCanBeProtected = vkCaps->supportsProtectedMemory();
if (fCanBeProtected) {
fIsProtected = GrProtected::kYes;
}
}
#endif
if (!rContext->priv().caps()->mipmapSupport()) {
fShouldCreateMipMaps = false;
}
}
int sampleCount() const { return fSampleCount; }
@ -88,7 +92,10 @@ public:
void setColorType(SkColorType ct) { fColorType = ct; }
SkColorType colorType() const { return fColorType; }
void setColorSpace(sk_sp<SkColorSpace> cs) { fColorSpace = std::move(cs); }
void setTextureable(bool isTextureable) { fIsTextureable = isTextureable; }
void disableTextureability() {
fIsTextureable = false;
fShouldCreateMipMaps = false;
}
void setShouldCreateMipMaps(bool shouldCreateMipMaps) {
fShouldCreateMipMaps = shouldCreateMipMaps;
}
@ -96,55 +103,66 @@ public:
fVkRTSupportsInputAttachment = inputSupport;
}
// Modify the SurfaceParameters in just one way
void modify(int i) {
// Modify the SurfaceParameters in just one way. Returns false if the requested modification had
// no effect.
bool modify(int i) {
bool changed = false;
auto set = [&changed](auto& var, auto value) {
if (var != value) {
changed = true;
}
var = value;
};
switch (i) {
case 0:
fWidth = 63;
set(fWidth, 63);
break;
case 1:
fHeight = 63;
set(fHeight, 63);
break;
case 2:
fOrigin = kBottomLeft_GrSurfaceOrigin;
set(fOrigin, kBottomLeft_GrSurfaceOrigin);
break;
case 3:
fColorType = kRGBA_F16_SkColorType;
set(fColorType, kRGBA_F16_SkColorType);
break;
case 4:
// This just needs to be a colorSpace different from that returned by MakeSRGB().
// In this case we just change the gamut.
fColorSpace = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kAdobeRGB);
set(fColorSpace, SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB,
SkNamedGamut::kAdobeRGB));
break;
case kSampleCount:
fSampleCount = 4;
case 5:
set(fSampleCount, 4);
break;
case 6:
fSurfaceProps = SkSurfaceProps(0x0, kRGB_H_SkPixelGeometry);
set(fSurfaceProps, SkSurfaceProps(0x0, kRGB_H_SkPixelGeometry));
break;
case 7:
fSurfaceProps = SkSurfaceProps(SkSurfaceProps::kUseDeviceIndependentFonts_Flag,
kUnknown_SkPixelGeometry);
set(fSurfaceProps, SkSurfaceProps(SkSurfaceProps::kUseDeviceIndependentFonts_Flag,
kUnknown_SkPixelGeometry));
break;
case 8:
fShouldCreateMipMaps = false;
set(fShouldCreateMipMaps, false);
break;
case 9:
if (GrBackendApi::kOpenGL == fBackend) {
fUsesGLFBO0 = true;
fShouldCreateMipMaps = false; // needs to changed in tandem w/ textureability
fIsTextureable = false;
set(fUsesGLFBO0, true);
set(fShouldCreateMipMaps, false); // needs to changed in tandem w/ textureability
set(fIsTextureable, false);
}
break;
case 10:
fShouldCreateMipMaps = false; // needs to changed in tandem w/ textureability
fIsTextureable = false;
set(fShouldCreateMipMaps, false); // needs to changed in tandem w/ textureability
set(fIsTextureable, false);
break;
case 11:
fIsProtected = GrProtected::kYes == fIsProtected ? GrProtected::kNo
: GrProtected::kYes;
if (fCanBeProtected) {
set(fIsProtected, GrProtected(!static_cast<bool>(fIsProtected)));
}
break;
}
return changed;
}
SkSurfaceCharacterization createCharacterization(GrDirectContext* dContext) const {
@ -188,13 +206,9 @@ public:
}
// Create the surface with the current set of parameters
sk_sp<SkSurface> make(GrDirectContext* dContext, GrBackendTexture* backend) const {
sk_sp<SkSurface> make(GrDirectContext* dContext) const {
const SkSurfaceCharacterization c = this->createCharacterization(dContext);
GrMipmapped mipmapped = !fIsTextureable
? GrMipmapped::kNo
: GrMipmapped(fShouldCreateMipMaps);
#ifdef SK_GL
if (fUsesGLFBO0) {
if (GrBackendApi::kOpenGL != dContext->backend()) {
@ -219,45 +233,50 @@ public:
return result;
}
#endif
CreateBackendTexture(dContext, backend, fWidth, fHeight, fColorType,
SkColors::kTransparent, mipmapped, GrRenderable::kYes, fIsProtected);
if (!backend->isValid()) {
return nullptr;
}
// Even if a characterization couldn't be constructed we want to soldier on to make
// sure that surface creation will/would've also failed
SkASSERT(!c.isValid() || c.isCompatible(*backend));
sk_sp<SkSurface> surface;
if (!fIsTextureable) {
// Create a surface w/ the current parameters but make it non-textureable
surface = SkSurface::MakeFromBackendTextureAsRenderTarget(
dContext, *backend, fOrigin, fSampleCount, fColorType,
fColorSpace, &fSurfaceProps);
if (fIsTextureable) {
surface = sk_gpu_test::MakeBackendTextureSurface(dContext,
{fWidth, fHeight},
fOrigin,
fSampleCount,
fColorType,
fColorSpace,
GrMipmapped(fShouldCreateMipMaps),
fIsProtected,
&fSurfaceProps);
} else {
surface = SkSurface::MakeFromBackendTexture(
dContext, *backend, fOrigin, fSampleCount, fColorType,
fColorSpace, &fSurfaceProps);
// Create a surface w/ the current parameters but make it non-textureable
SkASSERT(!fShouldCreateMipMaps);
surface = sk_gpu_test::MakeBackendRenderTargetSurface(dContext,
{fWidth, fHeight},
fOrigin,
fSampleCount,
fColorType,
fColorSpace,
fIsProtected,
&fSurfaceProps);
}
if (!surface) {
SkASSERT(!c.isValid());
this->cleanUpBackEnd(dContext, *backend);
return nullptr;
}
GrBackendTexture texture =
surface->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess);
if (texture.isValid()) {
SkASSERT(c.isCompatible(texture));
}
SkASSERT(c.isValid());
SkASSERT(surface->isCompatible(c));
return surface;
}
void cleanUpBackEnd(GrDirectContext* dContext, const GrBackendTexture& backend) const {
dContext->deleteBackendTexture(backend);
}
private:
GrBackendApi fBackend;
bool fCanBeProtected;
int fWidth;
int fHeight;
GrSurfaceOrigin fOrigin;
@ -276,43 +295,29 @@ private:
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLOperatorEqTest, reporter, ctxInfo) {
auto context = ctxInfo.directContext();
bool mipmapSupport = context->priv().caps()->mipmapSupport();
for (int i = 0; i < SurfaceParameters::kNumParams; ++i) {
for (int i = -1; i < SurfaceParameters::kNumParams; ++i) {
SurfaceParameters params1(context);
params1.modify(i);
bool didModify1 = i >= 0 && params1.modify(i);
SkSurfaceCharacterization char1 = params1.createCharacterization(context);
if (!char1.isValid()) {
continue; // can happen on some platforms (ChromeOS)
}
if (SurfaceParameters::kMipMipCount == i && !mipmapSupport) {
// If changing the mipmap setting won't result in a different surface characterization,
// skip this step.
continue;
}
for (int j = 0; j < SurfaceParameters::kNumParams; ++j) {
for (int j = -1; j < SurfaceParameters::kNumParams; ++j) {
SurfaceParameters params2(context);
params2.modify(j);
bool didModify2 = j >= 0 && params2.modify(j);
SkSurfaceCharacterization char2 = params2.createCharacterization(context);
if (!char2.isValid()) {
continue; // can happen on some platforms (ChromeOS)
}
if (SurfaceParameters::kMipMipCount == j && !mipmapSupport) {
// If changing the mipmap setting won't result in a different surface
// characterization, skip this step.
continue;
}
if (i == j) {
if (i == j || (!didModify1 && !didModify2)) {
REPORTER_ASSERT(reporter, char1 == char2);
} else {
REPORTER_ASSERT(reporter, char1 != char2);
}
}
}
@ -334,9 +339,6 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLOperatorEqTest, reporter, ctxInfo) {
////////////////////////////////////////////////////////////////////////////////
// This tests SkSurfaceCharacterization/SkSurface compatibility
void DDLSurfaceCharacterizationTestImpl(GrDirectContext* dContext, skiatest::Reporter* reporter) {
GrGpu* gpu = dContext->priv().getGpu();
const GrCaps* caps = dContext->priv().caps();
// Create a bitmap that we can readback into
SkImageInfo imageInfo = SkImageInfo::Make(64, 64, kRGBA_8888_SkColorType,
kPremul_SkAlphaType);
@ -355,88 +357,39 @@ void DDLSurfaceCharacterizationTestImpl(GrDirectContext* dContext, skiatest::Rep
SkAssertResult(ddl);
// The DDL should draw into an SkSurface created with the same parameters
GrBackendTexture backend;
sk_sp<SkSurface> s = params.make(dContext, &backend);
sk_sp<SkSurface> s = params.make(dContext);
if (!s) {
return;
}
REPORTER_ASSERT(reporter, s->draw(ddl));
s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
dContext->flushAndSubmit();
gpu->testingOnly_flushGpuAndSync();
s = nullptr;
params.cleanUpBackEnd(dContext, backend);
dContext->flush();
}
// Then, alter each parameter in turn and check that the DDL & surface are incompatible
for (int i = 0; i < SurfaceParameters::kNumParams; ++i) {
SurfaceParameters params(dContext);
params.modify(i);
if (SurfaceParameters::kProtectedCount == i) {
if (dContext->backend() != GrBackendApi::kVulkan) {
// Only the Vulkan backend respects the protected parameter
continue;
}
#ifdef SK_VULKAN
const GrVkCaps* vkCaps = (const GrVkCaps*) dContext->priv().caps();
// And, even then, only when it is a protected context
if (!vkCaps->supportsProtectedMemory()) {
continue;
}
#endif
if (!params.modify(i)) {
continue;
}
GrBackendTexture backend;
sk_sp<SkSurface> s = params.make(dContext, &backend);
sk_sp<SkSurface> s = params.make(dContext);
if (!s) {
continue;
}
if (SurfaceParameters::kSampleCount == i) {
int supportedSampleCount = caps->getRenderTargetSampleCount(
params.sampleCount(), backend.getBackendFormat());
if (1 == supportedSampleCount) {
// If changing the sample count won't result in a different
// surface characterization, skip this step
s = nullptr;
params.cleanUpBackEnd(dContext, backend);
continue;
}
}
if (SurfaceParameters::kMipMipCount == i && !caps->mipmapSupport()) {
// If changing the mipmap setting won't result in a different surface characterization,
// skip this step
s = nullptr;
params.cleanUpBackEnd(dContext, backend);
continue;
}
if (SurfaceParameters::kFBO0Count == i && dContext->backend() != GrBackendApi::kOpenGL) {
// FBO0 only affects the surface characterization when using OpenGL
s = nullptr;
params.cleanUpBackEnd(dContext, backend);
continue;
}
REPORTER_ASSERT(reporter, !s->draw(ddl),
"DDLSurfaceCharacterizationTest failed on parameter: %d\n", i);
dContext->flushAndSubmit();
gpu->testingOnly_flushGpuAndSync();
s = nullptr;
params.cleanUpBackEnd(dContext, backend);
dContext->flush();
}
// Next test the compatibility of resource cache parameters
{
const SurfaceParameters params(dContext);
GrBackendTexture backend;
sk_sp<SkSurface> s = params.make(dContext, &backend);
sk_sp<SkSurface> s = params.make(dContext);
size_t maxResourceBytes = dContext->getResourceCacheLimit();
@ -460,27 +413,19 @@ void DDLSurfaceCharacterizationTestImpl(GrDirectContext* dContext, skiatest::Rep
s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
#endif
dContext->flushAndSubmit();
gpu->testingOnly_flushGpuAndSync();
s = nullptr;
params.cleanUpBackEnd(dContext, backend);
dContext->flush();
}
// Test that the textureability of the DDL characterization can block a DDL draw
{
GrBackendTexture backend;
SurfaceParameters params(dContext);
params.setShouldCreateMipMaps(false);
params.setTextureable(false);
params.disableTextureability();
sk_sp<SkSurface> s = params.make(dContext, &backend);
sk_sp<SkSurface> s = params.make(dContext);
if (s) {
REPORTER_ASSERT(reporter, !s->draw(ddl)); // bc the DDL was made w/ textureability
dContext->flushAndSubmit();
gpu->testingOnly_flushGpuAndSync();
s = nullptr;
params.cleanUpBackEnd(dContext, backend);
dContext->flush();
}
}
@ -496,9 +441,8 @@ void DDLSurfaceCharacterizationTestImpl(GrDirectContext* dContext, skiatest::Rep
// Exercise the createResized method
{
SurfaceParameters params(dContext);
GrBackendTexture backend;
sk_sp<SkSurface> s = params.make(dContext, &backend);
sk_sp<SkSurface> s = params.make(dContext);
if (!s) {
return;
}
@ -519,17 +463,13 @@ void DDLSurfaceCharacterizationTestImpl(GrDirectContext* dContext, skiatest::Rep
REPORTER_ASSERT(reporter, char3.isValid());
REPORTER_ASSERT(reporter, 32 == char3.width());
REPORTER_ASSERT(reporter, 32 == char3.height());
s = nullptr;
params.cleanUpBackEnd(dContext, backend);
}
// Exercise the createColorSpace method
{
SurfaceParameters params(dContext);
GrBackendTexture backend;
sk_sp<SkSurface> s = params.make(dContext, &backend);
sk_sp<SkSurface> s = params.make(dContext);
if (!s) {
return;
}
@ -564,17 +504,13 @@ void DDLSurfaceCharacterizationTestImpl(GrDirectContext* dContext, skiatest::Rep
SkSurfaceCharacterization stillInvalid = invalid.createColorSpace(std::move(newCS));
REPORTER_ASSERT(reporter, !stillInvalid.isValid());
}
s = nullptr;
params.cleanUpBackEnd(dContext, backend);
}
// Exercise the createBackendFormat method
{
SurfaceParameters params(dContext);
GrBackendTexture backend;
sk_sp<SkSurface> s = params.make(dContext, &backend);
sk_sp<SkSurface> s = params.make(dContext);
if (!s) {
return;
}
@ -603,9 +539,6 @@ void DDLSurfaceCharacterizationTestImpl(GrDirectContext* dContext, skiatest::Rep
newBackendFormat);
REPORTER_ASSERT(reporter, !stillInvalid.isValid());
}
s = nullptr;
params.cleanUpBackEnd(dContext, backend);
}
// Exercise the createFBO0 method
@ -613,11 +546,9 @@ void DDLSurfaceCharacterizationTestImpl(GrDirectContext* dContext, skiatest::Rep
SurfaceParameters params(dContext);
// If the original characterization is textureable then we will fail trying to make an
// FBO0 characterization
params.setTextureable(false);
params.setShouldCreateMipMaps(false);
GrBackendTexture backend;
params.disableTextureability();
sk_sp<SkSurface> s = params.make(dContext, &backend);
sk_sp<SkSurface> s = params.make(dContext);
if (!s) {
return;
}
@ -640,9 +571,6 @@ void DDLSurfaceCharacterizationTestImpl(GrDirectContext* dContext, skiatest::Rep
SkSurfaceCharacterization stillInvalid = invalid.createFBO0(true);
REPORTER_ASSERT(reporter, !stillInvalid.isValid());
}
s = nullptr;
params.cleanUpBackEnd(dContext, backend);
}
}
@ -731,7 +659,6 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLSurfaceCharacterizationTest, reporter, ctx
// into a textureable destination.
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLNonTextureabilityTest, reporter, ctxInfo) {
auto context = ctxInfo.directContext();
GrGpu* gpu = context->priv().getGpu();
// Create a bitmap that we can readback into
SkImageInfo imageInfo = SkImageInfo::Make(64, 64, kRGBA_8888_SkColorType,
@ -746,8 +673,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLNonTextureabilityTest, reporter, ctxInfo)
// reusable DDLs, move this outside of the loop.
{
SurfaceParameters params(context);
params.setShouldCreateMipMaps(false);
params.setTextureable(false);
params.disableTextureability();
if (context->backend() == GrBackendApi::kVulkan) {
params.setVkRTInputAttachmentSupport(true);
}
@ -758,24 +684,22 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLNonTextureabilityTest, reporter, ctxInfo)
// Then verify it can draw into either flavor of destination
SurfaceParameters params(context);
params.setShouldCreateMipMaps(textureability);
params.setTextureable(textureability);
if (!textureability) {
params.disableTextureability();
}
if (context->backend() == GrBackendApi::kVulkan) {
params.setVkRTInputAttachmentSupport(true);
}
GrBackendTexture backend;
sk_sp<SkSurface> s = params.make(context, &backend);
sk_sp<SkSurface> s = params.make(context);
if (!s) {
continue;
}
REPORTER_ASSERT(reporter, s->draw(ddl));
s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
context->flushAndSubmit();
gpu->testingOnly_flushGpuAndSync();
s = nullptr;
params.cleanUpBackEnd(context, backend);
context->flush();
}
}
@ -787,33 +711,27 @@ static void test_make_render_target(skiatest::Reporter* reporter,
const SkSurfaceCharacterization c = params.createCharacterization(dContext);
if (!c.isValid()) {
GrBackendTexture backend;
sk_sp<SkSurface> tmp = params.make(dContext, &backend);
sk_sp<SkSurface> tmp = params.make(dContext);
// If we couldn't characterize the surface we shouldn't be able to create it either
REPORTER_ASSERT(reporter, !tmp);
if (tmp) {
tmp = nullptr;
params.cleanUpBackEnd(dContext, backend);
}
return;
}
}
const SkSurfaceCharacterization c = params.createCharacterization(dContext);
GrBackendTexture backend;
{
sk_sp<SkSurface> s = params.make(dContext, &backend);
sk_sp<SkSurface> s = params.make(dContext);
REPORTER_ASSERT(reporter, s);
if (!s) {
REPORTER_ASSERT(reporter, !c.isValid());
params.cleanUpBackEnd(dContext, backend);
return;
}
REPORTER_ASSERT(reporter, c.isValid());
REPORTER_ASSERT(reporter, c.isCompatible(backend));
GrBackendTexture backend = s->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess);
if (backend.isValid()) {
REPORTER_ASSERT(reporter, c.isCompatible(backend));
}
REPORTER_ASSERT(reporter, s->isCompatible(c));
// Note that we're leaving 'backend' live here
}
@ -824,8 +742,6 @@ static void test_make_render_target(skiatest::Reporter* reporter,
REPORTER_ASSERT(reporter, s);
REPORTER_ASSERT(reporter, s->isCompatible(c));
}
params.cleanUpBackEnd(dContext, backend);
}
////////////////////////////////////////////////////////////////////////////////
@ -833,34 +749,15 @@ static void test_make_render_target(skiatest::Reporter* reporter,
// In particular, the SkSurface, backendTexture and SkSurfaceCharacterization
// should always be compatible.
void DDLMakeRenderTargetTestImpl(GrDirectContext* dContext, skiatest::Reporter* reporter) {
for (int i = 0; i < SurfaceParameters::kNumParams; ++i) {
for (int i = -1; i < SurfaceParameters::kNumParams; ++i) {
if (SurfaceParameters::kFBO0Count == i) {
// MakeRenderTarget doesn't support FBO0
continue;
}
if (SurfaceParameters::kProtectedCount == i) {
if (dContext->backend() != GrBackendApi::kVulkan) {
// Only the Vulkan backend respects the protected parameter
continue;
}
#ifdef SK_VULKAN
const GrVkCaps* vkCaps = (const GrVkCaps*) dContext->priv().caps();
// And, even then, only when it is a protected context
if (!vkCaps->supportsProtectedMemory()) {
continue;
}
#endif
}
SurfaceParameters params(dContext);
params.modify(i);
if (!dContext->priv().caps()->mipmapSupport()) {
params.setShouldCreateMipMaps(false);
if (i >= 0 && !params.modify(i)) {
continue;
}
test_make_render_target(reporter, dContext, params);
@ -898,9 +795,8 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLWrapBackendTest, reporter, ctxInfo) {
}
SurfaceParameters params(dContext);
GrBackendTexture backend;
sk_sp<SkSurface> s = params.make(dContext, &backend);
sk_sp<SkSurface> s = params.make(dContext);
if (!s) {
dContext->deleteBackendTexture(backendTex);
return;
@ -917,7 +813,6 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLWrapBackendTest, reporter, ctxInfo) {
auto rContext = canvas->recordingContext();
if (!rContext) {
s = nullptr;
params.cleanUpBackEnd(dContext, backend);
dContext->deleteBackendTexture(backendTex);
return;
}
@ -931,9 +826,6 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLWrapBackendTest, reporter, ctxInfo) {
REPORTER_ASSERT(reporter, !image);
dContext->deleteBackendTexture(backendTex);
s = nullptr;
params.cleanUpBackEnd(dContext, backend);
}
static sk_sp<SkPromiseImageTexture> dummy_fulfill_proc(void*) {
@ -1277,10 +1169,6 @@ DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(DDLCompatibilityTest, reporter, ctxInfo) {
params.setColorType(colorType);
params.setColorSpace(nullptr);
if (!context->priv().caps()->mipmapSupport()) {
params.setShouldCreateMipMaps(false);
}
test_make_render_target(reporter, context, params);
}

View File

@ -159,8 +159,11 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrContext_colorTypeSupportedAsSurface, report
}
for (int sampleCnt : {1, 2}) {
auto surf = MakeBackendRenderTargetSurface(context, {16, 16}, sampleCnt,
kTopLeft_GrSurfaceOrigin, colorType);
auto surf = sk_gpu_test::MakeBackendRenderTargetSurface(context,
{16, 16},
kTopLeft_GrSurfaceOrigin,
sampleCnt,
colorType);
bool can = context->colorTypeSupportedAsSurface(colorType) &&
context->maxSurfaceSampleCountForColorType(colorType) >= sampleCnt;
if (!surf && can && colorType == kBGRA_8888_SkColorType && sampleCnt > 1 &&
@ -740,9 +743,14 @@ static sk_sp<SkSurface> create_gpu_surface_backend_render_target(GrDirectContext
const int kWidth = 10;
const int kHeight = 10;
auto surf = MakeBackendRenderTargetSurface(dContext, {kWidth, kHeight}, sampleCnt,
kTopLeft_GrSurfaceOrigin, kRGBA_8888_SkColorType,
nullptr, nullptr);
auto surf = sk_gpu_test::MakeBackendRenderTargetSurface(dContext,
{kWidth, kHeight},
kTopLeft_GrSurfaceOrigin,
sampleCnt,
kRGBA_8888_SkColorType,
nullptr,
GrProtected::kNo,
nullptr);
if (!surf) {
return nullptr;
}

View File

@ -461,8 +461,11 @@ static void test_write_pixels_non_texture(skiatest::Reporter* reporter,
}
for (auto& origin : { kTopLeft_GrSurfaceOrigin, kBottomLeft_GrSurfaceOrigin }) {
SkColorType colorType = kN32_SkColorType;
auto surface = MakeBackendRenderTargetSurface(dContext, {DEV_W, DEV_H}, sampleCnt, origin,
colorType);
auto surface = sk_gpu_test::MakeBackendRenderTargetSurface(dContext,
{DEV_W, DEV_H},
origin,
sampleCnt,
colorType);
if (surface) {
auto ii = SkImageInfo::MakeN32Premul(DEV_W, DEV_H);
test_write_pixels(reporter, surface.get(), ii);

View File

@ -311,8 +311,6 @@ static sk_sp<SkImage> draw_with_gpu(std::function<bool(SkCanvas*)> draw,
SkSurfaceProps props(flags, kRGB_H_SkPixelGeometry);
sk_sp<SkSurface> surface;
GrBackendTexture backendTexture;
GrBackendRenderTarget backendRT;
switch (surfaceType) {
case SurfaceType::kDefault:
@ -324,29 +322,26 @@ static sk_sp<SkImage> draw_with_gpu(std::function<bool(SkCanvas*)> draw,
break;
case SurfaceType::kBackendTexture:
backendTexture = context->createBackendTexture(info.width(),
info.height(),
info.colorType(),
GrMipmapped::kNo,
GrRenderable::kYes,
GrProtected::kNo);
surface = SkSurface::MakeFromBackendTexture(context,
backendTexture,
kTopLeft_GrSurfaceOrigin,
FLAGS_samples,
info.colorType(),
info.refColorSpace(),
&props);
surface = sk_gpu_test::MakeBackendTextureSurface(context,
info.dimensions(),
kTopLeft_GrSurfaceOrigin,
FLAGS_samples,
info.colorType(),
info.refColorSpace(),
GrMipmapped::kNo,
GrProtected::kNo,
&props);
break;
case SurfaceType::kBackendRenderTarget:
surface = MakeBackendRenderTargetSurface(context,
info.dimensions(),
FLAGS_samples,
kBottomLeft_GrSurfaceOrigin,
info.colorType(),
info.refColorSpace(),
&props);
surface = sk_gpu_test::MakeBackendRenderTargetSurface(context,
info.dimensions(),
kBottomLeft_GrSurfaceOrigin,
FLAGS_samples,
info.colorType(),
info.refColorSpace(),
GrProtected::kNo,
&props);
break;
}
@ -370,16 +365,6 @@ static sk_sp<SkImage> draw_with_gpu(std::function<bool(SkCanvas*)> draw,
factory->releaseResourcesAndAbandonContexts();
}
if (!context->abandoned()) {
surface.reset();
if (backendTexture.isValid()) {
context->deleteBackendTexture(backendTexture);
}
if (backendRT.isValid()) {
context->priv().getGpu()->deleteTestingOnlyBackendRenderTarget(backendRT);
}
}
return image;
}

View File

@ -11,13 +11,47 @@
#include "include/gpu/GrDirectContext.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrGpu.h"
#include "tools/gpu/ManagedBackendTexture.h"
namespace sk_gpu_test {
sk_sp<SkSurface> MakeBackendTextureSurface(GrDirectContext* context,
SkISize dimensions,
GrSurfaceOrigin origin,
int sampleCnt,
SkColorType colorType,
sk_sp<SkColorSpace> colorSpace,
GrMipmapped mipMapped,
GrProtected isProtected,
const SkSurfaceProps* props) {
auto mbet = ManagedBackendTexture::MakeWithoutData(context,
dimensions.fWidth,
dimensions.fHeight,
colorType,
mipMapped,
GrRenderable::kYes,
isProtected);
if (!mbet) {
return nullptr;
}
return SkSurface::MakeFromBackendTexture(context,
mbet->texture(),
origin,
sampleCnt,
colorType,
std::move(colorSpace),
props,
ManagedBackendTexture::ReleaseProc,
mbet->releaseContext());
}
sk_sp<SkSurface> MakeBackendRenderTargetSurface(GrDirectContext* context,
SkISize dimensions,
int sampleCnt,
GrSurfaceOrigin origin,
int sampleCnt,
SkColorType colorType,
sk_sp<SkColorSpace> colorSpace,
GrProtected isProtected,
const SkSurfaceProps* props) {
auto ct = SkColorTypeToGrColorType(colorType);
@ -27,7 +61,7 @@ sk_sp<SkSurface> MakeBackendRenderTargetSurface(GrDirectContext* context,
};
auto bert = context->priv().getGpu()->createTestingOnlyBackendRenderTarget(
dimensions, ct, sampleCnt);
dimensions, ct, sampleCnt, isProtected);
auto rc = new ReleaseContext{context, bert};
SkASSERT(!bert.isValid() || bert.sampleCnt() >= sampleCnt);
@ -42,3 +76,5 @@ sk_sp<SkSurface> MakeBackendRenderTargetSurface(GrDirectContext* context,
return SkSurface::MakeFromBackendRenderTarget(
context, bert, origin, colorType, std::move(colorSpace), props, proc, rc);
}
} // namespace sk_gpu_test

View File

@ -17,13 +17,27 @@ class GrDirectContext;
class SkSurface;
class SkSurfaceProps;
namespace sk_gpu_test {
sk_sp<SkSurface> MakeBackendTextureSurface(GrDirectContext*,
SkISize,
GrSurfaceOrigin,
int sampleCnt,
SkColorType,
sk_sp<SkColorSpace> = nullptr,
GrMipmapped = GrMipmapped::kNo,
GrProtected = GrProtected::kNo,
const SkSurfaceProps* = nullptr);
/** Creates an SkSurface backed by a non-textureable render target. */
sk_sp<SkSurface> MakeBackendRenderTargetSurface(GrDirectContext*,
SkISize,
int sampleCnt,
GrSurfaceOrigin,
int sampleCnt,
SkColorType,
sk_sp<SkColorSpace> = nullptr,
GrProtected = GrProtected::kNo,
const SkSurfaceProps* = nullptr);
} // namespace sk_gpu_test
#endif

View File

@ -12,41 +12,7 @@
#include "include/gpu/GrBackendSurface.h"
#include "include/gpu/GrDirectContext.h"
#include "src/core/SkAutoPixmapStorage.h"
namespace {
class ManagedBackendTexture : public SkNVRefCnt<ManagedBackendTexture> {
public:
~ManagedBackendTexture() {
if (fDContext && fTexture.isValid()) {
fDContext->submit(true);
fDContext->deleteBackendTexture(fTexture);
}
}
static void Release(void* context) { static_cast<ManagedBackendTexture*>(context)->unref(); }
template <typename... Args>
static sk_sp<ManagedBackendTexture> Make(GrDirectContext* dContext, Args&&... args) {
sk_sp<ManagedBackendTexture> mbet(new ManagedBackendTexture);
mbet->fDContext = dContext;
mbet->fTexture = dContext->createBackendTexture(std::forward<Args>(args)..., Release,
mbet->refAndPassAsContext());
return mbet;
}
const GrBackendTexture& texture() { return fTexture; }
void* refAndPassAsContext() {
this->ref();
return static_cast<void*>(this);
}
private:
ManagedBackendTexture() = default;
GrDirectContext* fDContext = nullptr;
GrBackendTexture fTexture;
};
} // namespace
#include "tools/gpu/ManagedBackendTexture.h"
namespace sk_gpu_test {
sk_sp<SkImage> MakeBackendTextureImage(GrDirectContext* dContext,
@ -64,14 +30,14 @@ sk_sp<SkImage> MakeBackendTextureImage(GrDirectContext* dContext,
}
src = &temp;
}
auto mbet = ManagedBackendTexture::Make(dContext, src, 1, renderable, GrProtected::kNo);
auto mbet = ManagedBackendTexture::MakeWithData(dContext, src, 1, renderable, GrProtected::kNo);
return SkImage::MakeFromTexture(dContext,
mbet->texture(),
origin,
src->colorType(),
src->alphaType(),
src->refColorSpace(),
ManagedBackendTexture::Release,
mbet->refAndPassAsContext());
ManagedBackendTexture::ReleaseProc,
mbet->releaseContext());
}
} // namespace sk_gpu_test

View File

@ -0,0 +1,27 @@
/*
* 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"
namespace sk_gpu_test {
void ManagedBackendTexture::ReleaseProc(void* context) {
static_cast<ManagedBackendTexture*>(context)->unref();
}
ManagedBackendTexture::~ManagedBackendTexture() {
if (fDContext && fTexture.isValid()) {
fDContext->deleteBackendTexture(fTexture);
}
}
void* ManagedBackendTexture::releaseContext() {
this->ref();
return static_cast<void*>(this);
}
} // namespace sk_gpu_test

View File

@ -0,0 +1,82 @@
/*
* Copyright 2020 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef ManagedBackendTexture_DEFINED
#define ManagedBackendTexture_DEFINED
#include "include/core/SkRefCnt.h"
#include "include/gpu/GrDirectContext.h"
namespace sk_gpu_test {
class ManagedBackendTexture : public SkNVRefCnt<ManagedBackendTexture> {
public:
/**
* Make a managed backend texture with initial pixmap/color data. The 'Args' are any valid set
* of arguments to GrDirectContext::createBackendTexture that takes data but with the release
* proc/context omitted as the ManagedBackendTexture will provide them.
*/
template <typename... Args>
static sk_sp<ManagedBackendTexture> MakeWithData(GrDirectContext*, Args&&...);
/**
* Make a managed backend texture without initial data. The 'Args' are any valid set of
* arguments to GrDirectContext::createBackendTexture that does not take data. Because our
* createBackendTexture methods that *do* take data also use default args for the proc/context
* this can be used to make a texture with data but then the MBET won't be able to ensure that
* the upload has completed before the texture is deleted. Use the WithData variant instead to
* avoid this issue.
*/
template <typename... Args>
static sk_sp<ManagedBackendTexture> MakeWithoutData(GrDirectContext*, Args&&...);
/** GrGpuFinishedProc or image/surface release proc. */
static void ReleaseProc(void* context);
~ManagedBackendTexture();
/**
* The context to use with ReleaseProc. This adds a ref so it *must* be balanced by a call to
* ReleaseProc.
*/
void* releaseContext();
const GrBackendTexture& texture() { return fTexture; }
private:
ManagedBackendTexture() = default;
ManagedBackendTexture(const ManagedBackendTexture&) = delete;
ManagedBackendTexture(ManagedBackendTexture&&) = delete;
GrDirectContext* fDContext = nullptr;
GrBackendTexture fTexture;
};
template <typename... Args>
inline sk_sp<ManagedBackendTexture> ManagedBackendTexture::MakeWithData(GrDirectContext* dContext,
Args&&... args) {
sk_sp<ManagedBackendTexture> mbet(new ManagedBackendTexture);
mbet->fDContext = dContext;
mbet->fTexture = dContext->createBackendTexture(std::forward<Args>(args)...,
ReleaseProc,
mbet->releaseContext());
return mbet;
}
template <typename... Args>
inline sk_sp<ManagedBackendTexture> ManagedBackendTexture::MakeWithoutData(
GrDirectContext* dContext,
Args&&... args) {
sk_sp<ManagedBackendTexture> mbet(new ManagedBackendTexture);
mbet->fDContext = dContext;
mbet->fTexture = dContext->createBackendTexture(std::forward<Args>(args)...);
return mbet;
}
} // namespace sk_gpu_test
#endif