1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/gl/DecomposeIntoNoRepeatTriangles.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,199 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* vim: set ts=8 sts=4 et sw=4 tw=80: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "DecomposeIntoNoRepeatTriangles.h" 1.11 +#include "gfxMatrix.h" 1.12 + 1.13 +namespace mozilla { 1.14 +namespace gl { 1.15 + 1.16 +void 1.17 +RectTriangles::AppendRectToCoordArray(InfallibleTArray<coord>& array, 1.18 + GLfloat x0, GLfloat y0, 1.19 + GLfloat x1, GLfloat y1) 1.20 +{ 1.21 + coord* v = array.AppendElements(6); 1.22 + 1.23 + v[0].x = x0; v[0].y = y0; 1.24 + v[1].x = x1; v[1].y = y0; 1.25 + v[2].x = x0; v[2].y = y1; 1.26 + v[3].x = x0; v[3].y = y1; 1.27 + v[4].x = x1; v[4].y = y0; 1.28 + v[5].x = x1; v[5].y = y1; 1.29 +} 1.30 + 1.31 +void 1.32 +RectTriangles::addRect(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, 1.33 + GLfloat tx0, GLfloat ty0, GLfloat tx1, GLfloat ty1, 1.34 + bool flip_y /* = false */) 1.35 +{ 1.36 + if (flip_y) { 1.37 + std::swap(ty0, ty1); 1.38 + } 1.39 + AppendRectToCoordArray(mVertexCoords, x0, y0, x1, y1); 1.40 + AppendRectToCoordArray(mTexCoords, tx0, ty0, tx1, ty1); 1.41 +} 1.42 + 1.43 +bool 1.44 +RectTriangles::isSimpleQuad(gfx3DMatrix& aOutTextureTransform) const 1.45 +{ 1.46 + if (mVertexCoords.Length() == 6 && 1.47 + mVertexCoords[0].x == 0.0f && 1.48 + mVertexCoords[0].y == 0.0f && 1.49 + mVertexCoords[5].x == 1.0f && 1.50 + mVertexCoords[5].y == 1.0f) 1.51 + { 1.52 + GLfloat tx0 = mTexCoords[0].x; 1.53 + GLfloat ty0 = mTexCoords[0].y; 1.54 + GLfloat tx1 = mTexCoords[5].x; 1.55 + GLfloat ty1 = mTexCoords[5].y; 1.56 + aOutTextureTransform = gfx3DMatrix::From2D(gfxMatrix(tx1 - tx0, 0, 0, ty1 - ty0, tx0, ty0)); 1.57 + return true; 1.58 + } 1.59 + return false; 1.60 +} 1.61 + 1.62 +static GLfloat 1.63 +WrapTexCoord(GLfloat v) 1.64 +{ 1.65 + // fmodf gives negative results for negative numbers; 1.66 + // that is, fmodf(0.75, 1.0) == 0.75, but 1.67 + // fmodf(-0.75, 1.0) == -0.75. For the negative case, 1.68 + // the result we need is 0.25, so we add 1.0f. 1.69 + if (v < 0.0f) { 1.70 + return 1.0f + fmodf(v, 1.0f); 1.71 + } 1.72 + 1.73 + return fmodf(v, 1.0f); 1.74 +} 1.75 + 1.76 +void 1.77 +DecomposeIntoNoRepeatTriangles(const nsIntRect& aTexCoordRect, 1.78 + const nsIntSize& aTexSize, 1.79 + RectTriangles& aRects, 1.80 + bool aFlipY /* = false */) 1.81 +{ 1.82 + // normalize this 1.83 + nsIntRect tcr(aTexCoordRect); 1.84 + while (tcr.x >= aTexSize.width) 1.85 + tcr.x -= aTexSize.width; 1.86 + while (tcr.y >= aTexSize.height) 1.87 + tcr.y -= aTexSize.height; 1.88 + 1.89 + // Compute top left and bottom right tex coordinates 1.90 + GLfloat tl[2] = 1.91 + { GLfloat(tcr.x) / GLfloat(aTexSize.width), 1.92 + GLfloat(tcr.y) / GLfloat(aTexSize.height) }; 1.93 + GLfloat br[2] = 1.94 + { GLfloat(tcr.XMost()) / GLfloat(aTexSize.width), 1.95 + GLfloat(tcr.YMost()) / GLfloat(aTexSize.height) }; 1.96 + 1.97 + // then check if we wrap in either the x or y axis; if we do, 1.98 + // then also use fmod to figure out the "true" non-wrapping 1.99 + // texture coordinates. 1.100 + 1.101 + bool xwrap = false, ywrap = false; 1.102 + if (tcr.x < 0 || tcr.x > aTexSize.width || 1.103 + tcr.XMost() < 0 || tcr.XMost() > aTexSize.width) 1.104 + { 1.105 + xwrap = true; 1.106 + tl[0] = WrapTexCoord(tl[0]); 1.107 + br[0] = WrapTexCoord(br[0]); 1.108 + } 1.109 + 1.110 + if (tcr.y < 0 || tcr.y > aTexSize.height || 1.111 + tcr.YMost() < 0 || tcr.YMost() > aTexSize.height) 1.112 + { 1.113 + ywrap = true; 1.114 + tl[1] = WrapTexCoord(tl[1]); 1.115 + br[1] = WrapTexCoord(br[1]); 1.116 + } 1.117 + 1.118 + NS_ASSERTION(tl[0] >= 0.0f && tl[0] <= 1.0f && 1.119 + tl[1] >= 0.0f && tl[1] <= 1.0f && 1.120 + br[0] >= 0.0f && br[0] <= 1.0f && 1.121 + br[1] >= 0.0f && br[1] <= 1.0f, 1.122 + "Somehow generated invalid texture coordinates"); 1.123 + 1.124 + // If xwrap is false, the texture will be sampled from tl[0] 1.125 + // .. br[0]. If xwrap is true, then it will be split into tl[0] 1.126 + // .. 1.0, and 0.0 .. br[0]. Same for the Y axis. The 1.127 + // destination rectangle is also split appropriately, according 1.128 + // to the calculated xmid/ymid values. 1.129 + 1.130 + // There isn't a 1:1 mapping between tex coords and destination coords; 1.131 + // when computing midpoints, we have to take that into account. We 1.132 + // need to map the texture coords, which are (in the wrap case): 1.133 + // |tl->1| and |0->br| to the |0->1| range of the vertex coords. So 1.134 + // we have the length (1-tl)+(br) that needs to map into 0->1. 1.135 + // These are only valid if there is wrap involved, they won't be used 1.136 + // otherwise. 1.137 + GLfloat xlen = (1.0f - tl[0]) + br[0]; 1.138 + GLfloat ylen = (1.0f - tl[1]) + br[1]; 1.139 + 1.140 + NS_ASSERTION(!xwrap || xlen > 0.0f, "xlen isn't > 0, what's going on?"); 1.141 + NS_ASSERTION(!ywrap || ylen > 0.0f, "ylen isn't > 0, what's going on?"); 1.142 + NS_ASSERTION(aTexCoordRect.width <= aTexSize.width && 1.143 + aTexCoordRect.height <= aTexSize.height, "tex coord rect would cause tiling!"); 1.144 + 1.145 + if (!xwrap && !ywrap) { 1.146 + aRects.addRect(0.0f, 0.0f, 1.147 + 1.0f, 1.0f, 1.148 + tl[0], tl[1], 1.149 + br[0], br[1], 1.150 + aFlipY); 1.151 + } else if (!xwrap && ywrap) { 1.152 + GLfloat ymid = (1.0f - tl[1]) / ylen; 1.153 + aRects.addRect(0.0f, 0.0f, 1.154 + 1.0f, ymid, 1.155 + tl[0], tl[1], 1.156 + br[0], 1.0f, 1.157 + aFlipY); 1.158 + aRects.addRect(0.0f, ymid, 1.159 + 1.0f, 1.0f, 1.160 + tl[0], 0.0f, 1.161 + br[0], br[1], 1.162 + aFlipY); 1.163 + } else if (xwrap && !ywrap) { 1.164 + GLfloat xmid = (1.0f - tl[0]) / xlen; 1.165 + aRects.addRect(0.0f, 0.0f, 1.166 + xmid, 1.0f, 1.167 + tl[0], tl[1], 1.168 + 1.0f, br[1], 1.169 + aFlipY); 1.170 + aRects.addRect(xmid, 0.0f, 1.171 + 1.0f, 1.0f, 1.172 + 0.0f, tl[1], 1.173 + br[0], br[1], 1.174 + aFlipY); 1.175 + } else { 1.176 + GLfloat xmid = (1.0f - tl[0]) / xlen; 1.177 + GLfloat ymid = (1.0f - tl[1]) / ylen; 1.178 + aRects.addRect(0.0f, 0.0f, 1.179 + xmid, ymid, 1.180 + tl[0], tl[1], 1.181 + 1.0f, 1.0f, 1.182 + aFlipY); 1.183 + aRects.addRect(xmid, 0.0f, 1.184 + 1.0f, ymid, 1.185 + 0.0f, tl[1], 1.186 + br[0], 1.0f, 1.187 + aFlipY); 1.188 + aRects.addRect(0.0f, ymid, 1.189 + xmid, 1.0f, 1.190 + tl[0], 0.0f, 1.191 + 1.0f, br[1], 1.192 + aFlipY); 1.193 + aRects.addRect(xmid, ymid, 1.194 + 1.0f, 1.0f, 1.195 + 0.0f, 0.0f, 1.196 + br[0], br[1], 1.197 + aFlipY); 1.198 + } 1.199 +} 1.200 + 1.201 +} 1.202 +}