Commit 53b8aec0 by Geoff Lang

Work around deprecated LUMA formats in the core profile.

Use R and RG textures with swizzle states to emulate them. A manual blit is required when calling CopyTex[Sub]Image from a RGB[A] framebuffer to an emulated L[A] texture so that the alpha channel ends up in the correct channel of the destination texture. Fixes the following tests when using the core profile: * conformance/extensions/oes-texture-float.html * conformance/extensions/oes-texture-half-float.html * conformance/textures/misc/tex-sub-image-2d.html * conformance/textures/misc/texture-formats-test.html * conformance/textures/misc/texture-npot.html BUG=angleproject:1113 Change-Id: If5540e66d9017596bd83d95ec3ede043cbcfe0d2 Reviewed-on: https://chromium-review.googlesource.com/293905Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Tested-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 2c34a4b0
//
// Copyright 2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// BlitGL.cpp: Implements the BlitGL class, a helper for blitting textures
#include "libANGLE/renderer/gl/BlitGL.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/Framebuffer.h"
#include "libANGLE/renderer/gl/formatutilsgl.h"
#include "libANGLE/renderer/gl/FramebufferGL.h"
#include "libANGLE/renderer/gl/FunctionsGL.h"
#include "libANGLE/renderer/gl/TextureGL.h"
#include "libANGLE/renderer/gl/StateManagerGL.h"
#include "libANGLE/renderer/gl/WorkaroundsGL.h"
namespace
{
gl::Error CheckCompileStatus(const rx::FunctionsGL *functions, GLuint shader)
{
GLint compileStatus = GL_FALSE;
functions->getShaderiv(shader, GL_COMPILE_STATUS, &compileStatus);
ASSERT(compileStatus == GL_TRUE);
if (compileStatus == GL_FALSE)
{
return gl::Error(GL_OUT_OF_MEMORY, "Failed to compile internal blit shader.");
}
return gl::Error(GL_NO_ERROR);
}
gl::Error CheckLinkStatus(const rx::FunctionsGL *functions, GLuint program)
{
GLint linkStatus = GL_FALSE;
functions->getProgramiv(program, GL_LINK_STATUS, &linkStatus);
ASSERT(linkStatus == GL_TRUE);
if (linkStatus == GL_FALSE)
{
return gl::Error(GL_OUT_OF_MEMORY, "Failed to link internal blit program.");
}
return gl::Error(GL_NO_ERROR);
}
} // anonymous namespace
namespace rx
{
BlitGL::BlitGL(const FunctionsGL *functions,
const WorkaroundsGL &workarounds,
StateManagerGL *stateManager)
: mFunctions(functions),
mWorkarounds(workarounds),
mStateManager(stateManager),
mBlitProgram(0),
mScratchFBO(0),
mScratchTexture(0),
mVAO(0)
{
ASSERT(mFunctions);
ASSERT(mStateManager);
}
BlitGL::~BlitGL()
{
if (mBlitProgram != 0)
{
mFunctions->deleteProgram(mBlitProgram);
mBlitProgram = 0;
}
if (mScratchTexture != 0)
{
mFunctions->deleteTextures(1, &mScratchTexture);
mScratchTexture = 0;
}
if (mScratchFBO != 0)
{
mFunctions->deleteFramebuffers(1, &mScratchFBO);
mScratchFBO = 0;
}
if (mVAO != 0)
{
mFunctions->deleteVertexArrays(1, &mVAO);
mVAO = 0;
}
}
gl::Error BlitGL::copyImageToLUMAWorkaroundTexture(GLuint texture,
GLenum textureType,
GLenum target,
GLenum lumaFormat,
size_t level,
const gl::Rectangle &sourceArea,
GLenum internalFormat,
const gl::Framebuffer *source)
{
mStateManager->bindTexture(textureType, texture);
// Allocate the texture memory
const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
mFunctions->texImage2D(target, static_cast<GLint>(level), internalFormat, sourceArea.width,
sourceArea.height, 0, internalFormatInfo.format,
source->getImplementationColorReadType(), nullptr);
return copySubImageToLUMAWorkaroundTexture(texture, textureType, target, lumaFormat, level,
gl::Offset(0, 0, 0), sourceArea, source);
}
gl::Error BlitGL::copySubImageToLUMAWorkaroundTexture(GLuint texture,
GLenum textureType,
GLenum target,
GLenum lumaFormat,
size_t level,
const gl::Offset &destOffset,
const gl::Rectangle &sourceArea,
const gl::Framebuffer *source)
{
gl::Error error = initializeResources();
if (error.isError())
{
return error;
}
// Blit the framebuffer to the scratch texture
const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(source);
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
nativegl::CopyTexImageImageFormat copyTexImageFormat = nativegl::GetCopyTexImageImageFormat(
mFunctions, mWorkarounds, source->getImplementationColorReadFormat(),
source->getImplementationColorReadType());
mStateManager->activeTexture(0);
mStateManager->bindTexture(GL_TEXTURE_2D, mScratchTexture);
mFunctions->copyTexImage2D(GL_TEXTURE_2D, 0, copyTexImageFormat.internalFormat, sourceArea.x,
sourceArea.y, sourceArea.width, sourceArea.height, 0);
// Set the swizzle of the scratch texture so that the channels sample into the correct emulated
// LUMA channels.
GLint swizzle[4] = {
(lumaFormat == GL_ALPHA) ? GL_ALPHA : GL_RED,
(lumaFormat == GL_LUMINANCE_ALPHA) ? GL_ALPHA : GL_ZERO, GL_ZERO, GL_ZERO,
};
mFunctions->texParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle);
// Make a temporary framebuffer using the destination texture
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mScratchFBO);
mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, texture,
static_cast<GLint>(level));
// Render to the destination texture, sampling from the scratch texture
mStateManager->useProgram(mBlitProgram);
mStateManager->setViewport(
gl::Rectangle(destOffset.x, destOffset.y, sourceArea.width, sourceArea.height));
mStateManager->setScissorTestEnabled(false);
mStateManager->setDepthRange(0.0f, 1.0f);
mStateManager->setBlendEnabled(false);
mStateManager->setColorMask(true, true, true, true);
mStateManager->setSampleAlphaToCoverageEnabled(false);
mStateManager->setSampleCoverageEnabled(false);
mStateManager->setDepthTestEnabled(false);
mStateManager->setStencilTestEnabled(false);
mStateManager->setCullFaceEnabled(false);
mStateManager->setPolygonOffsetFillEnabled(false);
mStateManager->setRasterizerDiscardEnabled(false);
mStateManager->bindVertexArray(mVAO, 0);
mFunctions->drawArrays(GL_TRIANGLES, 0, 6);
return gl::Error(GL_NO_ERROR);
}
gl::Error BlitGL::initializeResources()
{
if (mBlitProgram == 0)
{
mBlitProgram = mFunctions->createProgram();
// Compile the fragment shader
const char *vsSource =
"#version 150\n"
"out vec2 v_texcoord;\n"
"\n"
"void main()\n"
"{\n"
" const vec2 quad_positions[6] = vec2[6]\n"
" (\n"
" vec2(0.0f, 0.0f),\n"
" vec2(0.0f, 1.0f),\n"
" vec2(1.0f, 0.0f),\n"
"\n"
" vec2(0.0f, 1.0f),\n"
" vec2(1.0f, 0.0f),\n"
" vec2(1.0f, 1.0f)\n"
" );\n"
"\n"
" gl_Position = vec4((quad_positions[gl_VertexID] * 2.0) - 1.0, 0.0, 1.0);\n"
" v_texcoord = quad_positions[gl_VertexID];\n"
"}\n";
GLuint vs = mFunctions->createShader(GL_VERTEX_SHADER);
mFunctions->shaderSource(vs, 1, &vsSource, nullptr);
mFunctions->compileShader(vs);
gl::Error error = CheckCompileStatus(mFunctions, vs);
mFunctions->attachShader(mBlitProgram, vs);
mFunctions->deleteShader(vs);
if (error.isError())
{
return error;
}
// Compile the vertex shader
const char *fsSource =
"#version 150\n"
"uniform sampler2D u_source_texture;\n"
"in vec2 v_texcoord;\n"
"out vec4 output_color;\n"
"\n"
"void main()\n"
"{\n"
" output_color = texture(u_source_texture, v_texcoord);\n"
"}\n";
GLuint fs = mFunctions->createShader(GL_FRAGMENT_SHADER);
mFunctions->shaderSource(fs, 1, &fsSource, nullptr);
mFunctions->compileShader(fs);
error = CheckCompileStatus(mFunctions, fs);
mFunctions->attachShader(mBlitProgram, fs);
mFunctions->deleteShader(fs);
if (error.isError())
{
return error;
}
mFunctions->linkProgram(mBlitProgram);
error = CheckLinkStatus(mFunctions, mBlitProgram);
if (error.isError())
{
return error;
}
GLuint textureUniform = mFunctions->getUniformLocation(mBlitProgram, "u_source_texture");
mStateManager->useProgram(mBlitProgram);
mFunctions->uniform1i(textureUniform, 0);
}
if (mScratchTexture == 0)
{
mFunctions->genTextures(1, &mScratchTexture);
mStateManager->bindTexture(GL_TEXTURE_2D, mScratchTexture);
// Use nearest, non-mipmapped sampling with the scratch texture
mFunctions->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
mFunctions->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
if (mScratchFBO == 0)
{
mFunctions->genFramebuffers(1, &mScratchFBO);
}
if (mVAO == 0)
{
mFunctions->genVertexArrays(1, &mVAO);
}
return gl::Error(GL_NO_ERROR);
}
}
//
// Copyright 2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// BlitGL.h: Defines the BlitGL class, a helper for blitting textures
#ifndef LIBANGLE_RENDERER_GL_BLITGL_H_
#define LIBANGLE_RENDERER_GL_BLITGL_H_
#include "angle_gl.h"
#include "common/angleutils.h"
#include "libANGLE/angletypes.h"
#include "libANGLE/Error.h"
namespace gl
{
class Framebuffer;
}
namespace rx
{
class FramebufferGL;
class FunctionsGL;
class StateManagerGL;
struct WorkaroundsGL;
class BlitGL : public angle::NonCopyable
{
public:
BlitGL(const FunctionsGL *functions,
const WorkaroundsGL &workarounds,
StateManagerGL *stateManager);
~BlitGL();
gl::Error copyImageToLUMAWorkaroundTexture(GLuint texture,
GLenum textureType,
GLenum target,
GLenum lumaFormat,
size_t level,
const gl::Rectangle &sourceArea,
GLenum internalFormat,
const gl::Framebuffer *source);
gl::Error copySubImageToLUMAWorkaroundTexture(GLuint texture,
GLenum textureType,
GLenum target,
GLenum lumaFormat,
size_t level,
const gl::Offset &destOffset,
const gl::Rectangle &sourceArea,
const gl::Framebuffer *source);
gl::Error initializeResources();
private:
const FunctionsGL *mFunctions;
const WorkaroundsGL &mWorkarounds;
StateManagerGL *mStateManager;
GLuint mBlitProgram;
GLuint mScratchTexture;
GLuint mScratchFBO;
GLuint mVAO;
};
}
#endif // LIBANGLE_RENDERER_GL_BLITGL_H_
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "libANGLE/AttributeMap.h" #include "libANGLE/AttributeMap.h"
#include "libANGLE/Data.h" #include "libANGLE/Data.h"
#include "libANGLE/Surface.h" #include "libANGLE/Surface.h"
#include "libANGLE/renderer/gl/BlitGL.h"
#include "libANGLE/renderer/gl/BufferGL.h" #include "libANGLE/renderer/gl/BufferGL.h"
#include "libANGLE/renderer/gl/CompilerGL.h" #include "libANGLE/renderer/gl/CompilerGL.h"
#include "libANGLE/renderer/gl/FenceNVGL.h" #include "libANGLE/renderer/gl/FenceNVGL.h"
...@@ -83,11 +84,13 @@ RendererGL::RendererGL(const FunctionsGL *functions, const egl::AttributeMap &at ...@@ -83,11 +84,13 @@ RendererGL::RendererGL(const FunctionsGL *functions, const egl::AttributeMap &at
mMaxSupportedESVersion(0, 0), mMaxSupportedESVersion(0, 0),
mFunctions(functions), mFunctions(functions),
mStateManager(nullptr), mStateManager(nullptr),
mBlitter(nullptr),
mSkipDrawCalls(false) mSkipDrawCalls(false)
{ {
ASSERT(mFunctions); ASSERT(mFunctions);
mStateManager = new StateManagerGL(mFunctions, getRendererCaps()); mStateManager = new StateManagerGL(mFunctions, getRendererCaps());
nativegl_gl::GenerateWorkarounds(mFunctions, &mWorkarounds); nativegl_gl::GenerateWorkarounds(mFunctions, &mWorkarounds);
mBlitter = new BlitGL(functions, mWorkarounds, mStateManager);
#ifndef NDEBUG #ifndef NDEBUG
if (mFunctions->debugMessageControl && mFunctions->debugMessageCallback) if (mFunctions->debugMessageControl && mFunctions->debugMessageCallback)
...@@ -111,6 +114,7 @@ RendererGL::RendererGL(const FunctionsGL *functions, const egl::AttributeMap &at ...@@ -111,6 +114,7 @@ RendererGL::RendererGL(const FunctionsGL *functions, const egl::AttributeMap &at
RendererGL::~RendererGL() RendererGL::~RendererGL()
{ {
SafeDelete(mStateManager); SafeDelete(mStateManager);
SafeDelete(mBlitter);
} }
gl::Error RendererGL::flush() gl::Error RendererGL::flush()
...@@ -188,7 +192,7 @@ FramebufferImpl *RendererGL::createFramebuffer(const gl::Framebuffer::Data &data ...@@ -188,7 +192,7 @@ FramebufferImpl *RendererGL::createFramebuffer(const gl::Framebuffer::Data &data
TextureImpl *RendererGL::createTexture(GLenum target) TextureImpl *RendererGL::createTexture(GLenum target)
{ {
return new TextureGL(target, mFunctions, mWorkarounds, mStateManager); return new TextureGL(target, mFunctions, mWorkarounds, mStateManager, mBlitter);
} }
RenderbufferImpl *RendererGL::createRenderbuffer() RenderbufferImpl *RendererGL::createRenderbuffer()
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
namespace rx namespace rx
{ {
class BlitGL;
class FunctionsGL; class FunctionsGL;
class StateManagerGL; class StateManagerGL;
...@@ -92,6 +93,8 @@ class RendererGL : public Renderer ...@@ -92,6 +93,8 @@ class RendererGL : public Renderer
const FunctionsGL *mFunctions; const FunctionsGL *mFunctions;
StateManagerGL *mStateManager; StateManagerGL *mStateManager;
BlitGL *mBlitter;
WorkaroundsGL mWorkarounds; WorkaroundsGL mWorkarounds;
// For performance debugging // For performance debugging
......
...@@ -15,17 +15,29 @@ ...@@ -15,17 +15,29 @@
namespace rx namespace rx
{ {
class BlitGL;
class FunctionsGL; class FunctionsGL;
class StateManagerGL; class StateManagerGL;
struct WorkaroundsGL; struct WorkaroundsGL;
struct LUMAWorkaround
{
bool enabled;
GLenum sourceFormat;
GLenum workaroundFormat;
LUMAWorkaround();
LUMAWorkaround(bool enabled, GLenum sourceFormat, GLenum workaroundFormat);
};
class TextureGL : public TextureImpl class TextureGL : public TextureImpl
{ {
public: public:
TextureGL(GLenum type, TextureGL(GLenum type,
const FunctionsGL *functions, const FunctionsGL *functions,
const WorkaroundsGL &workarounds, const WorkaroundsGL &workarounds,
StateManagerGL *stateManager); StateManagerGL *stateManager,
BlitGL *blitter);
~TextureGL() override; ~TextureGL() override;
void setUsage(GLenum usage) override; void setUsage(GLenum usage) override;
...@@ -69,6 +81,9 @@ class TextureGL : public TextureImpl ...@@ -69,6 +81,9 @@ class TextureGL : public TextureImpl
const FunctionsGL *mFunctions; const FunctionsGL *mFunctions;
const WorkaroundsGL &mWorkarounds; const WorkaroundsGL &mWorkarounds;
StateManagerGL *mStateManager; StateManagerGL *mStateManager;
BlitGL *mBlitter;
std::vector<LUMAWorkaround> mLUMAWorkaroundLevels;
mutable gl::SamplerState mAppliedSamplerState; mutable gl::SamplerState mAppliedSamplerState;
GLuint mTextureID; GLuint mTextureID;
......
...@@ -316,6 +316,21 @@ static GLenum GetNativeInternalFormat(const FunctionsGL *functions, ...@@ -316,6 +316,21 @@ static GLenum GetNativeInternalFormat(const FunctionsGL *functions,
// Update the internal format to GL_RGBA. // Update the internal format to GL_RGBA.
result = GL_RGBA8; result = GL_RGBA8;
} }
if ((functions->profile & GL_CONTEXT_CORE_PROFILE_BIT) != 0)
{
// Work around deprecated luminance alpha formats in the OpenGL core profile by backing
// them with R or RG textures.
if (formatInfo.format == GL_LUMINANCE || formatInfo.format == GL_ALPHA)
{
result = gl::GetSizedInternalFormat(GL_RED, formatInfo.type);
}
if (formatInfo.format == GL_LUMINANCE_ALPHA)
{
result = gl::GetSizedInternalFormat(GL_RG, formatInfo.type);
}
}
} }
else if (functions->isAtLeastGLES(gl::Version(3, 0))) else if (functions->isAtLeastGLES(gl::Version(3, 0)))
{ {
...@@ -344,6 +359,21 @@ static GLenum GetNativeFormat(const FunctionsGL *functions, ...@@ -344,6 +359,21 @@ static GLenum GetNativeFormat(const FunctionsGL *functions,
{ {
result = GL_RGBA; result = GL_RGBA;
} }
if ((functions->profile & GL_CONTEXT_CORE_PROFILE_BIT) != 0)
{
// Work around deprecated luminance alpha formats in the OpenGL core profile by backing
// them with R or RG textures.
if (format == GL_LUMINANCE || format == GL_ALPHA)
{
result = GL_RED;
}
if (format == GL_LUMINANCE_ALPHA)
{
result = GL_RG;
}
}
} }
return result; return result;
......
...@@ -388,6 +388,8 @@ ...@@ -388,6 +388,8 @@
], ],
'libangle_gl_sources': 'libangle_gl_sources':
[ [
'libANGLE/renderer/gl/BlitGL.cpp',
'libANGLE/renderer/gl/BlitGL.h',
'libANGLE/renderer/gl/BufferGL.cpp', 'libANGLE/renderer/gl/BufferGL.cpp',
'libANGLE/renderer/gl/BufferGL.h', 'libANGLE/renderer/gl/BufferGL.h',
'libANGLE/renderer/gl/CompilerGL.cpp', 'libANGLE/renderer/gl/CompilerGL.cpp',
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
'<(angle_path)/src/tests/gl_tests/BufferDataTest.cpp', '<(angle_path)/src/tests/gl_tests/BufferDataTest.cpp',
'<(angle_path)/src/tests/gl_tests/ClearTest.cpp', '<(angle_path)/src/tests/gl_tests/ClearTest.cpp',
'<(angle_path)/src/tests/gl_tests/CompressedTextureTest.cpp', '<(angle_path)/src/tests/gl_tests/CompressedTextureTest.cpp',
'<(angle_path)/src/tests/gl_tests/CopyTexImageTest.cpp',
'<(angle_path)/src/tests/gl_tests/CubeMapTextureTest.cpp', '<(angle_path)/src/tests/gl_tests/CubeMapTextureTest.cpp',
'<(angle_path)/src/tests/gl_tests/DebugMarkerTest.cpp', '<(angle_path)/src/tests/gl_tests/DebugMarkerTest.cpp',
'<(angle_path)/src/tests/gl_tests/DepthStencilFormatsTest.cpp', '<(angle_path)/src/tests/gl_tests/DepthStencilFormatsTest.cpp',
......
//
// Copyright 2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#include "test_utils/ANGLETest.h"
namespace angle
{
class CopyTexImageTest : public ANGLETest
{
protected:
CopyTexImageTest()
{
setWindowWidth(16);
setWindowHeight(16);
setConfigRedBits(8);
setConfigGreenBits(8);
setConfigBlueBits(8);
setConfigAlphaBits(8);
}
GLuint createFramebuffer(GLenum format, GLenum type, GLfloat color[4]) const
{
GLuint fbo;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
GLuint texture = createTexture(format, type);
glBindTexture(GL_TEXTURE_2D, texture);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
glClearColor(color[0], color[1], color[2], color[3]);
glClear(GL_COLOR_BUFFER_BIT);
return fbo;
}
GLuint createTexture(GLenum format, GLenum type) const
{
GLuint tex;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(GL_TEXTURE_2D, 0, format, 16, 16, 0, format, type, nullptr);
// Disable mipmapping
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
return tex;
}
GLuint createTextureFromCopyTexImage(GLuint fbo, GLenum format) const
{
GLuint tex;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glCopyTexImage2D(GL_TEXTURE_2D, 0, format, 0, 0, 16, 16, 0);
// Disable mipmapping
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
return tex;
}
void copyTextureWithCopyTexSubImage(GLuint fbo,
GLuint texture,
GLint xoffset,
GLint yoffset,
GLint x,
GLint y,
GLsizei w,
GLsizei h) const
{
glBindTexture(GL_TEXTURE_2D, texture);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, xoffset, yoffset, x, y, w, h);
}
virtual void SetUp()
{
ANGLETest::SetUp();
const std::string vsSource =
"precision highp float;\n"
"attribute vec4 position;\n"
"varying vec2 texcoord;\n"
"\n"
"void main()\n"
"{\n"
" gl_Position = position;\n"
" texcoord = (position.xy * 0.5) + 0.5;\n"
" texcoord.y = 1.0 - texcoord.y;\n"
"}\n";
const std::string textureFSSource =
"precision highp float;\n"
"uniform sampler2D tex;\n"
"varying vec2 texcoord;\n"
"\n"
"void main()\n"
"{\n"
" gl_FragColor = texture2D(tex, texcoord);\n"
"}\n";
mTextureProgram = CompileProgram(vsSource, textureFSSource);
if (mTextureProgram == 0)
{
FAIL() << "shader compilation failed.";
}
mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "tex");
ASSERT_GL_NO_ERROR();
}
virtual void TearDown()
{
glDeleteProgram(mTextureProgram);
ANGLETest::TearDown();
}
void verifyResults(GLuint texture, GLubyte data[4], GLint x, GLint y) const
{
glViewport(0, 0, 16, 16);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Draw a quad with the target texture
glUseProgram(mTextureProgram);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(mTextureUniformLocation, 0);
drawQuad(mTextureProgram, "position", 0.5f);
// Expect that the rendered quad has the same color as the source texture
EXPECT_PIXEL_NEAR(x, y, data[0], data[1], data[2], data[3], 1.0);
}
GLuint mTextureProgram;
GLint mTextureUniformLocation;
};
TEST_P(CopyTexImageTest, RGBAToL)
{
GLfloat color[] = {
0.25f, 1.0f, 0.75f, 0.5f,
};
GLuint fbo = createFramebuffer(GL_RGBA, GL_UNSIGNED_BYTE, color);
GLuint tex = createTextureFromCopyTexImage(fbo, GL_LUMINANCE);
GLubyte expected[] = {
64, 64, 64, 255,
};
verifyResults(tex, expected, 0, 0);
}
TEST_P(CopyTexImageTest, RGBToL)
{
GLfloat color[] = {
0.25f, 1.0f, 0.75f, 0.5f,
};
GLuint fbo = createFramebuffer(GL_RGB, GL_UNSIGNED_BYTE, color);
GLuint tex = createTextureFromCopyTexImage(fbo, GL_LUMINANCE);
GLubyte expected[] = {
64, 64, 64, 255,
};
verifyResults(tex, expected, 0, 0);
}
TEST_P(CopyTexImageTest, RGBAToLA)
{
GLfloat color[] = {
0.25f, 1.0f, 0.75f, 0.5f,
};
GLuint fbo = createFramebuffer(GL_RGBA, GL_UNSIGNED_BYTE, color);
GLuint tex = createTextureFromCopyTexImage(fbo, GL_LUMINANCE_ALPHA);
GLubyte expected[] = {
64, 64, 64, 127,
};
verifyResults(tex, expected, 0, 0);
}
TEST_P(CopyTexImageTest, RGBAToA)
{
GLfloat color[] = {
0.25f, 1.0f, 0.75f, 0.5f,
};
GLuint fbo = createFramebuffer(GL_RGBA, GL_UNSIGNED_BYTE, color);
GLuint tex = createTextureFromCopyTexImage(fbo, GL_ALPHA);
GLubyte expected[] = {
0, 0, 0, 127,
};
verifyResults(tex, expected, 0, 0);
}
TEST_P(CopyTexImageTest, SubImageRGBAToL)
{
GLfloat color0[] = {
0.25f, 1.0f, 0.75f, 0.5f,
};
GLuint fbo0 = createFramebuffer(GL_RGBA, GL_UNSIGNED_BYTE, color0);
GLuint tex = createTextureFromCopyTexImage(fbo0, GL_LUMINANCE);
GLfloat color1[] = {
0.5f, 0.25f, 1.0f, 0.75f,
};
GLuint fbo1 = createFramebuffer(GL_RGBA, GL_UNSIGNED_BYTE, color1);
copyTextureWithCopyTexSubImage(fbo1, tex, 2, 4, 5, 6, 8, 8);
GLubyte expected0[] = {
64, 64, 64, 255,
};
verifyResults(tex, expected0, 0, 0);
GLubyte expected1[] = {
127, 127, 127, 255,
};
verifyResults(tex, expected1, 7, 7);
}
TEST_P(CopyTexImageTest, SubImageRGBAToLA)
{
GLfloat color0[] = {
0.25f, 1.0f, 0.75f, 0.5f,
};
GLuint fbo0 = createFramebuffer(GL_RGBA, GL_UNSIGNED_BYTE, color0);
GLuint tex = createTextureFromCopyTexImage(fbo0, GL_LUMINANCE_ALPHA);
GLfloat color1[] = {
0.5f, 0.25f, 1.0f, 0.75f,
};
GLuint fbo1 = createFramebuffer(GL_RGBA, GL_UNSIGNED_BYTE, color1);
copyTextureWithCopyTexSubImage(fbo1, tex, 2, 4, 5, 6, 8, 8);
GLubyte expected0[] = {
64, 64, 64, 127,
};
verifyResults(tex, expected0, 0, 0);
GLubyte expected1[] = {
127, 127, 127, 192,
};
verifyResults(tex, expected1, 7, 7);
}
TEST_P(CopyTexImageTest, SubImageRGBToL)
{
GLfloat color0[] = {
0.25f, 1.0f, 0.75f, 0.5f,
};
GLuint fbo0 = createFramebuffer(GL_RGB, GL_UNSIGNED_BYTE, color0);
GLuint tex = createTextureFromCopyTexImage(fbo0, GL_LUMINANCE);
GLfloat color1[] = {
0.5f, 0.25f, 1.0f, 0.75f,
};
GLuint fbo1 = createFramebuffer(GL_RGB, GL_UNSIGNED_BYTE, color1);
copyTextureWithCopyTexSubImage(fbo1, tex, 2, 4, 5, 6, 8, 8);
GLubyte expected0[] = {
64, 64, 64, 255,
};
verifyResults(tex, expected0, 0, 0);
GLubyte expected1[] = {
127, 127, 127, 255,
};
verifyResults(tex, expected1, 7, 7);
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against.
ANGLE_INSTANTIATE_TEST(CopyTexImageTest, ES2_D3D9(), ES2_D3D11(), ES2_OPENGL(), ES2_OPENGL(3, 3));
}
...@@ -108,8 +108,7 @@ class SwizzleTest : public ANGLETest ...@@ -108,8 +108,7 @@ class SwizzleTest : public ANGLETest
{ {
glGenTextures(1, &mTexture); glGenTextures(1, &mTexture);
glBindTexture(GL_TEXTURE_2D, mTexture); glBindTexture(GL_TEXTURE_2D, mTexture);
glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, 1, 1); glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, 1, 1, 0, dataFormat, dataType, data);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, dataFormat, dataType, data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
...@@ -268,6 +267,52 @@ TEST_P(SwizzleTest, D24_2D) ...@@ -268,6 +267,52 @@ TEST_P(SwizzleTest, D24_2D)
runTest2D(); runTest2D();
} }
TEST_P(SwizzleTest, L8_2D)
{
GLubyte data[] = {0x77};
init2DTexture(GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
runTest2D();
}
TEST_P(SwizzleTest, A8_2D)
{
GLubyte data[] = {0x55};
init2DTexture(GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, data);
runTest2D();
}
TEST_P(SwizzleTest, LA8_2D)
{
GLubyte data[] = {0x77, 0x66};
init2DTexture(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, data);
runTest2D();
}
TEST_P(SwizzleTest, L32F_2D)
{
GLfloat data[] = {0.7f};
init2DTexture(GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT, data);
runTest2D();
}
TEST_P(SwizzleTest, A32F_2D)
{
GLfloat data[] = {
0.4f,
};
init2DTexture(GL_ALPHA, GL_ALPHA, GL_FLOAT, data);
runTest2D();
}
TEST_P(SwizzleTest, LA32F_2D)
{
GLfloat data[] = {
0.5f, 0.6f,
};
init2DTexture(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT, data);
runTest2D();
}
#include "media/pixel.inl" #include "media/pixel.inl"
TEST_P(SwizzleTest, CompressedDXT_2D) TEST_P(SwizzleTest, CompressedDXT_2D)
...@@ -283,6 +328,6 @@ TEST_P(SwizzleTest, CompressedDXT_2D) ...@@ -283,6 +328,6 @@ TEST_P(SwizzleTest, CompressedDXT_2D)
} }
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against. // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
ANGLE_INSTANTIATE_TEST(SwizzleTest, ES3_D3D11(), ES3_OPENGL()); ANGLE_INSTANTIATE_TEST(SwizzleTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGL(3, 3));
} // namespace } // namespace
...@@ -105,14 +105,6 @@ class UnpackAlignmentTest : public ANGLETest ...@@ -105,14 +105,6 @@ class UnpackAlignmentTest : public ANGLETest
void testAlignment(int alignment, unsigned int offset, GLenum format, GLenum type) void testAlignment(int alignment, unsigned int offset, GLenum format, GLenum type)
{ {
// TODO(geofflang): Support LUMA formats in the core profile.
if (getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE &&
(format == GL_LUMINANCE_ALPHA || format == GL_LUMINANCE || format == GL_ALPHA))
{
std::cout << "Test skipped on OpenGL with LUMA formats." << std::endl;
return;
}
static const unsigned int width = 7; static const unsigned int width = 7;
static const unsigned int height = 2; static const unsigned int height = 2;
......
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