Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
b2ec8e7
feat(vertex): Add vertex and primitives functions
emiyl Jul 25, 2026
0d3d4ac
allow vertex id to be 0
emiyl Jul 25, 2026
654f7bc
fix(vm): stabilize CoW array writes before fork
emiyl Jul 24, 2026
dd1cfec
fix(layers): Use strcasecmp instead of strcmp to resolve layers (#348)
emiyl Jul 25, 2026
95ba8e8
perf(audio): mmap audiogroup*.dat if main data.win is being mapped (#…
cobaltgit Jul 25, 2026
fce7527
Make fast forward bools non-static (#354)
Un1q32 Jul 25, 2026
c678957
dynamic arrays of buffers and formats
emiyl Jul 25, 2026
5903785
fix double free
emiyl Jul 25, 2026
2241479
shh compiler
emiyl Jul 25, 2026
ad28aca
add vertex_submit_ext
emiyl Jul 25, 2026
f7379ea
shush compiler
emiyl Jul 25, 2026
deb41b7
findElement uses vertextype as well
emiyl Jul 25, 2026
3a0b15b
Merge branch 'main' into vertex
cobaltgit Jul 31, 2026
753d100
fix build fails
emiyl Aug 8, 2026
fa4ac98
raptor mini pass
emiyl Aug 8, 2026
1d4a996
Add browser width and browser height
Fancy2209 Jul 31, 2026
6f19d30
Fix previous commit
Fancy2209 Jul 31, 2026
a843d1b
PlayStation Vita port (#369)
hatoving Aug 2, 2026
1d4b131
update readme to show ps vita as a platform (#375)
casrielasriel Aug 2, 2026
ba2c825
remove goto
Un1q32 Aug 2, 2026
e0df045
Update gl_legacy_renderer.c (#376)
hatoving Aug 2, 2026
134038f
chore(vita): use safeMalloc for textures
cobaltgit Aug 2, 2026
c3ff7fd
perf(gl): only orphan what's been used, don't always assume quads
cobaltgit Aug 2, 2026
af2871d
use the variable
cobaltgit Aug 2, 2026
4f124ec
nah scratch that
cobaltgit Aug 2, 2026
fe74df6
Log system instead of printf and fprintf(stderr, ...) (#321)
Purplesmaug96 Aug 2, 2026
7a0fd78
more memory functions
Un1q32 Aug 3, 2026
e651a53
Parallelize conftests in configure.sh (#380)
Un1q32 Aug 5, 2026
365e744
fix fucking goddamn fucking ci right fucking now
Un1q32 Aug 5, 2026
0014e3d
fix(datawin): use calloc instead of malloc for shaders
cobaltgit Aug 5, 2026
08b33a3
Log output from failed conftests again, and better support SunOS (#382)
Un1q32 Aug 5, 2026
155cf9d
cleanup when exiting configure prematurely
Un1q32 Aug 5, 2026
38568a2
squeeze more optimization out of configure
Un1q32 Aug 6, 2026
6dafeeb
wording
Un1q32 Aug 6, 2026
042359f
chore(vita): add CI for PS Vita build! (#377)
cobaltgit Aug 6, 2026
af42981
fix configure output thingy
Un1q32 Aug 6, 2026
001a8aa
X11R7 in configure
Un1q32 Aug 7, 2026
235d23c
feat(path): add missing path functions (#351)
emiyl Aug 8, 2026
e3d7662
Revert miniaudio update
Un1q32 Aug 8, 2026
cab575f
update windows toolchain build script
Un1q32 Aug 8, 2026
b52cff0
chore(android): integrate Android frontend into main repo and add CI …
cobaltgit Aug 8, 2026
5c1ed88
chore(vita): *yawn* switch CI builds to use OpenAL for now
cobaltgit Aug 8, 2026
2b7f09b
align with the js version
emiyl Aug 8, 2026
85ea8cc
translate vertex primitives
emiyl Aug 8, 2026
81977e0
rewrite based on ghidra decomp
emiyl Aug 8, 2026
6a29a71
add rest of vertex format instructions
emiyl Aug 9, 2026
9114ecc
add vertex_buffer_create_*
emiyl Aug 9, 2026
66023ba
add vertex_update_buffer_from_*
emiyl Aug 9, 2026
008bedc
add rest of functions
emiyl Aug 9, 2026
cfa6445
extract some common functions
emiyl Aug 9, 2026
f050629
fix opengl rendering and add vertexformatpendingresourceid function
emiyl Aug 9, 2026
9532fd7
basic draw functions
emiyl Aug 9, 2026
3bd993d
hook up to gl renderer
emiyl Aug 9, 2026
75a4eff
swap around arguments for draw_vertex_texture_color
emiyl Aug 9, 2026
9749c62
resolve texture function
emiyl Aug 9, 2026
734e43e
use renderer drawColor and clamp alpha
emiyl Aug 9, 2026
a351849
Merge branch 'main' into vertex
emiyl Aug 9, 2026
da05e62
remove printfs
emiyl Aug 9, 2026
4ea7bc8
compare element->usage to yyVUMaxVertexUsage
emiyl Aug 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
324 changes: 324 additions & 0 deletions src/gl/gl_renderer.c
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,114 @@ static void flushIfNeededAndSetActiveState(GLRenderer* gl, BatchType batchType,
gl->currentTextureId = textureId;
}

static bool glResolveTextureHandle(GLRenderer* gl, uint32_t texHandle, TexturePageItem** outTpag, GLuint* outTexId, int32_t* outTexW, int32_t* outTexH);

static GLenum primitiveTypeToGL(int32_t primitiveType) {
switch (primitiveType) {
case PRIMITIVE_POINTS:
return GL_POINTS;
case PRIMITIVE_LINES:
return GL_LINES;
case PRIMITIVE_LINE_STRIP:
return GL_LINE_STRIP;
case PRIMITIVE_TRIANGLES:
return GL_TRIANGLES;
case PRIMITIVE_TRIANGLE_STRIP:
return GL_TRIANGLE_STRIP;
case PRIMITIVE_TRIANGLE_FAN:
return GL_TRIANGLE_FAN;
default:
return GL_TRIANGLES;
}
}

static void glPrimitiveBegin(Renderer* renderer, int32_t primitiveType) {
GLRenderer* gl = (GLRenderer*) renderer;
flushBatch(gl);

gl->primitiveType = primitiveType;
gl->primitiveVertexCount = 0;
gl->primitiveTextureId = gl->whiteTexture;
gl->primitiveHasTexture = false;
}

static void glPrimitiveBeginTexture(Renderer* renderer, int32_t primitiveType, int32_t texture) {
GLRenderer* gl = (GLRenderer*) renderer;
glPrimitiveBegin(renderer, primitiveType);

if (texture > 0) {
TexturePageItem* tpag = nullptr;
GLuint resolvedTexId = 0;
int32_t resolvedTexW = 0;
int32_t resolvedTexH = 0;

if (glResolveTextureHandle(gl, (uint32_t) texture, &tpag, &resolvedTexId, &resolvedTexW, &resolvedTexH) && resolvedTexId != 0) {
gl->primitiveTextureId = resolvedTexId;
gl->primitiveHasTexture = true;
} else if (glIsTexture((GLuint) texture)) {
gl->primitiveTextureId = (GLuint) texture;
gl->primitiveHasTexture = true;
}
}
}

static void glPrimitiveEnd(Renderer* renderer) {
GLRenderer* gl = (GLRenderer*) renderer;
if (gl->primitiveVertexCount <= 0) return;

GLuint textureId = gl->primitiveHasTexture ? gl->primitiveTextureId : gl->whiteTexture;
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, textureId);

glBindBuffer(GL_ARRAY_BUFFER, gl->vbo);
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(gl->primitiveVertexCount * sizeof(Vertex)), gl->vertexData, GL_DYNAMIC_DRAW);

if (hasVAO()) {
glBindVertexArray(gl->vao);
} else {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gl->ebo);

int32_t stride = sizeof(Vertex);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, stride, (void*) offsetof(Vertex, x));
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, (void*) offsetof(Vertex, r));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, stride, (void*) offsetof(Vertex, u));
glEnableVertexAttribArray(2);
}

glDrawArrays(primitiveTypeToGL(gl->primitiveType), 0, gl->primitiveVertexCount);

if (!hasVAO()) {
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
}

gl->primitiveVertexCount = 0;
}

static void glDrawVertex(Renderer* renderer, float x, float y, float z, uint32_t color, float alpha, float u, float v) {
GLRenderer* gl = (GLRenderer*) renderer;

if (gl->primitiveVertexCount < 0) {
gl->primitiveVertexCount = 0;
}

Vertex* vert = &gl->vertexData[gl->primitiveVertexCount];
vert->x = x;
vert->y = y;
vert->z = z;
vert->u = u;
vert->v = v;
vert->r = (uint8_t) BGR_R(color);
vert->g = (uint8_t) BGR_G(color);
vert->b = (uint8_t) BGR_B(color);
vert->a = floatToUnormByte(alpha);

gl->primitiveVertexCount++;
}

// ===[ Vtable Implementations ]===

static bool compileProgram(GMLShader* gmlShader, const char* name, const char* vertexShaderSource, const char* fragmentShaderSource, uint32_t vertexAttributeCount, const char** vertexAttributes) {
Expand Down Expand Up @@ -1610,6 +1718,217 @@ static void glDrawTriangle(Renderer *renderer, float x1, float y1, float x2, flo
}
}

static int vertex_type_components(int type)
{
switch (type) {
case VERTEX_TYPE_FLOAT1:
return 1;
case VERTEX_TYPE_FLOAT2:
return 2;
case VERTEX_TYPE_FLOAT3:
return 3;
case VERTEX_TYPE_FLOAT4:
return 4;
case VERTEX_TYPE_UBYTE4:
return 4;
case VERTEX_TYPE_COLOR:
return 4;
}

return 4;
}

static bool glResolveTextureHandle(GLRenderer* gl, uint32_t texHandle, TexturePageItem** outTpag, GLuint* outTexId, int32_t* outTexW, int32_t* outTexH);

static void glDrawVertexBuffer(MAYBE_UNUSED Renderer* renderer, VertexBuffer* buffer, int32_t primitive, int32_t texture, int32_t offset, int32_t number) {
if (!buffer || !buffer->format)
return;

GLRenderer* gl = (GLRenderer*) renderer;
flushBatch(gl);

typedef struct {
GLuint vbo;
} GLVertexBuffer;

GLVertexBuffer *glBuffer = (GLVertexBuffer *)buffer->rendererData;

if (!glBuffer) {
glBuffer = (GLVertexBuffer *)malloc(sizeof(*glBuffer));
glGenBuffers(1, &glBuffer->vbo);
buffer->rendererData = (void *) glBuffer;
}

GLenum mode;

switch (primitive) {
case PRIMITIVE_POINTS:
mode = GL_POINTS;
break;

case PRIMITIVE_LINES:
mode = GL_LINES;
break;

case PRIMITIVE_LINE_STRIP:
mode = GL_LINE_STRIP;
break;

case PRIMITIVE_TRIANGLES:
mode = GL_TRIANGLES;
break;

case PRIMITIVE_TRIANGLE_STRIP:
mode = GL_TRIANGLE_STRIP;
break;

case PRIMITIVE_TRIANGLE_FAN:
mode = GL_TRIANGLE_FAN;
break;

default:
return;
}

glBindBuffer(GL_ARRAY_BUFFER, glBuffer->vbo);
glBufferData(GL_ARRAY_BUFFER, buffer->size, buffer->data, GL_DYNAMIC_DRAW);

bool hasColor = false;
bool hasTexcoord = false;

for (int i = 0; i < buffer->format->numElements; i++) {
VertexElement *e = &buffer->format->elements[i];

switch (e->usage) {
case VERTEX_USAGE_POSITION:
glEnableVertexAttribArray(0);
glVertexAttribPointer(
0,
vertex_type_components(e->type),
GL_FLOAT,
GL_FALSE,
buffer->format->stride,
(void*)(intptr_t)e->offset
);
break;

case VERTEX_USAGE_COLOR:
hasColor = true;
glEnableVertexAttribArray(1);
glVertexAttribPointer(
1,
4,
GL_UNSIGNED_BYTE,
GL_TRUE,
buffer->format->stride,
(void*)(intptr_t)e->offset
);
break;

case VERTEX_USAGE_NORMAL:
glEnableVertexAttribArray(3);
glVertexAttribPointer(
3,
3,
GL_FLOAT,
GL_FALSE,
buffer->format->stride,
(void*)(intptr_t)e->offset
);
break;

case VERTEX_USAGE_TEXCOORD:
hasTexcoord = true;
glEnableVertexAttribArray(2);
glVertexAttribPointer(
2,
2,
GL_FLOAT,
GL_FALSE,
buffer->format->stride,
(void*)(intptr_t)e->offset
);
break;
}
}

if (!hasColor) {
glDisableVertexAttribArray(1);
glVertexAttrib4f(1, 1.0f, 1.0f, 1.0f, 1.0f);
}

if (!hasTexcoord) {
glDisableVertexAttribArray(2);
glVertexAttrib2f(2, 0.5f, 0.5f);
}

GLuint drawTexture = gl->whiteTexture;
if (texture != -1) {
TexturePageItem* textureTpag = nullptr;
GLuint resolvedTexId = 0;
int32_t resolvedTexW = 0;
int32_t resolvedTexH = 0;

if (glResolveTextureHandle(gl, (uint32_t) texture, &textureTpag, &resolvedTexId, &resolvedTexW, &resolvedTexH) && resolvedTexId != 0) {
drawTexture = resolvedTexId;
} else if (glIsTexture((GLuint) texture)) {
// Backward compatibility with callers that already pass raw GL ids.
drawTexture = (GLuint) texture;
}
}

// Position/color-only vertex formats should render untextured.
if (!hasTexcoord) {
drawTexture = gl->whiteTexture;
}

glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, drawTexture);

int vertexCount = buffer->size / buffer->format->stride;
if (vertexCount <= 0) {
for (int i = 0; i < buffer->format->numElements; i++) {
glDisableVertexAttribArray(i);
}

glBindBuffer(GL_ARRAY_BUFFER, 0);
return;
}

if (offset < 0) offset = 0;
if (offset > vertexCount) offset = vertexCount;

if (number == -1) {
number = vertexCount - offset;
} else {
if (number < 0) number = 0;
if (offset + number > vertexCount) {
number = vertexCount - offset;
}
}

if (number <= 0) {
for (int i = 0; i < buffer->format->numElements; i++) {
glDisableVertexAttribArray(i);
}

glBindBuffer(GL_ARRAY_BUFFER, 0);
return;
}

glDrawArrays(
mode,
offset,
number
);

for (int i = 0; i < buffer->format->numElements; i++) {
glDisableVertexAttribArray(i);
}

glBindBuffer(GL_ARRAY_BUFFER, 0);
}

// ===[ Text Drawing ]===

// Resolved font state shared between glDrawText and glDrawTextColor
Expand Down Expand Up @@ -2711,8 +3030,13 @@ Renderer* GLRenderer_create(void) {
glVtable.drawLine = glDrawLine;
glVtable.drawLineColor = glDrawLineColor;
glVtable.drawTriangle = glDrawTriangle;
glVtable.drawVertexBuffer = glDrawVertexBuffer;
glVtable.drawText = glDrawText;
glVtable.drawTextColor = glDrawTextColor;
glVtable.primitiveBegin = glPrimitiveBegin;
glVtable.primitiveBeginTexture = glPrimitiveBeginTexture;
glVtable.primitiveEnd = glPrimitiveEnd;
glVtable.drawVertex = glDrawVertex;
glVtable.flush = glRendererFlush;
glVtable.clearScreen = glClearScreen;
glVtable.createSpriteFromSurface = glCreateSpriteFromSurface;
Expand Down
4 changes: 4 additions & 0 deletions src/gl/gl_renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ typedef struct {
Vertex* vertexData; // MAX_QUADS * VERTICES_PER_QUAD vertices

BatchType batchType;
int32_t primitiveType;
int32_t primitiveVertexCount;
GLuint primitiveTextureId;
bool primitiveHasTexture;
int32_t batchCount;
GLuint currentTextureId;

Expand Down
Loading
Loading