Commit 14389ccf by Geoff Lang

Always use sized internal formats for textures in TextureGL.

On desktop GL, using an internal format of GL_RGBA produces GL_RGBA8 textures even if format is set to GL_FLOAT. Use sized internal formats whenever possible to ensure that the internal format of the texture is the expected format. Work around issues with Intel and AMD drivers that always round up when writing to a 1-bit alpha framebuffer format. Fixes: * conformance/extensions/oes-texture-float-with-image-data.htm * conformance/extensions/oes-texture-float-with-image.html * conformance/extensions/oes-texture-float.html * conformance/extensions/oes-texture-half-float-linear.html * conformance/extensions/oes-texture-half-float-with-image-data.html * conformance/extensions/oes-texture-half-float-with-image.html * conformance/extensions/oes-texture-half-float.html Reland of https://chromium-review.googlesource.com/#/c/288350/ BUG=angleproject:884 Change-Id: Ia2f9251d12dd3bbc7b6918d46e61623d0abedfac Reviewed-on: https://chromium-review.googlesource.com/288584Reviewed-by: 's avatarKenneth Russell <kbr@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Tested-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent d71620aa
......@@ -251,12 +251,12 @@ struct PixelPackState
namespace rx
{
enum VendorID : uint32_t
{
VENDOR_ID_AMD = 0x1002,
VENDOR_ID_INTEL = 0x8086,
VENDOR_ID_NVIDIA = 0x10DE,
VENDOR_ID_UNKNOWN = 0x0,
VENDOR_ID_AMD = 0x1002,
VENDOR_ID_INTEL = 0x8086,
VENDOR_ID_NVIDIA = 0x10DE,
};
// A macro that determines whether an object has a given runtime type.
......
......@@ -193,7 +193,7 @@ FramebufferImpl *RendererGL::createFramebuffer(const gl::Framebuffer::Data &data
TextureImpl *RendererGL::createTexture(GLenum target)
{
return new TextureGL(target, mFunctions, mStateManager);
return new TextureGL(target, mFunctions, mWorkarounds, mStateManager);
}
RenderbufferImpl *RendererGL::createRenderbuffer()
......
......@@ -17,6 +17,7 @@
#include "libANGLE/renderer/gl/FramebufferGL.h"
#include "libANGLE/renderer/gl/FunctionsGL.h"
#include "libANGLE/renderer/gl/StateManagerGL.h"
#include "libANGLE/renderer/gl/WorkaroundsGL.h"
#include "libANGLE/renderer/gl/formatutilsgl.h"
namespace rx
......@@ -55,10 +56,40 @@ static bool CompatibleTextureTarget(GLenum textureType, GLenum textureTarget)
}
}
TextureGL::TextureGL(GLenum type, const FunctionsGL *functions, StateManagerGL *stateManager)
static const nativegl::InternalFormat &GetNativeInternalFormat(const FunctionsGL *functions,
const WorkaroundsGL &workarounds,
GLenum internalFormat,
GLenum type)
{
GLenum sizedFormat = gl::GetSizedInternalFormat(internalFormat, type);
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
bool use1BitAlphaWorkaround = workarounds.avoid1BitAlphaTextureFormats &&
functions->standard == STANDARD_GL_DESKTOP &&
formatInfo.alphaBits == 1;
if (!use1BitAlphaWorkaround &&
(functions->standard == STANDARD_GL_DESKTOP || functions->isAtLeastGLES(gl::Version(3, 0))))
{
// 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.
return nativegl::GetInternalFormatInfo(sizedFormat, functions->standard);
}
else
{
// Use the original unsized format when the workaround is required or on top of ES2.
return nativegl::GetInternalFormatInfo(formatInfo.format, functions->standard);
}
}
TextureGL::TextureGL(GLenum type,
const FunctionsGL *functions,
const WorkaroundsGL &workarounds,
StateManagerGL *stateManager)
: TextureImpl(),
mTextureType(type),
mFunctions(functions),
mWorkarounds(workarounds),
mStateManager(stateManager),
mAppliedSamplerState(),
mTextureID(0)
......@@ -90,7 +121,8 @@ gl::Error TextureGL::setImage(GLenum target, size_t level, GLenum internalFormat
SetUnpackStateForTexImage(mStateManager, unpack);
const nativegl::InternalFormat &nativeInternalFormatInfo = nativegl::GetInternalFormatInfo(internalFormat, mFunctions->standard);
const nativegl::InternalFormat &nativeInternalFormatInfo =
GetNativeInternalFormat(mFunctions, mWorkarounds, internalFormat, type);
mStateManager->bindTexture(mTextureType, mTextureID);
if (UseTexImage2D(mTextureType))
......@@ -143,7 +175,8 @@ gl::Error TextureGL::setCompressedImage(GLenum target, size_t level, GLenum inte
SetUnpackStateForTexImage(mStateManager, unpack);
const nativegl::InternalFormat &nativeInternalFormatInfo = nativegl::GetInternalFormatInfo(internalFormat, mFunctions->standard);
const nativegl::InternalFormat &nativeInternalFormatInfo =
GetNativeInternalFormat(mFunctions, mWorkarounds, internalFormat, GL_UNSIGNED_BYTE);
mStateManager->bindTexture(mTextureType, mTextureID);
if (UseTexImage2D(mTextureType))
......@@ -171,19 +204,17 @@ gl::Error TextureGL::setCompressedSubImage(GLenum target, size_t level, const gl
SetUnpackStateForTexImage(mStateManager, unpack);
const nativegl::InternalFormat &nativeInternalFormatInfo = nativegl::GetInternalFormatInfo(format, mFunctions->standard);
mStateManager->bindTexture(mTextureType, mTextureID);
if (UseTexImage2D(mTextureType))
{
ASSERT(area.z == 0 && area.depth == 1);
mFunctions->compressedTexSubImage2D(target, level, area.x, area.y, area.width, area.height, nativeInternalFormatInfo.internalFormat, imageSize,
pixels);
mFunctions->compressedTexSubImage2D(target, level, area.x, area.y, area.width, area.height,
format, imageSize, pixels);
}
else if (UseTexImage3D(mTextureType))
{
mFunctions->compressedTexSubImage3D(target, level, area.x, area.y, area.z, area.width, area.height, area.depth,
nativeInternalFormatInfo.internalFormat, imageSize, pixels);
mFunctions->compressedTexSubImage3D(target, level, area.x, area.y, area.z, area.width,
area.height, area.depth, format, imageSize, pixels);
}
else
{
......@@ -196,7 +227,8 @@ gl::Error TextureGL::setCompressedSubImage(GLenum target, size_t level, const gl
gl::Error TextureGL::copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat,
const gl::Framebuffer *source)
{
const nativegl::InternalFormat &nativeInternalFormatInfo = nativegl::GetInternalFormatInfo(internalFormat, mFunctions->standard);
const nativegl::InternalFormat &nativeInternalFormatInfo = GetNativeInternalFormat(
mFunctions, mWorkarounds, internalFormat, source->getImplementationColorReadType());
const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(source);
......
......@@ -17,11 +17,15 @@ namespace rx
class FunctionsGL;
class StateManagerGL;
struct WorkaroundsGL;
class TextureGL : public TextureImpl
{
public:
TextureGL(GLenum type, const FunctionsGL *functions, StateManagerGL *stateManager);
TextureGL(GLenum type,
const FunctionsGL *functions,
const WorkaroundsGL &workarounds,
StateManagerGL *stateManager);
~TextureGL() override;
void setUsage(GLenum usage) override;
......@@ -61,6 +65,7 @@ class TextureGL : public TextureImpl
GLenum mTextureType;
const FunctionsGL *mFunctions;
const WorkaroundsGL &mWorkarounds;
StateManagerGL *mStateManager;
mutable gl::SamplerState mAppliedSamplerState;
......
......@@ -15,10 +15,18 @@ namespace rx
struct WorkaroundsGL
{
WorkaroundsGL()
: avoid1BitAlphaTextureFormats(false)
{
}
// TODO(geofflang): workarounds!
// When writing a float to a normalized integer framebuffer, desktop OpenGL is allowed to write
// one of the two closest normalized integer representations (although round to nearest is
// preferred) (see section 2.3.5.2 of the GL 4.5 core specification). OpenGL ES requires that
// round-to-nearest is used (see "Conversion from Floating-Point to Framebuffer Fixed-Point" in
// section 2.1.2 of the OpenGL ES 2.0.25 spec). This issue only shows up on Intel and AMD
// drivers on framebuffer formats that have 1-bit alpha, work around this by using higher
// precision formats instead.
bool avoid1BitAlphaTextureFormats;
};
}
......
......@@ -22,6 +22,27 @@
namespace rx
{
static VendorID GetVendorID(const FunctionsGL *functions)
{
std::string nativeVendorString(reinterpret_cast<const char *>(functions->getString(GL_VENDOR)));
if (nativeVendorString.find("Intel") != std::string::npos)
{
return VENDOR_ID_INTEL;
}
else if (nativeVendorString.find("NVIDIA") != std::string::npos)
{
return VENDOR_ID_NVIDIA;
}
else if (nativeVendorString.find("ATI") != std::string::npos ||
nativeVendorString.find("AMD") != std::string::npos)
{
return VENDOR_ID_AMD;
}
else
{
return VENDOR_ID_UNKNOWN;
}
}
namespace nativegl_gl
{
......@@ -514,7 +535,12 @@ void GenerateCaps(const FunctionsGL *functions, gl::Caps *caps, gl::TextureCapsM
void GenerateWorkarounds(const FunctionsGL *functions, WorkaroundsGL *workarounds)
{
*workarounds = WorkaroundsGL();
VendorID vendor = GetVendorID(functions);
// Don't use 1-bit alpha formats on desktop GL with AMD or Intel drivers.
workarounds->avoid1BitAlphaTextureFormats =
functions->standard == STANDARD_GL_DESKTOP &&
(vendor == VENDOR_ID_AMD || 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