Add SkSurface factory that takes an SkSurfaceCharacterization

TBR=bsalomon@google.com
Change-Id: Ie38123dc7c35005bfe8500bf4a16e0d16bbf36bd
Reviewed-on: https://skia-review.googlesource.com/117236
Reviewed-by: Robert Phillips <robertphillips@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Robert Phillips 2018-03-30 13:57:00 -04:00 committed by Skia Commit-Bot
parent 26339bf9a8
commit 6b6fcc7862
6 changed files with 118 additions and 9 deletions

View File

@ -711,6 +711,31 @@ Surface bottom-left corner is pinned to the origin.
# ------------------------------------------------------------------------------
#Method static sk_sp<SkSurface> MakeRenderTarget(GrContext* context,
const SkSurfaceCharacterization& characterization,
SkBudgeted budgeted)
Returns SkSurface on GPU indicated by context that is compatible with the provided
characterization. budgeted selects whether allocation for pixels is tracked by context.
@param context GPU context
@param characterization description of the desired SkSurface
@param budgeted one of: SkBudgeted::kNo, SkBudgeted::kYes
@return SkSurface if all parameters are valid; otherwise, nullptr
#Param context GPU_Context ##
#Param characterization description of the desired SkSurface ##
#Param budgeted one of: SkBudgeted::kNo, SkBudgeted::kYes
##
#Return Surface if all parameters are valid; otherwise, nullptr ##
#SeeAlso MakeFromBackendRenderTarget MakeFromBackendTextureAsRenderTarget
#Method ##
# ------------------------------------------------------------------------------
#Method static sk_sp<SkSurface> MakeNull(int width, int height)
#In Constructor

View File

@ -335,6 +335,18 @@ public:
nullptr);
}
/** Returns SkSurface on GPU indicated by context that is compatible with the provided
characterization. budgeted selects whether allocation for pixels is tracked by context.
@param context GPU context
@param characterization description of the desired SkSurface
@param budgeted one of: SkBudgeted::kNo, SkBudgeted::kYes
@return SkSurface if all parameters are valid; otherwise, nullptr
*/
static sk_sp<SkSurface> MakeRenderTarget(GrContext* context,
const SkSurfaceCharacterization& characterization,
SkBudgeted budgeted);
/** Returns SkSurface without backing pixels. Drawing to SkCanvas returned from SkSurface
has no effect. Calling makeImageSnapshot() on returned SkSurface returns nullptr.

View File

@ -33,6 +33,7 @@
#include "SkImageInfoPriv.h"
#include "SkJSONWriter.h"
#include "SkMakeUnique.h"
#include "SkSurface_Gpu.h"
#include "SkTaskGroup.h"
#include "SkUnPreMultiplyPriv.h"
#include "effects/GrConfigConversionEffect.h"
@ -172,8 +173,9 @@ SkSurfaceCharacterization GrContextThreadSafeProxy::createCharacterization(
return SkSurfaceCharacterization(); // return an invalid characterization
}
// We're assuming GrFSAAType::kMixedSamples will never be specified via this code path
GrFSAAType FSAAType = sampleCnt > 1 ? GrFSAAType::kUnifiedMSAA : GrFSAAType::kNone;
if (!SkSurface_Gpu::Valid(ii)) {
return SkSurfaceCharacterization(); // return an invalid characterization
}
if (!fCaps->mipMapSupport()) {
isMipMapped = false;
@ -184,6 +186,16 @@ SkSurfaceCharacterization GrContextThreadSafeProxy::createCharacterization(
return SkSurfaceCharacterization(); // return an invalid characterization
}
sampleCnt = fCaps->getRenderTargetSampleCount(sampleCnt, config);
if (!sampleCnt) {
return SkSurfaceCharacterization(); // return an invalid characterization
}
GrFSAAType FSAAType = GrFSAAType::kNone;
if (sampleCnt > 1) {
FSAAType = fCaps->usesMixedSamples() ? GrFSAAType::kMixedSamples : GrFSAAType::kUnifiedMSAA;
}
// This surface characterization factory assumes that the resulting characterization is
// textureable.
if (!fCaps->isConfigTexturable(config)) {

View File

@ -277,6 +277,11 @@ sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrContext*, SkBudgeted, const SkIma
return nullptr;
}
sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrContext*, const SkSurfaceCharacterization&,
SkBudgeted) {
return nullptr;
}
sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext*, const GrBackendTexture&,
GrSurfaceOrigin origin, int sampleCnt,
SkColorType, sk_sp<SkColorSpace>,

View File

@ -269,6 +269,26 @@ bool SkSurface_Gpu::Valid(GrContext* context, GrPixelConfig config, SkColorSpace
}
}
sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrContext* context,
const SkSurfaceCharacterization& c,
SkBudgeted budgeted) {
if (!c.isValid()) {
return nullptr;
}
SkColorType ct;
if (!GrPixelConfigToColorType(c.config(), &ct)) {
return nullptr;
}
SkImageInfo ii = SkImageInfo::Make(c.width(), c.height(), ct, kPremul_SkAlphaType,
c.refColorSpace());
return MakeRenderTarget(context, budgeted, ii, c.stencilCount(), c.origin(),
&c.surfaceProps(), c.isMipMapped());
}
sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrContext* ctx, SkBudgeted budgeted,
const SkImageInfo& info, int sampleCount,
GrSurfaceOrigin origin, const SkSurfaceProps* props,

View File

@ -121,13 +121,7 @@ public:
}
}
// Create a DDL whose characterization captures the current settings
std::unique_ptr<SkDeferredDisplayList> createDDL(GrContext* context) const {
sk_sp<SkSurface> s = this->make(context);
if (!s) {
return nullptr;
}
SkSurfaceCharacterization createCharacterization(GrContext* context) const {
int maxResourceCount;
size_t maxResourceBytes;
context->getResourceCacheLimits(&maxResourceCount, &maxResourceBytes);
@ -141,6 +135,12 @@ public:
SkSurfaceCharacterization c = context->threadSafeProxy()->createCharacterization(
maxResourceBytes, ii, backendFormat, fSampleCount,
fOrigin, fSurfaceProps, fShouldCreateMipMaps);
return c;
}
// Create a DDL whose characterization captures the current settings
std::unique_ptr<SkDeferredDisplayList> createDDL(GrContext* context) const {
SkSurfaceCharacterization c = this->createCharacterization(context);
SkAssertResult(c.isValid());
SkDeferredDisplayListRecorder r(c);
@ -205,6 +205,7 @@ private:
bool fShouldCreateMipMaps;
};
////////////////////////////////////////////////////////////////////////////////
// This tests SkSurfaceCharacterization/SkSurface compatibility
DEF_GPUTEST_FOR_ALL_CONTEXTS(DDLSurfaceCharacterizationTest, reporter, ctxInfo) {
GrContext* context = ctxInfo.grContext();
@ -258,6 +259,8 @@ DEF_GPUTEST_FOR_ALL_CONTEXTS(DDLSurfaceCharacterizationTest, reporter, ctxInfo)
}
if (SurfaceParameters::kMipMipCount == i && !context->caps()->mipMapSupport()) {
// If changing the mipmap setting won't result in a different surface characterization,
// skip this step
continue;
}
@ -345,6 +348,35 @@ DEF_GPUTEST_FOR_ALL_CONTEXTS(DDLSurfaceCharacterizationTest, reporter, ctxInfo)
}
}
////////////////////////////////////////////////////////////////////////////////
// This tests the SkSurface::MakeRenderTarget variant that takes an SkSurfaceCharacterization.
// In particular, the SkSurface and the SkSurfaceCharacterization should always be compatible.
DEF_GPUTEST_FOR_ALL_CONTEXTS(DDLMakeRenderTargetTest, reporter, ctxInfo) {
GrContext* context = ctxInfo.grContext();
for (int i = 0; i < SurfaceParameters::kNumParams; ++i) {
SurfaceParameters params;
params.modify(i);
SkSurfaceCharacterization c = params.createCharacterization(context);
sk_sp<SkSurface> s = params.make(context);
if (!s) {
REPORTER_ASSERT(reporter, !c.isValid());
continue;
}
REPORTER_ASSERT(reporter, c.isValid());
s = SkSurface::MakeRenderTarget(context, c, SkBudgeted::kYes);
REPORTER_ASSERT(reporter, s);
SkSurface_Gpu* g = static_cast<SkSurface_Gpu*>(s.get());
REPORTER_ASSERT(reporter, g->isCompatible(c));
}
}
////////////////////////////////////////////////////////////////////////////////
static constexpr int kSize = 8;
struct TextureReleaseChecker {
@ -411,6 +443,7 @@ static void dummy_fulfill_proc(void*, GrBackendTexture*) { SkASSERT(0); }
static void dummy_release_proc(void*) { SkASSERT(0); }
static void dummy_done_proc(void*) { }
////////////////////////////////////////////////////////////////////////////////
// Test out the behavior of an invalid DDLRecorder
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLInvalidRecorder, reporter, ctxInfo) {
GrContext* context = ctxInfo.grContext();
@ -450,6 +483,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLInvalidRecorder, reporter, ctxInfo) {
}
////////////////////////////////////////////////////////////////////////////////
// Ensure that flushing while DDL recording doesn't cause a crash
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLFlushWhileRecording, reporter, ctxInfo) {
GrContext* context = ctxInfo.grContext();
@ -467,6 +501,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLFlushWhileRecording, reporter, ctxInfo) {
canvas->getGrContext()->flush();
}
////////////////////////////////////////////////////////////////////////////////
// Check that the texture-specific flags (i.e., for external & rectangle textures) work
// for promise images. As such, this is a GL-only test.
DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(DDLTextureFlagsTest, reporter, ctxInfo) {