Add new GrContext queries for imagability, surfacability, and max sample count of color types

Bug: skia:7538
Change-Id: I235fc1aa947ba57faa7aef5e7e7ce9241b315fff
Reviewed-on: https://skia-review.googlesource.com/99704
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
This commit is contained in:
Brian Salomon 2018-02-01 18:02:35 -05:00 committed by Skia Commit-Bot
parent e45d32abe1
commit 85ae7159c9
7 changed files with 191 additions and 7 deletions

View File

@ -216,6 +216,26 @@ public:
/** Access the context capabilities */ /** Access the context capabilities */
const GrCaps* caps() const { return fCaps.get(); } const GrCaps* caps() const { return fCaps.get(); }
/**
* Can a SkImage be created with the given color type.
*/
bool colorTypeSupportedAsImage(SkColorType) const;
/**
* Can a SkSurface be created with the given color type. To check whether MSAA is supported
* use maxSurfaceSampleCountForColorType().
*/
bool colorTypeSupportedAsSurface(SkColorType colorType) const {
return this->maxSurfaceSampleCountForColorType(colorType) > 0;
}
/**
* Gets the maximum supported sample count for a color type. 1 is returned if only non-MSAA
* rendering is supported for the color type. 0 is returned if rendering to this color type
* is not supported at all.
*/
int maxSurfaceSampleCountForColorType(SkColorType) const;
/* /*
* Create a new render target context backed by a deferred-style * Create a new render target context backed by a deferred-style
* GrRenderTargetProxy. We guarantee that "asTextureProxy" will succeed for * GrRenderTargetProxy. We guarantee that "asTextureProxy" will succeed for

View File

@ -420,6 +420,18 @@ size_t GrContext::getResourceCachePurgeableBytes() const {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool GrContext::colorTypeSupportedAsImage(SkColorType colorType) const {
GrPixelConfig config = SkImageInfo2GrPixelConfig(colorType, nullptr, *this->caps());
return this->caps()->isConfigTexturable(config);
}
int GrContext::maxSurfaceSampleCountForColorType(SkColorType colorType) const {
GrPixelConfig config = SkImageInfo2GrPixelConfig(colorType, nullptr, *this->caps());
return this->caps()->maxRenderTargetSampleCount(config);
}
////////////////////////////////////////////////////////////////////////////////
void GrContext::TextBlobCacheOverBudgetCB(void* data) { void GrContext::TextBlobCacheOverBudgetCB(void* data) {
SkASSERT(data); SkASSERT(data);
// TextBlobs are drawn at the SkGpuDevice level, therefore they cannot rely on // TextBlobs are drawn at the SkGpuDevice level, therefore they cannot rely on

View File

@ -455,6 +455,10 @@ public:
/** Creates a texture directly in the backend API without wrapping it in a GrTexture. This is /** Creates a texture directly in the backend API without wrapping it in a GrTexture. This is
only to be used for testing (particularly for testing the methods that import an externally only to be used for testing (particularly for testing the methods that import an externally
created texture into Skia. Must be matched with a call to deleteTestingOnlyTexture(). */ created texture into Skia. Must be matched with a call to deleteTestingOnlyTexture(). */
GrBackendTexture createTestingOnlyBackendTexture(void* pixels, int w, int h, SkColorType,
bool isRenderTarget, GrMipMapped);
/** Older version based on GrPixelConfig. Currently the preferred one above devolves to this. */
virtual GrBackendTexture createTestingOnlyBackendTexture( virtual GrBackendTexture createTestingOnlyBackendTexture(
void* pixels, int w, int h, void* pixels, int w, int h,
GrPixelConfig config, GrPixelConfig config,

View File

@ -334,7 +334,9 @@ bool validate_backend_texture(GrContext* ctx, const GrBackendTexture& tex, GrPix
return false; return false;
} }
if (ctx->caps()->getRenderTargetSampleCount(sampleCnt, *config) != sampleCnt) { // We don't require that the client gave us an exact valid sample cnt. However, it must be
// less than the max supported sample count and 1 if MSAA is unsupported for the color type.
if (!ctx->caps()->getRenderTargetSampleCount(sampleCnt, *config)) {
return false; return false;
} }

View File

@ -38,6 +38,7 @@
#include "GrResourceCache.h" #include "GrResourceCache.h"
#include "GrTest.h" #include "GrTest.h"
#include "GrTexture.h" #include "GrTexture.h"
#include "SkGr.h"
#endif #endif
using namespace sk_gpu_test; using namespace sk_gpu_test;
@ -486,6 +487,29 @@ DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SkImage_drawAbandonedGpuImage, reporter, c
surface->getCanvas()->drawImage(image, 0, 0); surface->getCanvas()->drawImage(image, 0, 0);
} }
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrContext_colorTypeSupportedAsImage, reporter, ctxInfo) {
for (int ct = 0; ct < kLastEnum_SkColorType; ++ct) {
static constexpr int kSize = 10;
SkColorType colorType = static_cast<SkColorType>(ct);
bool can = ctxInfo.grContext()->colorTypeSupportedAsImage(colorType);
auto* gpu = ctxInfo.grContext()->contextPriv().getGpu();
GrBackendTexture backendTex = gpu->createTestingOnlyBackendTexture(
nullptr, kSize, kSize, colorType, false, GrMipMapped::kNo);
auto img =
SkImage::MakeFromTexture(ctxInfo.grContext(), backendTex, kTopLeft_GrSurfaceOrigin,
colorType, kOpaque_SkAlphaType, nullptr);
REPORTER_ASSERT(reporter, can == SkToBool(img),
"%d, colorTypeSupportedAsImage:%d, actual:%d, ct:%d", can, SkToBool(img),
colorType);
img.reset();
ctxInfo.grContext()->flush();
if (backendTex.isValid()) {
gpu->deleteTestingOnlyBackendTexture(&backendTex);
}
}
}
#endif #endif
class EmptyGenerator : public SkImageGenerator { class EmptyGenerator : public SkImageGenerator {

View File

@ -19,13 +19,17 @@
#include "Test.h" #include "Test.h"
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
#include <vector>
#include "GrContext.h" #include "GrContext.h"
#include "GrContextPriv.h" #include "GrContextPriv.h"
#include "GrRenderTargetContext.h"
#include "GrGpu.h" #include "GrGpu.h"
#include "GrGpuResourcePriv.h"
#include "GrRenderTargetContext.h"
#include "GrResourceProvider.h" #include "GrResourceProvider.h"
#include "GrTest.h" #include "GrTest.h"
#include <vector> #include "SkGpuDevice.h"
#include "SkImage_Gpu.h"
#include "SkSurface_Gpu.h"
#endif #endif
#include <initializer_list> #include <initializer_list>
@ -88,6 +92,121 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceEmpty_Gpu, reporter, ctxInfo) {
} }
#endif #endif
#if SK_SUPPORT_GPU
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrContext_colorTypeSupportedAsSurface, reporter, ctxInfo) {
for (int ct = 0; ct < kLastEnum_SkColorType; ++ct) {
static constexpr int kSize = 10;
SkColorType colorType = static_cast<SkColorType>(ct);
auto info = SkImageInfo::Make(kSize, kSize, colorType, kOpaque_SkAlphaType, nullptr);
bool can = ctxInfo.grContext()->colorTypeSupportedAsSurface(colorType);
auto surf = SkSurface::MakeRenderTarget(ctxInfo.grContext(), SkBudgeted::kYes, info, 1,
nullptr);
REPORTER_ASSERT(reporter, can == SkToBool(surf), "ct: %d, can: %d, surf: %d",
colorType, can, SkToBool(surf));
auto* gpu = ctxInfo.grContext()->contextPriv().getGpu();
GrBackendTexture backendTex = gpu->createTestingOnlyBackendTexture(
nullptr, kSize, kSize, colorType, true, GrMipMapped::kNo);
surf = SkSurface::MakeFromBackendTexture(ctxInfo.grContext(), backendTex,
kTopLeft_GrSurfaceOrigin, 0, colorType, nullptr,
nullptr);
REPORTER_ASSERT(reporter, can == SkToBool(surf), "ct: %d, can: %d, surf: %d",
colorType, can, SkToBool(surf));
surf = SkSurface::MakeFromBackendTextureAsRenderTarget(ctxInfo.grContext(), backendTex,
kTopLeft_GrSurfaceOrigin, 1,
colorType, nullptr, nullptr);
REPORTER_ASSERT(reporter, can == SkToBool(surf), "ct: %d, can: %d, surf: %d",
colorType, can, SkToBool(surf));
surf.reset();
ctxInfo.grContext()->flush();
if (backendTex.isValid()) {
gpu->deleteTestingOnlyBackendTexture(&backendTex);
}
static constexpr int kSampleCnt = 2;
can = ctxInfo.grContext()->maxSurfaceSampleCountForColorType(colorType) >= kSampleCnt;
surf = SkSurface::MakeRenderTarget(ctxInfo.grContext(), SkBudgeted::kYes, info, kSampleCnt,
nullptr);
REPORTER_ASSERT(reporter, can == SkToBool(surf), "ct: %d, can: %d, surf: %d",
colorType, can, SkToBool(surf));
backendTex = gpu->createTestingOnlyBackendTexture(nullptr, kSize, kSize, colorType, true,
GrMipMapped::kNo);
surf = SkSurface::MakeFromBackendTexture(ctxInfo.grContext(), backendTex,
kTopLeft_GrSurfaceOrigin, kSampleCnt, colorType,
nullptr, nullptr);
REPORTER_ASSERT(reporter, can == SkToBool(surf),
"colorTypeSupportedAsSurface:%d, surf:%d, ct:%d", can, SkToBool(surf),
colorType);
// Ensure that the sample count stored on the resulting SkSurface is a valid value.
if (surf) {
auto* rtc = ((SkSurface_Gpu*)(surf.get()))->getDevice()->accessRenderTargetContext();
int storedCnt = rtc->numStencilSamples();
int allowedCnt = ctxInfo.grContext()->caps()->getSampleCount(
storedCnt, rtc->asSurfaceProxy()->config());
REPORTER_ASSERT(reporter, storedCnt == allowedCnt,
"Should store an allowed sample count (%d vs %d)", allowedCnt,
storedCnt);
}
surf = SkSurface::MakeFromBackendTextureAsRenderTarget(ctxInfo.grContext(), backendTex,
kTopLeft_GrSurfaceOrigin, kSampleCnt,
colorType, nullptr, nullptr);
REPORTER_ASSERT(reporter, can == SkToBool(surf),
"colorTypeSupportedAsSurface:%d, surf:%d, ct:%d", can, SkToBool(surf),
colorType);
if (surf) {
auto* rtc = ((SkSurface_Gpu*)(surf.get()))->getDevice()->accessRenderTargetContext();
int storedCnt = rtc->numStencilSamples();
int allowedCnt = ctxInfo.grContext()->caps()->getSampleCount(
storedCnt, rtc->asSurfaceProxy()->config());
REPORTER_ASSERT(reporter, storedCnt == allowedCnt,
"Should store an allowed sample count (%d vs %d)", allowedCnt,
storedCnt);
}
surf.reset();
ctxInfo.grContext()->flush();
if (backendTex.isValid()) {
gpu->deleteTestingOnlyBackendTexture(&backendTex);
}
}
}
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrContext_maxSurfaceSamplesForColorType, reporter, ctxInfo) {
for (int ct = 0; ct < kLastEnum_SkColorType; ++ct) {
static constexpr int kSize = 10;
SkColorType colorType = static_cast<SkColorType>(ct);
int max = ctxInfo.grContext()->maxSurfaceSampleCountForColorType(colorType);
if (!max) {
continue;
}
auto* gpu = ctxInfo.grContext()->contextPriv().getGpu();
GrBackendTexture backendTex = gpu->createTestingOnlyBackendTexture(
nullptr, kSize, kSize, colorType, true, GrMipMapped::kNo);
auto info = SkImageInfo::Make(kSize, kSize, colorType, kOpaque_SkAlphaType, nullptr);
auto surf = SkSurface::MakeFromBackendTexture(ctxInfo.grContext(), backendTex,
kTopLeft_GrSurfaceOrigin, max,
colorType, nullptr, nullptr);
REPORTER_ASSERT(reporter, surf);
if (!surf) {
continue;
}
int sampleCnt = ((SkSurface_Gpu*)(surf.get()))
->getDevice()
->accessRenderTargetContext()
->numStencilSamples();
REPORTER_ASSERT(reporter, sampleCnt == max, "Exected: %d, actual: %d", max, sampleCnt);
}
}
#endif
static void test_canvas_peek(skiatest::Reporter* reporter, static void test_canvas_peek(skiatest::Reporter* reporter,
sk_sp<SkSurface>& surface, sk_sp<SkSurface>& surface,
const SkImageInfo& requestInfo, const SkImageInfo& requestInfo,
@ -437,10 +556,6 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfacepeekTexture_Gpu, reporter, ctxInfo) {
#endif #endif
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
#include "GrGpuResourcePriv.h"
#include "SkGpuDevice.h"
#include "SkImage_Gpu.h"
#include "SkSurface_Gpu.h"
static SkBudgeted is_budgeted(const sk_sp<SkSurface>& surf) { static SkBudgeted is_budgeted(const sk_sp<SkSurface>& surf) {
SkSurface_Gpu* gsurf = (SkSurface_Gpu*)surf.get(); SkSurface_Gpu* gsurf = (SkSurface_Gpu*)surf.get();

View File

@ -182,6 +182,13 @@ void GrGpu::Stats::dumpKeyValuePairs(SkTArray<SkString>* keys, SkTArray<double>*
#endif #endif
GrBackendTexture GrGpu::createTestingOnlyBackendTexture(void* pixels, int w, int h,
SkColorType colorType, bool isRenderTarget,
GrMipMapped mipMapped) {
GrPixelConfig config = SkImageInfo2GrPixelConfig(colorType, nullptr, *this->caps());
return this->createTestingOnlyBackendTexture(pixels, w, h, config, isRenderTarget, mipMapped);
}
#if GR_CACHE_STATS #if GR_CACHE_STATS
void GrResourceCache::getStats(Stats* stats) const { void GrResourceCache::getStats(Stats* stats) const {
stats->reset(); stats->reset();