1 /***************************************************************************
2 * Copyright (C) 2016 PCSX4ALL Team *
3 * Copyright (C) 2010 Unai *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. *
19 ***************************************************************************/
24 // GPU color operations for lighting calculations
26 static void SetupLightLUT()
28 // 1024-entry lookup table that modulates 5-bit texture + 5-bit light value.
29 // A light value of 15 does not modify the incoming texture color.
30 // LightLUT[32*32] array is initialized to following values:
31 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
32 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
33 // 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
34 // 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5,
35 // 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7,
36 // 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9,
37 // 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 9, 9, 9,10,10,10,11,11,
38 // 0, 0, 0, 1, 1, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 7, 8, 8, 9, 9,10,10,10,11,11,12,12,13,13,
39 // 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,10,10,11,11,12,12,13,13,14,14,15,15,
40 // 0, 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 6, 7, 7, 8, 9, 9,10,10,11,11,12,12,13,14,14,15,15,16,16,17,
41 // 0, 0, 1, 1, 2, 3, 3, 4, 5, 5, 6, 6, 7, 8, 8, 9,10,10,11,11,12,13,13,14,15,15,16,16,17,18,18,19,
42 // 0, 0, 1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9,10,11,11,12,13,13,14,15,15,16,17,17,18,19,19,20,21,
43 // 0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9,10,11,12,12,13,14,15,15,16,17,18,18,19,20,21,21,22,23,
44 // 0, 0, 1, 2, 3, 4, 4, 5, 6, 7, 8, 8, 9,10,11,12,13,13,14,15,16,17,17,18,19,20,21,21,22,23,24,25,
45 // 0, 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 9,10,11,12,13,14,14,15,16,17,18,19,20,21,21,22,23,24,25,26,27,
46 // 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,
47 // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
48 // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,31,
49 // 0, 1, 2, 3, 4, 5, 6, 7, 9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,27,28,29,30,31,31,31,31,
50 // 0, 1, 2, 3, 4, 5, 7, 8, 9,10,11,13,14,15,16,17,19,20,21,22,23,24,26,27,28,29,30,31,31,31,31,31,
51 // 0, 1, 2, 3, 5, 6, 7, 8,10,11,12,13,15,16,17,18,20,21,22,23,25,26,27,28,30,31,31,31,31,31,31,31,
52 // 0, 1, 2, 3, 5, 6, 7, 9,10,11,13,14,15,17,18,19,21,22,23,24,26,27,28,30,31,31,31,31,31,31,31,31,
53 // 0, 1, 2, 4, 5, 6, 8, 9,11,12,13,15,16,17,19,20,22,23,24,26,27,28,30,31,31,31,31,31,31,31,31,31,
54 // 0, 1, 2, 4, 5, 7, 8,10,11,12,14,15,17,18,20,21,23,24,25,27,28,30,31,31,31,31,31,31,31,31,31,31,
55 // 0, 1, 3, 4, 6, 7, 9,10,12,13,15,16,18,19,21,22,24,25,27,28,30,31,31,31,31,31,31,31,31,31,31,31,
56 // 0, 1, 3, 4, 6, 7, 9,10,12,14,15,17,18,20,21,23,25,26,28,29,31,31,31,31,31,31,31,31,31,31,31,31,
57 // 0, 1, 3, 4, 6, 8, 9,11,13,14,16,17,19,21,22,24,26,27,29,30,31,31,31,31,31,31,31,31,31,31,31,31,
58 // 0, 1, 3, 5, 6, 8,10,11,13,15,16,18,20,21,23,25,27,28,30,31,31,31,31,31,31,31,31,31,31,31,31,31,
59 // 0, 1, 3, 5, 7, 8,10,12,14,15,17,19,21,22,24,26,28,29,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
60 // 0, 1, 3, 5, 7, 9,10,12,14,16,18,19,21,23,25,27,29,30,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
61 // 0, 1, 3, 5, 7, 9,11,13,15,16,18,20,22,24,26,28,30,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
62 // 0, 1, 3, 5, 7, 9,11,13,15,17,19,21,23,25,27,29,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31
64 for (int j=0; j < 32; ++j) {
65 for (int i=0; i < 32; ++i) {
67 if (val > 31) val = 31;
68 gpu_unai.LightLUT[(j*32) + i] = val;
73 // gcc5+ and clang13+ understarnd this on ARM
74 GPU_INLINE s32 clamp_c(s32 x) {
76 if (x > 31) return 31;
80 ////////////////////////////////////////////////////////////////////////////////
81 // Create packed Gouraud fixed-pt 8.8 rgb triplet
84 // 'r','g','b' are 8.10 fixed-pt color components (r shown here)
85 // 'r' input: --------------rrrrrrrrXXXXXXXXXX
88 // gcol_t output: ccccccccXXXXXXXX for c in [r, g, b]
90 // Where 'r,g,b' are integer bits of colors, 'X' fixed-pt, and '-' don't care
91 ////////////////////////////////////////////////////////////////////////////////
92 GPU_INLINE gcol_t gpuPackGouraudCol(u32 r, u32 g, u32 b)
102 ////////////////////////////////////////////////////////////////////////////////
103 // Create packed increment for Gouraud fixed-pt 8.8 rgb triplet
106 // Sign-extended 8.10 fixed-pt r,g,b color increment values (only dr is shown)
107 // 'dr' input: ssssssssssssssrrrrrrrrXXXXXXXXXX
110 // gcol_t output: ccccccccXXXXXXXX for c in [r, g, b]
112 // Where 'r,g,b' are integer bits of colors, 'X' fixed-pt, and 's' sign bits
114 // NOTE: The correctness of this code/method has not been fully verified,
115 // having been merely factored out from original code in
116 // poly-drawing functions. Feel free to check/improve it -senquack
117 ////////////////////////////////////////////////////////////////////////////////
118 GPU_INLINE gcol_t gpuPackGouraudColInc(s32 dr, s32 dg, s32 db)
121 (u16)((dr >> 2) + (dr < 0)),
122 (u16)((dg >> 2) + (dg < 0)),
123 (u16)((db >> 2) + (db < 0)),
128 ////////////////////////////////////////////////////////////////////////////////
129 // Extract bgr555 color from Gouraud u32 fixed-pt 8.8 rgb triplet
132 // 'gCol' input: ccccccccXXXXXXXX for c in [r, g, b]
135 // u16 output: 0bbbbbgggggrrrrr
137 // Where 'r,g,b' are integer bits of colors, 'X' fixed-pt, and '0' zero
138 ////////////////////////////////////////////////////////////////////////////////
139 GPU_INLINE uint_fast16_t gpuLightingRGB(gcol_t gCol)
141 return (gCol.c.r >> 11) |
142 ((gCol.c.g >> 6) & 0x3e0) |
143 ((gCol.c.b >> 1) & 0x7c00);
146 GPU_INLINE uint_fast16_t gpuLightingRGBDither(gcol_t gCol, int_fast16_t dt)
149 return clamp_c(((s32)gCol.c.r + dt) >> 11) |
150 (clamp_c(((s32)gCol.c.g + dt) >> 11) << 5) |
151 (clamp_c(((s32)gCol.c.b + dt) >> 11) << 10);
154 ////////////////////////////////////////////////////////////////////////////////
155 // Apply fast (low-precision) 5-bit lighting to bgr555 texture color:
158 // 'r8','g8','b8' are unsigned 8-bit color values, value of 127
159 // is midpoint that doesn't modify that component of texture
160 // 'uSrc' input: mbbbbbgggggrrrrr
163 // u16 output: mbbbbbgggggrrrrr
164 // Where 'X' are fixed-pt bits, 'm' is the MSB to preserve
165 ////////////////////////////////////////////////////////////////////////////////
166 GPU_INLINE uint_fast16_t gpuLightingTXTGeneric(uint_fast16_t uSrc, u32 bgr0888)
168 // the compiler can move this out of the loop if it wants to
169 uint_fast32_t b5 = (bgr0888 >> 19);
170 uint_fast32_t g5 = (bgr0888 >> 11) & 0x1f;
171 uint_fast32_t r5 = (bgr0888 >> 3) & 0x1f;
173 return (gpu_unai.LightLUT[((uSrc&0x7C00)>>5) | b5] << 10) |
174 (gpu_unai.LightLUT[ (uSrc&0x03E0) | g5] << 5) |
175 (gpu_unai.LightLUT[((uSrc&0x001F)<<5) | r5] ) |
180 ////////////////////////////////////////////////////////////////////////////////
181 // Apply fast (low-precision) 5-bit Gouraud lighting to bgr555 texture color:
184 // 'gCol' is a Gouraud fixed-pt 8.8 rgb triplet
185 // 'gCol' input: ccccccccXXXXXXXX for c in [r, g, b]
187 // 'uSrc' input: mbbbbbgggggrrrrr
190 // u16 output: mbbbbbgggggrrrrr
191 // Where 'X' are fixed-pt bits, 'm' is the MSB to preserve
192 ////////////////////////////////////////////////////////////////////////////////
193 GPU_INLINE uint_fast16_t gpuLightingTXTGouraudGeneric(uint_fast16_t uSrc, gcol_t gCol)
195 return (gpu_unai.LightLUT[((uSrc&0x7C00)>>5) | (gCol.c.b >> 11)] << 10) |
196 (gpu_unai.LightLUT[ (uSrc&0x03E0) | (gCol.c.g >> 11)] << 5) |
197 (gpu_unai.LightLUT[((uSrc&0x001F)<<5) | (gCol.c.r >> 11)]) |
201 ////////////////////////////////////////////////////////////////////////////////
202 // Apply high-precision 8-bit lighting to bgr555 texture color,
205 // 'r','g','b' are unsigned 8-bit color component values, value of
206 // 127 is midpoint that doesn't modify that component of texture
208 // uSrc input: mbbbbbgggggrrrrr
211 // u16 output: mbbbbbgggggrrrrr
212 // Where 'X' are fixed-pt bits, 'm' is the MSB to preserve
213 ////////////////////////////////////////////////////////////////////////////////
214 GPU_INLINE uint_fast16_t gpuLightingTXTDitherRGB(uint_fast16_t uSrc,
215 uint_fast8_t r, uint_fast8_t g, uint_fast8_t b, int_fast16_t dv)
217 uint_fast16_t rs = uSrc & 0x001F;
218 uint_fast16_t gs = uSrc & 0x03E0;
219 uint_fast16_t bs = uSrc & 0x7C00;
220 s32 r3 = rs * r + dv;
221 s32 g3 = gs * g + (dv << 5);
222 s32 b3 = bs * b + (dv << 10);
223 return clamp_c(r3 >> 7) |
224 (clamp_c(g3 >> 12) << 5) |
225 (clamp_c(b3 >> 17) << 10) |
229 GPU_INLINE uint_fast16_t gpuLightingTXTDither(uint_fast16_t uSrc, u32 bgr0888, int_fast16_t dv)
231 return gpuLightingTXTDitherRGB(uSrc, bgr0888 & 0xff,
232 (bgr0888 >> 8) & 0xff, bgr0888 >> 16, dv);
235 GPU_INLINE uint_fast16_t gpuLightingTXTGouraudDither(uint_fast16_t uSrc, gcol_t gCol, int_fast8_t dv)
237 return gpuLightingTXTDitherRGB(uSrc, gCol.c.r >> 8, gCol.c.g >> 8, gCol.c.b >> 8, dv);
240 #endif //_OP_LIGHT_H_