mirror of
https://github.com/love2d/love.git
synced 2026-08-16 08:11:02 +02:00
Merge branch 'master' into 12.0-development
This commit is contained in:
@@ -60,7 +60,11 @@ static const char global_syntax[] = R"(
|
||||
#define DepthCubeImage samplerCubeShadow
|
||||
#endif
|
||||
#define extern uniform
|
||||
#ifdef GL_EXT_texture_array
|
||||
#if defined(GL_EXT_texture_array) && (!defined(GL_ES) || __VERSION__ > 100 || defined(GL_OES_gpu_shader5))
|
||||
// Only used when !GLSLES1 to work around Ouya driver bug. But we still want it
|
||||
// enabled for glslang validation when glsl 1-on-3 is used, so also enable it if
|
||||
// OES_gpu_shader5 exists.
|
||||
#define LOVE_EXT_TEXTURE_ARRAY_ENABLED
|
||||
#extension GL_EXT_texture_array : enable
|
||||
#endif
|
||||
#ifdef GL_OES_texture_3D
|
||||
@@ -122,7 +126,7 @@ void love_initializeBuiltinUniforms() {
|
||||
|
||||
static const char global_functions[] = R"(
|
||||
#ifdef GL_ES
|
||||
#if __VERSION__ >= 300 || defined(GL_EXT_texture_array)
|
||||
#if __VERSION__ >= 300 || defined(LOVE_EXT_TEXTURE_ARRAY_ENABLED)
|
||||
precision lowp sampler2DArray;
|
||||
#endif
|
||||
#if __VERSION__ >= 300 || defined(GL_OES_texture_3D)
|
||||
@@ -158,7 +162,7 @@ static const char global_functions[] = R"(
|
||||
#if __VERSION__ > 100 || defined(GL_OES_texture_3D)
|
||||
vec4 Texel(sampler3D s, vec3 c) { return love_texture3D(s, c); }
|
||||
#endif
|
||||
#if __VERSION__ >= 130 || defined(GL_EXT_texture_array)
|
||||
#if __VERSION__ >= 130 || defined(LOVE_EXT_TEXTURE_ARRAY_ENABLED)
|
||||
vec4 Texel(sampler2DArray s, vec3 c) { return love_texture2DArray(s, c); }
|
||||
#endif
|
||||
#ifdef PIXEL
|
||||
@@ -167,7 +171,7 @@ static const char global_functions[] = R"(
|
||||
#if __VERSION__ > 100 || defined(GL_OES_texture_3D)
|
||||
vec4 Texel(sampler3D s, vec3 c, float b) { return love_texture3D(s, c, b); }
|
||||
#endif
|
||||
#if __VERSION__ >= 130 || defined(GL_EXT_texture_array)
|
||||
#if __VERSION__ >= 130 || defined(LOVE_EXT_TEXTURE_ARRAY_ENABLED)
|
||||
vec4 Texel(sampler2DArray s, vec3 c, float b) { return love_texture2DArray(s, c, b); }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -316,8 +316,8 @@ bool Graphics::setMode(int width, int height, int pixelwidth, int pixelheight, b
|
||||
glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
|
||||
|
||||
// Set whether drawing converts input from linear -> sRGB colorspace.
|
||||
if (GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_sRGB || GLAD_EXT_framebuffer_sRGB
|
||||
|| GLAD_ES_VERSION_3_0)
|
||||
if (!gl.bugs.brokenSRGB && (GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_sRGB
|
||||
|| GLAD_EXT_framebuffer_sRGB || GLAD_ES_VERSION_3_0))
|
||||
{
|
||||
if (GLAD_VERSION_1_0 || GLAD_EXT_sRGB_write_control)
|
||||
gl.setEnableState(OpenGL::ENABLE_FRAMEBUFFER_SRGB, isGammaCorrect());
|
||||
|
||||
@@ -150,6 +150,16 @@ bool OpenGL::initContext()
|
||||
if (strstr(device, "HD Graphics 4000") || strstr(device, "HD Graphics 2500"))
|
||||
bugs.clientWaitSyncStalls = true;
|
||||
}
|
||||
|
||||
if (getVendor() == VENDOR_INTEL)
|
||||
{
|
||||
const char *device = (const char *) glGetString(GL_RENDERER);
|
||||
if (strstr(device, "HD Graphics 3000") || strstr(device, "HD Graphics 2000")
|
||||
|| !strcmp(device, "Intel(R) HD Graphics") || !strcmp(device, "Intel(R) HD Graphics Family"))
|
||||
{
|
||||
bugs.brokenSRGB = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LOVE_WINDOWS
|
||||
@@ -210,8 +220,8 @@ void OpenGL::setupContext()
|
||||
setEnableState(ENABLE_SCISSOR_TEST, state.enableState[ENABLE_SCISSOR_TEST]);
|
||||
setEnableState(ENABLE_FACE_CULL, state.enableState[ENABLE_FACE_CULL]);
|
||||
|
||||
if (GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_sRGB || GLAD_EXT_framebuffer_sRGB
|
||||
|| GLAD_EXT_sRGB_write_control)
|
||||
if (!bugs.brokenSRGB && (GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_sRGB
|
||||
|| GLAD_EXT_framebuffer_sRGB || GLAD_EXT_sRGB_write_control))
|
||||
{
|
||||
setEnableState(ENABLE_FRAMEBUFFER_SRGB, state.enableState[ENABLE_FRAMEBUFFER_SRGB]);
|
||||
}
|
||||
@@ -391,15 +401,23 @@ void OpenGL::initOpenGLFunctions()
|
||||
}
|
||||
}
|
||||
|
||||
if (GLAD_ES_VERSION_2_0 && GLAD_OES_texture_3D && !GLAD_ES_VERSION_3_0)
|
||||
if (GLAD_ES_VERSION_2_0 && !GLAD_ES_VERSION_3_0)
|
||||
{
|
||||
// Function signatures don't match, we'll have to conditionally call it
|
||||
//fp_glTexImage3D = fp_glTexImage3DOES;
|
||||
fp_glTexSubImage3D = fp_glTexSubImage3DOES;
|
||||
fp_glCopyTexSubImage3D = fp_glCopyTexSubImage3DOES;
|
||||
fp_glCompressedTexImage3D = fp_glCompressedTexImage3DOES;
|
||||
fp_glCompressedTexSubImage3D = fp_glCompressedTexSubImage3DOES;
|
||||
fp_glFramebufferTexture3D = fp_glFramebufferTexture3DOES;
|
||||
// The Nvidia Tegra 3 driver (used by Ouya) claims to support GL_EXT_texture_array but
|
||||
// segfaults if you actually try to use it. OpenGL ES 2.0 devices should use OES_texture_3D.
|
||||
// GL_EXT_texture_array is for desktops.
|
||||
GLAD_EXT_texture_array = false;
|
||||
|
||||
if (GLAD_OES_texture_3D)
|
||||
{
|
||||
// Function signatures don't match, we'll have to conditionally call it
|
||||
//fp_glTexImage3D = fp_glTexImage3DOES;
|
||||
fp_glTexSubImage3D = fp_glTexSubImage3DOES;
|
||||
fp_glCopyTexSubImage3D = fp_glCopyTexSubImage3DOES;
|
||||
fp_glCompressedTexImage3D = fp_glCompressedTexImage3DOES;
|
||||
fp_glCompressedTexSubImage3D = fp_glCompressedTexSubImage3DOES;
|
||||
fp_glFramebufferTexture3D = fp_glFramebufferTexture3DOES;
|
||||
}
|
||||
}
|
||||
|
||||
if (!GLAD_VERSION_3_2 && !GLAD_ES_VERSION_3_2 && !GLAD_ARB_draw_elements_base_vertex)
|
||||
@@ -1881,6 +1899,8 @@ bool OpenGL::isPixelFormatSupported(PixelFormat pixelformat, bool rendertarget,
|
||||
else
|
||||
return true;
|
||||
case PIXELFORMAT_sRGBA8_UNORM:
|
||||
if (gl.bugs.brokenSRGB)
|
||||
return false;
|
||||
if (rendertarget)
|
||||
{
|
||||
if (GLAD_VERSION_1_0)
|
||||
|
||||
@@ -178,6 +178,13 @@ public:
|
||||
**/
|
||||
bool brokenR8PixelFormat;
|
||||
|
||||
/**
|
||||
* Intel HD Graphics drivers on Windows prior to the HD 2500/4000 have
|
||||
* completely broken sRGB support.
|
||||
* https://github.com/love2d/love/issues/1592
|
||||
**/
|
||||
bool brokenSRGB;
|
||||
|
||||
/**
|
||||
* Other bugs which have workarounds that don't use conditional code at
|
||||
* the moment:
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace graphics
|
||||
namespace opengl
|
||||
{
|
||||
|
||||
static GLenum createFBO(GLuint &framebuffer, TextureType texType, PixelFormat format, GLuint texture, int layers, bool clear)
|
||||
static GLenum createFBO(GLuint &framebuffer, TextureType texType, PixelFormat format, GLuint texture, int mips, int layers, bool clear)
|
||||
{
|
||||
// get currently bound fbo to reset to it later
|
||||
GLuint current_fbo = gl.getFramebuffer(OpenGL::FRAMEBUFFER_ALL);
|
||||
@@ -68,37 +68,40 @@ static GLenum createFBO(GLuint &framebuffer, TextureType texType, PixelFormat fo
|
||||
// Make sure all faces and layers of the texture are initialized to
|
||||
// transparent black. This is unfortunately probably pretty slow for
|
||||
// 2D-array and 3D textures with a lot of layers...
|
||||
for (int layer = layers - 1; layer >= 0; layer--)
|
||||
for (int mip = mips - 1; mip >= 0; mip--)
|
||||
{
|
||||
for (int face = faces - 1; face >= 0; face--)
|
||||
for (int layer = layers - 1; layer >= 0; layer--)
|
||||
{
|
||||
for (GLenum attachment : fmt.framebufferAttachments)
|
||||
for (int face = faces - 1; face >= 0; face--)
|
||||
{
|
||||
if (attachment == GL_NONE)
|
||||
continue;
|
||||
|
||||
gl.framebufferTexture(attachment, texType, texture, 0, layer, face);
|
||||
}
|
||||
|
||||
if (clear)
|
||||
{
|
||||
if (isPixelFormatDepthStencil(format))
|
||||
for (GLenum attachment : fmt.framebufferAttachments)
|
||||
{
|
||||
bool hadDepthWrites = gl.hasDepthWrites();
|
||||
if (!hadDepthWrites) // glDepthMask also affects glClear.
|
||||
gl.setDepthWrites(true);
|
||||
if (attachment == GL_NONE)
|
||||
continue;
|
||||
|
||||
gl.clearDepth(1.0);
|
||||
glClearStencil(0);
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
if (!hadDepthWrites)
|
||||
gl.setDepthWrites(hadDepthWrites);
|
||||
gl.framebufferTexture(attachment, texType, texture, mip, layer, face);
|
||||
}
|
||||
else
|
||||
|
||||
if (clear)
|
||||
{
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
if (isPixelFormatDepthStencil(format))
|
||||
{
|
||||
bool hadDepthWrites = gl.hasDepthWrites();
|
||||
if (!hadDepthWrites) // glDepthMask also affects glClear.
|
||||
gl.setDepthWrites(true);
|
||||
|
||||
gl.clearDepth(1.0);
|
||||
glClearStencil(0);
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
if (!hadDepthWrites)
|
||||
gl.setDepthWrites(hadDepthWrites);
|
||||
}
|
||||
else
|
||||
{
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -328,28 +331,43 @@ void Texture::createTexture()
|
||||
|
||||
bool hasdata = slices.get(0, 0) != nullptr;
|
||||
|
||||
// All mipmap levels need to be initialized - for color formats we can clear
|
||||
// the base mip and use glGenerateMipmap after that's done. Depth and
|
||||
// stencil formats don't always support glGenerateMipmap so we need to
|
||||
// individually clear each mip level in that case. We avoid doing that for
|
||||
// color formats because of an Intel driver bug:
|
||||
// https://github.com/love2d/love/issues/1585
|
||||
int clearmips = 1;
|
||||
if (isPixelFormatDepthStencil(format))
|
||||
clearmips = mipmapCount;
|
||||
|
||||
// Create a local FBO used for glReadPixels as well as MSAA blitting.
|
||||
if (isRenderTarget())
|
||||
{
|
||||
bool clear = !hasdata;
|
||||
int slices = texType == TEXTURE_VOLUME ? depth : layers;
|
||||
framebufferStatus = createFBO(fbo, texType, format, texture, slices, clear);
|
||||
framebufferStatus = createFBO(fbo, texType, format, texture, clearmips, slices, clear);
|
||||
}
|
||||
else if (!hasdata)
|
||||
{
|
||||
// Initialize all slices to transparent black.
|
||||
std::vector<uint8> emptydata(getPixelFormatSliceSize(format, w, h));
|
||||
for (int mip = 0; mip < clearmips; mip++)
|
||||
{
|
||||
int mipw = getPixelWidth(mip);
|
||||
int miph = getPixelHeight(mip);
|
||||
std::vector<uint8> emptydata(getPixelFormatSliceSize(format, mipw, miph));
|
||||
|
||||
Rect r = {0, 0, w, h};
|
||||
int slices = texType == TEXTURE_VOLUME ? depth : layers;
|
||||
slices = texType == TEXTURE_CUBE ? 6 : slices;
|
||||
for (int i = 0; i < slices; i++)
|
||||
uploadByteData(format, emptydata.data(), emptydata.size(), 0, i, r);
|
||||
Rect r = {0, 0, mipw, miph};
|
||||
int slices = texType == TEXTURE_VOLUME ? getDepth(mip) : layers;
|
||||
slices = texType == TEXTURE_CUBE ? 6 : slices;
|
||||
for (int i = 0; i < slices; i++)
|
||||
uploadByteData(format, emptydata.data(), emptydata.size(), mip, i, r);
|
||||
}
|
||||
}
|
||||
|
||||
// Non-readable textures can't have mipmaps (enforced in the base class),
|
||||
// so generateMipmaps here is fine - when they aren't already initialized.
|
||||
if (getMipmapCount() > 1 && slices.getMipmapCount() <= 1)
|
||||
if (clearmips < mipmapCount && slices.getMipmapCount() <= 1 && getMipmapsMode() != MIPMAPS_NONE)
|
||||
generateMipmaps();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user