2 Commits

Author SHA1 Message Date
Ray
b465b4e2ea RENAMED: Variable names for consistency, textLength (length in bytes) vs textSize (measure in pixels) 2025-12-11 21:41:25 +01:00
Ray
2853b28d6d 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
2025-12-11 18:21:57 +01:00
8 changed files with 89 additions and 80 deletions

View File

@ -84,7 +84,6 @@ typedef struct {
// Global Variables Definition // Global Variables Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
extern CoreData CORE; // Global CORE state context extern CoreData CORE; // Global CORE state context
extern bool isGpuReady; // Flag to note GPU has been initialized successfully
static PlatformData platform = { 0 }; // Platform specific data static PlatformData platform = { 0 }; // Platform specific data
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -1042,7 +1041,6 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
// Initialize OpenGL context (states and resources) // Initialize OpenGL context (states and resources)
// NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl // NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl
rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height); rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
isGpuReady = true;
// Setup default viewport // Setup default viewport
// NOTE: It updated CORE.Window.render.width and CORE.Window.render.height // NOTE: It updated CORE.Window.render.width and CORE.Window.render.height

View File

@ -2770,9 +2770,9 @@ static const char *GetFileNameWithoutExt(const char *filePath)
if (filePath != NULL) strncpy(fileName, GetFileName(filePath), MAX_FILENAMEWITHOUTEXT_LENGTH - 1); // Get filename with extension if (filePath != NULL) strncpy(fileName, GetFileName(filePath), MAX_FILENAMEWITHOUTEXT_LENGTH - 1); // Get filename with extension
int size = (int)strlen(fileName); // Get size in bytes int fileNameLength = (int)strlen(fileName); // Get size in bytes
for (int i = 0; (i < size) && (i < MAX_FILENAMEWITHOUTEXT_LENGTH); i++) for (int i = 0; (i < fileNameLength) && (i < MAX_FILENAMEWITHOUTEXT_LENGTH); i++)
{ {
if (fileName[i] == '.') if (fileName[i] == '.')
{ {

View File

@ -387,11 +387,6 @@ RLAPI const char *raylib_version = RAYLIB_VERSION; // raylib version exported s
CoreData CORE = { 0 }; // Global CORE state context CoreData CORE = { 0 }; // Global CORE state context
// Flag to note GPU acceleration is available,
// referenced from other modules to support GPU data loading
// NOTE: Useful to allow Texture, RenderTexture, Font.texture, Mesh.vaoId/vboId, Shader loading
bool isGpuReady = false;
#if defined(SUPPORT_SCREEN_CAPTURE) #if defined(SUPPORT_SCREEN_CAPTURE)
static int screenshotCounter = 0; // Screenshots counter static int screenshotCounter = 0; // Screenshots counter
#endif #endif
@ -697,7 +692,6 @@ void InitWindow(int width, int height, const char *title)
// Initialize rlgl default data (buffers and shaders) // Initialize rlgl default data (buffers and shaders)
// NOTE: Current fbo size stored as globals in rlgl for convenience // NOTE: Current fbo size stored as globals in rlgl for convenience
rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height); rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
isGpuReady = true; // Flag to note GPU has been initialized successfully
// Setup default viewport // Setup default viewport
SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height); SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
@ -1266,7 +1260,14 @@ Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode)
shader.id = rlLoadShaderCode(vsCode, fsCode); shader.id = rlLoadShaderCode(vsCode, fsCode);
if (shader.id == rlGetShaderIdDefault()) shader.locs = rlGetShaderLocsDefault(); if (shader.id == 0)
{
// Shader could not be loaded but we still load the location points to avoid potential crashes
// NOTE: All locations set to -1 (no location)
shader.locs = (int *)RL_CALLOC(RL_MAX_SHADER_LOCATIONS, sizeof(int));
for (int i = 0; i < RL_MAX_SHADER_LOCATIONS; i++) shader.locs[i] = -1;
}
else if (shader.id == rlGetShaderIdDefault()) shader.locs = rlGetShaderLocsDefault();
else if (shader.id > 0) else if (shader.id > 0)
{ {
// After custom shader loading, we TRY to set default location names // After custom shader loading, we TRY to set default location names
@ -1282,9 +1283,9 @@ Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode)
// NOTE: If any location is not found, loc point becomes -1 // NOTE: If any location is not found, loc point becomes -1
// Load shader locations array
// NOTE: All locations set to -1 (no location)
shader.locs = (int *)RL_CALLOC(RL_MAX_SHADER_LOCATIONS, sizeof(int)); shader.locs = (int *)RL_CALLOC(RL_MAX_SHADER_LOCATIONS, sizeof(int));
// All locations reset to -1 (no location)
for (int i = 0; i < RL_MAX_SHADER_LOCATIONS; i++) shader.locs[i] = -1; for (int i = 0; i < RL_MAX_SHADER_LOCATIONS; i++) shader.locs[i] = -1;
// Get handles to GLSL input attribute locations // Get handles to GLSL input attribute locations
@ -2008,10 +2009,10 @@ bool IsFileExtension(const char *fileName, const char *ext)
if (fileExt != NULL) if (fileExt != NULL)
{ {
int fileExtLen = (int)strlen(fileExt); int fileExtLength = (int)strlen(fileExt);
char fileExtLower[16] = { 0 }; char fileExtLower[16] = { 0 };
char *fileExtLowerPtr = fileExtLower; char *fileExtLowerPtr = fileExtLower;
for (int i = 0; (i < fileExtLen) && (i < 16); i++) for (int i = 0; (i < fileExtLength) && (i < 16); i++)
{ {
// Copy and convert to lower-case // Copy and convert to lower-case
if ((fileExt[i] >= 'A') && (fileExt[i] <= 'Z')) fileExtLower[i] = fileExt[i] + 32; if ((fileExt[i] >= 'A') && (fileExt[i] <= 'Z')) fileExtLower[i] = fileExt[i] + 32;
@ -2019,13 +2020,13 @@ bool IsFileExtension(const char *fileName, const char *ext)
} }
int extCount = 1; int extCount = 1;
int extLen = (int)strlen(ext); int extLength = (int)strlen(ext);
char *extList = (char *)RL_CALLOC(extLen + 1, 1); char *extList = (char *)RL_CALLOC(extLength + 1, 1);
char *extListPtrs[MAX_FILE_EXTENSIONS] = { 0 }; char *extListPtrs[MAX_FILE_EXTENSIONS] = { 0 };
strncpy(extList, ext, extLen); strncpy(extList, ext, extLength);
extListPtrs[0] = extList; extListPtrs[0] = extList;
for (int i = 0; i < extLen; i++) for (int i = 0; i < extLength; i++)
{ {
// Convert to lower-case if extension is upper-case // Convert to lower-case if extension is upper-case
if ((extList[i] >= 'A') && (extList[i] <= 'Z')) extList[i] += 32; if ((extList[i] >= 'A') && (extList[i] <= 'Z')) extList[i] += 32;
@ -2162,9 +2163,9 @@ const char *GetFileNameWithoutExt(const char *filePath)
if (filePath != NULL) if (filePath != NULL)
{ {
strncpy(fileName, GetFileName(filePath), MAX_FILENAME_LENGTH - 1); // Get filename.ext without path strncpy(fileName, GetFileName(filePath), MAX_FILENAME_LENGTH - 1); // Get filename.ext without path
int size = (int)strlen(fileName); // Get size in bytes int fileNameLenght = (int)strlen(fileName); // Get size in bytes
for (int i = size; i > 0; i--) // Reverse search '.' for (int i = fileNameLenght; i > 0; i--) // Reverse search '.'
{ {
if (fileName[i] == '.') if (fileName[i] == '.')
{ {
@ -2231,11 +2232,11 @@ const char *GetPrevDirectoryPath(const char *dirPath)
{ {
static char prevDirPath[MAX_FILEPATH_LENGTH] = { 0 }; static char prevDirPath[MAX_FILEPATH_LENGTH] = { 0 };
memset(prevDirPath, 0, MAX_FILEPATH_LENGTH); memset(prevDirPath, 0, MAX_FILEPATH_LENGTH);
int pathLen = (int)strlen(dirPath); int dirPathLength = (int)strlen(dirPath);
if (pathLen <= 3) strncpy(prevDirPath, dirPath, MAX_FILEPATH_LENGTH - 1); if (dirPathLength <= 3) strncpy(prevDirPath, dirPath, MAX_FILEPATH_LENGTH - 1);
for (int i = (pathLen - 1); (i >= 0) && (pathLen > 3); i--) for (int i = (dirPathLength - 1); (i >= 0) && (dirPathLength > 3); i--)
{ {
if ((dirPath[i] == '\\') || (dirPath[i] == '/')) if ((dirPath[i] == '\\') || (dirPath[i] == '/'))
{ {
@ -2322,8 +2323,8 @@ const char *GetApplicationDirectory(void)
if (_NSGetExecutablePath(appDir, &size) == 0) if (_NSGetExecutablePath(appDir, &size) == 0)
{ {
int len = strlen(appDir); int appDirLength = (int)strlen(appDir);
for (int i = len; i >= 0; --i) for (int i = appDirLength; i >= 0; --i)
{ {
if (appDir[i] == '/') if (appDir[i] == '/')
{ {
@ -2345,8 +2346,8 @@ const char *GetApplicationDirectory(void)
if (sysctl(mib, 4, appDir, &size, NULL, 0) == 0) if (sysctl(mib, 4, appDir, &size, NULL, 0) == 0)
{ {
int len = strlen(appDir); int appDirLength = (int)strlen(appDir);
for (int i = len; i >= 0; --i) for (int i = appDirLength; i >= 0; --i)
{ {
if (appDir[i] == '/') if (appDir[i] == '/')
{ {
@ -2441,12 +2442,12 @@ int MakeDirectory(const char *dirPath)
if (DirectoryExists(dirPath)) return 0; // Path already exists (is valid) if (DirectoryExists(dirPath)) return 0; // Path already exists (is valid)
// Copy path string to avoid modifying original // Copy path string to avoid modifying original
int len = (int)strlen(dirPath) + 1; int dirPathLength = (int)strlen(dirPath) + 1;
char *pathcpy = (char *)RL_CALLOC(len, 1); char *pathcpy = (char *)RL_CALLOC(dirPathLength, 1);
memcpy(pathcpy, dirPath, len); memcpy(pathcpy, dirPath, dirPathLength);
// Iterate over pathcpy, create each subdirectory as needed // Iterate over pathcpy, create each subdirectory as needed
for (int i = 0; (i < len) && (pathcpy[i] != '\0'); i++) for (int i = 0; (i < dirPathLength) && (pathcpy[i] != '\0'); i++)
{ {
if (pathcpy[i] == ':') i++; if (pathcpy[i] == ':') i++;
else else
@ -2498,10 +2499,10 @@ bool IsFileNameValid(const char *fileName)
if ((fileName != NULL) && (fileName[0] != '\0')) if ((fileName != NULL) && (fileName[0] != '\0'))
{ {
int length = (int)strlen(fileName); int fileNameLength = (int)strlen(fileName);
bool allPeriods = true; bool allPeriods = true;
for (int i = 0; i < length; i++) for (int i = 0; i < fileNameLength; i++)
{ {
// Check invalid characters // Check invalid characters
if ((fileName[i] == '<') || if ((fileName[i] == '<') ||
@ -2527,7 +2528,7 @@ bool IsFileNameValid(const char *fileName)
if (valid) if (valid)
{ {
// Check invalid DOS names // Check invalid DOS names
if (length >= 3) if (fileNameLength >= 3)
{ {
if (((fileName[0] == 'C') && (fileName[1] == 'O') && (fileName[2] == 'N')) || // CON if (((fileName[0] == 'C') && (fileName[1] == 'O') && (fileName[2] == 'N')) || // CON
((fileName[0] == 'P') && (fileName[1] == 'R') && (fileName[2] == 'N')) || // PRN ((fileName[0] == 'P') && (fileName[1] == 'R') && (fileName[2] == 'N')) || // PRN
@ -2535,7 +2536,7 @@ bool IsFileNameValid(const char *fileName)
((fileName[0] == 'N') && (fileName[1] == 'U') && (fileName[2] == 'L'))) valid = false; // NUL ((fileName[0] == 'N') && (fileName[1] == 'U') && (fileName[2] == 'L'))) valid = false; // NUL
} }
if (length >= 4) if (fileNameLength >= 4)
{ {
if (((fileName[0] == 'C') && (fileName[1] == 'O') && (fileName[2] == 'M') && ((fileName[3] >= '0') && (fileName[3] <= '9'))) || // COM0-9 if (((fileName[0] == 'C') && (fileName[1] == 'O') && (fileName[2] == 'M') && ((fileName[3] >= '0') && (fileName[3] <= '9'))) || // COM0-9
((fileName[0] == 'L') && (fileName[1] == 'P') && (fileName[2] == 'T') && ((fileName[3] >= '0') && (fileName[3] <= '9')))) valid = false; // LPT0-9 ((fileName[0] == 'L') && (fileName[1] == 'P') && (fileName[2] == 'T') && ((fileName[3] >= '0') && (fileName[3] <= '9')))) valid = false; // LPT0-9

View File

@ -1153,6 +1153,7 @@ static double rlCullDistanceFar = RL_CULL_DISTANCE_FAR;
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
static rlglData RLGL = { 0 }; static rlglData RLGL = { 0 };
#endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2 #endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2
static bool isGpuReady = false;
#if defined(GRAPHICS_API_OPENGL_ES2) && !defined(GRAPHICS_API_OPENGL_ES3) #if defined(GRAPHICS_API_OPENGL_ES2) && !defined(GRAPHICS_API_OPENGL_ES3)
// NOTE: VAO functionality is exposed through extensions (OES) // 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 // Initialize rlgl: OpenGL extensions, default buffers/shaders/textures, OpenGL states
void rlglInit(int width, int height) void rlglInit(int width, int height)
{ {
isGpuReady = true;
// Enable OpenGL debug context if required // Enable OpenGL debug context if required
#if defined(RLGL_ENABLE_OPENGL_DEBUG_CONTEXT) && defined(GRAPHICS_API_OPENGL_43) #if defined(RLGL_ENABLE_OPENGL_DEBUG_CONTEXT) && defined(GRAPHICS_API_OPENGL_43)
if ((glDebugMessageCallback != NULL) && (glDebugMessageControl != NULL)) if ((glDebugMessageCallback != NULL) && (glDebugMessageControl != NULL))
@ -2395,6 +2398,7 @@ void rlglClose(void)
#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE) #if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
swClose(); // Unload sofware renderer resources swClose(); // Unload sofware renderer resources
#endif #endif
isGpuReady = false;
} }
// Load OpenGL extensions // Load OpenGL extensions
@ -2492,12 +2496,12 @@ void rlLoadExtensions(void *loader)
const char *extensions = (const char *)glGetString(GL_EXTENSIONS); // One big const string const char *extensions = (const char *)glGetString(GL_EXTENSIONS); // One big const string
// NOTE: We have to duplicate string because glGetString() returns a const string // NOTE: We have to duplicate string because glGetString() returns a const string
int extSize = (int)strlen(extensions); // Get extensions string size in bytes int extensionsLength = (int)strlen(extensions); // Get extensions string size in bytes
char *extensionsDup = (char *)RL_CALLOC(extSize + 1, sizeof(char)); // Allocate space for copy with additional EOL byte char *extensionsDup = (char *)RL_CALLOC(extensionsLength + 1, sizeof(char)); // Allocate space for copy with additional EOL byte
strncpy(extensionsDup, extensions, extSize); strncpy(extensionsDup, extensions, extensionsLength);
extList[numExt] = extensionsDup; extList[numExt] = extensionsDup;
for (int i = 0; i < extSize; i++) for (int i = 0; i < extensionsLength; i++)
{ {
if (extensionsDup[i] == ' ') if (extensionsDup[i] == ' ')
{ {
@ -2799,6 +2803,7 @@ int *rlGetShaderLocsDefault(void)
rlRenderBatch rlLoadRenderBatch(int numBuffers, int bufferElements) rlRenderBatch rlLoadRenderBatch(int numBuffers, int bufferElements)
{ {
rlRenderBatch batch = { 0 }; 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) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
// Initialize CPU (RAM) vertex buffers (position, texcoord, color data and indexes) // 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 rlLoadTexture(const void *data, int width, int height, int format, int mipmapCount)
{ {
unsigned int id = 0; 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 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 rlLoadTextureDepth(int width, int height, bool useRenderBuffer)
{ {
unsigned int id = 0; 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) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
// In case depth textures not supported, we force renderbuffer usage // 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 rlLoadTextureCubemap(const void *data, int size, int format, int mipmapCount)
{ {
unsigned int id = 0; 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) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
int mipSize = size; int mipSize = size;
@ -3813,6 +3821,7 @@ unsigned char *rlReadScreenPixels(int width, int height)
unsigned int rlLoadFramebuffer(void) unsigned int rlLoadFramebuffer(void)
{ {
unsigned int fboId = 0; 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) #if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(RLGL_RENDER_TEXTURES_HINT)
glGenFramebuffers(1, &fboId); // Create the framebuffer object 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 rlLoadVertexBuffer(const void *buffer, int size, bool dynamic)
{ {
unsigned int id = 0; 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) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
glGenBuffers(1, &id); 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 rlLoadVertexBufferElement(const void *buffer, int size, bool dynamic)
{ {
unsigned int id = 0; 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) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
glGenBuffers(1, &id); glGenBuffers(1, &id);
@ -4107,12 +4118,12 @@ void rlDisableStatePointer(int vertexAttribType)
unsigned int rlLoadVertexArray(void) unsigned int rlLoadVertexArray(void)
{ {
unsigned int vaoId = 0; 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 defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
if (RLGL.ExtSupported.vao) if (RLGL.ExtSupported.vao) glGenVertexArrays(1, &vaoId);
{
glGenVertexArrays(1, &vaoId);
}
#endif #endif
return vaoId; return vaoId;
} }
@ -4167,6 +4178,7 @@ void rlUnloadVertexBuffer(unsigned int vboId)
unsigned int rlLoadShaderCode(const char *vsCode, const char *fsCode) unsigned int rlLoadShaderCode(const char *vsCode, const char *fsCode)
{ {
unsigned int id = 0; 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) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
unsigned int vertexShaderId = 0; 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 rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId)
{ {
unsigned int programId = 0; 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) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
GLint success = 0; GLint success = 0;

View File

@ -1282,6 +1282,8 @@ void UploadMesh(Mesh *mesh, bool dynamic)
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
mesh->vaoId = rlLoadVertexArray(); mesh->vaoId = rlLoadVertexArray();
if (mesh->vaoId == 0) return;
rlEnableVertexArray(mesh->vaoId); rlEnableVertexArray(mesh->vaoId);
// NOTE: Vertex attributes must be uploaded considering default locations points and available vertex data // NOTE: Vertex attributes must be uploaded considering default locations points and available vertex data
@ -1470,6 +1472,8 @@ void DrawMesh(Mesh mesh, Material material, Matrix transform)
// Bind shader program // Bind shader program
rlEnableShader(material.shader.id); rlEnableShader(material.shader.id);
if (material.shader.locs == NULL) return;
// Send required data to shader (matrices, values) // Send required data to shader (matrices, values)
//----------------------------------------------------- //-----------------------------------------------------
// Upload to shader material.colDiffuse // Upload to shader material.colDiffuse

View File

@ -127,7 +127,6 @@
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Global variables // Global variables
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
extern bool isGpuReady;
#if defined(SUPPORT_DEFAULT_FONT) #if defined(SUPPORT_DEFAULT_FONT)
// Default font provided by raylib // Default font provided by raylib
// NOTE: Default font is loaded on InitWindow() and disposed on CloseWindow() [module: core] // NOTE: Default font is loaded on InitWindow() and disposed on CloseWindow() [module: core]
@ -164,8 +163,8 @@ extern void LoadFontDefault(void)
{ {
#define BIT_CHECK(a,b) ((a) & (1u << (b))) #define BIT_CHECK(a,b) ((a) & (1u << (b)))
// Check to see if we have allready allocated the font for an image, and if we don't need to upload, then just return // Check to see if we have already allocated the font for an image, and if we don't need to upload, then just return
if ((defaultFont.glyphs != NULL) && !isGpuReady) return; if (defaultFont.glyphs != NULL) return;
// NOTE: Using UTF-8 encoding table for Unicode U+0000..U+00FF Basic Latin + Latin-1 Supplement // NOTE: Using UTF-8 encoding table for Unicode U+0000..U+00FF Basic Latin + Latin-1 Supplement
// Ref: http://www.utf8-chartable.de/unicode-utf8-table.pl // Ref: http://www.utf8-chartable.de/unicode-utf8-table.pl
@ -263,8 +262,6 @@ extern void LoadFontDefault(void)
counter++; counter++;
} }
if (isGpuReady)
{
defaultFont.texture = LoadTextureFromImage(imFont); defaultFont.texture = LoadTextureFromImage(imFont);
// we have already loaded the font glyph data an image, and the GPU is ready, we are done // we have already loaded the font glyph data an image, and the GPU is ready, we are done
@ -274,7 +271,6 @@ extern void LoadFontDefault(void)
UnloadImage(imFont); UnloadImage(imFont);
return; return;
} }
}
// Reconstruct charSet using charsWidth[], charsHeight, charsDivisor, glyphCount // Reconstruct charSet using charsWidth[], charsHeight, charsDivisor, glyphCount
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -330,7 +326,7 @@ extern void LoadFontDefault(void)
extern void UnloadFontDefault(void) extern void UnloadFontDefault(void)
{ {
for (int i = 0; i < defaultFont.glyphCount; i++) UnloadImage(defaultFont.glyphs[i].image); for (int i = 0; i < defaultFont.glyphCount; i++) UnloadImage(defaultFont.glyphs[i].image);
if (isGpuReady) UnloadTexture(defaultFont.texture); UnloadTexture(defaultFont.texture);
RL_FREE(defaultFont.glyphs); RL_FREE(defaultFont.glyphs);
RL_FREE(defaultFont.recs); RL_FREE(defaultFont.recs);
defaultFont.glyphCount = 0; defaultFont.glyphCount = 0;
@ -384,18 +380,16 @@ Font LoadFont(const char *fileName)
{ {
Image image = LoadImage(fileName); Image image = LoadImage(fileName);
if (image.data != NULL) font = LoadFontFromImage(image, MAGENTA, FONT_TTF_DEFAULT_FIRST_CHAR); if (image.data != NULL) font = LoadFontFromImage(image, MAGENTA, FONT_TTF_DEFAULT_FIRST_CHAR);
else font = GetFontDefault();
UnloadImage(image); UnloadImage(image);
} }
if (isGpuReady)
{
if (font.texture.id == 0) TRACELOG(LOG_WARNING, "FONT: [%s] Failed to load font texture -> Using default font", fileName); if (font.texture.id == 0) TRACELOG(LOG_WARNING, "FONT: [%s] Failed to load font texture -> Using default font", fileName);
else else
{ {
SetTextureFilter(font.texture, TEXTURE_FILTER_POINT); // By default, we set point filter (the best performance) SetTextureFilter(font.texture, TEXTURE_FILTER_POINT); // By default, we set point filter (the best performance)
TRACELOG(LOG_INFO, "FONT: Data loaded successfully (%i pixel size | %i glyphs)", font.baseSize, font.glyphCount); TRACELOG(LOG_INFO, "FONT: Data loaded successfully (%i pixel size | %i glyphs)", font.baseSize, font.glyphCount);
} }
}
return font; return font;
} }
@ -515,7 +509,7 @@ Font LoadFontFromImage(Image image, Color key, int firstChar)
}; };
// Set font with all data parsed from image // Set font with all data parsed from image
if (isGpuReady) font.texture = LoadTextureFromImage(fontClear); // Convert processed image to OpenGL texture font.texture = LoadTextureFromImage(fontClear); // Convert processed image to OpenGL texture
font.glyphCount = index; font.glyphCount = index;
font.glyphPadding = 0; font.glyphPadding = 0;
@ -584,7 +578,7 @@ Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int
font.glyphPadding = FONT_TTF_DEFAULT_CHARS_PADDING; font.glyphPadding = FONT_TTF_DEFAULT_CHARS_PADDING;
Image atlas = GenImageFontAtlas(font.glyphs, &font.recs, font.glyphCount, font.baseSize, font.glyphPadding, 0); Image atlas = GenImageFontAtlas(font.glyphs, &font.recs, font.glyphCount, font.baseSize, font.glyphPadding, 0);
if (isGpuReady) font.texture = LoadTextureFromImage(atlas); font.texture = LoadTextureFromImage(atlas);
// Update glyphs[i].image to use alpha, required to be used on ImageDrawText() // Update glyphs[i].image to use alpha, required to be used on ImageDrawText()
for (int i = 0; i < font.glyphCount; i++) for (int i = 0; i < font.glyphCount; i++)
@ -1008,7 +1002,7 @@ void UnloadFont(Font font)
if (font.texture.id != GetFontDefault().texture.id) if (font.texture.id != GetFontDefault().texture.id)
{ {
UnloadFontData(font.glyphs, font.glyphCount); UnloadFontData(font.glyphs, font.glyphCount);
if (isGpuReady) UnloadTexture(font.texture); UnloadTexture(font.texture);
RL_FREE(font.recs); RL_FREE(font.recs);
TRACELOGD("FONT: Unloaded font data from RAM and VRAM"); TRACELOGD("FONT: Unloaded font data from RAM and VRAM");
@ -1339,8 +1333,7 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
{ {
Vector2 textSize = { 0 }; Vector2 textSize = { 0 };
if ((isGpuReady && (font.texture.id == 0)) || if ((font.texture.id == 0) || (text == NULL) || (text[0] == '\0')) return textSize; // Security check
(text == NULL) || (text[0] == '\0')) return textSize; // Security check
int size = TextLength(text); // Get size in bytes of text int size = TextLength(text); // Get size in bytes of text
int tempByteCounter = 0; // Used to count longer text line num chars int tempByteCounter = 0; // Used to count longer text line num chars
@ -1456,17 +1449,17 @@ char **LoadTextLines(const char *text, int *count)
if (text != NULL) if (text != NULL)
{ {
int textSize = TextLength(text); int textLength = TextLength(text);
lineCount = 1; lineCount = 1;
// First text scan pass to get required line count // First text scan pass to get required line count
for (int i = 0; i < textSize; i++) for (int i = 0; i < textLength; i++)
{ {
if (text[i] == '\n') lineCount++; if (text[i] == '\n') lineCount++;
} }
lines = (char **)RL_CALLOC(lineCount, sizeof(char *)); lines = (char **)RL_CALLOC(lineCount, sizeof(char *));
for (int i = 0, l = 0, lineLen = 0; i <= textSize; i++) for (int i = 0, l = 0, lineLen = 0; i <= textLength; i++)
{ {
if ((text[i] == '\n') || (text[i] == '\0')) if ((text[i] == '\n') || (text[i] == '\0'))
{ {
@ -2481,7 +2474,7 @@ static Font LoadBMFont(const char *fileName)
RL_FREE(imFonts); RL_FREE(imFonts);
if (isGpuReady) font.texture = LoadTextureFromImage(fullFont); font.texture = LoadTextureFromImage(fullFont);
// Fill font characters info data // Fill font characters info data
font.baseSize = fontSize; font.baseSize = fontSize;
@ -2523,7 +2516,7 @@ static Font LoadBMFont(const char *fileName)
UnloadImage(fullFont); UnloadImage(fullFont);
UnloadFileText(fileText); UnloadFileText(fileText);
if (isGpuReady && (font.texture.id == 0)) if (font.texture.id == 0)
{ {
UnloadFont(font); UnloadFont(font);
font = GetFontDefault(); font = GetFontDefault();

View File

@ -1488,7 +1488,7 @@ Image ImageTextEx(Font font, const char *text, float fontSize, float spacing, Co
#if defined(SUPPORT_MODULE_RTEXT) #if defined(SUPPORT_MODULE_RTEXT)
if (text == NULL) return imText; if (text == NULL) return imText;
int size = (int)strlen(text); // Get size in bytes of text int textLength = (int)strlen(text); // Get length of text in bytes
int textOffsetX = 0; // Image drawing position X int textOffsetX = 0; // Image drawing position X
int textOffsetY = 0; // Offset between lines (on linebreak '\n') int textOffsetY = 0; // Offset between lines (on linebreak '\n')
@ -1499,7 +1499,7 @@ Image ImageTextEx(Font font, const char *text, float fontSize, float spacing, Co
// Create image to store text // Create image to store text
imText = GenImageColor((int)imSize.x, (int)imSize.y, BLANK); imText = GenImageColor((int)imSize.x, (int)imSize.y, BLANK);
for (int i = 0; i < size;) for (int i = 0; i < textLength;)
{ {
// Get next codepoint from byte string and glyph index in font // Get next codepoint from byte string and glyph index in font
int codepointByteCount = 0; int codepointByteCount = 0;

View File

@ -142,8 +142,8 @@ void TraceLog(int logType, const char *text, ...)
default: break; default: break;
} }
unsigned int textSize = (unsigned int)strlen(text); unsigned int textLength = (unsigned int)strlen(text);
memcpy(buffer + strlen(buffer), text, (textSize < (MAX_TRACELOG_MSG_LENGTH - 12))? textSize : (MAX_TRACELOG_MSG_LENGTH - 12)); memcpy(buffer + strlen(buffer), text, (textLength < (MAX_TRACELOG_MSG_LENGTH - 12))? textLength : (MAX_TRACELOG_MSG_LENGTH - 12));
strcat(buffer, "\n"); strcat(buffer, "\n");
vprintf(buffer, args); vprintf(buffer, args);
fflush(stdout); fflush(stdout);