diff --git a/src/Graphics_GL1.c b/src/Graphics_GL1.c index 765ac9b83..417a6d913 100644 --- a/src/Graphics_GL1.c +++ b/src/Graphics_GL1.c @@ -72,6 +72,7 @@ typedef void (*GL_SetupVBFunc)(void); typedef void (*GL_SetupVBRangeFunc)(int startVertex); static GL_SetupVBFunc gfx_setupVBFunc; static GL_SetupVBRangeFunc gfx_setupVBRangeFunc; +static cc_bool rgba_only; #include "_GLShared.h" static void GLBackend_Init(void); @@ -359,6 +360,49 @@ void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) { /*########################################################################################################################* *---------------------------------------------------------Textures--------------------------------------------------------* *#########################################################################################################################*/ +static void ConvertRGBA(void* dst, void* src, int numPixels) { + cc_uint8* d = (cc_uint8*)dst; + cc_uint8* s = (cc_uint8*)src; + int i; + + for (i = 0; i < numPixels; i++, d += 4, s += 4) { + d[0] = s[2]; + d[1] = s[1]; + d[2] = s[0]; + d[3] = s[3]; + } +} + +static void CallTexSubImage2D(int lvl, int x, int y, int width, int height, void* pixels) { + void* tmp; + if (!rgba_only) { + _glTexSubImage2D(GL_TEXTURE_2D, lvl, x, y, width, height, PIXEL_FORMAT, TRANSFER_FORMAT, pixels); + return; + } + + tmp = Mem_TryAlloc(width * height, 4); + if (!tmp) return; + + ConvertRGBA(tmp, pixels, width * height); + _glTexSubImage2D(GL_TEXTURE_2D, lvl, x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, tmp); + Mem_Free(tmp); +} + +static void CallTexImage2D(int lvl, int width, int height, void* pixels) { + void* tmp; + if (!rgba_only) { + _glTexImage2D(GL_TEXTURE_2D, lvl, GL_RGBA, width, height, 0, PIXEL_FORMAT, TRANSFER_FORMAT, pixels); + return; + } + + tmp = Mem_TryAlloc(width * height, 4); + if (!tmp) return; + + ConvertRGBA(tmp, pixels, width * height); + _glTexImage2D(GL_TEXTURE_2D, lvl, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, tmp); + Mem_Free(tmp); +} + void Gfx_BindTexture(GfxResourceID texId) { _glBindTexture(GL_TEXTURE_2D, ptr_to_uint(texId)); } @@ -588,13 +632,7 @@ static void APIENTRY gl10_texImage(GLenum target, GLint level, GLint internalfor gl10_tex->height = height; gl10_tex->pixels = Mem_Alloc(width * height, 4, "GL 1.0 pixels"); - Mem_Copy(gl10_tex->pixels, pixels, width * height * 4); - for (i = 0; i < width * height * 4; i += 4) - { - cc_uint8 t = gl10_tex->pixels[i + 2]; - gl10_tex->pixels[i + 2] = gl10_tex->pixels[i + 0]; - gl10_tex->pixels[i + 0] = t; - } + ConvertRGBA(gl10_tex->pixels, pixels, width * height); } static void APIENTRY gl10_texSubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels) { @@ -708,7 +746,9 @@ static void GLBackend_Init(void) { DynamicLib_ReqSym2("glGenBuffersARB", glGenBuffers), DynamicLib_ReqSym2("glBufferDataARB", glBufferData), DynamicLib_ReqSym2("glBufferSubDataARB", glBufferSubData) }; - static const cc_string vboExt = String_FromConst("GL_ARB_vertex_buffer_object"); + + static const cc_string vboExt = String_FromConst("GL_ARB_vertex_buffer_object"); + static const cc_string bgraExt = String_FromConst("GL_EXT_bgra"); cc_string extensions = String_FromReadonly((const char*)_glGetString(GL_EXTENSIONS)); const GLubyte* ver = _glGetString(GL_VERSION); @@ -721,6 +761,8 @@ static void GLBackend_Init(void) { } else if (String_CaselessContains(&extensions, &vboExt)) { GLContext_GetAll(arbVboFuncs, Array_Elems(arbVboFuncs)); } else { + /* Some old IRIX cards don't support BGRA */ + rgba_only = major == 1 && minor <= 1 && String_CaselessContains(&extensions, &bgraExt); FallbackOpenGL(); } } diff --git a/src/Graphics_GL2.c b/src/Graphics_GL2.c index 607465833..ad3ccdef3 100644 --- a/src/Graphics_GL2.c +++ b/src/Graphics_GL2.c @@ -441,6 +441,14 @@ static void SwitchProgram(void) { /*########################################################################################################################* *---------------------------------------------------------Textures--------------------------------------------------------* *#########################################################################################################################*/ +static int CallTexSubImage2D(int lvl, int x, int y, int width, int height, void* pixels) { + glTexSubImage2D(GL_TEXTURE_2D, lvl, x, y, width, height, PIXEL_FORMAT, TRANSFER_FORMAT, pixels); +} + +static int CallTexImage2D(int lvl, int width, int height, void* pixels) { + glTexImage2D(GL_TEXTURE_2D, lvl, GL_RGBA, width, height, 0, PIXEL_FORMAT, TRANSFER_FORMAT, pixels); +} + void Gfx_BindTexture(GfxResourceID texId) { /* Texture 0 has different behaviour depending on backend */ /* Desktop OpenGL - pure white 1x1 texture */ diff --git a/src/_GLShared.h b/src/_GLShared.h index ced222efb..3cf030f9d 100644 --- a/src/_GLShared.h +++ b/src/_GLShared.h @@ -67,6 +67,9 @@ static void* FastAllocTempMem(int size) { /*########################################################################################################################* *---------------------------------------------------------Textures--------------------------------------------------------* *#########################################################################################################################*/ +static void CallTexSubImage2D(int lvl, int x, int y, int width, int height, void* pixels); +static void CallTexImage2D(int lvl, int width, int height, void* pixels); + static void Gfx_DoMipmaps(int x, int y, struct Bitmap* bmp, int rowWidth, cc_bool partial) { BitmapCol* prev = bmp->scan0; BitmapCol* cur; @@ -83,9 +86,9 @@ static void Gfx_DoMipmaps(int x, int y, struct Bitmap* bmp, int rowWidth, cc_boo GenMipmaps(width, height, cur, prev, rowWidth); if (partial) { - _glTexSubImage2D(GL_TEXTURE_2D, lvl, x, y, width, height, PIXEL_FORMAT, TRANSFER_FORMAT, cur); + CallTexSubImage2D(lvl, x, y, width, height, cur); } else { - _glTexImage2D(GL_TEXTURE_2D, lvl, GL_RGBA, width, height, 0, PIXEL_FORMAT, TRANSFER_FORMAT, cur); + CallTexImage2D(lvl, width, height, cur); } if (prev != bmp->scan0) Mem_Free(prev); @@ -111,9 +114,9 @@ static CC_NOINLINE void UpdateTextureSlow(int x, int y, struct Bitmap* part, int part, rowWidth * BITMAPCOLOR_SIZE); if (full) { - _glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, part->width, part->height, 0, PIXEL_FORMAT, TRANSFER_FORMAT, ptr); + CallTexImage2D(0, part->width, part->height, ptr); } else { - _glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, part->width, part->height, PIXEL_FORMAT, TRANSFER_FORMAT, ptr); + CallTexSubImage2D(0, x, y, part->width, part->height, ptr); } if (count > UPDATE_FAST_SIZE) Mem_Free(ptr); } @@ -135,7 +138,7 @@ GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, } if (bmp->width == rowWidth) { - _glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bmp->width, bmp->height, 0, PIXEL_FORMAT, TRANSFER_FORMAT, bmp->scan0); + CallTexImage2D(0, bmp->width, bmp->height, bmp->scan0); } else { UpdateTextureSlow(0, 0, bmp, rowWidth, true); } @@ -148,7 +151,7 @@ void Gfx_UpdateTexture(GfxResourceID texId, int x, int y, struct Bitmap* part, i _glBindTexture(GL_TEXTURE_2D, ptr_to_uint(texId)); if (part->width == rowWidth) { - _glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, part->width, part->height, PIXEL_FORMAT, TRANSFER_FORMAT, part->scan0); + CallTexSubImage2D(0, x, y, part->width, part->height, part->scan0); } else { UpdateTextureSlow(x, y, part, rowWidth, false); } diff --git a/src/_WindowBase.h b/src/_WindowBase.h index 6430faaa2..daa2da869 100644 --- a/src/_WindowBase.h +++ b/src/_WindowBase.h @@ -170,6 +170,12 @@ void GLContext_Create(void) { } if (!ctx_config) Window_ShowDialog("Warning", "Failed to choose EGL config, ClassiCube may be unable to start"); +#if CC_WIN_BACKEND == CC_WIN_BACKEND_X11 + EGLint visualID; + eglGetConfigAttrib(ctx_display, &ctx_config, EGL_NATIVE_VISUAL_ID, &visualID); + Platform_Log1("EGL visual ID: %h", &visualID); +#endif + ctx_context = eglCreateContext(ctx_display, ctx_config, EGL_NO_CONTEXT, context_attribs); if (!ctx_context) Process_Abort2(eglGetError(), "Failed to create EGL context"); GLContext_InitSurface();