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
      6  * are met:
      7  *
      8  * 1.  Redistributions of source code must retain the above copyright
      9  *     notice, this list of conditions and the following disclaimer.
     10  * 2.  Redistributions in binary form must reproduce the above copyright
     11  *     notice, this list of conditions and the following disclaimer in the
     12  *     documentation and/or other materials provided with the distribution.
     13  *
     14  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     17  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 
     28 #if ENABLE(ACCELERATED_2D_CANVAS)
     29 
     30 #include "LoopBlinnTextureCoords.h"
     31 
     32 #include <math.h>
     33 #include <wtf/Assertions.h>
     34 
     35 namespace WebCore {
     36 
     37 LoopBlinnTextureCoords::Result LoopBlinnTextureCoords::compute(const LoopBlinnClassifier::Result& classification, LoopBlinnConstants::FillSide sideToFill)
     38 {
     39     // Loop and Blinn's formulation states that the right side of the
     40     // curve is defined to be the inside (filled region), but for some
     41     // reason it looks like with the default orientation parameters we
     42     // are filling the left side of the curve. Regardless, because we
     43     // can receive arbitrarily oriented curves as input, we might have
     44     // to reverse the orientation of the cubic texture coordinates even
     45     // in cases where the paper doesn't say it is necessary.
     46     bool reverseOrientation = false;
     47     static const float OneThird = 1.0f / 3.0f;
     48     static const float TwoThirds = 2.0f / 3.0f;
     49     LoopBlinnClassifier::CurveType curveType = classification.curveType;
     50 
     51     LoopBlinnTextureCoords::Result result;
     52 
     53     switch (curveType) {
     54     case LoopBlinnClassifier::kSerpentine: {
     55         float t1 = sqrtf(9.0f * classification.d2 * classification.d2 - 12 * classification.d1 * classification.d3);
     56         float ls = 3.0f * classification.d2 - t1;
     57         float lt = 6.0f * classification.d1;
     58         float ms = 3.0f * classification.d2 + t1;
     59         float mt = lt;
     60         float ltMinusLs = lt - ls;
     61         float mtMinusMs = mt - ms;
     62         result.klmCoordinates[0] = FloatPoint3D(ls * ms,
     63                                                 ls * ls * ls,
     64                                                 ms * ms * ms);
     65         result.klmCoordinates[1] = FloatPoint3D(OneThird * (3.0f * ls * ms - ls * mt - lt * ms),
     66                                                 ls * ls * (ls - lt),
     67                                                 ms * ms * (ms - mt));
     68         result.klmCoordinates[2] = FloatPoint3D(OneThird * (lt * (mt - 2.0f * ms) + ls * (3.0f * ms - 2.0f * mt)),
     69                                                 ltMinusLs * ltMinusLs * ls,
     70                                                 mtMinusMs * mtMinusMs * ms);
     71         result.klmCoordinates[3] = FloatPoint3D(ltMinusLs * mtMinusMs,
     72                                                 -(ltMinusLs * ltMinusLs * ltMinusLs),
     73                                                 -(mtMinusMs * mtMinusMs * mtMinusMs));
     74         if (classification.d1 < 0.0f)
     75             reverseOrientation = true;
     76         break;
     77     }
     78 
     79     case LoopBlinnClassifier::kLoop: {
     80         float t1 = sqrtf(4.0f * classification.d1 * classification.d3 - 3.0f * classification.d2 * classification.d2);
     81         float ls = classification.d2 - t1;
     82         float lt = 2.0f * classification.d1;
     83         float ms = classification.d2 + t1;
     84         float mt = lt;
     85 
     86         // Figure out whether there is a rendering artifact requiring
     87         // the curve to be subdivided by the caller.
     88         float ql = ls / lt;
     89         float qm = ms / mt;
     90         if (0.0f < ql && ql < 1.0f) {
     91             result.hasRenderingArtifact = true;
     92             result.subdivisionParameterValue = ql;
     93             return result;
     94         }
     95 
     96         if (0.0f < qm && qm < 1.0f) {
     97             result.hasRenderingArtifact = true;
     98             result.subdivisionParameterValue = qm;
     99             return result;
    100         }
    101 
    102         float ltMinusLs = lt - ls;
    103         float mtMinusMs = mt - ms;
    104         result.klmCoordinates[0] = FloatPoint3D(ls * ms,
    105                                                 ls * ls * ms,
    106                                                 ls * ms * ms);
    107         result.klmCoordinates[1] = FloatPoint3D(OneThird * (-ls * mt - lt * ms + 3.0f * ls * ms),
    108                                                 -OneThird * ls * (ls * (mt - 3.0f * ms) + 2.0f * lt * ms),
    109                                                 -OneThird * ms * (ls * (2.0f * mt - 3.0f * ms) + lt * ms));
    110         result.klmCoordinates[2] = FloatPoint3D(OneThird * (lt * (mt - 2.0f * ms) + ls * (3.0f * ms - 2.0f * mt)),
    111                                                 OneThird * (lt - ls) * (ls * (2.0f * mt - 3.0f * ms) + lt * ms),
    112                                                 OneThird * (mt - ms) * (ls * (mt - 3.0f * ms) + 2.0f * lt * ms));
    113         result.klmCoordinates[3] = FloatPoint3D(ltMinusLs * mtMinusMs,
    114                                                 -(ltMinusLs * ltMinusLs) * mtMinusMs,
    115                                                 -ltMinusLs * mtMinusMs * mtMinusMs);
    116         reverseOrientation = ((classification.d1 > 0.0f && result.klmCoordinates[0].x() < 0.0f)
    117                            || (classification.d1 < 0.0f && result.klmCoordinates[0].x() > 0.0f));
    118         break;
    119     }
    120 
    121     case LoopBlinnClassifier::kCusp: {
    122         float ls = classification.d3;
    123         float lt = 3.0f * classification.d2;
    124         float lsMinusLt = ls - lt;
    125         result.klmCoordinates[0] = FloatPoint3D(ls,
    126                                                 ls * ls * ls,
    127                                                 1.0f);
    128         result.klmCoordinates[1] = FloatPoint3D(ls - OneThird * lt,
    129                                                 ls * ls * lsMinusLt,
    130                                                 1.0f);
    131         result.klmCoordinates[2] = FloatPoint3D(ls - TwoThirds * lt,
    132                                                 lsMinusLt * lsMinusLt * ls,
    133                                                 1.0f);
    134         result.klmCoordinates[3] = FloatPoint3D(lsMinusLt,
    135                                                 lsMinusLt * lsMinusLt * lsMinusLt,
    136                                                 1.0f);
    137         break;
    138     }
    139 
    140     case LoopBlinnClassifier::kQuadratic: {
    141         result.klmCoordinates[0] = FloatPoint3D(0, 0, 0);
    142         result.klmCoordinates[1] = FloatPoint3D(OneThird, 0, OneThird);
    143         result.klmCoordinates[2] = FloatPoint3D(TwoThirds, OneThird, TwoThirds);
    144         result.klmCoordinates[3] = FloatPoint3D(1, 1, 1);
    145         if (classification.d3 < 0)
    146             reverseOrientation = true;
    147         break;
    148     }
    149 
    150     case LoopBlinnClassifier::kLine:
    151     case LoopBlinnClassifier::kPoint:
    152         result.isLineOrPoint = true;
    153         break;
    154 
    155     default:
    156         ASSERT_NOT_REACHED();
    157         break;
    158     }
    159 
    160     if (sideToFill == LoopBlinnConstants::RightSide)
    161         reverseOrientation = !reverseOrientation;
    162 
    163     if (reverseOrientation) {
    164         for (int i = 0; i < 4; ++i) {
    165             result.klmCoordinates[i].setX(-result.klmCoordinates[i].x());
    166             result.klmCoordinates[i].setY(-result.klmCoordinates[i].y());
    167         }
    168     }
    169 
    170     return result;
    171 }
    172 
    173 } // namespace WebCore
    174 
    175 #endif
    176