Add a deferred copy surface (take 3)
This CL forces all GrSurface copies to go through a GrSurfaceContext (rather than GrContext). There is a bit of goofiness going on here until read/writePixels is also consolidated in GrSurfaceContext and a proxy-backed SkImage/SkSurface is added. This is a reland of https://skia-review.googlesource.com/c/5773/ (Add a deferred copy surface) Change-Id: Ib8fd96d0569274ef781366eb900ed8ee839ae9bd Reviewed-on: https://skia-review.googlesource.com/6109 Reviewed-by: Brian Salomon <bsalomon@google.com> Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: Robert Phillips <robertphillips@google.com>
This commit is contained in:
parent
db8f44f497
commit
e2f7d1899d
@ -14,7 +14,11 @@
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
#include "GrContext.h"
|
||||
#include "GrContextPriv.h"
|
||||
#include "GrSurfaceContext.h"
|
||||
#include "GrSurfaceProxy.h"
|
||||
#include "GrTexture.h"
|
||||
#include "GrTextureProxy.h"
|
||||
#include "../src/image/SkImage_Gpu.h"
|
||||
#endif
|
||||
|
||||
@ -209,15 +213,15 @@ class TextureGenerator : public SkImageGenerator {
|
||||
public:
|
||||
TextureGenerator(GrContext* ctx, const SkImageInfo& info, SkPicture* pic)
|
||||
: SkImageGenerator(info)
|
||||
, fCtx(SkRef(ctx))
|
||||
{
|
||||
auto surface(SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info));
|
||||
, fCtx(SkRef(ctx)) {
|
||||
|
||||
sk_sp<SkSurface> surface(SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info));
|
||||
if (surface) {
|
||||
surface->getCanvas()->clear(0);
|
||||
surface->getCanvas()->translate(-100, -100);
|
||||
surface->getCanvas()->drawPicture(pic);
|
||||
sk_sp<SkImage> image(surface->makeImageSnapshot());
|
||||
fTexture.reset(SkRef(as_IB(image)->peekTexture()));
|
||||
fProxy = GrSurfaceProxy::MakeWrapped(sk_ref_sp(as_IB(image)->peekTexture()));
|
||||
}
|
||||
}
|
||||
protected:
|
||||
@ -227,24 +231,45 @@ protected:
|
||||
SkASSERT(ctx == fCtx.get());
|
||||
}
|
||||
|
||||
if (!fTexture) {
|
||||
if (!fProxy) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (origin.fX == 0 && origin.fY == 0 &&
|
||||
info.width() == fProxy->width() && info.height() == fProxy->height()) {
|
||||
return SkSafeRef(fProxy->instantiate(fCtx->textureProvider())->asTexture());
|
||||
}
|
||||
|
||||
// need to copy the subset into a new texture
|
||||
GrSurfaceDesc desc = fTexture->desc();
|
||||
GrSurfaceDesc desc = fProxy->desc();
|
||||
desc.fWidth = info.width();
|
||||
desc.fHeight = info.height();
|
||||
|
||||
GrTexture* dst = fCtx->textureProvider()->createTexture(desc, SkBudgeted::kNo);
|
||||
fCtx->copySurface(dst, fTexture.get(),
|
||||
SkIRect::MakeXYWH(origin.x(), origin.y(), info.width(), info.height()),
|
||||
SkIPoint::Make(0, 0));
|
||||
return dst;
|
||||
sk_sp<GrSurfaceContext> dstContext(fCtx->contextPriv().makeDeferredSurfaceContext(
|
||||
desc,
|
||||
SkBackingFit::kExact,
|
||||
SkBudgeted::kNo));
|
||||
if (!dstContext) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!dstContext->copy(
|
||||
fProxy.get(),
|
||||
SkIRect::MakeXYWH(origin.x(), origin.y(), info.width(), info.height()),
|
||||
SkIPoint::Make(0, 0))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GrSurface* dstSurf = dstContext->asDeferredSurface()->instantiate(fCtx->textureProvider());
|
||||
if (!dstSurf) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return SkRef(dstSurf->asTexture());
|
||||
}
|
||||
private:
|
||||
sk_sp<GrContext> fCtx;
|
||||
sk_sp<GrTexture> fTexture;
|
||||
sk_sp<GrContext> fCtx;
|
||||
sk_sp<GrSurfaceProxy> fProxy;
|
||||
};
|
||||
static SkImageGenerator* make_tex_generator(GrContext* ctx, SkPicture* pic) {
|
||||
const SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);
|
||||
|
@ -300,25 +300,6 @@ public:
|
||||
size_t rowBytes,
|
||||
uint32_t pixelOpsFlags = 0);
|
||||
|
||||
/**
|
||||
* Copies a rectangle of texels from src to dst.
|
||||
* @param dst the surface to copy to.
|
||||
* @param src the surface to copy from.
|
||||
* @param srcRect the rectangle of the src that should be copied.
|
||||
* @param dstPoint the translation applied when writing the srcRect's pixels to the dst.
|
||||
*/
|
||||
bool copySurface(GrSurface* dst,
|
||||
GrSurface* src,
|
||||
const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint);
|
||||
|
||||
/** Helper that copies the whole surface but fails when the two surfaces are not identically
|
||||
sized. */
|
||||
bool copySurface(GrSurface* dst, GrSurface* src) {
|
||||
return this->copySurface(dst, src, SkIRect::MakeWH(dst->width(), dst->height()),
|
||||
SkIPoint::Make(0,0));
|
||||
}
|
||||
|
||||
/**
|
||||
* After this returns any pending writes to the surface will have been issued to the backend 3D API.
|
||||
*/
|
||||
|
@ -50,8 +50,6 @@ class SK_API GrRenderTargetContext : public GrSurfaceContext {
|
||||
public:
|
||||
~GrRenderTargetContext() override;
|
||||
|
||||
bool copySurface(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override;
|
||||
|
||||
// TODO: it is odd that we need both the SkPaint in the following 3 methods.
|
||||
// We should extract the text parameters from SkPaint and pass them separately
|
||||
// akin to GrStyle (GrTextInfo?)
|
||||
@ -469,6 +467,8 @@ private:
|
||||
const SkPath&,
|
||||
const GrStyle&);
|
||||
|
||||
bool onCopy(GrSurfaceProxy* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override;
|
||||
|
||||
// This entry point allows the GrTextContext-derived classes to add their ops to the GrOpList.
|
||||
void addDrawOp(const GrPipelineBuilder&, const GrClip&, sk_sp<GrDrawOp>);
|
||||
|
||||
|
@ -8,6 +8,8 @@
|
||||
#ifndef GrSurfaceContext_DEFINED
|
||||
#define GrSurfaceContext_DEFINED
|
||||
|
||||
#include "../private/GrSurfaceProxy.h"
|
||||
|
||||
#include "SkRefCnt.h"
|
||||
|
||||
class GrAuditTrail;
|
||||
@ -28,7 +30,27 @@ class SK_API GrSurfaceContext : public SkRefCnt {
|
||||
public:
|
||||
~GrSurfaceContext() override {}
|
||||
|
||||
virtual bool copySurface(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) = 0;
|
||||
/*
|
||||
* Copy 'src' into the proxy backing this context
|
||||
* @param src src of pixels
|
||||
* @param srcRect the subset of 'src' to copy
|
||||
* @param dstPoint the origin of the 'srcRect' in the destination coordinate space
|
||||
* @return true if the copy succeeded; false otherwise
|
||||
*
|
||||
* Note: Notionally, 'srcRect' is clipped to 'src's extent with 'dstPoint' being adjusted.
|
||||
* Then the 'srcRect' offset by 'dstPoint' is clipped against the dst's extent.
|
||||
* The end result is only valid src pixels and dst pixels will be touched but the copied
|
||||
* regions will not be shifted.
|
||||
*/
|
||||
bool copy(GrSurfaceProxy* src, const SkIRect& srcRect, const SkIPoint& dstPoint) {
|
||||
return this->onCopy(src, srcRect, dstPoint);
|
||||
}
|
||||
|
||||
bool copy(GrSurfaceProxy* src) {
|
||||
return this->onCopy(src,
|
||||
SkIRect::MakeWH(src->width(), src->height()),
|
||||
SkIPoint::Make(0, 0));
|
||||
}
|
||||
|
||||
// TODO: this is virtual b.c. this object doesn't have a pointer to the wrapped GrSurfaceProxy?
|
||||
virtual GrSurfaceProxy* asDeferredSurface() = 0;
|
||||
@ -55,6 +77,10 @@ protected:
|
||||
SkDEBUGCODE(mutable GrSingleOwner* fSingleOwner;)
|
||||
|
||||
private:
|
||||
virtual bool onCopy(GrSurfaceProxy* src,
|
||||
const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint) = 0;
|
||||
|
||||
typedef SkRefCnt INHERITED;
|
||||
};
|
||||
|
||||
|
@ -27,8 +27,6 @@ class SK_API GrTextureContext : public GrSurfaceContext {
|
||||
public:
|
||||
~GrTextureContext() override;
|
||||
|
||||
bool copySurface(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override;
|
||||
|
||||
GrSurfaceProxy* asDeferredSurface() override { return fTextureProxy.get(); }
|
||||
GrTextureProxy* asDeferredTexture() override { return fTextureProxy.get(); }
|
||||
GrRenderTargetProxy* asDeferredRenderTarget() override;
|
||||
@ -44,6 +42,8 @@ protected:
|
||||
private:
|
||||
friend class GrDrawingManager; // for ctor
|
||||
|
||||
bool onCopy(GrSurfaceProxy* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override;
|
||||
|
||||
GrTextureOpList* getOpList();
|
||||
|
||||
GrDrawingManager* fDrawingManager;
|
||||
@ -52,6 +52,8 @@ private:
|
||||
// In MDB-mode the GrOpList can be closed by some other renderTargetContext that has picked
|
||||
// it up. For this reason, the GrOpList should only ever be accessed via 'getOpList'.
|
||||
GrTextureOpList* fOpList;
|
||||
|
||||
typedef GrSurfaceContext INHERITED;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -53,6 +53,9 @@ public:
|
||||
|
||||
GrRenderTarget::Flags testingOnly_getFlags() const;
|
||||
|
||||
// TODO: move this to a priv class!
|
||||
bool refsWrappedObjects() const;
|
||||
|
||||
protected:
|
||||
friend class GrSurfaceProxy; // for ctors
|
||||
|
||||
|
@ -266,6 +266,20 @@ public:
|
||||
return fGpuMemorySize;
|
||||
}
|
||||
|
||||
// Helper function that creates a temporary SurfaceContext to perform the copy
|
||||
static sk_sp<GrSurfaceProxy> Copy(GrContext*, GrSurfaceProxy* src,
|
||||
SkIRect srcRect, SkBudgeted);
|
||||
|
||||
// Copy the entire 'src'
|
||||
static sk_sp<GrSurfaceProxy> Copy(GrContext* context, GrSurfaceProxy* src,
|
||||
SkBudgeted budgeted) {
|
||||
return Copy(context, src, SkIRect::MakeWH(src->width(), src->height()), budgeted);
|
||||
}
|
||||
|
||||
// Test-only entry point - should decrease in use as proxies propagate
|
||||
static sk_sp<GrSurfaceProxy> TestCopy(GrContext* context, const GrSurfaceDesc& dstDesc,
|
||||
GrTexture* srcTexture, SkBudgeted budgeted);
|
||||
|
||||
bool isWrapped_ForTesting() const;
|
||||
|
||||
SkDEBUGCODE(void validate(GrContext*) const;)
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
#include "GrContext.h"
|
||||
#include "GrSurfaceContext.h"
|
||||
#include "GrTexture.h"
|
||||
#include "GrSamplerParams.h"
|
||||
#include "GrTextureProxy.h"
|
||||
@ -346,6 +347,20 @@ sk_sp<SkSpecialImage> SkSpecialImage::MakeFromRaster(const SkIRect& subset,
|
||||
#include "GrTexture.h"
|
||||
#include "SkImage_Gpu.h"
|
||||
|
||||
static sk_sp<SkImage> wrap_proxy_in_image(GrContext* context, GrSurfaceProxy* proxy,
|
||||
SkAlphaType alphaType, sk_sp<SkColorSpace> colorSpace) {
|
||||
// TODO: add GrTextureProxy-backed SkImage_Gpus
|
||||
GrSurface* surf = proxy->instantiate(context->textureProvider());
|
||||
if (!surf) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return sk_make_sp<SkImage_Gpu>(proxy->width(), proxy->height(),
|
||||
kNeedNewImageUniqueID, alphaType,
|
||||
sk_ref_sp(surf->asTexture()),
|
||||
std::move(colorSpace), SkBudgeted::kYes);
|
||||
}
|
||||
|
||||
class SkSpecialImage_Gpu : public SkSpecialImage_Base {
|
||||
public:
|
||||
SkSpecialImage_Gpu(const SkIRect& subset,
|
||||
@ -478,34 +493,21 @@ public:
|
||||
fAlphaType);
|
||||
}
|
||||
|
||||
// TODO: move all the logic here into the subset-flavor GrSurfaceProxy::copy?
|
||||
sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
|
||||
// TODO: add GrTextureProxy-backed SkImage_Gpus
|
||||
GrSurface* surf = fSurfaceProxy->instantiate(fContext->textureProvider());
|
||||
if (!surf) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// TODO: this is problematic since the surfaceProxy could be loose
|
||||
if (0 == subset.fLeft && 0 == subset.fTop &&
|
||||
fSurfaceProxy->width() == subset.width() &&
|
||||
fSurfaceProxy->height() == subset.height()) {
|
||||
// The existing GrTexture is already tight so reuse it in the SkImage
|
||||
return sk_make_sp<SkImage_Gpu>(surf->width(), surf->height(),
|
||||
kNeedNewImageUniqueID, fAlphaType,
|
||||
sk_ref_sp(surf->asTexture()),
|
||||
fColorSpace, SkBudgeted::kYes);
|
||||
return wrap_proxy_in_image(fContext, fSurfaceProxy.get(),
|
||||
fAlphaType, fColorSpace);
|
||||
}
|
||||
|
||||
GrSurfaceDesc desc = fSurfaceProxy->desc();
|
||||
desc.fWidth = subset.width();
|
||||
desc.fHeight = subset.height();
|
||||
sk_sp<GrSurfaceProxy> subsetProxy(GrSurfaceProxy::Copy(fContext, fSurfaceProxy.get(),
|
||||
subset, SkBudgeted::kYes));
|
||||
|
||||
sk_sp<GrTexture> subTx(fContext->textureProvider()->createTexture(desc, SkBudgeted::kYes));
|
||||
if (!subTx) {
|
||||
return nullptr;
|
||||
}
|
||||
fContext->copySurface(subTx.get(), surf, subset, SkIPoint::Make(0, 0));
|
||||
return sk_make_sp<SkImage_Gpu>(desc.fWidth, desc.fHeight, kNeedNewImageUniqueID,
|
||||
fAlphaType, std::move(subTx), fColorSpace, SkBudgeted::kYes);
|
||||
return wrap_proxy_in_image(fContext, subsetProxy.get(), fAlphaType, fColorSpace);
|
||||
}
|
||||
|
||||
sk_sp<SkSurface> onMakeTightSurface(const SkImageFilter::OutputProperties& outProps,
|
||||
|
@ -540,43 +540,6 @@ void GrContext::prepareSurfaceForExternalIO(GrSurface* surface) {
|
||||
fDrawingManager->prepareSurfaceForExternalIO(surface);
|
||||
}
|
||||
|
||||
bool GrContext::copySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint) {
|
||||
ASSERT_SINGLE_OWNER
|
||||
RETURN_FALSE_IF_ABANDONED
|
||||
GR_AUDIT_TRAIL_AUTO_FRAME(&fAuditTrail, "GrContext::copySurface");
|
||||
|
||||
if (!src || !dst) {
|
||||
return false;
|
||||
}
|
||||
ASSERT_OWNED_RESOURCE(src);
|
||||
ASSERT_OWNED_RESOURCE(dst);
|
||||
|
||||
// We don't allow conversion between integer configs and float/fixed configs.
|
||||
if (GrPixelConfigIsSint(dst->config()) != GrPixelConfigIsSint(src->config())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef ENABLE_MDB
|
||||
// We can't yet fully defer copies to textures, so GrTextureContext::copySurface will
|
||||
// execute the copy immediately. Ensure the data is ready.
|
||||
src->flushWrites();
|
||||
#endif
|
||||
|
||||
sk_sp<GrSurfaceContext> surfaceContext(
|
||||
this->contextPriv().makeWrappedSurfaceContext(sk_ref_sp(dst)));
|
||||
|
||||
if (!surfaceContext) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!surfaceContext->copySurface(src, srcRect, dstPoint)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GrContext::flushSurfaceWrites(GrSurface* surface) {
|
||||
ASSERT_SINGLE_OWNER
|
||||
RETURN_IF_ABANDONED
|
||||
@ -593,23 +556,6 @@ void GrContext::flushSurfaceIO(GrSurface* surface) {
|
||||
}
|
||||
}
|
||||
|
||||
sk_sp<GrSurfaceContext> GrContextPriv::makeDeferredSurfaceContext(const GrSurfaceDesc& dstDesc,
|
||||
SkBackingFit fit,
|
||||
SkBudgeted isDstBudgeted) {
|
||||
|
||||
sk_sp<GrSurfaceProxy> proxy = GrSurfaceProxy::MakeDeferred(*fContext->caps(), dstDesc,
|
||||
fit, isDstBudgeted);
|
||||
|
||||
if (proxy->asRenderTargetProxy()) {
|
||||
return this->drawingManager()->makeRenderTargetContext(std::move(proxy), nullptr, nullptr);
|
||||
} else {
|
||||
SkASSERT(proxy->asTextureProxy());
|
||||
return this->drawingManager()->makeTextureContext(std::move(proxy));
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int GrContext::getRecommendedSampleCount(GrPixelConfig config,
|
||||
SkScalar dpi) const {
|
||||
@ -661,6 +607,16 @@ sk_sp<GrSurfaceContext> GrContextPriv::makeWrappedSurfaceContext(sk_sp<GrSurface
|
||||
return this->makeWrappedSurfaceContext(std::move(proxy));
|
||||
}
|
||||
|
||||
sk_sp<GrSurfaceContext> GrContextPriv::makeDeferredSurfaceContext(const GrSurfaceDesc& dstDesc,
|
||||
SkBackingFit fit,
|
||||
SkBudgeted isDstBudgeted) {
|
||||
|
||||
sk_sp<GrSurfaceProxy> proxy = GrSurfaceProxy::MakeDeferred(*fContext->caps(), dstDesc,
|
||||
fit, isDstBudgeted);
|
||||
|
||||
return this->makeWrappedSurfaceContext(std::move(proxy));
|
||||
}
|
||||
|
||||
sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendTextureRenderTargetContext(
|
||||
const GrBackendTextureDesc& desc,
|
||||
sk_sp<SkColorSpace> colorSpace,
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include "GrContext.h"
|
||||
#include "GrSurfaceContext.h"
|
||||
|
||||
class GrSurfaceProxy;
|
||||
|
||||
/** Class that adds methods to GrContext that are only intended for use internal to Skia.
|
||||
This class is purely a privileged window into GrContext. It should never have additional
|
||||
data members or virtual methods. */
|
||||
|
@ -133,12 +133,20 @@ GrRenderTargetOpList* GrRenderTargetContext::getOpList() {
|
||||
return fOpList;
|
||||
}
|
||||
|
||||
bool GrRenderTargetContext::copySurface(GrSurface* src, const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint) {
|
||||
// TODO: move this (and GrTextContext::copy) to GrSurfaceContext?
|
||||
bool GrRenderTargetContext::onCopy(GrSurfaceProxy* srcProxy,
|
||||
const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint) {
|
||||
ASSERT_SINGLE_OWNER
|
||||
RETURN_FALSE_IF_ABANDONED
|
||||
SkDEBUGCODE(this->validate();)
|
||||
GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::copySurface");
|
||||
GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::copy");
|
||||
|
||||
// TODO: defer instantiation until flush time
|
||||
sk_sp<GrSurface> src(sk_ref_sp(srcProxy->instantiate(fContext->textureProvider())));
|
||||
if (!src) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: this needs to be fixed up since it ends the deferrable of the GrRenderTarget
|
||||
sk_sp<GrRenderTarget> rt(
|
||||
@ -147,7 +155,7 @@ bool GrRenderTargetContext::copySurface(GrSurface* src, const SkIRect& srcRect,
|
||||
return false;
|
||||
}
|
||||
|
||||
return this->getOpList()->copySurface(rt.get(), src, srcRect, dstPoint);
|
||||
return this->getOpList()->copySurface(rt.get(), src.get(), srcRect, dstPoint);
|
||||
}
|
||||
|
||||
void GrRenderTargetContext::drawText(const GrClip& clip, const GrPaint& grPaint,
|
||||
|
@ -114,6 +114,10 @@ public:
|
||||
const GrUserStencilSettings* = nullptr,
|
||||
bool snapToCenters = false);
|
||||
|
||||
bool refsWrappedObjects() const {
|
||||
return fRenderTargetContext->fRenderTargetProxy->refsWrappedObjects();
|
||||
}
|
||||
|
||||
private:
|
||||
explicit GrRenderTargetContextPriv(GrRenderTargetContext* renderTargetContext)
|
||||
: fRenderTargetContext(renderTargetContext) {}
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "GrRenderTargetProxy.h"
|
||||
|
||||
#include "GrCaps.h"
|
||||
#include "GrGpuResourcePriv.h"
|
||||
#include "GrRenderTargetOpList.h"
|
||||
#include "GrRenderTargetPriv.h"
|
||||
#include "GrTextureProvider.h"
|
||||
@ -63,3 +64,10 @@ size_t GrRenderTargetProxy::onGpuMemorySize() const {
|
||||
return GrSurface::ComputeSize(fDesc, fDesc.fSampleCnt+1, false, SkBackingFit::kApprox == fFit);
|
||||
}
|
||||
|
||||
bool GrRenderTargetProxy::refsWrappedObjects() const {
|
||||
if (!fTarget) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return fTarget->resourcePriv().refsWrappedObjects();
|
||||
}
|
||||
|
@ -8,8 +8,11 @@
|
||||
#include "GrSurfaceProxy.h"
|
||||
|
||||
#include "GrCaps.h"
|
||||
#include "GrContext.h"
|
||||
#include "GrContextPriv.h"
|
||||
#include "GrGpuResourcePriv.h"
|
||||
#include "GrOpList.h"
|
||||
#include "GrSurfaceContext.h"
|
||||
#include "GrTextureProvider.h"
|
||||
#include "GrTextureRenderTargetProxy.h"
|
||||
|
||||
@ -161,3 +164,53 @@ void GrSurfaceProxy::validate(GrContext* context) const {
|
||||
INHERITED::validate();
|
||||
}
|
||||
#endif
|
||||
|
||||
sk_sp<GrSurfaceProxy> GrSurfaceProxy::Copy(GrContext* context,
|
||||
GrSurfaceProxy* src,
|
||||
SkIRect srcRect,
|
||||
SkBudgeted budgeted) {
|
||||
if (!srcRect.intersect(SkIRect::MakeWH(src->width(), src->height()))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GrSurfaceDesc dstDesc = src->desc();
|
||||
dstDesc.fWidth = srcRect.width();
|
||||
dstDesc.fHeight = srcRect.height();
|
||||
|
||||
sk_sp<GrSurfaceContext> dstContext(context->contextPriv().makeDeferredSurfaceContext(
|
||||
dstDesc,
|
||||
SkBackingFit::kExact,
|
||||
budgeted));
|
||||
if (!dstContext) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!dstContext->copy(src, srcRect, SkIPoint::Make(0, 0))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return sk_ref_sp(dstContext->asDeferredSurface());
|
||||
}
|
||||
|
||||
sk_sp<GrSurfaceProxy> GrSurfaceProxy::TestCopy(GrContext* context, const GrSurfaceDesc& dstDesc,
|
||||
GrTexture* srcTexture, SkBudgeted budgeted) {
|
||||
|
||||
sk_sp<GrSurfaceContext> dstContext(context->contextPriv().makeDeferredSurfaceContext(
|
||||
dstDesc,
|
||||
SkBackingFit::kExact,
|
||||
budgeted));
|
||||
if (!dstContext) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sk_sp<GrSurfaceProxy> srcProxy(GrSurfaceProxy::MakeWrapped(sk_ref_sp(srcTexture)));
|
||||
if (!srcProxy) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!dstContext->copy(srcProxy.get())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return sk_ref_sp(dstContext->asDeferredSurface());
|
||||
}
|
||||
|
@ -24,8 +24,7 @@ GrTextureContext::GrTextureContext(GrContext* context,
|
||||
: GrSurfaceContext(context, auditTrail, singleOwner)
|
||||
, fDrawingManager(drawingMgr)
|
||||
, fTextureProxy(std::move(textureProxy))
|
||||
, fOpList(SkSafeRef(fTextureProxy->getLastTextureOpList()))
|
||||
{
|
||||
, fOpList(SkSafeRef(fTextureProxy->getLastTextureOpList())) {
|
||||
SkDEBUGCODE(this->validate();)
|
||||
}
|
||||
|
||||
@ -62,12 +61,26 @@ GrTextureOpList* GrTextureContext::getOpList() {
|
||||
return fOpList;
|
||||
}
|
||||
|
||||
bool GrTextureContext::copySurface(GrSurface* src, const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint) {
|
||||
// TODO: move this (and GrRenderTargetContext::copy) to GrSurfaceContext?
|
||||
bool GrTextureContext::onCopy(GrSurfaceProxy* srcProxy,
|
||||
const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint) {
|
||||
ASSERT_SINGLE_OWNER
|
||||
RETURN_FALSE_IF_ABANDONED
|
||||
SkDEBUGCODE(this->validate();)
|
||||
GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrTextureContext::copySurface");
|
||||
GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrTextureContext::copy");
|
||||
|
||||
// TODO: defer instantiation until flush time
|
||||
sk_sp<GrSurface> src(sk_ref_sp(srcProxy->instantiate(fContext->textureProvider())));
|
||||
if (!src) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef ENABLE_MDB
|
||||
// We can't yet fully defer copies to textures, so GrTextureContext::copySurface will
|
||||
// execute the copy immediately. Ensure the data is ready.
|
||||
src->flushWrites();
|
||||
#endif
|
||||
|
||||
// TODO: this needs to be fixed up since it ends the deferrable of the GrTexture
|
||||
sk_sp<GrTexture> tex(sk_ref_sp(fTextureProxy->instantiate(fContext->textureProvider())));
|
||||
@ -76,7 +89,7 @@ bool GrTextureContext::copySurface(GrSurface* src, const SkIRect& srcRect,
|
||||
}
|
||||
|
||||
GrTextureOpList* opList = this->getOpList();
|
||||
bool result = opList->copySurface(tex.get(), src, srcRect, dstPoint);
|
||||
bool result = opList->copySurface(tex.get(), src.get(), srcRect, dstPoint);
|
||||
|
||||
#ifndef ENABLE_MDB
|
||||
GrOpFlushState flushState(fContext->getGpu(), nullptr);
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "GrRenderTargetContextPriv.h"
|
||||
#include "GrStyle.h"
|
||||
#include "GrTextureAdjuster.h"
|
||||
#include "GrTextureProxy.h"
|
||||
#include "GrTracing.h"
|
||||
|
||||
#include "SkCanvasPriv.h"
|
||||
@ -262,9 +263,7 @@ void SkGpuDevice::replaceRenderTargetContext(bool shouldRetainContent) {
|
||||
if (fRenderTargetContext->wasAbandoned()) {
|
||||
return;
|
||||
}
|
||||
newRTC->copySurface(fRenderTargetContext->asTexture().get(),
|
||||
SkIRect::MakeWH(this->width(), this->height()),
|
||||
SkIPoint::Make(0, 0));
|
||||
newRTC->copy(fRenderTargetContext->asDeferredSurface());
|
||||
}
|
||||
|
||||
fRenderTargetContext = newRTC;
|
||||
@ -1332,19 +1331,15 @@ sk_sp<SkSpecialImage> SkGpuDevice::makeSpecial(const SkImage* image) {
|
||||
}
|
||||
|
||||
sk_sp<SkSpecialImage> SkGpuDevice::snapSpecial() {
|
||||
sk_sp<GrTexture> texture(this->accessRenderTargetContext()->asTexture());
|
||||
if (!texture) {
|
||||
sk_sp<GrSurfaceProxy> sProxy(sk_ref_sp(this->accessRenderTargetContext()->asDeferredTexture()));
|
||||
if (!sProxy) {
|
||||
// When the device doesn't have a texture, we create a temporary texture.
|
||||
// TODO: we should actually only copy the portion of the source needed to apply the image
|
||||
// filter
|
||||
texture.reset(fContext->textureProvider()->createTexture(
|
||||
this->accessRenderTargetContext()->desc(), SkBudgeted::kYes));
|
||||
if (!texture) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!fContext->copySurface(texture.get(),
|
||||
this->accessRenderTargetContext()->accessRenderTarget())) {
|
||||
sProxy = GrSurfaceProxy::Copy(fContext.get(),
|
||||
this->accessRenderTargetContext()->asDeferredSurface(),
|
||||
SkBudgeted::kYes);
|
||||
if (!sProxy) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@ -1352,11 +1347,12 @@ sk_sp<SkSpecialImage> SkGpuDevice::snapSpecial() {
|
||||
const SkImageInfo ii = this->imageInfo();
|
||||
const SkIRect srcRect = SkIRect::MakeWH(ii.width(), ii.height());
|
||||
|
||||
return SkSpecialImage::MakeFromGpu(srcRect,
|
||||
kNeedNewImageUniqueID_SpecialImage,
|
||||
std::move(texture),
|
||||
sk_ref_sp(ii.colorSpace()),
|
||||
&this->surfaceProps());
|
||||
return SkSpecialImage::MakeDeferredFromGpu(fContext.get(),
|
||||
srcRect,
|
||||
kNeedNewImageUniqueID_SpecialImage,
|
||||
sProxy,
|
||||
sk_ref_sp(ii.colorSpace()),
|
||||
&this->surfaceProps());
|
||||
}
|
||||
|
||||
void SkGpuDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device,
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "GrBitmapTextureMaker.h"
|
||||
#include "GrCaps.h"
|
||||
#include "GrContext.h"
|
||||
#include "GrContextPriv.h"
|
||||
#include "GrImageTextureMaker.h"
|
||||
#include "GrRenderTargetContext.h"
|
||||
#include "GrTextureAdjuster.h"
|
||||
@ -153,13 +154,33 @@ sk_sp<SkImage> SkImage_Gpu::onMakeSubset(const SkIRect& subset) const {
|
||||
desc.fWidth = subset.width();
|
||||
desc.fHeight = subset.height();
|
||||
|
||||
sk_sp<GrTexture> subTx(ctx->textureProvider()->createTexture(desc, fBudgeted));
|
||||
sk_sp<GrSurfaceContext> sContext(ctx->contextPriv().makeDeferredSurfaceContext(
|
||||
desc,
|
||||
SkBackingFit::kExact,
|
||||
fBudgeted));
|
||||
if (!sContext) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// TODO: make gpu images be proxy-backed so we don't need to do this
|
||||
sk_sp<GrSurfaceProxy> tmpSrc(GrSurfaceProxy::MakeWrapped(fTexture));
|
||||
if (!tmpSrc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!sContext->copy(tmpSrc.get(), subset, SkIPoint::Make(0, 0))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// TODO: make gpu images be proxy-backed so we don't need to do this
|
||||
GrSurface* subTx = sContext->asDeferredSurface()->instantiate(ctx->textureProvider());
|
||||
if (!subTx) {
|
||||
return nullptr;
|
||||
}
|
||||
ctx->copySurface(subTx.get(), fTexture.get(), subset, SkIPoint::Make(0, 0));
|
||||
|
||||
return sk_make_sp<SkImage_Gpu>(desc.fWidth, desc.fHeight, kNeedNewImageUniqueID,
|
||||
fAlphaType, std::move(subTx), fColorSpace, fBudgeted);
|
||||
fAlphaType, sk_ref_sp(subTx->asTexture()),
|
||||
fColorSpace, fBudgeted);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "SkImage_Base.h"
|
||||
#include "SkImage_Gpu.h"
|
||||
#include "SkImagePriv.h"
|
||||
#include "GrRenderTargetContextPriv.h"
|
||||
#include "SkSurface_Base.h"
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
@ -82,29 +83,39 @@ sk_sp<SkSurface> SkSurface_Gpu::onNewSurface(const SkImageInfo& info) {
|
||||
}
|
||||
|
||||
sk_sp<SkImage> SkSurface_Gpu::onNewImageSnapshot(SkBudgeted budgeted, SkCopyPixelsMode cpm) {
|
||||
GrRenderTarget* rt = fDevice->accessRenderTargetContext()->accessRenderTarget();
|
||||
if (!rt) {
|
||||
GrRenderTargetContext* rtc = fDevice->accessRenderTargetContext();
|
||||
if (!rtc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GrTexture* tex = rt->asTexture();
|
||||
sk_sp<GrTexture> copy;
|
||||
GrContext* ctx = fDevice->context();
|
||||
|
||||
GrSurfaceProxy* srcProxy = rtc->asDeferredSurface();
|
||||
sk_sp<GrSurfaceContext> copyCtx;
|
||||
// If the original render target is a buffer originally created by the client, then we don't
|
||||
// want to ever retarget the SkSurface at another buffer we create. Force a copy now to avoid
|
||||
// copy-on-write.
|
||||
if (kAlways_SkCopyPixelsMode == cpm || !tex || rt->resourcePriv().refsWrappedObjects()) {
|
||||
GrSurfaceDesc desc = fDevice->accessRenderTargetContext()->desc();
|
||||
GrContext* ctx = fDevice->context();
|
||||
if (kAlways_SkCopyPixelsMode == cpm || !srcProxy || rtc->priv().refsWrappedObjects()) {
|
||||
GrSurfaceDesc desc = rtc->desc();
|
||||
desc.fFlags = desc.fFlags & ~kRenderTarget_GrSurfaceFlag;
|
||||
copy.reset(ctx->textureProvider()->createTexture(desc, budgeted));
|
||||
if (!copy) {
|
||||
|
||||
copyCtx = ctx->contextPriv().makeDeferredSurfaceContext(desc,
|
||||
SkBackingFit::kExact,
|
||||
budgeted);
|
||||
if (!copyCtx) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!ctx->copySurface(copy.get(), rt)) {
|
||||
|
||||
if (!copyCtx->copy(srcProxy)) {
|
||||
return nullptr;
|
||||
}
|
||||
tex = copy.get();
|
||||
|
||||
srcProxy = copyCtx->asDeferredSurface();
|
||||
}
|
||||
|
||||
// TODO: add proxy-backed SkImage_Gpu
|
||||
GrTexture* tex = srcProxy->instantiate(ctx->textureProvider())->asTexture();
|
||||
|
||||
const SkImageInfo info = fDevice->imageInfo();
|
||||
sk_sp<SkImage> image;
|
||||
if (tex) {
|
||||
|
@ -10,6 +10,9 @@
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
#include "GrContext.h"
|
||||
#include "GrContextPriv.h"
|
||||
#include "GrSurfaceContext.h"
|
||||
#include "GrSurfaceProxy.h"
|
||||
#include "GrTexture.h"
|
||||
#include "GrTextureProvider.h"
|
||||
|
||||
@ -68,22 +71,29 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(CopySurface, reporter, ctxInfo) {
|
||||
dstDesc.fOrigin = dOrigin;
|
||||
dstDesc.fFlags = dFlags;
|
||||
|
||||
sk_sp<GrTexture> src(
|
||||
context->textureProvider()->createTexture(srcDesc, SkBudgeted::kNo,
|
||||
srcPixels.get(),
|
||||
kRowBytes));
|
||||
sk_sp<GrTexture> dst(
|
||||
context->textureProvider()->createTexture(dstDesc, SkBudgeted::kNo,
|
||||
dstPixels.get(),
|
||||
kRowBytes));
|
||||
sk_sp<GrSurfaceProxy> src(GrSurfaceProxy::MakeDeferred(
|
||||
*context->caps(),
|
||||
context->textureProvider(),
|
||||
srcDesc, SkBudgeted::kNo,
|
||||
srcPixels.get(),
|
||||
kRowBytes));
|
||||
|
||||
sk_sp<GrSurfaceProxy> dst(GrSurfaceProxy::MakeDeferred(
|
||||
*context->caps(),
|
||||
context->textureProvider(),
|
||||
dstDesc, SkBudgeted::kNo,
|
||||
dstPixels.get(),
|
||||
kRowBytes));
|
||||
if (!src || !dst) {
|
||||
ERRORF(reporter,
|
||||
"Could not create surfaces for copy surface test.");
|
||||
continue;
|
||||
}
|
||||
|
||||
bool result
|
||||
= context->copySurface(dst.get(), src.get(), srcRect, dstPoint);
|
||||
sk_sp<GrSurfaceContext> sContext =
|
||||
context->contextPriv().makeWrappedSurfaceContext(dst);
|
||||
|
||||
bool result = sContext->copy(src.get(), srcRect, dstPoint);
|
||||
|
||||
bool expectedResult = true;
|
||||
SkIPoint dstOffset = { dstPoint.fX - srcRect.fLeft,
|
||||
@ -120,9 +130,11 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(CopySurface, reporter, ctxInfo) {
|
||||
continue;
|
||||
}
|
||||
|
||||
GrSurface* dstSurf = dst->instantiate(context->textureProvider());
|
||||
|
||||
sk_memset32(read.get(), 0, kW * kH);
|
||||
if (!dst->readPixels(0, 0, kW, kH, baseDesc.fConfig, read.get(),
|
||||
kRowBytes)) {
|
||||
if (!dstSurf->readPixels(0, 0, kW, kH, baseDesc.fConfig, read.get(),
|
||||
kRowBytes)) {
|
||||
ERRORF(reporter, "Error calling readPixels");
|
||||
continue;
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "GrContext.h"
|
||||
#include "GrContextFactory.h"
|
||||
#include "GrShaderCaps.h"
|
||||
#include "GrSurfaceContext.h"
|
||||
#include "gl/GrGLGpu.h"
|
||||
#include "gl/GrGLUtil.h"
|
||||
#include "gl/GLTestContext.h"
|
||||
@ -40,7 +41,7 @@ static void cleanup(GLTestContext* glctx0, GrGLuint texID0, GLTestContext* glctx
|
||||
}
|
||||
|
||||
static void test_read_pixels(skiatest::Reporter* reporter, GrContext* context,
|
||||
GrTexture* externalTexture, uint32_t expectedPixelValues[]) {
|
||||
GrSurface* externalTexture, uint32_t expectedPixelValues[]) {
|
||||
int pixelCnt = externalTexture->width() * externalTexture->height();
|
||||
SkAutoTMalloc<uint32_t> pixels(pixelCnt);
|
||||
memset(pixels.get(), 0, sizeof(uint32_t)*pixelCnt);
|
||||
@ -76,9 +77,13 @@ static void test_copy_surface(skiatest::Reporter* reporter, GrContext* context,
|
||||
copyDesc.fWidth = externalTexture->width();
|
||||
copyDesc.fHeight = externalTexture->height();
|
||||
copyDesc.fFlags = kRenderTarget_GrSurfaceFlag;
|
||||
sk_sp<GrTexture> copy(context->textureProvider()->createTexture(copyDesc, SkBudgeted::kYes));
|
||||
context->copySurface(copy.get(), externalTexture);
|
||||
test_read_pixels(reporter, context, copy.get(), expectedPixelValues);
|
||||
|
||||
sk_sp<GrSurfaceProxy> copy(GrSurfaceProxy::TestCopy(context, copyDesc,
|
||||
externalTexture, SkBudgeted::kYes));
|
||||
|
||||
GrSurface* copySurf = copy->instantiate(context->textureProvider());
|
||||
|
||||
test_read_pixels(reporter, context, copySurf, expectedPixelValues);
|
||||
}
|
||||
|
||||
DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(EGLImageTest, reporter, ctxInfo) {
|
||||
|
@ -9,6 +9,7 @@
|
||||
#if SK_SUPPORT_GPU
|
||||
|
||||
#include "GrContext.h"
|
||||
#include "GrContextPriv.h"
|
||||
#include "GrGpu.h"
|
||||
#include "GrTextureStripAtlas.h"
|
||||
#include "GrTypes.h"
|
||||
@ -21,51 +22,98 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrTextureStripAtlasFlush, reporter, ctxInfo)
|
||||
desc.fWidth = 32;
|
||||
desc.fHeight = 32;
|
||||
desc.fConfig = kRGBA_8888_GrPixelConfig;
|
||||
GrTexture* texture = context->textureProvider()->createTexture(desc, SkBudgeted::kYes,
|
||||
nullptr, 0);
|
||||
|
||||
GrSurfaceDesc targetDesc = desc;
|
||||
targetDesc.fFlags = kRenderTarget_GrSurfaceFlag;
|
||||
GrTexture* target = context->textureProvider()->createTexture(targetDesc, SkBudgeted::kYes,
|
||||
nullptr, 0);
|
||||
sk_sp<GrSurfaceProxy> srcProxy;
|
||||
|
||||
SkAutoTMalloc<uint32_t> pixels(desc.fWidth * desc.fHeight);
|
||||
memset(pixels.get(), 0xFF, sizeof(uint32_t) * desc.fWidth * desc.fHeight);
|
||||
texture->writePixels(0, 0, desc.fWidth, desc.fHeight, kRGBA_8888_GrPixelConfig, pixels.get());
|
||||
{
|
||||
SkAutoTMalloc<uint32_t> pixels(desc.fWidth * desc.fHeight);
|
||||
memset(pixels.get(), 0xFF, sizeof(uint32_t) * desc.fWidth * desc.fHeight);
|
||||
|
||||
// Add a pending read to the texture, and then make it available for reuse.
|
||||
context->copySurface(target, texture);
|
||||
texture->unref();
|
||||
srcProxy = GrSurfaceProxy::MakeDeferred(*context->caps(), context->textureProvider(),
|
||||
desc, SkBudgeted::kYes,
|
||||
pixels.get(), 0);
|
||||
}
|
||||
|
||||
// Add a pending read to the src texture, and then make it available for reuse.
|
||||
sk_sp<GrSurfaceProxy> targetProxy;
|
||||
GrSurface* srcSurface;
|
||||
|
||||
{
|
||||
GrSurfaceDesc targetDesc = desc;
|
||||
targetDesc.fFlags = kRenderTarget_GrSurfaceFlag;
|
||||
|
||||
// We can't use GrSurfaceProxy::Copy bc we may be changing the dst proxy type
|
||||
sk_sp<GrSurfaceContext> dstContext(context->contextPriv().makeDeferredSurfaceContext(
|
||||
targetDesc,
|
||||
SkBackingFit::kExact,
|
||||
SkBudgeted::kYes));
|
||||
REPORTER_ASSERT(reporter, dstContext);
|
||||
|
||||
if (!dstContext->copy(srcProxy.get())) {
|
||||
return;
|
||||
}
|
||||
|
||||
targetProxy = sk_ref_sp(dstContext->asDeferredSurface());
|
||||
|
||||
srcSurface = srcProxy->instantiate(context->textureProvider());
|
||||
srcProxy.reset();
|
||||
}
|
||||
|
||||
// Create an atlas with parameters that allow it to reuse the texture.
|
||||
GrTextureStripAtlas::Desc atlasDesc;
|
||||
atlasDesc.fContext = context;
|
||||
atlasDesc.fConfig = desc.fConfig;
|
||||
atlasDesc.fWidth = desc.fWidth;
|
||||
atlasDesc.fHeight = desc.fHeight;
|
||||
atlasDesc.fRowHeight = 1;
|
||||
GrTextureStripAtlas* atlas = GrTextureStripAtlas::GetAtlas(atlasDesc);
|
||||
GrTextureStripAtlas* atlas;
|
||||
|
||||
{
|
||||
GrTextureStripAtlas::Desc atlasDesc;
|
||||
atlasDesc.fContext = context;
|
||||
atlasDesc.fConfig = desc.fConfig;
|
||||
atlasDesc.fWidth = desc.fWidth;
|
||||
atlasDesc.fHeight = desc.fHeight;
|
||||
atlasDesc.fRowHeight = 1;
|
||||
atlas = GrTextureStripAtlas::GetAtlas(atlasDesc);
|
||||
}
|
||||
|
||||
// Write to the atlas' texture.
|
||||
SkImageInfo info = SkImageInfo::MakeN32(desc.fWidth, desc.fHeight, kPremul_SkAlphaType);
|
||||
size_t rowBytes = desc.fWidth * GrBytesPerPixel(desc.fConfig);
|
||||
SkBitmap bitmap;
|
||||
bitmap.allocPixels(info, rowBytes);
|
||||
memset(bitmap.getPixels(), 1, rowBytes * desc.fHeight);
|
||||
int row = atlas->lockRow(bitmap);
|
||||
if (!context->caps()->preferVRAMUseOverFlushes())
|
||||
REPORTER_ASSERT(reporter, texture == atlas->getTexture());
|
||||
int lockedRow;
|
||||
|
||||
{
|
||||
SkImageInfo info = SkImageInfo::MakeN32(desc.fWidth, desc.fHeight, kPremul_SkAlphaType);
|
||||
size_t rowBytes = desc.fWidth * GrBytesPerPixel(desc.fConfig);
|
||||
SkBitmap bitmap;
|
||||
bitmap.allocPixels(info, rowBytes);
|
||||
memset(bitmap.getPixels(), 1, rowBytes * desc.fHeight);
|
||||
lockedRow = atlas->lockRow(bitmap);
|
||||
}
|
||||
|
||||
// The atlas' use of its texture shouldn't change which pixels got copied to the target.
|
||||
SkAutoTMalloc<uint32_t> actualPixels(desc.fWidth * desc.fHeight);
|
||||
bool success = target->readPixels(0, 0, desc.fWidth, desc.fHeight, kRGBA_8888_GrPixelConfig,
|
||||
actualPixels.get());
|
||||
REPORTER_ASSERT(reporter, success);
|
||||
REPORTER_ASSERT(reporter,
|
||||
!memcmp(pixels.get(), actualPixels.get(),
|
||||
sizeof(uint32_t) * desc.fWidth * desc.fHeight));
|
||||
target->unref();
|
||||
atlas->unlockRow(row);
|
||||
{
|
||||
SkAutoTMalloc<uint8_t> actualPixels(sizeof(uint32_t) * desc.fWidth * desc.fHeight);
|
||||
|
||||
// TODO: move readPixels to GrSurfaceProxy?
|
||||
GrSurface* surf = targetProxy->instantiate(context->textureProvider());
|
||||
|
||||
bool success = surf->readPixels(0, 0, desc.fWidth, desc.fHeight,
|
||||
kRGBA_8888_GrPixelConfig, actualPixels.get());
|
||||
REPORTER_ASSERT(reporter, success);
|
||||
|
||||
bool good = true;
|
||||
|
||||
const uint8_t* bytes = actualPixels.get();
|
||||
for (size_t i = 0; i < sizeof(uint32_t) * desc.fWidth * desc.fHeight; ++i, ++bytes) {
|
||||
if (0xFF != *bytes) {
|
||||
good = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
REPORTER_ASSERT(reporter, good);
|
||||
}
|
||||
|
||||
if (!context->caps()->preferVRAMUseOverFlushes()) {
|
||||
// This is kindof dodgy since we released it!
|
||||
REPORTER_ASSERT(reporter, srcSurface == atlas->getTexture());
|
||||
}
|
||||
|
||||
atlas->unlockRow(lockedRow);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -95,40 +95,48 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(IntTexture, reporter, ctxInfo) {
|
||||
REPORTER_ASSERT(reporter, !success);
|
||||
|
||||
// Test that copying from one integer texture to another succeeds.
|
||||
sk_sp<GrTexture> copy(context->textureProvider()->createTexture(desc, SkBudgeted::kYes));
|
||||
REPORTER_ASSERT(reporter, copy);
|
||||
if (!copy) {
|
||||
return;
|
||||
}
|
||||
success = context->copySurface(copy.get(), texture.get());
|
||||
REPORTER_ASSERT(reporter, success);
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
sk_bzero(readData.get(), sizeof(int32_t) * kS * kS);
|
||||
success = texture->readPixels(0, 0, kS, kS, kRGBA_8888_sint_GrPixelConfig, readData.get());
|
||||
REPORTER_ASSERT(reporter, success);
|
||||
if (success) {
|
||||
check_pixels(reporter, kS, kS, testData.get(), readData.get());
|
||||
{
|
||||
sk_sp<GrSurfaceProxy> copy(GrSurfaceProxy::TestCopy(context, desc,
|
||||
texture.get(), SkBudgeted::kYes));
|
||||
REPORTER_ASSERT(reporter, copy);
|
||||
if (!copy) {
|
||||
return;
|
||||
}
|
||||
|
||||
GrSurface* copySurface = copy->instantiate(context->textureProvider());
|
||||
REPORTER_ASSERT(reporter, copySurface);
|
||||
if (!copySurface) {
|
||||
return;
|
||||
}
|
||||
|
||||
sk_bzero(readData.get(), sizeof(int32_t) * kS * kS);
|
||||
success = copySurface->readPixels(0, 0, kS, kS,
|
||||
kRGBA_8888_sint_GrPixelConfig, readData.get());
|
||||
REPORTER_ASSERT(reporter, success);
|
||||
if (success) {
|
||||
check_pixels(reporter, kS, kS, testData.get(), readData.get());
|
||||
}
|
||||
}
|
||||
|
||||
// Test that copying to a non-integer texture fails.
|
||||
GrSurfaceDesc nonIntDesc = desc;
|
||||
nonIntDesc.fConfig = kRGBA_8888_GrPixelConfig;
|
||||
copy.reset(context->textureProvider()->createTexture(nonIntDesc, SkBudgeted::kYes));
|
||||
REPORTER_ASSERT(reporter, copy);
|
||||
if (!copy) {
|
||||
return;
|
||||
|
||||
// Test that copying to a non-integer (8888) texture fails.
|
||||
{
|
||||
GrSurfaceDesc nonIntDesc = desc;
|
||||
nonIntDesc.fConfig = kRGBA_8888_GrPixelConfig;
|
||||
|
||||
sk_sp<GrSurfaceProxy> copy(GrSurfaceProxy::TestCopy(context, nonIntDesc,
|
||||
texture.get(), SkBudgeted::kYes));
|
||||
REPORTER_ASSERT(reporter, !copy);
|
||||
}
|
||||
success = context->copySurface(copy.get(), texture.get());
|
||||
REPORTER_ASSERT(reporter, !success);
|
||||
nonIntDesc.fConfig = kRGBA_half_GrPixelConfig;
|
||||
copy.reset(context->textureProvider()->createTexture(nonIntDesc, SkBudgeted::kYes));
|
||||
REPORTER_ASSERT(reporter, copy ||
|
||||
!context->caps()->isConfigTexturable(kRGBA_half_GrPixelConfig));
|
||||
if (copy) {
|
||||
success = context->copySurface(copy.get(), texture.get());
|
||||
REPORTER_ASSERT(reporter, !success);
|
||||
|
||||
// Test that copying to a non-integer (RGBA_half) texture fails.
|
||||
if (context->caps()->isConfigTexturable(kRGBA_half_GrPixelConfig)) {
|
||||
GrSurfaceDesc nonIntDesc = desc;
|
||||
nonIntDesc.fConfig = kRGBA_half_GrPixelConfig;
|
||||
|
||||
sk_sp<GrSurfaceProxy> copy(GrSurfaceProxy::TestCopy(context, nonIntDesc,
|
||||
texture.get(), SkBudgeted::kYes));
|
||||
REPORTER_ASSERT(reporter, !copy);
|
||||
}
|
||||
|
||||
// We overwrite the top left quarter of the texture with the bottom right quarter of the
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include "gl/GLTestContext.h"
|
||||
|
||||
static void test_read_pixels(skiatest::Reporter* reporter, GrContext* context,
|
||||
GrTexture* texture, uint32_t expectedPixelValues[]) {
|
||||
GrSurface* texture, uint32_t expectedPixelValues[]) {
|
||||
int pixelCnt = texture->width() * texture->height();
|
||||
SkAutoTMalloc<uint32_t> pixels(pixelCnt);
|
||||
memset(pixels.get(), 0, sizeof(uint32_t)*pixelCnt);
|
||||
@ -52,22 +52,30 @@ static void test_write_pixels(skiatest::Reporter* reporter, GrContext* context,
|
||||
}
|
||||
|
||||
static void test_copy_surface_src(skiatest::Reporter* reporter, GrContext* context,
|
||||
GrTexture* rectangleTexture, uint32_t expectedPixelValues[]) {
|
||||
GrTexture* rectTexture, uint32_t expectedPixelValues[]) {
|
||||
GrSurfaceDesc copyDstDesc;
|
||||
copyDstDesc.fConfig = kRGBA_8888_GrPixelConfig;
|
||||
copyDstDesc.fWidth = rectTexture->width();
|
||||
copyDstDesc.fHeight = rectTexture->height();
|
||||
|
||||
for (auto flags : {kNone_GrSurfaceFlags, kRenderTarget_GrSurfaceFlag}) {
|
||||
GrSurfaceDesc copyDstDesc;
|
||||
copyDstDesc.fConfig = kRGBA_8888_GrPixelConfig;
|
||||
copyDstDesc.fWidth = rectangleTexture->width();
|
||||
copyDstDesc.fHeight = rectangleTexture->height();
|
||||
copyDstDesc.fFlags = flags;
|
||||
sk_sp<GrTexture> dst(
|
||||
context->textureProvider()->createTexture(copyDstDesc, SkBudgeted::kYes));
|
||||
context->copySurface(dst.get(), rectangleTexture);
|
||||
test_read_pixels(reporter, context, dst.get(), expectedPixelValues);
|
||||
|
||||
sk_sp<GrSurfaceProxy> dst(GrSurfaceProxy::TestCopy(context, copyDstDesc,
|
||||
rectTexture, SkBudgeted::kYes));
|
||||
|
||||
GrSurface* dstSurf = dst->instantiate(context->textureProvider());
|
||||
|
||||
test_read_pixels(reporter, context, dstSurf, expectedPixelValues);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_copy_surface_dst(skiatest::Reporter* reporter, GrContext* context,
|
||||
GrTexture* rectangleTexture) {
|
||||
|
||||
sk_sp<GrSurfaceContext> sContext(context->contextPriv().makeWrappedSurfaceContext(
|
||||
sk_ref_sp(rectangleTexture)));
|
||||
|
||||
int pixelCnt = rectangleTexture->width() * rectangleTexture->height();
|
||||
SkAutoTMalloc<uint32_t> pixels(pixelCnt);
|
||||
for (int y = 0; y < rectangleTexture->width(); ++y) {
|
||||
@ -81,10 +89,13 @@ static void test_copy_surface_dst(skiatest::Reporter* reporter, GrContext* conte
|
||||
copySrcDesc.fWidth = rectangleTexture->width();
|
||||
copySrcDesc.fHeight = rectangleTexture->height();
|
||||
copySrcDesc.fFlags = flags;
|
||||
sk_sp<GrTexture> src(context->textureProvider()->createTexture(
|
||||
copySrcDesc, SkBudgeted::kYes, pixels.get(), 0));
|
||||
|
||||
context->copySurface(rectangleTexture, src.get());
|
||||
sk_sp<GrSurfaceProxy> src(GrSurfaceProxy::MakeDeferred(*context->caps(),
|
||||
context->textureProvider(),
|
||||
copySrcDesc,
|
||||
SkBudgeted::kYes, pixels.get(), 0));
|
||||
sContext->copy(src.get());
|
||||
|
||||
test_read_pixels(reporter, context, rectangleTexture, pixels.get());
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user