gpu: start doing some basic gpu timing
[pcsx_rearmed.git] / plugins / dfxvideo / gpulib_if.c
1 /***************************************************************************
2     copyright            : (C) 2001 by Pete Bernert, 2011 notaz
3
4  ***************************************************************************/
5 /***************************************************************************
6  *                                                                         *
7  *   This program is free software; you can redistribute it and/or modify  *
8  *   it under the terms of the GNU General Public License as published by  *
9  *   the Free Software Foundation; either version 2 of the License, or     *
10  *   (at your option) any later version. See also the license.txt file for *
11  *   additional informations.                                              *
12  *                                                                         *
13  ***************************************************************************/
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include "../gpulib/gpu.h"
19 #include "../../include/arm_features.h"
20
21 #if defined(__GNUC__) && (__GNUC__ >= 6 || (defined(__clang_major__) && __clang_major__ >= 10))
22 #pragma GCC diagnostic ignored "-Wmisleading-indentation"
23 #endif
24
25 #ifdef THREAD_RENDERING
26 #include "../gpulib/gpulib_thread_if.h"
27 #define do_cmd_list real_do_cmd_list
28 #define renderer_init real_renderer_init
29 #define renderer_finish real_renderer_finish
30 #define renderer_sync_ecmds real_renderer_sync_ecmds
31 #define renderer_update_caches real_renderer_update_caches
32 #define renderer_flush_queues real_renderer_flush_queues
33 #define renderer_set_interlace real_renderer_set_interlace
34 #define renderer_set_config real_renderer_set_config
35 #define renderer_notify_res_change real_renderer_notify_res_change
36 #define renderer_notify_update_lace real_renderer_notify_update_lace
37 #define renderer_sync real_renderer_sync
38 #define ex_regs scratch_ex_regs
39 #endif
40
41 #define u32 uint32_t
42
43 #define INFO_TW        0
44 #define INFO_DRAWSTART 1
45 #define INFO_DRAWEND   2
46 #define INFO_DRAWOFF   3
47
48 #define SHADETEXBIT(x) ((x>>24) & 0x1)
49 #define SEMITRANSBIT(x) ((x>>25) & 0x1)
50 #define PSXRGB(r,g,b) ((g<<10)|(b<<5)|r)
51
52 #define DATAREGISTERMODES unsigned short
53
54 #define DR_NORMAL        0
55 #define DR_VRAMTRANSFER  1
56
57 #define GPUSTATUS_READYFORVRAM        0x08000000
58
59 // byteswappings
60
61 #define SWAP16(x) __builtin_bswap16(x)
62 #define SWAP32(x) __builtin_bswap32(x)
63
64 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
65
66 // big endian config
67 #define HOST2LE32(x) SWAP32(x)
68 #define HOST2BE32(x) (x)
69 #define LE2HOST32(x) SWAP32(x)
70 #define BE2HOST32(x) (x)
71
72 #define HOST2LE16(x) SWAP16(x)
73 #define HOST2BE16(x) (x)
74 #define LE2HOST16(x) SWAP16(x)
75 #define BE2HOST16(x) (x)
76
77 #else
78
79 // little endian config
80 #define HOST2LE32(x) (x)
81 #define HOST2BE32(x) SWAP32(x)
82 #define LE2HOST32(x) (x)
83 #define BE2HOST32(x) SWAP32(x)
84
85 #define HOST2LE16(x) (x)
86 #define HOST2BE16(x) SWAP16(x)
87 #define LE2HOST16(x) (x)
88 #define BE2HOST16(x) SWAP16(x)
89
90 #endif
91
92 #define GETLEs16(X) ((int16_t)GETLE16((uint16_t *)(X)))
93
94 #define GETLE16(X) LE2HOST16(*(uint16_t *)(X))
95 #define GETLE32_(X) LE2HOST32(*(uint32_t *)(X))
96 #define PUTLE16(X, Y) do{*((uint16_t *)(X))=HOST2LE16((uint16_t)(Y));}while(0)
97 #define PUTLE32_(X, Y) do{*((uint32_t *)(X))=HOST2LE32((uint32_t)(Y));}while(0)
98 #if defined(__arm__) && !defined(HAVE_ARMV6)
99 // for (very) old ARMs with no unaligned loads?
100 #define GETLE32(X) (*(uint16_t *)(X)|((uint32_t)((uint16_t *)(X))[1]<<16))
101 #define PUTLE32(X, Y) do{uint16_t *p_=(uint16_t *)(X);uint32_t y_=Y;p_[0]=y_;p_[1]=y_>>16;}while(0)
102 #else
103 #define GETLE32 GETLE32_
104 #define PUTLE32 PUTLE32_
105 #endif
106
107 /////////////////////////////////////////////////////////////////////////////
108
109 typedef struct VRAMLOADTTAG
110 {
111  short x;
112  short y;
113  short Width;
114  short Height;
115  short RowsRemaining;
116  short ColsRemaining;
117  unsigned short *ImagePtr;
118 } VRAMLoad_t;
119
120 /////////////////////////////////////////////////////////////////////////////
121
122 typedef struct PSXPOINTTAG
123 {
124  int32_t x;
125  int32_t y;
126 } PSXPoint_t;
127
128 typedef struct PSXSPOINTTAG
129 {
130  short x;
131  short y;
132 } PSXSPoint_t;
133
134 typedef struct PSXRECTTAG
135 {
136  short x0;
137  short x1;
138  short y0;
139  short y1;
140 } PSXRect_t;
141
142 // linux defines for some windows stuff
143
144 #define FALSE 0
145 #define TRUE 1
146 #define BOOL unsigned short
147 #define LOWORD(l)           ((unsigned short)(l))
148 #define HIWORD(l)           ((unsigned short)(((uint32_t)(l) >> 16) & 0xFFFF))
149 #define max(a,b)            (((a) > (b)) ? (a) : (b))
150 #define min(a,b)            (((a) < (b)) ? (a) : (b))
151 #define DWORD uint32_t
152 #ifndef __int64
153 #define __int64 long long int
154 #endif
155
156 typedef struct RECTTAG
157 {
158  int left;
159  int top;
160  int right;
161  int bottom;
162 }RECT;
163
164 /////////////////////////////////////////////////////////////////////////////
165
166 typedef struct TWINTAG
167 {
168  PSXRect_t  Position;
169  int xmask, ymask;
170 } TWin_t;
171
172 /////////////////////////////////////////////////////////////////////////////
173
174 typedef struct PSXDISPLAYTAG
175 {
176  PSXPoint_t  DisplayModeNew;
177  PSXPoint_t  DisplayMode;
178  PSXPoint_t  DisplayPosition;
179  PSXPoint_t  DisplayEnd;
180
181  int32_t        Double;
182  int32_t        Height;
183  int32_t        PAL;
184  int32_t        InterlacedNew;
185  int32_t        Interlaced;
186  int32_t        RGB24New;
187  int32_t        RGB24;
188  PSXSPoint_t DrawOffset;
189  int32_t        Disabled;
190  PSXRect_t   Range;
191
192 } PSXDisplay_t;
193
194 /////////////////////////////////////////////////////////////////////////////
195
196 // draw.c
197
198 extern int32_t           GlobalTextAddrX,GlobalTextAddrY,GlobalTextTP;
199 extern int32_t           GlobalTextABR,GlobalTextPAGE;
200 extern short          ly0,lx0,ly1,lx1,ly2,lx2,ly3,lx3;
201 extern long           lLowerpart;
202 extern BOOL           bCheckMask;
203 extern unsigned short sSetMask;
204 extern unsigned long  lSetMask;
205 extern short          g_m1;
206 extern short          g_m2;
207 extern short          g_m3;
208 extern short          DrawSemiTrans;
209
210 // prim.c
211
212 extern BOOL           bUsingTWin;
213 extern TWin_t         TWin;
214 extern void (*primTableJ[256])(unsigned char *);
215 extern void (*primTableSkip[256])(unsigned char *);
216 extern unsigned short  usMirror;
217 extern int            iDither;
218 extern uint32_t  dwCfgFixes;
219 extern uint32_t  dwActFixes;
220 extern int            iUseFixes;
221 extern int            iUseDither;
222 extern BOOL           bDoVSyncUpdate;
223 extern int32_t           drawX;
224 extern int32_t           drawY;
225 extern int32_t           drawW;
226 extern int32_t           drawH;
227
228 // gpu.h
229
230 #define OPAQUEON   10
231 #define OPAQUEOFF  11
232
233 #define KEY_RESETTEXSTORE 1
234 #define KEY_SHOWFPS       2
235 #define KEY_RESETOPAQUE   4
236 #define KEY_RESETDITHER   8
237 #define KEY_RESETFILTER   16
238 #define KEY_RESETADVBLEND 32
239 #define KEY_BADTEXTURES   128
240 #define KEY_CHECKTHISOUT  256
241
242 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
243 #define RED(x) (x & 0xff)
244 #define BLUE(x) ((x>>16) & 0xff)
245 #define GREEN(x) ((x>>8) & 0xff)
246 #define COLOR(x) (x & 0xffffff)
247 #else
248 #define RED(x) ((x>>24) & 0xff)
249 #define BLUE(x) ((x>>8) & 0xff)
250 #define GREEN(x) ((x>>16) & 0xff)
251 #define COLOR(x) SWAP32(x & 0xffffff)
252 #endif
253
254 PSXDisplay_t      PSXDisplay;
255 unsigned char  *psxVub;
256 unsigned short *psxVuw;
257 unsigned short *psxVuw_eom;
258
259 long              lGPUstatusRet;
260 uint32_t          lGPUInfoVals[16];
261
262 VRAMLoad_t        VRAMWrite;
263 VRAMLoad_t        VRAMRead;
264
265 DATAREGISTERMODES DataWriteMode;
266 DATAREGISTERMODES DataReadMode;
267
268 BOOL           bCheckMask = FALSE;
269 unsigned short sSetMask = 0;
270 unsigned long  lSetMask = 0;
271 long           lLowerpart;
272
273 #if defined(__GNUC__) && __GNUC__ >= 6
274 #pragma GCC diagnostic ignored "-Wmisleading-indentation"
275 #endif
276
277 #include "soft.c"
278 #include "prim.c"
279
280 /////////////////////////////////////////////////////////////////////////////
281
282 static void set_vram(void *vram)
283 {
284  psxVub=vram;
285  psxVuw=(unsigned short *)psxVub;
286  psxVuw_eom=psxVuw+1024*512;                           // pre-calc of end of vram
287 }
288
289 int renderer_init(void)
290 {
291  set_vram(gpu.vram);
292
293  PSXDisplay.RGB24        = FALSE;                      // init some stuff
294  PSXDisplay.Interlaced   = FALSE;
295  PSXDisplay.DrawOffset.x = 0;
296  PSXDisplay.DrawOffset.y = 0;
297  PSXDisplay.DisplayMode.x= 320;
298  PSXDisplay.DisplayMode.y= 240;
299  PSXDisplay.Disabled     = FALSE;
300  PSXDisplay.Range.x0=0;
301  PSXDisplay.Range.x1=0;
302  PSXDisplay.Double = 1;
303
304  DataWriteMode = DR_NORMAL;
305  lGPUstatusRet = 0x14802000;
306
307  return 0;
308 }
309
310 void renderer_finish(void)
311 {
312 }
313
314 void renderer_notify_res_change(void)
315 {
316 }
317
318 void renderer_notify_scanout_change(int x, int y)
319 {
320 }
321
322 #include "../gpulib/gpu_timing.h"
323 extern const unsigned char cmd_lengths[256];
324
325 int do_cmd_list(uint32_t *list, int list_len, int *cpu_cycles_out, int *last_cmd)
326 {
327   unsigned int cmd = 0, len;
328   uint32_t *list_start = list;
329   uint32_t *list_end = list + list_len;
330   u32 cpu_cycles = 0;
331
332   for (; list < list_end; list += 1 + len)
333   {
334     short *slist = (void *)list;
335     cmd = GETLE32(list) >> 24;
336     len = cmd_lengths[cmd];
337     if (list + 1 + len > list_end) {
338       cmd = -1;
339       break;
340     }
341
342 #ifndef TEST
343     if (0x80 <= cmd && cmd < 0xe0)
344       break; // image i/o, forward to upper layer
345     else if ((cmd & 0xf8) == 0xe0)
346       gpu.ex_regs[cmd & 7] = GETLE32(list);
347 #endif
348
349     primTableJ[cmd]((void *)list);
350
351     switch(cmd)
352     {
353       case 0x48 ... 0x4F:
354       {
355         u32 num_vertexes = 2;
356         u32 *list_position = &(list[3]);
357
358         while(1)
359         {
360           cpu_cycles += gput_line(0);
361
362           if(list_position >= list_end) {
363             cmd = -1;
364             goto breakloop;
365           }
366
367           if((*list_position & HOST2LE32(0xf000f000)) == HOST2LE32(0x50005000))
368             break;
369
370           list_position++;
371           num_vertexes++;
372         }
373
374         len += (num_vertexes - 2);
375         break;
376       }
377
378       case 0x58 ... 0x5F:
379       {
380         u32 num_vertexes = 2;
381         u32 *list_position = &(list[4]);
382
383         while(1)
384         {
385           cpu_cycles += gput_line(0);
386
387           if(list_position >= list_end) {
388             cmd = -1;
389             goto breakloop;
390           }
391
392           if((*list_position & HOST2LE32(0xf000f000)) == HOST2LE32(0x50005000))
393             break;
394
395           list_position += 2;
396           num_vertexes++;
397         }
398
399         len += (num_vertexes - 2) * 2;
400         break;
401       }
402
403 #ifdef TEST
404       case 0xA0:          //  sys -> vid
405       {
406         u32 load_width = LE2HOST32(slist[4]);
407         u32 load_height = LE2HOST32(slist[5]);
408         u32 load_size = load_width * load_height;
409
410         len += load_size / 2;
411         break;
412       }
413 #endif
414
415       // timing
416       case 0x02:
417         cpu_cycles += gput_fill(LE2HOST32(slist[4]) & 0x3ff,
418             LE2HOST32(slist[5]) & 0x1ff);
419         break;
420       case 0x20 ... 0x23: cpu_cycles += gput_poly_base();    break;
421       case 0x24 ... 0x27: cpu_cycles += gput_poly_base_t();  break;
422       case 0x28 ... 0x2B: cpu_cycles += gput_quad_base();    break;
423       case 0x2C ... 0x2F: cpu_cycles += gput_quad_base_t();  break;
424       case 0x30 ... 0x33: cpu_cycles += gput_poly_base_g();  break;
425       case 0x34 ... 0x37: cpu_cycles += gput_poly_base_gt(); break;
426       case 0x38 ... 0x3B: cpu_cycles += gput_quad_base_g();  break;
427       case 0x3C ... 0x3F: cpu_cycles += gput_quad_base_gt(); break;
428       case 0x40 ... 0x47: cpu_cycles += gput_line(0);        break;
429       case 0x50 ... 0x57: cpu_cycles += gput_line(0);        break;
430       case 0x60 ... 0x63:
431         cpu_cycles += gput_sprite(LE2HOST32(slist[4]) & 0x3ff,
432             LE2HOST32(slist[5]) & 0x1ff);
433         break;
434       case 0x64 ... 0x67:
435         cpu_cycles += gput_sprite(LE2HOST32(slist[6]) & 0x3ff,
436             LE2HOST32(slist[7]) & 0x1ff);
437         break;
438       case 0x68 ... 0x6B: cpu_cycles += gput_sprite(1, 1);   break;
439       case 0x70 ... 0x73:
440       case 0x74 ... 0x77: cpu_cycles += gput_sprite(8, 8);   break;
441       case 0x78 ... 0x7B:
442       case 0x7C ... 0x7F: cpu_cycles += gput_sprite(16, 16); break;
443     }
444   }
445
446 breakloop:
447   gpu.ex_regs[1] &= ~0x1ff;
448   gpu.ex_regs[1] |= lGPUstatusRet & 0x1ff;
449
450   *cpu_cycles_out += cpu_cycles;
451   *last_cmd = cmd;
452   return list - list_start;
453 }
454
455 void renderer_sync_ecmds(uint32_t *ecmds_)
456 {
457 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
458   // the funcs below expect LE
459   uint32_t i, ecmds[8];
460   for (i = 1; i <= 6; i++)
461     ecmds[i] = HTOLE32(ecmds_[i]);
462 #else
463   uint32_t *ecmds = ecmds_;
464 #endif
465   cmdTexturePage((unsigned char *)&ecmds[1]);
466   cmdTextureWindow((unsigned char *)&ecmds[2]);
467   cmdDrawAreaStart((unsigned char *)&ecmds[3]);
468   cmdDrawAreaEnd((unsigned char *)&ecmds[4]);
469   cmdDrawOffset((unsigned char *)&ecmds[5]);
470   cmdSTP((unsigned char *)&ecmds[6]);
471 }
472
473 void renderer_update_caches(int x, int y, int w, int h, int state_changed)
474 {
475 }
476
477 void renderer_flush_queues(void)
478 {
479 }
480
481 void renderer_set_interlace(int enable, int is_odd)
482 {
483 }
484
485 void renderer_sync(void)
486 {
487 }
488
489 void renderer_notify_update_lace(int updated)
490 {
491 }
492
493 #include "../../frontend/plugin_lib.h"
494
495 void renderer_set_config(const struct rearmed_cbs *cbs)
496 {
497  iUseDither = cbs->gpu_peops.iUseDither;
498  dwActFixes = cbs->gpu_peops.dwActFixes;
499  if (cbs->pl_set_gpu_caps)
500   cbs->pl_set_gpu_caps(0);
501  set_vram(gpu.vram);
502 }
503
504 // vim:ts=2:shiftwidth=2:expandtab