Add unit test for SkDeferredDisplayLists

Change-Id: I015094145cb0af6cfe368c570a5d5280c11c8f28
Reviewed-on: https://skia-review.googlesource.com/78660
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Robert Phillips 2017-12-04 07:52:57 -05:00 committed by Skia Commit-Bot
parent 0c56d47b7e
commit 8458a2807b
10 changed files with 168 additions and 18 deletions

View File

@ -47,8 +47,9 @@ tests_sources = [
"$_tests/CTest.cpp",
"$_tests/DashPathEffectTest.cpp",
"$_tests/DataRefTest.cpp",
"$_tests/DequeTest.cpp",
"$_tests/DefaultPathRendererTest.cpp",
"$_tests/DeferredDisplayListTest.cpp",
"$_tests/DequeTest.cpp",
"$_tests/DetermineDomainModeTest.cpp",
"$_tests/DeviceLooperTest.cpp",
"$_tests/DeviceTest.cpp",

View File

@ -362,7 +362,7 @@ public:
* The draw will be skipped if the characterization stored in the display list
* isn't compatible with this surface.
*/
void draw(SkDeferredDisplayList* deferredDisplayList);
bool draw(SkDeferredDisplayList* deferredDisplayList);
protected:
SkSurface(int width, int height, const SkSurfaceProps* surfaceProps);

View File

@ -32,7 +32,7 @@ public:
}
// TODO: remove this. It is just scaffolding to get something up & running
void draw(SkSurface*);
bool draw(SkSurface*);
private:
const SkSurfaceCharacterization fCharacterization;

View File

@ -11,6 +11,7 @@
#include "GrTypes.h"
#if SK_SUPPORT_GPU
#include "GrTypesPriv.h"
#include "SkSurfaceProps.h"
class GrContextThreadSafeProxy;
@ -21,7 +22,7 @@ class SkColorSpace;
rendering decisions. When passed into a SkDeferredDisplayListRecorder it will copy the
data and pass it on to the SkDeferredDisplayList if/when it is created. Note that both of
those objects (the Recorder and the DisplayList) will take a ref on the
GrContextThreadSafeProxy object.
GrContextThreadSafeProxy and SkColorSpace objects.
*/
class SkSurfaceCharacterization {
public:
@ -30,7 +31,8 @@ public:
, fWidth(0)
, fHeight(0)
, fConfig(kUnknown_GrPixelConfig)
, fSampleCnt(0)
, fFSAAType(GrFSAAType::kNone)
, fStencilCnt(0)
, fSurfaceProps(0, kUnknown_SkPixelGeometry) {
}
@ -45,7 +47,8 @@ public:
int width() const { return fWidth; }
int height() const { return fHeight; }
GrPixelConfig config() const { return fConfig; }
int sampleCount() const { return fSampleCnt; }
GrFSAAType fsaaType() const { return fFSAAType; }
int stencilCount() const { return fStencilCnt; }
SkColorSpace* colorSpace() const { return fColorSpace.get(); }
sk_sp<SkColorSpace> refColorSpace() const { return fColorSpace; }
const SkSurfaceProps& surfaceProps()const { return fSurfaceProps; }
@ -57,7 +60,8 @@ private:
GrSurfaceOrigin origin,
int width, int height,
GrPixelConfig config,
int sampleCnt,
GrFSAAType fsaaType,
int stencilCnt,
sk_sp<SkColorSpace> colorSpace,
const SkSurfaceProps& surfaceProps) {
fContextInfo = contextInfo;
@ -65,7 +69,8 @@ private:
fWidth = width;
fHeight = height;
fConfig = config;
fSampleCnt = sampleCnt;
fFSAAType = fsaaType;
fStencilCnt = stencilCnt;
fColorSpace = std::move(colorSpace);
fSurfaceProps = surfaceProps;
}
@ -75,7 +80,8 @@ private:
int fWidth;
int fHeight;
GrPixelConfig fConfig;
int fSampleCnt;
GrFSAAType fFSAAType;
int fStencilCnt;
sk_sp<SkColorSpace> fColorSpace;
SkSurfaceProps fSurfaceProps;
};

View File

@ -43,6 +43,7 @@ std::unique_ptr<SkDeferredDisplayList> SkDeferredDisplayListRecorder::detach() {
// Placeholder. Ultimately, the SkSurface_Gpu will pass the wrapped opLists to its
// renderTargetContext.
void SkDeferredDisplayList::draw(SkSurface* surface) {
bool SkDeferredDisplayList::draw(SkSurface* surface) {
surface->getCanvas()->drawImage(fImage.get(), 0, 0);
return true;
}

View File

@ -213,7 +213,7 @@ bool SkSurface::characterize(SkSurfaceCharacterization* characterization) const
return asSB(const_cast<SkSurface*>(this))->onCharacterize(characterization);
}
void SkSurface::draw(SkDeferredDisplayList* ddl) {
bool SkSurface::draw(SkDeferredDisplayList* ddl) {
return asSB(this)->onDraw(ddl);
}

View File

@ -95,7 +95,7 @@ public:
}
virtual bool onCharacterize(SkSurfaceCharacterization*) const { return false; }
virtual void onDraw(SkDeferredDisplayList*) { }
virtual bool onDraw(SkDeferredDisplayList*) { return false; }
inline SkCanvas* getCachedCanvas();
inline sk_sp<SkImage> refCachedImage();

View File

@ -165,7 +165,7 @@ bool SkSurface_Gpu::onCharacterize(SkSurfaceCharacterization* data) const {
GrContext* ctx = fDevice->context();
data->set(ctx->threadSafeProxy(), rtc->origin(), rtc->width(), rtc->height(),
rtc->colorSpaceInfo().config(), rtc->numColorSamples(),
rtc->colorSpaceInfo().config(), rtc->fsaaType(), rtc->numStencilSamples(),
rtc->colorSpaceInfo().refColorSpace(), this->props());
return true;
@ -178,19 +178,19 @@ bool SkSurface_Gpu::isCompatible(const SkSurfaceCharacterization& data) const {
return data.contextInfo() && data.contextInfo()->matches(ctx) &&
data.origin() == rtc->origin() && data.width() == rtc->width() &&
data.height() == rtc->height() && data.config() == rtc->colorSpaceInfo().config() &&
data.sampleCount() == rtc->numColorSamples() &&
data.fsaaType() == rtc->fsaaType() && data.stencilCount() == rtc->numStencilSamples() &&
SkColorSpace::Equals(data.colorSpace(), rtc->colorSpaceInfo().colorSpace()) &&
data.surfaceProps() == rtc->surfaceProps();
}
void SkSurface_Gpu::onDraw(SkDeferredDisplayList* dl) {
bool SkSurface_Gpu::onDraw(SkDeferredDisplayList* dl) {
if (!this->isCompatible(dl->characterization())) {
return;
return false;
}
// Ultimately need to pass opLists from the DeferredDisplayList on to the
// SkGpuDevice's renderTargetContext.
dl->draw(this);
return dl->draw(this);
}

View File

@ -31,7 +31,7 @@ public:
bool onWait(int numSemaphores, const GrBackendSemaphore* waitSemaphores) override;
bool onCharacterize(SkSurfaceCharacterization*) const override;
bool isCompatible(const SkSurfaceCharacterization&) const;
void onDraw(SkDeferredDisplayList*) override;
bool onDraw(SkDeferredDisplayList*) override;
SkGpuDevice* getDevice() { return fDevice.get(); }

View File

@ -0,0 +1,142 @@
/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkTypes.h"
#if SK_SUPPORT_GPU
#include "SkCanvas.h"
#include "SkDeferredDisplayListRecorder.h"
#include "SkGpuDevice.h"
#include "SkSurface.h"
#include "SkSurface_Gpu.h"
#include "SkSurfaceCharacterization.h"
#include "SkSurfaceProps.h"
#include "Test.h"
class SurfaceParameters {
public:
static const int kNumParams = 8;
static const int kSampleCount = 5;
SurfaceParameters()
: fWidth(64)
, fHeight(64)
, fOrigin(kTopLeft_GrSurfaceOrigin)
, fColorType(kRGBA_8888_SkColorType)
, fColorSpace(SkColorSpace::MakeSRGB())
, fSampleCount(0)
, fSurfaceProps(0x0, kUnknown_SkPixelGeometry) {
}
int sampleCount() const { return fSampleCount; }
// Modify the SurfaceParameters in just one way
void modify(int i) {
switch (i) {
case 0:
fWidth = 63;
break;
case 1:
fHeight = 63;
break;
case 2:
fOrigin = kBottomLeft_GrSurfaceOrigin;
break;
case 3:
fColorType = kRGBA_F16_SkColorType;
break;
case 4:
fColorSpace = SkColorSpace::MakeSRGBLinear();
break;
case kSampleCount:
fSampleCount = 4;
break;
case 6:
fSurfaceProps = SkSurfaceProps(0x0, kRGB_H_SkPixelGeometry);
break;
case 7:
fSurfaceProps = SkSurfaceProps(SkSurfaceProps::kUseDeviceIndependentFonts_Flag,
kUnknown_SkPixelGeometry);
break;
}
}
// Create the surface with the current set of parameters
sk_sp<SkSurface> make(GrContext* context) const {
// Note that Ganesh doesn't make use of the SkImageInfo's alphaType
SkImageInfo ii = SkImageInfo::Make(fWidth, fHeight, fColorType,
kPremul_SkAlphaType, fColorSpace);
return SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, ii, fSampleCount,
fOrigin, &fSurfaceProps);
}
private:
int fWidth;
int fHeight;
GrSurfaceOrigin fOrigin;
SkColorType fColorType;
sk_sp<SkColorSpace> fColorSpace;
int fSampleCount;
SkSurfaceProps fSurfaceProps;
};
// This tests SkSurfaceCharacterization/SkSurface compatibility
DEF_GPUTEST_FOR_ALL_CONTEXTS(SkSurfaceCharacterization, reporter, ctxInfo) {
GrContext* context = ctxInfo.grContext();
std::unique_ptr<SkDeferredDisplayList> ddl;
// First, create a DDL using the stock SkSurface parameters
{
SurfaceParameters params;
sk_sp<SkSurface> s = params.make(context);
if (!s) {
return;
}
SkSurfaceCharacterization c;
SkAssertResult(s->characterize(&c));
SkDeferredDisplayListRecorder r(c);
SkCanvas* canvas = r.getCanvas();
canvas->drawRect(SkRect::MakeXYWH(10, 10, 10, 10), SkPaint());
ddl = r.detach();
REPORTER_ASSERT(reporter, s->draw(ddl.get()));
}
// Then, alter each parameter in turn and check that the DDL & surface are incompatible
for (int i = 0; i < SurfaceParameters::kNumParams; ++i) {
SurfaceParameters params;
params.modify(i);
sk_sp<SkSurface> s = params.make(context);
if (!s) {
continue;
}
if (SurfaceParameters::kSampleCount == i) {
SkSurface_Gpu* gpuSurf = static_cast<SkSurface_Gpu*>(s.get());
int supportedSampleCount = context->caps()->getSampleCount(
params.sampleCount(),
gpuSurf->getDevice()->accessRenderTargetContext()->asRenderTargetProxy()->config());
if (0 == supportedSampleCount) {
// If changing the sample count won't result in a different
// surface characterization, skip this step
continue;
}
}
REPORTER_ASSERT(reporter, !s->draw(ddl.get()));
}
}
#endif