Require budget decision when creating a RenderTarget SkSurface.

Restructure SkGpuDevice creation:
*SkSurfaceProps are optional.
*Use SkSurfaceProps to communicate DF text rather than a flag.
*Tell SkGpuDevice::Create whether RT comes from cache or not.

Review URL: https://codereview.chromium.org/848903004
This commit is contained in:
bsalomon 2015-01-16 07:32:33 -08:00 committed by Commit bot
parent b50ced7030
commit afe3005be3
29 changed files with 233 additions and 217 deletions

View File

@ -388,7 +388,8 @@ static Target* is_enabled(Benchmark* bench, const Config& config) {
else if (Benchmark::kGPU_Backend == config.backend) {
uint32_t flags = config.useDFText ? SkSurfaceProps::kUseDistanceFieldFonts_Flag : 0;
SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType);
target->surface.reset(SkSurface::NewRenderTarget(gGrFactory->get(config.ctxType), info,
target->surface.reset(SkSurface::NewRenderTarget(gGrFactory->get(config.ctxType),
SkSurface::kNo_Budgeted, info,
config.samples, &props));
target->gl = gGrFactory->getGLContext(config.ctxType);
}

View File

@ -25,7 +25,8 @@ static inline SkSurface* NewGpuSurface(GrContextFactory* grFactory,
bool useDFText) {
uint32_t flags = useDFText ? SkSurfaceProps::kUseDistanceFieldFonts_Flag : 0;
SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType);
return SkSurface::NewRenderTarget(grFactory->get(type, gpuAPI), info, samples, &props);
return SkSurface::NewRenderTarget(grFactory->get(type, gpuAPI), SkSurface::kNo_Budgeted,
info, samples, &props);
}
} // namespace DM

View File

@ -46,3 +46,6 @@ dropshadowimagefilter
# fmalita - rebaseline for http://crbug.com/447707
pictureshader
# bsalomon slight change to image-surface GM on gpu
image-surface

View File

@ -68,7 +68,8 @@ protected:
SkImageInfo info = SkImageInfo::MakeN32Premul(onISize());
SkSurfaceProps props(SkSurfaceProps::kUseDistanceFieldFonts_Flag,
SkSurfaceProps::kLegacyFontHost_InitType);
SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(ctx, info, 0, &props));
SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(ctx, SkSurface::kNo_Budgeted,
info, 0, &props));
SkCanvas* canvas = surface.get() ? surface->getCanvas() : inputCanvas;
// init our new canvas with the old canvas's matrix
canvas->setMatrix(inputCanvas->getTotalMatrix());

View File

@ -46,7 +46,7 @@ protected:
size.fWidth /= 10;
size.fHeight /= 10;
SkImageInfo info = SkImageInfo::MakeN32Premul(size);
SkSurface* surface = SkSurface::NewRenderTarget(context, info);
SkSurface* surface = SkSurface::NewRenderTarget(context, SkSurface::kNo_Budgeted, info);
if (NULL == surface) {
return;

View File

@ -177,7 +177,8 @@ protected:
#if SK_SUPPORT_GPU
GrContext* ctx = canvas->getGrContext();
SkAutoTUnref<SkSurface> surf4(SkSurface::NewRenderTarget(ctx, info));
SkAutoTUnref<SkSurface> surf4(SkSurface::NewRenderTarget(
ctx, SkSurface::kNo_Budgeted, info));
#endif
test_surface(canvas, surf0, true);

View File

@ -33,7 +33,7 @@ static SkSurface* make_surface(GrContext* ctx, const SkImageInfo& info, SkPixelG
SkSurfaceProps props(flags, geo);
if (ctx) {
return SkSurface::NewRenderTarget(ctx, info, 0, &props);
return SkSurface::NewRenderTarget(ctx, SkSurface::kNo_Budgeted, info, 0, &props);
} else {
return SkSurface::NewRaster(info, &props);
}

View File

@ -125,18 +125,13 @@ private:
SkCanvas* tempCanvas = NULL;
#if SK_SUPPORT_GPU
GrContext* context = baseCanvas->getGrContext();
if (context) {
GrSurfaceDesc desc;
desc.fWidth = w;
desc.fHeight = h;
desc.fConfig = SkImageInfo2GrPixelConfig(baseCanvas->imageInfo());
desc.fFlags = kRenderTarget_GrSurfaceFlag;
SkAutoTUnref<GrSurface> surface(context->createUncachedTexture(desc, NULL, 0));
SkAutoTUnref<SkBaseDevice> device(SkGpuDevice::Create(surface.get(),
SkSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType)));
if (device.get()) {
tempCanvas = SkNEW_ARGS(SkCanvas, (device.get()));
}
SkImageInfo baseInfo = baseCanvas->imageInfo();
SkImageInfo info = SkImageInfo::Make(w, h, baseInfo.colorType(), baseInfo.alphaType(),
baseInfo.profileType());
SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(context, SkSurface::kNo_Budgeted,
info, 0, NULL));
if (surface) {
tempCanvas = SkRef(surface->getCanvas());
}
#endif
return tempCanvas;

View File

@ -32,6 +32,18 @@ class SK_API SkSurface : public SkRefCnt {
public:
SK_DECLARE_INST_COUNT(SkSurface)
/**
* Indicates whether a new surface or image should count against a cache budget. Currently this
* is only used by the GPU backend (sw-raster surfaces and images are never counted against the
* resource cache budget.)
*/
enum Budgeted {
/** The surface or image does not count against the cache budget. */
kNo_Budgeted,
/** The surface or image counts against the cache budget. */
kYes_Budgeted
};
/**
* Create a new surface, using the specified pixels/rowbytes as its
* backend.
@ -86,30 +98,27 @@ public:
* Return a new surface whose contents will be drawn to an offscreen
* render target, allocated by the surface.
*/
static SkSurface* NewRenderTarget(GrContext*, const SkImageInfo&, int sampleCount,
static SkSurface* NewRenderTarget(GrContext*, Budgeted, const SkImageInfo&, int sampleCount,
const SkSurfaceProps* = NULL);
static SkSurface* NewRenderTarget(GrContext* gr, const SkImageInfo& info) {
return NewRenderTarget(gr, info, 0, NULL);
static SkSurface* NewRenderTarget(GrContext* gr, Budgeted b, const SkImageInfo& info) {
return NewRenderTarget(gr, b, info, 0, NULL);
}
/**
* Return a new surface whose contents will be drawn to an offscreen
* render target, allocated by the surface from the scratch texture pool
* managed by the GrContext. The scratch texture pool serves the purpose
* of retaining textures after they are no longer in use in order to
* re-use them later without having to re-allocate. Scratch textures
* should be used in cases where high turnover is expected. This allows,
* for example, the copy on write to recycle a texture from a recently
* released SkImage snapshot of the surface.
* Note: Scratch textures count against the GrContext's cached resource
* budget.
* Deprecated - use the Budgeted param on NewRenderTarget.
*/
static SkSurface* NewScratchRenderTarget(GrContext*, const SkImageInfo&, int sampleCount,
const SkSurfaceProps* = NULL);
static SkSurface* NewScratchRenderTarget(GrContext* gr, const SkImageInfo& info,
int sampleCount, const SkSurfaceProps* props) {
return NewRenderTarget(gr, kYes_Budgeted, info, sampleCount, props);
}
static SkSurface* NewScratchRenderTarget(GrContext* gr, const SkImageInfo& info) {
return NewScratchRenderTarget(gr, info, 0, NULL);
/**
* Deprecated - use the version that takes a Budgeted param.
*/
static SkSurface* NewRenderTarget(GrContext* gr, const SkImageInfo& info, int sampleCount,
const SkSurfaceProps* props) {
return NewRenderTarget(gr, kNo_Budgeted, info, sampleCount, props);
}
int width() const { return fWidth; }

View File

@ -262,6 +262,7 @@ private:
bool setContentKey(const GrResourceKey& contentKey);
void notifyIsPurgable() const;
void removeScratchKey();
void makeBudgeted();
#ifdef SK_DEBUG
friend class GrGpu; // for assert in GrGpu to access getGpu

View File

@ -6,7 +6,6 @@
* found in the LICENSE file.
*/
#include "GrGpuResource.h"
#include "GrResourceCache2.h"
#include "GrGpu.h"
@ -134,6 +133,13 @@ void GrGpuResource::removeScratchKey() {
}
}
void GrGpuResource::makeBudgeted() {
if (GrGpuResource::kUncached_LifeCycle == fLifeCycle) {
fLifeCycle = kCached_LifeCycle;
get_resource_cache2(fGpu)->resourceAccess().didChangeBudgetStatus(this);
}
}
uint32_t GrGpuResource::CreateUniqueID() {
static int32_t gUniqueID = SK_InvalidUniqueID;
uint32_t id;

View File

@ -69,6 +69,12 @@ public:
*/
bool isBudgeted() const { return GrGpuResource::kCached_LifeCycle == fResource->fLifeCycle; }
/**
* If the resource is uncached make it cached. Has no effect on resources that are wrapped or
* already cached.
*/
void makeBudgeted() { fResource->makeBudgeted(); }
/**
* Called by the cache to delete the resource under normal circumstances.
*/

View File

@ -306,6 +306,10 @@ void GrResourceCache2::didChangeBudgetStatus(GrGpuResource* resource) {
if (resource->cacheAccess().isBudgeted()) {
++fBudgetedCount;
fBudgetedBytes += size;
#if GR_CACHE_STATS
fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes);
fBudgetedHighWaterCount = SkTMax(fBudgetedCount, fBudgetedHighWaterCount);
#endif
this->purgeAsNeeded();
} else {
--fBudgetedCount;

View File

@ -48,8 +48,6 @@
enum { kDefaultImageFilterCacheSize = 32 * 1024 * 1024 };
#define CACHE_COMPATIBLE_DEVICE_TEXTURES 1
#if 0
extern bool (*gShouldDrawProc)();
#define CHECK_SHOULD_DRAW(draw) \
@ -68,8 +66,8 @@ enum { kDefaultImageFilterCacheSize = 32 * 1024 * 1024 };
#define DO_DEFERRED_CLEAR() \
do { \
if (fFlags & kNeedClear_Flag) { \
this->clearAll(); \
if (fNeedClear) { \
this->clearAll(); \
} \
} while (false) \
@ -124,56 +122,71 @@ public:
///////////////////////////////////////////////////////////////////////////////
SkGpuDevice* SkGpuDevice::Create(GrSurface* surface, const SkSurfaceProps& props, unsigned flags) {
SkASSERT(surface);
if (NULL == surface->asRenderTarget() || surface->wasDestroyed()) {
SkGpuDevice* SkGpuDevice::Create(GrRenderTarget* rt, const SkSurfaceProps* props, unsigned flags) {
if (!rt || rt->wasDestroyed()) {
return NULL;
}
return SkNEW_ARGS(SkGpuDevice, (surface, props, flags));
return SkNEW_ARGS(SkGpuDevice, (rt, props, flags));
}
static SkDeviceProperties surfaceprops_to_deviceprops(const SkSurfaceProps& props) {
return SkDeviceProperties(props.pixelGeometry());
static SkDeviceProperties surfaceprops_to_deviceprops(const SkSurfaceProps* props) {
if (props) {
return SkDeviceProperties(props->pixelGeometry());
} else {
return SkDeviceProperties(SkDeviceProperties::kLegacyLCD_InitType);
}
}
SkGpuDevice::SkGpuDevice(GrSurface* surface, const SkSurfaceProps& props, unsigned flags)
static SkSurfaceProps copy_or_default_props(const SkSurfaceProps* props) {
if (props) {
return SkSurfaceProps(*props);
} else {
return SkSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType);
}
}
SkGpuDevice::SkGpuDevice(GrRenderTarget* rt, const SkSurfaceProps* props, unsigned flags)
: INHERITED(surfaceprops_to_deviceprops(props))
, fSurfaceProps(copy_or_default_props(props))
{
fDrawProcs = NULL;
fContext = SkRef(surface->getContext());
fContext = SkRef(rt->getContext());
fNeedClear = flags & kNeedClear_Flag;
fFlags = flags;
fRenderTarget = SkRef(rt);
fRenderTarget = SkRef(surface->asRenderTarget());
SkImageInfo info = surface->surfacePriv().info();
SkPixelRef* pr = SkNEW_ARGS(SkGrPixelRef, (info, surface));
SkImageInfo info = rt->surfacePriv().info();
SkPixelRef* pr = SkNEW_ARGS(SkGrPixelRef, (info, rt));
fLegacyBitmap.setInfo(info);
fLegacyBitmap.setPixelRef(pr)->unref();
bool useDFT = SkToBool(flags & kDFText_Flag);
bool useDFT = fSurfaceProps.isUseDistanceFieldFonts();
fTextContext = fContext->createTextContext(fRenderTarget, this->getLeakyProperties(), useDFT);
}
SkGpuDevice* SkGpuDevice::Create(GrContext* context, const SkImageInfo& origInfo,
const SkSurfaceProps& props, int sampleCount) {
SkGpuDevice* SkGpuDevice::Create(GrContext* context, SkSurface::Budgeted budgeted,
const SkImageInfo& origInfo, int sampleCount,
const SkSurfaceProps* props, unsigned flags) {
if (kUnknown_SkColorType == origInfo.colorType() ||
origInfo.width() < 0 || origInfo.height() < 0) {
return NULL;
}
if (!context) {
return NULL;
}
SkColorType ct = origInfo.colorType();
SkAlphaType at = origInfo.alphaType();
// TODO: perhaps we can loosen this check now that colortype is more detailed
// e.g. can we support both RGBA and BGRA here?
if (kRGB_565_SkColorType == ct) {
at = kOpaque_SkAlphaType; // force this setting
} else {
} else if (ct != kBGRA_8888_SkColorType && ct != kRGBA_8888_SkColorType) {
// Fall back from whatever ct was to default of kRGBA or kBGRA which is aliased as kN32
ct = kN32_SkColorType;
if (kOpaque_SkAlphaType != at) {
at = kPremul_SkAlphaType; // force this setting
}
}
if (kOpaque_SkAlphaType != at) {
at = kPremul_SkAlphaType; // force this setting
}
const SkImageInfo info = SkImageInfo::Make(origInfo.width(), origInfo.height(), ct, at);
@ -184,12 +197,18 @@ SkGpuDevice* SkGpuDevice::Create(GrContext* context, const SkImageInfo& origInfo
desc.fConfig = SkImageInfo2GrPixelConfig(info);
desc.fSampleCnt = sampleCount;
SkAutoTUnref<GrTexture> texture(context->createUncachedTexture(desc, NULL, 0));
if (!texture.get()) {
SkAutoTUnref<GrTexture> texture;
if (SkSurface::kYes_Budgeted == budgeted) {
texture.reset(context->refScratchTexture(desc, GrContext::kExact_ScratchTexMatch));
} else {
texture.reset(context->createUncachedTexture(desc, NULL, 0));
}
if (!texture) {
return NULL;
}
return SkNEW_ARGS(SkGpuDevice, (texture.get(), props));
return SkNEW_ARGS(SkGpuDevice, (texture->asRenderTarget(), props, flags));
}
SkGpuDevice::~SkGpuDevice() {
@ -295,7 +314,7 @@ void SkGpuDevice::clearAll() {
GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::clearAll", fContext);
SkIRect rect = SkIRect::MakeWH(this->width(), this->height());
fContext->clear(&rect, color, true, fRenderTarget);
fFlags &= ~kNeedClear_Flag;
fNeedClear = false;
}
///////////////////////////////////////////////////////////////////////////////
@ -1517,7 +1536,7 @@ void SkGpuDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device,
// clear of the source device must occur before CHECK_SHOULD_DRAW
GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawDevice", fContext);
SkGpuDevice* dev = static_cast<SkGpuDevice*>(device);
if (dev->fFlags & kNeedClear_Flag) {
if (fNeedClear) {
// TODO: could check here whether we really need to draw at all
dev->clearAll();
}
@ -1800,21 +1819,17 @@ SkBaseDevice* SkGpuDevice::onCreateCompatibleDevice(const CreateInfo& cinfo) {
SkAutoTUnref<GrTexture> texture;
// Skia's convention is to only clear a device if it is non-opaque.
unsigned flags = cinfo.fInfo.isOpaque() ? 0 : kNeedClear_Flag;
// If we're using distance field text, enable in the new device
flags |= (fFlags & kDFText_Flag) ? kDFText_Flag : 0;
#if CACHE_COMPATIBLE_DEVICE_TEXTURES
// layers are never draw in repeat modes, so we can request an approx
// match and ignore any padding.
const GrContext::ScratchTexMatch match = (kSaveLayer_Usage == cinfo.fUsage) ?
GrContext::kApprox_ScratchTexMatch :
GrContext::kExact_ScratchTexMatch;
texture.reset(fContext->refScratchTexture(desc, match));
#else
texture.reset(fContext->createUncachedTexture(desc, NULL, 0));
#endif
if (texture.get()) {
return SkGpuDevice::Create(texture, SkSurfaceProps(0, cinfo.fPixelGeometry), flags);
if (texture) {
SkSurfaceProps props(fSurfaceProps.flags(), cinfo.fPixelGeometry);
return SkGpuDevice::Create(texture->asRenderTarget(), &props, flags);
} else {
SkDebugf("---- failed to create compatible device texture [%d %d]\n",
cinfo.fInfo.width(), cinfo.fInfo.height());
@ -1823,7 +1838,10 @@ SkBaseDevice* SkGpuDevice::onCreateCompatibleDevice(const CreateInfo& cinfo) {
}
SkSurface* SkGpuDevice::newSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
return SkSurface::NewRenderTarget(fContext, info, fRenderTarget->numSamples(), &props);
// TODO: Change the signature of newSurface to take a budgeted parameter.
static const SkSurface::Budgeted kBudgeted = SkSurface::kNo_Budgeted;
return SkSurface::NewRenderTarget(fContext, kBudgeted, info, fRenderTarget->numSamples(),
&props);
}
bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* mainCanvas, const SkPicture* mainPicture,

View File

@ -6,8 +6,6 @@
* found in the LICENSE file.
*/
#ifndef SkGpuDevice_DEFINED
#define SkGpuDevice_DEFINED
@ -16,6 +14,7 @@
#include "SkDevice.h"
#include "SkPicture.h"
#include "SkRegion.h"
#include "SkSurface.h"
#include "GrContext.h"
#include "GrSurfacePriv.h"
@ -34,25 +33,20 @@ class SK_API SkGpuDevice : public SkBaseDevice {
public:
enum Flags {
kNeedClear_Flag = 1 << 0, //!< Surface requires an initial clear
kDFText_Flag = 1 << 1, //!< Surface should render text using signed distance fields
};
/**
* Creates an SkGpuDevice from a GrSurface. This will fail if the surface is not a render
* target. The caller owns a ref on the returned device. If the surface is cached,
* the kCached_Flag should be specified to make the device responsible for unlocking
* the surface when it is released.
* Creates an SkGpuDevice from a GrRenderTarget.
*/
static SkGpuDevice* Create(GrSurface* surface, const SkSurfaceProps&, unsigned flags = 0);
static SkGpuDevice* Create(GrRenderTarget* target, const SkSurfaceProps*, unsigned flags = 0);
/**
* New device that will create an offscreen renderTarget based on the
* ImageInfo and sampleCount. The device's storage will not
* count against the GrContext's texture cache budget. The device's pixels
* will be uninitialized. On failure, returns NULL.
* New device that will create an offscreen renderTarget based on the ImageInfo and
* sampleCount. The Budgeted param controls whether the device's backing store counts against
* the resource cache budget. On failure, returns NULL.
*/
static SkGpuDevice* Create(GrContext*, const SkImageInfo&, const SkSurfaceProps&,
int sampleCount);
static SkGpuDevice* Create(GrContext*, SkSurface::Budgeted, const SkImageInfo&,
int sampleCount, const SkSurfaceProps*, unsigned flags = 0);
virtual ~SkGpuDevice();
@ -63,7 +57,7 @@ public:
return static_cast<SkGpuDevice*>(dev);
}
GrContext* context() const { return fContext; }
GrContext* context() const { return fRenderTarget->getContext(); }
// set all pixels to 0
void clearAll();
@ -74,6 +68,8 @@ public:
return fRenderTarget ? fRenderTarget->surfacePriv().info() : SkImageInfo::MakeUnknown();
}
const SkSurfaceProps& surfaceProps() const { return fSurfaceProps; }
void drawPaint(const SkDraw&, const SkPaint& paint) SK_OVERRIDE;
virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode, size_t count,
const SkPoint[], const SkPaint& paint) SK_OVERRIDE;
@ -139,21 +135,16 @@ protected:
private:
GrContext* fContext;
GrSkDrawProcs* fDrawProcs;
GrClipData fClipData;
GrTextContext* fTextContext;
// state for our render-target
SkSurfaceProps fSurfaceProps;
GrRenderTarget* fRenderTarget;
uint32_t fFlags;
// remove when our clients don't rely on accessBitmap()
SkBitmap fLegacyBitmap;
SkBitmap fLegacyBitmap;
bool fNeedClear;
SkGpuDevice(GrSurface*, const SkSurfaceProps&, unsigned flags = 0);
SkGpuDevice(GrRenderTarget*, const SkSurfaceProps*, unsigned flags);
SkBaseDevice* onCreateCompatibleDevice(const CreateInfo&) SK_OVERRIDE;

View File

@ -69,7 +69,9 @@ void SkImage_Gpu::onDrawRect(SkCanvas* canvas, const SkRect* src, const SkRect&
SkSurface* SkImage_Gpu::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) const {
GrContext* ctx = this->getTexture()->getContext();
return SkSurface::NewRenderTarget(ctx, info, fSampleCountForNewSurfaces, &props);
// TODO: Change signature of onNewSurface to take a budgeted param.
static const SkSurface::Budgeted kBudgeted = SkSurface::kNo_Budgeted;
return SkSurface::NewRenderTarget(ctx, kBudgeted, info, fSampleCountForNewSurfaces, &props);
}
GrTexture* SkImage_Gpu::onGetTexture() const {

View File

@ -183,13 +183,10 @@ SkSurface* SkSurface::NewRenderTargetDirect(GrRenderTarget*, const SkSurfaceProp
return NULL;
}
SkSurface* SkSurface::NewRenderTarget(GrContext*, const SkImageInfo&, int, const SkSurfaceProps*) {
SkSurface* SkSurface::NewRenderTarget(GrContext*, Budgeted, const SkImageInfo&, int,
const SkSurfaceProps*) {
return NULL;
}
SkSurface* SkSurface::NewScratchRenderTarget(GrContext*, const SkImageInfo&, int sampleCount,
const SkSurfaceProps*) {
return NULL;
}
#endif

View File

@ -5,27 +5,22 @@
* found in the LICENSE file.
*/
#include "SkSurface_Base.h"
#include "SkImagePriv.h"
#include "SkImage_Base.h"
#include "SkSurface_Gpu.h"
#include "GrGpuResourceCacheAccess.h"
#include "SkCanvas.h"
#include "SkGpuDevice.h"
#include "SkSurface_Gpu.h"
#include "SkImage_Base.h"
#include "SkImagePriv.h"
#include "SkSurface_Base.h"
#if SK_SUPPORT_GPU
///////////////////////////////////////////////////////////////////////////////
SkSurface_Gpu::SkSurface_Gpu(GrRenderTarget* renderTarget, const SkSurfaceProps* props,
bool doClear)
: INHERITED(renderTarget->width(), renderTarget->height(), props) {
int deviceFlags = 0;
deviceFlags |= this->props().isUseDistanceFieldFonts() ? SkGpuDevice::kDFText_Flag : 0;
fDevice = SkGpuDevice::Create(renderTarget, this->props(), deviceFlags);
if (kRGB_565_GrPixelConfig != renderTarget->config() && doClear) {
fDevice->clearAll();
}
SkSurface_Gpu::SkSurface_Gpu(SkGpuDevice* device)
: INHERITED(device->width(), device->height(), &device->surfaceProps())
, fDevice(SkRef(device)) {
}
SkSurface_Gpu::~SkSurface_Gpu() {
@ -43,7 +38,10 @@ SkCanvas* SkSurface_Gpu::onNewCanvas() {
SkSurface* SkSurface_Gpu::onNewSurface(const SkImageInfo& info) {
GrRenderTarget* rt = fDevice->accessRenderTarget();
int sampleCount = rt->numSamples();
return SkSurface::NewRenderTarget(fDevice->context(), info, sampleCount, &this->props());
// TODO: Make caller specify this (change virtual signature of onNewSurface).
static const Budgeted kBudgeted = kNo_Budgeted;
return SkSurface::NewRenderTarget(fDevice->context(), kBudgeted, info, sampleCount,
&this->props());
}
SkImage* SkSurface_Gpu::onNewImageSnapshot() {
@ -68,19 +66,26 @@ void SkSurface_Gpu::onCopyOnWrite(ContentChangeMode mode) {
// are we sharing our render target with the image?
SkASSERT(this->getCachedImage());
if (rt->asTexture() == SkTextureImageGetTexture(this->getCachedImage())) {
// We call createCompatibleDevice because it uses the texture cache. This isn't
// necessarily correct (http://skbug.com/2252), but never using the cache causes
// a Chromium regression. (http://crbug.com/344020)
SkGpuDevice* newDevice = fDevice->cloneDevice(this->props());
SkAutoTUnref<SkGpuDevice> aurd(newDevice);
if (kRetain_ContentChangeMode == mode) {
fDevice->context()->copySurface(newDevice->accessRenderTarget(), rt->asTexture());
GrRenderTarget* oldRT = this->fDevice->accessRenderTarget();
SkSurface::Budgeted budgeted = oldRT->cacheAccess().isBudgeted() ? kYes_Budgeted :
kNo_Budgeted;
SkAutoTUnref<SkGpuDevice> newDevice(
SkGpuDevice::Create(oldRT->getContext(), budgeted, fDevice->imageInfo(),
oldRT->numSamples(), &this->props(), 0));
if (kRetain_ContentChangeMode == mode && !oldRT->wasDestroyed() && newDevice) {
oldRT->getContext()->copySurface(newDevice->accessRenderTarget(), oldRT);
}
SkASSERT(this->getCachedCanvas());
SkASSERT(this->getCachedCanvas()->getDevice() == fDevice);
this->getCachedCanvas()->setRootDevice(newDevice);
SkRefCnt_SafeAssign(fDevice, newDevice);
SkRefCnt_SafeAssign(fDevice, newDevice.get());
// For now we always treat the image snapshots as budgeted. We could make newImageSnapshot
// take a Budgeted param.
oldRT->cacheAccess().makeBudgeted();
} else if (kDiscard_ContentChangeMode == mode) {
this->SkSurface_Gpu::onDiscard();
}
@ -93,53 +98,21 @@ void SkSurface_Gpu::onDiscard() {
///////////////////////////////////////////////////////////////////////////////
SkSurface* SkSurface::NewRenderTargetDirect(GrRenderTarget* target, const SkSurfaceProps* props) {
if (NULL == target) {
SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(target, props));
if (!device) {
return NULL;
}
return SkNEW_ARGS(SkSurface_Gpu, (target, props, false));
return SkNEW_ARGS(SkSurface_Gpu, (device));
}
SkSurface* SkSurface::NewRenderTarget(GrContext* ctx, const SkImageInfo& info, int sampleCount,
const SkSurfaceProps* props) {
if (NULL == ctx) {
SkSurface* SkSurface::NewRenderTarget(GrContext* ctx, Budgeted budgeted, const SkImageInfo& info,
int sampleCount, const SkSurfaceProps* props) {
SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(ctx, budgeted, info, sampleCount, props,
SkGpuDevice::kNeedClear_Flag));
if (!device) {
return NULL;
}
GrSurfaceDesc desc;
desc.fFlags = kRenderTarget_GrSurfaceFlag | kCheckAllocation_GrSurfaceFlag;
desc.fWidth = info.width();
desc.fHeight = info.height();
desc.fConfig = SkImageInfo2GrPixelConfig(info);
desc.fSampleCnt = sampleCount;
SkAutoTUnref<GrTexture> tex(ctx->createUncachedTexture(desc, NULL, 0));
if (NULL == tex) {
return NULL;
}
return SkNEW_ARGS(SkSurface_Gpu, (tex->asRenderTarget(), props, true));
}
SkSurface* SkSurface::NewScratchRenderTarget(GrContext* ctx, const SkImageInfo& info,
int sampleCount, const SkSurfaceProps* props) {
if (NULL == ctx) {
return NULL;
}
GrSurfaceDesc desc;
desc.fFlags = kRenderTarget_GrSurfaceFlag | kCheckAllocation_GrSurfaceFlag;
desc.fWidth = info.width();
desc.fHeight = info.height();
desc.fConfig = SkImageInfo2GrPixelConfig(info);
desc.fSampleCnt = sampleCount;
SkAutoTUnref<GrTexture> tex(ctx->refScratchTexture(desc, GrContext::kExact_ScratchTexMatch));
if (NULL == tex) {
return NULL;
}
return SkNEW_ARGS(SkSurface_Gpu, (tex->asRenderTarget(), props, true));
return SkNEW_ARGS(SkSurface_Gpu, (device));
}
#endif

View File

@ -18,7 +18,7 @@ class SkSurface_Gpu : public SkSurface_Base {
public:
SK_DECLARE_INST_COUNT(SkSurface_Gpu)
SkSurface_Gpu(GrRenderTarget*, const SkSurfaceProps*, bool doClear);
SkSurface_Gpu(SkGpuDevice*);
virtual ~SkSurface_Gpu();
SkCanvas* onNewCanvas() SK_OVERRIDE;

View File

@ -698,7 +698,8 @@ static void TestDeferredCanvasSurface(skiatest::Reporter* reporter, GrContextFac
return;
}
surface = SkSurface::NewRenderTarget(context, imageSpec, 0, NULL);
surface =
SkSurface::NewRenderTarget(context, SkSurface::kNo_Budgeted, imageSpec, 0, NULL);
} else
#endif
{
@ -780,8 +781,10 @@ static void TestDeferredCanvasSetSurface(skiatest::Reporter* reporter, GrContext
if (NULL == context) {
continue;
}
surface = SkSurface::NewRenderTarget(context, imageSpec, 0, NULL);
alternateSurface = SkSurface::NewRenderTarget(context, imageSpec, 0, NULL);
surface =
SkSurface::NewRenderTarget(context, SkSurface::kNo_Budgeted, imageSpec, 0, NULL);
alternateSurface =
SkSurface::NewRenderTarget(context, SkSurface::kNo_Budgeted, imageSpec, 0, NULL);
} else
#endif
{

View File

@ -56,8 +56,9 @@ DEF_GPUTEST(GpuDrawPath, reporter, factory) {
for (size_t i = 0; i < SK_ARRAY_COUNT(sampleCounts); ++i) {
SkImageInfo info = SkImageInfo::MakeN32Premul(255, 255);
SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(grContext, info,
sampleCounts[i], NULL));
SkAutoTUnref<SkSurface> surface(
SkSurface::NewRenderTarget(grContext, SkSurface::kNo_Budgeted, info,
sampleCounts[i], NULL));
test_drawPathEmpty(reporter, surface->getCanvas());
}
}

View File

@ -1074,36 +1074,40 @@ const SkSurfaceProps gProps = SkSurfaceProps(SkSurfaceProps::kLegacyFontHost_Ini
DEF_GPUTEST(ImageFilterCropRectGPU, reporter, factory) {
GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(0));
SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context,
SkSurface::kNo_Budgeted,
SkImageInfo::MakeN32Premul(100, 100),
gProps,
0));
0,
&gProps));
test_crop_rects(device, reporter);
}
DEF_GPUTEST(HugeBlurImageFilterGPU, reporter, factory) {
GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(0));
SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context,
SkSurface::kNo_Budgeted,
SkImageInfo::MakeN32Premul(100, 100),
gProps,
0));
0,
&gProps));
test_huge_blur(device, reporter);
}
DEF_GPUTEST(XfermodeImageFilterCroppedInputGPU, reporter, factory) {
GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(0));
SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context,
SkSurface::kNo_Budgeted,
SkImageInfo::MakeN32Premul(1, 1),
gProps,
0));
0,
&gProps));
test_xfermode_cropped_input(device, reporter);
}
DEF_GPUTEST(TestNegativeBlurSigmaGPU, reporter, factory) {
GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(0));
SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context,
SkSurface::kNo_Budgeted,
SkImageInfo::MakeN32Premul(1, 1),
gProps,
0));
0,
&gProps));
test_negative_blur_sigma(device, reporter);
}
#endif

View File

@ -80,11 +80,13 @@ DEF_GPUTEST(ImageIsOpaqueTest_GPU, reporter, factory) {
}
SkImageInfo infoTransparent = SkImageInfo::MakeN32Premul(5, 5);
SkAutoTUnref<SkSurface> surfaceTransparent(SkSurface::NewRenderTarget(context, infoTransparent));
SkAutoTUnref<SkSurface> surfaceTransparent(
SkSurface::NewRenderTarget(context,SkSurface::kNo_Budgeted, infoTransparent));
check_isopaque(reporter, surfaceTransparent, false);
SkImageInfo infoOpaque = SkImageInfo::MakeN32(5, 5, kOpaque_SkAlphaType);
SkAutoTUnref<SkSurface> surfaceOpaque(SkSurface::NewRenderTarget(context, infoOpaque));
SkAutoTUnref<SkSurface> surfaceOpaque(
SkSurface::NewRenderTarget(context,SkSurface::kNo_Budgeted, infoOpaque));
#if 0
// this is failing right now : TODO fix me
check_isopaque(reporter, surfaceOpaque, true);

View File

@ -115,8 +115,10 @@ DEF_TEST(ImageNewShader, reporter) {
void gpuToGpu(skiatest::Reporter* reporter, GrContext* context) {
SkImageInfo info = SkImageInfo::MakeN32Premul(5, 5);
SkAutoTUnref<SkSurface> sourceSurface(SkSurface::NewRenderTarget(context, info));
SkAutoTUnref<SkSurface> destinationSurface(SkSurface::NewRenderTarget(context, info));
SkAutoTUnref<SkSurface> sourceSurface(
SkSurface::NewRenderTarget(context, SkSurface::kNo_Budgeted, info));
SkAutoTUnref<SkSurface> destinationSurface(
SkSurface::NewRenderTarget(context, SkSurface::kNo_Budgeted, info));
runShaderTest(reporter, sourceSurface.get(), destinationSurface.get(), info);
}
@ -124,7 +126,8 @@ void gpuToGpu(skiatest::Reporter* reporter, GrContext* context) {
void gpuToRaster(skiatest::Reporter* reporter, GrContext* context) {
SkImageInfo info = SkImageInfo::MakeN32Premul(5, 5);
SkAutoTUnref<SkSurface> sourceSurface(SkSurface::NewRenderTarget(context, info));
SkAutoTUnref<SkSurface> sourceSurface(SkSurface::NewRenderTarget(context,
SkSurface::kNo_Budgeted, info));
SkAutoTUnref<SkSurface> destinationSurface(SkSurface::NewRaster(info));
runShaderTest(reporter, sourceSurface.get(), destinationSurface.get(), info);
@ -134,7 +137,8 @@ void rasterToGpu(skiatest::Reporter* reporter, GrContext* context) {
SkImageInfo info = SkImageInfo::MakeN32Premul(5, 5);
SkAutoTUnref<SkSurface> sourceSurface(SkSurface::NewRaster(info));
SkAutoTUnref<SkSurface> destinationSurface(SkSurface::NewRenderTarget(context, info));
SkAutoTUnref<SkSurface> destinationSurface(SkSurface::NewRenderTarget(context,
SkSurface::kNo_Budgeted, info));
runShaderTest(reporter, sourceSurface.get(), destinationSurface.get(), info);
}

View File

@ -85,13 +85,12 @@ DEF_GPUTEST(PremulAlphaRoundTrip, reporter, factory) {
if (!GrContextFactory::IsRenderingGLContext(type)) {
continue;
}
GrContext* context = factory->get(type);
if (NULL == context) {
GrContext* ctx = factory->get(type);
if (NULL == ctx) {
continue;
}
device.reset(SkGpuDevice::Create(context, info,
SkSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType), 0));
SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
device.reset(SkGpuDevice::Create(ctx, SkSurface::kNo_Budgeted, info, 0, &props));
#else
continue;
#endif

View File

@ -82,8 +82,8 @@ DEF_GPUTEST(ReadWriteAlpha, reporter, factory) {
REPORTER_ASSERT(reporter, match);
// Now try writing on the single channel texture
SkAutoTUnref<SkBaseDevice> device(SkGpuDevice::Create(texture->asRenderTarget(),
SkSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType)));
SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
SkAutoTUnref<SkBaseDevice> device(SkGpuDevice::Create(texture->asRenderTarget(), &props));
SkCanvas canvas(device);
SkPaint paint;

View File

@ -797,7 +797,8 @@ DEF_GPUTEST(ResourceCache, reporter, factory) {
desc.fWidth = gWidth;
desc.fHeight = gHeight;
SkImageInfo info = SkImageInfo::MakeN32Premul(gWidth, gHeight);
SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(context, info));
SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(context,
SkSurface::kNo_Budgeted, info));
test_cache(reporter, context, surface->getCanvas());
}

View File

@ -50,15 +50,9 @@ static SkSurface* createSurface(SurfaceType surfaceType, GrContext* context,
release_storage, storage);
}
case kGpu_SurfaceType:
#if SK_SUPPORT_GPU
return context ? SkSurface::NewRenderTarget(context, info, 0, NULL) : NULL;
#endif
break;
return SkSurface::NewRenderTarget(context, SkSurface::kNo_Budgeted, info, 0, NULL);
case kGpuScratch_SurfaceType:
#if SK_SUPPORT_GPU
return context ? SkSurface::NewScratchRenderTarget(context, info) : NULL;
#endif
break;
return SkSurface::NewRenderTarget(context, SkSurface::kYes_Budgeted, info, 0, NULL);
}
return NULL;
}
@ -94,8 +88,8 @@ static void test_empty_surface(skiatest::Reporter* reporter, GrContext* ctx) {
REPORTER_ASSERT(reporter, NULL == SkSurface::NewRaster(info));
REPORTER_ASSERT(reporter, NULL == SkSurface::NewRasterDirect(info, NULL, 0));
if (ctx) {
REPORTER_ASSERT(reporter, NULL == SkSurface::NewRenderTarget(ctx, info, 0, NULL));
REPORTER_ASSERT(reporter, NULL == SkSurface::NewScratchRenderTarget(ctx, info, 0, NULL));
REPORTER_ASSERT(reporter, NULL ==
SkSurface::NewRenderTarget(ctx, SkSurface::kNo_Budgeted, info, 0, NULL));
}
}
@ -129,7 +123,8 @@ static SkImage* createImage(ImageType imageType, GrContext* context, SkColor col
case kRasterData_ImageType:
return SkImage::NewRasterData(info, data, rowBytes);
case kGpu_ImageType: {
SkAutoTUnref<SkSurface> surf(SkSurface::NewRenderTarget(context, info, 0));
SkAutoTUnref<SkSurface> surf(
SkSurface::NewRenderTarget(context, SkSurface::kNo_Budgeted, info, 0));
surf->getCanvas()->clear(color);
return surf->newImageSnapshot();
}

View File

@ -157,16 +157,14 @@ SkCanvas* PictureRenderer::setupCanvas(int width, int height) {
desc.fSampleCnt = fSampleCount;
target.reset(fGrContext->createUncachedTexture(desc, NULL, 0));
}
if (NULL == target.get()) {
SkASSERT(0);
uint32_t flags = fUseDFText ? SkSurfaceProps::kUseDistanceFieldFonts_Flag : 0;
SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType);
SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(target->asRenderTarget(), &props));
if (!device) {
return NULL;
}
uint32_t flags = fUseDFText ? SkGpuDevice::kDFText_Flag : 0;
SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(target,
SkSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType),
flags));
canvas = SkNEW_ARGS(SkCanvas, (device.get()));
canvas = SkNEW_ARGS(SkCanvas, (device));
break;
}
#endif