Commit 23a2ae0c by Geoff Lang

Centralize GL format workarounds.

Instead of trying to encapsulate the GL texture format workarounds into tables, use functions that do manual checks for specific cases. Simplifies the logic. Fixes: * conformance/extensions/ext-sRGB.html * conformance/extensions/oes-texture-half-float.html * conformance/extensions/oes-texture-half-float-with-canvas.html * conformance/extensions/oes-texture-half-float-with-image.htm * conformance/extensions/oes-texture-half-float-with-video.html BUG=angleproject:884 Change-Id: Ifb719fff908680fddc7c53a544e2284a42a58356 Reviewed-on: https://chromium-review.googlesource.com/289082Reviewed-by: 's avatarKenneth Russell <kbr@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Tested-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent cbdf7366
......@@ -18,10 +18,13 @@
namespace rx
{
RenderbufferGL::RenderbufferGL(const FunctionsGL *functions, StateManagerGL *stateManager, const gl::TextureCapsMap &textureCaps)
RenderbufferGL::RenderbufferGL(const FunctionsGL *functions,
const WorkaroundsGL &workarounds,
StateManagerGL *stateManager,
const gl::TextureCapsMap &textureCaps)
: RenderbufferImpl(),
mFunctions(functions),
mWorkarounds(workarounds),
mStateManager(stateManager),
mTextureCaps(textureCaps),
mRenderbufferID(0)
......@@ -40,8 +43,10 @@ gl::Error RenderbufferGL::setStorage(GLenum internalformat, size_t width, size_t
{
mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mRenderbufferID);
const nativegl::InternalFormat &nativeInternalFormatInfo = nativegl::GetInternalFormatInfo(internalformat, mFunctions->standard);
mFunctions->renderbufferStorage(GL_RENDERBUFFER, nativeInternalFormatInfo.internalFormat, width, height);
nativegl::RenderbufferFormat renderbufferFormat =
nativegl::GetRenderbufferFormat(mFunctions, mWorkarounds, internalformat);
mFunctions->renderbufferStorage(GL_RENDERBUFFER, renderbufferFormat.internalFormat, width,
height);
return gl::Error(GL_NO_ERROR);
}
......@@ -50,8 +55,10 @@ gl::Error RenderbufferGL::setStorageMultisample(size_t samples, GLenum internalf
{
mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mRenderbufferID);
const nativegl::InternalFormat &nativeInternalFormatInfo = nativegl::GetInternalFormatInfo(internalformat, mFunctions->standard);
mFunctions->renderbufferStorageMultisample(GL_RENDERBUFFER, samples, nativeInternalFormatInfo.internalFormat, width, height);
nativegl::RenderbufferFormat renderbufferFormat =
nativegl::GetRenderbufferFormat(mFunctions, mWorkarounds, internalformat);
mFunctions->renderbufferStorageMultisample(GL_RENDERBUFFER, samples,
renderbufferFormat.internalFormat, width, height);
const gl::TextureCaps &formatCaps = mTextureCaps.get(internalformat);
if (samples > formatCaps.getMaxSamples())
......
......@@ -21,11 +21,15 @@ namespace rx
class FunctionsGL;
class StateManagerGL;
struct WorkaroundsGL;
class RenderbufferGL : public RenderbufferImpl
{
public:
RenderbufferGL(const FunctionsGL *functions, StateManagerGL *stateManager, const gl::TextureCapsMap &textureCaps);
RenderbufferGL(const FunctionsGL *functions,
const WorkaroundsGL &workarounds,
StateManagerGL *stateManager,
const gl::TextureCapsMap &textureCaps);
~RenderbufferGL() override;
virtual gl::Error setStorage(GLenum internalformat, size_t width, size_t height) override;
......@@ -41,6 +45,7 @@ class RenderbufferGL : public RenderbufferImpl
private:
const FunctionsGL *mFunctions;
const WorkaroundsGL &mWorkarounds;
StateManagerGL *mStateManager;
const gl::TextureCapsMap &mTextureCaps;
......
......@@ -198,7 +198,7 @@ TextureImpl *RendererGL::createTexture(GLenum target)
RenderbufferImpl *RendererGL::createRenderbuffer()
{
return new RenderbufferGL(mFunctions, mStateManager, getRendererTextureCaps());
return new RenderbufferGL(mFunctions, mWorkarounds, mStateManager, getRendererTextureCaps());
}
BufferImpl *RendererGL::createBuffer()
......
......@@ -15,7 +15,7 @@ namespace rx
struct WorkaroundsGL
{
WorkaroundsGL()
: avoid1BitAlphaTextureFormats(false)
: avoid1BitAlphaTextureFormats(false), rgba4IsNotSupportedForColorRendering(false)
{
}
......@@ -27,6 +27,11 @@ struct WorkaroundsGL
// drivers on framebuffer formats that have 1-bit alpha, work around this by using higher
// precision formats instead.
bool avoid1BitAlphaTextureFormats;
// On some older Intel drivers, GL_RGBA4 is not color renderable, glCheckFramebufferStatus
// returns GL_FRAMEBUFFER_UNSUPPORTED. Work around this by using a known color-renderable
// format.
bool rgba4IsNotSupportedForColorRendering;
};
}
......
......@@ -12,6 +12,7 @@
#include <limits>
#include "common/string_utils.h"
#include "libANGLE/formatutils.h"
namespace rx
{
......@@ -19,52 +20,6 @@ namespace rx
namespace nativegl
{
typedef std::map<GLenum, GLenum> InternalFormatConversionMap;
static InternalFormatConversionMap BuildGLInternalFormatConversionMap()
{
InternalFormatConversionMap map;
map[GL_BGRA8_EXT] = GL_RGBA8;
map[GL_BGRA_EXT] = GL_RGBA;
return map;
}
static InternalFormatConversionMap BuildGLESInternalFormatConversionMap()
{
InternalFormatConversionMap map;
return map;
}
static const InternalFormatConversionMap &GetInternalFormatConversionMap(StandardGL standard)
{
if (standard == STANDARD_GL_DESKTOP)
{
static const InternalFormatConversionMap map = BuildGLInternalFormatConversionMap();
return map;
}
else if (standard == STANDARD_GL_ES)
{
static const InternalFormatConversionMap map = BuildGLESInternalFormatConversionMap();
return map;
}
else
{
UNREACHABLE();
static const InternalFormatConversionMap map = InternalFormatConversionMap();;
return map;
}
}
static GLenum GetConvertedInternalFormat(GLenum format, StandardGL standard)
{
const InternalFormatConversionMap &map = GetInternalFormatConversionMap(standard);
auto iter = map.find(format);
return iter != map.end() ? iter->second : format;
}
SupportRequirement::SupportRequirement()
: version(std::numeric_limits<GLuint>::max(), std::numeric_limits<GLuint>::max()),
versionExtensions(),
......@@ -156,12 +111,10 @@ static inline void InsertFormatMapping(InternalFormatInfoMap *map, GLenum intern
const SupportRequirement &esTexture, const SupportRequirement &esFilter, const SupportRequirement &esRender)
{
InternalFormatInfo formatInfo;
formatInfo.glInfo.internalFormat = GetConvertedInternalFormat(internalFormat, STANDARD_GL_DESKTOP);
formatInfo.glInfo.texture = desktopTexture;
formatInfo.glInfo.filter = desktopFilter;
formatInfo.glInfo.renderbuffer = desktopRender;
formatInfo.glInfo.framebufferAttachment = desktopRender;
formatInfo.glesInfo.internalFormat = GetConvertedInternalFormat(internalFormat, STANDARD_GL_ES);
formatInfo.glesInfo.texture = esTexture;
formatInfo.glesInfo.filter = esTexture;
formatInfo.glesInfo.renderbuffer = esFilter;
......@@ -320,6 +273,183 @@ const InternalFormat &GetInternalFormatInfo(GLenum internalFormat, StandardGL st
return defaultInternalFormat;
}
static GLenum GetNativeInternalFormat(const FunctionsGL *functions,
const WorkaroundsGL &workarounds,
GLenum internalFormat,
GLenum sizedInternalFormat)
{
GLenum result = internalFormat;
if (functions->standard == STANDARD_GL_DESKTOP)
{
// Use sized internal formats whenever possible to guarantee the requested precision.
// On Desktop GL, passing an internal format of GL_RGBA will generate a GL_RGBA8 texture
// even if the provided type is GL_FLOAT.
result = sizedInternalFormat;
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedInternalFormat);
if (workarounds.avoid1BitAlphaTextureFormats && formatInfo.alphaBits == 1)
{
// Use an 8-bit format instead
result = GL_RGBA8;
}
if (workarounds.rgba4IsNotSupportedForColorRendering && sizedInternalFormat == GL_RGBA4)
{
// Use an 8-bit format instead
result = GL_RGBA8;
}
if (sizedInternalFormat == GL_RGB565 && !functions->isAtLeastGL(gl::Version(4, 1)) &&
functions->hasGLExtension("GL_ARB_ES2_compatibility"))
{
// GL_RGB565 is required for basic ES2 functionality but was not added to desktop GL
// until 4.1.
// Work around this by using an 8-bit format instead.
result = GL_RGB8;
}
if (sizedInternalFormat == GL_BGRA8_EXT)
{
// GLES accepts GL_BGRA as an internal format but desktop GL only accepts it as a type.
// Update the internal format to GL_RGBA.
result = GL_RGBA8;
}
}
else if (functions->isAtLeastGLES(gl::Version(3, 0)))
{
result = sizedInternalFormat;
}
return result;
}
static GLenum GetNativeFormat(const FunctionsGL *functions,
const WorkaroundsGL &workarounds,
GLenum format)
{
GLenum result = format;
if (functions->standard == STANDARD_GL_DESKTOP)
{
// The ES SRGB extensions require that the provided format is GL_SRGB or SRGB_ALPHA but
// the desktop GL extensions only accept GL_RGB or GL_RGBA. Convert them.
if (format == GL_SRGB)
{
result = GL_RGB;
}
if (format == GL_SRGB_ALPHA)
{
result = GL_RGBA;
}
}
return result;
}
static GLenum GetNativeType(const FunctionsGL *functions,
const WorkaroundsGL &workarounds,
GLenum type)
{
GLenum result = type;
if (functions->standard == STANDARD_GL_DESKTOP)
{
if (type == GL_HALF_FLOAT_OES)
{
// The enums differ for the OES half float extensions and desktop GL spec. Update it.
result = GL_HALF_FLOAT;
}
}
if (functions->isAtLeastGLES(gl::Version(3, 0)))
{
if (type == GL_HALF_FLOAT_OES)
{
// The enums differ for the OES half float extensions and ES 3 spec. Update it.
result = GL_HALF_FLOAT;
}
}
return result;
}
TexImageFormat GetTexImageFormat(const FunctionsGL *functions,
const WorkaroundsGL &workarounds,
GLenum internalFormat,
GLenum format,
GLenum type)
{
TexImageFormat result;
result.internalFormat = GetNativeInternalFormat(
functions, workarounds, internalFormat, gl::GetSizedInternalFormat(internalFormat, type));
result.format = GetNativeFormat(functions, workarounds, format);
result.type = GetNativeType(functions, workarounds, type);
return result;
}
TexSubImageFormat GetTexSubImageFormat(const FunctionsGL *functions,
const WorkaroundsGL &workarounds,
GLenum format,
GLenum type)
{
TexSubImageFormat result;
result.format = GetNativeFormat(functions, workarounds, format);
result.type = GetNativeType(functions, workarounds, type);
return result;
}
CompressedTexImageFormat GetCompressedTexImageFormat(const FunctionsGL *functions,
const WorkaroundsGL &workarounds,
GLenum internalFormat)
{
CompressedTexImageFormat result;
result.internalFormat = internalFormat;
return result;
}
CompressedTexSubImageFormat GetCompressedSubTexImageFormat(const FunctionsGL *functions,
const WorkaroundsGL &workarounds,
GLenum format)
{
CompressedTexSubImageFormat result;
result.format = format;
return result;
}
CopyTexImageImageFormat GetCopyTexImageImageFormat(const FunctionsGL *functions,
const WorkaroundsGL &workarounds,
GLenum internalFormat,
GLenum framebufferType)
{
CopyTexImageImageFormat result;
result.internalFormat =
GetNativeInternalFormat(functions, workarounds, internalFormat,
gl::GetSizedInternalFormat(internalFormat, framebufferType));
return result;
}
TexStorageFormat GetTexStorageFormat(const FunctionsGL *functions,
const WorkaroundsGL &workarounds,
GLenum internalFormat)
{
TexStorageFormat result;
result.internalFormat =
GetNativeInternalFormat(functions, workarounds, internalFormat, internalFormat);
return result;
}
RenderbufferFormat GetRenderbufferFormat(const FunctionsGL *functions,
const WorkaroundsGL &workarounds,
GLenum internalFormat)
{
RenderbufferFormat result;
result.internalFormat =
GetNativeInternalFormat(functions, workarounds, internalFormat, internalFormat);
return result;
}
}
}
......@@ -17,6 +17,7 @@
#include "angle_gl.h"
#include "libANGLE/Version.h"
#include "libANGLE/renderer/gl/FunctionsGL.h"
#include "libANGLE/renderer/gl/WorkaroundsGL.h"
namespace rx
{
......@@ -42,9 +43,6 @@ struct InternalFormat
{
InternalFormat();
// Internal format to use for the native texture
GLenum internalFormat;
SupportRequirement texture;
SupportRequirement filter;
SupportRequirement renderbuffer;
......@@ -52,6 +50,68 @@ struct InternalFormat
};
const InternalFormat &GetInternalFormatInfo(GLenum internalFormat, StandardGL standard);
struct TexImageFormat
{
GLenum internalFormat;
GLenum format;
GLenum type;
};
TexImageFormat GetTexImageFormat(const FunctionsGL *functions,
const WorkaroundsGL &workarounds,
GLenum internalFormat,
GLenum format,
GLenum type);
struct TexSubImageFormat
{
GLenum format;
GLenum type;
};
TexSubImageFormat GetTexSubImageFormat(const FunctionsGL *functions,
const WorkaroundsGL &workarounds,
GLenum format,
GLenum type);
struct CompressedTexImageFormat
{
GLenum internalFormat;
};
CompressedTexImageFormat GetCompressedTexImageFormat(const FunctionsGL *functions,
const WorkaroundsGL &workarounds,
GLenum internalFormat);
struct CompressedTexSubImageFormat
{
GLenum format;
};
CompressedTexSubImageFormat GetCompressedSubTexImageFormat(const FunctionsGL *functions,
const WorkaroundsGL &workarounds,
GLenum format);
struct CopyTexImageImageFormat
{
GLenum internalFormat;
};
CopyTexImageImageFormat GetCopyTexImageImageFormat(const FunctionsGL *functions,
const WorkaroundsGL &workarounds,
GLenum internalFormat,
GLenum framebufferType);
struct TexStorageFormat
{
GLenum internalFormat;
};
TexStorageFormat GetTexStorageFormat(const FunctionsGL *functions,
const WorkaroundsGL &workarounds,
GLenum internalFormat);
struct RenderbufferFormat
{
GLenum internalFormat;
};
RenderbufferFormat GetRenderbufferFormat(const FunctionsGL *functions,
const WorkaroundsGL &workarounds,
GLenum internalFormat);
}
}
......
......@@ -541,6 +541,9 @@ void GenerateWorkarounds(const FunctionsGL *functions, WorkaroundsGL *workaround
workarounds->avoid1BitAlphaTextureFormats =
functions->standard == STANDARD_GL_DESKTOP &&
(vendor == VENDOR_ID_AMD || vendor == VENDOR_ID_INTEL);
workarounds->rgba4IsNotSupportedForColorRendering =
functions->standard == STANDARD_GL_DESKTOP && vendor == VENDOR_ID_INTEL;
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment