blob: 0838895a1399700fd377f71314945fca21fbf968 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
reed@google.comac10a2d2010-12-22 21:39:39 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * 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.
reed@google.comac10a2d2010-12-22 21:39:39 +00007 */
8
9
epoger@google.comec3ed6a2011-07-28 14:26:00 +000010
reed@google.comac10a2d2010-12-22 21:39:39 +000011#include "GrAtlas.h"
12#include "GrGpu.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000013#include "GrRectanizer.h"
14#include "GrPlotMgr.h"
15
16#if 0
17#define GR_PLOT_WIDTH 8
18#define GR_PLOT_HEIGHT 4
19#define GR_ATLAS_WIDTH 256
20#define GR_ATLAS_HEIGHT 256
21
22#define GR_ATLAS_TEXTURE_WIDTH (GR_PLOT_WIDTH * GR_ATLAS_WIDTH)
23#define GR_ATLAS_TEXTURE_HEIGHT (GR_PLOT_HEIGHT * GR_ATLAS_HEIGHT)
24
25#else
26
27#define GR_ATLAS_TEXTURE_WIDTH 1024
28#define GR_ATLAS_TEXTURE_HEIGHT 2048
29
30#define GR_ATLAS_WIDTH 341
31#define GR_ATLAS_HEIGHT 341
32
33#define GR_PLOT_WIDTH (GR_ATLAS_TEXTURE_WIDTH / GR_ATLAS_WIDTH)
34#define GR_PLOT_HEIGHT (GR_ATLAS_TEXTURE_HEIGHT / GR_ATLAS_HEIGHT)
35
36#endif
37
38///////////////////////////////////////////////////////////////////////////////
39
40#define BORDER 1
41
42#if GR_DEBUG
43 static int gCounter;
44#endif
45
reed@google.com98539c62011-03-15 15:40:16 +000046GrAtlas::GrAtlas(GrAtlasMgr* mgr, int plotX, int plotY, GrMaskFormat format) {
reed@google.comac10a2d2010-12-22 21:39:39 +000047 fAtlasMgr = mgr; // just a pointer, not an owner
48 fNext = NULL;
reed@google.com759c16e2011-03-15 19:15:15 +000049 fTexture = mgr->getTexture(format); // we're not an owner, just a pointer
reed@google.comac10a2d2010-12-22 21:39:39 +000050 fPlot.set(plotX, plotY);
51
52 fRects = GrRectanizer::Factory(GR_ATLAS_WIDTH - BORDER,
53 GR_ATLAS_HEIGHT - BORDER);
54
reed@google.com98539c62011-03-15 15:40:16 +000055 fMaskFormat = format;
56
reed@google.comac10a2d2010-12-22 21:39:39 +000057#if GR_DEBUG
reed@google.com3ef80cf2011-07-05 19:09:47 +000058// GrPrintf(" GrAtlas %p [%d %d] %d\n", this, plotX, plotY, gCounter);
reed@google.comac10a2d2010-12-22 21:39:39 +000059 gCounter += 1;
60#endif
61}
62
63GrAtlas::~GrAtlas() {
64 fAtlasMgr->freePlot(fPlot.fX, fPlot.fY);
65
66 delete fRects;
67
68#if GR_DEBUG
69 --gCounter;
reed@google.com3ef80cf2011-07-05 19:09:47 +000070// GrPrintf("~GrAtlas %p [%d %d] %d\n", this, fPlot.fX, fPlot.fY, gCounter);
reed@google.comac10a2d2010-12-22 21:39:39 +000071#endif
72}
73
74static void adjustForPlot(GrIPoint16* loc, const GrIPoint16& plot) {
75 loc->fX += plot.fX * GR_ATLAS_WIDTH;
76 loc->fY += plot.fY * GR_ATLAS_HEIGHT;
77}
78
reed@google.com98539c62011-03-15 15:40:16 +000079static uint8_t* zerofill(uint8_t* ptr, int count) {
80 while (--count >= 0) {
81 *ptr++ = 0;
82 }
83 return ptr;
84}
85
reed@google.comac10a2d2010-12-22 21:39:39 +000086bool GrAtlas::addSubImage(int width, int height, const void* image,
87 GrIPoint16* loc) {
88 if (!fRects->addRect(width + BORDER, height + BORDER, loc)) {
89 return false;
90 }
91
bsalomon@google.com3582bf92011-06-30 21:32:31 +000092 SkAutoSMalloc<1024> storage;
reed@google.com98539c62011-03-15 15:40:16 +000093 int dstW = width + 2*BORDER;
94 int dstH = height + 2*BORDER;
reed@google.comac10a2d2010-12-22 21:39:39 +000095 if (BORDER) {
reed@google.com98539c62011-03-15 15:40:16 +000096 const int bpp = GrMaskFormatBytesPerPixel(fMaskFormat);
97 const size_t dstRB = dstW * bpp;
bsalomon@google.com7d4679a2011-09-02 22:06:24 +000098 uint8_t* dst = (uint8_t*)storage.reset(dstH * dstRB);
reed@google.com98539c62011-03-15 15:40:16 +000099 Gr_bzero(dst, dstRB); // zero top row
100 dst += dstRB;
reed@google.comac10a2d2010-12-22 21:39:39 +0000101 for (int y = 0; y < height; y++) {
reed@google.com98539c62011-03-15 15:40:16 +0000102 dst = zerofill(dst, bpp); // zero left edge
103 memcpy(dst, image, width * bpp);
104 dst += width * bpp;
105 dst = zerofill(dst, bpp); // zero right edge
106 image = (const void*)((const char*)image + width * bpp);
reed@google.comac10a2d2010-12-22 21:39:39 +0000107 }
reed@google.com98539c62011-03-15 15:40:16 +0000108 Gr_bzero(dst, dstRB); // zero bottom row
reed@google.comac10a2d2010-12-22 21:39:39 +0000109 image = storage.get();
110 }
111 adjustForPlot(loc, fPlot);
junov@google.com4ee7ae52011-06-30 17:30:49 +0000112 fTexture->uploadTextureData(loc->fX, loc->fY, dstW, dstH, image, 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000113
114 // now tell the caller to skip the top/left BORDER
115 loc->fX += BORDER;
116 loc->fY += BORDER;
117 return true;
118}
119
120///////////////////////////////////////////////////////////////////////////////
121
122GrAtlasMgr::GrAtlasMgr(GrGpu* gpu) {
123 fGpu = gpu;
124 gpu->ref();
reed@google.com759c16e2011-03-15 19:15:15 +0000125 Gr_bzero(fTexture, sizeof(fTexture));
reed@google.comac10a2d2010-12-22 21:39:39 +0000126 fPlotMgr = new GrPlotMgr(GR_PLOT_WIDTH, GR_PLOT_HEIGHT);
127}
128
129GrAtlasMgr::~GrAtlasMgr() {
reed@google.com759c16e2011-03-15 19:15:15 +0000130 for (size_t i = 0; i < GR_ARRAY_COUNT(fTexture); i++) {
131 GrSafeUnref(fTexture[i]);
132 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000133 delete fPlotMgr;
134 fGpu->unref();
135}
136
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000137static GrPixelConfig maskformat2pixelconfig(GrMaskFormat format) {
reed@google.com98539c62011-03-15 15:40:16 +0000138 switch (format) {
139 case kA8_GrMaskFormat:
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000140 return kAlpha_8_GrPixelConfig;
reed@google.com98539c62011-03-15 15:40:16 +0000141 case kA565_GrMaskFormat:
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000142 return kRGB_565_GrPixelConfig;
caryclark@google.com1eeaf0b2011-06-22 13:19:43 +0000143 case kA888_GrMaskFormat:
144 return kRGBA_8888_GrPixelConfig;
reed@google.com98539c62011-03-15 15:40:16 +0000145 default:
146 GrAssert(!"unknown maskformat");
147 }
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000148 return kUnknown_GrPixelConfig;
reed@google.com98539c62011-03-15 15:40:16 +0000149}
150
reed@google.comac10a2d2010-12-22 21:39:39 +0000151GrAtlas* GrAtlasMgr::addToAtlas(GrAtlas* atlas,
152 int width, int height, const void* image,
reed@google.com98539c62011-03-15 15:40:16 +0000153 GrMaskFormat format,
reed@google.comac10a2d2010-12-22 21:39:39 +0000154 GrIPoint16* loc) {
reed@google.com98539c62011-03-15 15:40:16 +0000155 GrAssert(NULL == atlas || atlas->getMaskFormat() == format);
reed@google.com759c16e2011-03-15 19:15:15 +0000156
reed@google.comac10a2d2010-12-22 21:39:39 +0000157 if (atlas && atlas->addSubImage(width, height, image, loc)) {
158 return atlas;
159 }
160
161 // If the above fails, then either we have no starting atlas, or the current
162 // one is full. Either way we need to allocate a new atlas
163
164 GrIPoint16 plot;
165 if (!fPlotMgr->newPlot(&plot)) {
166 return NULL;
167 }
168
reed@google.com759c16e2011-03-15 19:15:15 +0000169 GrAssert(0 == kA8_GrMaskFormat);
170 GrAssert(1 == kA565_GrMaskFormat);
171 if (NULL == fTexture[format]) {
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000172 GrTextureDesc desc = {
173 kDynamicUpdate_GrTextureFlagBit,
174 kNone_GrAALevel,
reed@google.com98539c62011-03-15 15:40:16 +0000175 GR_ATLAS_TEXTURE_WIDTH,
reed@google.comac10a2d2010-12-22 21:39:39 +0000176 GR_ATLAS_TEXTURE_HEIGHT,
reed@google.com98539c62011-03-15 15:40:16 +0000177 maskformat2pixelconfig(format)
reed@google.comac10a2d2010-12-22 21:39:39 +0000178 };
reed@google.com759c16e2011-03-15 19:15:15 +0000179 fTexture[format] = fGpu->createTexture(desc, NULL, 0);
180 if (NULL == fTexture[format]) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000181 return NULL;
182 }
183 }
184
reed@google.com98539c62011-03-15 15:40:16 +0000185 GrAtlas* newAtlas = new GrAtlas(this, plot.fX, plot.fY, format);
reed@google.comac10a2d2010-12-22 21:39:39 +0000186 if (!newAtlas->addSubImage(width, height, image, loc)) {
187 delete newAtlas;
188 return NULL;
189 }
190
191 newAtlas->fNext = atlas;
192 return newAtlas;
193}
194
195void GrAtlasMgr::freePlot(int x, int y) {
196 GrAssert(fPlotMgr->isBusy(x, y));
197 fPlotMgr->freePlot(x, y);
198}
199
reed@google.comac10a2d2010-12-22 21:39:39 +0000200