tile accelerator / renderer tlc

standardized some parameter names, added comments to provide an overview of the ta functionality
This commit is contained in:
Anthony Pesch 2017-09-05 17:21:53 -04:00
parent 6040ef924d
commit 1067df8099
12 changed files with 392 additions and 306 deletions

View File

@ -93,7 +93,7 @@ struct emu {
cond_t frame_cond;
/* latest context from the dreamcast, ready to be rendered */
struct tile_context *pending_ctx;
struct ta_context *pending_ctx;
struct tr_context pending_rc;
unsigned pending_id;
@ -275,10 +275,10 @@ static void emu_register_texture_source(struct emu *emu, union tsp tsp,
}
static void emu_register_texture_sources(struct emu *emu,
struct tile_context *ctx) {
struct ta_context *ctx) {
const uint8_t *data = ctx->params;
const uint8_t *end = ctx->params + ctx->size;
int vertex_type = 0;
int vert_type = 0;
while (data < end) {
union pcw pcw = *(union pcw *)data;
@ -288,7 +288,7 @@ static void emu_register_texture_sources(struct emu *emu,
case TA_PARAM_SPRITE: {
const union poly_param *param = (const union poly_param *)data;
vertex_type = ta_get_vert_type(param->type0.pcw);
vert_type = ta_vert_type(param->type0.pcw);
if (param->type0.pcw.texture) {
emu_register_texture_source(emu, param->type0.tsp, param->type0.tcw);
@ -299,7 +299,7 @@ static void emu_register_texture_sources(struct emu *emu,
break;
}
data += ta_get_param_size(pcw, vertex_type);
data += ta_param_size(pcw, vert_type);
}
}
@ -366,7 +366,7 @@ static void emu_guest_finish_render(void *userdata) {
}
}
static void emu_guest_start_render(void *userdata, struct tile_context *ctx) {
static void emu_guest_start_render(void *userdata, struct ta_context *ctx) {
struct emu *emu = userdata;
/* incement internal frame number. this frame number is assigned to the each

View File

@ -14,7 +14,7 @@ void trace_writer_close(struct trace_writer *writer) {
}
void trace_writer_render_context(struct trace_writer *writer,
struct tile_context *ctx) {
struct ta_context *ctx) {
struct trace_cmd cmd = {0};
cmd.type = TRACE_CMD_CONTEXT;
cmd.context.autosort = ctx->autosort;
@ -161,7 +161,7 @@ void trace_destroy(struct trace *trace) {
free(trace);
}
void trace_copy_context(const struct trace_cmd *cmd, struct tile_context *ctx) {
void trace_copy_context(const struct trace_cmd *cmd, struct ta_context *ctx) {
CHECK_EQ(cmd->type, TRACE_CMD_CONTEXT);
ctx->autosort = cmd->context.autosort;

View File

@ -31,7 +31,7 @@ struct trace_cmd {
const uint8_t *texture;
} texture;
/* slimmed down version of the tile_context structure, will need to be in
/* slimmed down version of the ta_context structure, will need to be in
sync */
struct {
uint32_t frame;
@ -64,7 +64,7 @@ struct trace_writer {
void get_next_trace_filename(char *filename, size_t size);
struct trace *trace_parse(const char *filename);
void trace_copy_context(const struct trace_cmd *cmd, struct tile_context *ctx);
void trace_copy_context(const struct trace_cmd *cmd, struct ta_context *ctx);
void trace_destroy(struct trace *trace);
struct trace_writer *trace_writer_open(const char *filename);
@ -73,7 +73,7 @@ void trace_writer_insert_texture(struct trace_writer *writer, union tsp tsp,
const uint8_t *palette, int palette_size,
const uint8_t *texture, int texture_size);
void trace_writer_render_context(struct trace_writer *writer,
struct tile_context *ctx);
struct ta_context *ctx);
void trace_writer_close(struct trace_writer *writer);
#endif

View File

@ -32,7 +32,7 @@ void dc_finish_render(struct dreamcast *dc) {
dc->finish_render(dc->userdata);
}
void dc_start_render(struct dreamcast *dc, struct tile_context *ctx) {
void dc_start_render(struct dreamcast *dc, struct ta_context *ctx) {
if (!dc->start_render) {
return;
}

View File

@ -23,7 +23,7 @@ struct pvr;
struct scheduler;
struct sh4;
struct ta;
struct tile_context;
struct ta_context;
/*
* register callbacks
@ -123,7 +123,7 @@ struct device {
* machine
*/
typedef void (*push_audio_cb)(void *, const int16_t *, int);
typedef void (*start_render_cb)(void *, struct tile_context *);
typedef void (*start_render_cb)(void *, struct ta_context *);
typedef void (*finish_render_cb)(void *);
typedef void (*vertical_blank_cb)(void *);
@ -190,7 +190,7 @@ void dc_input(struct dreamcast *dc, int port, int button, int16_t value);
/* client functionality */
void dc_push_audio(struct dreamcast *dc, const int16_t *data, int frames);
void dc_start_render(struct dreamcast *dc, struct tile_context *ctx);
void dc_start_render(struct dreamcast *dc, struct ta_context *ctx);
void dc_finish_render(struct dreamcast *dc);
void dc_vertical_blank(struct dreamcast *dc);

View File

@ -1,3 +1,23 @@
/*
* the HOLLY contained two graphics-related units:
*
* 1.) the tile accelerator. the ta acted as a frontend which received data from
* programs and converted / sanitized this data into display lists which
* were written back out to texture memory
* 2.) the core. the core acted as the backend, which took the display lists
* generated by the ta, rendered them, and wrote the results out to the
* framebuffer
*
* in our world, the display list generation used by the ta and core hardware
* is not emulated. instead, the parameters submitted to the ta are recorded
* to our ta_context structures, which are later converted to an appropriate
* format for the host's render backend in tr.c
*
* this file is responsible for processing the data fed to the ta into our
* internal ta_context format, and passing these contexts to the host for
* rendering when initiated
*/
#include "guest/pvr/ta.h"
#include "core/exception_handler.h"
#include "core/filesystem.h"
@ -12,11 +32,6 @@
DEFINE_AGGREGATE_COUNTER(ta_data);
DEFINE_AGGREGATE_COUNTER(ta_renders);
#define TA_YUV420_MACROBLOCK_SIZE 384
#define TA_YUV422_MACROBLOCK_SIZE 512
#define TA_MAX_MACROBLOCK_SIZE \
MAX(TA_YUV420_MACROBLOCK_SIZE, TA_YUV422_MACROBLOCK_SIZE)
struct ta {
struct device;
uint8_t *video_ram;
@ -29,26 +44,160 @@ struct ta {
int yuv_macroblock_count;
/* tile context pool */
struct tile_context contexts[8];
struct ta_context contexts[8];
struct list free_contexts;
struct list live_contexts;
struct tile_context *curr_context;
struct ta_context *curr_context;
};
int g_param_sizes[0x100 * TA_NUM_PARAMS * TA_NUM_VERTS];
int g_poly_types[0x100 * TA_NUM_PARAMS * TA_NUM_LISTS];
int g_vertex_types[0x100 * TA_NUM_PARAMS * TA_NUM_LISTS];
/*
* texture info helpers
*/
int ta_texture_stride(union tsp tsp, union tcw tcw, int stride) {
int twiddled = ta_texture_twiddled(tcw);
static holly_interrupt_t list_interrupts[] = {
HOLLY_INT_TAEOINT, /* TA_LIST_OPAQUE */
HOLLY_INT_TAEOMINT, /* TA_LIST_OPAQUE_MODVOL */
HOLLY_INT_TAETINT, /* TA_LIST_TRANSLUCENT */
HOLLY_INT_TAETMINT, /* TA_LIST_TRANSLUCENT_MODVOL */
HOLLY_INT_TAEPTIN /* TA_LIST_PUNCH_THROUGH */
};
if (!tcw.stride_select || twiddled) {
return ta_texture_width(tsp, tcw);
}
/* See "57.1.1.2 Parameter Combinations" for information on the poly types. */
static int ta_get_poly_type_raw(union pcw pcw) {
return stride;
}
int ta_texture_height(union tsp tsp, union tcw tcw) {
int mipmaps = ta_texture_mipmaps(tcw);
int height = 8 << tsp.texture_v_size;
if (mipmaps) {
height = ta_texture_width(tsp, tcw);
}
return height;
}
int ta_texture_width(union tsp tsp, union tcw tcw) {
return 8 << tsp.texture_u_size;
}
int ta_texture_mipmaps(union tcw tcw) {
return ta_texture_twiddled(tcw) && tcw.mip_mapped;
}
int ta_texture_twiddled(union tcw tcw) {
return !tcw.scan_order ||
/* paletted textures are always twiddled */
tcw.pixel_fmt == PVR_PXL_8BPP || tcw.pixel_fmt == PVR_PXL_4BPP;
}
int ta_texture_compressed(union tcw tcw) {
return tcw.vq_compressed;
}
int ta_texture_format(union tcw tcw) {
int compressed = ta_texture_compressed(tcw);
int twiddled = ta_texture_twiddled(tcw);
int mipmaps = ta_texture_mipmaps(tcw);
int texture_fmt = PVR_TEX_INVALID;
if (compressed) {
if (mipmaps) {
texture_fmt = PVR_TEX_VQ_MIPMAPS;
} else {
texture_fmt = PVR_TEX_VQ;
}
} else if (tcw.pixel_fmt == PVR_PXL_4BPP) {
if (mipmaps) {
texture_fmt = PVR_TEX_PALETTE_4BPP_MIPMAPS;
} else {
texture_fmt = PVR_TEX_PALETTE_4BPP;
}
} else if (tcw.pixel_fmt == PVR_PXL_8BPP) {
if (mipmaps) {
texture_fmt = PVR_TEX_PALETTE_8BPP_MIPMAPS;
} else {
texture_fmt = PVR_TEX_PALETTE_8BPP;
}
} else if (twiddled) {
if (mipmaps) {
texture_fmt = PVR_TEX_TWIDDLED_MIPMAPS;
} else {
texture_fmt = PVR_TEX_TWIDDLED;
}
} else {
texture_fmt = PVR_TEX_BITMAP;
}
return texture_fmt;
}
uint32_t ta_palette_addr(union tcw tcw, int *size) {
uint32_t palette_addr = 0;
int palette_size = 0;
if (tcw.pixel_fmt == PVR_PXL_4BPP || tcw.pixel_fmt == PVR_PXL_8BPP) {
/* palette ram is 4096 bytes, with each palette entry being 4 bytes each,
resulting in 1 << 10 indexes */
if (tcw.pixel_fmt == PVR_PXL_4BPP) {
/* in 4bpp mode, the palette selector represents the upper 6 bits of the
palette index, with the remaining 4 bits being filled in by the
texture */
palette_addr = tcw.p.palette_selector << 6;
palette_size = 1 << 6;
} else if (tcw.pixel_fmt == PVR_PXL_8BPP) {
/* in 8bpp mode, the palette selector represents the upper 2 bits of the
palette index, with the remaining 8 bits being filled in by the
texture */
palette_addr = (tcw.p.palette_selector >> 4) << 10;
palette_size = 1 << 10;
}
}
if (size) {
*size = palette_size;
}
return palette_addr;
}
uint32_t ta_texture_addr(union tsp tsp, union tcw tcw, int *size) {
uint32_t texture_addr = tcw.texture_addr << 3;
int texture_size = 0;
/* compressed textures have the additional fixed-size codebook */
if (ta_texture_compressed(tcw)) {
texture_size += PVR_CODEBOOK_SIZE;
}
/* calculate the size of each mipmap level */
int width = ta_texture_width(tsp, tcw);
int height = ta_texture_height(tsp, tcw);
int bpp = 16;
if (tcw.pixel_fmt == PVR_PXL_8BPP) {
bpp = 8;
} else if (tcw.pixel_fmt == PVR_PXL_4BPP) {
bpp = 4;
}
int mipmaps = ta_texture_mipmaps(tcw);
int levels = mipmaps ? ctz32(width) + 1 : 1;
while (levels--) {
int mip_width = width >> levels;
int mip_height = height >> levels;
texture_size += (mip_width * mip_height * bpp) >> 3;
}
if (size) {
*size = texture_size;
}
return texture_addr;
}
/*
* parameter stream processing helpers
*/
int ta_param_sizes[0x100 * TA_NUM_PARAMS * TA_NUM_VERTS];
int ta_poly_types[0x100 * TA_NUM_PARAMS * TA_NUM_LISTS];
int ta_vert_types[0x100 * TA_NUM_PARAMS * TA_NUM_LISTS];
static int ta_poly_type_raw(union pcw pcw) {
if (pcw.list_type == TA_LIST_OPAQUE_MODVOL ||
pcw.list_type == TA_LIST_TRANSLUCENT_MODVOL) {
return 6;
@ -86,8 +235,7 @@ static int ta_get_poly_type_raw(union pcw pcw) {
return 0;
}
/* See "57.1.1.2 Parameter Combinations" for information on the vertex types. */
static int ta_get_vert_type_raw(union pcw pcw) {
static int ta_vert_type_raw(union pcw pcw) {
if (pcw.list_type == TA_LIST_OPAQUE_MODVOL ||
pcw.list_type == TA_LIST_TRANSLUCENT_MODVOL) {
return 17;
@ -140,10 +288,7 @@ static int ta_get_vert_type_raw(union pcw pcw) {
return 0;
}
/* Parameter size can be determined by only the union pcw for every parameter
other than vertex parameters. For vertex parameters, the vertex type derived
from the last poly or modifier volume parameter is needed. */
static int ta_get_param_size_raw(union pcw pcw, int vertex_type) {
static int ta_param_size_raw(union pcw pcw, int vert_type) {
switch (pcw.para_type) {
case TA_PARAM_END_OF_LIST:
return 32;
@ -152,15 +297,15 @@ static int ta_get_param_size_raw(union pcw pcw, int vertex_type) {
case TA_PARAM_OBJ_LIST_SET:
return 32;
case TA_PARAM_POLY_OR_VOL: {
int type = ta_get_poly_type_raw(pcw);
int type = ta_poly_type_raw(pcw);
return type == 0 || type == 1 || type == 3 ? 32 : 64;
}
case TA_PARAM_SPRITE:
return 32;
case TA_PARAM_VERTEX: {
return vertex_type == 0 || vertex_type == 1 || vertex_type == 2 ||
vertex_type == 3 || vertex_type == 4 || vertex_type == 7 ||
vertex_type == 8 || vertex_type == 9 || vertex_type == 10
return vert_type == 0 || vert_type == 1 || vert_type == 2 ||
vert_type == 3 || vert_type == 4 || vert_type == 7 ||
vert_type == 8 || vert_type == 9 || vert_type == 10
? 32
: 64;
}
@ -173,8 +318,38 @@ static void ta_soft_reset(struct ta *ta) {
/* FIXME what are we supposed to do here? */
}
static struct tile_context *ta_get_context(struct ta *ta, uint32_t addr) {
list_for_each_entry(ctx, &ta->live_contexts, struct tile_context, it) {
/*
* ta parameter handling
*
* ta contexts are an encapsulation of all the state necessary to render a given
* frame submitted to the ta. this includes the raw poly and vertex parameters,
* as well as the relevant pvr register state at the time of rendering
*
* to understand this code, it's important to know how programs submitted data:
*
* 1.) initialize the TA_ISP_BASE / TA_ISP_LIMIT to an address range in memory
* where the poly and vertex parameters were to be stored
* 2.) initialize the TA_OL_BASE / TA_OL_LIMIT to an address in memory where the
* object lists generated by core would be stored
* 3.) write to TA_LIST_INIT to initialize the ta's internal registers
* 4.) start dma'ing poly / vertex parameters to 0x10000000
* 5.) wait for interrupts confirming that all of the data for a particular list
* has been transferred to texture memory
*
* due to the TA_ISP_BASE register, it was possible to have multiple frames of
* data in memory at a time, which is why a tree is maintained mapping a guest
* address to its respective ta_context
*/
static holly_interrupt_t list_interrupts[] = {
HOLLY_INT_TAEOINT, /* TA_LIST_OPAQUE */
HOLLY_INT_TAEOMINT, /* TA_LIST_OPAQUE_MODVOL */
HOLLY_INT_TAETINT, /* TA_LIST_TRANSLUCENT */
HOLLY_INT_TAETMINT, /* TA_LIST_TRANSLUCENT_MODVOL */
HOLLY_INT_TAEPTIN /* TA_LIST_PUNCH_THROUGH */
};
static struct ta_context *ta_get_context(struct ta *ta, uint32_t addr) {
list_for_each_entry(ctx, &ta->live_contexts, struct ta_context, it) {
if (ctx->addr == addr) {
return ctx;
}
@ -182,15 +357,15 @@ static struct tile_context *ta_get_context(struct ta *ta, uint32_t addr) {
return NULL;
}
static struct tile_context *ta_demand_context(struct ta *ta, uint32_t addr) {
struct tile_context *ctx = ta_get_context(ta, addr);
static struct ta_context *ta_demand_context(struct ta *ta, uint32_t addr) {
struct ta_context *ctx = ta_get_context(ta, addr);
if (ctx) {
return ctx;
}
/* remove from the object pool */
ctx = list_first_entry(&ta->free_contexts, struct tile_context, it);
ctx = list_first_entry(&ta->free_contexts, struct ta_context, it);
CHECK_NOTNULL(ctx);
list_remove(&ta->free_contexts, &ctx->it);
@ -199,7 +374,7 @@ static struct tile_context *ta_demand_context(struct ta *ta, uint32_t addr) {
ctx->cursor = 0;
ctx->size = 0;
ctx->list_type = 0;
ctx->vertex_type = 0;
ctx->vert_type = 0;
/* add to live list */
list_add(&ta->live_contexts, &ctx->it);
@ -207,29 +382,29 @@ static struct tile_context *ta_demand_context(struct ta *ta, uint32_t addr) {
return ctx;
}
static void ta_unlink_context(struct ta *ta, struct tile_context *ctx) {
static void ta_unlink_context(struct ta *ta, struct ta_context *ctx) {
/* remove from live list, but don't add back to object pool */
list_remove(&ta->live_contexts, &ctx->it);
}
static void ta_free_context(struct ta *ta, struct tile_context *ctx) {
static void ta_free_context(struct ta *ta, struct ta_context *ctx) {
/* add back to object pool */
list_add(&ta->free_contexts, &ctx->it);
}
static void ta_cont_context(struct ta *ta, struct tile_context *ctx) {
static void ta_cont_context(struct ta *ta, struct ta_context *ctx) {
ctx->list_type = TA_NUM_LISTS;
ctx->vertex_type = TA_NUM_VERTS;
ctx->vert_type = TA_NUM_VERTS;
}
static void ta_init_context(struct ta *ta, struct tile_context *ctx) {
static void ta_init_context(struct ta *ta, struct ta_context *ctx) {
ctx->cursor = 0;
ctx->size = 0;
ctx->list_type = TA_NUM_LISTS;
ctx->vertex_type = TA_NUM_VERTS;
ctx->vert_type = TA_NUM_VERTS;
}
static void ta_write_context(struct ta *ta, struct tile_context *ctx, void *ptr,
static void ta_write_context(struct ta *ta, struct ta_context *ctx, void *ptr,
int size) {
CHECK_LT(ctx->size + size, (int)sizeof(ctx->params));
memcpy(&ctx->params[ctx->size], ptr, size);
@ -245,7 +420,7 @@ static void ta_write_context(struct ta *ta, struct tile_context *ctx, void *ptr,
void *param = &ctx->params[ctx->cursor];
union pcw pcw = *(union pcw *)param;
int size = ta_get_param_size(pcw, ctx->vertex_type);
int size = ta_param_size(pcw, ctx->vert_type);
int recv = ctx->size - ctx->cursor;
if (recv < size) {
@ -266,7 +441,7 @@ static void ta_write_context(struct ta *ta, struct tile_context *ctx, void *ptr,
holly_raise_interrupt(ta->holly, list_interrupts[ctx->list_type]);
}
ctx->list_type = TA_NUM_LISTS;
ctx->vertex_type = TA_NUM_VERTS;
ctx->vert_type = TA_NUM_VERTS;
break;
case TA_PARAM_USER_TILE_CLIP:
@ -279,7 +454,7 @@ static void ta_write_context(struct ta *ta, struct tile_context *ctx, void *ptr,
/* global params */
case TA_PARAM_POLY_OR_VOL:
case TA_PARAM_SPRITE:
ctx->vertex_type = ta_get_vert_type(pcw);
ctx->vert_type = ta_vert_type(pcw);
break;
/* vertex params */
@ -295,40 +470,19 @@ static void ta_write_context(struct ta *ta, struct tile_context *ctx, void *ptr,
}
}
void ta_texture_info(struct ta *ta, union tsp tsp, union tcw tcw,
const uint8_t **texture, int *texture_size,
const uint8_t **palette, int *palette_size) {
uint32_t texture_addr = ta_texture_addr(tcw);
*texture = &ta->video_ram[texture_addr];
*texture_size = ta_texture_size(tsp, tcw);
if (tcw.pixel_fmt == TA_PXL_4BPP || tcw.pixel_fmt == TA_PXL_8BPP) {
uint32_t palette_addr = 0;
/* palette ram is 4096 bytes, with each palette entry being 4 bytes each,
resulting in 1 << 10 indexes */
if (tcw.pixel_fmt == TA_PXL_4BPP) {
/* in 4bpp mode, the palette selector represents the upper 6 bits of the
palette index, with the remaining 4 bits being filled in by the
texture */
palette_addr = tcw.p.palette_selector << 6;
*palette_size = 1 << 6;
} else if (tcw.pixel_fmt == TA_PXL_8BPP) {
/* in 8bpp mode, the palette selector represents the upper 2 bits of the
palette index, with the remaining 8 bits being filled in by the
texture */
palette_addr = (tcw.p.palette_selector >> 4) << 10;
*palette_size = 1 << 10;
}
*palette = &ta->pvr->palette_ram[palette_addr];
} else {
*palette = NULL;
*palette_size = 0;
}
}
static void ta_save_state(struct ta *ta, struct tile_context *ctx) {
/*
* ta rendering flow
*
* after dma'ing input parameters to texture memory, rendering is initiated by:
* 1.) writing the address of the parameters in the PARAM_BASE register
* 2.) writing to the STARTRENDER register
*
* once rendering is done, an interrupt is raised to signal so. many games take
* advantage of this time between start and end render to run additional cpu
* code, making it very adventageous to also render asynchronously at the host
* level in order to squeeze out extra free performance
*/
static void ta_save_state(struct ta *ta, struct ta_context *ctx) {
struct pvr *pvr = ta->pvr;
struct address_space *space = ta->sh4->memory_if->space;
@ -430,7 +584,7 @@ static void ta_save_state(struct ta *ta, struct tile_context *ctx) {
}
static void ta_finish_render(void *data) {
struct tile_context *ctx = data;
struct ta_context *ctx = data;
struct ta *ta = ctx->userdata;
/* ensure the client has finished rendering */
@ -445,7 +599,7 @@ static void ta_finish_render(void *data) {
holly_raise_interrupt(ta->holly, HOLLY_INT_PCEOTINT);
}
static void ta_start_render(struct ta *ta, struct tile_context *ctx) {
static void ta_start_render(struct ta *ta, struct ta_context *ctx) {
prof_counter_add(COUNTER_ta_renders, 1);
/* remove context from pool */
@ -465,6 +619,14 @@ static void ta_start_render(struct ta *ta, struct tile_context *ctx) {
scheduler_start_timer(ta->scheduler, &ta_finish_render, ctx, end);
}
/*
* yuv420 -> yuv422 conversion routines
*/
#define TA_YUV420_MACROBLOCK_SIZE 384
#define TA_YUV422_MACROBLOCK_SIZE 512
#define TA_MAX_MACROBLOCK_SIZE \
MAX(TA_YUV420_MACROBLOCK_SIZE, TA_YUV422_MACROBLOCK_SIZE)
static void ta_yuv_init(struct ta *ta) {
struct pvr *pvr = ta->pvr;
@ -561,9 +723,15 @@ static void ta_yuv_process_macroblock(struct ta *ta, void *data) {
}
}
static void ta_poly_fifo_write(struct ta *ta, uint32_t dst, void *ptr,
int size) {
PROF_ENTER("cpu", "ta_poly_fifo_write");
/* ta data handlers
*
* three types of data are written to the ta:
* 1.) polygon data - input parameters for display lists
* 2.) yuv data - yuv macroblocks that are to be reencoded as yuv422
* 3.) texture data - data that is written directly to vram
*/
static void ta_poly_write(struct ta *ta, uint32_t dst, void *ptr, int size) {
PROF_ENTER("cpu", "ta_poly_write");
CHECK(size % 32 == 0);
@ -577,9 +745,8 @@ static void ta_poly_fifo_write(struct ta *ta, uint32_t dst, void *ptr,
PROF_LEAVE();
}
static void ta_yuv_fifo_write(struct ta *ta, uint32_t dst, void *ptr,
int size) {
PROF_ENTER("cpu", "ta_yuv_fifo_write");
static void ta_yuv_write(struct ta *ta, uint32_t dst, void *ptr, int size) {
PROF_ENTER("cpu", "ta_yuv_write");
struct holly *holly = ta->holly;
struct pvr *pvr = ta->pvr;
@ -596,9 +763,8 @@ static void ta_yuv_fifo_write(struct ta *ta, uint32_t dst, void *ptr,
PROF_LEAVE();
}
static void ta_texture_fifo_write(struct ta *ta, uint32_t dst, void *ptr,
int size) {
PROF_ENTER("cpu", "ta_texture_fifo_write");
static void ta_texture_write(struct ta *ta, uint32_t dst, void *ptr, int size) {
PROF_ENTER("cpu", "ta_texture_write");
uint8_t *src = ptr;
dst &= 0xeeffffff;
@ -607,6 +773,9 @@ static void ta_texture_fifo_write(struct ta *ta, uint32_t dst, void *ptr,
PROF_LEAVE();
}
/*
* ta device interface
*/
static int ta_init(struct device *dev) {
struct ta *ta = (struct ta *)dev;
struct dreamcast *dc = ta->dc;
@ -614,7 +783,7 @@ static int ta_init(struct device *dev) {
ta->video_ram = memory_translate(dc->memory, "video ram", 0x0);
for (int i = 0; i < ARRAY_SIZE(ta->contexts); i++) {
struct tile_context *ctx = &ta->contexts[i];
struct ta_context *ctx = &ta->contexts[i];
list_add(&ta->free_contexts, &ctx->it);
}
@ -637,8 +806,8 @@ void ta_init_tables() {
pcw.para_type = j;
for (int k = 0; k < TA_NUM_VERTS; k++) {
g_param_sizes[i * TA_NUM_PARAMS * TA_NUM_VERTS + j * TA_NUM_VERTS + k] =
ta_get_param_size_raw(pcw, k);
int param_idx = i * TA_NUM_PARAMS * TA_NUM_VERTS + j * TA_NUM_VERTS + k;
ta_param_sizes[param_idx] = ta_param_size_raw(pcw, k);
}
}
}
@ -652,15 +821,26 @@ void ta_init_tables() {
for (int k = 0; k < TA_NUM_LISTS; k++) {
pcw.list_type = k;
g_poly_types[i * TA_NUM_PARAMS * TA_NUM_LISTS + j * TA_NUM_LISTS + k] =
ta_get_poly_type_raw(pcw);
g_vertex_types[i * TA_NUM_PARAMS * TA_NUM_LISTS + j * TA_NUM_LISTS +
k] = ta_get_vert_type_raw(pcw);
int poly_idx = i * TA_NUM_PARAMS * TA_NUM_LISTS + j * TA_NUM_LISTS + k;
ta_poly_types[poly_idx] = ta_poly_type_raw(pcw);
int vert_idx = i * TA_NUM_PARAMS * TA_NUM_LISTS + j * TA_NUM_LISTS + k;
ta_vert_types[vert_idx] = ta_vert_type_raw(pcw);
}
}
}
}
void ta_texture_info(struct ta *ta, union tsp tsp, union tcw tcw,
const uint8_t **texture, int *texture_size,
const uint8_t **palette, int *palette_size) {
uint32_t texture_addr = ta_texture_addr(tsp, tcw, texture_size);
*texture = &ta->video_ram[texture_addr];
uint32_t palette_addr = ta_palette_addr(tcw, palette_size);
*palette = *palette_size ? &ta->pvr->palette_ram[palette_addr] : NULL;
}
void ta_destroy(struct ta *ta) {
dc_destroy_device((struct device *)ta);
}
@ -673,6 +853,9 @@ struct ta *ta_create(struct dreamcast *dc) {
return ta;
}
/*
* ta mmio registers
*/
REG_W32(pvr_cb, SOFTRESET) {
struct ta *ta = dc->ta;
@ -690,7 +873,7 @@ REG_W32(pvr_cb, STARTRENDER) {
return;
}
struct tile_context *ctx =
struct ta_context *ctx =
ta_get_context(ta, ta->pvr->PARAM_BASE->base_address);
CHECK_NOTNULL(ctx);
ta_start_render(ta, ctx);
@ -703,7 +886,7 @@ REG_W32(pvr_cb, TA_LIST_INIT) {
return;
}
struct tile_context *ctx =
struct ta_context *ctx =
ta_demand_context(ta, ta->pvr->TA_ISP_BASE->base_address);
ta_init_context(ta, ctx);
ta->curr_context = ctx;
@ -716,7 +899,7 @@ REG_W32(pvr_cb, TA_LIST_CONT) {
return;
}
struct tile_context *ctx =
struct ta_context *ctx =
ta_get_context(ta, ta->pvr->TA_ISP_BASE->base_address);
CHECK_NOTNULL(ctx);
ta_cont_context(ta, ctx);
@ -733,15 +916,15 @@ REG_W32(pvr_cb, TA_YUV_TEX_BASE) {
}
/* clang-format off */
AM_BEGIN(struct ta, ta_fifo_map);
AM_BEGIN(struct ta, ta_data_map);
AM_RANGE(0x00000000, 0x007fffff) AM_HANDLE("ta poly fifo",
NULL, NULL, NULL,
(mmio_write_string_cb)&ta_poly_fifo_write)
(mmio_write_string_cb)&ta_poly_write)
AM_RANGE(0x00800000, 0x00ffffff) AM_HANDLE("ta yuv fifo",
NULL, NULL, NULL,
(mmio_write_string_cb)&ta_yuv_fifo_write)
(mmio_write_string_cb)&ta_yuv_write)
AM_RANGE(0x01000000, 0x01ffffff) AM_HANDLE("ta texture fifo",
NULL, NULL, NULL,
(mmio_write_string_cb)&ta_texture_fifo_write)
(mmio_write_string_cb)&ta_texture_write)
AM_END();
/* clang-format on */

View File

@ -8,29 +8,38 @@
struct dreamcast;
struct ta;
struct tr_provider;
DECLARE_COUNTER(ta_renders);
AM_DECLARE(ta_fifo_map);
AM_DECLARE(ta_data_map);
extern int g_param_sizes[0x100 * TA_NUM_PARAMS * TA_NUM_VERTS];
extern int g_poly_types[0x100 * TA_NUM_PARAMS * TA_NUM_LISTS];
extern int g_vertex_types[0x100 * TA_NUM_PARAMS * TA_NUM_LISTS];
struct ta *ta_create(struct dreamcast *dc);
void ta_destroy(struct ta *ta);
static inline int ta_get_param_size(union pcw pcw, int vertex_type) {
return g_param_sizes[pcw.obj_control * TA_NUM_PARAMS * TA_NUM_VERTS +
pcw.para_type * TA_NUM_VERTS + vertex_type];
void ta_texture_info(struct ta *ta, union tsp tsp, union tcw tcw,
const uint8_t **texture, int *texture_size,
const uint8_t **palette, int *palette_size);
/*
* parameter stream processing helpers, shared by both the ta and tr
*/
extern int ta_param_sizes[0x100 * TA_NUM_PARAMS * TA_NUM_VERTS];
extern int ta_poly_types[0x100 * TA_NUM_PARAMS * TA_NUM_LISTS];
extern int ta_vert_types[0x100 * TA_NUM_PARAMS * TA_NUM_LISTS];
static inline int ta_param_size(union pcw pcw, int vert_type) {
return ta_param_sizes[pcw.obj_control * TA_NUM_PARAMS * TA_NUM_VERTS +
pcw.para_type * TA_NUM_VERTS + vert_type];
}
static inline int ta_get_poly_type(union pcw pcw) {
return g_poly_types[pcw.obj_control * TA_NUM_PARAMS * TA_NUM_LISTS +
pcw.para_type * TA_NUM_LISTS + pcw.list_type];
static inline int ta_poly_type(union pcw pcw) {
return ta_poly_types[pcw.obj_control * TA_NUM_PARAMS * TA_NUM_LISTS +
pcw.para_type * TA_NUM_LISTS + pcw.list_type];
}
static inline int ta_get_vert_type(union pcw pcw) {
return g_vertex_types[pcw.obj_control * TA_NUM_PARAMS * TA_NUM_LISTS +
pcw.para_type * TA_NUM_LISTS + pcw.list_type];
static inline int ta_vert_type(union pcw pcw) {
return ta_vert_types[pcw.obj_control * TA_NUM_PARAMS * TA_NUM_LISTS +
pcw.para_type * TA_NUM_LISTS + pcw.list_type];
}
static inline int ta_pcw_list_type_valid(union pcw pcw, int current_list_type) {
@ -42,71 +51,19 @@ static inline int ta_pcw_list_type_valid(union pcw pcw, int current_list_type) {
pcw.para_type == TA_PARAM_SPRITE);
}
static inline uint32_t ta_texture_addr(union tcw tcw) {
return tcw.texture_addr << 3;
}
static inline int ta_texture_twiddled(union tcw tcw) {
return !tcw.scan_order ||
/* paletted textures are always twiddled */
tcw.pixel_fmt == TA_PXL_8BPP || tcw.pixel_fmt == TA_PXL_4BPP;
}
static inline int ta_texture_compressed(union tcw tcw) {
return tcw.vq_compressed;
}
static inline int ta_texture_mipmaps(union tcw tcw) {
return ta_texture_twiddled(tcw) && tcw.mip_mapped;
}
static inline int ta_texture_width(union tsp tsp, union tcw tcw) {
return 8 << tsp.texture_u_size;
}
static inline int ta_texture_height(union tsp tsp, union tcw tcw) {
int mipmaps = ta_texture_mipmaps(tcw);
int height = 8 << tsp.texture_v_size;
if (mipmaps) {
height = ta_texture_width(tsp, tcw);
}
return height;
}
static inline int ta_texture_bpp(union tcw tcw) {
int bpp = 16;
if (tcw.pixel_fmt == TA_PXL_8BPP) {
bpp = 8;
} else if (tcw.pixel_fmt == TA_PXL_4BPP) {
bpp = 4;
}
return bpp;
}
static inline int ta_texture_size(union tsp tsp, union tcw tcw) {
int compressed = ta_texture_compressed(tcw);
int mipmaps = ta_texture_mipmaps(tcw);
int width = ta_texture_width(tsp, tcw);
int height = ta_texture_height(tsp, tcw);
int bpp = ta_texture_bpp(tcw);
int texture_size = 0;
if (compressed) {
texture_size += PVR_CODEBOOK_SIZE;
}
int min_width = mipmaps ? 1 : width;
for (int i = width; i >= min_width; i /= 2) {
texture_size += (width * height * bpp) >> 3;
}
return texture_size;
}
void ta_init_tables();
struct ta *ta_create(struct dreamcast *dc);
void ta_destroy(struct ta *ta);
void ta_texture_info(struct ta *ta, union tsp tsp, union tcw tcw,
const uint8_t **texture, int *texture_size,
const uint8_t **palette, int *palette_size);
/*
* texture info helpers, shared by both the ta and tr
*/
uint32_t ta_texture_addr(union tsp tsp, union tcw tcw, int *size);
uint32_t ta_palette_addr(union tcw tcw, int *size);
int ta_texture_format(union tcw tcw);
int ta_texture_compressed(union tcw tcw);
int ta_texture_twiddled(union tcw tcw);
int ta_texture_mipmaps(union tcw tcw);
int ta_texture_width(union tsp tsp, union tcw tcw);
int ta_texture_height(union tsp tsp, union tcw tcw);
int ta_texture_stride(union tsp tsp, union tcw tcw, int stride);
#endif

View File

@ -3,7 +3,11 @@
#include <stdint.h>
#include "core/list.h"
#include "core/rb_tree.h"
#define TA_MAX_PARAMS 0x10000
/* worst case background vertex size, see ISP_BACKGND_T field */
#define TA_BG_VERTEX_SIZE ((0b111 * 2 + 3) * 4 * 3)
enum {
/* control params */
@ -33,24 +37,6 @@ enum {
TA_NUM_LISTS,
};
enum {
TA_PXL_1555,
TA_PXL_565,
TA_PXL_4444,
TA_PXL_YUV422,
TA_PXL_BUMPMAP,
TA_PXL_4BPP,
TA_PXL_8BPP,
TA_PXL_RESERVED,
};
enum {
TA_PAL_ARGB1555,
TA_PAL_RGB565,
TA_PAL_ARGB4444,
TA_PAL_ARGB8888,
};
union pcw {
struct {
/* obj control */
@ -77,7 +63,7 @@ union pcw {
uint32_t full;
};
/* Image Synthesis Processor parameters */
/* image synthesis processor parameters */
union isp {
struct {
uint32_t : 20;
@ -94,7 +80,7 @@ union isp {
uint32_t full;
};
/* Texture and Shading Processor parameters */
/* texture and shading processor parameters */
union tsp {
struct {
uint32_t texture_v_size : 3;
@ -119,7 +105,7 @@ union tsp {
uint32_t full;
};
/* Texture parameters */
/* texture parameters */
union tcw {
/* rgb, yuv and bumpmap textures */
struct {
@ -430,15 +416,7 @@ union vert_param {
} sprite1;
};
/* shared by tracer */
#define TA_MAX_SURFS (1024 * 16)
#define TA_MAX_VERTS (1024 * 64)
#define TA_MAX_PARAMS 0x10000
/* worst case background vertex size, see ISP_BACKGND_T field */
#define TA_BG_VERTEX_SIZE ((0b111 * 2 + 3) * 4 * 3)
struct tile_context {
struct ta_context {
void *user;
uint32_t addr;
void *userdata;
@ -463,7 +441,7 @@ struct tile_context {
/* current global state */
int list_type;
int vertex_type;
int vert_type;
struct list_node it;
};

View File

@ -1,3 +1,10 @@
/*
* tile accelerator rendering
*
* responsible for parsing a context generated by the ta frontend into draw
* commands to be passed to the host's render backend
*/
#include "guest/pvr/tr.h"
#include "core/assert.h"
#include "core/core.h"
@ -16,7 +23,7 @@ struct tr {
const union poly_param *last_poly;
const union vert_param *last_vertex;
int list_type;
int vertex_type;
int vert_type;
float face_color[4];
float face_offset_color[4];
int merged_surfs;
@ -118,7 +125,7 @@ static inline uint32_t float_to_rgba(float r, float g, float b, float a) {
}
static texture_handle_t tr_convert_texture(struct tr *tr,
const struct tile_context *ctx,
const struct ta_context *ctx,
union tsp tsp, union tcw tcw) {
PROF_ENTER("gpu", "tr_convert_texture");
@ -146,47 +153,13 @@ static texture_handle_t tr_convert_texture(struct tr *tr,
const uint8_t *texture = entry->texture;
/* get texture dimensions */
int compressed = ta_texture_compressed(tcw);
int twiddled = ta_texture_twiddled(tcw);
int texture_fmt = ta_texture_format(tcw);
int mipmaps = ta_texture_mipmaps(tcw);
int width = ta_texture_width(tsp, tcw);
int height = ta_texture_height(tsp, tcw);
int stride = width;
if (!twiddled && tcw.stride_select) {
stride = ctx->stride;
}
int stride = ta_texture_stride(tsp, tcw, ctx->stride);
/* figure out the texture format */
int texture_fmt = PVR_TEX_INVALID;
if (compressed) {
if (mipmaps) {
texture_fmt = PVR_TEX_VQ_MIPMAPS;
} else {
texture_fmt = PVR_TEX_VQ;
}
} else if (tcw.pixel_fmt == TA_PXL_4BPP) {
if (mipmaps) {
texture_fmt = PVR_TEX_PALETTE_4BPP_MIPMAPS;
} else {
texture_fmt = PVR_TEX_PALETTE_4BPP;
}
} else if (tcw.pixel_fmt == TA_PXL_8BPP) {
if (mipmaps) {
texture_fmt = PVR_TEX_PALETTE_8BPP_MIPMAPS;
} else {
texture_fmt = PVR_TEX_PALETTE_8BPP;
}
} else if (twiddled) {
if (mipmaps) {
texture_fmt = PVR_TEX_TWIDDLED_MIPMAPS;
} else {
texture_fmt = PVR_TEX_TWIDDLED;
}
} else {
texture_fmt = PVR_TEX_BITMAP;
}
pvr_tex_decode(texture, width, height, stride, texture_fmt, tcw.pixel_fmt,
palette, ctx->palette_fmt, converted, sizeof(converted));
@ -361,9 +334,8 @@ static void tr_commit_surf(struct tr *tr, struct tr_context *rc) {
tr->face_offset_color[3]); \
}
static int tr_parse_bg_vert(const struct tile_context *ctx,
struct tr_context *rc, int offset,
struct ta_vertex *v) {
static int tr_parse_bg_vert(const struct ta_context *ctx, struct tr_context *rc,
int offset, struct ta_vertex *v) {
PARSE_XYZ(*(float *)&ctx->bg_vertices[offset],
*(float *)&ctx->bg_vertices[offset + 4],
*(float *)&ctx->bg_vertices[offset + 8], v->xyz);
@ -393,7 +365,7 @@ static int tr_parse_bg_vert(const struct tile_context *ctx,
return offset;
}
static void tr_parse_bg(struct tr *tr, const struct tile_context *ctx,
static void tr_parse_bg(struct tr *tr, const struct ta_context *ctx,
struct tr_context *rc) {
tr->list_type = TA_LIST_OPAQUE;
@ -438,16 +410,16 @@ static void tr_parse_bg(struct tr *tr, const struct tile_context *ctx,
/* this offset color implementation is not correct at all, see the
Texture/Shading Instruction in the union tsp instruction word */
static void tr_parse_poly_param(struct tr *tr, const struct tile_context *ctx,
static void tr_parse_poly_param(struct tr *tr, const struct ta_context *ctx,
struct tr_context *rc, const uint8_t *data) {
const union poly_param *param = (const union poly_param *)data;
/* reset state */
tr->last_poly = param;
tr->last_vertex = NULL;
tr->vertex_type = ta_get_vert_type(param->type0.pcw);
tr->vert_type = ta_vert_type(param->type0.pcw);
int poly_type = ta_get_poly_type(param->type0.pcw);
int poly_type = ta_poly_type(param->type0.pcw);
if (poly_type == 6) {
/* FIXME handle modifier volumes */
@ -533,11 +505,11 @@ static void tr_parse_poly_param(struct tr *tr, const struct tile_context *ctx,
}
}
static void tr_parse_vert_param(struct tr *tr, const struct tile_context *ctx,
static void tr_parse_vert_param(struct tr *tr, const struct ta_context *ctx,
struct tr_context *rc, const uint8_t *data) {
const union vert_param *param = (const union vert_param *)data;
if (tr->vertex_type == 17) {
if (tr->vert_type == 17) {
/* FIXME handle modifier volumes */
return;
}
@ -550,7 +522,7 @@ static void tr_parse_vert_param(struct tr *tr, const struct tile_context *ctx,
}
tr->last_vertex = param;
switch (tr->vertex_type) {
switch (tr->vert_type) {
case 0: {
struct ta_vertex *vert = tr_reserve_vert(tr, rc);
PARSE_XYZ(param->type0.xyz[0], param->type0.xyz[1], param->type0.xyz[2],
@ -714,7 +686,7 @@ static void tr_parse_vert_param(struct tr *tr, const struct tile_context *ctx,
} break;
default:
LOG_FATAL("unsupported vertex type %d", tr->vertex_type);
LOG_FATAL("unsupported vertex type %d", tr->vert_type);
break;
}
@ -729,8 +701,8 @@ static void tr_parse_vert_param(struct tr *tr, const struct tile_context *ctx,
}
/* scratch buffers used by surface merge sort */
static int sort_tmp[TA_MAX_SURFS];
static float sort_minz[TA_MAX_SURFS];
static int sort_tmp[TR_MAX_SURFS];
static float sort_minz[TR_MAX_SURFS];
static int tr_compare_surf(const void *a, const void *b) {
int i = *(const int *)a;
@ -767,12 +739,12 @@ static void tr_sort_render_list(struct tr *tr, struct tr_context *rc,
PROF_LEAVE();
}
static void tr_parse_eol(struct tr *tr, const struct tile_context *ctx,
static void tr_parse_eol(struct tr *tr, const struct ta_context *ctx,
struct tr_context *rc, const uint8_t *data) {
tr->last_poly = NULL;
tr->last_vertex = NULL;
tr->list_type = TA_NUM_LISTS;
tr->vertex_type = TA_NUM_VERTS;
tr->vert_type = TA_NUM_VERTS;
}
static void tr_reset(struct tr *tr, struct tr_context *rc) {
@ -780,7 +752,7 @@ static void tr_reset(struct tr *tr, struct tr_context *rc) {
tr->last_poly = NULL;
tr->last_vertex = NULL;
tr->list_type = TA_NUM_LISTS;
tr->vertex_type = TA_NUM_VERTS;
tr->vert_type = TA_NUM_VERTS;
tr->merged_surfs = 0;
/* reset render context state */
@ -841,7 +813,7 @@ void tr_render_context(struct render_backend *r, const struct tr_context *rc) {
void tr_convert_context(struct render_backend *r, void *userdata,
tr_find_texture_cb find_texture,
const struct tile_context *ctx, struct tr_context *rc) {
const struct ta_context *ctx, struct tr_context *rc) {
PROF_ENTER("gpu", "tr_convert_context");
struct tr tr;
@ -897,11 +869,11 @@ void tr_convert_context(struct render_backend *r, void *userdata,
struct tr_param *rp = &rc->params[rc->num_params++];
rp->offset = (int)(data - ctx->params);
rp->list_type = tr.list_type;
rp->vertex_type = tr.list_type;
rp->vert_type = tr.list_type;
rp->last_surf = rc->num_surfs - 1;
rp->last_vert = rc->num_verts - 1;
data += ta_get_param_size(pcw, tr.vertex_type);
data += ta_param_size(pcw, tr.vert_type);
}
/* sort blended surface lists if requested */

View File

@ -1,15 +1,13 @@
#ifndef TR_H
#define TR_H
/* tile renderer code. responsible for parsing a raw tile_context into
draw commands to be passed to the supplied render backend */
#include "core/rb_tree.h"
#include "guest/pvr/ta_types.h"
#include "render/render_backend.h"
struct tr;
struct tr_texture;
#define TR_MAX_SURFS (1024 * 16)
#define TR_MAX_VERTS (1024 * 64)
typedef uint64_t tr_texture_key_t;
@ -36,18 +34,18 @@ struct tr_texture {
};
struct tr_param {
/* offset of parameter in tile_context param stream */
/* offset of parameter in ta_context param stream */
int offset;
/* global list and vertex types at time of parsing */
int list_type;
int vertex_type;
int vert_type;
/* last surf / vert generated for the param */
int last_surf;
int last_vert;
};
struct tr_list {
int surfs[TA_MAX_SURFS];
int surfs[TR_MAX_SURFS];
int num_surfs;
};
@ -57,13 +55,13 @@ struct tr_context {
int height;
/* parsed surfaces and vertices, ready to be passed to the render backend */
struct ta_surface surfs[TA_MAX_SURFS];
struct ta_surface surfs[TR_MAX_SURFS];
int num_surfs;
struct ta_vertex verts[TA_MAX_VERTS];
struct ta_vertex verts[TR_MAX_VERTS];
int num_verts;
uint16_t indices[TA_MAX_VERTS * 3];
uint16_t indices[TR_MAX_VERTS * 3];
int num_indices;
/* sorted list of surfaces corresponding to each of the ta's polygon lists */
@ -82,7 +80,7 @@ typedef struct tr_texture *(*tr_find_texture_cb)(void *, union tsp, union tcw);
void tr_convert_context(struct render_backend *r, void *userdata,
tr_find_texture_cb find_texture,
const struct tile_context *ctx, struct tr_context *rc);
const struct ta_context *ctx, struct tr_context *rc);
void tr_render_context(struct render_backend *r, const struct tr_context *rc);
void tr_render_context_until(struct render_backend *r,
const struct tr_context *rc, int end_surf);

View File

@ -403,7 +403,7 @@ AM_BEGIN(struct sh4, sh4_data_map)
AM_RANGE(0x01000000, 0x01ffffff) AM_DEVICE("holly", holly_expansion0_map)
AM_RANGE(0x02700000, 0x02ffffff) AM_DEVICE("holly", holly_expansion1_map)
AM_RANGE(0x04000000, 0x057fffff) AM_DEVICE("pvr", pvr_vram_map)
AM_RANGE(0x10000000, 0x11ffffff) AM_DEVICE("ta", ta_fifo_map)
AM_RANGE(0x10000000, 0x11ffffff) AM_DEVICE("ta", ta_data_map)
AM_RANGE(0x14000000, 0x17ffffff) AM_DEVICE("holly", holly_expansion2_map)
/* internal registers */

View File

@ -1,5 +1,6 @@
#include "tracer.h"
#include "core/math.h"
#include "core/rb_tree.h"
#include "file/trace.h"
#include "guest/pvr/ta.h"
#include "guest/pvr/tr.h"
@ -98,7 +99,7 @@ struct tracer {
/* trace state */
struct trace *trace;
struct tile_context ctx;
struct ta_context ctx;
struct trace_cmd *current_cmd;
int frame;
int current_param;
@ -346,7 +347,7 @@ static void tracer_param_tooltip(struct tracer *tracer, struct tr_param *rp) {
igText("tsp: 0x%x", param->type0.tsp.full);
igText("tcw: 0x%x", param->type0.tcw.full);
int poly_type = ta_get_poly_type(param->type0.pcw);
int poly_type = ta_poly_type(param->type0.pcw);
igText("poly type: %d", poly_type);
@ -378,9 +379,9 @@ static void tracer_param_tooltip(struct tracer *tracer, struct tr_param *rp) {
const union vert_param *param =
(const union vert_param *)(tracer->ctx.params + rp->offset);
igText("vert type: %d", rp->vertex_type);
igText("vert type: %d", rp->vert_type);
switch (rp->vertex_type) {
switch (rp->vert_type) {
case 0:
igText("xyz: {%.2f, %.2f, %f}", param->type0.xyz[0],
param->type0.xyz[1], param->type0.xyz[2]);
@ -610,9 +611,6 @@ static void tracer_render_side_menu(struct tracer *tracer) {
igText("filter: %s", filter_names[tex->filter]);
igText("wrap_u: %s", wrap_names[tex->wrap_u]);
igText("wrap_v: %s", wrap_names[tex->wrap_v]);
igText("twiddled: %d", ta_texture_twiddled(tex->tcw));
igText("compressed: %d", ta_texture_compressed(tex->tcw));
igText("mipmaps: %d", ta_texture_mipmaps(tex->tcw));
igText("width: %d", tex->width);
igText("height: %d", tex->height);