1572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams/*
2572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams * Copyright (C) 2012 The Android Open Source Project
3572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams *
4572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams * Licensed under the Apache License, Version 2.0 (the "License");
5572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams * you may not use this file except in compliance with the License.
6572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams * You may obtain a copy of the License at
7572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams *
8572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams *      http://www.apache.org/licenses/LICENSE-2.0
9572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams *
10572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams * Unless required by applicable law or agreed to in writing, software
11572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams * distributed under the License is distributed on an "AS IS" BASIS,
12572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams * See the License for the specific language governing permissions and
14572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams * limitations under the License.
15572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams */
16572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
17572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#include "ip.rsh"
186939f7bf32ab2765dcedb8a8d6fd352e7d08540fJason Sams#pragma rs_fp_relaxed
19572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
2023e1074f29f431f68c6b3230c1315ea0f7c7bc86Jason Samsstatic float shadowFilterMap[] = {
2123e1074f29f431f68c6b3230c1315ea0f7c7bc86Jason Sams    -0.00591f,  0.0001f,
2223e1074f29f431f68c6b3230c1315ea0f7c7bc86Jason Sams     1.16488f,  0.01668f,
2323e1074f29f431f68c6b3230c1315ea0f7c7bc86Jason Sams    -0.18027f, -0.06791f,
2423e1074f29f431f68c6b3230c1315ea0f7c7bc86Jason Sams    -0.12625f,  0.09001f,
2523e1074f29f431f68c6b3230c1315ea0f7c7bc86Jason Sams     0.15065f, -0.03897f
26572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams};
27572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
2823e1074f29f431f68c6b3230c1315ea0f7c7bc86Jason Samsstatic float poly[] = {
2923e1074f29f431f68c6b3230c1315ea0f7c7bc86Jason Sams    0.f, 0.f,
3023e1074f29f431f68c6b3230c1315ea0f7c7bc86Jason Sams    0.f, 0.f,
3123e1074f29f431f68c6b3230c1315ea0f7c7bc86Jason Sams    0.f
32572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams};
33572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
34572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsstatic const int ABITS = 4;
35572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsstatic const int HSCALE = 256;
36572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsstatic const int k1=255 << ABITS;
37572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsstatic const int k2=HSCALE << ABITS;
38572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
3923e1074f29f431f68c6b3230c1315ea0f7c7bc86Jason Samsstatic float fastevalPoly(float *poly,int n, float x){
40572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
4123e1074f29f431f68c6b3230c1315ea0f7c7bc86Jason Sams    float f =x;
4223e1074f29f431f68c6b3230c1315ea0f7c7bc86Jason Sams    float sum = poly[0]+poly[1]*f;
43572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    int i;
44572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    for (i = 2; i < n; i++) {
45572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        f*=x;
46572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        sum += poly[i]*f;
47572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    }
48572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    return sum;
49572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams}
50572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
51572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsstatic ushort3 rgb2hsv( uchar4 rgb)
52572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams{
53572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    int iMin,iMax,chroma;
54572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
55572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    int ri = rgb.r;
56572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    int gi = rgb.g;
57572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    int bi = rgb.b;
58572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    short rv,rs,rh;
59572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
60572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    if (ri > gi) {
61572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        iMax = max (ri, bi);
62572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        iMin = min (gi, bi);
63572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    } else {
64572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        iMax = max (gi, bi);
65572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        iMin = min (ri, bi);
66572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    }
67572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
68572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    chroma = iMax - iMin;
69572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    // set value
70572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    rv = (short)( iMax << ABITS);
71572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
72572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    // set saturation
73572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    if (rv == 0)
74572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        rs = 0;
75572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    else
76572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        rs = (short)((k1*chroma)/iMax);
77572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
78572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    // set hue
79572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    if (rs == 0)
80572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        rh = 0;
81572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    else {
82572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        if ( ri == iMax ) {
83572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            rh  = (short)( (k2*(6*chroma+gi - bi))/(6*chroma));
84572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            if (rh >= k2) rh -= k2;
85572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        } else if (gi  == iMax)
86572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            rh  = (short)( (k2*(2*chroma+bi - ri ))/(6*chroma));
87572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        else // (bi == iMax )
88572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams                    rh  = (short)( (k2*(4*chroma+ri - gi ))/(6*chroma));
89572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    }
90572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
91572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    ushort3 out;
92572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    out.x = rv;
93572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    out.y = rs;
94572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    out.z = rh;
95572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    return out;
96572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams}
97572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
98572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsstatic uchar4 hsv2rgb(ushort3 hsv)
99572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams{
100572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    int ABITS = 4;
101572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    int HSCALE = 256;
102572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    int m;
103572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    int H,X,ih,is,iv;
104572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    int k1=255<<ABITS;
105572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    int k2=HSCALE<<ABITS;
106572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    int k3=1<<(ABITS-1);
107572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    int rr=0;
108572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    int rg=0;
109572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    int rb=0;
110572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    short cv = hsv.x;
111572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    short cs = hsv.y;
112572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    short ch = hsv.z;
113572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
114572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    // set chroma and min component value m
115572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    //chroma = ( cv * cs )/k1;
116572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    //m = cv - chroma;
117572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    m = ((int)cv*(k1 - (int)cs ))/k1;
118572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
119572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    // chroma  == 0 <-> cs == 0 --> m=cv
120572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    if (cs == 0) {
121572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        rb = ( rg = ( rr =( cv >> ABITS) ));
122572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    } else {
123572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        ih=(int)ch;
124572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        is=(int)cs;
125572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        iv=(int)cv;
126572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
127572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        H = (6*ih)/k2;
128572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        X = ((iv*is)/k2)*(k2- abs(6*ih- 2*(H>>1)*k2 - k2)) ;
129572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
130572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        // removing additional bits --> unit8
131572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        X=( (X+iv*(k1 - is ))/k1 + k3 ) >> ABITS;
132572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        m=m >> ABITS;
133572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
134572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        // ( chroma + m ) --> cv ;
135572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        cv=(short) (cv >> ABITS);
136572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        switch (H) {
137572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        case 0:
138572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            rr = cv;
139572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            rg = X;
140572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            rb = m;
141572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            break;
142572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        case 1:
143572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            rr = X;
144572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            rg = cv;
145572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            rb = m;
146572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            break;
147572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        case 2:
148572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            rr = m;
149572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            rg = cv;
150572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            rb = X;
151572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            break;
152572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        case 3:
153572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            rr = m;
154572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            rg = X;
155572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            rb = cv;
156572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            break;
157572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        case 4:
158572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            rr = X;
159572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            rg = m;
160572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            rb = cv;
161572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            break;
162572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        case 5:
163572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            rr = cv;
164572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            rg = m ;
165572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            rb = X;
166572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            break;
167572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        }
168572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    }
169572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
170572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    uchar4 rgb;
171572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
172572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    rgb.r =  rr;
173572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    rgb.g =  rg;
174572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    rgb.b =  rb;
175572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
176572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    return rgb;
177572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams}
178572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
179572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsvoid prepareShadows(float scale) {
18023e1074f29f431f68c6b3230c1315ea0f7c7bc86Jason Sams    float s = (scale>=0) ? scale : scale / 5.f;
181572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    for (int i = 0; i < 5; i++) {
182572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        poly[i] = fastevalPoly(shadowFilterMap+i*2,2 , s);
183572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    }
184572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams}
185572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
186025b5f82971c431eb22df3c9d0f00b3cbe426bdbChris Wailesuchar4 RS_KERNEL shadowsKernel(uchar4 in) {
18723e1074f29f431f68c6b3230c1315ea0f7c7bc86Jason Sams    ushort3 hsv = rgb2hsv(in);
18823e1074f29f431f68c6b3230c1315ea0f7c7bc86Jason Sams    float v = (fastevalPoly(poly, 5, hsv.x * (1.f / 4080.f)) * 4080.f);
18923e1074f29f431f68c6b3230c1315ea0f7c7bc86Jason Sams    hsv.x = (unsigned short) clamp(v, 0.f, 4080.f);
19023e1074f29f431f68c6b3230c1315ea0f7c7bc86Jason Sams    return hsv2rgb(hsv);
191572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams}
192