"$_src/gpu/GrAuditTrail.cpp",
"$_src/gpu/GrAutoLocaleSetter.h",
"$_src/gpu/GrAllocator.h",
- "$_src/gpu/GrDrawOpAtlas.cpp",
- "$_src/gpu/GrDrawOpAtlas.h",
"$_src/gpu/GrBatchTest.cpp",
"$_src/gpu/GrBatchTest.h",
"$_src/gpu/GrBitmapTextureMaker.cpp",
"$_src/gpu/GrDefaultGeoProcFactory.h",
"$_src/gpu/GrDrawingManager.cpp",
"$_src/gpu/GrDrawingManager.h",
+ "$_src/gpu/GrDrawOpAtlas.cpp",
+ "$_src/gpu/GrDrawOpAtlas.h",
"$_src/gpu/GrFixedClip.cpp",
"$_src/gpu/GrFixedClip.h",
"$_src/gpu/GrFragmentProcessor.cpp",
#include "../private/GrSingleOwner.h"
class GrAtlasGlyphCache;
-struct GrBatchAtlasConfig;
struct GrContextOptions;
class GrContextPriv;
class GrContextThreadSafeProxy;
class GrDrawingManager;
+struct GrDrawOpAtlasConfig;
class GrRenderTargetContext;
class GrFragmentProcessor;
class GrGpu;
/** Specify the sizes of the GrAtlasTextContext atlases. The configs pointer below should be
to an array of 3 entries */
- void setTextContextAtlasSizes_ForTesting(const GrBatchAtlasConfig* configs);
+ void setTextContextAtlasSizes_ForTesting(const GrDrawOpAtlasConfig* configs);
/** Enumerates all cached GPU resources and dumps their memory to traceMemoryDump. */
void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const;
////////////////////////////////////////////////////////////////////////////////
-GrBatchAtlas::BatchPlot::BatchPlot(int index, uint64_t genID, int offX, int offY, int width,
- int height, GrPixelConfig config)
- : fLastUpload(GrDrawOpUploadToken::AlreadyFlushedToken())
- , fLastUse(GrDrawOpUploadToken::AlreadyFlushedToken())
- , fIndex(index)
- , fGenID(genID)
- , fID(CreateId(fIndex, fGenID))
- , fData(nullptr)
- , fWidth(width)
- , fHeight(height)
- , fX(offX)
- , fY(offY)
- , fRects(nullptr)
- , fOffset(SkIPoint16::Make(fX * fWidth, fY * fHeight))
- , fConfig(config)
- , fBytesPerPixel(GrBytesPerPixel(config))
+GrDrawOpAtlas::Plot::Plot(int index, uint64_t genID, int offX, int offY, int width, int height,
+ GrPixelConfig config)
+ : fLastUpload(GrDrawOpUploadToken::AlreadyFlushedToken())
+ , fLastUse(GrDrawOpUploadToken::AlreadyFlushedToken())
+ , fIndex(index)
+ , fGenID(genID)
+ , fID(CreateId(fIndex, fGenID))
+ , fData(nullptr)
+ , fWidth(width)
+ , fHeight(height)
+ , fX(offX)
+ , fY(offY)
+ , fRects(nullptr)
+ , fOffset(SkIPoint16::Make(fX * fWidth, fY * fHeight))
+ , fConfig(config)
+ , fBytesPerPixel(GrBytesPerPixel(config))
#ifdef SK_DEBUG
- , fDirty(false)
+ , fDirty(false)
#endif
{
fDirtyRect.setEmpty();
}
-GrBatchAtlas::BatchPlot::~BatchPlot() {
+GrDrawOpAtlas::Plot::~Plot() {
sk_free(fData);
delete fRects;
}
-bool GrBatchAtlas::BatchPlot::addSubImage(int width, int height, const void* image,
- SkIPoint16* loc) {
+bool GrDrawOpAtlas::Plot::addSubImage(int width, int height, const void* image, SkIPoint16* loc) {
SkASSERT(width <= fWidth && height <= fHeight);
if (!fRects) {
return true;
}
-void GrBatchAtlas::BatchPlot::uploadToTexture(GrDrawOp::WritePixelsFn& writePixels,
- GrTexture* texture) {
+void GrDrawOpAtlas::Plot::uploadToTexture(GrDrawOp::WritePixelsFn& writePixels,
+ GrTexture* texture) {
// We should only be issuing uploads if we are in fact dirty
SkASSERT(fDirty && fData && texture);
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("skia.gpu"), "GrBatchPlot::uploadToTexture");
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("skia.gpu"), "GrDrawOpAtlas::Plot::uploadToTexture");
size_t rowBytes = fBytesPerPixel * fWidth;
const unsigned char* dataPtr = fData;
dataPtr += rowBytes * fDirtyRect.fTop;
SkDEBUGCODE(fDirty = false;)
}
-void GrBatchAtlas::BatchPlot::resetRects() {
+void GrDrawOpAtlas::Plot::resetRects() {
if (fRects) {
fRects->reset();
}
///////////////////////////////////////////////////////////////////////////////
-GrBatchAtlas::GrBatchAtlas(sk_sp<GrTexture> texture, int numPlotsX, int numPlotsY)
- : fTexture(std::move(texture))
- , fAtlasGeneration(kInvalidAtlasGeneration + 1) {
-
+GrDrawOpAtlas::GrDrawOpAtlas(sk_sp<GrTexture> texture, int numPlotsX, int numPlotsY)
+ : fTexture(std::move(texture)), fAtlasGeneration(kInvalidAtlasGeneration + 1) {
fPlotWidth = fTexture->width() / numPlotsX;
fPlotHeight = fTexture->height() / numPlotsY;
SkASSERT(numPlotsX * numPlotsY <= BulkUseTokenUpdater::kMaxPlots);
SkASSERT(!GrPixelConfigIsCompressed(fTexture->desc().fConfig));
// set up allocated plots
- fPlotArray.reset(new sk_sp<BatchPlot>[numPlotsX * numPlotsY]);
+ fPlotArray.reset(new sk_sp<Plot>[ numPlotsX * numPlotsY ]);
- sk_sp<BatchPlot>* currPlot = fPlotArray.get();
+ sk_sp<Plot>* currPlot = fPlotArray.get();
for (int y = numPlotsY - 1, r = 0; y >= 0; --y, ++r) {
for (int x = numPlotsX - 1, c = 0; x >= 0; --x, ++c) {
uint32_t index = r * numPlotsX + c;
- currPlot->reset(new BatchPlot(index, 1, x, y, fPlotWidth, fPlotHeight,
- fTexture->desc().fConfig));
+ currPlot->reset(
+ new Plot(index, 1, x, y, fPlotWidth, fPlotHeight, fTexture->desc().fConfig));
// build LRU list
fPlotList.addToHead(currPlot->get());
}
}
-void GrBatchAtlas::processEviction(AtlasID id) {
+void GrDrawOpAtlas::processEviction(AtlasID id) {
for (int i = 0; i < fEvictionCallbacks.count(); i++) {
(*fEvictionCallbacks[i].fFunc)(id, fEvictionCallbacks[i].fData);
}
}
-inline void GrBatchAtlas::updatePlot(GrDrawOp::Target* target, AtlasID* id, BatchPlot* plot) {
+inline void GrDrawOpAtlas::updatePlot(GrDrawOp::Target* target, AtlasID* id, Plot* plot) {
this->makeMRU(plot);
// If our most recent upload has already occurred then we have to insert a new
// This new update will piggy back on that previously scheduled update.
if (target->hasDrawBeenFlushed(plot->lastUploadToken())) {
// With c+14 we could move sk_sp into lamba to only ref once.
- sk_sp<BatchPlot> plotsp(SkRef(plot));
+ sk_sp<Plot> plotsp(SkRef(plot));
GrTexture* texture = fTexture.get();
GrDrawOpUploadToken lastUploadToken = target->addAsapUpload(
[plotsp, texture] (GrDrawOp::WritePixelsFn& writePixels) {
*id = plot->id();
}
-bool GrBatchAtlas::addToAtlas(AtlasID* id, GrDrawOp::Target* target,
- int width, int height, const void* image, SkIPoint16* loc) {
+bool GrDrawOpAtlas::addToAtlas(AtlasID* id, GrDrawOp::Target* target, int width, int height,
+ const void* image, SkIPoint16* loc) {
// We should already have a texture, TODO clean this up
SkASSERT(fTexture);
if (width > fPlotWidth || height > fPlotHeight) {
}
// now look through all allocated plots for one we can share, in Most Recently Refed order
- GrBatchPlotList::Iter plotIter;
- plotIter.init(fPlotList, GrBatchPlotList::Iter::kHead_IterStart);
- BatchPlot* plot;
+ PlotList::Iter plotIter;
+ plotIter.init(fPlotList, PlotList::Iter::kHead_IterStart);
+ Plot* plot;
while ((plot = plotIter.get())) {
SkASSERT(GrBytesPerPixel(fTexture->desc().fConfig) == plot->bpp());
if (plot->addSubImage(width, height, image, loc)) {
return true;
}
- // If this plot has been used in a draw that is currently being prepared by a batch, then we
- // have to fail. This gives the batch a chance to enqueue the draw, and call back into this
- // function. When that draw is enqueued, the draw token advances, and the subsequent call will
- // continue past this branch and prepare an inline upload that will occur after the enqueued
- // draw which references the plot's pre-upload content.
+ // If this plot has been used in a draw that is currently being prepared by an op, then we have
+ // to fail. This gives the op a chance to enqueue the draw, and call back into this function.
+ // When that draw is enqueued, the draw token advances, and the subsequent call will continue
+ // past this branch and prepare an inline upload that will occur after the enqueued draw which
+ // references the plot's pre-upload content.
if (plot->lastUseToken() == target->nextDrawToken()) {
return false;
}
this->processEviction(plot->id());
fPlotList.remove(plot);
- sk_sp<BatchPlot>& newPlot = fPlotArray[plot->index()];
+ sk_sp<Plot>& newPlot = fPlotArray[plot->index()];
newPlot.reset(plot->clone());
fPlotList.addToHead(newPlot.get());
// Note that this plot will be uploaded inline with the draws whereas the
// one it displaced most likely was uploaded asap.
- // With c+14 we could move sk_sp into lamba to only ref once.
- sk_sp<BatchPlot> plotsp(SkRef(newPlot.get()));
+ // With c+14 we could move sk_sp into lambda to only ref once.
+ sk_sp<Plot> plotsp(SkRef(newPlot.get()));
GrTexture* texture = fTexture.get();
GrDrawOpUploadToken lastUploadToken = target->addInlineUpload(
[plotsp, texture] (GrDrawOp::WritePixelsFn& writePixels) {
* found in the LICENSE file.
*/
-#ifndef GrBatchAtlas_DEFINED
-#define GrBatchAtlas_DEFINED
+#ifndef GrDrawOpAtlas_DEFINED
+#define GrDrawOpAtlas_DEFINED
#include "GrTexture.h"
#include "SkPoint.h"
class GrRectanizer;
-struct GrBatchAtlasConfig {
+struct GrDrawOpAtlasConfig {
int numPlotsX() const { return fWidth / fPlotWidth; }
int numPlotsY() const { return fHeight / fPlotWidth; }
int fWidth;
int fPlotHeight;
};
-class GrBatchAtlas {
+/**
+ * This class manages an atlas texture on behalf of GrDrawOps. The draw ops that use the atlas
+ * perform texture uploads when preparing their draws during flush. The class provides facilities
+ * for using GrDrawOpUploadToken to detect data hazards. Op's uploads are performed in "asap" mode
+ * until it is impossible to add data without overwriting texels read by draws that have not yet
+ * executed on the gpu. At that point the uploads are performed "inline" between draws. If a single
+ * draw would use enough subimage space to overflow the atlas texture then the atlas will fail to
+ * add a subimage. This gives the op the chance to end the draw and begin a new one. Additional
+ * uploads will then succeed in inline mode.
+ */
+class GrDrawOpAtlas {
public:
- // An AtlasID is an opaque handle which callers can use to determine if the atlas contains
- // a specific piece of data
+ /**
+ * An AtlasID is an opaque handle which callers can use to determine if the atlas contains
+ * a specific piece of data.
+ */
typedef uint64_t AtlasID;
static const uint32_t kInvalidAtlasID = 0;
static const uint64_t kInvalidAtlasGeneration = 0;
- // A function pointer for use as a callback during eviction. Whenever GrBatchAtlas evicts a
- // specific AtlasID, it will call all of the registered listeners so they can optionally process
- // the eviction
- typedef void (*EvictionFunc)(GrBatchAtlas::AtlasID, void*);
-
- GrBatchAtlas(sk_sp<GrTexture>, int numPlotsX, int numPlotsY);
-
- // Adds a width x height subimage to the atlas. Upon success it returns
- // the containing GrPlot and absolute location in the backing texture.
- // nullptr is returned if the subimage cannot fit in the atlas.
- // If provided, the image data will be written to the CPU-side backing bitmap.
- // NOTE: If the client intends to refer to the atlas, they should immediately call 'setUseToken'
- // with the currentToken from the batch target, otherwise the next call to addToAtlas might
- // cause an eviction
+ /**
+ * A function pointer for use as a callback during eviction. Whenever GrDrawOpAtlas evicts a
+ * specific AtlasID, it will call all of the registered listeners so they can process the
+ * eviction.
+ */
+ typedef void (*EvictionFunc)(GrDrawOpAtlas::AtlasID, void*);
+
+ GrDrawOpAtlas(sk_sp<GrTexture>, int numPlotsX, int numPlotsY);
+
+ /**
+ * Adds a width x height subimage to the atlas. Upon success it returns an ID and the subimage's
+ * coordinates in the backing texture. False is returned if the subimage cannot fit in the
+ * atlas without overwriting texels that will be read in the current draw. This indicates that
+ * the op should end its current draw and begin another before adding more data. Upon success,
+ * an upload of the provided image data will have been added to the GrDrawOp::Target, in "asap"
+ * mode if possible, otherwise in "inline" mode. Successive uploads in either mode may be
+ * consolidated.
+ * NOTE: When the GrDrawOp prepares a draw that reads from the atlas, it must immediately call
+ * 'setUseToken' with the currentToken from the GrDrawOp::Target, otherwise the next call to
+ * addToAtlas might cause the previous data to be overwritten before it has been read.
+ */
bool addToAtlas(AtlasID*, GrDrawOp::Target*, int width, int height, const void* image,
SkIPoint16* loc);
return fPlotArray[index]->genID() == GetGenerationFromID(id);
}
- // To ensure the atlas does not evict a given entry, the client must set the last use token
- inline void setLastUseToken(AtlasID id, GrDrawOpUploadToken batchToken) {
+ /** To ensure the atlas does not evict a given entry, the client must set the last use token. */
+ inline void setLastUseToken(AtlasID id, GrDrawOpUploadToken token) {
SkASSERT(this->hasID(id));
uint32_t index = GetIndexFromID(id);
SkASSERT(index < fNumPlots);
this->makeMRU(fPlotArray[index].get());
- fPlotArray[index]->setLastUseToken(batchToken);
+ fPlotArray[index]->setLastUseToken(token);
}
inline void registerEvictionCallback(EvictionFunc func, void* userData) {
data->fData = userData;
}
- /*
- * A class which can be handed back to GrBatchAtlas for updating in bulk last use tokens. The
- * current max number of plots the GrBatchAtlas can handle is 32, if in the future this is
- * insufficient then we can move to a 64 bit int
+ /**
+ * A class which can be handed back to GrDrawOpAtlas for updating last use tokens in bulk. The
+ * current max number of plots the GrDrawOpAtlas can handle is 32. If in the future this is
+ * insufficient then we can move to a 64 bit int.
*/
class BulkUseTokenUpdater {
public:
}
void add(AtlasID id) {
- int index = GrBatchAtlas::GetIndexFromID(id);
+ int index = GrDrawOpAtlas::GetIndexFromID(id);
if (!this->find(index)) {
this->set(index);
}
SkSTArray<kMinItems, int, true> fPlotsToUpdate;
uint32_t fPlotAlreadyUpdated;
- friend class GrBatchAtlas;
+ friend class GrDrawOpAtlas;
};
- void setLastUseTokenBulk(const BulkUseTokenUpdater& updater, GrDrawOpUploadToken batchToken) {
+ void setLastUseTokenBulk(const BulkUseTokenUpdater& updater, GrDrawOpUploadToken token) {
int count = updater.fPlotsToUpdate.count();
for (int i = 0; i < count; i++) {
- BatchPlot* plot = fPlotArray[updater.fPlotsToUpdate[i]].get();
+ Plot* plot = fPlotArray[updater.fPlotsToUpdate[i]].get();
this->makeMRU(plot);
- plot->setLastUseToken(batchToken);
+ plot->setLastUseToken(token);
}
}
}
private:
- // The backing GrTexture for a GrBatchAtlas is broken into a spatial grid of BatchPlots.
- // The BatchPlots keep track of subimage placement via their GrRectanizer. A BatchPlot
- // manages the lifetime of its data using two tokens, a last use token and a last upload token.
- // Once a BatchPlot is "full" (i.e. there is no room for the new subimage according to the
- // GrRectanizer), it can no longer be used unless the last use of the GrPlot has already been
- // flushed through to the gpu.
- class BatchPlot : public SkRefCnt {
- SK_DECLARE_INTERNAL_LLIST_INTERFACE(BatchPlot);
+ /**
+ * The backing GrTexture for a GrDrawOpAtlas is broken into a spatial grid of Plots. The Plots
+ * keep track of subimage placement via their GrRectanizer. A Plot manages the lifetime of its
+ * data using two tokens, a last use token and a last upload token. Once a Plot is "full" (i.e.
+ * there is no room for the new subimage according to the GrRectanizer), it can no longer be
+ * used unless the last use of the Plot has already been flushed through to the gpu.
+ */
+ class Plot : public SkRefCnt {
+ SK_DECLARE_INTERNAL_LLIST_INTERFACE(Plot);
public:
- // index() is a unique id for the plot relative to the owning GrAtlas. genID() is a
- // monotonically incremented number which is bumped every time this plot is
- // evicted from the cache (i.e., there is continuity in genID() across atlas spills).
+ /** index() is a unique id for the plot relative to the owning GrAtlas. */
uint32_t index() const { return fIndex; }
+ /**
+ * genID() is incremented when the plot is evicted due to a atlas spill. It is used to know
+ * if a particular subimage is still present in the atlas.
+ */
uint64_t genID() const { return fGenID; }
- GrBatchAtlas::AtlasID id() const {
- SkASSERT(GrBatchAtlas::kInvalidAtlasID != fID);
+ GrDrawOpAtlas::AtlasID id() const {
+ SkASSERT(GrDrawOpAtlas::kInvalidAtlasID != fID);
return fID;
}
SkDEBUGCODE(size_t bpp() const { return fBytesPerPixel; })
bool addSubImage(int width, int height, const void* image, SkIPoint16* loc);
- // To manage the lifetime of a plot, we use two tokens. We use the last upload token to
- // know when we can 'piggy back' uploads, ie if the last upload hasn't been flushed to gpu,
- // we don't need to issue a new upload even if we update the cpu backing store. We use
- // lastUse to determine when we can evict a plot from the cache, ie if the last use has
- // already flushed through the gpu then we can reuse the plot.
+ /**
+ * To manage the lifetime of a plot, we use two tokens. We use the last upload token to
+ * know when we can 'piggy back' uploads, i.e. if the last upload hasn't been flushed to
+ * the gpu, we don't need to issue a new upload even if we update the cpu backing store. We
+ * use lastUse to determine when we can evict a plot from the cache, i.e. if the last use
+ * has already flushed through the gpu then we can reuse the plot.
+ */
GrDrawOpUploadToken lastUploadToken() const { return fLastUpload; }
GrDrawOpUploadToken lastUseToken() const { return fLastUse; }
- void setLastUploadToken(GrDrawOpUploadToken batchToken) { fLastUpload = batchToken; }
- void setLastUseToken(GrDrawOpUploadToken batchToken) { fLastUse = batchToken; }
+ void setLastUploadToken(GrDrawOpUploadToken token) { fLastUpload = token; }
+ void setLastUseToken(GrDrawOpUploadToken token) { fLastUse = token; }
void uploadToTexture(GrDrawOp::WritePixelsFn&, GrTexture* texture);
void resetRects();
private:
- BatchPlot(int index, uint64_t genID, int offX, int offY, int width, int height,
- GrPixelConfig config);
+ Plot(int index, uint64_t genID, int offX, int offY, int width, int height,
+ GrPixelConfig config);
- ~BatchPlot() override;
+ ~Plot() override;
- // Create a clone of this plot. The cloned plot will take the place of the
- // current plot in the atlas.
- BatchPlot* clone() const {
- return new BatchPlot(fIndex, fGenID+1, fX, fY, fWidth, fHeight, fConfig);
+ /**
+ * Create a clone of this plot. The cloned plot will take the place of the current plot in
+ * the atlas
+ */
+ Plot* clone() const {
+ return new Plot(fIndex, fGenID + 1, fX, fY, fWidth, fHeight, fConfig);
}
- static GrBatchAtlas::AtlasID CreateId(uint32_t index, uint64_t generation) {
+ static GrDrawOpAtlas::AtlasID CreateId(uint32_t index, uint64_t generation) {
SkASSERT(index < (1 << 16));
SkASSERT(generation < ((uint64_t)1 << 48));
return generation << 16 | index;
GrDrawOpUploadToken fLastUpload;
GrDrawOpUploadToken fLastUse;
- const uint32_t fIndex;
- uint64_t fGenID;
- GrBatchAtlas::AtlasID fID;
- unsigned char* fData;
- const int fWidth;
- const int fHeight;
- const int fX;
- const int fY;
- GrRectanizer* fRects;
- const SkIPoint16 fOffset; // the offset of the plot in the backing texture
- const GrPixelConfig fConfig;
- const size_t fBytesPerPixel;
- SkIRect fDirtyRect;
- SkDEBUGCODE(bool fDirty;)
-
- friend class GrBatchAtlas;
+ const uint32_t fIndex;
+ uint64_t fGenID;
+ GrDrawOpAtlas::AtlasID fID;
+ unsigned char* fData;
+ const int fWidth;
+ const int fHeight;
+ const int fX;
+ const int fY;
+ GrRectanizer* fRects;
+ const SkIPoint16 fOffset; // the offset of the plot in the backing texture
+ const GrPixelConfig fConfig;
+ const size_t fBytesPerPixel;
+ SkIRect fDirtyRect;
+ SkDEBUGCODE(bool fDirty);
+
+ friend class GrDrawOpAtlas;
typedef SkRefCnt INHERITED;
};
- typedef SkTInternalLList<BatchPlot> GrBatchPlotList;
+ typedef SkTInternalLList<Plot> PlotList;
static uint32_t GetIndexFromID(AtlasID id) {
return id & 0xffff;
return (id >> 16) & 0xffffffffffff;
}
- inline void updatePlot(GrDrawOp::Target*, AtlasID*, BatchPlot*);
+ inline void updatePlot(GrDrawOp::Target*, AtlasID*, Plot*);
- inline void makeMRU(BatchPlot* plot) {
+ inline void makeMRU(Plot* plot) {
if (fPlotList.head() == plot) {
return;
}
};
SkTDArray<EvictionData> fEvictionCallbacks;
- // allocated array of GrBatchPlots
- std::unique_ptr<sk_sp<BatchPlot>[]> fPlotArray;
- // LRU list of GrPlots (MRU at head - LRU at tail)
- GrBatchPlotList fPlotList;
+ // allocated array of Plots
+ std::unique_ptr<sk_sp<Plot>[]> fPlotArray;
+ // LRU list of Plots (MRU at head - LRU at tail)
+ PlotList fPlotList;
};
#endif
typedef uint32_t PackedID;
- GrBatchAtlas::AtlasID fID;
+ GrDrawOpAtlas::AtlasID fID;
SkPath* fPath;
PackedID fPackedID;
GrMaskFormat fMaskFormat;
bool fTooLargeForAtlas;
void init(GrGlyph::PackedID packed, const SkIRect& bounds, GrMaskFormat format) {
- fID = GrBatchAtlas::kInvalidAtlasID;
+ fID = GrDrawOpAtlas::kInvalidAtlasID;
fPath = nullptr;
fPackedID = packed;
fBounds.set(bounds);
fMaskFormat = format;
fAtlasLocation.set(0, 0);
- fTooLargeForAtlas = GrBatchAtlas::GlyphTooLargeForAtlas(bounds.width(), bounds.height());
+ fTooLargeForAtlas = GrDrawOpAtlas::GlyphTooLargeForAtlas(bounds.width(), bounds.height());
}
void reset() {
* that case the ASAP upload would happen prior to the previous draw causing the draw to read the
* new (wrong) texture data. In that case they should schedule an inline upload.
*
- * Ops, in conjunction with helpers such as GrBatchAtlas, can use the token system to know
+ * Ops, in conjunction with helpers such as GrDrawOpAtlas, can use the token system to know
* what the most recent draw was that referenced a resource (or portion of a resource). Each draw
* is assigned a token. A resource (or portion) can be tagged with the most recent draw's
* token. The target provides a facility for testing whether the draw corresponding to the token
return buffer;
}
-std::unique_ptr<GrBatchAtlas> GrResourceProvider::makeAtlas(GrPixelConfig config,
- int width, int height,
- int numPlotsX, int numPlotsY,
- GrBatchAtlas::EvictionFunc func,
- void* data) {
+std::unique_ptr<GrDrawOpAtlas> GrResourceProvider::makeAtlas(GrPixelConfig config, int width,
+ int height, int numPlotsX,
+ int numPlotsY,
+ GrDrawOpAtlas::EvictionFunc func,
+ void* data) {
GrSurfaceDesc desc;
desc.fFlags = kNone_GrSurfaceFlags;
desc.fWidth = width;
if (!texture) {
return nullptr;
}
- std::unique_ptr<GrBatchAtlas> atlas(new GrBatchAtlas(std::move(texture), numPlotsX, numPlotsY));
+ std::unique_ptr<GrDrawOpAtlas> atlas(
+ new GrDrawOpAtlas(std::move(texture), numPlotsX, numPlotsY));
atlas->registerEvictionCallback(func, data);
return atlas;
}
#ifndef GrResourceProvider_DEFINED
#define GrResourceProvider_DEFINED
-#include "GrDrawOpAtlas.h"
#include "GrBuffer.h"
+#include "GrDrawOpAtlas.h"
#include "GrGpu.h"
-#include "GrTextureProvider.h"
#include "GrPathRange.h"
+#include "GrTextureProvider.h"
-class GrBatchAtlas;
+class GrDrawOpAtlas;
class GrPath;
class GrRenderTarget;
class GrSingleOwner;
return this->internalCreateApproxTexture(desc, flags);
}
- /** Returns a GrBatchAtlas. This function can be called anywhere, but the returned atlas should
- * only be used inside of GrOp::generateGeometry
- * @param GrPixelConfig The pixel config which this atlas will store
- * @param width width in pixels of the atlas
- * @param height height in pixels of the atlas
- * @param numPlotsX The number of plots the atlas should be broken up into in the X
- * direction
- * @param numPlotsY The number of plots the atlas should be broken up into in the Y
- * direction
- * @param func An eviction function which will be called whenever the atlas has to
- * evict data
- * @param data User supplied data which will be passed into func whenver an
- * eviction occurs
- *
- * @return An initialized GrBatchAtlas, or nullptr if creation fails
+ /**
+ * Returns a GrDrawOpAtlas. This function can be called anywhere, but the returned atlas
+ * should only be used inside of GrMeshDrawOp::onPrepareDraws.
+ * @param GrPixelConfig The pixel config which this atlas will store
+ * @param width width in pixels of the atlas
+ * @param height height in pixels of the atlas
+ * @param numPlotsX The number of plots the atlas should be broken up into in the X
+ * direction
+ * @param numPlotsY The number of plots the atlas should be broken up into in the Y
+ * direction
+ * @param func An eviction function which will be called whenever the atlas has to
+ * evict data
+ * @param data User supplied data which will be passed into func whenver an
+ * eviction occurs
+ * @return An initialized GrDrawOpAtlas, or nullptr if creation fails
*/
- std::unique_ptr<GrBatchAtlas> makeAtlas(GrPixelConfig, int width, int height,
- int numPlotsX, int numPlotsY,
- GrBatchAtlas::EvictionFunc func, void* data);
+ std::unique_ptr<GrDrawOpAtlas> makeAtlas(GrPixelConfig, int width, int height, int numPlotsX,
+ int numPlotsY, GrDrawOpAtlas::EvictionFunc func,
+ void* data);
/**
* If passed in render target already has a stencil buffer, return it. Otherwise attempt to
static const int kLargeMIP = 162;
// Callback to clear out internal path cache when eviction occurs
-void GrAADistanceFieldPathRenderer::HandleEviction(GrBatchAtlas::AtlasID id, void* pr) {
+void GrAADistanceFieldPathRenderer::HandleEviction(GrDrawOpAtlas::AtlasID id, void* pr) {
GrAADistanceFieldPathRenderer* dfpr = (GrAADistanceFieldPathRenderer*)pr;
// remove any paths that use this plot
ShapeDataList::Iter iter;
using ShapeDataList = GrAADistanceFieldPathRenderer::ShapeDataList;
static sk_sp<GrDrawOp> Make(GrColor color, const GrShape& shape, const SkMatrix& viewMatrix,
- GrBatchAtlas* atlas, ShapeCache* shapeCache,
+ GrDrawOpAtlas* atlas, ShapeCache* shapeCache,
ShapeDataList* shapeList, bool gammaCorrect) {
return sk_sp<GrDrawOp>(new AADistanceFieldPathOp(color, shape, viewMatrix, atlas,
shapeCache, shapeList, gammaCorrect));
private:
AADistanceFieldPathOp(GrColor color, const GrShape& shape, const SkMatrix& viewMatrix,
- GrBatchAtlas* atlas, ShapeCache* shapeCache, ShapeDataList* shapeList,
+ GrDrawOpAtlas* atlas, ShapeCache* shapeCache, ShapeDataList* shapeList,
bool gammaCorrect)
: INHERITED(ClassID()) {
SkASSERT(shape.hasUnstyledKey());
FlushInfo flushInfo;
// Setup GrGeometryProcessor
- GrBatchAtlas* atlas = fAtlas;
+ GrDrawOpAtlas* atlas = fAtlas;
flushInfo.fGeometryProcessor = GrDistanceFieldPathGeoProc::Make(this->color(),
this->viewMatrix(),
atlas->getTexture(),
this->flush(target, &flushInfo);
}
- bool addPathToAtlas(GrMeshDrawOp::Target* target, FlushInfo* flushInfo, GrBatchAtlas* atlas,
+ bool addPathToAtlas(GrMeshDrawOp::Target* target, FlushInfo* flushInfo, GrDrawOpAtlas* atlas,
ShapeData* shapeData, const GrShape& shape, uint32_t dimension,
SkScalar scale) const {
const SkRect& bounds = shape.bounds();
// add to atlas
SkIPoint16 atlasLocation;
- GrBatchAtlas::AtlasID id;
+ GrDrawOpAtlas::AtlasID id;
if (!atlas->addToAtlas(&id, target, width, height, dfStorage.get(), &atlasLocation)) {
this->flush(target, flushInfo);
if (!atlas->addToAtlas(&id, target, width, height, dfStorage.get(), &atlasLocation)) {
}
void writePathVertices(GrDrawOp::Target* target,
- GrBatchAtlas* atlas,
+ GrDrawOpAtlas* atlas,
intptr_t offset,
GrColor color,
size_t vertexStride,
SkScalar maxScale,
const ShapeData* shapeData) const {
-
SkPoint* positions = reinterpret_cast<SkPoint*>(offset);
// vertex positions
};
SkSTArray<1, Entry> fShapes;
- GrBatchAtlas* fAtlas;
+ GrDrawOpAtlas* fAtlas;
ShapeCache* fShapeCache;
ShapeDataList* fShapeList;
bool fGammaCorrect;
fShapeCache.reset();
}
- static void HandleEviction(GrBatchAtlas::AtlasID id, void* pr) {
+ static void HandleEviction(GrDrawOpAtlas::AtlasID id, void* pr) {
PathTestStruct* dfpr = (PathTestStruct*)pr;
// remove any paths that use this plot
ShapeDataList::Iter iter;
}
uint32_t fContextID;
- std::unique_ptr<GrBatchAtlas> fAtlas;
+ std::unique_ptr<GrDrawOpAtlas> fAtlas;
ShapeCache fShapeCache;
ShapeDataList fShapeList;
};
// 64x64 max, 128x128 max) and the GrShape's key.
SkAutoSTArray<24, uint32_t> fKey;
};
- Key fKey;
- GrBatchAtlas::AtlasID fID;
- SkRect fBounds;
- SkRect fTexCoords;
+ Key fKey;
+ GrDrawOpAtlas::AtlasID fID;
+ SkRect fBounds;
+ SkRect fTexCoords;
SK_DECLARE_INTERNAL_LLIST_INTERFACE(ShapeData);
static inline const Key& GetKey(const ShapeData& data) {
}
};
- static void HandleEviction(GrBatchAtlas::AtlasID, void*);
+ static void HandleEviction(GrDrawOpAtlas::AtlasID, void*);
typedef SkTDynamicHash<ShapeData, ShapeData::Key> ShapeCache;
typedef SkTInternalLList<ShapeData> ShapeDataList;
- std::unique_ptr<GrBatchAtlas> fAtlas;
+ std::unique_ptr<GrDrawOpAtlas> fAtlas;
ShapeCache fShapeCache;
ShapeDataList fShapeList;
}
}
-void GrAtlasGlyphCache::HandleEviction(GrBatchAtlas::AtlasID id, void* ptr) {
+void GrAtlasGlyphCache::HandleEviction(GrDrawOpAtlas::AtlasID id, void* ptr) {
GrAtlasGlyphCache* fontCache = reinterpret_cast<GrAtlasGlyphCache*>(ptr);
StrikeHash::Iter iter(&fontCache->fCache);
}
#endif
-void GrAtlasGlyphCache::setAtlasSizes_ForTesting(const GrBatchAtlasConfig configs[3]) {
+void GrAtlasGlyphCache::setAtlasSizes_ForTesting(const GrDrawOpAtlasConfig configs[3]) {
// Delete any old atlases.
// This should be safe to do as long as we are not in the middle of a flush.
for (int i = 0; i < kMaskFormatCount; i++) {
return glyph;
}
-void GrAtlasTextStrike::removeID(GrBatchAtlas::AtlasID id) {
+void GrAtlasTextStrike::removeID(GrDrawOpAtlas::AtlasID id) {
SkTDynamicHash<GrGlyph, GrGlyph::PackedID>::Iter iter(&fCache);
while (!iter.done()) {
if (id == (*iter).fID) {
- (*iter).fID = GrBatchAtlas::kInvalidAtlasID;
+ (*iter).fID = GrDrawOpAtlas::kInvalidAtlasID;
fAtlasedGlyphs--;
SkASSERT(fAtlasedGlyphs >= 0);
}
glyph->width(), glyph->height(),
storage.get(), &glyph->fAtlasLocation);
if (success) {
- SkASSERT(GrBatchAtlas::kInvalidAtlasID != glyph->fID);
+ SkASSERT(GrDrawOpAtlas::kInvalidAtlasID != glyph->fID);
fAtlasedGlyphs++;
}
return success;
#ifndef GrAtlasGlyphCache_DEFINED
#define GrAtlasGlyphCache_DEFINED
-#include "GrDrawOpAtlas.h"
#include "GrCaps.h"
+#include "GrDrawOpAtlas.h"
#include "GrGlyph.h"
#include "SkGlyphCache.h"
#include "SkTDynamicHash.h"
int countGlyphs() const { return fCache.count(); }
// remove any references to this plot
- void removeID(GrBatchAtlas::AtlasID);
+ void removeID(GrDrawOpAtlas::AtlasID);
// If a TextStrike is abandoned by the cache, then the caller must get a new strike
bool isAbandoned() const { return fIsAbandoned; }
friend class GrAtlasGlyphCache;
};
-/*
+/**
* GrAtlasGlyphCache manages strikes which are indexed by a SkGlyphCache. These strikes can then be
- * used to generate individual Glyph Masks. The GrAtlasGlyphCache also manages GrBatchAtlases,
+ * used to generate individual Glyph Masks. The GrAtlasGlyphCache also manages GrDrawOpAtlases,
* though this is more or less transparent to the client(aside from atlasGeneration, described
* below).
*/
return this->getAtlas(glyph->fMaskFormat)->hasID(glyph->fID);
}
- // To ensure the GrBatchAtlas does not evict the Glyph Mask from its texture backing store,
+ // To ensure the GrDrawOpAtlas does not evict the Glyph Mask from its texture backing store,
// the client must pass in the current op token along with the GrGlyph.
// A BulkUseTokenUpdater is used to manage bulk last use token updating in the Atlas.
// For convenience, this function will also set the use token for the current glyph if required
// NOTE: the bulk uploader is only valid if the subrun has a valid atlasGeneration
- void addGlyphToBulkAndSetUseToken(GrBatchAtlas::BulkUseTokenUpdater* updater,
- GrGlyph* glyph, GrDrawOpUploadToken token) {
+ void addGlyphToBulkAndSetUseToken(GrDrawOpAtlas::BulkUseTokenUpdater* updater, GrGlyph* glyph,
+ GrDrawOpUploadToken token) {
SkASSERT(glyph);
updater->add(glyph->fID);
this->getAtlas(glyph->fMaskFormat)->setLastUseToken(glyph->fID, token);
}
- void setUseTokenBulk(const GrBatchAtlas::BulkUseTokenUpdater& updater,
+ void setUseTokenBulk(const GrDrawOpAtlas::BulkUseTokenUpdater& updater,
GrDrawOpUploadToken token,
GrMaskFormat format) {
this->getAtlas(format)->setLastUseTokenBulk(updater, token);
}
// add to texture atlas that matches this format
- bool addToAtlas(GrAtlasTextStrike* strike, GrBatchAtlas::AtlasID* id,
- GrDrawOp::Target* target,
+ bool addToAtlas(GrAtlasTextStrike* strike, GrDrawOpAtlas::AtlasID* id, GrDrawOp::Target* target,
GrMaskFormat format, int width, int height, const void* image,
SkIPoint16* loc) {
fPreserveStrike = strike;
}
// Some clients may wish to verify the integrity of the texture backing store of the
- // GrBatchAtlas. The atlasGeneration returned below is a monotonically increasing number which
+ // GrDrawOpAtlas. The atlasGeneration returned below is a monotonically increasing number which
// changes every time something is removed from the texture backing store.
uint64_t atlasGeneration(GrMaskFormat format) const {
return this->getAtlas(format)->atlasGeneration();
void dump() const;
#endif
- void setAtlasSizes_ForTesting(const GrBatchAtlasConfig configs[3]);
+ void setAtlasSizes_ForTesting(const GrDrawOpAtlasConfig configs[3]);
private:
static GrPixelConfig MaskFormatToPixelConfig(GrMaskFormat format, const GrCaps& caps) {
return strike;
}
- GrBatchAtlas* getAtlas(GrMaskFormat format) const {
+ GrDrawOpAtlas* getAtlas(GrMaskFormat format) const {
int atlasIndex = MaskFormatToAtlasIndex(format);
SkASSERT(fAtlases[atlasIndex]);
return fAtlases[atlasIndex].get();
}
- static void HandleEviction(GrBatchAtlas::AtlasID, void*);
+ static void HandleEviction(GrDrawOpAtlas::AtlasID, void*);
using StrikeHash = SkTDynamicHash<GrAtlasTextStrike, SkDescriptor>;
GrContext* fContext;
StrikeHash fCache;
- std::unique_ptr<GrBatchAtlas> fAtlases[kMaskFormatCount];
+ std::unique_ptr<GrDrawOpAtlas> fAtlases[kMaskFormatCount];
GrAtlasTextStrike* fPreserveStrike;
- GrBatchAtlasConfig fAtlasConfigs[kMaskFormatCount];
+ GrDrawOpAtlasConfig fAtlasConfigs[kMaskFormatCount];
};
#endif
#define GrAtlasTextBlob_DEFINED
#include "GrAtlasGlyphCache.h"
-#include "GrDrawOpAtlas.h"
#include "GrColor.h"
+#include "GrDrawOpAtlas.h"
#include "GrMemoryPool.h"
#include "SkDescriptor.h"
#include "SkMaskFilter.h"
}
struct SubRunInfo {
SubRunInfo()
- : fAtlasGeneration(GrBatchAtlas::kInvalidAtlasGeneration)
- , fVertexStartIndex(0)
- , fVertexEndIndex(0)
- , fGlyphStartIndex(0)
- , fGlyphEndIndex(0)
- , fColor(GrColor_ILLEGAL)
- , fMaskFormat(kA8_GrMaskFormat)
- , fDrawAsDistanceFields(false)
- , fUseLCDText(false) {
+ : fAtlasGeneration(GrDrawOpAtlas::kInvalidAtlasGeneration)
+ , fVertexStartIndex(0)
+ , fVertexEndIndex(0)
+ , fGlyphStartIndex(0)
+ , fGlyphEndIndex(0)
+ , fColor(GrColor_ILLEGAL)
+ , fMaskFormat(kA8_GrMaskFormat)
+ , fDrawAsDistanceFields(false)
+ , fUseLCDText(false) {
fVertexBounds.setLargestInverted();
}
SubRunInfo(const SubRunInfo& that)
// TODO when this object is more internal, drop the privacy
void resetBulkUseToken() { fBulkUseToken.reset(); }
- GrBatchAtlas::BulkUseTokenUpdater* bulkUseToken() { return &fBulkUseToken; }
+ GrDrawOpAtlas::BulkUseTokenUpdater* bulkUseToken() { return &fBulkUseToken; }
void setStrike(GrAtlasTextStrike* strike) { fStrike.reset(SkRef(strike)); }
GrAtlasTextStrike* strike() const { return fStrike.get(); }
bool drawAsDistanceFields() const { return fDrawAsDistanceFields; }
private:
- GrBatchAtlas::BulkUseTokenUpdater fBulkUseToken;
+ GrDrawOpAtlas::BulkUseTokenUpdater fBulkUseToken;
sk_sp<GrAtlasTextStrike> fStrike;
SkMatrix fCurrentViewMatrix;
SkRect fVertexBounds;
if (regenGlyphs) {
info->setStrike(strike);
}
- info->setAtlasGeneration(brokenRun ? GrBatchAtlas::kInvalidAtlasGeneration :
- fontCache->atlasGeneration(info->maskFormat()));
+ info->setAtlasGeneration(brokenRun ? GrDrawOpAtlas::kInvalidAtlasGeneration
+ : fontCache->atlasGeneration(info->maskFormat()));
}
}
#include "GrTest.h"
-#include "GrDrawOpAtlas.h"
#include "GrContextOptions.h"
-#include "GrRenderTargetContextPriv.h"
+#include "GrDrawOpAtlas.h"
#include "GrDrawingManager.h"
#include "GrGpuResourceCacheAccess.h"
#include "GrPipelineBuilder.h"
+#include "GrRenderTargetContextPriv.h"
#include "GrRenderTargetProxy.h"
#include "GrResourceCache.h"
void SetupAlwaysEvictAtlas(GrContext* context) {
// These sizes were selected because they allow each atlas to hold a single plot and will thus
// stress the atlas
- int dim = GrBatchAtlas::kGlyphMaxDim;
- GrBatchAtlasConfig configs[3];
+ int dim = GrDrawOpAtlas::kGlyphMaxDim;
+ GrDrawOpAtlasConfig configs[3];
configs[kA8_GrMaskFormat].fWidth = dim;
configs[kA8_GrMaskFormat].fHeight = dim;
configs[kA8_GrMaskFormat].fLog2Width = SkNextLog2(dim);
fTextBlobCache->setBudget(bytes);
}
-void GrContext::setTextContextAtlasSizes_ForTesting(const GrBatchAtlasConfig* configs) {
+void GrContext::setTextContextAtlasSizes_ForTesting(const GrDrawOpAtlasConfig* configs) {
fAtlasGlyphCache->setAtlasSizes_ForTesting(configs);
}