Skip to content
Open
438 changes: 379 additions & 59 deletions src/gl/gl_renderer.c

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions src/gl/gl_renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ typedef struct {
GLint uTexture;
GLint uAlphaTestRef;
GLint uFogColor;
GLint uAlphaTestEnabled;
GLuint* GMLShaders;
bool* GMLShaderCompiled;
uint32_t GMLShaderCount;
int32_t** Sampler2DLookUpTable;
GLint** Sampler2DLocationLookUpTable;

bool alphaTestEnable;
float alphaTestRef;
Expand Down
5 changes: 3 additions & 2 deletions src/gl_common/gl_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@ void GLCommon_beginLetterboxBlit(GLuint fbo) {

void GLCommon_endLetterboxBlit(int32_t fboWidth, int32_t fboHeight, int32_t gameW, int32_t gameH, int32_t windowW, int32_t windowH) {
int32_t sx, sy, ex, ey;
glClearColor(0.0, 0.0, 0.0, 1.0);
GLCommon_computeLetterbox(gameW, gameH, windowW, windowH, &sx, &sy, &ex, &ey);
glBlitFramebuffer(0, 0, fboWidth, fboHeight, sx, sy, ex, ey, GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBlitFramebuffer(0, 0, fboWidth, fboHeight, sx, ey, ex, sy, GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

Expand Down Expand Up @@ -86,7 +87,7 @@ void GLCommon_surfaceBlit(GLuint* surfaces, int32_t* surfaceWidth, int32_t* surf

if (part) {
// GL Y is bottom-up; convert GML's top-down (srcX, srcY) source rect.
int32_t srcY0 = srcFboH - srcY - srcH;
int32_t srcY0 = srcY;
glBlitFramebuffer(srcX, srcY0, srcX + srcW, srcY0 + srcH, dstX, dstY, dstX + srcW, dstY + srcH, GL_COLOR_BUFFER_BIT, GL_NEAREST);
} else {
glBlitFramebuffer(0, 0, srcFboW, srcFboH, dstX, dstY, dstX + srcFboW, dstY + srcFboH, GL_COLOR_BUFFER_BIT, GL_NEAREST);
Expand Down
51 changes: 18 additions & 33 deletions src/gl_legacy/gl_legacy_renderer.c
Original file line number Diff line number Diff line change
Expand Up @@ -280,8 +280,8 @@ bool GLLegacyRenderer_ensureTextureLoaded(GLLegacyRenderer* gl, uint32_t pageId)
// Nearest is mandatory for index textures, bilinear would interpolate palette indices into nonsense colors.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

free(pixels);
#else
Expand All @@ -302,8 +302,8 @@ bool GLLegacyRenderer_ensureTextureLoaded(GLLegacyRenderer* gl, uint32_t pageId)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

free(pixels);
#endif
Expand Down Expand Up @@ -1218,37 +1218,22 @@ static int32_t glCreateSpriteFromSurface(Renderer* renderer, int32_t surfaceID,
if (gl->surfaces[surfaceID] == 0) return -1;

glBindFramebuffer(GL_READ_FRAMEBUFFER, gl->surfaces[surfaceID]);
int32_t srcHeight = gl->surfaceHeight[surfaceID];

uint8_t* pixels = safeMalloc((size_t) w * (size_t) h * 4);
if (pixels == nullptr)
return -1;

// OpenGL Y is bottom-up, GML Y is top-down, so flip the Y coordinate
int32_t glY = srcHeight - y - h;
glReadPixels(x, glY, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);

// Flip vertically (OpenGL reads bottom-to-top)
size_t rowBytes = (size_t) w * 4;
uint8_t* rowTemp = safeMalloc(rowBytes);
repeat(h / 2, row) {
uint8_t* top = pixels + row * rowBytes;
uint8_t* bot = pixels + (h - 1 - row) * rowBytes;
memcpy(rowTemp, top, rowBytes);
memcpy(top, bot, rowBytes);
memcpy(bot, rowTemp, rowBytes);
}
free(rowTemp);
glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);

// Create a new GL texture from the captured pixels
GLuint newTexId;
glGenTextures(1, &newTexId);
glBindTexture(GL_TEXTURE_2D, newTexId);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, smooth ? GL_LINEAR : GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, smooth ? GL_LINEAR : GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

free(pixels);

Expand Down Expand Up @@ -1390,8 +1375,8 @@ static int32_t glLegacyCreateSurface(Renderer* renderer, int32_t width, int32_t
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

glBindFramebuffer(GL_FRAMEBUFFER, gl->surfaces[surfaceIndex]);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gl->surfaceTexture[surfaceIndex], 0);
Expand Down Expand Up @@ -1463,8 +1448,8 @@ static void glLegacySurfaceResize(Renderer* renderer, int32_t surfaceId, int32_t
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

glBindFramebuffer(GL_FRAMEBUFFER, gl->surfaces[surfaceId]);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gl->surfaceTexture[surfaceId], 0);
Expand Down Expand Up @@ -1515,7 +1500,7 @@ static bool glLegacySetRenderTarget(Renderer* renderer, int32_t surfaceId) {

Matrix4f projection;
Matrix4f_identity(&projection);
Matrix4f_ortho(&projection, 0.0f, (float) w, (float) h, 0.0f, -1.0f, 1.0f);
Matrix4f_ortho(&projection, 0.0f, (float) w, 0.0f, (float) h, -1.0f, 1.0f);
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(projection.m);
glMatrixMode(GL_MODELVIEW);
Expand Down Expand Up @@ -1547,11 +1532,11 @@ static void glLegacyDrawSurface(Renderer* renderer, int32_t surfaceId, int32_t s
float u0 = (float) srcLeft / (float) texW;
float u1 = (float) (srcLeft + srcWidth) / (float) texW;
#ifndef PLATFORM_PS3
float v0 = 1.0f - (float) srcTop / (float) texH;
float v1 = 1.0f - (float) (srcTop + srcHeight) / (float) texH;
float v0 = (float) srcTop / (float) texH;
float v1 = (float) (srcTop + srcHeight) / (float) texH;
#else
float v1 = 1.0f - (float) srcTop / (float) texH;
float v0 = 1.0f - (float) (srcTop + srcHeight) / (float) texH;
float v1 = (float) srcTop / (float) texH;
float v0 = (float) (srcTop + srcHeight) / (float) texH;
#endif

float r = (float) BGR_R(color) / 255.0f;
Expand Down
2 changes: 1 addition & 1 deletion src/matrix_math.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ static inline Matrix4f* Matrix4f_setTransform2D(Matrix4f* dest, float x, float y
// Y-down coordinate space, optionally rotated by angleDeg counter-clockwise about the view center (matching GML view_angle).
static inline Matrix4f* Matrix4f_viewProjection(Matrix4f* dest, float left, float top, float width, float height, float angleDeg) {
Matrix4f_identity(dest);
Matrix4f_ortho(dest, left, left + width, top + height, top, -1.0f, 1.0f);
Matrix4f_ortho(dest, left, left + width, top, top + height, -1.0f, 1.0f);

if (angleDeg != 0.0f) {
// Rotate the world opposite the camera, about the view center, to spin the camera by angleDeg.
Expand Down
25 changes: 25 additions & 0 deletions src/renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,17 @@
#define bm_inv_dest_color 10
#define bm_src_alpha_sat 11

#define MATRIX_VIEW 0
#define MATRIX_PROJECTION 1
#define MATRIX_WORLD 2
#define MATRIX_WORLD_VIEW 3
#define MATRIX_WORLD_VIEW_PROJECTION 4
#define MATRICES_MAX 5

#define MAX_VS_LIGHTS 8

#define MAX_TEXTURE_STAGES 8

// Sentinel returned by ensureApplicationSurface on platforms that don't back the application_surface with a real entry in the renderer's surface table.
//
// Also used as the initial value of Runner.applicationSurfaceId before the first ensure call.
Expand Down Expand Up @@ -110,6 +121,18 @@ typedef struct {
// Optional: tile a source sub-rect (in tpag source-page space) across a dest rect, for nine-slice Repeat/BlankRepeat at angle 0.
// srcX/srcY are post tpag->targetX/Y. nullptr = per-tile drawSpritePart fallback (also used for Mirror and non-zero angle).
void (*drawTiledPart)(Renderer* renderer, int32_t tpagIndex, int32_t srcX, int32_t srcY, int32_t srcW, int32_t srcH, float dstX, float dstY, float dstW, float dstH, uint32_t color, float alpha);
// Shader Functions
void (*gpuSetShader)(Renderer* renderer, int32_t shaderIndex);
void (*gpuResetShader)(Renderer* renderer);
int32_t (*shaderGetUniform)(Renderer* renderer, int32_t shaderIndex, char* uniform);
int32_t (*shaderGetSamplerIndex)(Renderer* renderer, int32_t shaderIndex, char* uniform);
void (*shaderSetUniformF)(Renderer* renderer, int32_t handle, int32_t count, float value1, float value2, float value3, float value4);
uint32_t (*spriteGetTexture)(Renderer* renderer, int32_t tpagIndex);
float (*textureGetTexelWidth)(Renderer* renderer, uint32_t texID);
float (*textureGetTexelHeight)(Renderer* renderer, uint32_t texID);
void (*textureSetStage)(Renderer* renderer, int32_t slot, uint32_t texID);
bool (*shaderIsCompiled)(Renderer* renderer, int32_t shader);
bool (*shadersSupported)(Renderer* renderer);
} RendererVtable;

// ===[ Renderer Base Struct ]===
Expand All @@ -130,6 +153,8 @@ struct Renderer {
int32_t CPortW;
int32_t CPortH;
Runner* runner;
Matrix4f GML_Matrices[MATRICES_MAX];
int32_t CurrentShader;
};

// ===[ Shared Helpers (platform-agnostic) ]===
Expand Down
Loading
Loading