gpu: start doing some basic gpu timing
[pcsx_rearmed.git] / plugins / dfxvideo / gpulib_if.c
CommitLineData
b094071f 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>
62d7fa95 18#include "../gpulib/gpu.h"
f3af2eb5 19#include "../../include/arm_features.h"
b094071f 20
1290ebe4 21#if defined(__GNUC__) && (__GNUC__ >= 6 || (defined(__clang_major__) && __clang_major__ >= 10))
22#pragma GCC diagnostic ignored "-Wmisleading-indentation"
23#endif
24
a903b131
JW
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
b094071f 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
495d603c
PC
61#define SWAP16(x) __builtin_bswap16(x)
62#define SWAP32(x) __builtin_bswap32(x)
b094071f 63
ffe97735 64#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
b094071f 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
f3af2eb5 92#define GETLEs16(X) ((int16_t)GETLE16((uint16_t *)(X)))
b094071f 93
f3af2eb5 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))
b094071f 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
109typedef 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
122typedef struct PSXPOINTTAG
123{
124 int32_t x;
125 int32_t y;
126} PSXPoint_t;
127
128typedef struct PSXSPOINTTAG
129{
130 short x;
131 short y;
132} PSXSPoint_t;
133
134typedef 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
156typedef struct RECTTAG
157{
158 int left;
159 int top;
160 int right;
161 int bottom;
162}RECT;
163
164/////////////////////////////////////////////////////////////////////////////
165
166typedef struct TWINTAG
167{
168 PSXRect_t Position;
169 int xmask, ymask;
170} TWin_t;
171
172/////////////////////////////////////////////////////////////////////////////
173
174typedef 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
198extern int32_t GlobalTextAddrX,GlobalTextAddrY,GlobalTextTP;
199extern int32_t GlobalTextABR,GlobalTextPAGE;
200extern short ly0,lx0,ly1,lx1,ly2,lx2,ly3,lx3;
201extern long lLowerpart;
202extern BOOL bCheckMask;
203extern unsigned short sSetMask;
204extern unsigned long lSetMask;
205extern short g_m1;
206extern short g_m2;
207extern short g_m3;
208extern short DrawSemiTrans;
209
210// prim.c
211
212extern BOOL bUsingTWin;
213extern TWin_t TWin;
214extern void (*primTableJ[256])(unsigned char *);
215extern void (*primTableSkip[256])(unsigned char *);
216extern unsigned short usMirror;
217extern int iDither;
218extern uint32_t dwCfgFixes;
219extern uint32_t dwActFixes;
220extern int iUseFixes;
221extern int iUseDither;
222extern BOOL bDoVSyncUpdate;
223extern int32_t drawX;
224extern int32_t drawY;
225extern int32_t drawW;
226extern 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
ffe97735 242#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
b094071f 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)
ffe97735 247#else
b094071f 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
254PSXDisplay_t PSXDisplay;
255unsigned char *psxVub;
b094071f 256unsigned short *psxVuw;
257unsigned short *psxVuw_eom;
b094071f 258
259long lGPUstatusRet;
260uint32_t lGPUInfoVals[16];
261
262VRAMLoad_t VRAMWrite;
263VRAMLoad_t VRAMRead;
264
265DATAREGISTERMODES DataWriteMode;
266DATAREGISTERMODES DataReadMode;
267
268BOOL bCheckMask = FALSE;
269unsigned short sSetMask = 0;
270unsigned long lSetMask = 0;
271long lLowerpart;
272
5b568098 273#if defined(__GNUC__) && __GNUC__ >= 6
274#pragma GCC diagnostic ignored "-Wmisleading-indentation"
275#endif
276
62d7fa95 277#include "soft.c"
278#include "prim.c"
b094071f 279
280/////////////////////////////////////////////////////////////////////////////
281
9ee0fd5b 282static void set_vram(void *vram)
b094071f 283{
9ee0fd5b 284 psxVub=vram;
b094071f 285 psxVuw=(unsigned short *)psxVub;
b094071f 286 psxVuw_eom=psxVuw+1024*512; // pre-calc of end of vram
9ee0fd5b 287}
288
289int renderer_init(void)
290{
291 set_vram(gpu.vram);
b094071f 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
e929dec5 310void renderer_finish(void)
311{
312}
313
314void renderer_notify_res_change(void)
315{
316}
317
9a864a8f 318void renderer_notify_scanout_change(int x, int y)
3b7b0065 319{
320}
321
f99193c2 322#include "../gpulib/gpu_timing.h"
b094071f 323extern const unsigned char cmd_lengths[256];
324
f99193c2 325int do_cmd_list(uint32_t *list, int list_len, int *cpu_cycles_out, int *last_cmd)
b094071f 326{
b243416b 327 unsigned int cmd = 0, len;
fc99395c 328 uint32_t *list_start = list;
329 uint32_t *list_end = list + list_len;
f99193c2 330 u32 cpu_cycles = 0;
b094071f 331
332 for (; list < list_end; list += 1 + len)
333 {
f99193c2 334 short *slist = (void *)list;
495d603c 335 cmd = GETLE32(list) >> 24;
b094071f 336 len = cmd_lengths[cmd];
b243416b 337 if (list + 1 + len > list_end) {
338 cmd = -1;
339 break;
340 }
341
342#ifndef TEST
36da9c13 343 if (0x80 <= cmd && cmd < 0xe0)
b243416b 344 break; // image i/o, forward to upper layer
345 else if ((cmd & 0xf8) == 0xe0)
495d603c 346 gpu.ex_regs[cmd & 7] = GETLE32(list);
b243416b 347#endif
b094071f 348
349 primTableJ[cmd]((void *)list);
350
351 switch(cmd)
352 {
353 case 0x48 ... 0x4F:
354 {
b243416b 355 u32 num_vertexes = 2;
356 u32 *list_position = &(list[3]);
b094071f 357
358 while(1)
359 {
f99193c2 360 cpu_cycles += gput_line(0);
361
804789d7 362 if(list_position >= list_end) {
363 cmd = -1;
364 goto breakloop;
365 }
366
495d603c 367 if((*list_position & HOST2LE32(0xf000f000)) == HOST2LE32(0x50005000))
b094071f 368 break;
369
370 list_position++;
371 num_vertexes++;
372 }
373
b243416b 374 len += (num_vertexes - 2);
b094071f 375 break;
376 }
377
378 case 0x58 ... 0x5F:
379 {
b243416b 380 u32 num_vertexes = 2;
381 u32 *list_position = &(list[4]);
b094071f 382
383 while(1)
384 {
f99193c2 385 cpu_cycles += gput_line(0);
386
804789d7 387 if(list_position >= list_end) {
388 cmd = -1;
389 goto breakloop;
390 }
391
495d603c 392 if((*list_position & HOST2LE32(0xf000f000)) == HOST2LE32(0x50005000))
b094071f 393 break;
394
395 list_position += 2;
396 num_vertexes++;
397 }
398
b243416b 399 len += (num_vertexes - 2) * 2;
b094071f 400 break;
401 }
402
9a6e7816 403#ifdef TEST
b094071f 404 case 0xA0: // sys -> vid
405 {
495d603c
PC
406 u32 load_width = LE2HOST32(slist[4]);
407 u32 load_height = LE2HOST32(slist[5]);
b094071f 408 u32 load_size = load_width * load_height;
409
410 len += load_size / 2;
411 break;
412 }
9a6e7816 413#endif
f99193c2 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;
b094071f 443 }
444 }
b243416b 445
804789d7 446breakloop:
b243416b 447 gpu.ex_regs[1] &= ~0x1ff;
448 gpu.ex_regs[1] |= lGPUstatusRet & 0x1ff;
449
f99193c2 450 *cpu_cycles_out += cpu_cycles;
b243416b 451 *last_cmd = cmd;
452 return list - list_start;
b094071f 453}
454
3e629be9 455void renderer_sync_ecmds(uint32_t *ecmds_)
5b745e5b 456{
3e629be9 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
5b745e5b 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
3b7b0065 473void renderer_update_caches(int x, int y, int w, int h, int state_changed)
b094071f 474{
475}
476
477void renderer_flush_queues(void)
478{
479}
914455e6 480
5440b88e 481void renderer_set_interlace(int enable, int is_odd)
482{
483}
484
c765eb86
JW
485void renderer_sync(void)
486{
487}
488
489void renderer_notify_update_lace(int updated)
490{
491}
492
914455e6 493#include "../../frontend/plugin_lib.h"
494
495void renderer_set_config(const struct rearmed_cbs *cbs)
496{
497 iUseDither = cbs->gpu_peops.iUseDither;
498 dwActFixes = cbs->gpu_peops.dwActFixes;
fa56d360 499 if (cbs->pl_set_gpu_caps)
500 cbs->pl_set_gpu_caps(0);
9ee0fd5b 501 set_vram(gpu.vram);
914455e6 502}
f99193c2 503
504// vim:ts=2:shiftwidth=2:expandtab