• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2     Copyright 2010 Google Inc.
3 
4     Licensed under the Apache License, Version 2.0 (the "License");
5     you may not use this file except in compliance with the License.
6     You may obtain a copy of the License at
7 
8          http://www.apache.org/licenses/LICENSE-2.0
9 
10     Unless required by applicable law or agreed to in writing, software
11     distributed under the License is distributed on an "AS IS" BASIS,
12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13     See the License for the specific language governing permissions and
14     limitations under the License.
15  */
16 
17 
18 #include "GrAtlas.h"
19 #include "GrGpu.h"
20 #include "GrMemory.h"
21 #include "GrRectanizer.h"
22 #include "GrPlotMgr.h"
23 
24 #if 0
25 #define GR_PLOT_WIDTH   8
26 #define GR_PLOT_HEIGHT  4
27 #define GR_ATLAS_WIDTH  256
28 #define GR_ATLAS_HEIGHT 256
29 
30 #define GR_ATLAS_TEXTURE_WIDTH  (GR_PLOT_WIDTH * GR_ATLAS_WIDTH)
31 #define GR_ATLAS_TEXTURE_HEIGHT (GR_PLOT_HEIGHT * GR_ATLAS_HEIGHT)
32 
33 #else
34 
35 #define GR_ATLAS_TEXTURE_WIDTH  1024
36 #define GR_ATLAS_TEXTURE_HEIGHT 2048
37 
38 #define GR_ATLAS_WIDTH  341
39 #define GR_ATLAS_HEIGHT 341
40 
41 #define GR_PLOT_WIDTH   (GR_ATLAS_TEXTURE_WIDTH / GR_ATLAS_WIDTH)
42 #define GR_PLOT_HEIGHT  (GR_ATLAS_TEXTURE_HEIGHT / GR_ATLAS_HEIGHT)
43 
44 #endif
45 
46 ///////////////////////////////////////////////////////////////////////////////
47 
48 #define BORDER      1
49 
50 #if GR_DEBUG
51     static int gCounter;
52 #endif
53 
GrAtlas(GrAtlasMgr * mgr,int plotX,int plotY,GrMaskFormat format)54 GrAtlas::GrAtlas(GrAtlasMgr* mgr, int plotX, int plotY, GrMaskFormat format) {
55     fAtlasMgr = mgr;    // just a pointer, not an owner
56     fNext = NULL;
57     fTexture = mgr->getTexture(format); // we're not an owner, just a pointer
58     fPlot.set(plotX, plotY);
59 
60     fRects = GrRectanizer::Factory(GR_ATLAS_WIDTH - BORDER,
61                                    GR_ATLAS_HEIGHT - BORDER);
62 
63     fMaskFormat = format;
64 
65 #if GR_DEBUG
66     GrPrintf(" GrAtlas %p [%d %d] %d\n", this, plotX, plotY, gCounter);
67     gCounter += 1;
68 #endif
69 }
70 
~GrAtlas()71 GrAtlas::~GrAtlas() {
72     fAtlasMgr->freePlot(fPlot.fX, fPlot.fY);
73 
74     delete fRects;
75 
76 #if GR_DEBUG
77     --gCounter;
78     GrPrintf("~GrAtlas %p [%d %d] %d\n", this, fPlot.fX, fPlot.fY, gCounter);
79 #endif
80 }
81 
adjustForPlot(GrIPoint16 * loc,const GrIPoint16 & plot)82 static void adjustForPlot(GrIPoint16* loc, const GrIPoint16& plot) {
83     loc->fX += plot.fX * GR_ATLAS_WIDTH;
84     loc->fY += plot.fY * GR_ATLAS_HEIGHT;
85 }
86 
zerofill(uint8_t * ptr,int count)87 static uint8_t* zerofill(uint8_t* ptr, int count) {
88     while (--count >= 0) {
89         *ptr++ = 0;
90     }
91     return ptr;
92 }
93 
addSubImage(int width,int height,const void * image,GrIPoint16 * loc)94 bool GrAtlas::addSubImage(int width, int height, const void* image,
95                           GrIPoint16* loc) {
96     if (!fRects->addRect(width + BORDER, height + BORDER, loc)) {
97         return false;
98     }
99 
100     GrAutoSMalloc<1024> storage;
101     int dstW = width + 2*BORDER;
102     int dstH = height + 2*BORDER;
103     if (BORDER) {
104         const int bpp = GrMaskFormatBytesPerPixel(fMaskFormat);
105         const size_t dstRB = dstW * bpp;
106         uint8_t* dst = (uint8_t*)storage.realloc(dstH * dstRB);
107         Gr_bzero(dst, dstRB);                // zero top row
108         dst += dstRB;
109         for (int y = 0; y < height; y++) {
110             dst = zerofill(dst, bpp);   // zero left edge
111             memcpy(dst, image, width * bpp);
112             dst += width * bpp;
113             dst = zerofill(dst, bpp);   // zero right edge
114             image = (const void*)((const char*)image + width * bpp);
115         }
116         Gr_bzero(dst, dstRB);                // zero bottom row
117         image = storage.get();
118     }
119     adjustForPlot(loc, fPlot);
120     fTexture->uploadTextureData(loc->fX, loc->fY, dstW, dstH, image);
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         default:
152             GrAssert(!"unknown maskformat");
153     }
154     return kUnknown_GrPixelConfig;
155 }
156 
addToAtlas(GrAtlas * atlas,int width,int height,const void * image,GrMaskFormat format,GrIPoint16 * loc)157 GrAtlas* GrAtlasMgr::addToAtlas(GrAtlas* atlas,
158                                 int width, int height, const void* image,
159                                 GrMaskFormat format,
160                                 GrIPoint16* loc) {
161     GrAssert(NULL == atlas || atlas->getMaskFormat() == format);
162 
163     if (atlas && atlas->addSubImage(width, height, image, loc)) {
164         return atlas;
165     }
166 
167     // If the above fails, then either we have no starting atlas, or the current
168     // one is full. Either way we need to allocate a new atlas
169 
170     GrIPoint16 plot;
171     if (!fPlotMgr->newPlot(&plot)) {
172         return NULL;
173     }
174 
175     GrAssert(0 == kA8_GrMaskFormat);
176     GrAssert(1 == kA565_GrMaskFormat);
177     if (NULL == fTexture[format]) {
178         GrTextureDesc desc = {
179             kDynamicUpdate_GrTextureFlagBit,
180             kNone_GrAALevel,
181             GR_ATLAS_TEXTURE_WIDTH,
182             GR_ATLAS_TEXTURE_HEIGHT,
183             maskformat2pixelconfig(format)
184         };
185         fTexture[format] = fGpu->createTexture(desc, NULL, 0);
186         if (NULL == fTexture[format]) {
187             return NULL;
188         }
189     }
190 
191     GrAtlas* newAtlas = new GrAtlas(this, plot.fX, plot.fY, format);
192     if (!newAtlas->addSubImage(width, height, image, loc)) {
193         delete newAtlas;
194         return NULL;
195     }
196 
197     newAtlas->fNext = atlas;
198     return newAtlas;
199 }
200 
freePlot(int x,int y)201 void GrAtlasMgr::freePlot(int x, int y) {
202     GrAssert(fPlotMgr->isBusy(x, y));
203     fPlotMgr->freePlot(x, y);
204 }
205 
206 
207