Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
michael@0 | 2 | /* vim: set ts=8 sts=4 et sw=4 tw=80: */ |
michael@0 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 6 | |
michael@0 | 7 | #include "DecomposeIntoNoRepeatTriangles.h" |
michael@0 | 8 | #include "gfxMatrix.h" |
michael@0 | 9 | |
michael@0 | 10 | namespace mozilla { |
michael@0 | 11 | namespace gl { |
michael@0 | 12 | |
michael@0 | 13 | void |
michael@0 | 14 | RectTriangles::AppendRectToCoordArray(InfallibleTArray<coord>& array, |
michael@0 | 15 | GLfloat x0, GLfloat y0, |
michael@0 | 16 | GLfloat x1, GLfloat y1) |
michael@0 | 17 | { |
michael@0 | 18 | coord* v = array.AppendElements(6); |
michael@0 | 19 | |
michael@0 | 20 | v[0].x = x0; v[0].y = y0; |
michael@0 | 21 | v[1].x = x1; v[1].y = y0; |
michael@0 | 22 | v[2].x = x0; v[2].y = y1; |
michael@0 | 23 | v[3].x = x0; v[3].y = y1; |
michael@0 | 24 | v[4].x = x1; v[4].y = y0; |
michael@0 | 25 | v[5].x = x1; v[5].y = y1; |
michael@0 | 26 | } |
michael@0 | 27 | |
michael@0 | 28 | void |
michael@0 | 29 | RectTriangles::addRect(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, |
michael@0 | 30 | GLfloat tx0, GLfloat ty0, GLfloat tx1, GLfloat ty1, |
michael@0 | 31 | bool flip_y /* = false */) |
michael@0 | 32 | { |
michael@0 | 33 | if (flip_y) { |
michael@0 | 34 | std::swap(ty0, ty1); |
michael@0 | 35 | } |
michael@0 | 36 | AppendRectToCoordArray(mVertexCoords, x0, y0, x1, y1); |
michael@0 | 37 | AppendRectToCoordArray(mTexCoords, tx0, ty0, tx1, ty1); |
michael@0 | 38 | } |
michael@0 | 39 | |
michael@0 | 40 | bool |
michael@0 | 41 | RectTriangles::isSimpleQuad(gfx3DMatrix& aOutTextureTransform) const |
michael@0 | 42 | { |
michael@0 | 43 | if (mVertexCoords.Length() == 6 && |
michael@0 | 44 | mVertexCoords[0].x == 0.0f && |
michael@0 | 45 | mVertexCoords[0].y == 0.0f && |
michael@0 | 46 | mVertexCoords[5].x == 1.0f && |
michael@0 | 47 | mVertexCoords[5].y == 1.0f) |
michael@0 | 48 | { |
michael@0 | 49 | GLfloat tx0 = mTexCoords[0].x; |
michael@0 | 50 | GLfloat ty0 = mTexCoords[0].y; |
michael@0 | 51 | GLfloat tx1 = mTexCoords[5].x; |
michael@0 | 52 | GLfloat ty1 = mTexCoords[5].y; |
michael@0 | 53 | aOutTextureTransform = gfx3DMatrix::From2D(gfxMatrix(tx1 - tx0, 0, 0, ty1 - ty0, tx0, ty0)); |
michael@0 | 54 | return true; |
michael@0 | 55 | } |
michael@0 | 56 | return false; |
michael@0 | 57 | } |
michael@0 | 58 | |
michael@0 | 59 | static GLfloat |
michael@0 | 60 | WrapTexCoord(GLfloat v) |
michael@0 | 61 | { |
michael@0 | 62 | // fmodf gives negative results for negative numbers; |
michael@0 | 63 | // that is, fmodf(0.75, 1.0) == 0.75, but |
michael@0 | 64 | // fmodf(-0.75, 1.0) == -0.75. For the negative case, |
michael@0 | 65 | // the result we need is 0.25, so we add 1.0f. |
michael@0 | 66 | if (v < 0.0f) { |
michael@0 | 67 | return 1.0f + fmodf(v, 1.0f); |
michael@0 | 68 | } |
michael@0 | 69 | |
michael@0 | 70 | return fmodf(v, 1.0f); |
michael@0 | 71 | } |
michael@0 | 72 | |
michael@0 | 73 | void |
michael@0 | 74 | DecomposeIntoNoRepeatTriangles(const nsIntRect& aTexCoordRect, |
michael@0 | 75 | const nsIntSize& aTexSize, |
michael@0 | 76 | RectTriangles& aRects, |
michael@0 | 77 | bool aFlipY /* = false */) |
michael@0 | 78 | { |
michael@0 | 79 | // normalize this |
michael@0 | 80 | nsIntRect tcr(aTexCoordRect); |
michael@0 | 81 | while (tcr.x >= aTexSize.width) |
michael@0 | 82 | tcr.x -= aTexSize.width; |
michael@0 | 83 | while (tcr.y >= aTexSize.height) |
michael@0 | 84 | tcr.y -= aTexSize.height; |
michael@0 | 85 | |
michael@0 | 86 | // Compute top left and bottom right tex coordinates |
michael@0 | 87 | GLfloat tl[2] = |
michael@0 | 88 | { GLfloat(tcr.x) / GLfloat(aTexSize.width), |
michael@0 | 89 | GLfloat(tcr.y) / GLfloat(aTexSize.height) }; |
michael@0 | 90 | GLfloat br[2] = |
michael@0 | 91 | { GLfloat(tcr.XMost()) / GLfloat(aTexSize.width), |
michael@0 | 92 | GLfloat(tcr.YMost()) / GLfloat(aTexSize.height) }; |
michael@0 | 93 | |
michael@0 | 94 | // then check if we wrap in either the x or y axis; if we do, |
michael@0 | 95 | // then also use fmod to figure out the "true" non-wrapping |
michael@0 | 96 | // texture coordinates. |
michael@0 | 97 | |
michael@0 | 98 | bool xwrap = false, ywrap = false; |
michael@0 | 99 | if (tcr.x < 0 || tcr.x > aTexSize.width || |
michael@0 | 100 | tcr.XMost() < 0 || tcr.XMost() > aTexSize.width) |
michael@0 | 101 | { |
michael@0 | 102 | xwrap = true; |
michael@0 | 103 | tl[0] = WrapTexCoord(tl[0]); |
michael@0 | 104 | br[0] = WrapTexCoord(br[0]); |
michael@0 | 105 | } |
michael@0 | 106 | |
michael@0 | 107 | if (tcr.y < 0 || tcr.y > aTexSize.height || |
michael@0 | 108 | tcr.YMost() < 0 || tcr.YMost() > aTexSize.height) |
michael@0 | 109 | { |
michael@0 | 110 | ywrap = true; |
michael@0 | 111 | tl[1] = WrapTexCoord(tl[1]); |
michael@0 | 112 | br[1] = WrapTexCoord(br[1]); |
michael@0 | 113 | } |
michael@0 | 114 | |
michael@0 | 115 | NS_ASSERTION(tl[0] >= 0.0f && tl[0] <= 1.0f && |
michael@0 | 116 | tl[1] >= 0.0f && tl[1] <= 1.0f && |
michael@0 | 117 | br[0] >= 0.0f && br[0] <= 1.0f && |
michael@0 | 118 | br[1] >= 0.0f && br[1] <= 1.0f, |
michael@0 | 119 | "Somehow generated invalid texture coordinates"); |
michael@0 | 120 | |
michael@0 | 121 | // If xwrap is false, the texture will be sampled from tl[0] |
michael@0 | 122 | // .. br[0]. If xwrap is true, then it will be split into tl[0] |
michael@0 | 123 | // .. 1.0, and 0.0 .. br[0]. Same for the Y axis. The |
michael@0 | 124 | // destination rectangle is also split appropriately, according |
michael@0 | 125 | // to the calculated xmid/ymid values. |
michael@0 | 126 | |
michael@0 | 127 | // There isn't a 1:1 mapping between tex coords and destination coords; |
michael@0 | 128 | // when computing midpoints, we have to take that into account. We |
michael@0 | 129 | // need to map the texture coords, which are (in the wrap case): |
michael@0 | 130 | // |tl->1| and |0->br| to the |0->1| range of the vertex coords. So |
michael@0 | 131 | // we have the length (1-tl)+(br) that needs to map into 0->1. |
michael@0 | 132 | // These are only valid if there is wrap involved, they won't be used |
michael@0 | 133 | // otherwise. |
michael@0 | 134 | GLfloat xlen = (1.0f - tl[0]) + br[0]; |
michael@0 | 135 | GLfloat ylen = (1.0f - tl[1]) + br[1]; |
michael@0 | 136 | |
michael@0 | 137 | NS_ASSERTION(!xwrap || xlen > 0.0f, "xlen isn't > 0, what's going on?"); |
michael@0 | 138 | NS_ASSERTION(!ywrap || ylen > 0.0f, "ylen isn't > 0, what's going on?"); |
michael@0 | 139 | NS_ASSERTION(aTexCoordRect.width <= aTexSize.width && |
michael@0 | 140 | aTexCoordRect.height <= aTexSize.height, "tex coord rect would cause tiling!"); |
michael@0 | 141 | |
michael@0 | 142 | if (!xwrap && !ywrap) { |
michael@0 | 143 | aRects.addRect(0.0f, 0.0f, |
michael@0 | 144 | 1.0f, 1.0f, |
michael@0 | 145 | tl[0], tl[1], |
michael@0 | 146 | br[0], br[1], |
michael@0 | 147 | aFlipY); |
michael@0 | 148 | } else if (!xwrap && ywrap) { |
michael@0 | 149 | GLfloat ymid = (1.0f - tl[1]) / ylen; |
michael@0 | 150 | aRects.addRect(0.0f, 0.0f, |
michael@0 | 151 | 1.0f, ymid, |
michael@0 | 152 | tl[0], tl[1], |
michael@0 | 153 | br[0], 1.0f, |
michael@0 | 154 | aFlipY); |
michael@0 | 155 | aRects.addRect(0.0f, ymid, |
michael@0 | 156 | 1.0f, 1.0f, |
michael@0 | 157 | tl[0], 0.0f, |
michael@0 | 158 | br[0], br[1], |
michael@0 | 159 | aFlipY); |
michael@0 | 160 | } else if (xwrap && !ywrap) { |
michael@0 | 161 | GLfloat xmid = (1.0f - tl[0]) / xlen; |
michael@0 | 162 | aRects.addRect(0.0f, 0.0f, |
michael@0 | 163 | xmid, 1.0f, |
michael@0 | 164 | tl[0], tl[1], |
michael@0 | 165 | 1.0f, br[1], |
michael@0 | 166 | aFlipY); |
michael@0 | 167 | aRects.addRect(xmid, 0.0f, |
michael@0 | 168 | 1.0f, 1.0f, |
michael@0 | 169 | 0.0f, tl[1], |
michael@0 | 170 | br[0], br[1], |
michael@0 | 171 | aFlipY); |
michael@0 | 172 | } else { |
michael@0 | 173 | GLfloat xmid = (1.0f - tl[0]) / xlen; |
michael@0 | 174 | GLfloat ymid = (1.0f - tl[1]) / ylen; |
michael@0 | 175 | aRects.addRect(0.0f, 0.0f, |
michael@0 | 176 | xmid, ymid, |
michael@0 | 177 | tl[0], tl[1], |
michael@0 | 178 | 1.0f, 1.0f, |
michael@0 | 179 | aFlipY); |
michael@0 | 180 | aRects.addRect(xmid, 0.0f, |
michael@0 | 181 | 1.0f, ymid, |
michael@0 | 182 | 0.0f, tl[1], |
michael@0 | 183 | br[0], 1.0f, |
michael@0 | 184 | aFlipY); |
michael@0 | 185 | aRects.addRect(0.0f, ymid, |
michael@0 | 186 | xmid, 1.0f, |
michael@0 | 187 | tl[0], 0.0f, |
michael@0 | 188 | 1.0f, br[1], |
michael@0 | 189 | aFlipY); |
michael@0 | 190 | aRects.addRect(xmid, ymid, |
michael@0 | 191 | 1.0f, 1.0f, |
michael@0 | 192 | 0.0f, 0.0f, |
michael@0 | 193 | br[0], br[1], |
michael@0 | 194 | aFlipY); |
michael@0 | 195 | } |
michael@0 | 196 | } |
michael@0 | 197 | |
michael@0 | 198 | } |
michael@0 | 199 | } |