diff --git a/src/gl/system/gl_interface.cpp b/src/gl/system/gl_interface.cpp index 7f98c7f3c..485876e7a 100644 --- a/src/gl/system/gl_interface.cpp +++ b/src/gl/system/gl_interface.cpp @@ -130,8 +130,16 @@ void gl_LoadExtensions() InitContext(); CollectExtensions(); - const char *version = Args->CheckValue("-glversion"); const char *glversion = (const char*)glGetString(GL_VERSION); + gl.es = false; + + if (glversion && strlen(glversion) > 10 && memcmp(glversion, "OpenGL ES ", 10) == 0) + { + glversion += 10; + gl.es = true; + } + + const char *version = Args->CheckValue("-glversion"); if (version == NULL) { @@ -147,90 +155,117 @@ void gl_LoadExtensions() float gl_version = (float)strtod(version, NULL) + 0.01f; - // Don't even start if it's lower than 2.0 or no framebuffers are available (The framebuffer extension is needed for glGenerateMipmapsEXT!) - if ((gl_version < 2.0f || !CheckExtension("GL_EXT_framebuffer_object")) && gl_version < 3.0f) + if (gl.es) { - I_FatalError("Unsupported OpenGL version.\nAt least OpenGL 2.0 with framebuffer support is required to run " GAMENAME ".\n"); - } + if (gl_version < 2.0f) + { + I_FatalError("Unsupported OpenGL ES version.\nAt least OpenGL ES 2.0 is required to run " GAMENAME ".\n"); + } + + const char *glslversion = (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION); + if (glslversion && strlen(glslversion) > 18 && memcmp(glslversion, "OpenGL ES GLSL ES ", 10) == 0) + { + glslversion += 18; + } + + // add 0.01 to account for roundoff errors making the number a tad smaller than the actual version + gl.glslversion = strtod(glslversion, NULL) + 0.01f; + gl.vendorstring = (char*)glGetString(GL_VENDOR); - // add 0.01 to account for roundoff errors making the number a tad smaller than the actual version - gl.glslversion = strtod((char*)glGetString(GL_SHADING_LANGUAGE_VERSION), NULL) + 0.01f; - - gl.vendorstring = (char*)glGetString(GL_VENDOR); - - // first test for optional features - if (CheckExtension("GL_ARB_texture_compression")) gl.flags |= RFL_TEXTURE_COMPRESSION; - if (CheckExtension("GL_EXT_texture_compression_s3tc")) gl.flags |= RFL_TEXTURE_COMPRESSION_S3TC; - - if ((gl_version >= 3.3f || CheckExtension("GL_ARB_sampler_objects")) && !Args->CheckParm("-nosampler")) - { - gl.flags |= RFL_SAMPLER_OBJECTS; - } - - // The minimum requirement for the modern render path are GL 3.0 + uniform buffers. Also exclude the Linux Mesa driver at GL 3.0 because it errors out on shader compilation. - if (gl_version < 3.0f || (gl_version < 3.1f && (!CheckExtension("GL_ARB_uniform_buffer_object") || strstr(gl.vendorstring, "X.Org") != nullptr))) - { - gl.legacyMode = true; - gl.lightmethod = LM_LEGACY; - gl.buffermethod = BM_LEGACY; - gl.glslversion = 0; - gl.flags |= RFL_NO_CLIP_PLANES; - } - else - { + // Use the slowest/oldest modern path for now gl.legacyMode = false; gl.lightmethod = LM_DEFERRED; gl.buffermethod = BM_DEFERRED; - if (gl_version < 4.f) + } + else + { + // Don't even start if it's lower than 2.0 or no framebuffers are available (The framebuffer extension is needed for glGenerateMipmapsEXT!) + if ((gl_version < 2.0f || !CheckExtension("GL_EXT_framebuffer_object")) && gl_version < 3.0f) { -#ifdef _WIN32 - if (strstr(gl.vendorstring, "ATI Tech")) - { - gl.flags |= RFL_NO_CLIP_PLANES; // gl_ClipDistance is horribly broken on ATI GL3 drivers for Windows. - } -#endif + I_FatalError("Unsupported OpenGL version.\nAt least OpenGL 2.0 with framebuffer support is required to run " GAMENAME ".\n"); } - else if (gl_version < 4.5f) + + gl.es = false; + + // add 0.01 to account for roundoff errors making the number a tad smaller than the actual version + gl.glslversion = strtod((char*)glGetString(GL_SHADING_LANGUAGE_VERSION), NULL) + 0.01f; + + gl.vendorstring = (char*)glGetString(GL_VENDOR); + + // first test for optional features + if (CheckExtension("GL_ARB_texture_compression")) gl.flags |= RFL_TEXTURE_COMPRESSION; + if (CheckExtension("GL_EXT_texture_compression_s3tc")) gl.flags |= RFL_TEXTURE_COMPRESSION_S3TC; + + if ((gl_version >= 3.3f || CheckExtension("GL_ARB_sampler_objects")) && !Args->CheckParm("-nosampler")) { - // don't use GL 4.x features when running a GL 3.x context. - if (CheckExtension("GL_ARB_buffer_storage")) - { - // work around a problem with older AMD drivers: Their implementation of shader storage buffer objects is piss-poor and does not match uniform buffers even closely. - // Recent drivers, GL 4.4 don't have this problem, these can easily be recognized by also supporting the GL_ARB_buffer_storage extension. - if (CheckExtension("GL_ARB_shader_storage_buffer_object")) - { - // Shader storage buffer objects are broken on current Intel drivers. - if (strstr(gl.vendorstring, "Intel") == NULL) - { - gl.flags |= RFL_SHADER_STORAGE_BUFFER; - } - } - gl.flags |= RFL_BUFFER_STORAGE; - gl.lightmethod = LM_DIRECT; - gl.buffermethod = BM_PERSISTENT; - } + gl.flags |= RFL_SAMPLER_OBJECTS; + } + + // The minimum requirement for the modern render path are GL 3.0 + uniform buffers. Also exclude the Linux Mesa driver at GL 3.0 because it errors out on shader compilation. + if (gl_version < 3.0f || (gl_version < 3.1f && (!CheckExtension("GL_ARB_uniform_buffer_object") || strstr(gl.vendorstring, "X.Org") != nullptr))) + { + gl.legacyMode = true; + gl.lightmethod = LM_LEGACY; + gl.buffermethod = BM_LEGACY; + gl.glslversion = 0; + gl.flags |= RFL_NO_CLIP_PLANES; } else { - // Assume that everything works without problems on GL 4.5 drivers where these things are core features. - gl.flags |= RFL_SHADER_STORAGE_BUFFER | RFL_BUFFER_STORAGE; - gl.lightmethod = LM_DIRECT; - gl.buffermethod = BM_PERSISTENT; - } + gl.legacyMode = false; + gl.lightmethod = LM_DEFERRED; + gl.buffermethod = BM_DEFERRED; + if (gl_version < 4.f) + { +#ifdef _WIN32 + if (strstr(gl.vendorstring, "ATI Tech")) + { + gl.flags |= RFL_NO_CLIP_PLANES; // gl_ClipDistance is horribly broken on ATI GL3 drivers for Windows. + } +#endif + } + else if (gl_version < 4.5f) + { + // don't use GL 4.x features when running a GL 3.x context. + if (CheckExtension("GL_ARB_buffer_storage")) + { + // work around a problem with older AMD drivers: Their implementation of shader storage buffer objects is piss-poor and does not match uniform buffers even closely. + // Recent drivers, GL 4.4 don't have this problem, these can easily be recognized by also supporting the GL_ARB_buffer_storage extension. + if (CheckExtension("GL_ARB_shader_storage_buffer_object")) + { + // Shader storage buffer objects are broken on current Intel drivers. + if (strstr(gl.vendorstring, "Intel") == NULL) + { + gl.flags |= RFL_SHADER_STORAGE_BUFFER; + } + } + gl.flags |= RFL_BUFFER_STORAGE; + gl.lightmethod = LM_DIRECT; + gl.buffermethod = BM_PERSISTENT; + } + } + else + { + // Assume that everything works without problems on GL 4.5 drivers where these things are core features. + gl.flags |= RFL_SHADER_STORAGE_BUFFER | RFL_BUFFER_STORAGE; + gl.lightmethod = LM_DIRECT; + gl.buffermethod = BM_PERSISTENT; + } - if (gl_version >= 4.3f || CheckExtension("GL_ARB_invalidate_subdata")) gl.flags |= RFL_INVALIDATE_BUFFER; - if (gl_version >= 4.3f || CheckExtension("GL_KHR_debug")) gl.flags |= RFL_DEBUG; + if (gl_version >= 4.3f || CheckExtension("GL_ARB_invalidate_subdata")) gl.flags |= RFL_INVALIDATE_BUFFER; + if (gl_version >= 4.3f || CheckExtension("GL_KHR_debug")) gl.flags |= RFL_DEBUG; - const char *lm = Args->CheckValue("-lightmethod"); - if (lm != NULL) - { - if (!stricmp(lm, "deferred") && gl.lightmethod == LM_DIRECT) gl.lightmethod = LM_DEFERRED; - } + const char *lm = Args->CheckValue("-lightmethod"); + if (lm != NULL) + { + if (!stricmp(lm, "deferred") && gl.lightmethod == LM_DIRECT) gl.lightmethod = LM_DEFERRED; + } - lm = Args->CheckValue("-buffermethod"); - if (lm != NULL) - { - if (!stricmp(lm, "deferred") && gl.buffermethod == BM_PERSISTENT) gl.buffermethod = BM_DEFERRED; + lm = Args->CheckValue("-buffermethod"); + if (lm != NULL) + { + if (!stricmp(lm, "deferred") && gl.buffermethod == BM_PERSISTENT) gl.buffermethod = BM_DEFERRED; + } } } diff --git a/src/gl/system/gl_interface.h b/src/gl/system/gl_interface.h index edaec58c0..a839e13b4 100644 --- a/src/gl/system/gl_interface.h +++ b/src/gl/system/gl_interface.h @@ -66,6 +66,7 @@ struct RenderContext int max_texturesize; char * vendorstring; bool legacyMode; + bool es; int MaxLights() const { diff --git a/src/gl/system/gl_swframebuffer.cpp b/src/gl/system/gl_swframebuffer.cpp index 7bcb71f6b..2250588d3 100644 --- a/src/gl/system/gl_swframebuffer.cpp +++ b/src/gl/system/gl_swframebuffer.cpp @@ -303,8 +303,11 @@ OpenGLSWFrameBuffer::HWPixelShader::~HWPixelShader() bool OpenGLSWFrameBuffer::CreateFrameBuffer(const FString &name, int width, int height, HWFrameBuffer **outFramebuffer) { auto fb = std::make_unique(); + + GLint format = GL_RGBA16F; + if (gl.es) format = GL_RGB; - if (!CreateTexture(name, width, height, 1, GL_RGBA16F, &fb->Texture)) + if (!CreateTexture(name, width, height, 1, format, &fb->Texture)) { outFramebuffer = nullptr; return false; @@ -329,7 +332,7 @@ bool OpenGLSWFrameBuffer::CreateFrameBuffer(const FString &name, int width, int if (result != GL_FRAMEBUFFER_COMPLETE) { - //Printf("Framebuffer is not complete"); + Printf("Framebuffer is not complete\n"); outFramebuffer = nullptr; return false; } @@ -351,6 +354,7 @@ bool OpenGLSWFrameBuffer::CreatePixelShader(FString vertexsrc, FString fragments FString prefix; prefix.AppendFormat("#version %d\n%s\n#line 0\n", shaderVersion, defines.GetChars()); + //Printf("Shader prefix: %s", prefix.GetChars()); vertexsrc = prefix + vertexsrc; fragmentsrc = prefix + fragmentsrc; @@ -400,7 +404,7 @@ bool OpenGLSWFrameBuffer::CreatePixelShader(FString vertexsrc, FString fragments GLsizei length = 0; buffer[0] = 0; glGetProgramInfoLog(shader->Program, 10000, &length, buffer); - //Printf("Shader compile failed: %s", buffer); + //Printf("Shader link failed: %s", buffer); *outShader = nullptr; return false; @@ -485,8 +489,9 @@ bool OpenGLSWFrameBuffer::CreateTexture(const FString &name, int width, int heig GLenum srcformat; switch (format) { + case GL_RGB: srcformat = GL_RGB; break; case GL_R8: srcformat = GL_RED; break; - case GL_RGBA8: srcformat = GL_BGRA; break; + case GL_RGBA8: srcformat = gl.es ? GL_RGBA : GL_BGRA; break; case GL_RGBA16F: srcformat = GL_RGBA; break; case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: srcformat = GL_RGB; break; case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: srcformat = GL_RGBA; break; @@ -743,6 +748,8 @@ void OpenGLSWFrameBuffer::Present() void OpenGLSWFrameBuffer::SetInitialState() { + if (gl.es) UseMappedMemBuffer = false; + AlphaBlendEnabled = false; AlphaBlendOp = GL_FUNC_ADD; AlphaSrcBlend = 0; @@ -787,12 +794,11 @@ bool OpenGLSWFrameBuffer::CreateResources() { Atlases = nullptr; if (!LoadShaders()) - { return false; - } if (!CreateFrameBuffer("OutputFB", Width, Height, &OutputFB)) return false; + glBindFramebuffer(GL_FRAMEBUFFER, OutputFB->Framebuffer); if (!CreateFBTexture() || @@ -1312,6 +1318,23 @@ void OpenGLSWFrameBuffer::BindFBBuffer() } } +void OpenGLSWFrameBuffer::BgraToRgba(uint32_t *dest, const uint32_t *src, int width, int height, int srcpitch) +{ + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + uint32_t r = RPART(src[x]); + uint32_t g = GPART(src[x]); + uint32_t b = BPART(src[x]); + uint32_t a = APART(src[x]); + dest[x] = r | (g << 8) | (b << 16) | (a << 24); + } + dest += width; + src += srcpitch; + } +} + void OpenGLSWFrameBuffer::Draw3DPart(bool copy3d) { if (copy3d) @@ -1327,7 +1350,11 @@ void OpenGLSWFrameBuffer::Draw3DPart(bool copy3d) uint8_t *dest = (uint8_t*)MapBuffer(GL_PIXEL_UNPACK_BUFFER, size); if (dest) { - if (Pitch == Width) + if (gl.es && pixelsize == 4) + { + BgraToRgba((uint32_t*)dest, (const uint32_t *)MemBuffer, Width, Height, Pitch); + } + else if (Pitch == Width) { memcpy(dest, MemBuffer, Width * Height * pixelsize); } @@ -1354,7 +1381,7 @@ void OpenGLSWFrameBuffer::Draw3DPart(bool copy3d) glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldBinding); glBindTexture(GL_TEXTURE_2D, FBTexture->Texture); if (IsBgra()) - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, Width, Height, GL_BGRA, GL_UNSIGNED_BYTE, 0); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, Width, Height, gl.es ? GL_RGBA : GL_BGRA, GL_UNSIGNED_BYTE, 0); else glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, Width, Height, GL_RED, GL_UNSIGNED_BYTE, 0); glBindTexture(GL_TEXTURE_2D, oldBinding); @@ -1462,6 +1489,8 @@ void OpenGLSWFrameBuffer::UploadPalette() glBufferData(GL_PIXEL_UNPACK_BUFFER, 256 * 4, nullptr, GL_STREAM_DRAW); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, PaletteTexture->Buffers[1]); glBufferData(GL_PIXEL_UNPACK_BUFFER, 256 * 4, nullptr, GL_STREAM_DRAW); + + if (gl.es) PaletteTexture->MapBuffer.resize(256 * 4); } else { @@ -1469,7 +1498,7 @@ void OpenGLSWFrameBuffer::UploadPalette() PaletteTexture->CurrentBuffer = (PaletteTexture->CurrentBuffer + 1) & 1; } - uint8_t *pix = (uint8_t*)MapBuffer(GL_PIXEL_UNPACK_BUFFER, 256 * 4); + uint8_t *pix = gl.es ? PaletteTexture->MapBuffer.data() : (uint8_t*)MapBuffer(GL_PIXEL_UNPACK_BUFFER, 256 * 4); if (pix) { int i; @@ -1490,11 +1519,21 @@ void OpenGLSWFrameBuffer::UploadPalette() pix[2] = SourcePalette[i].r; pix[3] = 255; } - glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); + if (gl.es) + { + uint8_t *tempbuffer = PaletteTexture->MapBuffer.data(); + BgraToRgba((uint32_t*)tempbuffer, (const uint32_t *)tempbuffer, 256, 1, 256); + glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, 256 * 4, tempbuffer); + } + else + { + glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); + } + GLint oldBinding = 0; glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldBinding); glBindTexture(GL_TEXTURE_2D, PaletteTexture->Texture); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, 1, GL_BGRA, GL_UNSIGNED_BYTE, 0); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, 1, gl.es ? GL_RGBA : GL_BGRA, GL_UNSIGNED_BYTE, 0); glBindTexture(GL_TEXTURE_2D, oldBinding); BorderColor = ColorXRGB(SourcePalette[255].r, SourcePalette[255].g, SourcePalette[255].b); } @@ -2094,9 +2133,13 @@ bool OpenGLSWFrameBuffer::OpenGLTex::Update() glBindBuffer(GL_PIXEL_UNPACK_BUFFER, Box->Owner->Tex->Buffers[Box->Owner->Tex->CurrentBuffer]); glBufferData(GL_PIXEL_UNPACK_BUFFER, buffersize, nullptr, GL_STREAM_DRAW); Box->Owner->Tex->CurrentBuffer = (Box->Owner->Tex->CurrentBuffer + 1) & 1; + + static std::vector tempbuffer; + if (gl.es) + tempbuffer.resize(buffersize); int pitch = (rect.right - rect.left) * bytesPerPixel; - uint8_t *bits = (uint8_t *)MapBuffer(GL_PIXEL_UNPACK_BUFFER, buffersize); + uint8_t *bits = gl.es ? tempbuffer.data() : (uint8_t *)MapBuffer(GL_PIXEL_UNPACK_BUFFER, buffersize); dest = bits; if (!dest) { @@ -2140,13 +2183,21 @@ bool OpenGLSWFrameBuffer::OpenGLTex::Update() // Clear bottom padding row. memset(dest, 0, numbytes); } + + if (gl.es && format == GL_RGBA8) + { + BgraToRgba((uint32_t*)bits, (const uint32_t *)bits, rect.right - rect.left, rect.bottom - rect.top, rect.right - rect.left); + } - glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); + if (gl.es) + glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, buffersize, bits); + else + glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); GLint oldBinding = 0; glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldBinding); glBindTexture(GL_TEXTURE_2D, Box->Owner->Tex->Texture); if (format == GL_RGBA8) - glTexSubImage2D(GL_TEXTURE_2D, 0, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, GL_BGRA, GL_UNSIGNED_BYTE, 0); + glTexSubImage2D(GL_TEXTURE_2D, 0, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, gl.es ? GL_RGBA : GL_BGRA, GL_UNSIGNED_BYTE, 0); else glTexSubImage2D(GL_TEXTURE_2D, 0, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, GL_RED, GL_UNSIGNED_BYTE, 0); glBindTexture(GL_TEXTURE_2D, oldBinding); @@ -2302,8 +2353,12 @@ bool OpenGLSWFrameBuffer::OpenGLPal::Update() } int numEntries = MIN(Remap->NumEntries, RoundedPaletteSize); + + std::vector &tempbuffer = Tex->MapBuffer; + if (gl.es) + tempbuffer.resize(numEntries * 4); - buff = (uint32_t *)MapBuffer(GL_PIXEL_UNPACK_BUFFER, numEntries * 4); + buff = gl.es ? (uint32_t*)tempbuffer.data() : (uint32_t *)MapBuffer(GL_PIXEL_UNPACK_BUFFER, numEntries * 4); if (buff == nullptr) { return false; @@ -2326,12 +2381,21 @@ bool OpenGLSWFrameBuffer::OpenGLPal::Update() i = numEntries - 1; BorderColor = ColorARGB(pal[i].a, pal[i - 1].r, pal[i - 1].g, pal[i - 1].b); } - - glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); + + if (gl.es) + { + BgraToRgba((uint32_t*)buff, (const uint32_t *)buff, numEntries, 1, numEntries); + glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, numEntries * 4, buff); + } + else + { + glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); + } + GLint oldBinding = 0; glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldBinding); glBindTexture(GL_TEXTURE_2D, Tex->Texture); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, numEntries, 1, GL_BGRA, GL_UNSIGNED_BYTE, 0); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, numEntries, 1, gl.es ? GL_RGBA : GL_BGRA, GL_UNSIGNED_BYTE, 0); glBindTexture(GL_TEXTURE_2D, oldBinding); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); diff --git a/src/gl/system/gl_swframebuffer.h b/src/gl/system/gl_swframebuffer.h index e211b3e51..6e69e9421 100644 --- a/src/gl/system/gl_swframebuffer.h +++ b/src/gl/system/gl_swframebuffer.h @@ -121,6 +121,8 @@ private: int WrapS = 0; int WrapT = 0; int Format = 0; + + std::vector MapBuffer; }; class HWFrameBuffer @@ -193,6 +195,8 @@ private: void DrawLineList(int count); void DrawTriangleList(int minIndex, int numVertices, int startIndex, int primitiveCount); void Present(); + + static void BgraToRgba(uint32_t *dest, const uint32_t *src, int width, int height, int srcpitch); void BindFBBuffer(); void *MappedMemBuffer = nullptr; diff --git a/src/posix/sdl/sdlglvideo.cpp b/src/posix/sdl/sdlglvideo.cpp index 576ca570b..51a15b8c4 100644 --- a/src/posix/sdl/sdlglvideo.cpp +++ b/src/posix/sdl/sdlglvideo.cpp @@ -63,6 +63,18 @@ CUSTOM_CVAR(Bool, gl_debug, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINI Printf("This won't take effect until " GAMENAME " is restarted.\n"); } +#ifdef __arm__ +CUSTOM_CVAR(Bool, gl_es, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) +{ + Printf("This won't take effect until " GAMENAME " is restarted.\n"); +} +#else +CUSTOM_CVAR(Bool, gl_es, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) +{ + Printf("This won't take effect until " GAMENAME " is restarted.\n"); +} +#endif + // PRIVATE DATA DEFINITIONS ------------------------------------------------ // Dummy screen sizes to pass when windowed @@ -303,6 +315,14 @@ bool SDLGLVideo::SetupPixelFormat(bool allowsoftware, int multisample) } if (gl_debug) SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG); + + if (gl_es) + { + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); + } + return true; } diff --git a/wadsrc/static/shaders/glsl/swshader.fp b/wadsrc/static/shaders/glsl/swshader.fp index 01d539c88..e33389f29 100644 --- a/wadsrc/static/shaders/glsl/swshader.fp +++ b/wadsrc/static/shaders/glsl/swshader.fp @@ -1,4 +1,6 @@ +precision mediump float; + in vec4 PixelColor0; in vec4 PixelColor1; in vec4 PixelTexCoord0; @@ -75,7 +77,7 @@ vec4 SpecialColormap(vec2 tex_coord, vec4 start, vec4 end) vec4 range = end - start; // We can't store values greater than 1.0 in a color register, so we multiply // the final result by 2 and expect the caller to divide the start and end by 2. - color.rgb = 2 * (start + Grayscale(color) * range).rgb; + color.rgb = 2.0 * (start + Grayscale(color) * range).rgb; // Duplicate alpha semantics of NormalColor. color.a = start.a + color.a * end.a; return color; @@ -120,7 +122,7 @@ vec4 BurnWipe(vec4 coord) { vec4 color = texture(NewScreen, coord.xy); vec4 alpha = texture(Burn, coord.zw); - color.a = alpha.r * 2; + color.a = alpha.r * 2.0; return color; }