unai: Use 8.8 RGB triplet format for gouraud shading
[pcsx_rearmed.git] / plugins / gpu_unai / gpu_unai.h
CommitLineData
0bfe8d59 1/***************************************************************************
2* Copyright (C) 2010 PCSX4ALL Team *
3* Copyright (C) 2010 Unai *
4* Copyright (C) 2016 Senquack (dansilsby <AT> gmail <DOT> com) *
5* *
6* This program is free software; you can redistribute it and/or modify *
7* it under the terms of the GNU General Public License as published by *
8* the Free Software Foundation; either version 2 of the License, or *
9* (at your option) any later version. *
10* *
11* This program is distributed in the hope that it will be useful, *
12* but WITHOUT ANY WARRANTY; without even the implied warranty of *
13* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14* GNU General Public License for more details. *
15* *
16* You should have received a copy of the GNU General Public License *
17* along with this program; if not, write to the *
18* Free Software Foundation, Inc., *
19* 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. *
20***************************************************************************/
21
22#ifndef GPU_UNAI_H
23#define GPU_UNAI_H
24
25#include "gpu.h"
26
e223fa15 27// Header shared between both standalone gpu_unai (gpu.cpp) and new
28// gpulib-compatible gpu_unai (gpulib_if.cpp)
29// -> Anything here should be for gpu_unai's private use. <-
0bfe8d59 30
31///////////////////////////////////////////////////////////////////////////////
32// Compile Options
33
34//#define ENABLE_GPU_NULL_SUPPORT // Enables NullGPU support
35//#define ENABLE_GPU_LOG_SUPPORT // Enables gpu logger, very slow only for windows debugging
36//#define ENABLE_GPU_ARMV7 // Enables ARMv7 optimized assembly
37
38//Poly routine options (default is integer math and accurate division)
39//#define GPU_UNAI_USE_FLOATMATH // Use float math in poly routines
40//#define GPU_UNAI_USE_FLOAT_DIV_MULTINV // If GPU_UNAI_USE_FLOATMATH is defined,
41 // use multiply-by-inverse for division
42//#define GPU_UNAI_USE_INT_DIV_MULTINV // If GPU_UNAI_USE_FLOATMATH is *not*
43 // defined, use old inaccurate division
44
45
46#define GPU_INLINE static inline __attribute__((always_inline))
47#define INLINE static inline __attribute__((always_inline))
48
49#define u8 uint8_t
50#define s8 int8_t
51#define u16 uint16_t
52#define s16 int16_t
53#define u32 uint32_t
54#define s32 int32_t
55#define s64 int64_t
b3bce60e
PC
56#define u64 uint64_t
57
58typedef union {
59 struct {
60 u16 r, g, b;
61 } c;
62 u64 raw;
63} gcol_t;
0bfe8d59 64
e223fa15 65typedef struct {
66 u32 v;
67} le32_t;
68
69typedef struct {
70 u16 v;
71} le16_t;
72
73static inline u32 le32_to_u32(le32_t le)
74{
75 return LE32TOH(le.v);
76}
77
78static inline s32 le32_to_s32(le32_t le)
79{
80 return (int32_t) LE32TOH(le.v);
81}
82
83static inline u32 le32_raw(le32_t le)
84{
85 return le.v;
86}
87
88static inline le32_t u32_to_le32(u32 u)
89{
90 return (le32_t){ .v = HTOLE32(u) };
91}
92
93static inline u16 le16_to_u16(le16_t le)
94{
95 return LE16TOH(le.v);
96}
97
98static inline s16 le16_to_s16(le16_t le)
99{
100 return (int16_t) LE16TOH(le.v);
101}
102
103static inline u16 le16_raw(le16_t le)
104{
105 return le.v;
106}
107
108static inline le16_t u16_to_le16(u16 u)
109{
110 return (le16_t){ .v = HTOLE16(u) };
111}
112
0bfe8d59 113union PtrUnion
114{
e223fa15 115 le32_t *U4;
116 le16_t *U2;
0bfe8d59 117 u8 *U1;
0bfe8d59 118 void *ptr;
119};
120
121union GPUPacket
122{
e223fa15 123 le32_t U4[16];
124 le16_t U2[32];
0bfe8d59 125 u8 U1[64];
0bfe8d59 126};
127
128template<class T> static inline void SwapValues(T &x, T &y)
129{
130 T tmp(x); x = y; y = tmp;
131}
132
133template<typename T>
134static inline T Min2 (const T a, const T b)
135{
136 return (a<b)?a:b;
137}
138
139template<typename T>
140static inline T Min3 (const T a, const T b, const T c)
141{
142 return Min2(Min2(a,b),c);
143}
144
145template<typename T>
146static inline T Max2 (const T a, const T b)
147{
148 return (a>b)?a:b;
149}
150
151template<typename T>
152static inline T Max3 (const T a, const T b, const T c)
153{
154 return Max2(Max2(a,b),c);
155}
156
157
158///////////////////////////////////////////////////////////////////////////////
159// GPU Raster Macros
160
161// Convert 24bpp color parameter of GPU command to 16bpp (15bpp + mask bit)
162#define GPU_RGB16(rgb) ((((rgb)&0xF80000)>>9)|(((rgb)&0xF800)>>6)|(((rgb)&0xF8)>>3))
163
164// Sign-extend 11-bit coordinate command param
165#define GPU_EXPANDSIGN(x) (((s32)(x)<<(32-11))>>(32-11))
166
167// Max difference between any two X or Y primitive coordinates
168#define CHKMAX_X 1024
169#define CHKMAX_Y 512
170
171#define FRAME_BUFFER_SIZE (1024*512*2)
172#define FRAME_WIDTH 1024
173#define FRAME_HEIGHT 512
174#define FRAME_OFFSET(x,y) (((y)<<10)+(x))
175#define FRAME_BYTE_STRIDE 2048
176#define FRAME_BYTES_PER_PIXEL 2
177
178static inline s32 GPU_DIV(s32 rs, s32 rt)
179{
180 return rt ? (rs / rt) : (0);
181}
182
183// 'Unsafe' version of above that doesn't check for div-by-zero
184#define GPU_FAST_DIV(rs, rt) ((signed)(rs) / (signed)(rt))
185
e223fa15 186struct gpu_unai_t {
0bfe8d59 187 u32 GPU_GP1;
188 GPUPacket PacketBuffer;
e223fa15 189 le16_t *vram;
0bfe8d59 190
e223fa15 191#ifdef USE_GPULIB
192 le16_t *downscale_vram;
193#endif
194 ////////////////////////////////////////////////////////////////////////////
195 // Variables used only by older standalone version of gpu_unai (gpu.cpp)
0bfe8d59 196#ifndef USE_GPULIB
197 u32 GPU_GP0;
198 u32 tex_window; // Current texture window vals (set by GP0(E2h) cmd)
199 s32 PacketCount;
200 s32 PacketIndex;
201 bool fb_dirty; // Framebuffer is dirty (according to GPU)
202
203 // Display status
e223fa15 204 // NOTE: Standalone older gpu_unai didn't care about horiz display range
0bfe8d59 205 u16 DisplayArea[6]; // [0] : Start of display area (in VRAM) X
206 // [1] : Start of display area (in VRAM) Y
207 // [2] : Display mode resolution HORIZONTAL
208 // [3] : Display mode resolution VERTICAL
209 // [4] : Vertical display range (on TV) START
210 // [5] : Vertical display range (on TV) END
211
212 ////////////////////////////////////////////////////////////////////////////
213 // Dma Transfers info
214 struct {
215 s32 px,py;
216 s32 x_end,y_end;
e223fa15 217 le16_t* pvram;
0bfe8d59 218 u32 *last_dma; // Last dma pointer
219 bool FrameToRead; // Load image in progress
220 bool FrameToWrite; // Store image in progress
221 } dma;
222
223 ////////////////////////////////////////////////////////////////////////////
224 // Frameskip
225 struct {
226 int skipCount; // Frame skip (0,1,2,3...)
227 bool isSkip; // Skip frame (according to GPU)
228 bool skipFrame; // Skip this frame (according to frame skip)
229 bool wasSkip; // Skip frame old value (according to GPU)
230 bool skipGPU; // Skip GPU primitives
231 } frameskip;
232#endif
e223fa15 233 // END of standalone gpu_unai variables
0bfe8d59 234 ////////////////////////////////////////////////////////////////////////////
235
236 u32 TextureWindowCur; // Current setting from last GP0(0xE2) cmd (raw form)
237 u8 TextureWindow[4]; // [0] : Texture window offset X
238 // [1] : Texture window offset Y
239 // [2] : Texture window mask X
240 // [3] : Texture window mask Y
241
242 u16 DrawingArea[4]; // [0] : Drawing area top left X
243 // [1] : Drawing area top left Y
244 // [2] : Drawing area bottom right X
245 // [3] : Drawing area bottom right Y
246
247 s16 DrawingOffset[2]; // [0] : Drawing offset X (signed)
248 // [1] : Drawing offset Y (signed)
249
e223fa15 250 le16_t* TBA; // Ptr to current texture in VRAM
251 le16_t* CBA; // Ptr to current CLUT in VRAM
0bfe8d59 252
253 ////////////////////////////////////////////////////////////////////////////
254 // Inner Loop parameters
255
256 // 22.10 Fixed-pt texture coords, mask, scanline advance
257 // NOTE: U,V are no longer packed together into one u32, this proved to be
258 // too imprecise, leading to pixel dropouts. Example: NFS3's skybox.
259 u32 u, v;
260 u32 u_msk, v_msk;
261 s32 u_inc, v_inc;
262
263 // Color for Gouraud-shaded prims
b3bce60e 264 // Fixed-pt 8.8 rgb triplet
0bfe8d59 265 // Packed fixed-pt 8.3:8.3:8.2 rgb triplet
b3bce60e
PC
266 // layout: ccccccccXXXXXXXX for c in [r, g, b]
267 // ^ bit 16
268 gcol_t gCol;
269 gcol_t gInc; // Increment along scanline for gCol
0bfe8d59 270
271 // Color for flat-shaded, texture-blended prims
272 u8 r5, g5, b5; // 5-bit light for undithered prims
273 u8 r8, g8, b8; // 8-bit light for dithered prims
274
275 // Color for flat-shaded, untextured prims
276 u16 PixelData; // bgr555 color for untextured flat-shaded polys
277
278 // End of inner Loop parameters
279 ////////////////////////////////////////////////////////////////////////////
280
281
282 u8 blit_mask; // Determines what pixels to skip when rendering.
283 // Only useful on low-resolution devices using
284 // a simple pixel-dropping downscaler for PS1
285 // high-res modes. See 'pixel_skip' option.
286
287 u8 ilace_mask; // Determines what lines to skip when rendering.
288 // Normally 0 when PS1 240 vertical res is in
289 // use and ilace_force is 0. When running in
290 // PS1 480 vertical res on a low-resolution
291 // device (320x240), will usually be set to 1
292 // so odd lines are not rendered. (Unless future
293 // full-screen scaling option is in use ..TODO)
294
295 bool prog_ilace_flag; // Tracks successive frames for 'prog_ilace' option
296
297 u8 BLEND_MODE;
298 u8 TEXT_MODE;
299 u8 Masking;
300
301 u16 PixelMSB;
302
e223fa15 303 gpu_unai_config_t config;
0bfe8d59 304
305 u8 LightLUT[32*32]; // 5-bit lighting LUT (gpu_inner_light.h)
306 u32 DitherMatrix[64]; // Matrix of dither coefficients
307};
308
e223fa15 309static gpu_unai_t gpu_unai;
0bfe8d59 310
311// Global config that frontend can alter.. Values are read in GPU_init().
312// TODO: if frontend menu modifies a setting, add a function that can notify
313// GPU plugin to use new setting.
e223fa15 314gpu_unai_config_t gpu_unai_config_ext;
0bfe8d59 315
316///////////////////////////////////////////////////////////////////////////////
317// Internal inline funcs to get option status: (Allows flexibility)
318static inline bool LightingEnabled()
319{
e223fa15 320 return gpu_unai.config.lighting;
0bfe8d59 321}
322
323static inline bool FastLightingEnabled()
324{
e223fa15 325 return gpu_unai.config.fast_lighting;
0bfe8d59 326}
327
328static inline bool BlendingEnabled()
329{
e223fa15 330 return gpu_unai.config.blending;
0bfe8d59 331}
332
333static inline bool DitheringEnabled()
334{
e223fa15 335 return gpu_unai.config.dithering;
0bfe8d59 336}
337
338// For now, this is just for development/experimentation purposes..
339// If modified to return true, it will allow ignoring the status register
340// bit 9 setting (dither enable). It will still restrict dithering only
341// to Gouraud-shaded or texture-blended polys.
342static inline bool ForcedDitheringEnabled()
343{
344 return false;
345}
346
347static inline bool ProgressiveInterlaceEnabled()
348{
349#ifdef USE_GPULIB
350 // Using this old option greatly decreases quality of image. Disabled
351 // for now when using new gpulib, since it also adds more work in loops.
352 return false;
353#else
e223fa15 354 return gpu_unai.config.prog_ilace;
0bfe8d59 355#endif
356}
357
358// For now, 320x240 output resolution is assumed, using simple line-skipping
359// and pixel-skipping downscaler.
360// TODO: Flesh these out so they return useful values based on whether
361// running on higher-res device or a resampling downscaler is enabled.
362static inline bool PixelSkipEnabled()
363{
e223fa15 364 return gpu_unai.config.pixel_skip || gpu_unai.config.scale_hires;
0bfe8d59 365}
366
367static inline bool LineSkipEnabled()
368{
369 return true;
370}
371
372#endif // GPU_UNAI_H