aboutsummaryrefslogtreecommitdiff
path: root/plugins/gpu_neon/psx_gpu/psx_gpu_4x.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/gpu_neon/psx_gpu/psx_gpu_4x.c')
-rw-r--r--plugins/gpu_neon/psx_gpu/psx_gpu_4x.c384
1 files changed, 384 insertions, 0 deletions
diff --git a/plugins/gpu_neon/psx_gpu/psx_gpu_4x.c b/plugins/gpu_neon/psx_gpu/psx_gpu_4x.c
new file mode 100644
index 0000000..83c6680
--- /dev/null
+++ b/plugins/gpu_neon/psx_gpu/psx_gpu_4x.c
@@ -0,0 +1,384 @@
+#define select_enhancement_buf_ptr(psx_gpu, x) \
+ ((psx_gpu)->enhancement_buf_ptr + \
+ ((psx_gpu)->enhancement_buf_by_x16[(x) / 16] << 20))
+
+#ifndef NEON_BUILD
+void setup_sprite_16bpp_4x(psx_gpu_struct *psx_gpu, s32 x, s32 y, s32 u,
+ s32 v, s32 width, s32 height, u32 color)
+{
+ u32 left_offset = u & 0x7;
+ u32 width_rounded = width + left_offset + 7;
+
+ u16 *fb_ptr = psx_gpu->vram_out_ptr + (y * 1024) + (s32)(x - left_offset * 2);
+ u32 right_width = width_rounded & 0x7;
+ u32 block_width = width_rounded / 8;
+ u32 fb_ptr_pitch = (2048 + 16) - (block_width * 16);
+
+ u32 left_mask_bits = ~(0xFFFF << (left_offset * 2));
+ u32 right_mask_bits = 0xFFFC << (right_width * 2);
+
+ u32 texture_offset_base = u + (v * 1024);
+ u32 texture_mask =
+ psx_gpu->texture_mask_width | (psx_gpu->texture_mask_height * 1024);
+
+ u32 blocks_remaining;
+ u32 num_blocks = psx_gpu->num_blocks;
+ block_struct *block = psx_gpu->blocks + num_blocks;
+
+ u16 *texture_page_ptr = psx_gpu->texture_page_ptr;
+ u16 *texture_block_ptr;
+
+ texture_offset_base &= ~0x7;
+
+ sprites_16bpp++;
+
+ if(block_width == 1)
+ {
+ u32 mask_bits = left_mask_bits | right_mask_bits;
+ u32 mask_bits_a = mask_bits & 0xFF;
+ u32 mask_bits_b = mask_bits >> 8;
+
+ vec_8x16u texels;
+ vec_8x16u texels_wide;
+
+ while(height)
+ {
+ num_blocks += 4;
+ sprite_blocks += 4;
+
+ if(num_blocks > MAX_BLOCKS)
+ {
+ flush_render_block_buffer(psx_gpu);
+ num_blocks = 4;
+ block = psx_gpu->blocks;
+ }
+
+ texture_block_ptr =
+ texture_page_ptr + (texture_offset_base & texture_mask);
+
+ load_128b(texels, texture_block_ptr);
+
+ zip_4x32b(vector_cast(vec_4x32u, texels_wide), texels.low, texels.low);
+ block->texels = texels_wide;
+ block->draw_mask_bits = mask_bits_a;
+ block->fb_ptr = fb_ptr;
+ block++;
+
+ block->texels = texels_wide;
+ block->draw_mask_bits = mask_bits_a;
+ block->fb_ptr = fb_ptr + 1024;
+ block++;
+
+ zip_4x32b(vector_cast(vec_4x32u, texels_wide), texels.high, texels.high);
+ block->texels = texels_wide;
+ block->draw_mask_bits = mask_bits_b;
+ block->fb_ptr = fb_ptr + 8;
+ block++;
+
+ block->texels = texels_wide;
+ block->draw_mask_bits = mask_bits_b;
+ block->fb_ptr = fb_ptr + 8 + 1024;
+ block++;
+
+ texture_offset_base += 1024;
+ fb_ptr += 2048;
+
+ height--;
+ psx_gpu->num_blocks = num_blocks;
+ }
+ }
+ else
+ {
+ u32 texture_offset;
+
+ u32 left_mask_bits_a = left_mask_bits & 0xFF;
+ u32 left_mask_bits_b = left_mask_bits >> 8;
+ u32 right_mask_bits_a = right_mask_bits & 0xFF;
+ u32 right_mask_bits_b = right_mask_bits >> 8;
+
+ vec_8x16u texels;
+ vec_8x16u texels_wide;
+
+ while(height)
+ {
+ blocks_remaining = block_width - 2;
+ num_blocks += block_width * 4;
+ sprite_blocks += block_width * 4;
+
+ if(num_blocks > MAX_BLOCKS)
+ {
+ flush_render_block_buffer(psx_gpu);
+ num_blocks = block_width * 4;
+ block = psx_gpu->blocks;
+ }
+
+ texture_offset = texture_offset_base;
+ texture_offset_base += 1024;
+
+ texture_block_ptr = texture_page_ptr + (texture_offset & texture_mask);
+
+ load_128b(texels, texture_block_ptr);
+
+ zip_4x32b(vector_cast(vec_4x32u, texels_wide), texels.low, texels.low);
+ block->texels = texels_wide;
+ block->draw_mask_bits = left_mask_bits_a;
+ block->fb_ptr = fb_ptr;
+ block++;
+
+ block->texels = texels_wide;
+ block->draw_mask_bits = left_mask_bits_a;
+ block->fb_ptr = fb_ptr + 1024;
+ block++;
+
+ zip_4x32b(vector_cast(vec_4x32u, texels_wide), texels.high, texels.high);
+ block->texels = texels_wide;
+ block->draw_mask_bits = left_mask_bits_b;
+ block->fb_ptr = fb_ptr + 8;
+ block++;
+
+ block->texels = texels_wide;
+ block->draw_mask_bits = left_mask_bits_b;
+ block->fb_ptr = fb_ptr + 8 + 1024;
+ block++;
+
+ texture_offset += 8;
+ fb_ptr += 16;
+
+ while(blocks_remaining)
+ {
+ texture_block_ptr = texture_page_ptr + (texture_offset & texture_mask);
+ load_128b(texels, texture_block_ptr);
+
+ zip_4x32b(vector_cast(vec_4x32u, texels_wide), texels.low, texels.low);
+ block->texels = texels_wide;
+ block->draw_mask_bits = 0;
+ block->fb_ptr = fb_ptr;
+ block++;
+
+ block->texels = texels_wide;
+ block->draw_mask_bits = 0;
+ block->fb_ptr = fb_ptr + 1024;
+ block++;
+
+ zip_4x32b(vector_cast(vec_4x32u, texels_wide), texels.high, texels.high);
+ block->texels = texels_wide;
+ block->draw_mask_bits = 0;
+ block->fb_ptr = fb_ptr + 8;
+ block++;
+
+ block->texels = texels_wide;
+ block->draw_mask_bits = 0;
+ block->fb_ptr = fb_ptr + 8 + 1024;
+ block++;
+
+ texture_offset += 8;
+ fb_ptr += 16;
+
+ blocks_remaining--;
+ }
+
+ texture_block_ptr = texture_page_ptr + (texture_offset & texture_mask);
+ load_128b(texels, texture_block_ptr);
+
+ zip_4x32b(vector_cast(vec_4x32u, texels_wide), texels.low, texels.low);
+ block->texels = texels_wide;
+ block->draw_mask_bits = right_mask_bits_a;
+ block->fb_ptr = fb_ptr;
+ block++;
+
+ block->texels = texels_wide;
+ block->draw_mask_bits = right_mask_bits_a;
+ block->fb_ptr = fb_ptr + 1024;
+ block++;
+
+ zip_4x32b(vector_cast(vec_4x32u, texels_wide), texels.high, texels.high);
+ block->texels = texels_wide;
+ block->draw_mask_bits = right_mask_bits_b;
+ block->fb_ptr = fb_ptr + 8;
+ block++;
+
+ block->texels = texels_wide;
+ block->draw_mask_bits = right_mask_bits_b;
+ block->fb_ptr = fb_ptr + 8 + 1024;
+ block++;
+
+ fb_ptr += fb_ptr_pitch;
+
+ height--;
+ psx_gpu->num_blocks = num_blocks;
+ }
+ }
+}
+
+#endif
+
+static void setup_sprite_untextured_4x(psx_gpu_struct *psx_gpu, s32 x, s32 y,
+ s32 u, s32 v, s32 width, s32 height, u32 color)
+{
+ setup_sprite_untextured(psx_gpu, x, y, u, v, width * 2, height * 2, color);
+}
+
+#define setup_sprite_blocks_switch_textured_4x(texture_mode) \
+ setup_sprite_##texture_mode##_4x \
+
+#define setup_sprite_blocks_switch_untextured_4x(texture_mode) \
+ setup_sprite_untextured_4x \
+
+#define setup_sprite_blocks_switch_4x(texturing, texture_mode) \
+ setup_sprite_blocks_switch_##texturing##_4x(texture_mode) \
+
+
+#define render_sprite_blocks_switch_block_modulation_4x(texture_mode, \
+ blend_mode, mask_evaluate, shading, dithering, texturing, blending, \
+ modulation) \
+{ \
+ setup_sprite_blocks_switch_4x(texturing, texture_mode), \
+ texture_sprite_blocks_switch_##texturing(texture_mode), \
+ shade_blocks_switch(unshaded, texturing, modulation, undithered, blending, \
+ mask_evaluate), \
+ blend_blocks_switch(texturing, blending, blend_mode, mask_evaluate) \
+} \
+
+#define render_sprite_blocks_switch_block_blending_4x(texture_mode, \
+ blend_mode, mask_evaluate, shading, dithering, texturing, blending) \
+ render_sprite_blocks_switch_block_modulation_4x(texture_mode, blend_mode, \
+ mask_evaluate, shading, dithering, texturing, blending, modulated), \
+ render_sprite_blocks_switch_block_modulation_4x(texture_mode, blend_mode, \
+ mask_evaluate, shading, dithering, texturing, blending, unmodulated) \
+
+#define render_sprite_blocks_switch_block_texturing_4x(texture_mode, \
+ blend_mode, mask_evaluate, shading, dithering, texturing) \
+ render_sprite_blocks_switch_block_blending_4x(texture_mode, blend_mode, \
+ mask_evaluate, shading, dithering, texturing, unblended), \
+ render_sprite_blocks_switch_block_blending_4x(texture_mode, blend_mode, \
+ mask_evaluate, shading, dithering, texturing, blended) \
+
+#define render_sprite_blocks_switch_block_dithering_4x(texture_mode, \
+ blend_mode, mask_evaluate, shading, dithering) \
+ render_sprite_blocks_switch_block_texturing_4x(texture_mode, blend_mode, \
+ mask_evaluate, shading, dithering, untextured), \
+ render_sprite_blocks_switch_block_texturing_4x(texture_mode, blend_mode, \
+ mask_evaluate, shading, dithering, textured) \
+
+#define render_sprite_blocks_switch_block_shading_4x(texture_mode, blend_mode, \
+ mask_evaluate, shading) \
+ render_sprite_blocks_switch_block_dithering_4x(texture_mode, blend_mode, \
+ mask_evaluate, shading, undithered), \
+ render_sprite_blocks_switch_block_dithering_4x(texture_mode, blend_mode, \
+ mask_evaluate, shading, dithered) \
+
+#define render_sprite_blocks_switch_block_mask_evaluate_4x(texture_mode, \
+ blend_mode, mask_evaluate) \
+ render_sprite_blocks_switch_block_shading_4x(texture_mode, blend_mode, \
+ mask_evaluate, unshaded), \
+ render_sprite_blocks_switch_block_shading_4x(texture_mode, blend_mode, \
+ mask_evaluate, shaded) \
+
+#define render_sprite_blocks_switch_block_blend_mode_4x(texture_mode, \
+ blend_mode) \
+ render_sprite_blocks_switch_block_mask_evaluate_4x(texture_mode, blend_mode, \
+ off), \
+ render_sprite_blocks_switch_block_mask_evaluate_4x(texture_mode, blend_mode, \
+ on) \
+
+#define render_sprite_blocks_switch_block_texture_mode_4x(texture_mode) \
+ render_sprite_blocks_switch_block_blend_mode_4x(texture_mode, average), \
+ render_sprite_blocks_switch_block_blend_mode_4x(texture_mode, add), \
+ render_sprite_blocks_switch_block_blend_mode_4x(texture_mode, subtract), \
+ render_sprite_blocks_switch_block_blend_mode_4x(texture_mode, add_fourth) \
+
+#define render_sprite_blocks_switch_block_4x() \
+ render_sprite_blocks_switch_block_texture_mode_4x(4bpp), \
+ render_sprite_blocks_switch_block_texture_mode_4x(8bpp), \
+ render_sprite_blocks_switch_block_texture_mode_4x(16bpp), \
+ render_sprite_blocks_switch_block_texture_mode_4x(4bpp) \
+
+
+render_block_handler_struct render_sprite_block_handlers_4x[] =
+{
+ render_sprite_blocks_switch_block_4x()
+};
+
+
+void render_sprite_4x(psx_gpu_struct *psx_gpu, s32 x, s32 y, u32 u, u32 v,
+ s32 width, s32 height, u32 flags, u32 color)
+{
+ s32 x_right = x + width - 1;
+ s32 y_bottom = y + height - 1;
+
+#ifdef PROFILE
+ sprites++;
+#endif
+
+ if(x < psx_gpu->viewport_start_x)
+ {
+ u32 clip = psx_gpu->viewport_start_x - x;
+ x += clip;
+ u += clip;
+ width -= clip;
+ }
+
+ if(y < psx_gpu->viewport_start_y)
+ {
+ s32 clip = psx_gpu->viewport_start_y - y;
+ y += clip;
+ v += clip;
+ height -= clip;
+ }
+
+ if(x_right > psx_gpu->viewport_end_x)
+ width -= x_right - psx_gpu->viewport_end_x;
+
+ if(y_bottom > psx_gpu->viewport_end_y)
+ height -= y_bottom - psx_gpu->viewport_end_y;
+
+ if((width <= 0) || (height <= 0))
+ return;
+
+ psx_gpu->vram_out_ptr = select_enhancement_buf_ptr(psx_gpu, x);
+
+ x *= 2;
+ y *= 2;
+
+#ifdef PROFILE
+ span_pixels += width * height;
+ spans += height;
+#endif
+
+ u32 render_state = flags &
+ (RENDER_FLAGS_MODULATE_TEXELS | RENDER_FLAGS_BLEND |
+ RENDER_FLAGS_TEXTURE_MAP);
+ render_state |=
+ (psx_gpu->render_state_base & ~RENDER_STATE_DITHER);
+
+ if((psx_gpu->render_state != render_state) ||
+ (psx_gpu->primitive_type != PRIMITIVE_TYPE_SPRITE))
+ {
+ psx_gpu->render_state = render_state;
+ flush_render_block_buffer(psx_gpu);
+#ifdef PROFILE
+ state_changes++;
+#endif
+ }
+
+ psx_gpu->primitive_type = PRIMITIVE_TYPE_SPRITE;
+
+ color &= 0xFFFFFF;
+
+ if(psx_gpu->triangle_color != color)
+ {
+ flush_render_block_buffer(psx_gpu);
+ psx_gpu->triangle_color = color;
+ }
+
+ if(color == 0x808080)
+ render_state |= RENDER_FLAGS_MODULATE_TEXELS;
+
+ render_block_handler_struct *render_block_handler =
+ &(render_sprite_block_handlers_4x[render_state]);
+ psx_gpu->render_block_handler = render_block_handler;
+
+ ((setup_sprite_function_type *)render_block_handler->setup_blocks)
+ (psx_gpu, x, y, u, v, width, height, color);
+}
+