Revert "Migrate uses of deferred proxies to lazy proxies"

This reverts commit 990a0d8b65.

Reason for revert: Keeping it. Deferred proxies are uploaded later than lazy and we want that for this use case.

Original change's description:
> Migrate uses of deferred proxies to lazy proxies
>
> A follow-up CL removes the deferred proxies system entirely.
>
> Bug: skia:11288
> Change-Id: Ic5b3ce820ea946f6ae27bd763c0f389caf8863d1
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/366716
> Reviewed-by: Brian Salomon <bsalomon@google.com>
> Commit-Queue: Adlai Holler <adlai@google.com>

TBR=bsalomon@google.com,robertphillips@google.com,adlai@google.com

# Not skipping CQ checks because original CL landed > 1 day ago.

Bug: skia:11288
Change-Id: I9ced532d013805afae3b20baa53cab31cae2b953
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/368797
Reviewed-by: Adlai Holler <adlai@google.com>
Commit-Queue: Adlai Holler <adlai@google.com>
This commit is contained in:
Adlai Holler 2021-02-10 13:58:34 +00:00 committed by Skia Commit-Bot
parent 4908a24d4b
commit cc25d53420
8 changed files with 217 additions and 181 deletions

View File

@ -22,6 +22,7 @@
struct SkIRect;
class GrTexture;
class SkDiscardableMemory;
/** \class SkPixelRef

View File

@ -19,7 +19,7 @@ class GrBitmapTextureMaker final : public GrTextureMaker {
public:
GrBitmapTextureMaker(GrRecordingContext*, const SkBitmap&, GrImageTexGenPolicy);
// Always uncached-budgeted. It doesn't make sense to have kApprox cached textures. Moreover, we
// Always uncached-budgeted. It doesn't make sense to have kApprox cached textures. Moreover,we
// create kApprox textures intermediate buffers and those ought to be budgeted.
GrBitmapTextureMaker(GrRecordingContext*, const SkBitmap&, SkBackingFit);

View File

@ -317,19 +317,62 @@ static GrSurfaceProxyView render_sw_mask(GrRecordingContext* context, const SkIR
const GrClipStack::Element** elements, int count) {
SkASSERT(count > 0);
SkTArray<GrClipStack::Element> data(count);
for (int i = 0; i < count; ++i) {
data.push_back(*(elements[i]));
SkTaskGroup* taskGroup = nullptr;
if (auto direct = context->asDirectContext()) {
taskGroup = direct->priv().getTaskGroup();
}
return GrSWMaskHelper::MakeTexture(bounds,
context,
SkBackingFit::kApprox,
[data{std::move(data)}](GrSWMaskHelper* helper) {
TRACE_EVENT0("skia.gpu", "SW Clip Mask Render");
for (int i = 0; i < data.count(); ++i) {
draw_to_sw_mask(helper, data[i], i == 0);
if (taskGroup) {
const GrCaps* caps = context->priv().caps();
GrProxyProvider* proxyProvider = context->priv().proxyProvider();
// Create our texture proxy
GrBackendFormat format = caps->getDefaultBackendFormat(GrColorType::kAlpha_8,
GrRenderable::kNo);
GrSwizzle swizzle = context->priv().caps()->getReadSwizzle(format, GrColorType::kAlpha_8);
auto proxy = proxyProvider->createProxy(format, bounds.size(), GrRenderable::kNo, 1,
GrMipMapped::kNo, SkBackingFit::kApprox,
SkBudgeted::kYes, GrProtected::kNo);
// Since this will be rendered on another thread, make a copy of the elements in case
// the clip stack is modified on the main thread
using Uploader = GrTDeferredProxyUploader<SkTArray<GrClipStack::Element>>;
std::unique_ptr<Uploader> uploader = std::make_unique<Uploader>(count);
for (int i = 0; i < count; ++i) {
uploader->data().push_back(*(elements[i]));
}
});
Uploader* uploaderRaw = uploader.get();
auto drawAndUploadMask = [uploaderRaw, bounds] {
TRACE_EVENT0("skia.gpu", "Threaded SW Clip Mask Render");
GrSWMaskHelper helper(uploaderRaw->getPixels());
if (helper.init(bounds)) {
for (int i = 0; i < uploaderRaw->data().count(); ++i) {
draw_to_sw_mask(&helper, uploaderRaw->data()[i], i == 0);
}
} else {
SkDEBUGFAIL("Unable to allocate SW clip mask.");
}
uploaderRaw->signalAndFreeData();
};
taskGroup->add(std::move(drawAndUploadMask));
proxy->texPriv().setDeferredUploader(std::move(uploader));
return {std::move(proxy), kMaskOrigin, swizzle};
} else {
GrSWMaskHelper helper;
if (!helper.init(bounds)) {
return {};
}
for (int i = 0; i < count; ++i) {
draw_to_sw_mask(&helper,*(elements[i]), i == 0);
}
return helper.toTextureView(context, SkBackingFit::kApprox);
}
}
static void render_stencil_mask(GrRecordingContext* context, GrSurfaceDrawContext* rtc,

View File

@ -380,7 +380,7 @@ GrSurfaceProxyView GrClipStackClip::createAlphaClipMask(GrRecordingContext* cont
namespace {
/**
* Payload class for use with GrSWMaskHelper. The clip mask code renders multiple
* Payload class for use with GrTDeferredProxyUploader. The clip mask code renders multiple
* elements, each storing their own AA setting (and already transformed into device space). This
* stores all of the information needed by the worker thread to draw all clip elements (see below,
* in createSoftwareClipMask).
@ -468,17 +468,61 @@ GrSurfaceProxyView GrClipStackClip::createSoftwareClipMask(
// left corner of the resulting rect to the top left of the texture.
SkIRect maskSpaceIBounds = SkIRect::MakeWH(reducedClip.width(), reducedClip.height());
std::shared_ptr<ClipMaskData> data = std::make_shared<ClipMaskData>(reducedClip);
auto view = GrSWMaskHelper::MakeTexture(maskSpaceIBounds,
context,
SkBackingFit::kApprox,
[data{std::move(data)}](GrSWMaskHelper* helper) {
TRACE_EVENT0("skia.gpu", "SW Clip Mask Render");
draw_clip_elements_to_mask_helper(*helper,
data->elements(),
data->scissor(),
data->initialState());
});
SkTaskGroup* taskGroup = nullptr;
if (auto direct = context->asDirectContext()) {
taskGroup = direct->priv().getTaskGroup();
}
GrSurfaceProxyView view;
if (taskGroup && surfaceDrawContext) {
const GrCaps* caps = context->priv().caps();
// Create our texture proxy
GrBackendFormat format = caps->getDefaultBackendFormat(GrColorType::kAlpha_8,
GrRenderable::kNo);
GrSwizzle swizzle = context->priv().caps()->getReadSwizzle(format, GrColorType::kAlpha_8);
// MDB TODO: We're going to fill this proxy with an ASAP upload (which is out of order wrt
// to ops), so it can't have any pending IO.
auto proxy = proxyProvider->createProxy(format,
maskSpaceIBounds.size(),
GrRenderable::kNo,
1,
GrMipmapped::kNo,
SkBackingFit::kApprox,
SkBudgeted::kYes,
GrProtected::kNo);
auto uploader = std::make_unique<GrTDeferredProxyUploader<ClipMaskData>>(reducedClip);
GrTDeferredProxyUploader<ClipMaskData>* uploaderRaw = uploader.get();
auto drawAndUploadMask = [uploaderRaw, maskSpaceIBounds] {
TRACE_EVENT0("skia.gpu", "Threaded SW Clip Mask Render");
GrSWMaskHelper helper(uploaderRaw->getPixels());
if (helper.init(maskSpaceIBounds)) {
draw_clip_elements_to_mask_helper(helper, uploaderRaw->data().elements(),
uploaderRaw->data().scissor(),
uploaderRaw->data().initialState());
} else {
SkDEBUGFAIL("Unable to allocate SW clip mask.");
}
uploaderRaw->signalAndFreeData();
};
taskGroup->add(std::move(drawAndUploadMask));
proxy->texPriv().setDeferredUploader(std::move(uploader));
view = {std::move(proxy), kMaskOrigin, swizzle};
} else {
GrSWMaskHelper helper;
if (!helper.init(maskSpaceIBounds)) {
return {};
}
draw_clip_elements_to_mask_helper(helper, reducedClip.maskElements(), reducedClip.scissor(),
reducedClip.initialState());
view = helper.toTextureView(context, SkBackingFit::kApprox);
}
SkASSERT(view);
SkASSERT(view.origin() == kMaskOrigin);

View File

@ -9,10 +9,8 @@
#include "include/gpu/GrRecordingContext.h"
#include "src/core/SkMatrixProvider.h"
#include "src/core/SkTaskGroup.h"
#include "src/gpu/GrBitmapTextureMaker.h"
#include "src/gpu/GrCaps.h"
#include "src/gpu/GrDirectContextPriv.h"
#include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/GrSurfaceContext.h"
@ -45,96 +43,6 @@ static SkPaint get_paint(SkRegion::Op op, GrAA aa, uint8_t alpha) {
return paint;
}
GrSurfaceProxyView GrSWMaskHelper::MakeTexture(SkIRect bounds,
GrRecordingContext* context,
SkBackingFit fit,
DrawFunc&& draw) {
SkTaskGroup* taskGroup = nullptr;
if (auto dContext = context->asDirectContext()) {
taskGroup = dContext->priv().getTaskGroup();
}
if (taskGroup) {
GrSWMaskHelper* helper = new GrSWMaskHelper(bounds);
return helper->threadedExecute(taskGroup, context, fit, std::move(draw));
} else {
GrSWMaskHelper helper(bounds);
return helper.nonThreadedExecute(context, fit, draw);
}
}
GrSurfaceProxyView GrSWMaskHelper::threadedExecute(SkTaskGroup* taskGroup,
GrRecordingContext* context,
SkBackingFit fit,
DrawFunc&& draw) {
sk_sp<GrSWMaskHelper> spThis(this);
taskGroup->add([spThis, draw{std::move(draw)}]() {
if (spThis->allocate()) {
draw(spThis.get());
spThis->fBitmap.setImmutable();
}
spThis->fSemaphore.signal();
});
auto lazy_cb = [spThis{std::move(spThis)}](GrResourceProvider* provider,
const GrProxyProvider::LazySurfaceDesc& desc) {
spThis->fSemaphore.wait();
const SkBitmap& mask = spThis->fBitmap;
if (!mask.getPixels()) {
return GrProxyProvider::LazyCallbackResult();
}
GrMipLevel mip{mask.getPixels(), mask.pixmap().rowBytes()};
GrColorType ct{SkColorTypeToGrColorType(mask.colorType())};
sk_sp<GrTexture> tex = provider->createTexture(desc.fDimensions,
desc.fFormat,
ct,
desc.fRenderable,
desc.fSampleCnt,
desc.fBudgeted,
desc.fFit,
desc.fProtected,
mip);
GrProxyProvider::LazyCallbackResult result(std::move(tex));
// Callback refs us, we own bitmap, don't release callback.
result.fReleaseCallback = false;
return result;
};
const GrCaps* caps = context->priv().caps();
GrProxyProvider* proxyProvider = context->priv().proxyProvider();
GrBackendFormat format = caps->getDefaultBackendFormat(GrColorType::kAlpha_8,
GrRenderable::kNo);
GrSwizzle swizzle = caps->getReadSwizzle(format, GrColorType::kAlpha_8);
sk_sp<GrTextureProxy> p = proxyProvider->createLazyProxy(std::move(lazy_cb),
format,
fBitmap.dimensions(),
GrMipMapped::kNo,
GrMipmapStatus::kNotAllocated,
GrInternalSurfaceFlags::kNone,
fit,
SkBudgeted::kYes,
GrProtected::kNo,
GrProxyProvider::UseAllocator::kYes);
return GrSurfaceProxyView(std::move(p), kTopLeft_GrSurfaceOrigin, swizzle);
}
GrSurfaceProxyView GrSWMaskHelper::nonThreadedExecute(GrRecordingContext* context,
SkBackingFit fit,
const DrawFunc& draw) {
if (!this->allocate()) {
return {};
}
draw(this);
fBitmap.setImmutable();
GrBitmapTextureMaker maker(context, fBitmap, fit);
return maker.view(GrMipmapped::kNo);
}
GrSWMaskHelper::GrSWMaskHelper(const SkIRect& resultBounds) {
// We will need to translate draws so the bound's UL corner is at the origin
fTranslate = {-SkIntToScalar(resultBounds.fLeft), -SkIntToScalar(resultBounds.fTop)};
SkIRect bounds = SkIRect::MakeWH(resultBounds.width(), resultBounds.height());
fBitmap.setInfo(SkImageInfo::MakeA8(bounds.width(), bounds.height()));
}
/**
* Draw a single rect element of the clip stack into the accumulation bitmap
*/
@ -220,14 +128,33 @@ void GrSWMaskHelper::drawShape(const GrShape& shape, const SkMatrix& matrix, SkR
}
}
bool GrSWMaskHelper::allocate() {
if (!fBitmap.tryAllocPixels()) {
SkDEBUGFAIL("Unable to allocate SW mask.");
bool GrSWMaskHelper::init(const SkIRect& resultBounds) {
// We will need to translate draws so the bound's UL corner is at the origin
fTranslate = {-SkIntToScalar(resultBounds.fLeft), -SkIntToScalar(resultBounds.fTop)};
SkIRect bounds = SkIRect::MakeWH(resultBounds.width(), resultBounds.height());
const SkImageInfo bmImageInfo = SkImageInfo::MakeA8(bounds.width(), bounds.height());
if (!fPixels->tryAlloc(bmImageInfo)) {
return false;
}
fPixels->erase(0);
fDraw.fDst = fBitmap.pixmap();
fRasterClip.setRect(fBitmap.info().bounds());
fDraw.fDst = *fPixels;
fRasterClip.setRect(bounds);
fDraw.fRC = &fRasterClip;
return true;
}
GrSurfaceProxyView GrSWMaskHelper::toTextureView(GrRecordingContext* context, SkBackingFit fit) {
SkImageInfo ii = SkImageInfo::MakeA8(fPixels->width(), fPixels->height());
size_t rowBytes = fPixels->rowBytes();
SkBitmap bitmap;
SkAssertResult(bitmap.installPixels(ii, fPixels->detachPixels(), rowBytes,
[](void* addr, void* context) { sk_free(addr); },
nullptr));
bitmap.setImmutable();
GrBitmapTextureMaker maker(context, bitmap, fit);
return maker.view(GrMipmapped::kNo);
}

View File

@ -21,37 +21,31 @@ class GrShape;
class GrStyledShape;
class GrRecordingContext;
class GrTextureProxy;
class SkTaskGroup;
/**
* The GrSWMaskHelper helps generate clip masks using the software rendering
* path. It is intended to be used as:
*
* auto data = copy_required_drawing_data();
* GrSurfaceProxyView proxy
* = GrSWMaskHelper::MakeTexture(bounds,
* context,
* SkBackingFit::kApprox/kExact,
* [data{std::move(data)}](GrSWMaskHelper* helper) {
* // draw one or more paths/rects specifying the required boolean ops
* helper->drawRect(data.rect(), ...);
* });
* GrSWMaskHelper helper(context);
* helper.init(...);
*
* draw one or more paths/rects specifying the required boolean ops
*
* toTextureView(); // to get it from the internal bitmap to the GPU
*
* The result of this process will be the final mask (on the GPU) in the
* upper left hand corner of the texture.
*/
class GrSWMaskHelper : public SkNVRefCnt<GrSWMaskHelper> {
class GrSWMaskHelper : SkNoncopyable {
public:
using DrawFunc = std::function<void(GrSWMaskHelper*)>;
GrSWMaskHelper(SkAutoPixmapStorage* pixels = nullptr)
: fPixels(pixels ? pixels : &fPixelsStorage) { }
// Make a texture by drawing a software mask. If the context has a task group, the draw will be
// done async in that task group, and a lazy proxy will be returned to wait & upload it.
// Otherwise the drawing is done immediately.
// NOTE: The draw fn is async it should not capture by reference.
static GrSurfaceProxyView MakeTexture(SkIRect bounds,
GrRecordingContext*,
SkBackingFit,
DrawFunc&&);
// set up the internal state in preparation for draws. Since many masks
// may be accumulated in the helper during creation, "resultBounds"
// allows the caller to specify the region of interest - to limit the
// amount of work.
bool init(const SkIRect& resultBounds);
// Draw a single rect into the accumulation bitmap using the specified op
void drawRect(const SkRect& rect, const SkMatrix& matrix, SkRegion::Op op, GrAA, uint8_t alpha);
@ -63,38 +57,24 @@ public:
// Draw a single path into the accumuation bitmap using the specified op
void drawShape(const GrStyledShape&, const SkMatrix& matrix, SkRegion::Op op, GrAA,
uint8_t alpha);
// Like the GrStyledShape variant, but assumes a simple fill style
void drawShape(const GrShape&, const SkMatrix& matrix, SkRegion::Op op, GrAA, uint8_t alpha);
GrSurfaceProxyView toTextureView(GrRecordingContext*, SkBackingFit fit);
// Reset the internal bitmap
void clear(uint8_t alpha) {
fBitmap.pixmap().erase(SkColorSetARGB(alpha, 0xFF, 0xFF, 0xFF));
fPixels->erase(SkColorSetARGB(alpha, 0xFF, 0xFF, 0xFF));
}
private:
GrSWMaskHelper(const SkIRect& resultBounds);
SkVector fTranslate;
SkAutoPixmapStorage* fPixels;
SkAutoPixmapStorage fPixelsStorage;
SkDraw fDraw;
SkRasterClip fRasterClip;
GrSWMaskHelper(const GrSWMaskHelper&) = delete;
GrSWMaskHelper& operator=(const GrSWMaskHelper&) = delete;
GrSurfaceProxyView nonThreadedExecute(GrRecordingContext*,
SkBackingFit,
const DrawFunc&);
// `this` must be heap-allocated. Task & proxy take on ownership; do not unref.
GrSurfaceProxyView threadedExecute(SkTaskGroup*,
GrRecordingContext*,
SkBackingFit,
DrawFunc&&);
bool allocate();
SkVector fTranslate;
SkBitmap fBitmap;
SkDraw fDraw;
SkRasterClip fRasterClip;
SkSemaphore fSemaphore;
using INHERITED = SkNoncopyable;
};
#endif // GrSWMaskHelper_DEFINED

View File

@ -173,10 +173,27 @@ void GrSoftwarePathRenderer::DrawToTargetWithShapeMask(
dstRect, invert);
}
static GrSurfaceProxyView make_deferred_mask_texture_view(GrRecordingContext* context,
SkBackingFit fit,
SkISize dimensions) {
GrProxyProvider* proxyProvider = context->priv().proxyProvider();
const GrCaps* caps = context->priv().caps();
const GrBackendFormat format = caps->getDefaultBackendFormat(GrColorType::kAlpha_8,
GrRenderable::kNo);
GrSwizzle swizzle = caps->getReadSwizzle(format, GrColorType::kAlpha_8);
auto proxy =
proxyProvider->createProxy(format, dimensions, GrRenderable::kNo, 1, GrMipmapped::kNo,
fit, SkBudgeted::kYes, GrProtected::kNo);
return {std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle};
}
namespace {
/**
* Payload class for use with GrSWMaskHelper. The software path renderer only draws
* Payload class for use with GrTDeferredProxyUploader. The software path renderer only draws
* a single path into the mask texture. This stores all of the information needed by the worker
* thread's call to drawShape (see below, in onDrawPath).
*/
@ -190,7 +207,7 @@ public:
, fAA(aa) {}
const SkIRect& getMaskBounds() const { return fMaskBounds; }
const SkMatrix& getViewMatrix() const { return fViewMatrix; }
const SkMatrix* getViewMatrix() const { return &fViewMatrix; }
const GrStyledShape& getShape() const { return fShape; }
GrAA getAA() const { return fAA; }
@ -309,15 +326,44 @@ bool GrSoftwarePathRenderer::onDrawPath(const DrawPathArgs& args) {
if (!view) {
SkBackingFit fit = useCache ? SkBackingFit::kExact : SkBackingFit::kApprox;
GrAA aa = GrAA(GrAAType::kCoverage == args.fAAType);
SoftwarePathData data(*boundsForMask, *args.fViewMatrix, *args.fShape, aa);
view = GrSWMaskHelper::MakeTexture(data.getMaskBounds(),
args.fContext,
fit,
[data{std::move(data)}](GrSWMaskHelper* helper) {
TRACE_EVENT0("skia.gpu", "SW Mask Render");
helper->drawShape(data.getShape(), data.getViewMatrix(), SkRegion::kReplace_Op,
data.getAA(), 0xFF);
});
SkTaskGroup* taskGroup = nullptr;
if (auto direct = args.fContext->asDirectContext()) {
taskGroup = direct->priv().getTaskGroup();
}
if (taskGroup) {
view = make_deferred_mask_texture_view(args.fContext, fit, boundsForMask->size());
if (!view) {
return false;
}
auto uploader = std::make_unique<GrTDeferredProxyUploader<SoftwarePathData>>(
*boundsForMask, *args.fViewMatrix, *args.fShape, aa);
GrTDeferredProxyUploader<SoftwarePathData>* uploaderRaw = uploader.get();
auto drawAndUploadMask = [uploaderRaw] {
TRACE_EVENT0("skia.gpu", "Threaded SW Mask Render");
GrSWMaskHelper helper(uploaderRaw->getPixels());
if (helper.init(uploaderRaw->data().getMaskBounds())) {
helper.drawShape(uploaderRaw->data().getShape(),
*uploaderRaw->data().getViewMatrix(),
SkRegion::kReplace_Op, uploaderRaw->data().getAA(), 0xFF);
} else {
SkDEBUGFAIL("Unable to allocate SW mask.");
}
uploaderRaw->signalAndFreeData();
};
taskGroup->add(std::move(drawAndUploadMask));
view.asTextureProxy()->texPriv().setDeferredUploader(std::move(uploader));
} else {
GrSWMaskHelper helper;
if (!helper.init(*boundsForMask)) {
return false;
}
helper.drawShape(*args.fShape, *args.fViewMatrix, SkRegion::kReplace_Op, aa, 0xFF);
view = helper.toTextureView(args.fContext, fit);
}
if (!view) {
return false;

View File

@ -1577,12 +1577,7 @@ DEF_GPUTEST_FOR_ALL_CONTEXTS(ClipMaskCache, reporter, ctxInfo) {
stack.clipPath(path, m, SkClipOp::kIntersect, true);
sk_sp<GrTextureProxy> mask =
GrClipStackClip(stackBounds.size(), &stack).testingOnly_createClipMask(context);
// TODO: Make `instantiate` work for lazy proxies.
if (mask->isLazy()) {
mask->priv().doLazyInstantiation(context->priv().resourceProvider());
} else {
mask->instantiate(context->priv().resourceProvider());
}
mask->instantiate(context->priv().resourceProvider());
GrTexture* tex = mask->peekTexture();
REPORTER_ASSERT(reporter, 0 == strcmp(tex->getUniqueKey().tag(), kTag));
// Make sure mask isn't pinned in cache.