Home | History | Annotate | Download | only in gpu
      1 /*
      2  * Copyright (c) 2010, Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "config.h"
     32 
     33 #if ENABLE(ACCELERATED_2D_CANVAS)
     34 
     35 #include "TilingData.h"
     36 
     37 #include "FloatRect.h"
     38 #include "IntRect.h"
     39 #include <algorithm>
     40 
     41 using namespace std;
     42 
     43 namespace WebCore {
     44 
     45 static int computeNumTiles(int maxTextureSize, int totalSize, int borderTexels)
     46 {
     47     if (maxTextureSize - 2 * borderTexels <= 0)
     48         return totalSize > 0 && maxTextureSize >= totalSize ? 1 : 0;
     49 
     50     int numTiles = max(1, 1 + (totalSize - 1 - 2 * borderTexels) / (maxTextureSize - 2 * borderTexels));
     51     return totalSize > 0 ? numTiles : 0;
     52 }
     53 
     54 TilingData::TilingData(int maxTextureSize, int totalSizeX, int totalSizeY, bool hasBorderTexels)
     55     : m_maxTextureSize(maxTextureSize)
     56     , m_totalSizeX(totalSizeX)
     57     , m_totalSizeY(totalSizeY)
     58     , m_borderTexels(hasBorderTexels ? 1 : 0)
     59 {
     60     recomputeNumTiles();
     61 }
     62 
     63 void TilingData::setTotalSize(int totalSizeX, int totalSizeY)
     64 {
     65     m_totalSizeX = totalSizeX;
     66     m_totalSizeY = totalSizeY;
     67     recomputeNumTiles();
     68 }
     69 
     70 void TilingData::setMaxTextureSize(int maxTextureSize)
     71 {
     72     m_maxTextureSize = maxTextureSize;
     73     recomputeNumTiles();
     74 }
     75 
     76 int TilingData::tileXIndexFromSrcCoord(int srcPos) const
     77 {
     78     int x = (srcPos - m_borderTexels) / (m_maxTextureSize - 2 * m_borderTexels);
     79     return min(max(x, 0), numTilesX() - 1);
     80 }
     81 
     82 int TilingData::tileYIndexFromSrcCoord(int srcPos) const
     83 {
     84     int y = (srcPos - m_borderTexels) / (m_maxTextureSize - 2 * m_borderTexels);
     85     return min(max(y, 0), numTilesY() - 1);
     86 }
     87 
     88 IntRect TilingData::tileBounds(int tile) const
     89 {
     90     assertTile(tile);
     91     int ix = tileXIndex(tile);
     92     int iy = tileYIndex(tile);
     93     int x = tilePositionX(ix);
     94     int y = tilePositionY(iy);
     95     int width = tileSizeX(ix);
     96     int height = tileSizeY(iy);
     97     ASSERT(x >= 0 && y >= 0 && width >= 0 && height >= 0);
     98     ASSERT(x <= totalSizeX() && y <= totalSizeY());
     99     return IntRect(x, y, width, height);
    100 }
    101 
    102 IntRect TilingData::tileBoundsWithBorder(int tile) const
    103 {
    104     IntRect bounds = tileBounds(tile);
    105 
    106     if (m_borderTexels) {
    107         int x1 = bounds.x();
    108         int x2 = bounds.maxX();
    109         int y1 = bounds.y();
    110         int y2 = bounds.maxY();
    111 
    112         if (tileXIndex(tile) > 0)
    113             x1--;
    114         if (tileXIndex(tile) < (numTilesX() - 1))
    115             x2++;
    116         if (tileYIndex(tile) > 0)
    117             y1--;
    118         if (tileYIndex(tile) < (numTilesY() - 1))
    119             y2++;
    120 
    121         bounds = IntRect(x1, y1, x2 - x1, y2 - y1);
    122     }
    123 
    124     return bounds;
    125 }
    126 
    127 FloatRect TilingData::tileBoundsNormalized(int tile) const
    128 {
    129     assertTile(tile);
    130     FloatRect bounds(tileBounds(tile));
    131     bounds.scale(1.0f / m_totalSizeX, 1.0f / m_totalSizeY);
    132     return bounds;
    133 }
    134 
    135 int TilingData::tilePositionX(int xIndex) const
    136 {
    137     ASSERT(xIndex >= 0 && xIndex < numTilesX());
    138 
    139     int pos = 0;
    140     for (int i = 0; i < xIndex; i++)
    141         pos += tileSizeX(i);
    142 
    143     return pos;
    144 }
    145 
    146 int TilingData::tilePositionY(int yIndex) const
    147 {
    148     ASSERT(yIndex >= 0 && yIndex < numTilesY());
    149 
    150     int pos = 0;
    151     for (int i = 0; i < yIndex; i++)
    152         pos += tileSizeY(i);
    153 
    154     return pos;
    155 }
    156 
    157 int TilingData::tileSizeX(int xIndex) const
    158 {
    159     ASSERT(xIndex >= 0 && xIndex < numTilesX());
    160 
    161     if (!xIndex && m_numTilesX == 1)
    162         return m_totalSizeX;
    163     if (!xIndex && m_numTilesX > 1)
    164         return m_maxTextureSize - m_borderTexels;
    165     if (xIndex < numTilesX() - 1)
    166         return m_maxTextureSize - 2 * m_borderTexels;
    167     if (xIndex == numTilesX() - 1)
    168         return m_totalSizeX - tilePositionX(xIndex);
    169 
    170     ASSERT_NOT_REACHED();
    171     return 0;
    172 }
    173 
    174 int TilingData::tileSizeY(int yIndex) const
    175 {
    176     ASSERT(yIndex >= 0 && yIndex < numTilesY());
    177 
    178     if (!yIndex && m_numTilesY == 1)
    179         return m_totalSizeY;
    180     if (!yIndex && m_numTilesY > 1)
    181         return m_maxTextureSize - m_borderTexels;
    182     if (yIndex < numTilesY() - 1)
    183         return m_maxTextureSize - 2 * m_borderTexels;
    184     if (yIndex == numTilesY() - 1)
    185         return m_totalSizeY - tilePositionY(yIndex);
    186 
    187     ASSERT_NOT_REACHED();
    188     return 0;
    189 }
    190 
    191 IntRect TilingData::overlappedTileIndices(const WebCore::IntRect &srcRect) const
    192 {
    193     int x = tileXIndexFromSrcCoord(srcRect.x());
    194     int y = tileYIndexFromSrcCoord(srcRect.y());
    195     int r = tileXIndexFromSrcCoord(srcRect.maxX());
    196     int b = tileYIndexFromSrcCoord(srcRect.maxY());
    197     return IntRect(x, y, r - x, b - y);
    198 }
    199 
    200 IntRect TilingData::overlappedTileIndices(const WebCore::FloatRect &srcRect) const
    201 {
    202     return overlappedTileIndices(enclosingIntRect(srcRect));
    203 }
    204 
    205 void TilingData::intersectDrawQuad(const FloatRect& srcRect, const FloatRect& dstRect, int tile,
    206                                    FloatRect* newSrc, FloatRect* newDst) const
    207 {
    208     // Intersect with tile
    209     FloatRect tileBounds = this->tileBounds(tile);
    210     FloatRect srcRectIntersected = srcRect;
    211     srcRectIntersected.intersect(tileBounds);
    212 
    213     if (srcRectIntersected.isEmpty()) {
    214         *newSrc = *newDst = FloatRect(0, 0, 0, 0);
    215         return;
    216     }
    217 
    218     float srcRectIntersectedNormX = (srcRectIntersected.x() - srcRect.x()) / srcRect.width();
    219     float srcRectIntersectedNormY = (srcRectIntersected.y() - srcRect.y()) / srcRect.height();
    220     float srcRectIntersectedNormW = srcRectIntersected.width() / srcRect.width();
    221     float srcRectIntersectedNormH = srcRectIntersected.height() / srcRect.height();
    222 
    223     *newSrc = srcRectIntersected;
    224     newSrc->move(
    225         -tileBounds.x() + ((tileXIndex(tile) > 0) ? m_borderTexels : 0),
    226         -tileBounds.y() + ((tileYIndex(tile) > 0) ? m_borderTexels : 0));
    227 
    228     *newDst = FloatRect(
    229         srcRectIntersectedNormX * dstRect.width() + dstRect.x(),
    230         srcRectIntersectedNormY * dstRect.height() + dstRect.y(),
    231         srcRectIntersectedNormW * dstRect.width(),
    232         srcRectIntersectedNormH * dstRect.height());
    233 }
    234 
    235 IntPoint TilingData::textureOffset(int xIndex, int yIndex) const
    236 {
    237     int left = (!xIndex || m_numTilesX == 1) ? 0 : m_borderTexels;
    238     int top = (!yIndex || m_numTilesY == 1) ? 0 : m_borderTexels;
    239 
    240     return IntPoint(left, top);
    241 }
    242 
    243 void TilingData::recomputeNumTiles()
    244 {
    245     m_numTilesX = computeNumTiles(m_maxTextureSize, m_totalSizeX, m_borderTexels);
    246     m_numTilesY = computeNumTiles(m_maxTextureSize, m_totalSizeY, m_borderTexels);
    247 }
    248 
    249 }
    250 
    251 #endif
    252