dreamcast/font/font_bitmap.cpp
Zack Buhman a71ac1c4b1 suzanne_profile: remove tearing
Though I did spend much time thinking about this, my idea was not correct.

The "tearing" and "previous frame is being shown while it is being drawn" is
simply because that's exactly what the logic in holly/core.cpp did.

This is no longer the case--by the time the newly-created core_flip function is
called, the core render is complete, and we should switch the FB_R_SOF1 to the
current framebuffer, not the one that is going to be written on next frame.

This also modifies alt.lds so that (non-startup) code now runs in the P1 area,
with operand/instruction/copyback caches enabled. This caused a 10x speed
increase in my testing.
2024-02-02 13:11:32 +08:00

174 lines
6.1 KiB
C++

#include <cstdint>
#include "../holly/holly.hpp"
#include "../holly/core_bits.hpp"
#include "../holly/texture_memory_alloc.hpp"
#include "../holly/isp_tsp.hpp"
#include "../holly/ta_parameter.hpp"
#include "../holly/ta_global_parameter.hpp"
#include "../holly/ta_vertex_parameter.hpp"
#include "../memorymap.hpp"
#include "../twiddle.hpp"
#include "../sh7091/serial.hpp"
#include "font_bitmap.hpp"
namespace font_bitmap {
static inline void inflate_character(const uint32_t pitch,
const uint32_t width,
const uint32_t height,
const uint32_t texture_width,
const uint32_t texture_height,
const uint8_t * src,
const uint8_t c)
{
const uint32_t character_index = c - ' ';
const uint32_t offset = pitch * height * character_index;
uint8_t temp[texture_width * texture_height];
for (uint32_t y = 0; y < height; y++) {
for (uint32_t x = 0; x < width; x++) {
uint8_t row = src[offset + (y * pitch) + (x / 8)];
uint8_t px = (row >> (7 - (x % 8))) & 1;
//serial::character((px == 1) ? 'X' : '_');
uint16_t palette_index = px ? 2 : 1;
temp[y * texture_width + x] = palette_index;
}
for (uint32_t x = width; x < texture_width; x++) {
temp[y * texture_width + x] = 1;
}
//serial::character('\n');
}
for (uint32_t y = height; y < texture_height; y++) {
for (uint32_t x = 0; x < texture_width; x++) {
temp[y * texture_width + x] = 1;
}
}
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory64);
auto texture = reinterpret_cast<volatile uint32_t *>(mem->texture);
const uint32_t texture_offset = texture_width * texture_height * character_index / 2;
twiddle::texture2<4>(&texture[texture_offset / 4], // uint32_t *
temp,
texture_width,
texture_width * texture_height);
}
void inflate(const uint32_t pitch,
const uint32_t width,
const uint32_t height,
const uint32_t texture_width,
const uint32_t texture_height,
const uint8_t * src)
{
for (uint8_t ix = 0x20; ix < 0x7f; ix++) {
inflate_character(pitch,
width,
height,
texture_width,
texture_height,
src,
ix);
}
}
void palette_data()
{
holly.PAL_RAM_CTRL = pal_ram_ctrl::pixel_format::rgb565;
holly.PALETTE_RAM[1] = 0x0000;
holly.PALETTE_RAM[2] = 0xffff;
}
struct quad_vertex {
float x;
float y;
float z;
float u;
float v;
};
const struct quad_vertex quad_vertices[4] = {
// [ position ] [ uv coordinates ]
{ -0.5f, 0.5f, 0.f, 0.f, 1.f, },
{ -0.5f, -0.5f, 0.f, 0.f, 0.f, },
{ 0.5f, 0.5f, 0.f, 1.f, 1.f, },
{ 0.5f, -0.5f, 0.f, 1.f, 0.f, },
};
constexpr uint32_t quad_length = (sizeof (quad_vertices)) / (sizeof (struct quad_vertex));
void transform_string(ta_parameter_writer& parameter,
const uint32_t texture_width,
const uint32_t texture_height,
const uint32_t glyph_width,
const uint32_t glyph_height,
const int32_t position_x,
const int32_t position_y,
const char * s,
const uint32_t len
)
{
const uint32_t parameter_control_word = para_control::para_type::polygon_or_modifier_volume
| para_control::list_type::opaque
| obj_control::col_type::packed_color
| obj_control::texture;
const uint32_t isp_tsp_instruction_word = isp_tsp_instruction_word::depth_compare_mode::always
| isp_tsp_instruction_word::culling_mode::no_culling;
const uint32_t tsp_instruction_word = tsp_instruction_word::src_alpha_instr::one
| tsp_instruction_word::dst_alpha_instr::zero
| tsp_instruction_word::fog_control::no_fog
| tsp_instruction_word::texture_u_size::from_int(texture_width)
| tsp_instruction_word::texture_v_size::from_int(texture_height);
for (uint32_t string_ix = 0; string_ix < len; string_ix++) {
const uint32_t texture_address = (offsetof (struct texture_memory_alloc, texture));
const uint32_t glyph_address = texture_address + texture_width * texture_height * (s[string_ix] - ' ') / 2;
const uint32_t texture_control_word = texture_control_word::pixel_format::_4bpp_palette
| texture_control_word::scan_order::twiddled
| texture_control_word::texture_address(glyph_address / 8);
parameter.append<ta_global_parameter::polygon_type_0>() =
ta_global_parameter::polygon_type_0(parameter_control_word,
isp_tsp_instruction_word,
tsp_instruction_word,
texture_control_word,
0, // data_size_for_sort_dma
0 // next_address_for_sort_dma
);
for (uint32_t i = 0; i < quad_length; i++) {
bool end_of_strip = i == quad_length - 1;
float x = quad_vertices[i].x;
float y = quad_vertices[i].y;
float z = quad_vertices[i].z;
float u = quad_vertices[i].u;
float v = quad_vertices[i].v;
x *= static_cast<float>(glyph_width * 1);
y *= static_cast<float>(glyph_height * 1);
x += static_cast<float>(position_x + glyph_width * string_ix);
y += static_cast<float>(position_y);
z = 1.f / (z + 10.f);
u *= static_cast<float>(glyph_width) / static_cast<float>(texture_width);
v *= static_cast<float>(glyph_height) / static_cast<float>(texture_height);
parameter.append<ta_vertex_parameter::polygon_type_3>() =
ta_vertex_parameter::polygon_type_3(polygon_vertex_parameter_control_word(end_of_strip),
x, y, z,
u, v,
0, // base_color
0 // offset_color
);
}
}
}
}