psx_gpu: consolidate C code, implement exnhancement asm
[pcsx_rearmed.git] / plugins / gpu_neon / psx_gpu / psx_gpu_4x.c
1 #ifndef NEON_BUILD\r
2 void setup_sprite_16bpp_4x(psx_gpu_struct *psx_gpu, s32 x, s32 y, s32 u,\r
3  s32 v, s32 width, s32 height, u32 color)\r
4 {\r
5   u32 left_offset = u & 0x7;\r
6   u32 width_rounded = width + left_offset + 7;\r
7 \r
8   u16 *fb_ptr = psx_gpu->vram_out_ptr + (y * 1024) + (s32)(x - left_offset * 2);\r
9   u32 right_width = width_rounded & 0x7;\r
10   u32 block_width = width_rounded / 8;\r
11   u32 fb_ptr_pitch = (2048 + 16) - (block_width * 16);\r
12 \r
13   u32 left_mask_bits = ~(0xFFFF << (left_offset * 2));\r
14   u32 right_mask_bits = 0xFFFC << (right_width * 2);\r
15 \r
16   u32 texture_offset_base = u + (v * 1024);\r
17   u32 texture_mask =\r
18    psx_gpu->texture_mask_width | (psx_gpu->texture_mask_height * 1024);\r
19 \r
20   u32 blocks_remaining;\r
21   u32 num_blocks = psx_gpu->num_blocks;\r
22   block_struct *block = psx_gpu->blocks + num_blocks;\r
23 \r
24   u16 *texture_page_ptr = psx_gpu->texture_page_ptr;\r
25   u16 *texture_block_ptr;\r
26 \r
27   texture_offset_base &= ~0x7;\r
28 \r
29   sprites_16bpp++;\r
30 \r
31   if(block_width == 1)\r
32   {\r
33     u32 mask_bits = left_mask_bits | right_mask_bits;\r
34     u32 mask_bits_a = mask_bits & 0xFF;\r
35     u32 mask_bits_b = mask_bits >> 8;\r
36     \r
37     vec_8x16u texels;\r
38     vec_8x16u texels_wide;\r
39 \r
40     while(height)\r
41     {\r
42       num_blocks += 4;\r
43       sprite_blocks += 4;\r
44 \r
45       if(num_blocks > MAX_BLOCKS)\r
46       {\r
47         flush_render_block_buffer(psx_gpu);\r
48         num_blocks = 4;\r
49         block = psx_gpu->blocks;\r
50       }\r
51       \r
52       texture_block_ptr =\r
53        texture_page_ptr + (texture_offset_base & texture_mask);\r
54 \r
55       load_128b(texels, texture_block_ptr);\r
56       \r
57       zip_4x32b(vector_cast(vec_4x32u, texels_wide), texels.low, texels.low);\r
58       block->texels = texels_wide;\r
59       block->draw_mask_bits = mask_bits_a;\r
60       block->fb_ptr = fb_ptr;          \r
61       block++;\r
62       \r
63       block->texels = texels_wide;\r
64       block->draw_mask_bits = mask_bits_a;\r
65       block->fb_ptr = fb_ptr + 1024;          \r
66       block++;\r
67       \r
68       zip_4x32b(vector_cast(vec_4x32u, texels_wide), texels.high, texels.high);\r
69       block->texels = texels_wide;\r
70       block->draw_mask_bits = mask_bits_b;\r
71       block->fb_ptr = fb_ptr + 8;\r
72       block++;\r
73       \r
74       block->texels = texels_wide;\r
75       block->draw_mask_bits = mask_bits_b;\r
76       block->fb_ptr = fb_ptr + 8 + 1024;          \r
77       block++;      \r
78 \r
79       texture_offset_base += 1024;\r
80       fb_ptr += 2048;\r
81 \r
82       height--;\r
83       psx_gpu->num_blocks = num_blocks;\r
84     }\r
85   }\r
86   else\r
87   {\r
88     u32 texture_offset;\r
89     \r
90     u32 left_mask_bits_a = left_mask_bits & 0xFF;\r
91     u32 left_mask_bits_b = left_mask_bits >> 8;\r
92     u32 right_mask_bits_a = right_mask_bits & 0xFF;\r
93     u32 right_mask_bits_b = right_mask_bits >> 8;\r
94     \r
95     vec_8x16u texels;\r
96     vec_8x16u texels_wide;    \r
97 \r
98     while(height)\r
99     {\r
100       blocks_remaining = block_width - 2;\r
101       num_blocks += block_width * 4;\r
102       sprite_blocks += block_width * 4;\r
103 \r
104       if(num_blocks > MAX_BLOCKS)\r
105       {\r
106         flush_render_block_buffer(psx_gpu);\r
107         num_blocks = block_width * 4;\r
108         block = psx_gpu->blocks;\r
109       }\r
110 \r
111       texture_offset = texture_offset_base;\r
112       texture_offset_base += 1024;\r
113 \r
114       texture_block_ptr = texture_page_ptr + (texture_offset & texture_mask);\r
115       \r
116       load_128b(texels, texture_block_ptr);\r
117 \r
118       zip_4x32b(vector_cast(vec_4x32u, texels_wide), texels.low, texels.low);\r
119       block->texels = texels_wide;\r
120       block->draw_mask_bits = left_mask_bits_a;\r
121       block->fb_ptr = fb_ptr;\r
122       block++;\r
123       \r
124       block->texels = texels_wide;\r
125       block->draw_mask_bits = left_mask_bits_a;\r
126       block->fb_ptr = fb_ptr + 1024;\r
127       block++;      \r
128 \r
129       zip_4x32b(vector_cast(vec_4x32u, texels_wide), texels.high, texels.high);\r
130       block->texels = texels_wide;\r
131       block->draw_mask_bits = left_mask_bits_b;\r
132       block->fb_ptr = fb_ptr + 8;\r
133       block++;  \r
134       \r
135       block->texels = texels_wide;\r
136       block->draw_mask_bits = left_mask_bits_b;\r
137       block->fb_ptr = fb_ptr + 8 + 1024;\r
138       block++;  \r
139       \r
140       texture_offset += 8;\r
141       fb_ptr += 16;\r
142 \r
143       while(blocks_remaining)\r
144       {\r
145         texture_block_ptr = texture_page_ptr + (texture_offset & texture_mask);\r
146         load_128b(texels, texture_block_ptr);\r
147 \r
148         zip_4x32b(vector_cast(vec_4x32u, texels_wide), texels.low, texels.low);\r
149         block->texels = texels_wide;\r
150         block->draw_mask_bits = 0;\r
151         block->fb_ptr = fb_ptr;\r
152         block++;\r
153         \r
154         block->texels = texels_wide;\r
155         block->draw_mask_bits = 0;\r
156         block->fb_ptr = fb_ptr + 1024;\r
157         block++;      \r
158 \r
159         zip_4x32b(vector_cast(vec_4x32u, texels_wide), texels.high, texels.high);\r
160         block->texels = texels_wide;\r
161         block->draw_mask_bits = 0;\r
162         block->fb_ptr = fb_ptr + 8;\r
163         block++;\r
164         \r
165         block->texels = texels_wide;\r
166         block->draw_mask_bits = 0;\r
167         block->fb_ptr = fb_ptr + 8 + 1024;\r
168         block++;\r
169         \r
170         texture_offset += 8;\r
171         fb_ptr += 16;\r
172 \r
173         blocks_remaining--;\r
174       }\r
175 \r
176       texture_block_ptr = texture_page_ptr + (texture_offset & texture_mask);\r
177       load_128b(texels, texture_block_ptr);\r
178       \r
179       zip_4x32b(vector_cast(vec_4x32u, texels_wide), texels.low, texels.low);\r
180       block->texels = texels_wide;\r
181       block->draw_mask_bits = right_mask_bits_a;\r
182       block->fb_ptr = fb_ptr;\r
183       block++;\r
184       \r
185       block->texels = texels_wide;\r
186       block->draw_mask_bits = right_mask_bits_a;\r
187       block->fb_ptr = fb_ptr + 1024;\r
188       block++;      \r
189 \r
190       zip_4x32b(vector_cast(vec_4x32u, texels_wide), texels.high, texels.high);\r
191       block->texels = texels_wide;\r
192       block->draw_mask_bits = right_mask_bits_b;\r
193       block->fb_ptr = fb_ptr + 8;\r
194       block++;\r
195 \r
196       block->texels = texels_wide;\r
197       block->draw_mask_bits = right_mask_bits_b;\r
198       block->fb_ptr = fb_ptr + 8 + 1024;      \r
199       block++;\r
200 \r
201       fb_ptr += fb_ptr_pitch;\r
202 \r
203       height--;\r
204       psx_gpu->num_blocks = num_blocks;\r
205     }\r
206   }\r
207 }\r
208 \r
209 #endif\r
210 \r
211 static void setup_sprite_untextured_4x(psx_gpu_struct *psx_gpu, s32 x, s32 y,\r
212  s32 u, s32 v, s32 width, s32 height, u32 color)\r
213 {\r
214   setup_sprite_untextured(psx_gpu, x, y, u, v, width * 2, height * 2, color);\r
215 }\r
216 \r
217 #define setup_sprite_blocks_switch_textured_4x(texture_mode)                   \\r
218   setup_sprite_##texture_mode##_4x                                             \\r
219 \r
220 #define setup_sprite_blocks_switch_untextured_4x(texture_mode)                 \\r
221   setup_sprite_untextured_4x                                                   \\r
222 \r
223 #define setup_sprite_blocks_switch_4x(texturing, texture_mode)                 \\r
224   setup_sprite_blocks_switch_##texturing##_4x(texture_mode)                    \\r
225 \r
226   \r
227 #define render_sprite_blocks_switch_block_modulation_4x(texture_mode,          \\r
228  blend_mode, mask_evaluate, shading, dithering, texturing, blending,           \\r
229  modulation)                                                                   \\r
230 {                                                                              \\r
231   setup_sprite_blocks_switch_4x(texturing, texture_mode),                      \\r
232   texture_sprite_blocks_switch_##texturing(texture_mode),                      \\r
233   shade_blocks_switch(unshaded, texturing, modulation, undithered, blending,   \\r
234    mask_evaluate),                                                             \\r
235   blend_blocks_switch(texturing, blending, blend_mode, mask_evaluate)          \\r
236 }                                                                              \\r
237 \r
238 #define render_sprite_blocks_switch_block_blending_4x(texture_mode,            \\r
239  blend_mode, mask_evaluate, shading, dithering, texturing, blending)           \\r
240   render_sprite_blocks_switch_block_modulation_4x(texture_mode, blend_mode,    \\r
241    mask_evaluate, shading, dithering, texturing, blending, modulated),         \\r
242   render_sprite_blocks_switch_block_modulation_4x(texture_mode, blend_mode,    \\r
243    mask_evaluate, shading, dithering, texturing, blending, unmodulated)        \\r
244 \r
245 #define render_sprite_blocks_switch_block_texturing_4x(texture_mode,           \\r
246  blend_mode, mask_evaluate, shading, dithering, texturing)                     \\r
247   render_sprite_blocks_switch_block_blending_4x(texture_mode, blend_mode,      \\r
248    mask_evaluate, shading, dithering, texturing, unblended),                   \\r
249   render_sprite_blocks_switch_block_blending_4x(texture_mode, blend_mode,      \\r
250    mask_evaluate, shading, dithering, texturing, blended)                      \\r
251 \r
252 #define render_sprite_blocks_switch_block_dithering_4x(texture_mode,           \\r
253  blend_mode, mask_evaluate, shading, dithering)                                \\r
254   render_sprite_blocks_switch_block_texturing_4x(texture_mode, blend_mode,     \\r
255    mask_evaluate, shading, dithering, untextured),                             \\r
256   render_sprite_blocks_switch_block_texturing_4x(texture_mode, blend_mode,     \\r
257    mask_evaluate, shading, dithering, textured)                                \\r
258 \r
259 #define render_sprite_blocks_switch_block_shading_4x(texture_mode, blend_mode, \\r
260  mask_evaluate, shading)                                                       \\r
261   render_sprite_blocks_switch_block_dithering_4x(texture_mode, blend_mode,     \\r
262    mask_evaluate, shading, undithered),                                        \\r
263   render_sprite_blocks_switch_block_dithering_4x(texture_mode, blend_mode,     \\r
264    mask_evaluate, shading, dithered)                                           \\r
265 \r
266 #define render_sprite_blocks_switch_block_mask_evaluate_4x(texture_mode,       \\r
267  blend_mode, mask_evaluate)                                                    \\r
268   render_sprite_blocks_switch_block_shading_4x(texture_mode, blend_mode,       \\r
269    mask_evaluate, unshaded),                                                   \\r
270   render_sprite_blocks_switch_block_shading_4x(texture_mode, blend_mode,       \\r
271    mask_evaluate, shaded)                                                      \\r
272 \r
273 #define render_sprite_blocks_switch_block_blend_mode_4x(texture_mode,          \\r
274  blend_mode)                                                                   \\r
275   render_sprite_blocks_switch_block_mask_evaluate_4x(texture_mode, blend_mode, \\r
276    off),                                                                       \\r
277   render_sprite_blocks_switch_block_mask_evaluate_4x(texture_mode, blend_mode, \\r
278    on)                                                                         \\r
279 \r
280 #define render_sprite_blocks_switch_block_texture_mode_4x(texture_mode)        \\r
281   render_sprite_blocks_switch_block_blend_mode_4x(texture_mode, average),      \\r
282   render_sprite_blocks_switch_block_blend_mode_4x(texture_mode, add),          \\r
283   render_sprite_blocks_switch_block_blend_mode_4x(texture_mode, subtract),     \\r
284   render_sprite_blocks_switch_block_blend_mode_4x(texture_mode, add_fourth)    \\r
285 \r
286 #define render_sprite_blocks_switch_block_4x()                                 \\r
287   render_sprite_blocks_switch_block_texture_mode_4x(4bpp),                     \\r
288   render_sprite_blocks_switch_block_texture_mode_4x(8bpp),                     \\r
289   render_sprite_blocks_switch_block_texture_mode_4x(16bpp),                    \\r
290   render_sprite_blocks_switch_block_texture_mode_4x(4bpp)                      \\r
291 \r
292 \r
293 render_block_handler_struct render_sprite_block_handlers_4x[] =\r
294 {\r
295   render_sprite_blocks_switch_block_4x()\r
296 };\r
297 \r
298 \r
299 void render_sprite_4x(psx_gpu_struct *psx_gpu, s32 x, s32 y, u32 u, u32 v,\r
300  s32 width, s32 height, u32 flags, u32 color)\r
301 {\r
302   s32 x_right = x + width - 1;\r
303   s32 y_bottom = y + height - 1;\r
304 \r
305 #ifdef PROFILE\r
306   sprites++;\r
307 #endif\r
308 \r
309   if(x < psx_gpu->viewport_start_x)\r
310   {\r
311     u32 clip = psx_gpu->viewport_start_x - x;\r
312     x += clip;\r
313     u += clip;\r
314     width -= clip;\r
315   }\r
316 \r
317   if(y < psx_gpu->viewport_start_y)\r
318   {\r
319     s32 clip = psx_gpu->viewport_start_y - y;\r
320     y += clip;\r
321     v += clip;\r
322     height -= clip;\r
323   }\r
324 \r
325   if(x_right > psx_gpu->viewport_end_x)\r
326     width -= x_right - psx_gpu->viewport_end_x;\r
327 \r
328   if(y_bottom > psx_gpu->viewport_end_y)\r
329     height -= y_bottom - psx_gpu->viewport_end_y;\r
330 \r
331   if((width <= 0) || (height <= 0))\r
332     return;\r
333 \r
334   x *= 2;\r
335   y *= 2;\r
336 \r
337 #ifdef PROFILE\r
338   span_pixels += width * height;\r
339   spans += height;\r
340 #endif\r
341 \r
342   u32 render_state = flags &\r
343    (RENDER_FLAGS_MODULATE_TEXELS | RENDER_FLAGS_BLEND |\r
344    RENDER_FLAGS_TEXTURE_MAP);\r
345   render_state |=\r
346    (psx_gpu->render_state_base & ~RENDER_STATE_DITHER);\r
347 \r
348   if((psx_gpu->render_state != render_state) ||\r
349    (psx_gpu->primitive_type != PRIMITIVE_TYPE_SPRITE))\r
350   {\r
351     psx_gpu->render_state = render_state;\r
352     flush_render_block_buffer(psx_gpu);\r
353 #ifdef PROFILE\r
354     state_changes++;\r
355 #endif\r
356   }\r
357 \r
358   psx_gpu->primitive_type = PRIMITIVE_TYPE_SPRITE;\r
359 \r
360   color &= 0xFFFFFF;\r
361 \r
362   if(psx_gpu->triangle_color != color)\r
363   {\r
364     flush_render_block_buffer(psx_gpu);\r
365     psx_gpu->triangle_color = color;\r
366   }\r
367 \r
368   if(color == 0x808080)\r
369     render_state |= RENDER_FLAGS_MODULATE_TEXELS;\r
370 \r
371   render_block_handler_struct *render_block_handler =\r
372    &(render_sprite_block_handlers_4x[render_state]);\r
373   psx_gpu->render_block_handler = render_block_handler;\r
374 \r
375   ((setup_sprite_function_type *)render_block_handler->setup_blocks)\r
376    (psx_gpu, x, y, u, v, width, height, color);\r
377 }\r
378 \r