libdragon
rdpq_rect.h
Go to the documentation of this file.
1
7#ifndef LIBDRAGON_RDPQ_RECT_H
8#define LIBDRAGON_RDPQ_RECT_H
9
10#include "rdpq.h"
11
12#ifdef __cplusplus
13extern "C" {
14#endif
15
16// Internal functions used for inline optimizations. Not part of the public API.
17// Do not call directly
19#define __UNLIKELY(x) __builtin_expect(!!(x), 0)
20
21__attribute__((always_inline))
22inline void __rdpq_fill_rectangle_inline(int32_t x0, int32_t y0, int32_t x1, int32_t y1) {
23 if (__UNLIKELY(x0 < 0)) x0 = 0;
24 if (__UNLIKELY(y0 < 0)) y0 = 0;
25 if (__UNLIKELY(x1 > 0xFFF)) x1 = 0xFFF;
26 if (__UNLIKELY(y1 > 0xFFF)) y1 = 0xFFF;
27 if (__UNLIKELY(x0 >= x1 || y0 >= y1)) return;
28
29 extern void __rdpq_fill_rectangle(uint32_t w0, uint32_t w1);
30 __rdpq_fill_rectangle(
31 _carg(x1, 0xFFF, 12) | _carg(y1, 0xFFF, 0),
32 _carg(x0, 0xFFF, 12) | _carg(y0, 0xFFF, 0));
33}
34
35__attribute__((always_inline))
36inline void __rdpq_texture_rectangle_inline(rdpq_tile_t tile,
37 int32_t x0, int32_t y0, int32_t x1, int32_t y1,
38 int32_t s0, int32_t t0)
39{
40 if (__UNLIKELY(x1 == x0 || y1 == y0)) return;
41 int32_t dsdx = 1<<10, dtdy = 1<<10;
42
43 if (__UNLIKELY(x0 > x1)) {
44 int32_t tmp = x0; x0 = x1; x1 = tmp;
45 x0 += 4; x1 += 4;
46 s0 += (x1 - x0 - 4) << 3;
47 dsdx = -dsdx;
48 }
49 if (__UNLIKELY(y0 > y1)) {
50 int32_t tmp = y0; y0 = y1; y1 = tmp;
51 y0 += 4; y1 += 4;
52 t0 += (y1 - y0 - 4) << 3;
53 dtdy = -dtdy;
54 }
55 if (__UNLIKELY(x0 < 0)) {
56 s0 -= (x0 * dsdx) >> 7;
57 x0 = 0;
58 if (__UNLIKELY(x0 >= x1)) return;
59 }
60 if (__UNLIKELY(y0 < 0)) {
61 t0 -= (y0 * dtdy) >> 7;
62 y0 = 0;
63 if (__UNLIKELY(y0 >= y1)) return;
64 }
65 if (__UNLIKELY(x1 > 1024*4-1)) {
66 x1 = 1024*4-1;
67 if (__UNLIKELY(x0 >= x1)) return;
68 }
69 if (__UNLIKELY(y1 > 1024*4-1)) {
70 y1 = 1024*4-1;
71 if (__UNLIKELY(y0 >= y1)) return;
72 }
73
74 extern void __rdpq_texture_rectangle(uint32_t w0, uint32_t w1, uint32_t w2, uint32_t w3);
75 __rdpq_texture_rectangle(
76 _carg(x1, 0xFFF, 12) | _carg(y1, 0xFFF, 0),
77 _carg(tile, 0x7, 24) | _carg(x0, 0xFFF, 12) | _carg(y0, 0xFFF, 0),
78 _carg(s0, 0xFFFF, 16) | _carg(t0, 0xFFFF, 0),
79 _carg(dsdx, 0xFFFF, 16) | _carg(dtdy, 0xFFFF, 0));
80}
81
82__attribute__((always_inline))
83inline void __rdpq_texture_rectangle_scaled_inline(rdpq_tile_t tile,
84 int32_t x0, int32_t y0, int32_t x1, int32_t y1,
85 int32_t s0, int32_t t0, int32_t s1, int32_t t1)
86{
87 if (__UNLIKELY(x1 == x0 || y1 == y0)) return;
88 int32_t dsdx = ((s1 - s0) << 7) / (x1 - x0), dtdy = ((t1 - t0) << 7) / (y1 - y0);
89
90 if (__UNLIKELY(x0 > x1)) {
91 int32_t tmp = x0; x0 = x1; x1 = tmp;
92 s0 += ((x0 - x1 - 4) * dsdx) >> 7;
93 }
94 if (__UNLIKELY(y0 > y1)) {
95 int32_t tmp = y0; y0 = y1; y1 = tmp;
96 t0 += ((y0 - y1 - 4) * dtdy) >> 7;
97 }
98 if (__UNLIKELY(x0 < 0)) {
99 s0 -= (x0 * dsdx) >> 7;
100 x0 = 0;
101 if (__UNLIKELY(x0 >= x1)) return;
102 }
103 if (__UNLIKELY(y0 < 0)) {
104 t0 -= (y0 * dtdy) >> 7;
105 y0 = 0;
106 if (__UNLIKELY(y0 >= y1)) return;
107 }
108 if (__UNLIKELY(x1 > 1024*4-1)) {
109 s1 -= ((x1 - 1024*4-1) * dsdx) >> 7;
110 x1 = 1024*4-1;
111 if (__UNLIKELY(x0 >= x1)) return;
112 }
113 if (__UNLIKELY(y1 > 1024*4-1)) {
114 t1 -= ((y1 - 1024*4-1) * dtdy) >> 7;
115 y1 = 1024*4-1;
116 if (__UNLIKELY(y0 >= y1)) return;
117 }
118
119 extern void __rdpq_texture_rectangle(uint32_t w0, uint32_t w1, uint32_t w2, uint32_t w3);
120 __rdpq_texture_rectangle(
121 _carg(x1, 0xFFF, 12) | _carg(y1, 0xFFF, 0),
122 _carg(tile, 0x7, 24) | _carg(x0, 0xFFF, 12) | _carg(y0, 0xFFF, 0),
123 _carg(s0, 0xFFFF, 16) | _carg(t0, 0xFFFF, 0),
124 _carg(dsdx, 0xFFFF, 16) | _carg(dtdy, 0xFFFF, 0));
125}
126
127inline void __rdpq_fill_rectangle_fx(int32_t x0, int32_t y0, int32_t x1, int32_t y1)
128{
129 if (__builtin_constant_p(x0) && __builtin_constant_p(y0) && __builtin_constant_p(x1) && __builtin_constant_p(y1)) {
130 __rdpq_fill_rectangle_inline(x0, y0, x1, y1);
131 } else {
132 extern void __rdpq_fill_rectangle_offline(int32_t x0, int32_t y0, int32_t x1, int32_t y1);
133 __rdpq_fill_rectangle_offline(x0, y0, x1, y1);
134 }
135}
136
137inline void __rdpq_texture_rectangle_fx(rdpq_tile_t tile, int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t s, int32_t t)
138{
139 if (__builtin_constant_p(x0) && __builtin_constant_p(y0) && __builtin_constant_p(x1) && __builtin_constant_p(y1)) {
140 __rdpq_texture_rectangle_inline(tile, x0, y0, x1, y1, s, t);
141 } else {
142 extern void __rdpq_texture_rectangle_offline(rdpq_tile_t tile, int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t s0, int32_t t0);
143 __rdpq_texture_rectangle_offline(tile, x0, y0, x1, y1, s, t);
144 }
145}
146
147inline void __rdpq_texture_rectangle_scaled_fx(rdpq_tile_t tile, int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t s0, int32_t t0, int32_t s1, int32_t t1)
148{
149 if (__builtin_constant_p(x0) && __builtin_constant_p(y0) && __builtin_constant_p(x1) && __builtin_constant_p(y1)) {
150 __rdpq_texture_rectangle_scaled_inline(tile, x0, y0, x1, y1, s0, t0, s1, t1);
151 } else {
152 extern void __rdpq_texture_rectangle_scaled_offline(rdpq_tile_t tile, int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t s0, int32_t t0, int32_t s1, int32_t t1);
153 __rdpq_texture_rectangle_scaled_offline(tile, x0, y0, x1, y1, s0, t0, s1, t1);
154 }
155}
156
157inline void __rdpq_texture_rectangle_raw_fx(rdpq_tile_t tile, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t s0, uint16_t t0, int16_t dsdx, int16_t dtdy)
158{
159 extern void __rdpq_texture_rectangle(uint32_t w0, uint32_t w1, uint32_t w2, uint32_t w3);
160 __rdpq_texture_rectangle(
161 _carg(x1, 0xFFF, 12) | _carg(y1, 0xFFF, 0),
162 _carg(tile, 0x7, 24) | _carg(x0, 0xFFF, 12) | _carg(y0, 0xFFF, 0),
163 _carg(s0, 0xFFFF, 16) | _carg(t0, 0xFFFF, 0),
164 _carg(dsdx, 0xFFFF, 16) | _carg(dtdy, 0xFFFF, 0));
165}
166
167inline void __rdpq_texture_rectangle_flip_raw_fx(rdpq_tile_t tile, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, int16_t s, int16_t t, int16_t dsdy, int16_t dtdx)
168{
169 extern void __rdpq_write16_syncuse(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
170
171 // Note that this command is broken in copy mode, so it doesn't
172 // require any fixup. The RSP will trigger an assert if this
173 // is called in such a mode.
174 __rdpq_write16_syncuse(RDPQ_CMD_TEXTURE_RECTANGLE_FLIP,
175 _carg(x1, 0xFFF, 12) | _carg(y1, 0xFFF, 0),
176 _carg(tile, 0x7, 24) | _carg(x0, 0xFFF, 12) | _carg(y0, 0xFFF, 0),
177 _carg(s, 0xFFFF, 16) | _carg(t, 0xFFFF, 0),
178 _carg(dsdy, 0xFFFF, 16) | _carg(dtdx, 0xFFFF, 0),
179 AUTOSYNC_PIPE | AUTOSYNC_TILE(tile) | AUTOSYNC_TMEM(0));
180}
181#undef __UNLIKELY
183
249#define rdpq_fill_rectangle(x0, y0, x1, y1) ({ \
250 __rdpq_fill_rectangle_fx((x0)*4, (y0)*4, (x1)*4, (y1)*4); \
251})
252
305// NOTE: we use a macro here to support both integer and float inputs without ever forcing
306// a useless additional conversion.
307#define rdpq_texture_rectangle(tile, x0, y0, x1, y1, s, t) \
308 __rdpq_texture_rectangle_fx((tile), (x0)*4, (y0)*4, (x1)*4, (y1)*4, (s)*32, (t)*32)
309
331#define rdpq_texture_rectangle_scaled(tile, x0, y0, x1, y1, s0, t0, s1, t1) \
332 __rdpq_texture_rectangle_scaled_fx((tile), (x0)*4, (y0)*4, (x1)*4, (y1)*4, (s0)*32, (t0)*32, (s1)*32, (t1)*32)
333
334
375#define rdpq_texture_rectangle_raw(tile, x0, y0, x1, y1, s0, t0, dsdx, dtdy) \
376 __rdpq_texture_rectangle_raw_fx(tile, (x0)*4, (y0)*4, (x1)*4, (y1)*4, (s0)*32, (t0)*32, (dsdx)*1024, (dtdy)*1024)
377
378
404#define rdpq_texture_rectangle_flip_raw(tile, x0, y0, x1, y1, s, t, dsdy, dtdx) ({ \
405 __rdpq_texture_rectangle_flip_raw_fx((tile), (x0)*4, (y0)*4, (x1)*4, (y1)*4, (s)*32, (t)*32, (dsdy)*1024, (dtdx)*1024); \
406})
407
408
413#ifdef __cplusplus
414}
415#endif
416
417#endif
void __rdpq_write16_syncuse(uint32_t cmd_id, uint32_t arg0, uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t autosync)
Write a standard 16-byte RDP command, which uses some autosync resources
Definition: rdpq.c:943
RDP Command queue.
rdpq_tile_t
Tile descriptors.
Definition: rdpq.h:249