Skip to content

Commit

Permalink
Merge pull request #664 from zturtleman/opengles2
Browse files Browse the repository at this point in the history
  • Loading branch information
NuclearMonster authored Jun 6, 2024
2 parents 1fc83e4 + 98b9008 commit 9801477
Show file tree
Hide file tree
Showing 18 changed files with 778 additions and 181 deletions.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,21 @@ Makefile.local:
The defaults for these variables differ depending on the target platform.


# OpenGL ES support

The opengl2 renderer (the default) supports OpenGL ES 2+. Though there
are many missing features and the performance may not be sufficient for
embedded System-on-a-Chip and mobile platforms.

The opengl1 renderer does not have OpenGL ES support.

The `r_useOpenGLES` cvar controls whether to use OpenGL or OpenGL ES API.
Set to -1 for auto (default), 0 for OpenGL, and 1 for OpenGL ES. It should be
set using command line arguments:

ioquake3 +set cl_renderer opengl2 +set r_useOpenGLES 1


# Console

## New cvars
Expand Down
5 changes: 3 additions & 2 deletions code/client/cl_avi.c
Original file line number Diff line number Diff line change
Expand Up @@ -357,11 +357,12 @@ qboolean CL_OpenAVIForWriting( const char *fileName )
else
afd.motionJpeg = qfalse;

// Buffers only need to store RGB pixels.
// Capture buffer stores RGB pixels but OpenGL ES reads RGBA and converts to RGB in-place.
// Encode buffer only needs to store RGB pixels.
// Allocate a bit more space for the capture buffer to account for possible
// padding at the end of pixel lines, and padding for alignment
#define MAX_PACK_LEN 16
afd.cBuffer = Z_Malloc((afd.width * 3 + MAX_PACK_LEN - 1) * afd.height + MAX_PACK_LEN - 1);
afd.cBuffer = Z_Malloc((afd.width * 4 + MAX_PACK_LEN - 1) * afd.height + MAX_PACK_LEN - 1);
// raw avi files have pixel lines start on 4-byte boundaries
afd.eBuffer = Z_Malloc(PAD(afd.width * 3, AVI_LINE_PADDING) * afd.height);

Expand Down
29 changes: 25 additions & 4 deletions code/renderergl2/tr_backend.c
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,7 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *
}

void RE_UploadCinematic (int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty) {
byte *buffer;
GLuint texture;

if (!tr.scratchImage[client])
Expand All @@ -746,7 +747,18 @@ void RE_UploadCinematic (int w, int h, int cols, int rows, const byte *data, int
if ( cols != tr.scratchImage[client]->width || rows != tr.scratchImage[client]->height ) {
tr.scratchImage[client]->width = tr.scratchImage[client]->uploadWidth = cols;
tr.scratchImage[client]->height = tr.scratchImage[client]->uploadHeight = rows;
qglTextureImage2DEXT(texture, GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);

if ( qglesMajorVersion >= 1 ) {
buffer = ri.Hunk_AllocateTempMemory( 3 * cols * rows );

R_ConvertTextureFormat( data, cols, rows, GL_RGB, GL_UNSIGNED_BYTE, buffer );
qglTextureImage2DEXT(texture, GL_TEXTURE_2D, 0, GL_RGB, cols, rows, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer);

ri.Hunk_FreeTempMemory( buffer );
} else {
qglTextureImage2DEXT(texture, GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
}

qglTextureParameterfEXT(texture, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTextureParameterfEXT(texture, GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
qglTextureParameterfEXT(texture, GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
Expand All @@ -755,7 +767,16 @@ void RE_UploadCinematic (int w, int h, int cols, int rows, const byte *data, int
if (dirty) {
// otherwise, just subimage upload it so that drivers can tell we are going to be changing
// it and don't try and do a texture compression
qglTextureSubImage2DEXT(texture, GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data);
if ( qglesMajorVersion >= 1 ) {
buffer = ri.Hunk_AllocateTempMemory( 3 * cols * rows );

R_ConvertTextureFormat( data, cols, rows, GL_RGB, GL_UNSIGNED_BYTE, buffer );
qglTextureSubImage2DEXT(texture, GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGB, GL_UNSIGNED_BYTE, buffer);

ri.Hunk_FreeTempMemory( buffer );
} else {
qglTextureSubImage2DEXT(texture, GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data);
}
}
}
}
Expand Down Expand Up @@ -1140,14 +1161,14 @@ const void *RB_DrawSurfs( const void *data ) {
if (glRefConfig.occlusionQuery)
{
tr.sunFlareQueryActive[tr.sunFlareQueryIndex] = qtrue;
qglBeginQuery(GL_SAMPLES_PASSED, tr.sunFlareQuery[tr.sunFlareQueryIndex]);
qglBeginQuery(glRefConfig.occlusionQueryTarget, tr.sunFlareQuery[tr.sunFlareQueryIndex]);
}

RB_DrawSun(0.3, tr.sunFlareShader);

if (glRefConfig.occlusionQuery)
{
qglEndQuery(GL_SAMPLES_PASSED);
qglEndQuery(glRefConfig.occlusionQueryTarget);
}

FBO_Bind(oldFbo);
Expand Down
2 changes: 1 addition & 1 deletion code/renderergl2/tr_bsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ static void R_LoadLightmaps( lump_t *l, lump_t *surfs ) {
tr.deluxemaps = ri.Hunk_Alloc( tr.numLightmaps * sizeof(image_t *), h_low );

textureInternalFormat = GL_RGBA8;
if (r_hdr->integer)
if (r_hdr->integer && !qglesMajorVersion)
{
// Check for the first hdr lightmap, if it exists, use GL_RGBA16 for textures.
char filename[MAX_QPATH];
Expand Down
15 changes: 14 additions & 1 deletion code/renderergl2/tr_cmds.c
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,13 @@ void RE_BeginFrame( stereoFrame_t stereoFrame ) {
//
if ( r_measureOverdraw->integer )
{
if ( glConfig.stencilBits < 4 )
if ( qglesMajorVersion >= 1 && !glRefConfig.readStencil )
{
ri.Printf( PRINT_WARNING, "OpenGL ES needs GL_NV_read_stencil to read stencil bits to measure overdraw\n" );
ri.Cvar_Set( "r_measureOverdraw", "0" );
r_measureOverdraw->modified = qfalse;
}
else if ( glConfig.stencilBits < 4 )
{
ri.Printf( PRINT_ALL, "Warning: not enough stencil bits to measure overdraw: %d\n", glConfig.stencilBits );
ri.Cvar_Set( "r_measureOverdraw", "0" );
Expand Down Expand Up @@ -426,6 +432,13 @@ void RE_BeginFrame( stereoFrame_t stereoFrame ) {
}
else
{
if (qglesMajorVersion >= 1 && r_anaglyphMode->integer)
{
ri.Printf( PRINT_WARNING, "OpenGL ES does not support drawing to separate buffer for anaglyph mode\n" );
ri.Cvar_Set( "r_anaglyphMode", "0" );
r_anaglyphMode->modified = qfalse;
}

if(r_anaglyphMode->integer)
{
if(r_anaglyphMode->modified)
Expand Down
132 changes: 120 additions & 12 deletions code/renderergl2/tr_extensions.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,17 @@ void GLimp_InitExtraExtensions(void)
if (strstr((char *)qglGetString(GL_RENDERER), "Intel"))
glRefConfig.intelGraphics = qtrue;

if (qglesMajorVersion)
{
glRefConfig.vaoCacheGlIndexType = GL_UNSIGNED_SHORT;
glRefConfig.vaoCacheGlIndexSize = sizeof(unsigned short);
}
else
{
glRefConfig.vaoCacheGlIndexType = GL_UNSIGNED_INT;
glRefConfig.vaoCacheGlIndexSize = sizeof(unsigned int);
}

// set DSA fallbacks
#define GLE(ret, name, ...) qgl##name = GLDSA_##name;
QGL_EXT_direct_state_access_PROCS;
Expand All @@ -53,8 +64,96 @@ void GLimp_InitExtraExtensions(void)
// GL function loader, based on https://gist.github.com/rygorous/16796a0c876cf8a5f542caddb55bce8a
#define GLE(ret, name, ...) qgl##name = (name##proc *) SDL_GL_GetProcAddress("gl" #name);

//
// OpenGL ES extensions
//
if (qglesMajorVersion)
{
if (!r_allowExtensions->integer)
goto done;

extension = "GL_EXT_occlusion_query_boolean";
if (SDL_GL_ExtensionSupported(extension))
{
glRefConfig.occlusionQuery = qtrue;
glRefConfig.occlusionQueryTarget = GL_ANY_SAMPLES_PASSED;

QGL_ARB_occlusion_query_PROCS;

ri.Printf(PRINT_ALL, result[glRefConfig.occlusionQuery], extension);
}
else
{
ri.Printf(PRINT_ALL, result[2], extension);
}

// GL_NV_read_depth
extension = "GL_NV_read_depth";
if (SDL_GL_ExtensionSupported(extension))
{
glRefConfig.readDepth = qtrue;
ri.Printf(PRINT_ALL, result[glRefConfig.readDepth], extension);
}
else
{
ri.Printf(PRINT_ALL, result[2], extension);
}

// GL_NV_read_stencil
extension = "GL_NV_read_stencil";
if (SDL_GL_ExtensionSupported(extension))
{
glRefConfig.readStencil = qtrue;
ri.Printf(PRINT_ALL, result[glRefConfig.readStencil], extension);
}
else
{
ri.Printf(PRINT_ALL, result[2], extension);
}

// GL_EXT_shadow_samplers
extension = "GL_EXT_shadow_samplers";
if (qglesMajorVersion >= 3 || SDL_GL_ExtensionSupported(extension))
{
glRefConfig.shadowSamplers = qtrue;
ri.Printf(PRINT_ALL, result[glRefConfig.shadowSamplers], extension);
}
else
{
ri.Printf(PRINT_ALL, result[2], extension);
}

// GL_OES_standard_derivatives
extension = "GL_OES_standard_derivatives";
if (qglesMajorVersion >= 3 || SDL_GL_ExtensionSupported(extension))
{
glRefConfig.standardDerivatives = qtrue;
ri.Printf(PRINT_ALL, result[glRefConfig.standardDerivatives], extension);
}
else
{
ri.Printf(PRINT_ALL, result[2], extension);
}

// GL_OES_element_index_uint
extension = "GL_OES_element_index_uint";
if (SDL_GL_ExtensionSupported(extension))
{
glRefConfig.vaoCacheGlIndexType = GL_UNSIGNED_INT;
glRefConfig.vaoCacheGlIndexSize = sizeof(unsigned int);
ri.Printf(PRINT_ALL, result[1], extension);
}
else
{
ri.Printf(PRINT_ALL, result[2], extension);
}

goto done;
}

// OpenGL 1.5 - GL_ARB_occlusion_query
glRefConfig.occlusionQuery = qtrue;
glRefConfig.occlusionQueryTarget = GL_SAMPLES_PASSED;
QGL_ARB_occlusion_query_PROCS;

// OpenGL 3.0 - GL_ARB_framebuffer_object
Expand Down Expand Up @@ -146,18 +245,6 @@ void GLimp_InitExtraExtensions(void)
ri.Printf(PRINT_ALL, result[2], extension);
}

// Determine GLSL version
if (1)
{
char version[256];

Q_strncpyz(version, (char *)qglGetString(GL_SHADING_LANGUAGE_VERSION), sizeof(version));

sscanf(version, "%d.%d", &glRefConfig.glslMajorVersion, &glRefConfig.glslMinorVersion);

ri.Printf(PRINT_ALL, "...using GLSL version %s\n", version);
}

glRefConfig.memInfo = MI_NONE;

// GL_NVX_gpu_memory_info
Expand Down Expand Up @@ -249,5 +336,26 @@ void GLimp_InitExtraExtensions(void)
ri.Printf(PRINT_ALL, result[2], extension);
}

done:

// Determine GLSL version
if (1)
{
char version[256], *version_p;

Q_strncpyz(version, (char *)qglGetString(GL_SHADING_LANGUAGE_VERSION), sizeof(version));

// Skip leading text such as "OpenGL ES GLSL ES "
version_p = version;
while ( *version_p && !isdigit( *version_p ) )
{
version_p++;
}

sscanf(version_p, "%d.%d", &glRefConfig.glslMajorVersion, &glRefConfig.glslMinorVersion);

ri.Printf(PRINT_ALL, "...using GLSL version %s\n", version);
}

#undef GLE
}
8 changes: 8 additions & 0 deletions code/renderergl2/tr_flares.c
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,14 @@ void RB_RenderFlares (void) {
return;
}

if ( r_flares->modified ) {
if ( qglesMajorVersion >= 1 && !glRefConfig.readDepth ) {
ri.Printf( PRINT_WARNING, "OpenGL ES needs GL_NV_read_depth to read depth to determine if flares are visible\n" );
ri.Cvar_Set( "r_flares", "0" );
}
r_flares->modified = qfalse;
}

if(r_flareCoeff->modified)
{
R_SetFlareCoeff();
Expand Down
Loading

0 comments on commit 9801477

Please sign in to comment.