Commit 13b708f2 by Lingfeng Yang Committed by Commit Bot

GLES1: glAlphaFunc

BUG=angleproject:2306 Change-Id: I0bf229d3ab8a4a1217c12b434dcd8fa67d7cbadc Reviewed-on: https://chromium-review.googlesource.com/973897 Commit-Queue: Lingfeng Yang <lfy@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 7a06ac1b
{
"glAlphaFunc": {
"func": "AlphaTestFunc"
},
"glAlphaFuncx": {
"func": "AlphaTestFunc"
},
"glBindBuffer": {
"target": "BufferBinding"
},
......
......@@ -9,12 +9,12 @@
#ifndef COMMON_MATHUTIL_H_
#define COMMON_MATHUTIL_H_
#include <limits>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <limits>
#include <anglebase/numerics/safe_math.h>
......@@ -30,10 +30,10 @@ using base::IsValueInRangeForNumericType;
namespace gl
{
const unsigned int Float32One = 0x3F800000;
const unsigned int Float32One = 0x3F800000;
const unsigned short Float16One = 0x3C00;
template<typename T>
template <typename T>
inline bool isPow2(T x)
{
static_assert(std::is_integral<T>::value, "isPow2 must be called on an integer type.");
......@@ -43,13 +43,15 @@ inline bool isPow2(T x)
inline int log2(int x)
{
int r = 0;
while ((x >> r) > 1) r++;
while ((x >> r) > 1)
r++;
return r;
}
inline unsigned int ceilPow2(unsigned int x)
{
if (x != 0) x--;
if (x != 0)
x--;
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
......@@ -108,7 +110,7 @@ inline int clampCast(bool value)
return static_cast<int>(value);
}
template<typename T, typename MIN, typename MAX>
template <typename T, typename MIN, typename MAX>
inline T clamp(T x, MIN min, MAX max)
{
// Since NaNs fail all comparison tests, a NaN value will default to min
......@@ -120,7 +122,7 @@ inline float clamp01(float x)
return clamp(x, 0.0f, 1.0f);
}
template<const int n>
template <const int n>
inline unsigned int unorm(float x)
{
const unsigned int max = 0xFFFFFFFF >> (32 - n);
......@@ -142,7 +144,7 @@ inline unsigned int unorm(float x)
inline bool supportsSSE2()
{
#if defined(ANGLE_USE_SSE)
static bool checked = false;
static bool checked = false;
static bool supports = false;
if (checked)
......@@ -182,19 +184,19 @@ destType bitCast(const sourceType &source)
inline unsigned short float32ToFloat16(float fp32)
{
unsigned int fp32i = bitCast<unsigned int>(fp32);
unsigned int sign = (fp32i & 0x80000000) >> 16;
unsigned int abs = fp32i & 0x7FFFFFFF;
unsigned int sign = (fp32i & 0x80000000) >> 16;
unsigned int abs = fp32i & 0x7FFFFFFF;
if(abs > 0x47FFEFFF) // Infinity
if (abs > 0x47FFEFFF) // Infinity
{
return static_cast<unsigned short>(sign | 0x7FFF);
}
else if(abs < 0x38800000) // Denormal
else if (abs < 0x38800000) // Denormal
{
unsigned int mantissa = (abs & 0x007FFFFF) | 0x00800000;
int e = 113 - (abs >> 23);
int e = 113 - (abs >> 23);
if(e < 24)
if (e < 24)
{
abs = mantissa >> e;
}
......@@ -207,7 +209,8 @@ inline unsigned short float32ToFloat16(float fp32)
}
else
{
return static_cast<unsigned short>(sign | (abs + 0xC8000000 + 0x00000FFF + ((abs >> 13) & 1)) >> 13);
return static_cast<unsigned short>(
sign | (abs + 0xC8000000 + 0x00000FFF + ((abs >> 13) & 1)) >> 13);
}
}
......@@ -218,24 +221,24 @@ void convert999E5toRGBFloats(unsigned int input, float *red, float *green, float
inline unsigned short float32ToFloat11(float fp32)
{
const unsigned int float32MantissaMask = 0x7FFFFF;
const unsigned int float32ExponentMask = 0x7F800000;
const unsigned int float32SignMask = 0x80000000;
const unsigned int float32ValueMask = ~float32SignMask;
const unsigned int float32MantissaMask = 0x7FFFFF;
const unsigned int float32ExponentMask = 0x7F800000;
const unsigned int float32SignMask = 0x80000000;
const unsigned int float32ValueMask = ~float32SignMask;
const unsigned int float32ExponentFirstBit = 23;
const unsigned int float32ExponentBias = 127;
const unsigned int float32ExponentBias = 127;
const unsigned short float11Max = 0x7BF;
const unsigned short float11Max = 0x7BF;
const unsigned short float11MantissaMask = 0x3F;
const unsigned short float11ExponentMask = 0x7C0;
const unsigned short float11BitMask = 0x7FF;
const unsigned int float11ExponentBias = 14;
const unsigned short float11BitMask = 0x7FF;
const unsigned int float11ExponentBias = 14;
const unsigned int float32Maxfloat11 = 0x477E0000;
const unsigned int float32Minfloat11 = 0x38800000;
const unsigned int float32Bits = bitCast<unsigned int>(fp32);
const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask;
const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask;
unsigned int float32Val = float32Bits & float32ValueMask;
......@@ -244,7 +247,9 @@ inline unsigned short float32ToFloat11(float fp32)
// INF or NAN
if ((float32Val & float32MantissaMask) != 0)
{
return float11ExponentMask | (((float32Val >> 17) | (float32Val >> 11) | (float32Val >> 6) | (float32Val)) & float11MantissaMask);
return float11ExponentMask |
(((float32Val >> 17) | (float32Val >> 11) | (float32Val >> 6) | (float32Val)) &
float11MantissaMask);
}
else if (float32Sign)
{
......@@ -272,8 +277,10 @@ inline unsigned short float32ToFloat11(float fp32)
{
// The number is too small to be represented as a normalized float11
// Convert it to a denormalized value.
const unsigned int shift = (float32ExponentBias - float11ExponentBias) - (float32Val >> float32ExponentFirstBit);
float32Val = ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;
const unsigned int shift = (float32ExponentBias - float11ExponentBias) -
(float32Val >> float32ExponentFirstBit);
float32Val =
((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;
}
else
{
......@@ -287,24 +294,24 @@ inline unsigned short float32ToFloat11(float fp32)
inline unsigned short float32ToFloat10(float fp32)
{
const unsigned int float32MantissaMask = 0x7FFFFF;
const unsigned int float32ExponentMask = 0x7F800000;
const unsigned int float32SignMask = 0x80000000;
const unsigned int float32ValueMask = ~float32SignMask;
const unsigned int float32MantissaMask = 0x7FFFFF;
const unsigned int float32ExponentMask = 0x7F800000;
const unsigned int float32SignMask = 0x80000000;
const unsigned int float32ValueMask = ~float32SignMask;
const unsigned int float32ExponentFirstBit = 23;
const unsigned int float32ExponentBias = 127;
const unsigned int float32ExponentBias = 127;
const unsigned short float10Max = 0x3DF;
const unsigned short float10Max = 0x3DF;
const unsigned short float10MantissaMask = 0x1F;
const unsigned short float10ExponentMask = 0x3E0;
const unsigned short float10BitMask = 0x3FF;
const unsigned int float10ExponentBias = 14;
const unsigned short float10BitMask = 0x3FF;
const unsigned int float10ExponentBias = 14;
const unsigned int float32Maxfloat10 = 0x477C0000;
const unsigned int float32Minfloat10 = 0x38800000;
const unsigned int float32Bits = bitCast<unsigned int>(fp32);
const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask;
const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask;
unsigned int float32Val = float32Bits & float32ValueMask;
......@@ -313,7 +320,9 @@ inline unsigned short float32ToFloat10(float fp32)
// INF or NAN
if ((float32Val & float32MantissaMask) != 0)
{
return float10ExponentMask | (((float32Val >> 18) | (float32Val >> 13) | (float32Val >> 3) | (float32Val)) & float10MantissaMask);
return float10ExponentMask |
(((float32Val >> 18) | (float32Val >> 13) | (float32Val >> 3) | (float32Val)) &
float10MantissaMask);
}
else if (float32Sign)
{
......@@ -341,8 +350,10 @@ inline unsigned short float32ToFloat10(float fp32)
{
// The number is too small to be represented as a normalized float11
// Convert it to a denormalized value.
const unsigned int shift = (float32ExponentBias - float10ExponentBias) - (float32Val >> float32ExponentFirstBit);
float32Val = ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;
const unsigned int shift = (float32ExponentBias - float10ExponentBias) -
(float32Val >> float32ExponentFirstBit);
float32Val =
((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;
}
else
{
......@@ -379,12 +390,11 @@ inline float float11ToFloat32(unsigned short fp11)
{
exponent--;
mantissa <<= 1;
}
while ((mantissa & 0x40) == 0);
} while ((mantissa & 0x40) == 0);
mantissa = mantissa & 0x3F;
}
else // The value is zero
else // The value is zero
{
exponent = static_cast<unsigned short>(-112);
}
......@@ -418,12 +428,11 @@ inline float float10ToFloat32(unsigned short fp11)
{
exponent--;
mantissa <<= 1;
}
while ((mantissa & 0x20) == 0);
} while ((mantissa & 0x20) == 0);
mantissa = mantissa & 0x1F;
}
else // The value is zero
else // The value is zero
{
exponent = static_cast<unsigned short>(-112);
}
......@@ -432,6 +441,32 @@ inline float float10ToFloat32(unsigned short fp11)
}
}
// Convers to and from float and 16.16 fixed point format.
inline float FixedToFloat(uint32_t fixedInput)
{
return static_cast<float>(fixedInput) / 65536.0f;
}
inline uint32_t FloatToFixed(float floatInput)
{
static constexpr uint32_t kHighest = 32767 * 65536 + 65535;
static constexpr uint32_t kLowest = static_cast<uint32_t>(-32768 * 65536 + 65535);
if (floatInput > 32767.65535)
{
return kHighest;
}
else if (floatInput < -32768.65535)
{
return kLowest;
}
else
{
return static_cast<uint32_t>(floatInput * 65536);
}
}
template <typename T>
inline float normalizedToFloat(T input)
{
......@@ -563,12 +598,16 @@ inline unsigned short averageHalfFloat(unsigned short a, unsigned short b)
inline unsigned int averageFloat11(unsigned int a, unsigned int b)
{
return float32ToFloat11((float11ToFloat32(static_cast<unsigned short>(a)) + float11ToFloat32(static_cast<unsigned short>(b))) * 0.5f);
return float32ToFloat11((float11ToFloat32(static_cast<unsigned short>(a)) +
float11ToFloat32(static_cast<unsigned short>(b))) *
0.5f);
}
inline unsigned int averageFloat10(unsigned int a, unsigned int b)
{
return float32ToFloat10((float10ToFloat32(static_cast<unsigned short>(a)) + float10ToFloat32(static_cast<unsigned short>(b))) * 0.5f);
return float32ToFloat10((float10ToFloat32(static_cast<unsigned short>(a)) +
float10ToFloat32(static_cast<unsigned short>(b))) *
0.5f);
}
template <typename T>
......@@ -687,21 +726,21 @@ inline float Ldexp(float x, int exp)
inline uint32_t packSnorm2x16(float f1, float f2)
{
int16_t leastSignificantBits = static_cast<int16_t>(roundf(clamp(f1, -1.0f, 1.0f) * 32767.0f));
int16_t mostSignificantBits = static_cast<int16_t>(roundf(clamp(f2, -1.0f, 1.0f) * 32767.0f));
int16_t mostSignificantBits = static_cast<int16_t>(roundf(clamp(f2, -1.0f, 1.0f) * 32767.0f));
return static_cast<uint32_t>(mostSignificantBits) << 16 |
(static_cast<uint32_t>(leastSignificantBits) & 0xFFFF);
}
// First, unpacks a single 32-bit unsigned integer u into a pair of 16-bit unsigned integers. Then, each
// component is converted to a normalized floating-point value to generate the returned two float values.
// The first float value will be extracted from the least significant bits of the input;
// the last float value will be extracted from the most-significant bits.
// The conversion for unpacked fixed-point value to floating point is done as follows:
// unpackSnorm2x16 : clamp(f / 32767.0, -1, +1)
// First, unpacks a single 32-bit unsigned integer u into a pair of 16-bit unsigned integers. Then,
// each component is converted to a normalized floating-point value to generate the returned two
// float values. The first float value will be extracted from the least significant bits of the
// input; the last float value will be extracted from the most-significant bits. The conversion for
// unpacked fixed-point value to floating point is done as follows: unpackSnorm2x16 : clamp(f /
// 32767.0, -1, +1)
inline void unpackSnorm2x16(uint32_t u, float *f1, float *f2)
{
int16_t leastSignificantBits = static_cast<int16_t>(u & 0xFFFF);
int16_t mostSignificantBits = static_cast<int16_t>(u >> 16);
int16_t mostSignificantBits = static_cast<int16_t>(u >> 16);
*f1 = clamp(static_cast<float>(leastSignificantBits) / 32767.0f, -1.0f, 1.0f);
*f2 = clamp(static_cast<float>(mostSignificantBits) / 32767.0f, -1.0f, 1.0f);
}
......@@ -715,22 +754,22 @@ inline void unpackSnorm2x16(uint32_t u, float *f1, float *f2)
inline uint32_t packUnorm2x16(float f1, float f2)
{
uint16_t leastSignificantBits = static_cast<uint16_t>(roundf(clamp(f1, 0.0f, 1.0f) * 65535.0f));
uint16_t mostSignificantBits = static_cast<uint16_t>(roundf(clamp(f2, 0.0f, 1.0f) * 65535.0f));
return static_cast<uint32_t>(mostSignificantBits) << 16 | static_cast<uint32_t>(leastSignificantBits);
uint16_t mostSignificantBits = static_cast<uint16_t>(roundf(clamp(f2, 0.0f, 1.0f) * 65535.0f));
return static_cast<uint32_t>(mostSignificantBits) << 16 |
static_cast<uint32_t>(leastSignificantBits);
}
// First, unpacks a single 32-bit unsigned integer u into a pair of 16-bit unsigned integers. Then, each
// component is converted to a normalized floating-point value to generate the returned two float values.
// The first float value will be extracted from the least significant bits of the input;
// the last float value will be extracted from the most-significant bits.
// The conversion for unpacked fixed-point value to floating point is done as follows:
// unpackUnorm2x16 : f / 65535.0
// First, unpacks a single 32-bit unsigned integer u into a pair of 16-bit unsigned integers. Then,
// each component is converted to a normalized floating-point value to generate the returned two
// float values. The first float value will be extracted from the least significant bits of the
// input; the last float value will be extracted from the most-significant bits. The conversion for
// unpacked fixed-point value to floating point is done as follows: unpackUnorm2x16 : f / 65535.0
inline void unpackUnorm2x16(uint32_t u, float *f1, float *f2)
{
uint16_t leastSignificantBits = static_cast<uint16_t>(u & 0xFFFF);
uint16_t mostSignificantBits = static_cast<uint16_t>(u >> 16);
*f1 = static_cast<float>(leastSignificantBits) / 65535.0f;
*f2 = static_cast<float>(mostSignificantBits) / 65535.0f;
uint16_t mostSignificantBits = static_cast<uint16_t>(u >> 16);
*f1 = static_cast<float>(leastSignificantBits) / 65535.0f;
*f2 = static_cast<float>(mostSignificantBits) / 65535.0f;
}
// Helper functions intended to be used only here.
......@@ -821,19 +860,20 @@ inline void UnpackSnorm4x8(uint32_t u, float *f)
inline uint32_t packHalf2x16(float f1, float f2)
{
uint16_t leastSignificantBits = static_cast<uint16_t>(float32ToFloat16(f1));
uint16_t mostSignificantBits = static_cast<uint16_t>(float32ToFloat16(f2));
return static_cast<uint32_t>(mostSignificantBits) << 16 | static_cast<uint32_t>(leastSignificantBits);
uint16_t mostSignificantBits = static_cast<uint16_t>(float32ToFloat16(f2));
return static_cast<uint32_t>(mostSignificantBits) << 16 |
static_cast<uint32_t>(leastSignificantBits);
}
// Returns two floating-point values obtained by unpacking a 32-bit unsigned integer into a pair of 16-bit values,
// interpreting those values as 16-bit floating-point numbers according to the OpenGL ES Specification,
// and converting them to 32-bit floating-point values.
// The first float value is obtained from the 16 least-significant bits of u;
// the second component is obtained from the 16 most-significant bits of u.
// Returns two floating-point values obtained by unpacking a 32-bit unsigned integer into a pair of
// 16-bit values, interpreting those values as 16-bit floating-point numbers according to the OpenGL
// ES Specification, and converting them to 32-bit floating-point values. The first float value is
// obtained from the 16 least-significant bits of u; the second component is obtained from the 16
// most-significant bits of u.
inline void unpackHalf2x16(uint32_t u, float *f1, float *f2)
{
uint16_t leastSignificantBits = static_cast<uint16_t>(u & 0xFFFF);
uint16_t mostSignificantBits = static_cast<uint16_t>(u >> 16);
uint16_t mostSignificantBits = static_cast<uint16_t>(u >> 16);
*f1 = float16ToFloat32(leastSignificantBits);
*f2 = float16ToFloat32(mostSignificantBits);
......@@ -1004,21 +1044,25 @@ int FindMSB(T bits)
}
// Returns whether the argument is Not a Number.
// IEEE 754 single precision NaN representation: Exponent(8 bits) - 255, Mantissa(23 bits) - non-zero.
// IEEE 754 single precision NaN representation: Exponent(8 bits) - 255, Mantissa(23 bits) -
// non-zero.
inline bool isNaN(float f)
{
// Exponent mask: ((1u << 8) - 1u) << 23 = 0x7f800000u
// Mantissa mask: ((1u << 23) - 1u) = 0x7fffffu
return ((bitCast<uint32_t>(f) & 0x7f800000u) == 0x7f800000u) && (bitCast<uint32_t>(f) & 0x7fffffu);
return ((bitCast<uint32_t>(f) & 0x7f800000u) == 0x7f800000u) &&
(bitCast<uint32_t>(f) & 0x7fffffu);
}
// Returns whether the argument is infinity.
// IEEE 754 single precision infinity representation: Exponent(8 bits) - 255, Mantissa(23 bits) - zero.
// IEEE 754 single precision infinity representation: Exponent(8 bits) - 255, Mantissa(23 bits) -
// zero.
inline bool isInf(float f)
{
// Exponent mask: ((1u << 8) - 1u) << 23 = 0x7f800000u
// Mantissa mask: ((1u << 23) - 1u) = 0x7fffffu
return ((bitCast<uint32_t>(f) & 0x7f800000u) == 0x7f800000u) && !(bitCast<uint32_t>(f) & 0x7fffffu);
return ((bitCast<uint32_t>(f) & 0x7f800000u) == 0x7f800000u) &&
!(bitCast<uint32_t>(f) & 0x7fffffu);
}
namespace priv
......@@ -1117,8 +1161,8 @@ inline unsigned int UnsignedCeilDivide(unsigned int value, unsigned int divisor)
#if defined(_MSC_VER)
#define ANGLE_ROTL(x,y) _rotl(x,y)
#define ANGLE_ROTR16(x,y) _rotr16(x,y)
#define ANGLE_ROTL(x, y) _rotl(x, y)
#define ANGLE_ROTR16(x, y) _rotr16(x, y)
#else
......@@ -1135,8 +1179,7 @@ inline uint16_t RotR16(uint16_t x, int8_t r)
#define ANGLE_ROTL(x, y) ::rx::RotL(x, y)
#define ANGLE_ROTR16(x, y) ::rx::RotR16(x, y)
#endif // namespace rx
#endif // namespace rx
}
#endif // COMMON_MATHUTIL_H_
#endif // COMMON_MATHUTIL_H_
......@@ -6373,6 +6373,21 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu
return true;
}
if (getClientVersion() < Version(2, 0))
{
switch (pname)
{
case GL_ALPHA_TEST_FUNC:
*type = GL_INT;
*numParams = 1;
return true;
case GL_ALPHA_TEST_REF:
*type = GL_FLOAT;
*numParams = 1;
return true;
}
}
if (getClientVersion() < Version(3, 0))
{
return false;
......
......@@ -8,19 +8,20 @@
#include "libANGLE/Context.h"
#include "common/mathutil.h"
#include "common/utilities.h"
namespace gl
{
void Context::alphaFunc(GLenum func, GLfloat ref)
void Context::alphaFunc(AlphaTestFunc func, GLfloat ref)
{
UNIMPLEMENTED();
mGLState.gles1().setAlphaFunc(func, ref);
}
void Context::alphaFuncx(GLenum func, GLfixed ref)
void Context::alphaFuncx(AlphaTestFunc func, GLfixed ref)
{
UNIMPLEMENTED();
mGLState.gles1().setAlphaFunc(func, FixedToFloat(ref));
}
void Context::clearColorx(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha)
......
......@@ -11,8 +11,8 @@
#define ANGLE_CONTEXT_GLES_1_0_AUTOGEN_H_
#define ANGLE_GLES1_CONTEXT_API \
void alphaFunc(GLenum func, GLfloat ref); \
void alphaFuncx(GLenum func, GLfixed ref); \
void alphaFunc(AlphaTestFunc funcPacked, GLfloat ref); \
void alphaFuncx(AlphaTestFunc funcPacked, GLfixed ref); \
void clearColorx(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha); \
void clearDepthx(GLfixed depth); \
void clientActiveTexture(GLenum texture); \
......
......@@ -46,6 +46,7 @@ ERRMSG(FramebufferIncompleteAttachment,
"Attachment type must be compatible with attachment object.");
ERRMSG(GenerateMipmapNotAllowed, "Texture format does not support mipmap generation.");
ERRMSG(GeometryShaderExtensionNotEnabled, "GL_EXT_geometry_shader extension not enabled.");
ERRMSG(GLES1Only, "GLES1-only function.");
ERRMSG(IncompatibleDrawModeAgainstGeometryShader,
"Primitive mode is incompatible with the input primitive type of the geometry shader.");
ERRMSG(IndexExceedsMaxActiveUniform, "Index exceeds program active uniform count.");
......@@ -146,7 +147,7 @@ ERRMSG(NoActiveGeometryShaderStage, "No active geometry shader stage in this pro
ERRMSG(NoActiveProgramWithComputeShader, "No active program for the compute shader stage.");
ERRMSG(NoSuchPath, "No such path object.");
ERRMSG(NoTransformFeedbackOutputVariables,
"The active program has specified no output variables to record.");
"The active program has specified no output variables to record.");
ERRMSG(NoZeroDivisor, "At least one enabled attribute must have a divisor of zero.");
ERRMSG(NVFenceNotSupported, "GL_NV_fence is not supported");
ERRMSG(ObjectNotGenerated, "Object cannot be used because it has not been generated.");
......
......@@ -34,7 +34,7 @@ GLES1State::GLES1State()
mCurrentNormal({0.0f, 0.0f, 0.0f}),
mCurrMatrixMode(MatrixType::Modelview),
mShadeModel(ShadingModel::Smooth),
mAlphaFunc(AlphaTestFunc::AlwaysPass),
mAlphaTestFunc(AlphaTestFunc::AlwaysPass),
mAlphaTestRef(0.0f),
mLogicOp(LogicalOperation::Copy),
mLineSmoothHint(HintSetting::DontCare),
......@@ -118,8 +118,8 @@ void GLES1State::initialize(const Context *context)
mShadeModel = ShadingModel::Smooth;
mAlphaFunc = AlphaTestFunc::AlwaysPass;
mAlphaTestRef = 0.0f;
mAlphaTestFunc = AlphaTestFunc::AlwaysPass;
mAlphaTestRef = 0.0f;
mLogicOp = LogicalOperation::Copy;
......@@ -142,4 +142,10 @@ void GLES1State::initialize(const Context *context)
mFogHint = HintSetting::DontCare;
}
void GLES1State::setAlphaFunc(AlphaTestFunc func, GLfloat ref)
{
mAlphaTestFunc = func;
mAlphaTestRef = ref;
}
} // namespace gl
......@@ -109,6 +109,7 @@ struct PointParameters
};
class Context;
class State;
class GLES1State final : angle::NonCopyable
{
public:
......@@ -117,7 +118,11 @@ class GLES1State final : angle::NonCopyable
void initialize(const Context *context);
void setAlphaFunc(AlphaTestFunc func, GLfloat ref);
private:
friend class State;
// All initial state values come from the
// OpenGL ES 1.1 spec.
struct TextureEnables
......@@ -179,7 +184,7 @@ class GLES1State final : angle::NonCopyable
PointParameters mPointParameters;
// Table 6.16
AlphaTestFunc mAlphaFunc;
AlphaTestFunc mAlphaTestFunc;
GLfloat mAlphaTestRef;
LogicalOperation mLogicOp;
......
......@@ -98,7 +98,9 @@ State::State()
{
}
State::~State() {}
State::~State()
{
}
void State::initialize(const Context *context,
bool debug,
......@@ -764,6 +766,12 @@ void State::setEnableFeature(GLenum feature, bool enabled)
case GL_FRAMEBUFFER_SRGB_EXT:
setFramebufferSRGB(enabled);
break;
// GLES1 emulation
case GL_ALPHA_TEST:
mGLES1State.mAlphaTestEnabled = enabled;
break;
default:
UNREACHABLE();
}
......@@ -816,6 +824,10 @@ bool State::getEnableFeature(GLenum feature) const
case GL_PROGRAM_CACHE_ENABLED_ANGLE:
return mProgramBinaryCacheEnabled;
// GLES1 emulation
case GL_ALPHA_TEST:
return mGLES1State.mAlphaTestEnabled;
default:
UNREACHABLE();
return false;
......@@ -1915,6 +1927,9 @@ void State::getFloatv(GLenum pname, GLfloat *params)
case GL_COVERAGE_MODULATION_CHROMIUM:
params[0] = static_cast<GLfloat>(mCoverageModulation);
break;
case GL_ALPHA_TEST_REF:
*params = mGLES1State.mAlphaTestRef;
break;
default:
UNREACHABLE();
break;
......@@ -2286,6 +2301,9 @@ Error State::getIntegerv(const Context *context, GLenum pname, GLint *params)
case GL_DISPATCH_INDIRECT_BUFFER_BINDING:
*params = mBoundBuffers[BufferBinding::DispatchIndirect].id();
break;
case GL_ALPHA_TEST_FUNC:
*params = ToGLenum(mGLES1State.mAlphaTestFunc);
break;
default:
UNREACHABLE();
break;
......
......@@ -474,6 +474,9 @@ class State : public angle::ObserverInterface, angle::NonCopyable
bool isCurrentTransformFeedback(const TransformFeedback *tf) const;
bool isCurrentVertexArray(const VertexArray *va) const;
GLES1State &gles1() { return mGLES1State; }
const GLES1State &gles1() const { return mGLES1State; }
private:
void syncProgramTextures(const Context *context);
......@@ -603,7 +606,6 @@ class State : public angle::ObserverInterface, angle::NonCopyable
bool mProgramBinaryCacheEnabled;
// GLES1 emulation: state specific to GLES1
friend class GLES1State;
GLES1State mGLES1State;
DirtyBits mDirtyBits;
......
......@@ -10,8 +10,8 @@
#include <vector>
#include "libANGLE/Context.h"
#include "common/utilities.h"
#include "libANGLE/Context.h"
namespace gl
{
......@@ -31,14 +31,22 @@ QueryT CastFromStateValueToInt(GLenum pname, NativeT value)
if (nativeType == GL_FLOAT)
{
// RGBA color values and DepthRangeF values are converted to integer using Equation 2.4 from Table 4.5
if (pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR)
{
return clampCast<QueryT>(ExpandFloatToInteger(static_cast<GLfloat>(value)));
}
else
// RGBA color values and DepthRangeF values are converted to integer using Equation 2.4 from
// Table 4.5
switch (pname)
{
return clampCast<QueryT>(std::round(value));
case GL_DEPTH_RANGE:
case GL_COLOR_CLEAR_VALUE:
case GL_DEPTH_CLEAR_VALUE:
case GL_BLEND_COLOR:
// GLES1 emulation:
// Also, several GLES1.x values need to be converted to integer with
// ExpandFloatToInteger rather than rounding. See GLES 1.1 spec 6.1.2 "Data
// Conversions".
case GL_ALPHA_TEST_REF:
return clampCast<QueryT>(ExpandFloatToInteger(static_cast<GLfloat>(value)));
default:
return clampCast<QueryT>(std::round(value));
}
}
......@@ -151,8 +159,11 @@ template GLuint CastQueryValueTo<GLuint, GLint>(GLenum pname, GLint value);
template GLuint CastQueryValueTo<GLuint, GLfloat>(GLenum pname, GLfloat value);
template <typename QueryT>
void CastStateValues(Context *context, GLenum nativeType, GLenum pname,
unsigned int numParams, QueryT *outParams)
void CastStateValues(Context *context,
GLenum nativeType,
GLenum pname,
unsigned int numParams,
QueryT *outParams)
{
if (nativeType == GL_INT)
{
......@@ -171,7 +182,8 @@ void CastStateValues(Context *context, GLenum nativeType, GLenum pname,
for (unsigned int i = 0; i < numParams; ++i)
{
outParams[i] = (boolParams[i] == GL_FALSE ? static_cast<QueryT>(0) : static_cast<QueryT>(1));
outParams[i] =
(boolParams[i] == GL_FALSE ? static_cast<QueryT>(0) : static_cast<QueryT>(1));
}
}
else if (nativeType == GL_FLOAT)
......@@ -194,7 +206,8 @@ void CastStateValues(Context *context, GLenum nativeType, GLenum pname,
outParams[i] = CastFromStateValue<QueryT>(pname, int64Params[i]);
}
}
else UNREACHABLE();
else
UNREACHABLE();
}
// Explicit template instantiation (how we export template functions in different files)
......
......@@ -9,20 +9,53 @@
#include "libANGLE/validationES1.h"
#include "common/debug.h"
#include "libANGLE/Context.h"
#include "libANGLE/ErrorStrings.h"
#define ANGLE_VALIDATE_IS_GLES1(context) \
if (context->getClientMajorVersion() > 1) \
{ \
ANGLE_VALIDATION_ERR(context, InvalidOperation(), GLES1Only); \
return false; \
}
namespace
{
bool ValidateAlphaFuncCommon(gl::Context *context, gl::AlphaTestFunc func)
{
switch (func)
{
case gl::AlphaTestFunc::AlwaysPass:
case gl::AlphaTestFunc::Equal:
case gl::AlphaTestFunc::Gequal:
case gl::AlphaTestFunc::Greater:
case gl::AlphaTestFunc::Lequal:
case gl::AlphaTestFunc::Less:
case gl::AlphaTestFunc::Never:
case gl::AlphaTestFunc::NotEqual:
return true;
default:
context->handleError(gl::InvalidEnum() << gl::kErrorEnumNotSupported);
return false;
}
}
} // anonymous namespace
namespace gl
{
bool ValidateAlphaFunc(Context *context, GLenum func, GLfloat ref)
bool ValidateAlphaFunc(Context *context, AlphaTestFunc func, GLfloat ref)
{
UNIMPLEMENTED();
return true;
ANGLE_VALIDATE_IS_GLES1(context);
return ValidateAlphaFuncCommon(context, func);
}
bool ValidateAlphaFuncx(Context *context, GLenum func, GLfixed ref)
bool ValidateAlphaFuncx(Context *context, AlphaTestFunc func, GLfixed ref)
{
UNIMPLEMENTED();
return true;
ANGLE_VALIDATE_IS_GLES1(context);
return ValidateAlphaFuncCommon(context, func);
}
bool ValidateClearColorx(Context *context, GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha)
......
......@@ -18,8 +18,8 @@ namespace gl
{
class Context;
bool ValidateAlphaFunc(Context *context, GLenum func, GLfloat ref);
bool ValidateAlphaFuncx(Context *context, GLenum func, GLfixed ref);
bool ValidateAlphaFunc(Context *context, AlphaTestFunc func, GLfloat ref);
bool ValidateAlphaFuncx(Context *context, AlphaTestFunc func, GLfixed ref);
bool ValidateClearColorx(Context *context, GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
bool ValidateClearDepthx(Context *context, GLfixed depth);
bool ValidateClientActiveTexture(Context *context, GLenum texture);
......
......@@ -792,6 +792,10 @@ bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
case GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
return queryOnly && context->getExtensions().robustResourceInitialization;
// GLES1 emulation: GLES1-specific caps
case GL_ALPHA_TEST:
return context->getClientVersion() < Version(2, 0);
default:
return false;
}
......
......@@ -23,11 +23,12 @@ void GL_APIENTRY AlphaFunc(GLenum func, GLfloat ref)
Context *context = GetValidGlobalContext();
if (context)
{
context->gatherParams<EntryPoint::AlphaFunc>(func, ref);
AlphaTestFunc funcPacked = FromGLenum<AlphaTestFunc>(func);
context->gatherParams<EntryPoint::AlphaFunc>(funcPacked, ref);
if (context->skipValidation() || ValidateAlphaFunc(context, func, ref))
if (context->skipValidation() || ValidateAlphaFunc(context, funcPacked, ref))
{
context->alphaFunc(func, ref);
context->alphaFunc(funcPacked, ref);
}
}
}
......@@ -39,11 +40,12 @@ void GL_APIENTRY AlphaFuncx(GLenum func, GLfixed ref)
Context *context = GetValidGlobalContext();
if (context)
{
context->gatherParams<EntryPoint::AlphaFuncx>(func, ref);
AlphaTestFunc funcPacked = FromGLenum<AlphaTestFunc>(func);
context->gatherParams<EntryPoint::AlphaFuncx>(funcPacked, ref);
if (context->skipValidation() || ValidateAlphaFuncx(context, func, ref))
if (context->skipValidation() || ValidateAlphaFuncx(context, funcPacked, ref))
{
context->alphaFuncx(func, ref);
context->alphaFuncx(funcPacked, ref);
}
}
}
......
......@@ -179,6 +179,7 @@ if (is_win || is_linux || is_mac || is_android) {
angle_root + ":angle_image_util",
angle_root + ":angle_util",
angle_root + ":libEGL${angle_libs_suffix}",
angle_root + ":libGLESv1_CM${angle_libs_suffix}",
angle_root + ":libGLESv2${angle_libs_suffix}",
angle_root + ":preprocessor",
angle_root + ":translator",
......
......@@ -47,6 +47,7 @@
'<(angle_path)/src/tests/gl_tests/FramebufferRenderMipmapTest.cpp',
'<(angle_path)/src/tests/gl_tests/FramebufferTest.cpp',
'<(angle_path)/src/tests/gl_tests/GeometryShaderTest.cpp',
'<(angle_path)/src/tests/gl_tests/gles1/AlphaFuncTest.cpp',
'<(angle_path)/src/tests/gl_tests/GLSLTest.cpp',
'<(angle_path)/src/tests/gl_tests/ImageTest.cpp',
'<(angle_path)/src/tests/gl_tests/IncompleteTextureTest.cpp',
......@@ -147,6 +148,7 @@
# This lets us filter test configs more intelligently.
'<(angle_path)/src/angle.gyp:libANGLE_renderer_config',
'<(angle_path)/src/angle.gyp:libEGL',
'<(angle_path)/src/angle.gyp:libGLESv1_CM',
'<(angle_path)/src/angle.gyp:libGLESv2',
'<(angle_path)/src/tests/tests.gyp:angle_test_support',
'<(angle_path)/util/util.gyp:angle_util',
......
//
// Copyright 2018 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.
//
// AlphaFuncTest.cpp: Tests basic usage of glAlphaFunc.
#include "test_utils/ANGLETest.h"
#include "test_utils/gl_raii.h"
#include "random_utils.h"
#include <stdint.h>
using namespace angle;
class AlphaFuncTest : public ANGLETest
{
protected:
AlphaFuncTest()
{
setWindowWidth(32);
setWindowHeight(32);
setConfigRedBits(8);
setConfigGreenBits(8);
setConfigBlueBits(8);
setConfigAlphaBits(8);
setConfigDepthBits(24);
}
};
// Checks that disable / enable works as expected.
TEST_P(AlphaFuncTest, EnableDisable)
{
EXPECT_GL_FALSE(glIsEnabled(GL_ALPHA_TEST));
EXPECT_GL_NO_ERROR();
glEnable(GL_ALPHA_TEST);
EXPECT_GL_NO_ERROR();
EXPECT_GL_TRUE(glIsEnabled(GL_ALPHA_TEST));
EXPECT_GL_NO_ERROR();
glDisable(GL_ALPHA_TEST);
EXPECT_GL_NO_ERROR();
EXPECT_GL_FALSE(glIsEnabled(GL_ALPHA_TEST));
EXPECT_GL_NO_ERROR();
}
// Negative test: Checks that invalid enums for alpha test function generate the proper GL error.
TEST_P(AlphaFuncTest, SetFuncNegative)
{
glAlphaFunc((GLenum)0, 0.0f);
EXPECT_GL_ERROR(GL_INVALID_ENUM);
glAlphaFunc((GLenum)1, 0.0f);
EXPECT_GL_ERROR(GL_INVALID_ENUM);
glAlphaFunc((GLenum)GL_ALPHA, 0.0f);
EXPECT_GL_ERROR(GL_INVALID_ENUM);
}
// Query test: Checks that the alpha test ref value can be obtained with glGetFloatv.
TEST_P(AlphaFuncTest, SetFuncGetFloat)
{
GLfloat alphaTestVal = -1.0f;
glAlphaFunc(GL_ALWAYS, 0.0f);
glGetFloatv(GL_ALPHA_TEST_REF, &alphaTestVal);
EXPECT_GL_NO_ERROR();
EXPECT_EQ(0.0f, alphaTestVal);
glAlphaFunc(GL_ALWAYS, 0.4f);
glGetFloatv(GL_ALPHA_TEST_REF, &alphaTestVal);
EXPECT_GL_NO_ERROR();
EXPECT_EQ(0.4f, alphaTestVal);
}
// Query test: Checks that the alpha test ref value can be obtained with glGetIntegerv,
// with proper scaling.
TEST_P(AlphaFuncTest, SetFuncGetInt)
{
GLint alphaTestVal = -1;
glAlphaFunc(GL_ALWAYS, 0.0f);
glGetIntegerv(GL_ALPHA_TEST_REF, &alphaTestVal);
EXPECT_GL_NO_ERROR();
EXPECT_EQ(0, alphaTestVal);
glAlphaFunc(GL_ALWAYS, 1.0f);
glGetIntegerv(GL_ALPHA_TEST_REF, &alphaTestVal);
EXPECT_GL_NO_ERROR();
EXPECT_EQ(std::numeric_limits<GLint>::max(), alphaTestVal);
}
ANGLE_INSTANTIATE_TEST(AlphaFuncTest, ES1_D3D11(), ES1_OPENGL(), ES1_OPENGLES());
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