mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-08-04 11:17:14 -04:00
N64 optimised, stage 3
This commit is contained in:
parent
eba646cebb
commit
1f395b9a6c
271
misc/n64/gpu.c
271
misc/n64/gpu.c
@ -1,4 +1,3 @@
|
|||||||
#include "GL/gl.h"
|
|
||||||
#include "rspq.h"
|
#include "rspq.h"
|
||||||
#include "rdpq.h"
|
#include "rdpq.h"
|
||||||
#include "rdpq_rect.h"
|
#include "rdpq_rect.h"
|
||||||
@ -6,14 +5,11 @@
|
|||||||
#include "rdpq_debug.h"
|
#include "rdpq_debug.h"
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
#include "rdp.h"
|
#include "rdp.h"
|
||||||
#include <string.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include <malloc.h>
|
|
||||||
#include "gl_constants.h"
|
#include "gl_constants.h"
|
||||||
|
|
||||||
// This is a severely cutdown version of libdragon's OpenGL implementation
|
// This is a severely cutdown version of libdragon's OpenGL implementation
|
||||||
|
|
||||||
static uint32_t glp_id;
|
static uint32_t gpup_id;
|
||||||
//DEFINE_RSP_UCODE(rsp_gpu);
|
//DEFINE_RSP_UCODE(rsp_gpu);
|
||||||
extern uint8_t _binary_build_n64_rsp_gpu_text_bin_start[];
|
extern uint8_t _binary_build_n64_rsp_gpu_text_bin_start[];
|
||||||
extern uint8_t _binary_build_n64_rsp_gpu_data_bin_start[];
|
extern uint8_t _binary_build_n64_rsp_gpu_data_bin_start[];
|
||||||
@ -46,23 +42,16 @@ enum {
|
|||||||
GPU_CMD_PRE_INIT_PIPE = 0x8,
|
GPU_CMD_PRE_INIT_PIPE = 0x8,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
|
||||||
ATTRIB_VERTEX,
|
|
||||||
ATTRIB_COLOR,
|
|
||||||
ATTRIB_TEXCOORD,
|
|
||||||
ATTRIB_COUNT
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GLfloat scale[3];
|
float scale[3];
|
||||||
GLfloat offset[3];
|
float offset[3];
|
||||||
} gl_viewport_t;
|
} gpu_viewport_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int16_t i[4][4];
|
int16_t i[4][4];
|
||||||
uint16_t f[4][4];
|
uint16_t f[4][4];
|
||||||
} gl_matrix_srv_t;
|
} gpu_matrix_srv_t;
|
||||||
_Static_assert(sizeof(gl_matrix_srv_t) == MATRIX_SIZE, "Matrix size does not match");
|
_Static_assert(sizeof(gpu_matrix_srv_t) == MATRIX_SIZE, "Matrix size does not match");
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
rspq_write_t w;
|
rspq_write_t w;
|
||||||
@ -71,16 +60,10 @@ typedef struct {
|
|||||||
uint32_t word;
|
uint32_t word;
|
||||||
};
|
};
|
||||||
uint32_t buffer_head;
|
uint32_t buffer_head;
|
||||||
} gl_cmd_stream_t;
|
} gpu_cmd_stream_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GLsizei stride;
|
gpu_matrix_srv_t mvp_matrix;
|
||||||
const GLvoid *pointer;
|
|
||||||
bool enabled;
|
|
||||||
} gl_array_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
gl_matrix_srv_t mvp_matrix;
|
|
||||||
int16_t viewport_scale[4];
|
int16_t viewport_scale[4];
|
||||||
int16_t viewport_offset[4];
|
int16_t viewport_offset[4];
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
@ -88,134 +71,111 @@ typedef struct {
|
|||||||
uint16_t tex_offset[2];
|
uint16_t tex_offset[2];
|
||||||
uint16_t tri_cmd;
|
uint16_t tri_cmd;
|
||||||
uint16_t tri_cull;
|
uint16_t tri_cull;
|
||||||
} __attribute__((aligned(8), packed)) gl_server_state_t;
|
} __attribute__((aligned(8), packed)) gpu_state;
|
||||||
|
|
||||||
static inline const void *gl_get_attrib_element(const gl_array_t *src, uint32_t index)
|
static inline gpu_cmd_stream_t gpu_cmd_stream_begin(uint32_t ovl_id, uint32_t cmd_id, int size)
|
||||||
{
|
{
|
||||||
return src->pointer + index * src->stride;
|
return (gpu_cmd_stream_t) {
|
||||||
}
|
|
||||||
|
|
||||||
static inline gl_cmd_stream_t gl_cmd_stream_begin(uint32_t ovl_id, uint32_t cmd_id, int size)
|
|
||||||
{
|
|
||||||
return (gl_cmd_stream_t) {
|
|
||||||
.w = rspq_write_begin(ovl_id, cmd_id, size),
|
.w = rspq_write_begin(ovl_id, cmd_id, size),
|
||||||
.buffer_head = 2,
|
.buffer_head = 2,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void gl_cmd_stream_commit(gl_cmd_stream_t *s)
|
static inline void gpu_cmd_stream_commit(gpu_cmd_stream_t *s)
|
||||||
{
|
{
|
||||||
rspq_write_arg(&s->w, s->word);
|
rspq_write_arg(&s->w, s->word);
|
||||||
s->buffer_head = 0;
|
s->buffer_head = 0;
|
||||||
s->word = 0;
|
s->word = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void gl_cmd_stream_put_half(gl_cmd_stream_t *s, uint16_t v)
|
static inline void gpu_cmd_stream_put_half(gpu_cmd_stream_t *s, uint16_t v)
|
||||||
{
|
{
|
||||||
s->bytes[s->buffer_head++] = v >> 8;
|
s->bytes[s->buffer_head++] = v >> 8;
|
||||||
s->bytes[s->buffer_head++] = v & 0xFF;
|
s->bytes[s->buffer_head++] = v & 0xFF;
|
||||||
|
|
||||||
if (s->buffer_head == sizeof(uint32_t)) {
|
if (s->buffer_head == sizeof(uint32_t)) {
|
||||||
gl_cmd_stream_commit(s);
|
gpu_cmd_stream_commit(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void gl_cmd_stream_end(gl_cmd_stream_t *s)
|
static inline void gpu_cmd_stream_end(gpu_cmd_stream_t *s)
|
||||||
{
|
{
|
||||||
if (s->buffer_head > 0) {
|
if (s->buffer_head > 0) {
|
||||||
gl_cmd_stream_commit(s);
|
gpu_cmd_stream_commit(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
rspq_write_end(&s->w);
|
rspq_write_end(&s->w);
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((always_inline))
|
__attribute__((always_inline))
|
||||||
static inline void gl_set_flag_raw(uint32_t offset, uint32_t flag, bool value)
|
static inline void gpu_set_flag_raw(uint32_t offset, uint32_t flag, bool value)
|
||||||
{
|
{
|
||||||
rspq_write(glp_id, GPU_CMD_SET_FLAG, offset | value, value ? flag : ~flag);
|
rspq_write(gpup_id, GPU_CMD_SET_FLAG, offset | value, value ? flag : ~flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((always_inline))
|
__attribute__((always_inline))
|
||||||
static inline void gl_set_flag(uint32_t flag, bool value)
|
static inline void gpu_set_flag(uint32_t flag, bool value)
|
||||||
{
|
{
|
||||||
gl_set_flag_raw(offsetof(gl_server_state_t, flags), flag, value);
|
gpu_set_flag_raw(offsetof(gpu_state, flags), flag, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((always_inline))
|
__attribute__((always_inline))
|
||||||
static inline void gl_set_byte(uint32_t offset, uint8_t value)
|
static inline void gpu_set_byte(uint32_t offset, uint8_t value)
|
||||||
{
|
{
|
||||||
rspq_write(glp_id, GPU_CMD_SET_BYTE, offset, value);
|
rspq_write(gpup_id, GPU_CMD_SET_BYTE, offset, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((always_inline))
|
__attribute__((always_inline))
|
||||||
static inline void gl_set_short(uint32_t offset, uint16_t value)
|
static inline void gpu_set_short(uint32_t offset, uint16_t value)
|
||||||
{
|
{
|
||||||
rspq_write(glp_id, GPU_CMD_SET_SHORT, offset, value);
|
rspq_write(gpup_id, GPU_CMD_SET_SHORT, offset, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((always_inline))
|
__attribute__((always_inline))
|
||||||
static inline void gl_set_word(uint32_t offset, uint32_t value)
|
static inline void gpu_set_word(uint32_t offset, uint32_t value)
|
||||||
{
|
{
|
||||||
rspq_write(glp_id, GPU_CMD_SET_WORD, offset, value);
|
rspq_write(gpup_id, GPU_CMD_SET_WORD, offset, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((always_inline))
|
__attribute__((always_inline))
|
||||||
static inline void gl_set_long(uint32_t offset, uint64_t value)
|
static inline void gpu_set_long(uint32_t offset, uint64_t value)
|
||||||
{
|
{
|
||||||
rspq_write(glp_id, GPU_CMD_SET_LONG, offset, value >> 32, value & 0xFFFFFFFF);
|
rspq_write(gpup_id, GPU_CMD_SET_LONG, offset, value >> 32, value & 0xFFFFFFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void glpipe_draw_triangle(int i0, int i1, int i2)
|
static inline void gpupipe_draw_triangle(int i0, int i1, int i2)
|
||||||
{
|
{
|
||||||
// We pass -1 because the triangle can be clipped and split into multiple
|
// We pass -1 because the triangle can be clipped and split into multiple
|
||||||
// triangles.
|
// triangles.
|
||||||
rdpq_write(-1, glp_id, GPU_CMD_DRAW_TRI,
|
rdpq_write(-1, gpup_id, GPU_CMD_DRAW_TRI,
|
||||||
(i0*PRIM_VTX_SIZE),
|
(i0*PRIM_VTX_SIZE),
|
||||||
((i1*PRIM_VTX_SIZE)<<16) | (i2*PRIM_VTX_SIZE)
|
((i1*PRIM_VTX_SIZE)<<16) | (i2*PRIM_VTX_SIZE)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static gl_viewport_t state_viewport;
|
static gpu_viewport_t state_viewport;
|
||||||
static gl_array_t state_arrays[ATTRIB_COUNT];
|
static bool gpu_texturing;
|
||||||
|
static void* gpu_pointer;
|
||||||
|
static int gpu_stride;
|
||||||
|
|
||||||
void gl_init()
|
#define GPU_ATTR_Z 0
|
||||||
{
|
#define GPU_ATTR_TEX 1
|
||||||
glp_id = rspq_overlay_register(&rsp_gpu);
|
static void gpuSetFlag(int target, bool value)
|
||||||
glDepthRange(0, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gl_close()
|
|
||||||
{
|
|
||||||
rspq_wait();
|
|
||||||
rspq_overlay_unregister(glp_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gl_set_flag2(GLenum target, bool value)
|
|
||||||
{
|
{
|
||||||
switch (target) {
|
switch (target) {
|
||||||
case GL_DEPTH_TEST:
|
case GPU_ATTR_Z:
|
||||||
gl_set_flag(FLAG_DEPTH_TEST, value);
|
gpu_set_flag(FLAG_DEPTH_TEST, value);
|
||||||
break;
|
break;
|
||||||
case GL_TEXTURE_2D:
|
case GPU_ATTR_TEX:
|
||||||
gl_set_flag(FLAG_TEXTURE_ACTIVE, value);
|
gpu_set_flag(FLAG_TEXTURE_ACTIVE, value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void glEnable(GLenum target)
|
static void gpuSetTexSize(uint16_t width, uint16_t height)
|
||||||
{
|
{
|
||||||
gl_set_flag2(target, true);
|
gpu_set_word(offsetof(gpu_state, tex_size[0]), (width << 16) | height);
|
||||||
}
|
|
||||||
|
|
||||||
void glDisable(GLenum target)
|
|
||||||
{
|
|
||||||
gl_set_flag2(target, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void glTexSizeN64(uint16_t width, uint16_t height)
|
|
||||||
{
|
|
||||||
gl_set_word(offsetof(gl_server_state_t, tex_size[0]), (width << 16) | height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -228,7 +188,7 @@ static inline void write_shorts(rspq_write_t *w, const uint16_t *s, uint32_t cou
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void gl_matrix_write(rspq_write_t *w, const GLfloat *m)
|
static inline void gpu_matrix_write(rspq_write_t* w, const float* m)
|
||||||
{
|
{
|
||||||
uint16_t integer[16];
|
uint16_t integer[16];
|
||||||
uint16_t fraction[16];
|
uint16_t fraction[16];
|
||||||
@ -244,125 +204,80 @@ static inline void gl_matrix_write(rspq_write_t *w, const GLfloat *m)
|
|||||||
write_shorts(w, fraction, 16);
|
write_shorts(w, fraction, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
void glLoadMatrixf(const GLfloat *m)
|
static void gpuLoadMatrix(const float* m)
|
||||||
{
|
{
|
||||||
rspq_write_t w = rspq_write_begin(glp_id, GPU_CMD_MATRIX_LOAD, 17);
|
rspq_write_t w = rspq_write_begin(gpup_id, GPU_CMD_MATRIX_LOAD, 17);
|
||||||
rspq_write_arg(&w, false); // no multiply
|
rspq_write_arg(&w, false); // no multiply
|
||||||
gl_matrix_write(&w, m);
|
gpu_matrix_write(&w, m);
|
||||||
rspq_write_end(&w);
|
rspq_write_end(&w);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void upload_vertex(const gl_array_t *arrays, uint32_t index, uint8_t cache_index)
|
static void upload_vertex(uint32_t index, uint8_t cache_index)
|
||||||
{
|
{
|
||||||
gl_cmd_stream_t s = gl_cmd_stream_begin(glp_id, GPU_CMD_UPLOAD_VTX, 6);
|
gpu_cmd_stream_t s = gpu_cmd_stream_begin(gpup_id, GPU_CMD_UPLOAD_VTX, 6);
|
||||||
gl_cmd_stream_put_half(&s, cache_index * PRIM_VTX_SIZE);
|
gpu_cmd_stream_put_half(&s, cache_index * PRIM_VTX_SIZE);
|
||||||
|
char* ptr = gpu_pointer + index * gpu_stride;
|
||||||
|
|
||||||
const float* vtx = gl_get_attrib_element(&arrays[ATTRIB_VERTEX], index);
|
float* vtx = (float*)(ptr + 0);
|
||||||
gl_cmd_stream_put_half(&s, vtx[0] * (1<<VTX_SHIFT));
|
gpu_cmd_stream_put_half(&s, vtx[0] * (1<<VTX_SHIFT));
|
||||||
gl_cmd_stream_put_half(&s, vtx[1] * (1<<VTX_SHIFT));
|
gpu_cmd_stream_put_half(&s, vtx[1] * (1<<VTX_SHIFT));
|
||||||
gl_cmd_stream_put_half(&s, vtx[2] * (1<<VTX_SHIFT));
|
gpu_cmd_stream_put_half(&s, vtx[2] * (1<<VTX_SHIFT));
|
||||||
gl_cmd_stream_put_half(&s, 1.0f * (1<<VTX_SHIFT));
|
gpu_cmd_stream_put_half(&s, 1.0f * (1<<VTX_SHIFT));
|
||||||
|
|
||||||
const uint8_t* col = gl_get_attrib_element(&arrays[ATTRIB_COLOR], index);
|
uint8_t* col = (uint8_t*)(ptr + 12);
|
||||||
gl_cmd_stream_put_half(&s, col[0] << 7); // TODO put_byte ?
|
gpu_cmd_stream_put_half(&s, col[0] << 7); // TODO put_byte ?
|
||||||
gl_cmd_stream_put_half(&s, col[1] << 7); // TODO put_byte ?
|
gpu_cmd_stream_put_half(&s, col[1] << 7); // TODO put_byte ?
|
||||||
gl_cmd_stream_put_half(&s, col[2] << 7); // TODO put_byte ?
|
gpu_cmd_stream_put_half(&s, col[2] << 7); // TODO put_byte ?
|
||||||
gl_cmd_stream_put_half(&s, col[3] << 7); // TODO put_byte ?
|
gpu_cmd_stream_put_half(&s, col[3] << 7); // TODO put_byte ?
|
||||||
|
|
||||||
if (arrays[ATTRIB_TEXCOORD].enabled) {
|
if (gpu_texturing) {
|
||||||
const float* tex = gl_get_attrib_element(&arrays[ATTRIB_TEXCOORD], index);
|
float* tex = (float*)(ptr + 16);
|
||||||
gl_cmd_stream_put_half(&s, tex[0] * (1<<TEX_SHIFT));
|
gpu_cmd_stream_put_half(&s, tex[0] * (1<<TEX_SHIFT));
|
||||||
gl_cmd_stream_put_half(&s, tex[1] * (1<<TEX_SHIFT));
|
gpu_cmd_stream_put_half(&s, tex[1] * (1<<TEX_SHIFT));
|
||||||
} else {
|
} else {
|
||||||
gl_cmd_stream_put_half(&s, 0);
|
gpu_cmd_stream_put_half(&s, 0);
|
||||||
gl_cmd_stream_put_half(&s, 0);
|
gpu_cmd_stream_put_half(&s, 0);
|
||||||
}
|
}
|
||||||
gl_cmd_stream_end(&s);
|
gpu_cmd_stream_end(&s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gl_rsp_draw_arrays(uint32_t first, uint32_t count)
|
static void gpu_rsp_draw_arrays(uint32_t first, uint32_t count)
|
||||||
{
|
{
|
||||||
for (uint32_t i = 0; i < count; i++)
|
for (uint32_t i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
uint8_t cache_index = i % VERTEX_CACHE_SIZE;
|
uint8_t cache_index = i % VERTEX_CACHE_SIZE;
|
||||||
upload_vertex(state_arrays, first + i, cache_index);
|
upload_vertex(first + i, cache_index);
|
||||||
|
|
||||||
// Last vertex of quad?
|
// Last vertex of quad?
|
||||||
if ((i & 3) != 3) continue;
|
if ((i & 3) != 3) continue;
|
||||||
|
|
||||||
// Add two triangles
|
// Add two triangles
|
||||||
uint8_t idx = cache_index - 3;
|
uint8_t idx = cache_index - 3;
|
||||||
glpipe_draw_triangle(idx + 0, idx + 1, idx + 2);
|
gpupipe_draw_triangle(idx + 0, idx + 1, idx + 2);
|
||||||
glpipe_draw_triangle(idx + 0, idx + 2, idx + 3);
|
gpupipe_draw_triangle(idx + 0, idx + 2, idx + 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int gl_array_type_from_enum(GLenum array)
|
static void gpuDrawArrays(int first, int count)
|
||||||
{
|
{
|
||||||
switch (array) {
|
rspq_write(gpup_id, GPU_CMD_PRE_INIT_PIPE);
|
||||||
case GL_VERTEX_ARRAY: return ATTRIB_VERTEX;
|
gpu_rsp_draw_arrays(first, count);
|
||||||
case GL_TEXTURE_COORD_ARRAY: return ATTRIB_TEXCOORD;
|
|
||||||
case GL_COLOR_ARRAY: return ATTRIB_COLOR;
|
|
||||||
default: return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void glVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
|
static void gpuDepthRange(float n, float f)
|
||||||
{
|
|
||||||
gl_array_t *array = &state_arrays[ATTRIB_VERTEX];
|
|
||||||
array->stride = stride;
|
|
||||||
array->pointer = pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
|
|
||||||
{
|
|
||||||
gl_array_t *array = &state_arrays[ATTRIB_TEXCOORD];
|
|
||||||
array->stride = stride;
|
|
||||||
array->pointer = pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void glColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
|
|
||||||
{
|
|
||||||
gl_array_t *array = &state_arrays[ATTRIB_COLOR];
|
|
||||||
array->stride = stride;
|
|
||||||
array->pointer = pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void gl_set_array_enabled(int array_type, bool enabled)
|
|
||||||
{
|
|
||||||
state_arrays[array_type].enabled = enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
void glEnableClientState(GLenum array)
|
|
||||||
{
|
|
||||||
gl_set_array_enabled(gl_array_type_from_enum(array), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void glDisableClientState(GLenum array)
|
|
||||||
{
|
|
||||||
gl_set_array_enabled(gl_array_type_from_enum(array), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void glDrawArrays(GLenum mode, GLint first, GLsizei count)
|
|
||||||
{
|
|
||||||
rspq_write(glp_id, GPU_CMD_PRE_INIT_PIPE);
|
|
||||||
gl_rsp_draw_arrays(first, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
void glDepthRange(GLclampd n, GLclampd f)
|
|
||||||
{
|
{
|
||||||
state_viewport.scale[2] = (f - n) * 0.5f;
|
state_viewport.scale[2] = (f - n) * 0.5f;
|
||||||
state_viewport.offset[2] = n + (f - n) * 0.5f;
|
state_viewport.offset[2] = n + (f - n) * 0.5f;
|
||||||
|
|
||||||
gl_set_short(
|
gpu_set_short(
|
||||||
offsetof(gl_server_state_t, viewport_scale) + sizeof(int16_t) * 2,
|
offsetof(gpu_state, viewport_scale) + sizeof(int16_t) * 2,
|
||||||
state_viewport.scale[2] * 4);
|
state_viewport.scale[2] * 4);
|
||||||
gl_set_short(
|
gpu_set_short(
|
||||||
offsetof(gl_server_state_t, viewport_offset) + sizeof(int16_t) * 2,
|
offsetof(gpu_state, viewport_offset) + sizeof(int16_t) * 2,
|
||||||
state_viewport.offset[2] * 4);
|
state_viewport.offset[2] * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void glViewport(GLint x, GLint y, GLsizei w, GLsizei h)
|
static void gpuViewport(int x, int y, int w, int h)
|
||||||
{
|
{
|
||||||
state_viewport.scale[0] = w * 0.5f;
|
state_viewport.scale[0] = w * 0.5f;
|
||||||
state_viewport.scale[1] = h * -0.5f;
|
state_viewport.scale[1] = h * -0.5f;
|
||||||
@ -382,17 +297,29 @@ void glViewport(GLint x, GLint y, GLsizei w, GLsizei h)
|
|||||||
uint16_t offset_y = state_viewport.offset[1] * SCREEN_XY_SCALE;
|
uint16_t offset_y = state_viewport.offset[1] * SCREEN_XY_SCALE;
|
||||||
uint16_t offset_z = state_viewport.offset[2] * SCREEN_Z_SCALE;
|
uint16_t offset_z = state_viewport.offset[2] * SCREEN_Z_SCALE;
|
||||||
|
|
||||||
gl_set_long(
|
gpu_set_long(
|
||||||
offsetof(gl_server_state_t, viewport_scale),
|
offsetof(gpu_state, viewport_scale),
|
||||||
((uint64_t)scale_x << 48) | ((uint64_t)scale_y << 32) | ((uint64_t)scale_z << 16));
|
((uint64_t)scale_x << 48) | ((uint64_t)scale_y << 32) | ((uint64_t)scale_z << 16));
|
||||||
gl_set_long(
|
gpu_set_long(
|
||||||
offsetof(gl_server_state_t, viewport_offset),
|
offsetof(gpu_state, viewport_offset),
|
||||||
((uint64_t)offset_x << 48) | ((uint64_t)offset_y << 32) | ((uint64_t)offset_z << 16));
|
((uint64_t)offset_x << 48) | ((uint64_t)offset_y << 32) | ((uint64_t)offset_z << 16));
|
||||||
}
|
}
|
||||||
|
|
||||||
void glCullFace(GLenum mode)
|
static void gpuSetCullFace(bool enabled)
|
||||||
{
|
{
|
||||||
// 1 = cull backfaces
|
// 1 = cull backfaces
|
||||||
// 2 = don't cull
|
// 2 = don't cull
|
||||||
gl_set_short(offsetof(gl_server_state_t, tri_cull), mode ? 1 : 2);
|
gpu_set_short(offsetof(gpu_state, tri_cull), enabled ? 1 : 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gpu_init()
|
||||||
|
{
|
||||||
|
gpup_id = rspq_overlay_register(&rsp_gpu);
|
||||||
|
gpuDepthRange(0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gpu_close()
|
||||||
|
{
|
||||||
|
rspq_wait();
|
||||||
|
rspq_overlay_unregister(gpup_id);
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,6 @@
|
|||||||
#include <rspq_profile.h>
|
#include <rspq_profile.h>
|
||||||
#include "../misc/n64/gpu.c"
|
#include "../misc/n64/gpu.c"
|
||||||
|
|
||||||
typedef void (*GL_SetupVBFunc)(void);
|
|
||||||
static GL_SetupVBFunc gfx_setupVBFunc;
|
|
||||||
|
|
||||||
|
|
||||||
/*########################################################################################################################*
|
/*########################################################################################################################*
|
||||||
*---------------------------------------------------------General---------------------------------------------------------*
|
*---------------------------------------------------------General---------------------------------------------------------*
|
||||||
*#########################################################################################################################*/
|
*#########################################################################################################################*/
|
||||||
@ -34,7 +30,7 @@ void Gfx_Create(void) {
|
|||||||
// Set alpha compare threshold
|
// Set alpha compare threshold
|
||||||
rdpq_set_blend_color(RGBA32(0,0,0, 127));
|
rdpq_set_blend_color(RGBA32(0,0,0, 127));
|
||||||
|
|
||||||
gl_init();
|
gpu_init();
|
||||||
zbuffer = surface_alloc(FMT_RGBA16, display_get_width(), display_get_height());
|
zbuffer = surface_alloc(FMT_RGBA16, display_get_width(), display_get_height());
|
||||||
|
|
||||||
Gfx.MaxTexWidth = 256;
|
Gfx.MaxTexWidth = 256;
|
||||||
@ -60,11 +56,9 @@ cc_bool Gfx_TryRestoreContext(void) {
|
|||||||
|
|
||||||
void Gfx_Free(void) {
|
void Gfx_Free(void) {
|
||||||
Gfx_FreeState();
|
Gfx_FreeState();
|
||||||
gl_close();
|
gpu_close();
|
||||||
}
|
}
|
||||||
|
|
||||||
#define gl_Toggle(cap) if (enabled) { glEnable(cap); } else { glDisable(cap); }
|
|
||||||
|
|
||||||
|
|
||||||
/*########################################################################################################################*
|
/*########################################################################################################################*
|
||||||
*-----------------------------------------------------------Misc----------------------------------------------------------*
|
*-----------------------------------------------------------Misc----------------------------------------------------------*
|
||||||
@ -89,7 +83,7 @@ void Gfx_SetVSync(cc_bool vsync) {
|
|||||||
void Gfx_OnWindowResize(void) { }
|
void Gfx_OnWindowResize(void) { }
|
||||||
|
|
||||||
void Gfx_SetViewport(int x, int y, int w, int h) {
|
void Gfx_SetViewport(int x, int y, int w, int h) {
|
||||||
glViewport(x, y, w, h);
|
gpuViewport(x, y, w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gfx_SetScissor(int x, int y, int w, int h) {
|
void Gfx_SetScissor(int x, int y, int w, int h) {
|
||||||
@ -146,7 +140,7 @@ void Gfx_BindTexture(GfxResourceID texId) {
|
|||||||
CCTexture* tex = (CCTexture*)texId;
|
CCTexture* tex = (CCTexture*)texId;
|
||||||
|
|
||||||
rspq_block_run(tex->upload_block);
|
rspq_block_run(tex->upload_block);
|
||||||
glTexSizeN64(tex->surface.width, tex->surface.height);
|
gpuSetTexSize(tex->surface.width, tex->surface.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ALIGNUP8(size) (((size) + 7) & ~0x07)
|
#define ALIGNUP8(size) (((size) + 7) & ~0x07)
|
||||||
@ -207,10 +201,7 @@ GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Gfx_UpdateTexture(GfxResourceID texId, int x, int y, struct Bitmap* part, int rowWidth, cc_bool mipmaps) {
|
void Gfx_UpdateTexture(GfxResourceID texId, int x, int y, struct Bitmap* part, int rowWidth, cc_bool mipmaps) {
|
||||||
// TODO: Just memcpying doesn't actually work. maybe due to glSurfaceTexImageN64 caching the RSQ upload block?
|
|
||||||
// TODO: Is there a more optimised approach than just calling glSurfaceTexImageN64
|
|
||||||
CCTexture* tex = (CCTexture*)texId;
|
CCTexture* tex = (CCTexture*)texId;
|
||||||
|
|
||||||
surface_t* fb = &tex->surface;
|
surface_t* fb = &tex->surface;
|
||||||
cc_uint32* src = (cc_uint32*)part->scan0 + x;
|
cc_uint32* src = (cc_uint32*)part->scan0 + x;
|
||||||
cc_uint8* dst = (cc_uint8*)fb->buffer + (x * 4) + (y * fb->stride);
|
cc_uint8* dst = (cc_uint8*)fb->buffer + (x * 4) + (y * fb->stride);
|
||||||
@ -250,7 +241,7 @@ void Gfx_DisableMipmaps(void) { }
|
|||||||
*-----------------------------------------------------State management----------------------------------------------------*
|
*-----------------------------------------------------State management----------------------------------------------------*
|
||||||
*#########################################################################################################################*/
|
*#########################################################################################################################*/
|
||||||
void Gfx_SetFaceCulling(cc_bool enabled) {
|
void Gfx_SetFaceCulling(cc_bool enabled) {
|
||||||
glCullFace(enabled ? GL_BACK : 0);
|
gpuSetCullFace(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetAlphaBlend(cc_bool enabled) {
|
static void SetAlphaBlend(cc_bool enabled) {
|
||||||
@ -265,7 +256,7 @@ static void SetAlphaTest(cc_bool enabled) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void SetColorWrite(cc_bool r, cc_bool g, cc_bool b, cc_bool a) {
|
static void SetColorWrite(cc_bool r, cc_bool g, cc_bool b, cc_bool a) {
|
||||||
//glColorMask(r, g, b, a); TODO
|
//gpuColorMask(r, g, b, a); TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gfx_SetDepthWrite(cc_bool enabled) {
|
void Gfx_SetDepthWrite(cc_bool enabled) {
|
||||||
@ -275,14 +266,12 @@ void Gfx_SetDepthWrite(cc_bool enabled) {
|
|||||||
void Gfx_SetDepthTest(cc_bool enabled) {
|
void Gfx_SetDepthTest(cc_bool enabled) {
|
||||||
__rdpq_mode_change_som(SOM_Z_COMPARE, enabled ? SOM_Z_COMPARE : 0);
|
__rdpq_mode_change_som(SOM_Z_COMPARE, enabled ? SOM_Z_COMPARE : 0);
|
||||||
|
|
||||||
gl_Toggle(GL_DEPTH_TEST);
|
gpuSetFlag(GPU_ATTR_Z, enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Gfx_FreeState(void) { FreeDefaultResources(); }
|
static void Gfx_FreeState(void) { FreeDefaultResources(); }
|
||||||
static void Gfx_RestoreState(void) {
|
static void Gfx_RestoreState(void) {
|
||||||
InitDefaultResources();
|
InitDefaultResources();
|
||||||
glEnableClientState(GL_VERTEX_ARRAY);
|
|
||||||
glEnableClientState(GL_COLOR_ARRAY);
|
|
||||||
gfx_format = -1;
|
gfx_format = -1;
|
||||||
|
|
||||||
// 1x1 dummy white texture
|
// 1x1 dummy white texture
|
||||||
@ -379,8 +368,8 @@ static rspq_block_t* VB_GetCached(struct VertexBuffer* vb, int offset, int count
|
|||||||
if (vb->cache.blocks[i]) continue;
|
if (vb->cache.blocks[i]) continue;
|
||||||
|
|
||||||
rspq_block_begin();
|
rspq_block_begin();
|
||||||
gfx_setupVBFunc();
|
gpu_pointer = gfx_vb->vertices;
|
||||||
glDrawArrays(GL_QUADS, offset, count);
|
gpuDrawArrays(offset, count);
|
||||||
rspq_block_t* block = rspq_block_end();
|
rspq_block_t* block = rspq_block_end();
|
||||||
|
|
||||||
vb->cache.blocks[i] = block;
|
vb->cache.blocks[i] = block;
|
||||||
@ -469,9 +458,10 @@ void Gfx_SetFogMode(FogFunc func) {
|
|||||||
void Gfx_DepthOnlyRendering(cc_bool depthOnly) {
|
void Gfx_DepthOnlyRendering(cc_bool depthOnly) {
|
||||||
depthOnlyRendering = depthOnly; // TODO: Better approach? maybe using glBlendFunc instead?
|
depthOnlyRendering = depthOnly; // TODO: Better approach? maybe using glBlendFunc instead?
|
||||||
cc_bool enabled = !depthOnly;
|
cc_bool enabled = !depthOnly;
|
||||||
|
|
||||||
//SetColorWrite(enabled & gfx_colorMask[0], enabled & gfx_colorMask[1],
|
//SetColorWrite(enabled & gfx_colorMask[0], enabled & gfx_colorMask[1],
|
||||||
// enabled & gfx_colorMask[2], enabled & gfx_colorMask[3]);
|
// enabled & gfx_colorMask[2], enabled & gfx_colorMask[3]);
|
||||||
if (enabled) { glEnable(GL_TEXTURE_2D); } else { glDisable(GL_TEXTURE_2D); }
|
gpuSetFlag(GPU_ATTR_TEX, enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -486,7 +476,7 @@ void Gfx_LoadMatrix(MatrixType type, const struct Matrix* matrix) {
|
|||||||
|
|
||||||
struct Matrix mvp __attribute__((aligned(64)));
|
struct Matrix mvp __attribute__((aligned(64)));
|
||||||
Matrix_Mul(&mvp, &_view, &_proj);
|
Matrix_Mul(&mvp, &_view, &_proj);
|
||||||
glLoadMatrixf((const float*)&mvp);
|
gpuLoadMatrix((const float*)&mvp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gfx_LoadMVP(const struct Matrix* view, const struct Matrix* proj, struct Matrix* mvp) {
|
void Gfx_LoadMVP(const struct Matrix* view, const struct Matrix* proj, struct Matrix* mvp) {
|
||||||
@ -494,7 +484,7 @@ void Gfx_LoadMVP(const struct Matrix* view, const struct Matrix* proj, struct Ma
|
|||||||
_view = *view;
|
_view = *view;
|
||||||
|
|
||||||
Matrix_Mul(mvp, view, proj);
|
Matrix_Mul(mvp, view, proj);
|
||||||
glLoadMatrixf((const float*)mvp);
|
gpuLoadMatrix((const float*)mvp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gfx_EnableTextureOffset(float x, float y) {
|
void Gfx_EnableTextureOffset(float x, float y) {
|
||||||
@ -507,35 +497,20 @@ void Gfx_DisableTextureOffset(void) { }
|
|||||||
/*########################################################################################################################*
|
/*########################################################################################################################*
|
||||||
*--------------------------------------------------------Rendering--------------------------------------------------------*
|
*--------------------------------------------------------Rendering--------------------------------------------------------*
|
||||||
*#########################################################################################################################*/
|
*#########################################################################################################################*/
|
||||||
static void GL_SetupVbColoured(void) {
|
|
||||||
glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_COLOURED, (void*)(gfx_vb->vertices + 0));
|
|
||||||
glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_COLOURED, (void*)(gfx_vb->vertices + 12));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void GL_SetupVbTextured(void) {
|
|
||||||
glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (void*)(gfx_vb->vertices + 0));
|
|
||||||
glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_TEXTURED, (void*)(gfx_vb->vertices + 12));
|
|
||||||
glTexCoordPointer(2, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (void*)(gfx_vb->vertices + 16));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Gfx_SetVertexFormat(VertexFormat fmt) {
|
void Gfx_SetVertexFormat(VertexFormat fmt) {
|
||||||
if (fmt == gfx_format) return;
|
if (fmt == gfx_format) return;
|
||||||
gfx_format = fmt;
|
gfx_format = fmt;
|
||||||
gfx_stride = strideSizes[fmt];
|
gfx_stride = strideSizes[fmt];
|
||||||
|
gpu_stride = gfx_stride;
|
||||||
|
|
||||||
if (fmt == VERTEX_FORMAT_TEXTURED) {
|
if (fmt == VERTEX_FORMAT_TEXTURED) {
|
||||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
|
||||||
|
|
||||||
gfx_setupVBFunc = GL_SetupVbTextured;
|
|
||||||
rdpq_mode_combiner(RDPQ_COMBINER_TEX_SHADE);
|
rdpq_mode_combiner(RDPQ_COMBINER_TEX_SHADE);
|
||||||
} else {
|
} else {
|
||||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
||||||
glDisable(GL_TEXTURE_2D);
|
|
||||||
|
|
||||||
gfx_setupVBFunc = GL_SetupVbColoured;
|
|
||||||
rdpq_mode_combiner(RDPQ_COMBINER_SHADE);
|
rdpq_mode_combiner(RDPQ_COMBINER_SHADE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gpu_texturing = fmt == VERTEX_FORMAT_TEXTURED;
|
||||||
|
gpuSetFlag(GPU_ATTR_TEX, gpu_texturing);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gfx_DrawVb_Lines(int verticesCount) {
|
void Gfx_DrawVb_Lines(int verticesCount) {
|
||||||
@ -547,8 +522,8 @@ void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex, DrawHints
|
|||||||
if (block) {
|
if (block) {
|
||||||
rspq_block_run(block);
|
rspq_block_run(block);
|
||||||
} else {
|
} else {
|
||||||
gfx_setupVBFunc();
|
gpu_pointer = gfx_vb->vertices;
|
||||||
glDrawArrays(GL_QUADS, startVertex, verticesCount);
|
gpuDrawArrays(startVertex, verticesCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -558,8 +533,8 @@ void Gfx_DrawVb_IndexedTris(int verticesCount) {
|
|||||||
if (block) {
|
if (block) {
|
||||||
rspq_block_run(block);
|
rspq_block_run(block);
|
||||||
} else {
|
} else {
|
||||||
gfx_setupVBFunc();
|
gpu_pointer = gfx_vb->vertices;
|
||||||
glDrawArrays(GL_QUADS, 0, verticesCount);
|
gpuDrawArrays(0, verticesCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -570,10 +545,8 @@ void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) {
|
|||||||
if (block) {
|
if (block) {
|
||||||
rspq_block_run(block);
|
rspq_block_run(block);
|
||||||
} else {
|
} else {
|
||||||
glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (void*)(gfx_vb->vertices));
|
gpu_pointer = gfx_vb->vertices;
|
||||||
glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_TEXTURED, (void*)(gfx_vb->vertices + 12));
|
gpuDrawArrays(startVertex, verticesCount);
|
||||||
glTexCoordPointer(2, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (void*)(gfx_vb->vertices + 16));
|
|
||||||
glDrawArrays(GL_QUADS, startVertex, verticesCount);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user