Add stubbed out GrContext

This CL mainly just:
   stores the GrContextOptions in GrContextThreadSafeProxy (so they can be passed on to a stubbed out GrContext)
   adds a method to create a stubbed out GrContext that has a GrStubGpu
      - the stubbed out GrContext isn't quite ready for prime time yet

Change-Id: I31be6763640e406c5963e6f0714489ac358339e4
Reviewed-on: https://skia-review.googlesource.com/79601
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Robert Phillips 2017-12-13 11:50:22 -05:00 committed by Skia Commit-Bot
parent b9042d206a
commit e42edcc8ef
14 changed files with 402 additions and 66 deletions

View File

@ -495,6 +495,10 @@ skia_gpu_sources = [
"$_src/gpu/mock/GrMockStencilAttachment.h",
"$_src/gpu/mock/GrMockTexture.h",
# DDL
"$_src/gpu/ddl/GrDDLGpu.cpp",
"$_src/gpu/ddl/GrDDLGpu.h",
# Sk files
"$_src/gpu/SkGpuDevice.cpp",
"$_src/gpu/SkGpuDevice.h",

View File

@ -13,8 +13,12 @@
#include "../private/SkDeferredDisplayList.h"
#include "../private/SkSurfaceCharacterization.h"
class GrContext;
class SkCanvas;
class SkSurface; // TODO: remove
class SkSurface;
#define SK_RASTER_RECORDER_IMPLEMENTATION 1
/*
* This class is intended to be used as:
@ -44,9 +48,13 @@ public:
std::unique_ptr<SkDeferredDisplayList> detach();
private:
const SkSurfaceCharacterization fCharacterization;
bool init();
sk_sp<SkSurface> fSurface; // temporary until we have a real implementation
const SkSurfaceCharacterization fCharacterization;
#ifndef SK_RASTER_RECORDER_IMPLEMENTATION
sk_sp<GrContext> fContext;
#endif
sk_sp<SkSurface> fSurface;
};
#endif

View File

@ -382,16 +382,16 @@ private:
GrAuditTrail fAuditTrail;
GrBackend fBackend;
const GrBackend fBackend;
GrContextOptions::PersistentCache* fPersistentCache;
// TODO: have the GrClipStackClip use renderTargetContexts and rm this friending
friend class GrContextPriv;
GrContext(); // init must be called after the constructor.
bool init(GrBackend, GrBackendContext, const GrContextOptions& options);
bool init(const GrContextOptions& options);
GrContext(GrBackend); // init must be called after the constructor.
GrContext(GrContextThreadSafeProxy*);
bool init(const GrContextOptions&);
/**
* These functions create premul <-> unpremul effects. If the second argument is 'true', they
@ -427,14 +427,24 @@ public:
bool matches(GrContext* context) const { return context->uniqueID() == fContextUniqueID; }
private:
GrContextThreadSafeProxy(sk_sp<const GrCaps> caps, uint32_t uniqueID)
// DDL TODO: need to add unit tests for backend & maybe options
GrContextThreadSafeProxy(sk_sp<const GrCaps> caps,
uint32_t uniqueID,
GrBackend backend,
const GrContextOptions& options)
: fCaps(std::move(caps))
, fContextUniqueID(uniqueID) {}
, fContextUniqueID(uniqueID)
, fBackend(backend)
, fOptions(options) {
}
sk_sp<const GrCaps> fCaps;
uint32_t fContextUniqueID;
sk_sp<const GrCaps> fCaps;
const uint32_t fContextUniqueID;
const GrBackend fBackend;
const GrContextOptions fOptions;
friend class GrContext;
friend class GrContextPriv;
friend class SkImage;
typedef SkRefCnt INHERITED;

View File

@ -10,13 +10,15 @@
#include "GrTypes.h"
#if SK_SUPPORT_GPU
#include "GrTypesPriv.h"
#include "SkSurfaceProps.h"
class GrContextThreadSafeProxy;
class SkColorSpace;
#if SK_SUPPORT_GPU
#include "GrTypesPriv.h"
class GrContextThreadSafeProxy;
/** \class SkSurfaceCharacterization
A surface characterization contains all the information Ganesh requires to makes its internal
rendering decisions. When passed into a SkDeferredDisplayListRecorder it will copy the
@ -103,14 +105,23 @@ private:
class SkSurfaceCharacterization {
public:
SkSurfaceCharacterization() : fWidth(0), fHeight(0) { }
SkSurfaceCharacterization()
: fWidth(0)
, fHeight(0)
, fSurfaceProps(0, kUnknown_SkPixelGeometry) {
}
int width() const { return fWidth; }
int height() const { return fHeight; }
SkColorSpace* colorSpace() const { return fColorSpace.get(); }
sk_sp<SkColorSpace> refColorSpace() const { return fColorSpace; }
const SkSurfaceProps& surfaceProps()const { return fSurfaceProps; }
private:
int fWidth;
int fHeight;
sk_sp<SkColorSpace> fColorSpace;
SkSurfaceProps fSurfaceProps;
};
#endif

View File

@ -7,25 +7,61 @@
#include "SkDeferredDisplayListRecorder.h"
#include "GrContext.h"
#if SK_SUPPORT_GPU
#include "GrContextPriv.h"
#include "SkGr.h"
#endif
#include "SkCanvas.h" // TODO: remove
#include "SkDeferredDisplayList.h"
#include "SkSurface.h" // TODO: remove
#include "SkSurface.h"
#include "SkSurfaceCharacterization.h"
SkDeferredDisplayListRecorder::SkDeferredDisplayListRecorder(
const SkSurfaceCharacterization& characterization)
: fCharacterization(characterization) {
}
bool SkDeferredDisplayListRecorder::init() {
SkASSERT(!fSurface);
#ifdef SK_RASTER_RECORDER_IMPLEMENTATION
// Use raster right now to allow threading
const SkImageInfo ii = SkImageInfo::Make(fCharacterization.width(), fCharacterization.height(),
kN32_SkColorType, kOpaque_SkAlphaType,
fCharacterization.refColorSpace());
fSurface = SkSurface::MakeRaster(ii, &fCharacterization.surfaceProps());
#else
if (!fContext) {
fContext = GrContextPriv::MakeStubbedOut(fCharacterization.contextInfo());
if (!fContext) {
return false;
}
}
SkColorType colorType = kUnknown_SkColorType;
if (!GrPixelConfigToColorType(fCharacterization.config(), &colorType)) {
return false;
}
const SkImageInfo ii = SkImageInfo::Make(fCharacterization.width(), fCharacterization.height(),
colorType, kPremul_SkAlphaType,
fCharacterization.refColorSpace());
fSurface = SkSurface::MakeRenderTarget(fContext.get(), SkBudgeted::kYes,
ii, fCharacterization.stencilCount(),
fCharacterization.origin(),
&fCharacterization.surfaceProps());
#endif
return SkToBool(fSurface.get());
}
SkCanvas* SkDeferredDisplayListRecorder::getCanvas() {
if (!fSurface) {
SkImageInfo ii = SkImageInfo::MakeN32(fCharacterization.width(),
fCharacterization.height(),
kOpaque_SkAlphaType);
// Use raster right now to allow threading
fSurface = SkSurface::MakeRaster(ii, nullptr);
if (!this->init()) {
return nullptr;
}
}
return fSurface->getCanvas();

View File

@ -38,6 +38,7 @@
#ifdef SK_METAL
#include "mtl/GrMtlTrampoline.h"
#endif
#include "ddl/GrDDLGpu.h"
#ifdef SK_VULKAN
#include "vk/GrVkGpu.h"
#endif
@ -67,11 +68,18 @@ GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext)
GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext,
const GrContextOptions& options) {
sk_sp<GrContext> context(new GrContext);
if (!context->init(backend, backendContext, options)) {
sk_sp<GrContext> context(new GrContext(backend));
context->fGpu = GrGpu::Make(backend, backendContext, options, context.get());
if (!context->fGpu) {
return nullptr;
}
if (!context->init(options)) {
return nullptr;
}
return context.release();
}
@ -82,12 +90,12 @@ sk_sp<GrContext> GrContext::MakeGL(sk_sp<const GrGLInterface> interface) {
sk_sp<GrContext> GrContext::MakeGL(sk_sp<const GrGLInterface> interface,
const GrContextOptions& options) {
sk_sp<GrContext> context(new GrContext);
sk_sp<GrContext> context(new GrContext(kOpenGL_GrBackend));
context->fGpu = GrGLGpu::Make(std::move(interface), options, context.get());
if (!context->fGpu) {
return nullptr;
}
context->fBackend = kOpenGL_GrBackend;
if (!context->init(options)) {
return nullptr;
}
@ -110,12 +118,12 @@ sk_sp<GrContext> GrContext::MakeMock(const GrMockOptions* mockOptions) {
sk_sp<GrContext> GrContext::MakeMock(const GrMockOptions* mockOptions,
const GrContextOptions& options) {
sk_sp<GrContext> context(new GrContext);
sk_sp<GrContext> context(new GrContext(kMock_GrBackend));
context->fGpu = GrMockGpu::Make(mockOptions, options, context.get());
if (!context->fGpu) {
return nullptr;
}
context->fBackend = kMock_GrBackend;
if (!context->init(options)) {
return nullptr;
}
@ -130,12 +138,12 @@ sk_sp<GrContext> GrContext::MakeVulkan(sk_sp<const GrVkBackendContext> backendCo
sk_sp<GrContext> GrContext::MakeVulkan(sk_sp<const GrVkBackendContext> backendContext,
const GrContextOptions& options) {
sk_sp<GrContext> context(new GrContext);
sk_sp<GrContext> context(new GrContext(kVulkan_GrBackend));
context->fGpu = GrVkGpu::Make(std::move(backendContext), options, context.get());
if (!context->fGpu) {
return nullptr;
}
context->fBackend = kVulkan_GrBackend;
if (!context->init(options)) {
return nullptr;
}
@ -150,12 +158,12 @@ sk_sp<GrContext> GrContext::MakeMetal(void* device, void* queue) {
}
sk_sp<GrContext> GrContext::MakeMetal(void* device, void* queue, const GrContextOptions& options) {
sk_sp<GrContext> context(new GrContext);
sk_sp<GrContext> context(new GrContext(kMetal_GrBackend));
context->fGpu = GrMtlTrampoline::MakeGpu(context.get(), options, device, queue);
if (!context->fGpu) {
return nullptr;
}
context->fBackend = kMetal_GrBackend;
if (!context->init(options)) {
return nullptr;
}
@ -172,31 +180,44 @@ static int32_t next_id() {
return id;
}
GrContext::GrContext() : fUniqueID(next_id()) {
sk_sp<GrContext> GrContextPriv::MakeDDL(GrContextThreadSafeProxy* proxy) {
sk_sp<GrContext> context(new GrContext(proxy));
context->fGpu = GrDDLGpu::Make(context.get(), proxy->fCaps);
if (!context->fGpu) {
return nullptr;
}
if (!context->init(proxy->fOptions)) {
return nullptr;
}
return context;
}
GrContext::GrContext(GrBackend backend)
: fUniqueID(next_id())
, fBackend(backend) {
fResourceCache = nullptr;
fResourceProvider = nullptr;
fAtlasGlyphCache = nullptr;
}
bool GrContext::init(GrBackend backend, GrBackendContext backendContext,
const GrContextOptions& options) {
ASSERT_SINGLE_OWNER
SkASSERT(!fGpu);
fBackend = backend;
fGpu = GrGpu::Make(backend, backendContext, options, this);
if (!fGpu) {
return false;
}
return this->init(options);
GrContext::GrContext(GrContextThreadSafeProxy* proxy)
: fUniqueID(proxy->fContextUniqueID)
, fBackend(proxy->fBackend) {
fResourceCache = nullptr;
fResourceProvider = nullptr;
fAtlasGlyphCache = nullptr;
}
bool GrContext::init(const GrContextOptions& options) {
ASSERT_SINGLE_OWNER
fCaps = sk_ref_sp(fGpu->caps());
fCaps = fGpu->refCaps();
fResourceCache = new GrResourceCache(fCaps.get(), fUniqueID);
fResourceProvider = new GrResourceProvider(fGpu.get(), fResourceCache, &fSingleOwner);
// DDL TODO: we need to think through how the task group & persistent cache
// get passed on to/shared between all the DDLRecorders created with this context.
fThreadSafeProxy.reset(new GrContextThreadSafeProxy(fCaps, this->uniqueID(), fBackend,
options));
fDisableGpuYUVConversion = options.fDisableGpuYUVConversion;
fDidTestPMConversions = false;
@ -270,9 +291,6 @@ GrContext::~GrContext() {
}
sk_sp<GrContextThreadSafeProxy> GrContext::threadSafeProxy() {
if (!fThreadSafeProxy) {
fThreadSafeProxy.reset(new GrContextThreadSafeProxy(fCaps, this->uniqueID()));
}
return fThreadSafeProxy;
}

View File

@ -22,6 +22,11 @@ class GrTextureContext;
data members or virtual methods. */
class GrContextPriv {
public:
/**
* Create a GrContext without a resource cache
*/
static sk_sp<GrContext> MakeDDL(GrContextThreadSafeProxy*);
GrDrawingManager* drawingManager() { return fContext->fDrawingManager.get(); }
sk_sp<GrSurfaceContext> makeWrappedSurfaceContext(sk_sp<GrSurfaceProxy>, sk_sp<SkColorSpace>);

View File

@ -8,6 +8,7 @@
#ifndef GrGpu_DEFINED
#define GrGpu_DEFINED
#include "GrCaps.h"
#include "GrGpuCommandBuffer.h"
#include "GrProgramDesc.h"
#include "GrSwizzle.h"
@ -48,8 +49,7 @@ public:
* not supported (at compile-time or run-time) this returns nullptr. The context will not be
* fully constructed and should not be used by GrGpu until after this function returns.
*/
static sk_sp<GrGpu> Make(GrBackend, GrBackendContext, const GrContextOptions&,
GrContext* context);
static sk_sp<GrGpu> Make(GrBackend, GrBackendContext, const GrContextOptions&, GrContext*);
////////////////////////////////////////////////////////////////////////////
@ -63,6 +63,7 @@ public:
* Gets the capabilities of the draw target.
*/
const GrCaps* caps() const { return fCaps.get(); }
sk_sp<const GrCaps> refCaps() const { return fCaps; }
GrPathRendering* pathRendering() { return fPathRendering.get(); }

73
src/gpu/ddl/GrDDLGpu.cpp Normal file
View File

@ -0,0 +1,73 @@
/*
* 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 "GrDDLGpu.h"
#include "GrCaps.h"
sk_sp<GrGpu> GrDDLGpu::Make(GrContext* context, sk_sp<const GrCaps> caps) {
return sk_sp<GrGpu>(new GrDDLGpu(context, std::move(caps)));
}
GrGpuRTCommandBuffer* GrDDLGpu::createCommandBuffer(
GrRenderTarget* rt, GrSurfaceOrigin origin,
const GrGpuRTCommandBuffer::LoadAndStoreInfo&,
const GrGpuRTCommandBuffer::StencilLoadAndStoreInfo&) {
SkASSERT(0);
return nullptr;
}
GrGpuTextureCommandBuffer* GrDDLGpu::createCommandBuffer(GrTexture* texture,
GrSurfaceOrigin origin) {
SkASSERT(0);
return nullptr;
}
void GrDDLGpu::submitCommandBuffer(const GrGpuRTCommandBuffer* cmdBuffer) {
SkASSERT(0);
}
GrDDLGpu::GrDDLGpu(GrContext* context, sk_sp<const GrCaps> caps)
: INHERITED(context) {
fCaps = caps;
}
sk_sp<GrTexture> GrDDLGpu::onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
const GrMipLevel texels[], int mipLevelCount) {
SkASSERT(0);
return nullptr;
}
GrBuffer* GrDDLGpu::onCreateBuffer(size_t sizeInBytes, GrBufferType type,
GrAccessPattern accessPattern, const void*) {
SkASSERT(0);
return nullptr;
}
GrStencilAttachment* GrDDLGpu::createStencilAttachmentForRenderTarget(const GrRenderTarget* rt,
int width,
int height) {
SkASSERT(0);
return nullptr;
}
GrBackendTexture GrDDLGpu::createTestingOnlyBackendTexture(void* pixels, int w, int h,
GrPixelConfig config, bool isRT,
GrMipMapped) {
SkASSERT(0);
return GrBackendTexture(); // invalid
}
bool GrDDLGpu::isTestingOnlyBackendTexture(const GrBackendTexture& tex) const {
SkASSERT(0);
return false;
}
void GrDDLGpu::deleteTestingOnlyBackendTexture(GrBackendTexture* tex, bool abandonTexture) {
SkASSERT(0);
}

174
src/gpu/ddl/GrDDLGpu.h Normal file
View File

@ -0,0 +1,174 @@
/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrDDLGpu_DEFINED
#define GrDDLGpu_DEFINED
#include "GrGpu.h"
#include "GrRenderTarget.h"
#include "GrSemaphore.h"
#include "GrTexture.h"
class GrDDLGpu : public GrGpu {
public:
static sk_sp<GrGpu> Make(GrContext*, sk_sp<const GrCaps>);
~GrDDLGpu() override {}
bool onGetReadPixelsInfo(GrSurface* srcSurface, GrSurfaceOrigin srcOrigin,
int readWidth, int readHeight, size_t rowBytes,
GrPixelConfig readConfig, DrawPreference*,
ReadPixelTempDrawInfo*) override {
SkASSERT(0);
return true;
}
bool onGetWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin dstOrigin,
int width, int height,
GrPixelConfig srcConfig, DrawPreference*,
WritePixelTempDrawInfo*) override {
SkASSERT(0);
return true;
}
bool onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
GrSurface* src, GrSurfaceOrigin srcOrigin,
const SkIRect& srcRect, const SkIPoint& dstPoint) override {
SkASSERT(0);
return true;
}
void onQueryMultisampleSpecs(GrRenderTarget* rt, GrSurfaceOrigin, const GrStencilSettings&,
int* effectiveSampleCnt, SamplePattern*) override {
SkASSERT(0);
*effectiveSampleCnt = 0; // ??
}
GrGpuRTCommandBuffer* createCommandBuffer(
GrRenderTarget*, GrSurfaceOrigin,
const GrGpuRTCommandBuffer::LoadAndStoreInfo&,
const GrGpuRTCommandBuffer::StencilLoadAndStoreInfo&) override;
GrGpuTextureCommandBuffer* createCommandBuffer(GrTexture*, GrSurfaceOrigin) override;
GrFence SK_WARN_UNUSED_RESULT insertFence() override {
SkASSERT(0);
return 0;
}
bool waitFence(GrFence, uint64_t) override {
SkASSERT(0);
return true;
}
void deleteFence(GrFence) const override {
SkASSERT(0);
}
sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT makeSemaphore(bool isOwned) override {
SkASSERT(0);
return nullptr;
}
sk_sp<GrSemaphore> wrapBackendSemaphore(const GrBackendSemaphore& semaphore,
GrWrapOwnership ownership) override {
SkASSERT(0);
return nullptr;
}
void insertSemaphore(sk_sp<GrSemaphore> semaphore, bool flush) override {
SkASSERT(0);
}
void waitSemaphore(sk_sp<GrSemaphore> semaphore) override {
SkASSERT(0);
}
sk_sp<GrSemaphore> prepareTextureForCrossContextUsage(GrTexture*) override {
SkASSERT(0);
return nullptr;
}
void submitCommandBuffer(const GrGpuRTCommandBuffer*);
private:
GrDDLGpu(GrContext* context, sk_sp<const GrCaps> caps);
void onResetContext(uint32_t resetBits) override { SkASSERT(0); }
void xferBarrier(GrRenderTarget*, GrXferBarrierType) override { SkASSERT(0); }
sk_sp<GrTexture> onCreateTexture(const GrSurfaceDesc&, SkBudgeted,
const GrMipLevel texels[], int mipLevelCount) override;
sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTexture&, GrWrapOwnership) override {
SkASSERT(0);
return nullptr;
}
sk_sp<GrTexture> onWrapRenderableBackendTexture(const GrBackendTexture&,
int sampleCnt,
GrWrapOwnership) override {
SkASSERT(0);
return nullptr;
}
sk_sp<GrRenderTarget> onWrapBackendRenderTarget(const GrBackendRenderTarget&) override {
SkASSERT(0);
return nullptr;
}
sk_sp<GrRenderTarget> onWrapBackendTextureAsRenderTarget(const GrBackendTexture&,
int sampleCnt) override {
SkASSERT(0);
return nullptr;
}
GrBuffer* onCreateBuffer(size_t sizeInBytes, GrBufferType, GrAccessPattern,
const void*) override;
bool onReadPixels(GrSurface* surface, GrSurfaceOrigin,
int left, int top, int width, int height,
GrPixelConfig,
void* buffer,
size_t rowBytes) override {
SkASSERT(0);
return true;
}
bool onWritePixels(GrSurface* surface, GrSurfaceOrigin,
int left, int top, int width, int height,
GrPixelConfig config,
const GrMipLevel texels[], int mipLevelCount) override {
SkASSERT(0);
return true;
}
bool onTransferPixels(GrTexture* texture,
int left, int top, int width, int height,
GrPixelConfig config, GrBuffer* transferBuffer,
size_t offset, size_t rowBytes) override {
SkASSERT(0);
return true;
}
void onResolveRenderTarget(GrRenderTarget* target, GrSurfaceOrigin) override {
SkASSERT(0);
return;
}
void onFinishFlush(bool insertedSemaphores) override { SkASSERT(0); }
GrStencilAttachment* createStencilAttachmentForRenderTarget(const GrRenderTarget*,
int width,
int height) override;
void clearStencil(GrRenderTarget*, int clearValue) override { SkASSERT(0); }
GrBackendTexture createTestingOnlyBackendTexture(void* pixels, int w, int h, GrPixelConfig,
bool isRT, GrMipMapped) override;
bool isTestingOnlyBackendTexture(const GrBackendTexture&) const override;
void deleteTestingOnlyBackendTexture(GrBackendTexture*, bool abandon = false) override;
typedef GrGpu INHERITED;
};
#endif

View File

@ -34,10 +34,8 @@ class GrSwizzle;
class GrGLGpu final : public GrGpu, private GrMesh::SendToGpuImpl {
public:
static sk_sp<GrGpu> Make(GrBackendContext backendContext, const GrContextOptions& options,
GrContext* context);
static sk_sp<GrGpu> Make(sk_sp<const GrGLInterface>, const GrContextOptions& options,
GrContext* context);
static sk_sp<GrGpu> Make(GrBackendContext backendContext, const GrContextOptions&, GrContext*);
static sk_sp<GrGpu> Make(sk_sp<const GrGLInterface>, const GrContextOptions&, GrContext*);
~GrGLGpu() override;
void disconnect(DisconnectType) override;

View File

@ -21,10 +21,7 @@ struct GrContextOptions;
*/
class GrMtlTrampoline {
public:
static sk_sp<GrGpu> MakeGpu(GrContext* context,
const GrContextOptions& options,
void* device,
void* queue);
static sk_sp<GrGpu> MakeGpu(GrContext*, const GrContextOptions&, void* device, void* queue);
};
#endif

View File

@ -38,10 +38,8 @@ namespace SkSL {
class GrVkGpu : public GrGpu {
public:
static sk_sp<GrGpu> Make(GrBackendContext backendContext, const GrContextOptions& options,
GrContext* context);
static sk_sp<GrGpu> Make(sk_sp<const GrVkBackendContext>, const GrContextOptions& options,
GrContext* context);
static sk_sp<GrGpu> Make(GrBackendContext backendContext, const GrContextOptions&, GrContext*);
static sk_sp<GrGpu> Make(sk_sp<const GrVkBackendContext>, const GrContextOptions&, GrContext*);
~GrVkGpu() override;
@ -173,8 +171,7 @@ public:
GrVkHeap* getHeap(Heap heap) const { return fHeaps[heap].get(); }
private:
GrVkGpu(GrContext* context, const GrContextOptions& options,
sk_sp<const GrVkBackendContext> backendContext);
GrVkGpu(GrContext*, const GrContextOptions&, sk_sp<const GrVkBackendContext> backendContext);
void onResetContext(uint32_t resetBits) override {}

View File

@ -106,6 +106,10 @@ DEF_GPUTEST_FOR_ALL_CONTEXTS(SkSurfaceCharacterization, reporter, ctxInfo) {
SkDeferredDisplayListRecorder r(c);
SkCanvas* canvas = r.getCanvas();
if (!canvas) {
return;
}
canvas->drawRect(SkRect::MakeXYWH(10, 10, 10, 10), SkPaint());
ddl = r.detach();