mirror of https://github.com/inolen/redream.git
moved ta rendering into emulator
This commit is contained in:
parent
cd0f94c205
commit
646b108bb7
|
@ -5,6 +5,8 @@
|
|||
#include "hw/gdrom/gdrom.h"
|
||||
#include "hw/memory.h"
|
||||
#include "hw/pvr/pvr.h"
|
||||
#include "hw/pvr/ta.h"
|
||||
#include "hw/pvr/tr.h"
|
||||
#include "hw/scheduler.h"
|
||||
#include "hw/sh4/sh4.h"
|
||||
#include "sys/thread.h"
|
||||
|
@ -19,6 +21,13 @@ struct emu {
|
|||
int running;
|
||||
int throttled;
|
||||
|
||||
/* render state */
|
||||
struct tr *tr;
|
||||
struct render_context render_ctx;
|
||||
struct surface surfs[TA_MAX_SURFS];
|
||||
struct vertex verts[TA_MAX_VERTS];
|
||||
int sorted_surfs[TA_MAX_SURFS];
|
||||
|
||||
/* fps */
|
||||
int fps;
|
||||
int64_t last_frame_time;
|
||||
|
@ -69,6 +78,25 @@ static bool emu_launch_gdi(struct emu *emu, const char *path) {
|
|||
static void emu_paint(void *data) {
|
||||
struct emu *emu = data;
|
||||
|
||||
/* render latest ta context */
|
||||
struct render_context *render_ctx = &emu->render_ctx;
|
||||
struct tile_ctx *pending_ctx = NULL;
|
||||
int pending_frame = 0;
|
||||
|
||||
if (ta_lock_pending_context(emu->dc->ta, &pending_ctx, &pending_frame)) {
|
||||
render_ctx->surfs = emu->surfs;
|
||||
render_ctx->surfs_size = array_size(emu->surfs);
|
||||
render_ctx->verts = emu->verts;
|
||||
render_ctx->verts_size = array_size(emu->verts);
|
||||
render_ctx->sorted_surfs = emu->sorted_surfs;
|
||||
render_ctx->sorted_surfs_size = array_size(emu->sorted_surfs);
|
||||
tr_parse_context(emu->tr, pending_ctx, pending_frame, render_ctx);
|
||||
|
||||
ta_unlock_pending_context(emu->dc->ta);
|
||||
}
|
||||
|
||||
tr_render_context(emu->tr, render_ctx);
|
||||
|
||||
/* track fps */
|
||||
int64_t now = time_nanoseconds();
|
||||
int64_t next_time = emu->last_frame_time + NS_PER_SEC;
|
||||
|
@ -81,16 +109,20 @@ static void emu_paint(void *data) {
|
|||
emu->num_frames = 0;
|
||||
}
|
||||
|
||||
dc_paint(emu->dc);
|
||||
|
||||
PROF_FLIP();
|
||||
}
|
||||
|
||||
static void emu_debug_menu(void *data, struct nk_context *ctx) {
|
||||
struct emu *emu = data;
|
||||
|
||||
nk_layout_row_push(ctx, 70.0f);
|
||||
/* set status string */
|
||||
char status[128];
|
||||
snprintf(status, sizeof(status), "%3d FPS %3d VBS %4d MIPS", emu->fps,
|
||||
emu->dc->pvr->vbs, emu->dc->sh4->mips);
|
||||
win_set_status(emu->window, status);
|
||||
|
||||
/* add drop down menus */
|
||||
nk_layout_row_push(ctx, 70.0f);
|
||||
if (nk_menu_begin_label(ctx, "EMULATOR", NK_TEXT_LEFT,
|
||||
nk_vec2(140.0f, 200.0f))) {
|
||||
nk_layout_row_dynamic(ctx, DEBUG_MENU_HEIGHT, 1);
|
||||
|
@ -98,11 +130,6 @@ static void emu_debug_menu(void *data, struct nk_context *ctx) {
|
|||
nk_menu_end(ctx);
|
||||
}
|
||||
|
||||
char status[128];
|
||||
snprintf(status, sizeof(status), "%3d FPS %3d VBS %4d MIPS", emu->fps,
|
||||
emu->dc->pvr->vbs, emu->dc->sh4->mips);
|
||||
win_set_status(emu->window, status);
|
||||
|
||||
dc_debug_menu(emu->dc, ctx);
|
||||
}
|
||||
|
||||
|
@ -149,7 +176,7 @@ static void *emu_core_thread(void *data) {
|
|||
}
|
||||
|
||||
void emu_run(struct emu *emu, const char *path) {
|
||||
emu->dc = dc_create(emu->window->video);
|
||||
emu->dc = dc_create();
|
||||
|
||||
if (!emu->dc) {
|
||||
return;
|
||||
|
@ -165,6 +192,9 @@ void emu_run(struct emu *emu, const char *path) {
|
|||
}
|
||||
}
|
||||
|
||||
/* create tile renderer */
|
||||
emu->tr = tr_create(emu->window->video, ta_texture_provider(emu->dc->ta));
|
||||
|
||||
/* start core emulator thread */
|
||||
thread_t core_thread;
|
||||
emu->running = 1;
|
||||
|
@ -196,6 +226,10 @@ struct emu *emu_create(struct window *window) {
|
|||
void emu_destroy(struct emu *emu) {
|
||||
win_remove_listener(emu->window, &emu->listener);
|
||||
|
||||
if (emu->tr) {
|
||||
tr_destroy(emu->tr);
|
||||
}
|
||||
|
||||
if (emu->dc) {
|
||||
dc_destroy(emu->dc);
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@ struct tracer {
|
|||
int num_contexts;
|
||||
|
||||
// render state
|
||||
struct render_ctx rctx;
|
||||
struct render_context rctx;
|
||||
struct surface surfs[TA_MAX_SURFS];
|
||||
struct vertex verts[TA_MAX_VERTS];
|
||||
int sorted_surfs[TA_MAX_SURFS];
|
||||
|
|
|
@ -76,14 +76,6 @@ void dc_tick(struct dreamcast *dc, int64_t ns) {
|
|||
}
|
||||
}
|
||||
|
||||
void dc_paint(struct dreamcast *dc) {
|
||||
list_for_each_entry(dev, &dc->devices, struct device, it) {
|
||||
if (dev->window_if && dev->window_if->paint) {
|
||||
dev->window_if->paint(dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dc_debug_menu(struct dreamcast *dc, struct nk_context *ctx) {
|
||||
list_for_each_entry(dev, &dc->devices, struct device, it) {
|
||||
if (dev->window_if && dev->window_if->debug_menu) {
|
||||
|
@ -127,10 +119,8 @@ void dc_destroy_memory_interface(struct memory_interface *memory) {
|
|||
}
|
||||
|
||||
struct window_interface *dc_create_window_interface(
|
||||
device_paint_cb paint, device_debug_menu_cb debug_menu,
|
||||
device_keydown_cb keydown) {
|
||||
device_debug_menu_cb debug_menu, device_keydown_cb keydown) {
|
||||
struct window_interface *window = calloc(1, sizeof(struct window_interface));
|
||||
window->paint = paint;
|
||||
window->debug_menu = debug_menu;
|
||||
window->keydown = keydown;
|
||||
return window;
|
||||
|
@ -169,7 +159,7 @@ void dc_destroy_device(struct device *dev) {
|
|||
free(dev);
|
||||
}
|
||||
|
||||
struct dreamcast *dc_create(struct video_backend *video) {
|
||||
struct dreamcast *dc_create() {
|
||||
struct dreamcast *dc = calloc(1, sizeof(struct dreamcast));
|
||||
|
||||
dc->debugger = OPTION_gdb ? debugger_create(dc) : NULL;
|
||||
|
@ -184,7 +174,7 @@ struct dreamcast *dc_create(struct video_backend *video) {
|
|||
dc->holly = holly_create(dc);
|
||||
dc->maple = maple_create(dc);
|
||||
dc->pvr = pvr_create(dc);
|
||||
dc->ta = ta_create(dc, video);
|
||||
dc->ta = ta_create(dc);
|
||||
|
||||
if (!dc_init(dc)) {
|
||||
dc_destroy(dc);
|
||||
|
|
|
@ -24,7 +24,6 @@ struct pvr;
|
|||
struct scheduler;
|
||||
struct sh4;
|
||||
struct ta;
|
||||
struct video_backend;
|
||||
|
||||
//
|
||||
// register callbacks
|
||||
|
@ -86,12 +85,10 @@ struct memory_interface {
|
|||
};
|
||||
|
||||
// window interface
|
||||
typedef void (*device_paint_cb)(struct device *);
|
||||
typedef void (*device_debug_menu_cb)(struct device *, struct nk_context *);
|
||||
typedef void (*device_keydown_cb)(struct device *, enum keycode, int16_t);
|
||||
|
||||
struct window_interface {
|
||||
device_paint_cb paint;
|
||||
device_debug_menu_cb debug_menu;
|
||||
device_keydown_cb keydown;
|
||||
};
|
||||
|
@ -153,7 +150,6 @@ bool dc_init(struct dreamcast *dc);
|
|||
void dc_suspend(struct dreamcast *dc);
|
||||
void dc_resume(struct dreamcast *dc);
|
||||
void dc_tick(struct dreamcast *dc, int64_t ns);
|
||||
void dc_paint(struct dreamcast *dc);
|
||||
void dc_debug_menu(struct dreamcast *dc, struct nk_context *ctx);
|
||||
void dc_keydown(struct dreamcast *dc, enum keycode code, int16_t value);
|
||||
|
||||
|
@ -166,8 +162,7 @@ struct memory_interface *dc_create_memory_interface(struct dreamcast *dc,
|
|||
void dc_destroy_memory_interface(struct memory_interface *memory);
|
||||
|
||||
struct window_interface *dc_create_window_interface(
|
||||
device_paint_cb paint, device_debug_menu_cb debug_menu,
|
||||
device_keydown_cb keydown);
|
||||
device_debug_menu_cb debug_menu, device_keydown_cb keydown);
|
||||
void dc_destroy_window_interface(struct window_interface *window);
|
||||
|
||||
void *dc_create_device(struct dreamcast *dc, size_t size, const char *name,
|
||||
|
@ -175,7 +170,7 @@ void *dc_create_device(struct dreamcast *dc, size_t size, const char *name,
|
|||
struct device *dc_get_device(struct dreamcast *dc, const char *name);
|
||||
void dc_destroy_device(struct device *dev);
|
||||
|
||||
struct dreamcast *dc_create(struct video_backend *video);
|
||||
struct dreamcast *dc_create();
|
||||
void dc_destroy(struct dreamcast *dc);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -36,7 +36,7 @@ int maple_handle_command(struct maple *mp, int port, struct maple_frame *frame,
|
|||
struct maple *maple_create(struct dreamcast *dc) {
|
||||
struct maple *mp =
|
||||
dc_create_device(dc, sizeof(struct maple), "maple", &maple_init);
|
||||
mp->window_if = dc_create_window_interface(NULL, NULL, &maple_keydown);
|
||||
mp->window_if = dc_create_window_interface(NULL, &maple_keydown);
|
||||
|
||||
mp->devices[0] = controller_create();
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include "sys/filesystem.h"
|
||||
#include "sys/thread.h"
|
||||
#include "ui/nuklear.h"
|
||||
#include "video/backend.h"
|
||||
|
||||
#define TA_MAX_CONTEXTS 8
|
||||
#define TA_YUV420_MACROBLOCK_SIZE 384
|
||||
|
@ -32,7 +31,6 @@ struct ta_texture_entry {
|
|||
struct ta {
|
||||
struct device;
|
||||
struct texture_provider provider;
|
||||
struct tr *tr;
|
||||
uint8_t *video_ram;
|
||||
uint8_t *palette_ram;
|
||||
|
||||
|
@ -65,19 +63,11 @@ struct ta {
|
|||
mutex_t pending_mutex;
|
||||
struct tile_ctx *pending_context;
|
||||
|
||||
// last parsed pending context
|
||||
struct render_ctx render_context;
|
||||
|
||||
// buffers used by the tile contexts. allocating here instead of inside each
|
||||
// tile_ctx to avoid blowing the stack when a tile_ctx is needed temporarily
|
||||
// on the stack for searching
|
||||
uint8_t params[TA_MAX_CONTEXTS * TA_MAX_PARAMS];
|
||||
|
||||
// buffers used by render context
|
||||
struct surface surfs[TA_MAX_SURFS];
|
||||
struct vertex verts[TA_MAX_VERTS];
|
||||
int sorted_surfs[TA_MAX_SURFS];
|
||||
|
||||
// debug info
|
||||
int frame;
|
||||
int frames_skipped;
|
||||
|
@ -862,31 +852,6 @@ static void ta_toggle_tracing(struct ta *ta) {
|
|||
}
|
||||
}
|
||||
|
||||
static void ta_paint(struct device *dev) {
|
||||
struct ta *ta = (struct ta *)dev;
|
||||
struct render_ctx *rctx = &ta->render_context;
|
||||
|
||||
mutex_lock(ta->pending_mutex);
|
||||
|
||||
if (ta->pending_context) {
|
||||
rctx->surfs = ta->surfs;
|
||||
rctx->surfs_size = array_size(ta->surfs);
|
||||
rctx->verts = ta->verts;
|
||||
rctx->verts_size = array_size(ta->verts);
|
||||
rctx->sorted_surfs = ta->sorted_surfs;
|
||||
rctx->sorted_surfs_size = array_size(ta->sorted_surfs);
|
||||
|
||||
tr_parse_context(ta->tr, ta->pending_context, ta->frame, rctx);
|
||||
|
||||
ta_free_context(ta, ta->pending_context);
|
||||
ta->pending_context = NULL;
|
||||
}
|
||||
|
||||
mutex_unlock(ta->pending_mutex);
|
||||
|
||||
tr_render_context(ta->tr, rctx);
|
||||
}
|
||||
|
||||
static void ta_debug_menu(struct device *dev, struct nk_context *ctx) {
|
||||
struct ta *ta = (struct ta *)dev;
|
||||
|
||||
|
@ -949,21 +914,44 @@ void ta_build_tables() {
|
|||
}
|
||||
}
|
||||
|
||||
void ta_unlock_pending_context(struct ta *ta) {
|
||||
ta_free_context(ta, ta->pending_context);
|
||||
ta->pending_context = NULL;
|
||||
|
||||
mutex_unlock(ta->pending_mutex);
|
||||
}
|
||||
|
||||
int ta_lock_pending_context(struct ta *ta, struct tile_ctx **pending_ctx,
|
||||
int *pending_frame) {
|
||||
mutex_lock(ta->pending_mutex);
|
||||
|
||||
if (!ta->pending_context) {
|
||||
mutex_unlock(ta->pending_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*pending_ctx = ta->pending_context;
|
||||
*pending_frame = ta->frame;
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct texture_provider *ta_texture_provider(struct ta *ta) {
|
||||
return &ta->provider;
|
||||
}
|
||||
|
||||
void ta_destroy(struct ta *ta) {
|
||||
mutex_destroy(ta->pending_mutex);
|
||||
tr_destroy(ta->tr);
|
||||
dc_destroy_window_interface(ta->window_if);
|
||||
dc_destroy_device((struct device *)ta);
|
||||
}
|
||||
|
||||
struct ta *ta_create(struct dreamcast *dc, struct video_backend *video) {
|
||||
struct ta *ta_create(struct dreamcast *dc) {
|
||||
ta_build_tables();
|
||||
|
||||
struct ta *ta = dc_create_device(dc, sizeof(struct ta), "ta", &ta_init);
|
||||
ta->window_if = dc_create_window_interface(&ta_paint, &ta_debug_menu, NULL);
|
||||
ta->window_if = dc_create_window_interface(&ta_debug_menu, NULL);
|
||||
ta->provider =
|
||||
(struct texture_provider){ta, &ta_texture_provider_find_texture};
|
||||
ta->tr = tr_create(video, &ta->provider);
|
||||
ta->pending_mutex = mutex_create();
|
||||
|
||||
return ta;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "hw/pvr/ta_types.h"
|
||||
|
||||
struct dreamcast;
|
||||
struct video_backend;
|
||||
struct texture_provider;
|
||||
|
||||
extern int g_param_sizes[0x100 * TA_NUM_PARAMS * TA_NUM_VERT_TYPES];
|
||||
extern int g_poly_types[0x100 * TA_NUM_PARAMS * TA_NUM_LISTS];
|
||||
|
@ -30,9 +30,14 @@ struct ta;
|
|||
|
||||
void ta_build_tables();
|
||||
|
||||
void ta_destroy(struct ta *ta);
|
||||
struct ta *ta_create(struct dreamcast *dc, struct video_backend *video);
|
||||
|
||||
AM_DECLARE(ta_fifo_map);
|
||||
|
||||
struct ta *ta_create(struct dreamcast *dc);
|
||||
void ta_destroy(struct ta *ta);
|
||||
|
||||
struct texture_provider *ta_texture_provider(struct ta *ta);
|
||||
int ta_lock_pending_context(struct ta *ta, struct tile_ctx **pending_ctx,
|
||||
int *pending_frame);
|
||||
void ta_unlock_pending_context(struct ta *ta);
|
||||
|
||||
#endif
|
||||
|
|
352
src/hw/pvr/tr.c
352
src/hw/pvr/tr.c
|
@ -11,7 +11,7 @@ struct tr {
|
|||
struct video_backend *video;
|
||||
struct texture_provider *provider;
|
||||
|
||||
// current global state
|
||||
/* current global state */
|
||||
const union poly_param *last_poly;
|
||||
const union vert_param *last_vertex;
|
||||
int list_type;
|
||||
|
@ -22,47 +22,47 @@ struct tr {
|
|||
};
|
||||
|
||||
static int compressed_mipmap_offsets[] = {
|
||||
0x00006, // 8 x 8
|
||||
0x00016, // 16 x 16
|
||||
0x00056, // 32 x 32
|
||||
0x00156, // 64 x 64
|
||||
0x00556, // 128 x 128
|
||||
0x01556, // 256 x 256
|
||||
0x05556, // 512 x 512
|
||||
0x15556, // 1024 x 1024
|
||||
0x00006, /* 8 x 8 */
|
||||
0x00016, /* 16 x 16 */
|
||||
0x00056, /* 32 x 32 */
|
||||
0x00156, /* 64 x 64 */
|
||||
0x00556, /* 128 x 128 */
|
||||
0x01556, /* 256 x 256 */
|
||||
0x05556, /* 512 x 512 */
|
||||
0x15556, /* 1024 x 1024 */
|
||||
};
|
||||
|
||||
static int paletted_4bpp_mipmap_offsets[] = {
|
||||
0x0000c, // 8 x 8
|
||||
0x0002c, // 16 x 16
|
||||
0x000ac, // 32 x 32
|
||||
0x002ac, // 64 x 64
|
||||
0x00aac, // 128 x 128
|
||||
0x02aac, // 256 x 256
|
||||
0x0aaac, // 512 x 512
|
||||
0x2aaac, // 1024 x 1024
|
||||
0x0000c, /* 8 x 8 */
|
||||
0x0002c, /* 16 x 16 */
|
||||
0x000ac, /* 32 x 32 */
|
||||
0x002ac, /* 64 x 64 */
|
||||
0x00aac, /* 128 x 128 */
|
||||
0x02aac, /* 256 x 256 */
|
||||
0x0aaac, /* 512 x 512 */
|
||||
0x2aaac, /* 1024 x 1024 */
|
||||
};
|
||||
|
||||
static int paletted_8bpp_mipmap_offsets[] = {
|
||||
0x00018, // 8 x 8
|
||||
0x00058, // 16 x 16
|
||||
0x00158, // 32 x 32
|
||||
0x00558, // 64 x 64
|
||||
0x01558, // 128 x 128
|
||||
0x05558, // 256 x 256
|
||||
0x15558, // 512 x 512
|
||||
0x55558, // 1024 x 1024
|
||||
0x00018, /* 8 x 8 */
|
||||
0x00058, /* 16 x 16 */
|
||||
0x00158, /* 32 x 32 */
|
||||
0x00558, /* 64 x 64 */
|
||||
0x01558, /* 128 x 128 */
|
||||
0x05558, /* 256 x 256 */
|
||||
0x15558, /* 512 x 512 */
|
||||
0x55558, /* 1024 x 1024 */
|
||||
};
|
||||
|
||||
static int nonpaletted_mipmap_offsets[] = {
|
||||
0x00030, // 8 x 8
|
||||
0x000b0, // 16 x 16
|
||||
0x002b0, // 32 x 32
|
||||
0x00ab0, // 64 x 64
|
||||
0x02ab0, // 128 x 128
|
||||
0x0aab0, // 256 x 256
|
||||
0x2aab0, // 512 x 512
|
||||
0xaaab0, // 1024 x 1024
|
||||
0x00030, /* 8 x 8 */
|
||||
0x000b0, /* 16 x 16 */
|
||||
0x002b0, /* 32 x 32 */
|
||||
0x00ab0, /* 64 x 64 */
|
||||
0x02ab0, /* 128 x 128 */
|
||||
0x0aab0, /* 256 x 256 */
|
||||
0x2aab0, /* 512 x 512 */
|
||||
0xaaab0, /* 1024 x 1024 */
|
||||
};
|
||||
|
||||
static inline enum depth_func translate_depth_func(uint32_t depth_func) {
|
||||
|
@ -119,28 +119,33 @@ static inline uint32_t float_to_rgba(float r, float g, float b, float a) {
|
|||
static texture_handle_t tr_demand_texture(struct tr *tr,
|
||||
const struct tile_ctx *ctx, int frame,
|
||||
union tsp tsp, union tcw tcw) {
|
||||
// TODO it's bad that textures are only cached based off tsp / tcw yet
|
||||
// the TEXT_CONTROL registers and PAL_RAM_CTRL registers are used here
|
||||
// to control texture generation
|
||||
/*
|
||||
* TODO
|
||||
* it's bad that textures are only cached based off tsp / tcw yet the
|
||||
* TEXT_CONTROL registers and PAL_RAM_CTRL registers are used here to
|
||||
* control texture generation
|
||||
*/
|
||||
|
||||
struct texture_entry *entry =
|
||||
tr->provider->find_texture(tr->provider->data, tsp, tcw);
|
||||
CHECK_NOTNULL(entry);
|
||||
|
||||
// if there's a non-dirty handle, go ahead and return it
|
||||
/* if there's a non-dirty handle, return it */
|
||||
if (entry->handle && !entry->dirty) {
|
||||
return entry->handle;
|
||||
}
|
||||
|
||||
// if there's a dirty handle, destroy it before creating the new one
|
||||
/* if there's a dirty handle, destroy it before creating the new one */
|
||||
if (entry->handle && entry->dirty) {
|
||||
video_destroy_texture(tr->video, entry->handle);
|
||||
entry->handle = 0;
|
||||
}
|
||||
|
||||
// sanity check that the texture source is valid for the current frame. video
|
||||
// ram will be modified between frames, if these values don't match something
|
||||
// is broken in the ta's thread synchronization
|
||||
/*
|
||||
* sanity check that the texture source is valid for the current frame. video
|
||||
* ram will be modified between frames, if these values don't match something
|
||||
* is broken in the ta's thread synchronization
|
||||
*/
|
||||
CHECK_EQ(frame, entry->frame);
|
||||
|
||||
static uint8_t converted[1024 * 1024 * 4];
|
||||
|
@ -149,13 +154,15 @@ static texture_handle_t tr_demand_texture(struct tr *tr,
|
|||
const uint8_t *input = texture;
|
||||
const uint8_t *output = texture;
|
||||
|
||||
// textures are either twiddled and vq compressed, twiddled and uncompressed
|
||||
// or planar
|
||||
/*
|
||||
* textures are either twiddled and vq compressed, twiddled and uncompressed
|
||||
* or planar
|
||||
*/
|
||||
bool twiddled = !tcw.scan_order;
|
||||
bool compressed = tcw.vq_compressed;
|
||||
bool mip_mapped = !tcw.scan_order && tcw.mip_mapped;
|
||||
|
||||
// get texture dimensions
|
||||
/* get texture dimensions */
|
||||
int width = 8 << tsp.texture_u_size;
|
||||
int height = mip_mapped ? width : 8 << tsp.texture_v_size;
|
||||
int stride = width;
|
||||
|
@ -163,12 +170,16 @@ static texture_handle_t tr_demand_texture(struct tr *tr,
|
|||
stride = ctx->stride;
|
||||
}
|
||||
|
||||
// mipmap textures contain data for 1 x 1 up to width x height. skip to the
|
||||
// highest res texture and let the renderer backend generate its own mipmaps
|
||||
/*
|
||||
* mipmap textures contain data for 1 x 1 up to width x height. skip to the
|
||||
* highest res texture and let the renderer backend generate its own mipmaps
|
||||
*/
|
||||
if (mip_mapped) {
|
||||
if (compressed) {
|
||||
// for vq compressed textures the offset is only for the index data, the
|
||||
// codebook is the same for all levels
|
||||
/*
|
||||
* for vq compressed textures the offset is only for the index data, the
|
||||
* codebook is the same for all levels
|
||||
*/
|
||||
input += compressed_mipmap_offsets[tsp.texture_u_size];
|
||||
} else if (tcw.pixel_format == TA_PIXEL_4BPP) {
|
||||
input += paletted_4bpp_mipmap_offsets[tsp.texture_u_size];
|
||||
|
@ -179,7 +190,7 @@ static texture_handle_t tr_demand_texture(struct tr *tr,
|
|||
}
|
||||
}
|
||||
|
||||
// used by vq compressed textures
|
||||
/* used by vq compressed textures */
|
||||
static const int codebook_size = 256 * 8;
|
||||
const uint8_t *codebook = texture;
|
||||
const uint8_t *index = input + codebook_size;
|
||||
|
@ -289,7 +300,7 @@ static texture_handle_t tr_demand_texture(struct tr *tr,
|
|||
break;
|
||||
}
|
||||
|
||||
// ignore trilinear filtering for now
|
||||
/* ignore trilinear filtering for now */
|
||||
enum filter_mode filter =
|
||||
tsp.filter_mode == 0 ? FILTER_NEAREST : FILTER_BILINEAR;
|
||||
enum wrap_mode wrap_u =
|
||||
|
@ -314,9 +325,8 @@ static texture_handle_t tr_demand_texture(struct tr *tr,
|
|||
return entry->handle;
|
||||
}
|
||||
|
||||
static struct surface *tr_alloc_surf(struct tr *tr, struct render_ctx *rctx,
|
||||
static struct surface *tr_alloc_surf(struct tr *tr, struct render_context *rctx,
|
||||
bool copy_from_prev) {
|
||||
// either reset the surface state, or copy the state from the previous surface
|
||||
CHECK_LT(rctx->num_surfs, rctx->surfs_size);
|
||||
int id = rctx->num_surfs++;
|
||||
struct surface *surf = &rctx->surfs[id];
|
||||
|
@ -327,48 +337,52 @@ static struct surface *tr_alloc_surf(struct tr *tr, struct render_ctx *rctx,
|
|||
memset(surf, 0, sizeof(*surf));
|
||||
}
|
||||
|
||||
// star verts at the end
|
||||
/* start verts at the end */
|
||||
surf->first_vert = rctx->num_verts;
|
||||
surf->num_verts = 0;
|
||||
|
||||
// default sort the surface
|
||||
/* default sort the surface */
|
||||
rctx->sorted_surfs[id] = id;
|
||||
|
||||
return surf;
|
||||
}
|
||||
|
||||
static struct vertex *tr_alloc_vert(struct tr *tr, struct render_ctx *rctx) {
|
||||
static struct vertex *tr_alloc_vert(struct tr *tr,
|
||||
struct render_context *rctx) {
|
||||
CHECK_LT(rctx->num_verts, rctx->verts_size);
|
||||
int id = rctx->num_verts++;
|
||||
struct vertex *v = &rctx->verts[id];
|
||||
memset(v, 0, sizeof(*v));
|
||||
|
||||
// update vertex count on the current surface
|
||||
/* update vertex count on the current surface */
|
||||
struct surface *surf = &rctx->surfs[rctx->num_surfs - 1];
|
||||
surf->num_verts++;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
static void tr_discard_incomplete_surf(struct tr *tr, struct render_ctx *rctx) {
|
||||
// free up the last surface if it wasn't finished
|
||||
static void tr_discard_incomplete_surf(struct tr *tr,
|
||||
struct render_context *rctx) {
|
||||
/* free up the last surface if it wasn't finished */
|
||||
if (tr->last_vertex && !tr->last_vertex->type0.pcw.end_of_strip) {
|
||||
rctx->num_surfs--;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME we could offload a lot of this to the GPU, generating shaders
|
||||
// for different combinations of ISP/union tsp parameters once the logic is
|
||||
// ironed out
|
||||
// FIXME honor use alpha
|
||||
// FIXME honor ignore tex alpha
|
||||
/*
|
||||
* TODO
|
||||
* offload thiis to the GPU, generating shader for different combinations of
|
||||
* ISP/TSP parameters once the logic is ironed out
|
||||
*/
|
||||
/* FIXME honor use alpha */
|
||||
/* FIXME honor ignore tex alpha */
|
||||
static void tr_parse_color(struct tr *tr, uint32_t base_color,
|
||||
uint32_t *color) {
|
||||
*color = abgr_to_rgba(base_color);
|
||||
|
||||
// if (!tr->last_poly->type0.tsp.use_alpha) {
|
||||
// color[3] = 1.0f;
|
||||
// }
|
||||
/*if (!tr->last_poly->type0.tsp.use_alpha) {
|
||||
color[3] = 1.0f;
|
||||
}*/
|
||||
}
|
||||
|
||||
static void tr_parse_color_intensity(struct tr *tr, float base_intensity,
|
||||
|
@ -377,18 +391,18 @@ static void tr_parse_color_intensity(struct tr *tr, float base_intensity,
|
|||
tr->face_color[1] * base_intensity,
|
||||
tr->face_color[2] * base_intensity, tr->face_color[3]);
|
||||
|
||||
// if (!tr->last_poly->type0.tsp.use_alpha) {
|
||||
// color[3] = 1.0f;
|
||||
// }
|
||||
/*if (!tr->last_poly->type0.tsp.use_alpha) {
|
||||
color[3] = 1.0f;
|
||||
}*/
|
||||
}
|
||||
|
||||
static void tr_parse_color_rgba(struct tr *tr, float r, float g, float b,
|
||||
float a, uint32_t *color) {
|
||||
*color = float_to_rgba(r, g, b, a);
|
||||
|
||||
// if (!tr->last_poly->type0.tsp.use_alpha) {
|
||||
// color[3] = 1.0f;
|
||||
// }
|
||||
/*if (!tr->last_poly->type0.tsp.use_alpha) {
|
||||
color[3] = 1.0f;
|
||||
}*/
|
||||
}
|
||||
|
||||
static void tr_parse_offset_color(struct tr *tr, uint32_t offset_color,
|
||||
|
@ -431,9 +445,9 @@ static int tr_parse_bg_vert(const struct tile_ctx *ctx, int offset,
|
|||
|
||||
if (ctx->bg_isp.texture) {
|
||||
LOG_FATAL("Unsupported bg_isp.texture");
|
||||
// v->uv[0] = *(float *)(&ctx->bg_vertices[offset]);
|
||||
// v->uv[1] = *(float *)(&ctx->bg_vertices[offset + 4]);
|
||||
// offset += 8;
|
||||
/*v->uv[0] = *(float *)(&ctx->bg_vertices[offset]);
|
||||
v->uv[1] = *(float *)(&ctx->bg_vertices[offset + 4]);
|
||||
offset += 8;*/
|
||||
}
|
||||
|
||||
uint32_t base_color = *(uint32_t *)&ctx->bg_vertices[offset];
|
||||
|
@ -442,20 +456,20 @@ static int tr_parse_bg_vert(const struct tile_ctx *ctx, int offset,
|
|||
|
||||
if (ctx->bg_isp.offset) {
|
||||
LOG_FATAL("Unsupported bg_isp.offset");
|
||||
// uint32_t offset_color = *(uint32_t *)(&ctx->bg_vertices[offset]);
|
||||
// v->offset_color[0] = ((offset_color >> 16) & 0xff) / 255.0f;
|
||||
// v->offset_color[1] = ((offset_color >> 16) & 0xff) / 255.0f;
|
||||
// v->offset_color[2] = ((offset_color >> 16) & 0xff) / 255.0f;
|
||||
// v->offset_color[3] = 0.0f;
|
||||
// offset += 4;
|
||||
/*uint32_t offset_color = *(uint32_t *)(&ctx->bg_vertices[offset]);
|
||||
v->offset_color[0] = ((offset_color >> 16) & 0xff) / 255.0f;
|
||||
v->offset_color[1] = ((offset_color >> 16) & 0xff) / 255.0f;
|
||||
v->offset_color[2] = ((offset_color >> 16) & 0xff) / 255.0f;
|
||||
v->offset_color[3] = 0.0f;
|
||||
offset += 4;*/
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
static void tr_parse_bg(struct tr *tr, const struct tile_ctx *ctx,
|
||||
struct render_ctx *rctx) {
|
||||
// translate the surface
|
||||
struct render_context *rctx) {
|
||||
/* translate the surface */
|
||||
struct surface *surf = tr_alloc_surf(tr, rctx, false);
|
||||
|
||||
surf->texture = 0;
|
||||
|
@ -465,7 +479,7 @@ static void tr_parse_bg(struct tr *tr, const struct tile_ctx *ctx,
|
|||
surf->src_blend = BLEND_NONE;
|
||||
surf->dst_blend = BLEND_NONE;
|
||||
|
||||
// translate the first 3 vertices
|
||||
/* translate the first 3 vertices */
|
||||
struct vertex *v0 = tr_alloc_vert(tr, rctx);
|
||||
struct vertex *v1 = tr_alloc_vert(tr, rctx);
|
||||
struct vertex *v2 = tr_alloc_vert(tr, rctx);
|
||||
|
@ -476,8 +490,10 @@ static void tr_parse_bg(struct tr *tr, const struct tile_ctx *ctx,
|
|||
offset = tr_parse_bg_vert(ctx, offset, v1);
|
||||
offset = tr_parse_bg_vert(ctx, offset, v2);
|
||||
|
||||
// override the xyz values supplied by ISP_BACKGND_T. while the hardware docs
|
||||
// act like the should be correct, they're most definitely not in most cases
|
||||
/*
|
||||
* override the xyz values supplied by ISP_BACKGND_T. while the hardware docs
|
||||
* act like the should be correct, they're most definitely not in most cases
|
||||
*/
|
||||
v0->xyz[0] = 0.0f;
|
||||
v0->xyz[1] = (float)ctx->video_height;
|
||||
v0->xyz[2] = ctx->bg_depth;
|
||||
|
@ -488,7 +504,7 @@ static void tr_parse_bg(struct tr *tr, const struct tile_ctx *ctx,
|
|||
v2->xyz[1] = (float)ctx->video_height;
|
||||
v2->xyz[2] = ctx->bg_depth;
|
||||
|
||||
// 4th vertex isn't supplied, fill it out automatically
|
||||
/* 4th vertex isn't supplied, fill it out automatically */
|
||||
v3->xyz[0] = v2->xyz[0];
|
||||
v3->xyz[1] = v1->xyz[1];
|
||||
v3->xyz[2] = ctx->bg_depth;
|
||||
|
@ -498,10 +514,12 @@ static void tr_parse_bg(struct tr *tr, const struct tile_ctx *ctx,
|
|||
v3->uv[1] = v1->uv[1];
|
||||
}
|
||||
|
||||
// NOTE this offset color implementation is not correct at all, see the
|
||||
// Texture/Shading Instruction in the union tsp instruction word
|
||||
/*
|
||||
* 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_ctx *ctx,
|
||||
int frame, struct render_ctx *rctx,
|
||||
int frame, struct render_context *rctx,
|
||||
const uint8_t *data) {
|
||||
tr_discard_incomplete_surf(tr, rctx);
|
||||
|
||||
|
@ -515,8 +533,8 @@ static void tr_parse_poly_param(struct tr *tr, const struct tile_ctx *ctx,
|
|||
int poly_type = ta_get_poly_type(param->type0.pcw);
|
||||
switch (poly_type) {
|
||||
case 0: {
|
||||
// uint32_t sdma_data_size;
|
||||
// uint32_t sdma_next_addr;
|
||||
/*uint32_t sdma_data_size;
|
||||
uint32_t sdma_next_addr;*/
|
||||
} break;
|
||||
|
||||
case 1: {
|
||||
|
@ -552,7 +570,7 @@ static void tr_parse_poly_param(struct tr *tr, const struct tile_ctx *ctx,
|
|||
} break;
|
||||
|
||||
case 6:
|
||||
// don't do anything with modifier volume yet
|
||||
/* don't do anything with modifier volume yet */
|
||||
return;
|
||||
|
||||
default:
|
||||
|
@ -560,7 +578,7 @@ static void tr_parse_poly_param(struct tr *tr, const struct tile_ctx *ctx,
|
|||
break;
|
||||
}
|
||||
|
||||
// setup the new surface
|
||||
/* setup the new surface */
|
||||
struct surface *surf = tr_alloc_surf(tr, rctx, false);
|
||||
surf->depth_write = !param->type0.isp_tsp.z_write_disable;
|
||||
surf->depth_func =
|
||||
|
@ -571,7 +589,7 @@ static void tr_parse_poly_param(struct tr *tr, const struct tile_ctx *ctx,
|
|||
surf->shade = translate_shade_mode(param->type0.tsp.texture_shading_instr);
|
||||
surf->ignore_tex_alpha = param->type0.tsp.ignore_tex_alpha;
|
||||
|
||||
// override a few surface parameters based on the list type
|
||||
/* override a few surface parameters based on the list type */
|
||||
if (tr->list_type != TA_LIST_TRANSLUCENT &&
|
||||
tr->list_type != TA_LIST_TRANSLUCENT_MODVOL) {
|
||||
surf->src_blend = BLEND_NONE;
|
||||
|
@ -594,10 +612,10 @@ static void tr_parse_poly_param(struct tr *tr, const struct tile_ctx *ctx,
|
|||
|
||||
static void tr_parse_spritea_vert(struct tr *tr, const union vert_param *param,
|
||||
int i, struct vertex *vert) {
|
||||
// FIXME this is assuming all sprites are billboards
|
||||
// z isn't specified for i == 3
|
||||
/* FIXME this is assuming all sprites are billboards */
|
||||
vert->xyz[0] = param->sprite0.xyz[i][0];
|
||||
vert->xyz[1] = param->sprite0.xyz[i][1];
|
||||
/* z isn't specified for i == 3 */
|
||||
vert->xyz[2] = param->sprite0.xyz[0][2];
|
||||
|
||||
tr_parse_color_rgba(tr, tr->face_color[0], tr->face_color[1],
|
||||
|
@ -609,10 +627,10 @@ static void tr_parse_spritea_vert(struct tr *tr, const union vert_param *param,
|
|||
|
||||
static void tr_parse_spriteb_vert(struct tr *tr, const union vert_param *param,
|
||||
int i, struct vertex *vert) {
|
||||
// FIXME this is assuming all sprites are billboards
|
||||
// z isn't specified for i == 3
|
||||
/* FIXME this is assuming all sprites are billboards */
|
||||
vert->xyz[0] = param->sprite1.xyz[i][0];
|
||||
vert->xyz[1] = param->sprite1.xyz[i][1];
|
||||
/* z isn't specified for i == 3 */
|
||||
vert->xyz[2] = param->sprite1.xyz[0][2];
|
||||
tr_parse_color_rgba(tr, tr->face_color[0], tr->face_color[1],
|
||||
tr->face_color[2], tr->face_color[3], &vert->color);
|
||||
|
@ -632,13 +650,14 @@ static void tr_parse_spriteb_vert(struct tr *tr, const union vert_param *param,
|
|||
}
|
||||
|
||||
static void tr_parse_vert_param(struct tr *tr, const struct tile_ctx *ctx,
|
||||
struct render_ctx *rctx, const uint8_t *data) {
|
||||
struct render_context *rctx,
|
||||
const uint8_t *data) {
|
||||
const union vert_param *param = (const union vert_param *)data;
|
||||
// If there is no need to change the Global Parameters, a struct vertex
|
||||
// Parameter
|
||||
// for
|
||||
// the next polygon may be input immediately after inputting a vertex_t
|
||||
// Parameter for which "End of Strip" was specified.
|
||||
/*
|
||||
* if there is no need to change the Global Parameters, a Vertex Parameter
|
||||
* for the next polygon may be input immediately after inputting a Vertex
|
||||
* Parameter for which "End of Strip" was specified
|
||||
*/
|
||||
if (tr->last_vertex && tr->last_vertex->type0.pcw.end_of_strip) {
|
||||
tr_alloc_surf(tr, rctx, true);
|
||||
}
|
||||
|
@ -779,7 +798,7 @@ static void tr_parse_vert_param(struct tr *tr, const struct tile_ctx *ctx,
|
|||
} break;
|
||||
|
||||
case 17: {
|
||||
// LOG_WARNING("Unhandled modvol triangle");
|
||||
/* LOG_WARNING("Unhandled modvol triangle"); */
|
||||
} break;
|
||||
|
||||
default:
|
||||
|
@ -787,16 +806,18 @@ static void tr_parse_vert_param(struct tr *tr, const struct tile_ctx *ctx,
|
|||
break;
|
||||
}
|
||||
|
||||
// In the case of the Polygon type, the last struct vertex Parameter for an
|
||||
// object
|
||||
// must have "End of Strip" specified. If Vertex Parameters with the "End
|
||||
// of Strip" specification were not input, but parameters other than the
|
||||
// Vertex Parameters were input, the polygon data in question is ignored and
|
||||
// an interrupt signal is output.
|
||||
// FIXME is this true for sprites which come through this path as well?
|
||||
/*
|
||||
* in the case of the Polygon type, the last Vertex Parameter for an object
|
||||
* must have "End of Strip" specified. If Vertex Parameters with the "End of
|
||||
* Strip" specification were not input, but parameters other than the Vertex
|
||||
* Parameters were input, the polygon data in question is ignored and
|
||||
* an interrupt signal is output
|
||||
*/
|
||||
|
||||
/* FIXME is this true for sprites which come through this path as well? */
|
||||
}
|
||||
|
||||
static float tr_cmp_surf(struct render_ctx *rctx, const struct surface *a,
|
||||
static float tr_cmp_surf(struct render_context *rctx, const struct surface *a,
|
||||
const struct surface *b) {
|
||||
float minza = FLT_MAX;
|
||||
for (int i = 0, n = a->num_verts; i < n; i++) {
|
||||
|
@ -819,7 +840,7 @@ static float tr_cmp_surf(struct render_ctx *rctx, const struct surface *a,
|
|||
return minza - minzb;
|
||||
}
|
||||
|
||||
static void tr_merge_surfs(struct render_ctx *rctx, int *low, int *mid,
|
||||
static void tr_merge_surfs(struct render_context *rctx, int *low, int *mid,
|
||||
int *high) {
|
||||
static int tmp[16384];
|
||||
|
||||
|
@ -850,7 +871,7 @@ static void tr_merge_surfs(struct render_ctx *rctx, int *low, int *mid,
|
|||
memcpy(low, tmp, (k - tmp) * sizeof(tmp[0]));
|
||||
}
|
||||
|
||||
static void tr_sort_surfs(struct render_ctx *rctx, int low, int high) {
|
||||
static void tr_sort_surfs(struct render_context *rctx, int low, int high) {
|
||||
if (low >= high) {
|
||||
return;
|
||||
}
|
||||
|
@ -863,11 +884,13 @@ static void tr_sort_surfs(struct render_ctx *rctx, int low, int high) {
|
|||
}
|
||||
|
||||
static void tr_parse_eol(struct tr *tr, const struct tile_ctx *ctx,
|
||||
struct render_ctx *rctx, const uint8_t *data) {
|
||||
struct render_context *rctx, const uint8_t *data) {
|
||||
tr_discard_incomplete_surf(tr, rctx);
|
||||
|
||||
// sort transparent polys by their z value, from back to front. remember, in
|
||||
// dreamcast coordinates smaller z values are further away from the camera
|
||||
/*
|
||||
* sort transparent polys by their z value, from back to front. remember, in
|
||||
* dreamcast coordinates smaller z values are further away from the camera
|
||||
*/
|
||||
if ((tr->list_type == TA_LIST_TRANSLUCENT ||
|
||||
tr->list_type == TA_LIST_TRANSLUCENT_MODVOL) &&
|
||||
ctx->autosort) {
|
||||
|
@ -879,18 +902,20 @@ static void tr_parse_eol(struct tr *tr, const struct tile_ctx *ctx,
|
|||
tr->last_sorted_surf = rctx->num_surfs;
|
||||
}
|
||||
|
||||
// Vertices coming into the TA are in window space, with the Z component being
|
||||
// 1/W. These coordinates need to be converted back to clip space in order to
|
||||
// be rendered with OpenGL, etc. While we want to perform an orthographic
|
||||
// projection on the vertices as they're already perspective correct, the
|
||||
// renderer backend will have to deal with setting the W component of each
|
||||
// in order to perspective correct the texture mapping.
|
||||
/*
|
||||
* vertices coming into the TA are in window space, with the Z component being
|
||||
* 1/W. these coordinates need to be converted back to clip space in order to
|
||||
* be rendered with OpenGL, etc. while we want to perform an orthographic
|
||||
* projection on the vertices as they're already perspective correct, the
|
||||
* renderer backend will have to deal with setting the W component of each
|
||||
* in order to perspective correct the texture mapping
|
||||
*/
|
||||
static void tr_proj_mat(struct tr *tr, const struct tile_ctx *ctx,
|
||||
struct render_ctx *rctx) {
|
||||
struct render_context *rctx) {
|
||||
float znear = FLT_MIN;
|
||||
float zfar = FLT_MAX;
|
||||
|
||||
// Z component is 1/W, so +Z is into the screen
|
||||
/* Z component is 1/W, so +Z is into the screen */
|
||||
for (int i = 0; i < rctx->num_verts; i++) {
|
||||
struct vertex *v = &rctx->verts[i];
|
||||
if (v->xyz[2] > znear) {
|
||||
|
@ -901,15 +926,15 @@ static void tr_proj_mat(struct tr *tr, const struct tile_ctx *ctx,
|
|||
}
|
||||
}
|
||||
|
||||
// fudge so Z isn't being mapped to exactly 0.0 and 1.0
|
||||
/* fudge so Z isn't being mapped to exactly 0.0 and 1.0 */
|
||||
float zdepth = (znear - zfar) * 1.1f;
|
||||
|
||||
// fix case where a single polygon being renderered
|
||||
/* fix case where a single polygon being renderered */
|
||||
if (zdepth <= 0.0f) {
|
||||
zdepth = 1.0f;
|
||||
}
|
||||
|
||||
// convert from window space coordinates into clip space
|
||||
/* convert from window space coordinates into clip space */
|
||||
rctx->projection[0] = 2.0f / (float)ctx->video_width;
|
||||
rctx->projection[4] = 0.0f;
|
||||
rctx->projection[8] = 0.0f;
|
||||
|
@ -931,13 +956,13 @@ static void tr_proj_mat(struct tr *tr, const struct tile_ctx *ctx,
|
|||
rctx->projection[15] = 1.0f;
|
||||
}
|
||||
|
||||
static void tr_reset(struct tr *tr, struct render_ctx *rctx) {
|
||||
// reset render state
|
||||
static void tr_reset(struct tr *tr, struct render_context *rctx) {
|
||||
/* reset render state */
|
||||
rctx->num_surfs = 0;
|
||||
rctx->num_verts = 0;
|
||||
rctx->num_states = 0;
|
||||
|
||||
// reset global state
|
||||
/* reset global state */
|
||||
tr->last_poly = NULL;
|
||||
tr->last_vertex = NULL;
|
||||
tr->list_type = 0;
|
||||
|
@ -945,8 +970,10 @@ static void tr_reset(struct tr *tr, struct render_ctx *rctx) {
|
|||
tr->last_sorted_surf = 0;
|
||||
}
|
||||
|
||||
static void tr_parse_context_inner(struct tr *tr, const struct tile_ctx *ctx,
|
||||
int frame, struct render_ctx *rctx) {
|
||||
void tr_parse_context(struct tr *tr, const struct tile_ctx *ctx, int frame,
|
||||
struct render_context *rctx) {
|
||||
PROF_ENTER("gpu", "tr_parse_context");
|
||||
|
||||
const uint8_t *data = ctx->params;
|
||||
const uint8_t *end = ctx->params + ctx->size;
|
||||
|
||||
|
@ -957,26 +984,28 @@ static void tr_parse_context_inner(struct tr *tr, const struct tile_ctx *ctx,
|
|||
while (data < end) {
|
||||
union pcw pcw = *(union pcw *)data;
|
||||
|
||||
// FIXME
|
||||
// If Vertex Parameters with the "End of Strip" specification were not
|
||||
// input, but parameters other than the Vertex Parameters were input, the
|
||||
// polygon data in question is ignored and an interrupt signal is output.
|
||||
/*
|
||||
* FIXME
|
||||
* if Vertex Parameters with the "End of Strip" specification were not
|
||||
* input, but parameters other than the Vertex Parameters were input, the
|
||||
* polygon data in question is ignored and an interrupt signal is output
|
||||
*/
|
||||
|
||||
switch (pcw.para_type) {
|
||||
// control params
|
||||
/* control params */
|
||||
case TA_PARAM_END_OF_LIST:
|
||||
tr_parse_eol(tr, ctx, rctx, data);
|
||||
break;
|
||||
|
||||
case TA_PARAM_USER_TILE_CLIP:
|
||||
// nothing to do
|
||||
/* nothing to do */
|
||||
break;
|
||||
|
||||
case TA_PARAM_OBJ_LIST_SET:
|
||||
LOG_FATAL("TA_PARAM_OBJ_LIST_SET unsupported");
|
||||
break;
|
||||
|
||||
// global params
|
||||
/* global params */
|
||||
case TA_PARAM_POLY_OR_VOL:
|
||||
tr_parse_poly_param(tr, ctx, frame, rctx, data);
|
||||
break;
|
||||
|
@ -985,7 +1014,7 @@ static void tr_parse_context_inner(struct tr *tr, const struct tile_ctx *ctx,
|
|||
tr_parse_poly_param(tr, ctx, frame, rctx, data);
|
||||
break;
|
||||
|
||||
// vertex params
|
||||
/* vertex params */
|
||||
case TA_PARAM_VERTEX:
|
||||
tr_parse_vert_param(tr, ctx, rctx, data);
|
||||
break;
|
||||
|
@ -995,7 +1024,7 @@ static void tr_parse_context_inner(struct tr *tr, const struct tile_ctx *ctx,
|
|||
break;
|
||||
}
|
||||
|
||||
// keep track of the surf / vert counts at each parameter offset
|
||||
/* keep track of the surf / vert counts at each parameter offset */
|
||||
if (rctx->states) {
|
||||
int offset = (int)(data - ctx->params);
|
||||
CHECK_LT(offset, rctx->states_size);
|
||||
|
@ -1010,39 +1039,32 @@ static void tr_parse_context_inner(struct tr *tr, const struct tile_ctx *ctx,
|
|||
}
|
||||
|
||||
tr_proj_mat(tr, ctx, rctx);
|
||||
}
|
||||
|
||||
void tr_parse_context(struct tr *tr, const struct tile_ctx *ctx, int frame,
|
||||
struct render_ctx *rctx) {
|
||||
PROF_ENTER("gpu", "tr_parse_context");
|
||||
|
||||
tr_parse_context_inner(tr, ctx, frame, rctx);
|
||||
|
||||
PROF_LEAVE();
|
||||
}
|
||||
|
||||
static void tr_render_context_inner(struct tr *tr,
|
||||
const struct render_ctx *ctx) {
|
||||
video_begin_surfaces(tr->video, ctx->projection, ctx->verts, ctx->num_verts);
|
||||
void tr_render_context(struct tr *tr, const struct render_context *rctx) {
|
||||
PROF_ENTER("gpu", "tr_render_context");
|
||||
|
||||
const int *sorted_surf = ctx->sorted_surfs;
|
||||
const int *sorted_surf_end = ctx->sorted_surfs + ctx->num_surfs;
|
||||
video_begin_surfaces(tr->video, rctx->projection, rctx->verts,
|
||||
rctx->num_verts);
|
||||
|
||||
const int *sorted_surf = rctx->sorted_surfs;
|
||||
const int *sorted_surf_end = rctx->sorted_surfs + rctx->num_surfs;
|
||||
while (sorted_surf < sorted_surf_end) {
|
||||
video_draw_surface(tr->video, &ctx->surfs[*sorted_surf]);
|
||||
video_draw_surface(tr->video, &rctx->surfs[*sorted_surf]);
|
||||
sorted_surf++;
|
||||
}
|
||||
|
||||
video_end_surfaces(tr->video);
|
||||
}
|
||||
|
||||
void tr_render_context(struct tr *tr, const struct render_ctx *ctx) {
|
||||
PROF_ENTER("gpu", "tr_render_context");
|
||||
|
||||
tr_render_context_inner(tr, ctx);
|
||||
|
||||
PROF_LEAVE();
|
||||
}
|
||||
|
||||
void tr_destroy(struct tr *tr) {
|
||||
free(tr);
|
||||
}
|
||||
|
||||
struct tr *tr_create(struct video_backend *video,
|
||||
struct texture_provider *provider) {
|
||||
struct tr *tr = calloc(1, sizeof(struct tr));
|
||||
|
@ -1052,7 +1074,3 @@ struct tr *tr_create(struct video_backend *video,
|
|||
|
||||
return tr;
|
||||
}
|
||||
|
||||
void tr_destroy(struct tr *tr) {
|
||||
free(tr);
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ struct texture_entry {
|
|||
union tsp tsp;
|
||||
union tcw tcw;
|
||||
|
||||
// source info
|
||||
/* source info */
|
||||
int frame;
|
||||
int dirty;
|
||||
const uint8_t *texture;
|
||||
|
@ -21,7 +21,7 @@ struct texture_entry {
|
|||
const uint8_t *palette;
|
||||
int palette_size;
|
||||
|
||||
// backend info
|
||||
/* backend info */
|
||||
enum pxl_format format;
|
||||
enum filter_mode filter;
|
||||
enum wrap_mode wrap_u;
|
||||
|
@ -32,24 +32,28 @@ struct texture_entry {
|
|||
texture_handle_t handle;
|
||||
};
|
||||
|
||||
// provides abstraction around providing texture data to the renderer. when
|
||||
// emulating the actual ta, textures will be provided from guest memory, but
|
||||
// when playing back traces the textures will come from the trace itself
|
||||
/*
|
||||
* provides abstraction around providing texture data to the renderer. when
|
||||
* emulating the actual ta, textures will be provided from guest memory, but
|
||||
* when playing back traces the textures will come from the trace itself
|
||||
*/
|
||||
struct texture_provider {
|
||||
void *data;
|
||||
struct texture_entry *(*find_texture)(void *, union tsp, union tcw);
|
||||
};
|
||||
|
||||
// represents the parse state after each ta parameter. used to visually scrub
|
||||
// through the scene parameter by parameter in the tracer
|
||||
/*
|
||||
* represents the parse state after each ta parameter. used to visually scrub
|
||||
* through the scene parameter by parameter in the tracer
|
||||
*/
|
||||
struct param_state {
|
||||
int num_surfs;
|
||||
int num_verts;
|
||||
};
|
||||
|
||||
// tile context parsed into appropriate structures for the render backend
|
||||
struct render_ctx {
|
||||
// supplied by caller
|
||||
/* tile context parsed into appropriate structures for the video backend */
|
||||
struct render_context {
|
||||
/* supplied by caller */
|
||||
struct surface *surfs;
|
||||
int surfs_size;
|
||||
|
||||
|
@ -62,7 +66,7 @@ struct render_ctx {
|
|||
struct param_state *states;
|
||||
int states_size;
|
||||
|
||||
//
|
||||
/* */
|
||||
float projection[16];
|
||||
int num_surfs;
|
||||
int num_verts;
|
||||
|
@ -73,12 +77,12 @@ static inline texture_key_t tr_texture_key(union tsp tsp, union tcw tcw) {
|
|||
return ((uint64_t)tsp.full << 32) | tcw.full;
|
||||
}
|
||||
|
||||
void tr_parse_context(struct tr *tr, const struct tile_ctx *ctx, int frame,
|
||||
struct render_ctx *rctx);
|
||||
void tr_render_context(struct tr *tr, const struct render_ctx *rctx);
|
||||
|
||||
struct tr *tr_create(struct video_backend *video,
|
||||
struct texture_provider *provider);
|
||||
void tr_destroy(struct tr *tr);
|
||||
|
||||
void tr_parse_context(struct tr *tr, const struct tile_ctx *ctx, int frame,
|
||||
struct render_context *rctx);
|
||||
void tr_render_context(struct tr *tr, const struct render_context *rctx);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -100,7 +100,7 @@ struct sh4 *sh4_create(struct dreamcast *dc) {
|
|||
struct sh4 *sh4 = dc_create_device(dc, sizeof(struct sh4), "sh", &sh4_init);
|
||||
sh4->execute_if = dc_create_execute_interface(&sh4_run, 0);
|
||||
sh4->memory_if = dc_create_memory_interface(dc, &sh4_data_map);
|
||||
sh4->window_if = dc_create_window_interface(NULL, &sh4_debug_menu, NULL);
|
||||
sh4->window_if = dc_create_window_interface(&sh4_debug_menu, NULL);
|
||||
|
||||
return sh4;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue