Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(209)

Unified Diff: src/gpu/GrAtlas.cpp

Issue 269423007: Add CPU backing store for GrAtlas to reduce texture uploads (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Turn on texture update for distance fields Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/gpu/GrAtlas.h ('k') | src/gpu/GrBitmapTextContext.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/gpu/GrAtlas.cpp
diff --git a/src/gpu/GrAtlas.cpp b/src/gpu/GrAtlas.cpp
index 008bae2f00eaf3812bb7121d6f52941338cd86fb..6809a087e794923c2fde4bc80b38cf8eeda08be9 100644
--- a/src/gpu/GrAtlas.cpp
+++ b/src/gpu/GrAtlas.cpp
@@ -29,6 +29,8 @@ GrPlot::GrPlot() : fDrawToken(NULL, 0)
}
GrPlot::~GrPlot() {
+ SkDELETE_ARRAY(fPlotData);
+ fPlotData = NULL;
delete fRects;
}
@@ -37,6 +39,9 @@ void GrPlot::init(GrAtlasMgr* mgr, int offX, int offY, int width, int height, si
fAtlasMgr = mgr;
fOffset.set(offX * width, offY * height);
fBytesPerPixel = bpp;
+ fPlotData = NULL;
+ fDirtyRect.setEmpty();
+ fDirty = false;
}
static inline void adjust_for_offset(GrIPoint16* loc, const GrIPoint16& offset) {
@@ -46,20 +51,45 @@ static inline void adjust_for_offset(GrIPoint16* loc, const GrIPoint16& offset)
bool GrPlot::addSubImage(int width, int height, const void* image,
GrIPoint16* loc) {
+ float percentFull = fRects->percentFull();
if (!fRects->addRect(width, height, loc)) {
return false;
}
- SkAutoSMalloc<1024> storage;
- adjust_for_offset(loc, fOffset);
- GrContext* context = fTexture->getContext();
- // We pass the flag that does not force a flush. We assume our caller is
- // smart and hasn't referenced the part of the texture we're about to update
- // since the last flush.
- context->writeTexturePixels(fTexture,
- loc->fX, loc->fY, width, height,
- fTexture->config(), image, 0,
- GrContext::kDontFlush_PixelOpsFlag);
+ // create backing memory on first use
robertphillips 2014/05/12 19:45:52 // Once the plot is nearly full we will revert to
jvanverth1 2014/05/12 20:44:04 Done.
+ int plotWidth = fRects->width();
+ int plotHeight = fRects->height();
+ if (NULL == fPlotData && 0.0f == percentFull) {
+ fPlotData = SkNEW_ARRAY(unsigned char, fBytesPerPixel*plotWidth*plotHeight);
+ memset(fPlotData, 0, fBytesPerPixel*plotWidth*plotHeight);
+ }
+
+ // if we have backing memory, copy to the memory and set for future upload
+ if (NULL != fPlotData) {
robertphillips 2014/05/12 19:45:52 const unsigned char* ?
jvanverth1 2014/05/12 20:44:04 Done.
+ unsigned char* imagePtr = (unsigned char*) image;
+ // point ourselves at the right starting spot
+ unsigned char* dataPtr = fPlotData;
+ dataPtr += fBytesPerPixel*plotWidth*loc->fY;
+ dataPtr += fBytesPerPixel*loc->fX;
+ // copy into the data buffer
+ for (int i = 0; i < height; ++i) {
+ memcpy(dataPtr, imagePtr, fBytesPerPixel*width);
+ dataPtr += fBytesPerPixel*plotWidth;
+ imagePtr += fBytesPerPixel*width;
+ }
+
+ fDirtyRect.join(loc->fX, loc->fY, loc->fX + width, loc->fY + height);
+ adjust_for_offset(loc, fOffset);
+ fDirty = true;
+ // otherwise, just upload the image directly
+ } else {
+ adjust_for_offset(loc, fOffset);
+ GrContext* context = fTexture->getContext();
+ context->writeTexturePixels(fTexture,
+ loc->fX, loc->fY, width, height,
+ fTexture->config(), image, 0,
+ GrContext::kDontFlush_PixelOpsFlag);
+ }
#if FONT_CACHE_STATS
++g_UploadCount;
@@ -68,6 +98,33 @@ bool GrPlot::addSubImage(int width, int height, const void* image,
return true;
}
+void GrPlot::uploadToTexture() {
+ if (fDirty && NULL != fTexture) {
+ GrContext* context = fTexture->getContext();
+ // We pass the flag that does not force a flush. We assume our caller is
+ // smart and hasn't referenced the part of the texture we're about to update
+ // since the last flush.
+ int rowBytes = fBytesPerPixel*fRects->width();
robertphillips 2014/05/12 19:45:52 const unsigned char* ?
jvanverth1 2014/05/12 20:44:04 Done.
+ unsigned char* dataPtr = fPlotData;
+ dataPtr += rowBytes*fDirtyRect.fTop;
+ dataPtr += fBytesPerPixel*fDirtyRect.fLeft;
+ context->writeTexturePixels(fTexture,
+ fOffset.fX + fDirtyRect.fLeft, fOffset.fY + fDirtyRect.fTop,
+ fDirtyRect.width(), fDirtyRect.height(),
+ fTexture->config(), dataPtr,
+ rowBytes,
+ GrContext::kDontFlush_PixelOpsFlag);
+ fDirtyRect.setEmpty();
+ // If the Plot is nearly full, anything else we add will probably be small and one
+ // at a time, so free up the memory and upload any new images directly.
robertphillips 2014/05/12 19:45:52 static const int kNearlyFullTolerance = 0.85f; ?
jvanverth1 2014/05/12 20:44:04 Done.
+ if (fRects->percentFull() > 0.85f) {
+ SkDELETE_ARRAY(fPlotData);
+ fPlotData = NULL;
+ }
+ }
robertphillips 2014/05/12 19:45:52 It seems like if we're going to clear fDirty out h
jvanverth1 2014/05/12 20:44:04 Cleaned up. We shouldn't hit the 'if' block unless
+ fDirty = false;
+}
+
void GrPlot::resetRects() {
SkASSERT(NULL != fRects);
fRects->reset();
@@ -85,11 +142,14 @@ GrAtlasMgr::GrAtlasMgr(GrGpu* gpu, GrPixelConfig config,
fNumPlotsY = numPlotsY;
fTexture = NULL;
- int plotWidth = fBackingTextureSize.width() / fNumPlotsX;
- int plotHeight = fBackingTextureSize.height() / fNumPlotsY;
+ int textureWidth = fBackingTextureSize.width();
+ int textureHeight = fBackingTextureSize.height();
- SkASSERT(plotWidth * fNumPlotsX == fBackingTextureSize.width());
- SkASSERT(plotHeight * fNumPlotsY == fBackingTextureSize.height());
+ int plotWidth = textureWidth / fNumPlotsX;
+ int plotHeight = textureHeight / fNumPlotsY;
+
+ SkASSERT(plotWidth * fNumPlotsX == textureWidth);
+ SkASSERT(plotHeight * fNumPlotsY == textureHeight);
// set up allocated plots
size_t bpp = GrBytesPerPixel(fPixelConfig);
@@ -201,3 +261,13 @@ GrPlot* GrAtlasMgr::getUnusedPlot() {
return NULL;
}
+
+void GrAtlasMgr::uploadPlotsToTexture() {
+ GrPlotList::Iter plotIter;
+ plotIter.init(fPlotList, GrPlotList::Iter::kHead_IterStart);
+ GrPlot* plot;
+ while (NULL != (plot = plotIter.get())) {
+ plot->uploadToTexture();
+ plotIter.next();
+ }
+}
« no previous file with comments | « src/gpu/GrAtlas.h ('k') | src/gpu/GrBitmapTextContext.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698