REVIEWED: Avoid program crash if GPU data is tried to be loaded before InitWindow() #4751

Following raylib design, a warning log message is shown and program can continue execution.
Some early return checks have been added on most  critical functions.
[rtext] Previous implementation checking `isGpuReady` cross-module variable is not needed any more, resulting in a more decoupled code, load failure is managed at rlgl level
This commit is contained in:
Ray
2025-12-11 18:21:57 +01:00
parent 8fa5f1fe2c
commit 2853b28d6d
5 changed files with 53 additions and 44 deletions

View File

@ -1153,6 +1153,7 @@ static double rlCullDistanceFar = RL_CULL_DISTANCE_FAR;
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
static rlglData RLGL = { 0 };
#endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2
static bool isGpuReady = false;
#if defined(GRAPHICS_API_OPENGL_ES2) && !defined(GRAPHICS_API_OPENGL_ES3)
// NOTE: VAO functionality is exposed through extensions (OES)
@ -2283,6 +2284,8 @@ static void GLAPIENTRY rlDebugMessageCallback(GLenum source, GLenum type, GLuint
// Initialize rlgl: OpenGL extensions, default buffers/shaders/textures, OpenGL states
void rlglInit(int width, int height)
{
isGpuReady = true;
// Enable OpenGL debug context if required
#if defined(RLGL_ENABLE_OPENGL_DEBUG_CONTEXT) && defined(GRAPHICS_API_OPENGL_43)
if ((glDebugMessageCallback != NULL) && (glDebugMessageControl != NULL))
@ -2395,6 +2398,7 @@ void rlglClose(void)
#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
swClose(); // Unload sofware renderer resources
#endif
isGpuReady = false;
}
// Load OpenGL extensions
@ -2799,6 +2803,7 @@ int *rlGetShaderLocsDefault(void)
rlRenderBatch rlLoadRenderBatch(int numBuffers, int bufferElements)
{
rlRenderBatch batch = { 0 };
if (!isGpuReady) { TRACELOG(RL_LOG_WARNING, "GL: GPU is not ready to load data, trying to load before InitWindow()?"); return batch; }
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
// Initialize CPU (RAM) vertex buffers (position, texcoord, color data and indexes)
@ -3253,6 +3258,7 @@ bool rlCheckRenderBatchLimit(int vCount)
unsigned int rlLoadTexture(const void *data, int width, int height, int format, int mipmapCount)
{
unsigned int id = 0;
if (!isGpuReady) { TRACELOG(RL_LOG_WARNING, "GL: GPU is not ready to load data, trying to load before InitWindow()?"); return id; }
glBindTexture(GL_TEXTURE_2D, 0); // Free any old binding
@ -3411,6 +3417,7 @@ unsigned int rlLoadTexture(const void *data, int width, int height, int format,
unsigned int rlLoadTextureDepth(int width, int height, bool useRenderBuffer)
{
unsigned int id = 0;
if (!isGpuReady) { TRACELOG(RL_LOG_WARNING, "GL: GPU is not ready to load data, trying to load before InitWindow()?"); return id; }
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
// In case depth textures not supported, we force renderbuffer usage
@ -3469,6 +3476,7 @@ unsigned int rlLoadTextureDepth(int width, int height, bool useRenderBuffer)
unsigned int rlLoadTextureCubemap(const void *data, int size, int format, int mipmapCount)
{
unsigned int id = 0;
if (!isGpuReady) { TRACELOG(RL_LOG_WARNING, "GL: GPU is not ready to load data, trying to load before InitWindow()?"); return id; }
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
int mipSize = size;
@ -3813,6 +3821,7 @@ unsigned char *rlReadScreenPixels(int width, int height)
unsigned int rlLoadFramebuffer(void)
{
unsigned int fboId = 0;
if (!isGpuReady) { TRACELOG(RL_LOG_WARNING, "GL: GPU is not ready to load data, trying to load before InitWindow()?"); return fboId; }
#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(RLGL_RENDER_TEXTURES_HINT)
glGenFramebuffers(1, &fboId); // Create the framebuffer object
@ -3928,6 +3937,7 @@ void rlUnloadFramebuffer(unsigned int id)
unsigned int rlLoadVertexBuffer(const void *buffer, int size, bool dynamic)
{
unsigned int id = 0;
if (!isGpuReady) { TRACELOG(RL_LOG_WARNING, "GL: GPU is not ready to load data, trying to load before InitWindow()?"); return id; }
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
glGenBuffers(1, &id);
@ -3942,6 +3952,7 @@ unsigned int rlLoadVertexBuffer(const void *buffer, int size, bool dynamic)
unsigned int rlLoadVertexBufferElement(const void *buffer, int size, bool dynamic)
{
unsigned int id = 0;
if (!isGpuReady) { TRACELOG(RL_LOG_WARNING, "GL: GPU is not ready to load data, trying to load before InitWindow()?"); return id; }
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
glGenBuffers(1, &id);
@ -4107,12 +4118,12 @@ void rlDisableStatePointer(int vertexAttribType)
unsigned int rlLoadVertexArray(void)
{
unsigned int vaoId = 0;
if (!isGpuReady) { TRACELOG(RL_LOG_WARNING, "GL: GPU is not ready to load data, trying to load before InitWindow()?"); return vaoId; }
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
if (RLGL.ExtSupported.vao)
{
glGenVertexArrays(1, &vaoId);
}
if (RLGL.ExtSupported.vao) glGenVertexArrays(1, &vaoId);
#endif
return vaoId;
}
@ -4167,6 +4178,7 @@ void rlUnloadVertexBuffer(unsigned int vboId)
unsigned int rlLoadShaderCode(const char *vsCode, const char *fsCode)
{
unsigned int id = 0;
if (!isGpuReady) { TRACELOG(RL_LOG_WARNING, "GL: GPU is not ready to load data, trying to load before InitWindow()?"); return id; }
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
unsigned int vertexShaderId = 0;
@ -4309,6 +4321,7 @@ unsigned int rlCompileShader(const char *shaderCode, int type)
unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId)
{
unsigned int programId = 0;
if (!isGpuReady) { TRACELOG(RL_LOG_WARNING, "GL: GPU is not ready to load data, trying to load before InitWindow()?"); return programId; }
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
GLint success = 0;