Home | History | Annotate | Download | only in src
      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 
     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 
     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 
     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 
     87 static uint8_t* zerofill(uint8_t* ptr, int count) {
     88     while (--count >= 0) {
     89         *ptr++ = 0;
     90     }
     91     return ptr;
     92 }
     93 
     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 
    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 
    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 
    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 
    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 
    201 void GrAtlasMgr::freePlot(int x, int y) {
    202     GrAssert(fPlotMgr->isBusy(x, y));
    203     fPlotMgr->freePlot(x, y);
    204 }
    205 
    206 
    207