Home | History | Annotate | Download | only in hwui
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      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 #define LOG_TAG "OpenGLRenderer"
     18 
     19 #include <math.h>
     20 #include <stdlib.h>
     21 #include <string.h>
     22 
     23 #include <utils/Log.h>
     24 
     25 #include <SkMatrix.h>
     26 
     27 #include "utils/Compare.h"
     28 #include "Matrix.h"
     29 
     30 namespace android {
     31 namespace uirenderer {
     32 
     33 void Matrix4::loadIdentity() {
     34     data[kScaleX]       = 1.0f;
     35     data[kSkewY]        = 0.0f;
     36     data[2]             = 0.0f;
     37     data[kPerspective0] = 0.0f;
     38 
     39     data[kSkewX]        = 0.0f;
     40     data[kScaleY]       = 1.0f;
     41     data[6]             = 0.0f;
     42     data[kPerspective1] = 0.0f;
     43 
     44     data[8]             = 0.0f;
     45     data[9]             = 0.0f;
     46     data[kScaleZ]       = 1.0f;
     47     data[11]            = 0.0f;
     48 
     49     data[kTranslateX]   = 0.0f;
     50     data[kTranslateY]   = 0.0f;
     51     data[kTranslateZ]   = 0.0f;
     52     data[kPerspective2] = 1.0f;
     53 
     54     mIsIdentity = true;
     55     mSimpleMatrix = true;
     56 }
     57 
     58 bool Matrix4::changesBounds() {
     59     return !(ALMOST_EQUAL(data[0], 1.0f) && ALMOST_EQUAL(data[1], 0.0f) &&
     60              ALMOST_EQUAL(data[2], 0.0f) && ALMOST_EQUAL(data[4], 0.0f) &&
     61              ALMOST_EQUAL(data[5], 1.0f) && ALMOST_EQUAL(data[6], 0.0f) &&
     62              ALMOST_EQUAL(data[8], 0.0f) && ALMOST_EQUAL(data[9], 0.0f) &&
     63              ALMOST_EQUAL(data[10], 1.0f));
     64 }
     65 
     66 bool Matrix4::isPureTranslate() {
     67     return mSimpleMatrix &&
     68             ALMOST_EQUAL(data[kScaleX], 1.0f) && ALMOST_EQUAL(data[kScaleY], 1.0f);
     69 }
     70 
     71 bool Matrix4::isSimple() {
     72     return mSimpleMatrix;
     73 }
     74 
     75 bool Matrix4::isIdentity() {
     76     return mIsIdentity;
     77 }
     78 
     79 void Matrix4::load(const float* v) {
     80     memcpy(data, v, sizeof(data));
     81     // TODO: Do something smarter here
     82     mSimpleMatrix = false;
     83     mIsIdentity = false;
     84 }
     85 
     86 void Matrix4::load(const Matrix4& v) {
     87     memcpy(data, v.data, sizeof(data));
     88     mSimpleMatrix = v.mSimpleMatrix;
     89     mIsIdentity = v.mIsIdentity;
     90 }
     91 
     92 void Matrix4::load(const SkMatrix& v) {
     93     memset(data, 0, sizeof(data));
     94 
     95     data[kScaleX]     = v[SkMatrix::kMScaleX];
     96     data[kSkewX]      = v[SkMatrix::kMSkewX];
     97     data[kTranslateX] = v[SkMatrix::kMTransX];
     98 
     99     data[kSkewY]      = v[SkMatrix::kMSkewY];
    100     data[kScaleY]     = v[SkMatrix::kMScaleY];
    101     data[kTranslateY] = v[SkMatrix::kMTransY];
    102 
    103     data[kPerspective0]  = v[SkMatrix::kMPersp0];
    104     data[kPerspective1]  = v[SkMatrix::kMPersp1];
    105     data[kPerspective2]  = v[SkMatrix::kMPersp2];
    106 
    107     data[kScaleZ] = 1.0f;
    108 
    109     mSimpleMatrix = (v.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask));
    110     mIsIdentity = v.isIdentity();
    111 }
    112 
    113 void Matrix4::copyTo(SkMatrix& v) const {
    114     v.reset();
    115 
    116     v.set(SkMatrix::kMScaleX, data[kScaleX]);
    117     v.set(SkMatrix::kMSkewX,  data[kSkewX]);
    118     v.set(SkMatrix::kMTransX, data[kTranslateX]);
    119 
    120     v.set(SkMatrix::kMSkewY,  data[kSkewY]);
    121     v.set(SkMatrix::kMScaleY, data[kScaleY]);
    122     v.set(SkMatrix::kMTransY, data[kTranslateY]);
    123 
    124     v.set(SkMatrix::kMPersp0, data[kPerspective0]);
    125     v.set(SkMatrix::kMPersp1, data[kPerspective1]);
    126     v.set(SkMatrix::kMPersp2, data[kPerspective2]);
    127 }
    128 
    129 void Matrix4::loadInverse(const Matrix4& v) {
    130     double scale = 1.0 /
    131             (v.data[kScaleX] * ((double) v.data[kScaleY]  * v.data[kPerspective2] -
    132                     (double) v.data[kTranslateY] * v.data[kPerspective1]) +
    133              v.data[kSkewX] * ((double) v.data[kTranslateY] * v.data[kPerspective0] -
    134                      (double) v.data[kSkewY] * v.data[kPerspective2]) +
    135              v.data[kTranslateX] * ((double) v.data[kSkewY] * v.data[kPerspective1] -
    136                      (double) v.data[kScaleY] * v.data[kPerspective0]));
    137 
    138     data[kScaleX] = (v.data[kScaleY] * v.data[kPerspective2] -
    139             v.data[kTranslateY] * v.data[kPerspective1])  * scale;
    140     data[kSkewX] = (v.data[kTranslateX] * v.data[kPerspective1] -
    141             v.data[kSkewX]  * v.data[kPerspective2]) * scale;
    142     data[kTranslateX] = (v.data[kSkewX] * v.data[kTranslateY] -
    143             v.data[kTranslateX] * v.data[kScaleY])  * scale;
    144 
    145     data[kSkewY] = (v.data[kTranslateY] * v.data[kPerspective0] -
    146             v.data[kSkewY]  * v.data[kPerspective2]) * scale;
    147     data[kScaleY] = (v.data[kScaleX] * v.data[kPerspective2] -
    148             v.data[kTranslateX] * v.data[kPerspective0])  * scale;
    149     data[kTranslateY] = (v.data[kTranslateX] * v.data[kSkewY] -
    150             v.data[kScaleX]  * v.data[kTranslateY]) * scale;
    151 
    152     data[kPerspective0] = (v.data[kSkewY] * v.data[kPerspective1] -
    153             v.data[kScaleY] * v.data[kPerspective0]) * scale;
    154     data[kPerspective1] = (v.data[kSkewX] * v.data[kPerspective0] -
    155             v.data[kScaleX] * v.data[kPerspective1]) * scale;
    156     data[kPerspective2] = (v.data[kScaleX] * v.data[kScaleY] -
    157             v.data[kSkewX] * v.data[kSkewY]) * scale;
    158 
    159     mSimpleMatrix = v.mSimpleMatrix;
    160     mIsIdentity = v.mIsIdentity;
    161 }
    162 
    163 void Matrix4::copyTo(float* v) const {
    164     memcpy(v, data, sizeof(data));
    165 }
    166 
    167 float Matrix4::getTranslateX() {
    168     return data[kTranslateX];
    169 }
    170 
    171 float Matrix4::getTranslateY() {
    172     return data[kTranslateY];
    173 }
    174 
    175 void Matrix4::multiply(float v) {
    176     for (int i = 0; i < 16; i++) {
    177         data[i] *= v;
    178     }
    179     mIsIdentity = false;
    180 }
    181 
    182 void Matrix4::loadTranslate(float x, float y, float z) {
    183     loadIdentity();
    184 
    185     data[kTranslateX] = x;
    186     data[kTranslateY] = y;
    187     data[kTranslateZ] = z;
    188 
    189     mIsIdentity = false;
    190 }
    191 
    192 void Matrix4::loadScale(float sx, float sy, float sz) {
    193     loadIdentity();
    194 
    195     data[kScaleX] = sx;
    196     data[kScaleY] = sy;
    197     data[kScaleZ] = sz;
    198 
    199     mIsIdentity = false;
    200 }
    201 
    202 void Matrix4::loadSkew(float sx, float sy) {
    203     loadIdentity();
    204 
    205     data[kScaleX]       = 1.0f;
    206     data[kSkewX]        = sx;
    207     data[kTranslateX]   = 0.0f;
    208 
    209     data[kSkewY]        = sy;
    210     data[kScaleY]       = 1.0f;
    211     data[kTranslateY]   = 0.0f;
    212 
    213     data[kPerspective0] = 0.0f;
    214     data[kPerspective1] = 0.0f;
    215     data[kPerspective2] = 1.0f;
    216 
    217     mSimpleMatrix = false;
    218     mIsIdentity = false;
    219 }
    220 
    221 void Matrix4::loadRotate(float angle, float x, float y, float z) {
    222     data[kPerspective0]  = 0.0f;
    223     data[kPerspective1]  = 0.0f;
    224     data[11]             = 0.0f;
    225     data[kTranslateX]    = 0.0f;
    226     data[kTranslateY]    = 0.0f;
    227     data[kTranslateZ]    = 0.0f;
    228     data[kPerspective2]  = 1.0f;
    229 
    230     angle *= float(M_PI / 180.0f);
    231     float c = cosf(angle);
    232     float s = sinf(angle);
    233 
    234     const float length = sqrtf(x * x + y * y + z * z);
    235     float recipLen = 1.0f / length;
    236     x *= recipLen;
    237     y *= recipLen;
    238     z *= recipLen;
    239 
    240     const float nc = 1.0f - c;
    241     const float xy = x * y;
    242     const float yz = y * z;
    243     const float zx = z * x;
    244     const float xs = x * s;
    245     const float ys = y * s;
    246     const float zs = z * s;
    247 
    248     data[kScaleX] = x * x * nc +  c;
    249     data[kSkewX]  =    xy * nc - zs;
    250     data[8]       =    zx * nc + ys;
    251     data[kSkewY]  =    xy * nc + zs;
    252     data[kScaleY] = y * y * nc +  c;
    253     data[9]       =    yz * nc - xs;
    254     data[2]       =    zx * nc - ys;
    255     data[6]       =    yz * nc + xs;
    256     data[kScaleZ] = z * z * nc +  c;
    257 
    258     mSimpleMatrix = false;
    259     mIsIdentity = false;
    260 }
    261 
    262 void Matrix4::loadMultiply(const Matrix4& u, const Matrix4& v) {
    263     for (int i = 0 ; i < 4 ; i++) {
    264         float x = 0;
    265         float y = 0;
    266         float z = 0;
    267         float w = 0;
    268 
    269         for (int j = 0 ; j < 4 ; j++) {
    270             const float e = v.get(i, j);
    271             x += u.get(j, 0) * e;
    272             y += u.get(j, 1) * e;
    273             z += u.get(j, 2) * e;
    274             w += u.get(j, 3) * e;
    275         }
    276 
    277         set(i, 0, x);
    278         set(i, 1, y);
    279         set(i, 2, z);
    280         set(i, 3, w);
    281     }
    282 
    283     mSimpleMatrix = u.mSimpleMatrix && v.mSimpleMatrix;
    284     mIsIdentity = false;
    285 }
    286 
    287 void Matrix4::loadOrtho(float left, float right, float bottom, float top, float near, float far) {
    288     loadIdentity();
    289 
    290     data[kScaleX] = 2.0f / (right - left);
    291     data[kScaleY] = 2.0f / (top - bottom);
    292     data[kScaleZ] = -2.0f / (far - near);
    293     data[kTranslateX] = -(right + left) / (right - left);
    294     data[kTranslateY] = -(top + bottom) / (top - bottom);
    295     data[kTranslateZ] = -(far + near) / (far - near);
    296 
    297     mIsIdentity = false;
    298 }
    299 
    300 #define MUL_ADD_STORE(a, b, c) a = (a) * (b) + (c)
    301 
    302 void Matrix4::mapPoint(float& x, float& y) const {
    303     if (mSimpleMatrix) {
    304         MUL_ADD_STORE(x, data[kScaleX], data[kTranslateX]);
    305         MUL_ADD_STORE(y, data[kScaleY], data[kTranslateY]);
    306         return;
    307     }
    308 
    309     float dx = x * data[kScaleX] + y * data[kSkewX] + data[kTranslateX];
    310     float dy = x * data[kSkewY] + y * data[kScaleY] + data[kTranslateY];
    311     float dz = x * data[kPerspective0] + y * data[kPerspective1] + data[kPerspective2];
    312     if (dz) dz = 1.0f / dz;
    313 
    314     x = dx * dz;
    315     y = dy * dz;
    316 }
    317 
    318 void Matrix4::mapRect(Rect& r) const {
    319     if (mSimpleMatrix) {
    320         MUL_ADD_STORE(r.left, data[kScaleX], data[kTranslateX]);
    321         MUL_ADD_STORE(r.right, data[kScaleX], data[kTranslateX]);
    322         MUL_ADD_STORE(r.top, data[kScaleY], data[kTranslateY]);
    323         MUL_ADD_STORE(r.bottom, data[kScaleY], data[kTranslateY]);
    324 
    325         if (r.left > r.right) {
    326             float x = r.left;
    327             r.left = r.right;
    328             r.right = x;
    329         }
    330 
    331         if (r.top > r.bottom) {
    332             float y = r.top;
    333             r.top = r.bottom;
    334             r.bottom = y;
    335         }
    336 
    337         return;
    338     }
    339 
    340     float vertices[] = {
    341         r.left, r.top,
    342         r.right, r.top,
    343         r.right, r.bottom,
    344         r.left, r.bottom
    345     };
    346 
    347     float x, y, z;
    348 
    349     for (int i = 0; i < 8; i+= 2) {
    350         float px = vertices[i];
    351         float py = vertices[i + 1];
    352 
    353         x = px * data[kScaleX] + py * data[kSkewX] + data[kTranslateX];
    354         y = px * data[kSkewY] + py * data[kScaleY] + data[kTranslateY];
    355         z = px * data[kPerspective0] + py * data[kPerspective1] + data[kPerspective2];
    356         if (z) z = 1.0f / z;
    357 
    358         vertices[i] = x * z;
    359         vertices[i + 1] = y * z;
    360     }
    361 
    362     r.left = r.right = vertices[0];
    363     r.top = r.bottom = vertices[1];
    364 
    365     for (int i = 2; i < 8; i += 2) {
    366         x = vertices[i];
    367         y = vertices[i + 1];
    368 
    369         if (x < r.left) r.left = x;
    370         else if (x > r.right) r.right = x;
    371         if (y < r.top) r.top = y;
    372         else if (y > r.bottom) r.bottom = y;
    373     }
    374 }
    375 
    376 void Matrix4::dump() const {
    377     LOGD("Matrix4[simple=%d", mSimpleMatrix);
    378     LOGD("  %f %f %f %f", data[kScaleX], data[kSkewX], data[8], data[kTranslateX]);
    379     LOGD("  %f %f %f %f", data[kSkewY], data[kScaleY], data[9], data[kTranslateY]);
    380     LOGD("  %f %f %f %f", data[2], data[6], data[kScaleZ], data[kTranslateZ]);
    381     LOGD("  %f %f %f %f", data[kPerspective0], data[kPerspective1], data[11], data[kPerspective2]);
    382     LOGD("]");
    383 }
    384 
    385 }; // namespace uirenderer
    386 }; // namespace android
    387