Begin experimental new renderig code

This commit is contained in:
Luke Benstead 2018-05-05 20:38:55 +01:00
parent 493c078b19
commit 1356ae352c
6 changed files with 615 additions and 0 deletions

109
containers/aligned_vector.h Normal file
View File

@ -0,0 +1,109 @@
#ifndef ALIGNED_VECTOR_H
#define ALIGNED_VECTOR_H
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <math.h>
#define ALIGNED_VECTOR_INITIAL_CAPACITY 256
typedef struct {
unsigned int size;
unsigned int capacity;
unsigned char* data;
unsigned int element_size;
} AlignedVector;
inline void aligned_vector_reserve(AlignedVector* vector, unsigned int element_count);
inline void aligned_vector_resize(AlignedVector* vector, const unsigned int element_count);
inline void aligned_vector_init(AlignedVector* vector, unsigned int element_size) {
vector->size = vector->capacity = 0;
vector->element_size = element_size;
vector->data = NULL;
/* Reserve some initial capacity */
aligned_vector_reserve(vector, ALIGNED_VECTOR_INITIAL_CAPACITY);
}
inline void aligned_vector_reserve(AlignedVector* vector, unsigned int element_count) {
if(element_count <= vector->capacity) {
return;
}
unsigned int original_byte_size = vector->size * vector->element_size;
unsigned int new_byte_size = element_count * vector->element_size;
unsigned char* original_data = vector->data;
vector->data = (unsigned char*) memalign(0x20, new_byte_size);
if(original_data) {
memcpy(vector->data, original_data, original_byte_size);
free(original_data);
}
vector->capacity = element_count;
}
inline void aligned_vector_push_back(AlignedVector* vector, const void* objs, unsigned int count) {
/* Resize enough room */
unsigned int initial_size = vector->size;
aligned_vector_resize(vector, vector->size + count);
unsigned char* dest = vector->data + (vector->element_size * initial_size);
/* Copy the objects in */
memcpy(dest, objs, vector->element_size * count);
}
inline void aligned_vector_resize(AlignedVector* vector, const unsigned int element_count) {
/* Don't change memory when resizing downwards, just change the size */
if(element_count <= vector->size) {
vector->size = element_count;
return;
}
if(vector->capacity < element_count) {
/* Reserve more than we need so that a subsequent push_back doesn't trigger yet another
* resize */
aligned_vector_reserve(vector, (int) ceil(((float)element_count) * 1.5f));
}
vector->size = element_count;
}
inline void* aligned_vector_at(AlignedVector* vector, const unsigned int index) {
return &vector->data[index * vector->element_size];
}
inline void aligned_vector_clear(AlignedVector* vector) {
vector->size = 0;
}
inline void aligned_vector_shrink_to_fit(AlignedVector* vector) {
if(vector->size == 0) {
free(vector->data);
vector->data = NULL;
vector->capacity = 0;
} else {
unsigned int new_byte_size = vector->size * vector->element_size;
unsigned char* original_data = vector->data;
vector->data = (unsigned char*) memalign(0x20, new_byte_size);
if(original_data) {
memcpy(vector->data, original_data, new_byte_size);
free(original_data);
}
vector->capacity = vector->size;
}
}
void aligned_vector_cleanup(AlignedVector* vector) {
aligned_vector_clear(vector);
aligned_vector_shrink_to_fit(vector);
}
#endif // ALIGNED_VECTOR_H

212
experimental/draw.c Normal file
View File

@ -0,0 +1,212 @@
#include "../include/gl.h"
#include "private.h"
typedef struct {
void* ptr;
GLenum type;
GLsizei stride;
GLint size;
} AttribPointer;
static AttribPointer VERTEX_POINTER;
static AttribPointer UV_POINTER;
static AttribPointer ST_POINTER;
static AttribPointer NORMAL_POINTER;
static AttribPointer DIFFUSE_POINTER;
#define VERTEX_ENABLED_FLAG (1 << 0)
#define UV_ENABLED_FLAG (1 << 1)
#define ST_ENABLED_FLAG (1 << 2)
#define DIFFUSE_ENABLED_FLAG (1 << 3)
#define NORMAL_ENABLED_FLAG (1 << 4)
static GLuint ENABLED_VERTEX_ATTRIBUTES = 0;
static GLubyte ACTIVE_CLIENT_TEXTURE = 0;
void initAttributePointers() {
VERTEX_POINTER.ptr = NULL;
VERTEX_POINTER.stride = 0;
VERTEX_POINTER.type = GL_FLOAT;
VERTEX_POINTER.size = 4;
}
static GLuint byte_size(GLenum type) {
switch(type) {
case GL_BYTE: return sizeof(GLbyte);
case GL_UNSIGNED_BYTE: return sizeof(GLubyte);
case GL_SHORT: return sizeof(GLshort);
case GL_UNSIGNED_SHORT: return sizeof(GLushort);
case GL_INT: return sizeof(GLint);
case GL_UNSIGNED_INT: return sizeof(GLuint);
case GL_DOUBLE: return sizeof(GLdouble);
default: return sizeof(GLfloat);
}
}
static void transformVertex(const GLfloat* src) {
register float __x __asm__("fr12");
register float __y __asm__("fr13");
register float __z __asm__("fr14");
__x = src[0];
__y = src[1];
__z = src[2];
mat_trans_fv12()
src[0] = __x;
src[1] = __y;
src[2] = __z;
}
static void _parseFloats(GLfloat* out, const GLubyte* in, GLint size, GLenum type) {
switch(type) {
case GL_SHORT: {
GLshort* inp = (GLshort*) in;
for(GLubyte i = 0; i < size; ++i) {
out[i] = (GLfloat) inp[i];
}
} break;
case GL_INT: {
GLint* inp = (GLint*) in;
for(GLubyte i = 0; i < size; ++i) {
out[i] = (GLfloat) inp[i];
}
} break;
case GL_FLOAT:
case GL_DOUBLE: /* Double == Float */
default:
for(GLubyte i = 0; i < size; ++i) out[i] = ((GLfloat*) in)[i];
}
}
static void _parseIndex(GLshort* out, const GLubyte* in, GLenum type) {
switch(type) {
case GL_UNSIGNED_BYTE:
*out = (GLshort) *in;
break;
case GL_UNSIGNED_SHORT:
default:
*out = *((GLshort*) in);
}
}
static void submitVertices(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) {
if(!(ENABLED_VERTEX_ATTRIBUTES & VERTEX_ENABLED_FLAG)) {
return;
}
_glKosMatrixApplyRender(); /* Apply the Render Matrix Stack */
const GLbyte elements = (mode == GL_QUADS) ? 4 : (mode == GL_TRIANGLES) ? 3 : (mode == GL_LINES) ? 2 : count;
pvr_vertex_t vertex;
vertex.u = vertex.v = 0.0f;
vertex.argb = 0xFFFFFFFF;
static GLfloat vparts[4];
GLubyte vstride = (VERTEX_POINTER.stride) ? VERTEX_POINTER.stride : VERTEX_POINTER.size * byte_size(VERTEX_POINTER.type);
GLubyte* vptr = VERTEX_POINTER.ptr;
for(GLuint i = 0; i < count; ++i) {
GLshort idx = i;
if(indices) {
_parseIndex(&idx, indices[byte_size(type) * i], type);
}
_parseFloats(vparts, vptr + (idx * vstride), VERTEX_POINTER.size, VERTEX_POINTER.type);
vertex.x = vparts[0];
vertex.y = vparts[1];
vertex.z = vparts[2];
transformVertex(&vertex.x);
}
}
GLAPI void APIENTRY glDrawElementsExp(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) {
submitVertices(mode, count, type, indices);
}
GLAPI void APIENTRY glDrawArraysExp(GLenum mode, GLint first, GLsizei count) {
submitVertices(mode, count, type, NULL);
}
GLAPI void APIENTRY glEnableClientStateExp(GLenum cap) {
switch(cap) {
case GL_VERTEX_ARRAY:
ENABLED_VERTEX_ATTRIBUTES |= VERTEX_ENABLED_FLAG;
break;
case GL_COLOR_ARRAY:
ENABLED_VERTEX_ATTRIBUTES |= DIFFUSE_ENABLED_FLAG;
break;
case GL_NORMAL_ARRAY:
ENABLED_VERTEX_ATTRIBUTES |= NORMAL_ENABLED_FLAG;
break;
case GL_TEXTURE_COORD_ARRAY:
(ACTIVE_CLIENT_TEXTURE) ?
(ENABLED_VERTEX_ATTRIBUTES |= ST_ENABLED_FLAG):
(ENABLED_VERTEX_ATTRIBUTES |= UV_ENABLED_FLAG);
break;
default:
_glKosThrowError(GL_INVALID_ENUM, "glEnableClientState");
}
}
GLAPI void APIENTRY glDisableClientStateExp(GLenum cap) {
switch(cap) {
case GL_VERTEX_ARRAY:
ENABLED_VERTEX_ATTRIBUTES &= ~VERTEX_ENABLED_FLAG;
break;
case GL_COLOR_ARRAY:
ENABLED_VERTEX_ATTRIBUTES &= ~DIFFUSE_ENABLED_FLAG;
break;
case GL_NORMAL_ARRAY:
ENABLED_VERTEX_ATTRIBUTES &= ~NORMAL_ENABLED_FLAG;
break;
case GL_TEXTURE_COORD_ARRAY:
(ACTIVE_CLIENT_TEXTURE) ?
(ENABLED_VERTEX_ATTRIBUTES &= ~ST_ENABLED_FLAG):
(ENABLED_VERTEX_ATTRIBUTES &= ~UV_ENABLED_FLAG);
break;
default:
_glKosThrowError(GL_INVALID_ENUM, "glDisableClientState");
}
}
GLAPI void APIENTRY glClientActiveTextureExp(GLenum texture) {
ACTIVE_CLIENT_TEXTURE = (texture == GL_TEXTURE1) ? 1 : 0;
}
GLAPI void APIENTRY glTexcoordPointerExp(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer) {
AttribPointer* texpointer = (ACTIVE_CLIENT_TEXTURE == 0) ? &UV_POINTER : &ST_POINTER;
texpointer->ptr = pointer;
texpointer->stride = stride;
texpointer->type = type;
texpointer->size = size;
}
GLAPI void APIENTRY glVertexPointerExp(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer) {
VERTEX_POINTER.ptr = pointer;
VERTEX_POINTER.stride = stride;
VERTEX_POINTER.type = type;
VERTEX_POINTER.size = size;
}
GLAPI void APIENTRY glColorPointerExp(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer) {
DIFFUSE_POINTER.ptr = pointer;
DIFFUSE_POINTER.stride = stride;
DIFFUSE_POINTER.type = type;
DIFFUSE_POINTER.size = size;
}
GLAPI void APIENTRY glNormalPointerExp(GLenum type, GLsizei stride, const GLvoid * pointer) {
NORMAL_POINTER.ptr = pointer;
NORMAL_POINTER.stride = stride;
NORMAL_POINTER.type = type;
NORMAL_POINTER.size = 3;
}

88
experimental/flush.c Normal file
View File

@ -0,0 +1,88 @@
#include <kos.h>
#include "../containers/aligned_vector.h"
#include "private.h"
#define TA_SQ_ADDR (unsigned int *)(void *) \
(0xe0000000 | (((unsigned long)0x10000000) & 0x03ffffe0))
static AlignedVector OP_LIST;
static AlignedVector PT_LIST;
static AlignedVector TR_LIST;
typedef struct {
unsigned int cmd[8];
} PVRCommand;
static void pvr_list_submit(void *src, int n) {
GLuint *d = TA_SQ_ADDR;
GLuint *s = src;
/* fill/write queues as many times necessary */
while(n--) {
__asm__("pref @%0" : : "r"(s + 8)); /* prefetch 32 bytes for next loop */
d[0] = *(s++);
d[1] = *(s++);
d[2] = *(s++);
d[3] = *(s++);
d[4] = *(s++);
d[5] = *(s++);
d[6] = *(s++);
d[7] = *(s++);
__asm__("pref @%0" : : "r"(d));
d += 8;
}
/* Wait for both store queues to complete */
d = (GLuint *)0xe0000000;
d[0] = d[8] = 0;
}
static void _initPVR() {
pvr_init_params_t params = {
/* Enable opaque and translucent polygons with size 32 and 32 */
{ PVR_BINSIZE_32, PVR_BINSIZE_0, PVR_BINSIZE_32, PVR_BINSIZE_0, PVR_BINSIZE_32 },
GL_PVR_VERTEX_BUF_SIZE, /* Vertex buffer size */
0, /* No DMA */
0, /* No FSAA */
1 /* Disable translucent auto-sorting to match traditional GL */
};
pvr_init(&params);
}
AlignedVector* activePolyList() {
return &OP_LIST;
}
/* FIXME: Rename to glKosInit when experimental is core */
void glKosBoot() {
_initPVR();
initAttributePointers();
aligned_vector_init(&OP_LIST, sizeof(PVRCommand));
aligned_vector_init(&PT_LIST, sizeof(PVRCommand));
aligned_vector_init(&TR_LIST, sizeof(PVRCommand));
}
void glKosSwapBuffers() {
pvr_wait_ready();
pvr_scene_begin();
pvr_list_begin(PVR_LIST_OP_POLY);
pvr_list_submit(OP_LIST.data, OP_LIST.size);
pvr_list_finish();
pvr_list_begin(PVR_LIST_PT_POLY);
pvr_list_submit(PT_LIST.data, PT_LIST.size);
pvr_list_finish();
pvr_list_begin(PVR_LIST_TR_POLY);
pvr_list_submit(TR_LIST.data, TR_LIST.size);
pvr_list_finish();
pvr_scene_finish();
}

25
experimental/private.h Normal file
View File

@ -0,0 +1,25 @@
#ifndef PRIVATE_H
#define PRIVATE_H
#include "../include/gl.h"
struct AlignedVector;
AlignedVector* activePolyList();
void initAttributePointers();
#define mat_trans_fv12() { \
__asm__ __volatile__( \
"fldi1 fr15\n" \
"ftrv xmtrx, fv12\n" \
"fldi1 fr14\n" \
"fdiv fr15, fr14\n" \
"fmul fr14, fr12\n" \
"fmul fr14, fr13\n" \
: "=f" (__x), "=f" (__y), "=f" (__z) \
: "0" (__x), "1" (__y), "2" (__z) \
: "fr15" ); \
}
#endif // PRIVATE_H

175
experimental/state.c Normal file
View File

@ -0,0 +1,175 @@
#include "../include/gl.h"
static pvr_poly_cxt_t GL_CONTEXT;
/* We can't just use the GL_CONTEXT for this state as the two
* GL states are combined, so we store them separately and then
* calculate the appropriate PVR state from them. */
static GLenum CULL_FACE = GL_BACK;
static GLenum FRONT_FACE = GL_CCW;
static GLboolean CULLING_ENABLED = GL_FALSE;
static int _calc_pvr_face_culling() {
if(!CULLING_ENABLED) {
return PVR_CULLING_NONE;
} else {
if(CULL_FACE == GL_BACK) {
return (FRONT_FACE == GL_CW) ? PVR_CULLING_CCW : PVR_CULLING_CW;
} else {
return (FRONT_FACE == GL_CCW) ? PVR_CULLING_CCW : PVR_CULLING_CW;
}
}
}
static GLenum DEPTH_FUNC = GL_LESS;
static GLboolean DEPTH_TEST_ENABLED = GL_FALSE;
static int _calc_pvr_depth_test() {
if(!DEPTH_TEST_ENABLED) {
return PVR_DEPTH_CMP_ALWAYS;
}
switch(func) {
case GL_NEVER:
return PVR_DEPTH_CMP_NEVER;
case GL_LESS:
return PVR_DEPTH_CMP_LESS;
case GL_EQUAL:
return PVR_DEPTH_CMP_EQUAL;
case GL_LEQUAL:
return PVR_DEPTH_CMP_LEQUAL;
case GL_GREATER:
return PVR_DEPTH_CMP_GREATER;
case GL_NOTEQUAL:
return PVR_DEPTH_CMP_NOTEQUAL;
case GL_GEQUAL:
return PVR_DEPTH_CMP_GEQUAL;
break;
case GL_ALWAYS:
default:
return PVR_DEPTH_CMP_ALWAYS;
}
}
void initContext() {
glDepthFunc(GL_LESS);
glDepthMask(GL_TRUE);
glCullFace(GL_CCW);
glDisable(GL_ALPHA_TEST);
glDisable(GL_CULL_FACE);
glDisable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glDisable(GL_TEXTURE_2D);
}
GLAPI void APIENTRY glEnable(GLenum cap) {
switch(cap) {
case GL_TEXTURE_2D:
GL_CONTEXT.txr.enable = 1;
break;
case GL_CULL_FACE: {
CULLING_ENABLED = GL_TRUE;
GL_CONTEXT.gen.culling = _calc_pvr_face_culling();
} break;
case GL_DEPTH_TEST: {
DEPTH_TEST_ENABLED = GL_TRUE;
GL_CONTEXT.depth.comparison = _calc_pvr_depth_test();
} break;
}
}
GLAPI void APIENTRY glDisable(GLenum cap) {
switch(cap) {
case GL_TEXTURE_2D: {
GL_CONTEXT.txr.enabled = 0;
} break;
case GL_CULL_FACE: {
CULLING_ENABLED = GL_FALSE;
GL_CONTEXT.gen.culling = _calc_pvr_face_culling();
} break;
case GL_DEPTH_TEST: {
DEPTH_TEST_ENABLED = GL_FALSE;
GL_CONTEXT.depth.comparison = _calc_pvr_depth_test();
} break;
}
}
/* Clear Caps */
GLAPI void APIENTRY glClear(GLuint mode) {
}
GLAPI void APIENTRY glClearColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
}
/* Depth Testing */
GLAPI void APIENTRY glClearDepthf(GLfloat depth) {
}
GLAPI void APIENTRY glClearDepth(GLfloat depth) {
}
GLAPI void APIENTRY glDepthMask(GLboolean flag) {
GL_CONTEXT.depth.write = (flag == GL_TRUE) ? PVR_DEPTHWRITE_ENABLE : PVR_DEPTHWRITE_DISABLE;
}
GLAPI void APIENTRY glDepthFunc(GLenum func) {
DEPTH_FUNC = func;
GL_CONTEXT.depth.comparison = _calc_pvr_depth_test();
}
/* Hints */
/* Currently Supported Capabilities:
GL_PERSPECTIVE_CORRECTION_HINT - This will Enable Texture Super-Sampling on the PVR */
GLAPI void APIENTRY glHint(GLenum target, GLenum mode) {
}
/* Culling */
GLAPI void APIENTRY glFrontFace(GLenum mode) {
FRONT_FACE = mode;
}
GLAPI void APIENTRY glCullFace(GLenum mode) {
CULL_FACE = mode;
}
/* Shading - Flat or Goraud */
GLAPI void APIENTRY glShadeModel(GLenum mode) {
}
/* Blending */
GLAPI void APIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor) {
}
/* Texturing */
GLAPI void APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param) {
}
GLAPI void APIENTRY glTexEnvi(GLenum target, GLenum pname, GLint param) {
}
GLAPI void APIENTRY glTexEnvf(GLenum target, GLenum pname, GLfloat param) {
}
GLAPI void APIENTRY glGenTextures(GLsizei n, GLuint *textures) {
}
GLAPI void APIENTRY glDeleteTextures(GLsizei n, GLuint *textures) {
}
GLAPI void APIENTRY glBindTexture(GLenum target, GLuint texture) {
}

6
include/glkos.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef GLKOS_H
#define GLKOS_H
void glKosSwapBuffers();
#endif // GLKOS_H