• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright 2010 Google Inc.
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 
9 
10 
11 #include "GrAtlas.h"
12 #include "GrContext.h"
13 #include "GrGpu.h"
14 #include "GrRectanizer.h"
15 #include "GrPlotMgr.h"
16 
17 #if 0
18 #define GR_PLOT_WIDTH   8
19 #define GR_PLOT_HEIGHT  4
20 #define GR_ATLAS_WIDTH  256
21 #define GR_ATLAS_HEIGHT 256
22 
23 #define GR_ATLAS_TEXTURE_WIDTH  (GR_PLOT_WIDTH * GR_ATLAS_WIDTH)
24 #define GR_ATLAS_TEXTURE_HEIGHT (GR_PLOT_HEIGHT * GR_ATLAS_HEIGHT)
25 
26 #else
27 
28 #define GR_ATLAS_TEXTURE_WIDTH  1024
29 #define GR_ATLAS_TEXTURE_HEIGHT 2048
30 
31 #define GR_ATLAS_WIDTH  341
32 #define GR_ATLAS_HEIGHT 341
33 
34 #define GR_PLOT_WIDTH   (GR_ATLAS_TEXTURE_WIDTH / GR_ATLAS_WIDTH)
35 #define GR_PLOT_HEIGHT  (GR_ATLAS_TEXTURE_HEIGHT / GR_ATLAS_HEIGHT)
36 
37 #endif
38 
39 ///////////////////////////////////////////////////////////////////////////////
40 
41 #define BORDER      1
42 
43 #if GR_DEBUG
44     static int gCounter;
45 #endif
46 
GrAtlas(GrAtlasMgr * mgr,int plotX,int plotY,GrMaskFormat format)47 GrAtlas::GrAtlas(GrAtlasMgr* mgr, int plotX, int plotY, GrMaskFormat format) {
48     fAtlasMgr = mgr;    // just a pointer, not an owner
49     fNext = NULL;
50     fTexture = mgr->getTexture(format); // we're not an owner, just a pointer
51     fPlot.set(plotX, plotY);
52 
53     fRects = GrRectanizer::Factory(GR_ATLAS_WIDTH - BORDER,
54                                    GR_ATLAS_HEIGHT - BORDER);
55 
56     fMaskFormat = format;
57 
58 #if GR_DEBUG
59 //    GrPrintf(" GrAtlas %p [%d %d] %d\n", this, plotX, plotY, gCounter);
60     gCounter += 1;
61 #endif
62 }
63 
~GrAtlas()64 GrAtlas::~GrAtlas() {
65     fAtlasMgr->freePlot(fPlot.fX, fPlot.fY);
66 
67     delete fRects;
68 
69 #if GR_DEBUG
70     --gCounter;
71 //    GrPrintf("~GrAtlas %p [%d %d] %d\n", this, fPlot.fX, fPlot.fY, gCounter);
72 #endif
73 }
74 
adjustForPlot(GrIPoint16 * loc,const GrIPoint16 & plot)75 static void adjustForPlot(GrIPoint16* loc, const GrIPoint16& plot) {
76     loc->fX += plot.fX * GR_ATLAS_WIDTH;
77     loc->fY += plot.fY * GR_ATLAS_HEIGHT;
78 }
79 
zerofill(uint8_t * ptr,int count)80 static uint8_t* zerofill(uint8_t* ptr, int count) {
81     while (--count >= 0) {
82         *ptr++ = 0;
83     }
84     return ptr;
85 }
86 
addSubImage(int width,int height,const void * image,GrIPoint16 * loc)87 bool GrAtlas::addSubImage(int width, int height, const void* image,
88                           GrIPoint16* loc) {
89     if (!fRects->addRect(width + BORDER, height + BORDER, loc)) {
90         return false;
91     }
92 
93     SkAutoSMalloc<1024> storage;
94     int dstW = width + 2*BORDER;
95     int dstH = height + 2*BORDER;
96     if (BORDER) {
97         const int bpp = GrMaskFormatBytesPerPixel(fMaskFormat);
98         const size_t dstRB = dstW * bpp;
99         uint8_t* dst = (uint8_t*)storage.reset(dstH * dstRB);
100         Gr_bzero(dst, dstRB);                // zero top row
101         dst += dstRB;
102         for (int y = 0; y < height; y++) {
103             dst = zerofill(dst, bpp);   // zero left edge
104             memcpy(dst, image, width * bpp);
105             dst += width * bpp;
106             dst = zerofill(dst, bpp);   // zero right edge
107             image = (const void*)((const char*)image + width * bpp);
108         }
109         Gr_bzero(dst, dstRB);                // zero bottom row
110         image = storage.get();
111     }
112     adjustForPlot(loc, fPlot);
113     GrContext* context = fTexture->getContext();
114     // We call the internal version so that we don't force a flush. We assume
115     // our caller is smart and hasn't referenced the part of the texture we're
116     // about to update since the last flush.
117     context->internalWriteTexturePixels(fTexture, loc->fX, loc->fY,
118                                         dstW, dstH, fTexture->config(),
119                                         image, 0,
120                                         GrContext::kDontFlush_PixelOpsFlag);
121 
122     // now tell the caller to skip the top/left BORDER
123     loc->fX += BORDER;
124     loc->fY += BORDER;
125     return true;
126 }
127 
128 ///////////////////////////////////////////////////////////////////////////////
129 
GrAtlasMgr(GrGpu * gpu)130 GrAtlasMgr::GrAtlasMgr(GrGpu* gpu) {
131     fGpu = gpu;
132     gpu->ref();
133     Gr_bzero(fTexture, sizeof(fTexture));
134     fPlotMgr = new GrPlotMgr(GR_PLOT_WIDTH, GR_PLOT_HEIGHT);
135 }
136 
~GrAtlasMgr()137 GrAtlasMgr::~GrAtlasMgr() {
138     for (size_t i = 0; i < GR_ARRAY_COUNT(fTexture); i++) {
139         GrSafeUnref(fTexture[i]);
140     }
141     delete fPlotMgr;
142     fGpu->unref();
143 }
144 
maskformat2pixelconfig(GrMaskFormat format)145 static GrPixelConfig maskformat2pixelconfig(GrMaskFormat format) {
146     switch (format) {
147         case kA8_GrMaskFormat:
148             return kAlpha_8_GrPixelConfig;
149         case kA565_GrMaskFormat:
150             return kRGB_565_GrPixelConfig;
151         case kA888_GrMaskFormat:
152             return kSkia8888_PM_GrPixelConfig;
153         default:
154             GrAssert(!"unknown maskformat");
155     }
156     return kUnknown_GrPixelConfig;
157 }
158 
addToAtlas(GrAtlas * atlas,int width,int height,const void * image,GrMaskFormat format,GrIPoint16 * loc)159 GrAtlas* GrAtlasMgr::addToAtlas(GrAtlas* atlas,
160                                 int width, int height, const void* image,
161                                 GrMaskFormat format,
162                                 GrIPoint16* loc) {
163     GrAssert(NULL == atlas || atlas->getMaskFormat() == format);
164 
165     if (atlas && atlas->addSubImage(width, height, image, loc)) {
166         return atlas;
167     }
168 
169     // If the above fails, then either we have no starting atlas, or the current
170     // one is full. Either way we need to allocate a new atlas
171 
172     GrIPoint16 plot;
173     if (!fPlotMgr->newPlot(&plot)) {
174         return NULL;
175     }
176 
177     GrAssert(0 == kA8_GrMaskFormat);
178     GrAssert(1 == kA565_GrMaskFormat);
179     if (NULL == fTexture[format]) {
180         GrTextureDesc desc = {
181             kDynamicUpdate_GrTextureFlagBit,
182             GR_ATLAS_TEXTURE_WIDTH,
183             GR_ATLAS_TEXTURE_HEIGHT,
184             maskformat2pixelconfig(format),
185             {0} // samples
186         };
187         fTexture[format] = fGpu->createTexture(desc, NULL, 0);
188         if (NULL == fTexture[format]) {
189             return NULL;
190         }
191     }
192 
193     GrAtlas* newAtlas = new GrAtlas(this, plot.fX, plot.fY, format);
194     if (!newAtlas->addSubImage(width, height, image, loc)) {
195         delete newAtlas;
196         return NULL;
197     }
198 
199     newAtlas->fNext = atlas;
200     return newAtlas;
201 }
202 
freePlot(int x,int y)203 void GrAtlasMgr::freePlot(int x, int y) {
204     GrAssert(fPlotMgr->isBusy(x, y));
205     fPlotMgr->freePlot(x, y);
206 }
207 
208 
209