db: a hack for Tunguska
[pcsx_rearmed.git] / plugins / gpu_unai / gpu_inner_light.h
... / ...
CommitLineData
1/***************************************************************************
2* Copyright (C) 2016 PCSX4ALL Team *
3* Copyright (C) 2010 Unai *
4* *
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. *
9* *
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. *
14* *
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***************************************************************************/
20
21#ifndef _OP_LIGHT_H_
22#define _OP_LIGHT_H_
23
24// GPU color operations for lighting calculations
25
26static void SetupLightLUT()
27{
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
63
64 for (int j=0; j < 32; ++j) {
65 for (int i=0; i < 32; ++i) {
66 int val = i * j / 16;
67 if (val > 31) val = 31;
68 gpu_unai.LightLUT[(j*32) + i] = val;
69 }
70 }
71}
72
73// gcc5+ and clang13+ understarnd this on ARM
74GPU_INLINE s32 clamp_c(s32 x) {
75 if (x < 0) return 0;
76 if (x > 31) return 31;
77 return x;
78}
79
80////////////////////////////////////////////////////////////////////////////////
81// Create packed Gouraud fixed-pt 8.8 rgb triplet
82//
83// INPUT:
84// 'r','g','b' are 8.10 fixed-pt color components (r shown here)
85// 'r' input: --------------rrrrrrrrXXXXXXXXXX
86// ^ bit 31
87// RETURNS:
88// gcol_t output: ccccccccXXXXXXXX for c in [r, g, b]
89// ^ bit 16
90// Where 'r,g,b' are integer bits of colors, 'X' fixed-pt, and '-' don't care
91////////////////////////////////////////////////////////////////////////////////
92GPU_INLINE gcol_t gpuPackGouraudCol(u32 r, u32 g, u32 b)
93{
94 return (gcol_t){{
95 (u16)(r >> 2),
96 (u16)(g >> 2),
97 (u16)(b >> 2),
98 0
99 }};
100}
101
102////////////////////////////////////////////////////////////////////////////////
103// Create packed increment for Gouraud fixed-pt 8.8 rgb triplet
104//
105// INPUT:
106// Sign-extended 8.10 fixed-pt r,g,b color increment values (only dr is shown)
107// 'dr' input: ssssssssssssssrrrrrrrrXXXXXXXXXX
108// ^ bit 31
109// RETURNS:
110// gcol_t output: ccccccccXXXXXXXX for c in [r, g, b]
111// ^ bit 16
112// Where 'r,g,b' are integer bits of colors, 'X' fixed-pt, and 's' sign bits
113//
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////////////////////////////////////////////////////////////////////////////////
118GPU_INLINE gcol_t gpuPackGouraudColInc(s32 dr, s32 dg, s32 db)
119{
120 return (gcol_t){{
121 (u16)((dr >> 2) + (dr < 0)),
122 (u16)((dg >> 2) + (dg < 0)),
123 (u16)((db >> 2) + (db < 0)),
124 0
125 }};
126}
127
128////////////////////////////////////////////////////////////////////////////////
129// Extract bgr555 color from Gouraud u32 fixed-pt 8.8 rgb triplet
130//
131// INPUT:
132// 'gCol' input: ccccccccXXXXXXXX for c in [r, g, b]
133// ^ bit 16
134// RETURNS:
135// u16 output: 0bbbbbgggggrrrrr
136// ^ bit 16
137// Where 'r,g,b' are integer bits of colors, 'X' fixed-pt, and '0' zero
138////////////////////////////////////////////////////////////////////////////////
139GPU_INLINE uint_fast16_t gpuLightingRGB(gcol_t gCol)
140{
141 return (gCol.c.r >> 11) |
142 ((gCol.c.g >> 6) & 0x3e0) |
143 ((gCol.c.b >> 1) & 0x7c00);
144}
145
146GPU_INLINE uint_fast16_t gpuLightingRGBDither(gcol_t gCol, int_fast16_t dt)
147{
148 dt <<= 4;
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);
152}
153
154////////////////////////////////////////////////////////////////////////////////
155// Apply fast (low-precision) 5-bit lighting to bgr555 texture color:
156//
157// INPUT:
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
161// ^ bit 16
162// RETURNS:
163// u16 output: mbbbbbgggggrrrrr
164// Where 'X' are fixed-pt bits, 'm' is the MSB to preserve
165////////////////////////////////////////////////////////////////////////////////
166GPU_INLINE uint_fast16_t gpuLightingTXTGeneric(uint_fast16_t uSrc, u32 bgr0888)
167{
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;
172
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] ) |
176 (uSrc & 0x8000);
177}
178
179
180////////////////////////////////////////////////////////////////////////////////
181// Apply fast (low-precision) 5-bit Gouraud lighting to bgr555 texture color:
182//
183// INPUT:
184// 'gCol' is a Gouraud fixed-pt 8.8 rgb triplet
185// 'gCol' input: ccccccccXXXXXXXX for c in [r, g, b]
186// ^ bit 16
187// 'uSrc' input: mbbbbbgggggrrrrr
188// ^ bit 16
189// RETURNS:
190// u16 output: mbbbbbgggggrrrrr
191// Where 'X' are fixed-pt bits, 'm' is the MSB to preserve
192////////////////////////////////////////////////////////////////////////////////
193GPU_INLINE uint_fast16_t gpuLightingTXTGouraudGeneric(uint_fast16_t uSrc, gcol_t gCol)
194{
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)]) |
198 (uSrc & 0x8000);
199}
200
201////////////////////////////////////////////////////////////////////////////////
202// Apply high-precision 8-bit lighting to bgr555 texture color,
203//
204// INPUT:
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
207//
208// uSrc input: mbbbbbgggggrrrrr
209// ^ bit 16
210// RETURNS:
211// u16 output: mbbbbbgggggrrrrr
212// Where 'X' are fixed-pt bits, 'm' is the MSB to preserve
213////////////////////////////////////////////////////////////////////////////////
214GPU_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)
216{
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) |
226 (uSrc & 0x8000);
227}
228
229GPU_INLINE uint_fast16_t gpuLightingTXTDither(uint_fast16_t uSrc, u32 bgr0888, int_fast16_t dv)
230{
231 return gpuLightingTXTDitherRGB(uSrc, bgr0888 & 0xff,
232 (bgr0888 >> 8) & 0xff, bgr0888 >> 16, dv);
233}
234
235GPU_INLINE uint_fast16_t gpuLightingTXTGouraudDither(uint_fast16_t uSrc, gcol_t gCol, int_fast8_t dv)
236{
237 return gpuLightingTXTDitherRGB(uSrc, gCol.c.r >> 8, gCol.c.g >> 8, gCol.c.b >> 8, dv);
238}
239
240#endif //_OP_LIGHT_H_