Commit 81c6b577 by Geoff Lang Committed by Commit Bot

Implement GL_EXT_texture_sRGB_decode for GL.

BUG=angleproject:1383 BUG=655247 Change-Id: I409b12e1ae418530576de5ec9ce26b7be5d91650 Reviewed-on: https://chromium-review.googlesource.com/400807Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Geoff Lang <geofflang@chromium.org>
parent de318b26
...@@ -170,6 +170,7 @@ Extensions::Extensions() ...@@ -170,6 +170,7 @@ Extensions::Extensions()
webglCompatibility(false), webglCompatibility(false),
bindGeneratesResource(false), bindGeneratesResource(false),
robustClientMemory(false), robustClientMemory(false),
textureSRGBDecode(false),
colorBufferFloat(false), colorBufferFloat(false),
multisampleCompatibility(false), multisampleCompatibility(false),
framebufferMixedSamples(false), framebufferMixedSamples(false),
...@@ -585,6 +586,7 @@ const ExtensionInfoMap &GetExtensionInfoMap() ...@@ -585,6 +586,7 @@ const ExtensionInfoMap &GetExtensionInfoMap()
map["GL_ANGLE_webgl_compatibility"] = esOnlyExtension(&Extensions::webglCompatibility); map["GL_ANGLE_webgl_compatibility"] = esOnlyExtension(&Extensions::webglCompatibility);
map["GL_CHROMIUM_bind_generates_resource"] = esOnlyExtension(&Extensions::bindGeneratesResource); map["GL_CHROMIUM_bind_generates_resource"] = esOnlyExtension(&Extensions::bindGeneratesResource);
map["GL_ANGLE_robust_client_memory"] = esOnlyExtension(&Extensions::robustClientMemory); map["GL_ANGLE_robust_client_memory"] = esOnlyExtension(&Extensions::robustClientMemory);
map["GL_EXT_texture_sRGB_decode"] = esOnlyExtension(&Extensions::textureSRGBDecode);
map["GL_EXT_multisample_compatibility"] = esOnlyExtension(&Extensions::multisampleCompatibility); map["GL_EXT_multisample_compatibility"] = esOnlyExtension(&Extensions::multisampleCompatibility);
map["GL_CHROMIUM_framebuffer_mixed_samples"] = esOnlyExtension(&Extensions::framebufferMixedSamples); map["GL_CHROMIUM_framebuffer_mixed_samples"] = esOnlyExtension(&Extensions::framebufferMixedSamples);
map["GL_EXT_texture_norm16"] = esOnlyExtension(&Extensions::textureNorm16); map["GL_EXT_texture_norm16"] = esOnlyExtension(&Extensions::textureNorm16);
......
...@@ -305,6 +305,9 @@ struct Extensions ...@@ -305,6 +305,9 @@ struct Extensions
// GL_ANGLE_robust_client_memory // GL_ANGLE_robust_client_memory
bool robustClientMemory; bool robustClientMemory;
// GL_EXT_texture_sRGB_decode
bool textureSRGBDecode;
// ES3 Extension support // ES3 Extension support
// GL_EXT_color_buffer_float // GL_EXT_color_buffer_float
......
...@@ -135,6 +135,16 @@ GLenum Sampler::getCompareFunc() const ...@@ -135,6 +135,16 @@ GLenum Sampler::getCompareFunc() const
return mSamplerState.compareFunc; return mSamplerState.compareFunc;
} }
void Sampler::setSRGBDecode(GLenum sRGBDecode)
{
mSamplerState.sRGBDecode = sRGBDecode;
}
GLenum Sampler::getSRGBDecode() const
{
return mSamplerState.sRGBDecode;
}
const SamplerState &Sampler::getSamplerState() const const SamplerState &Sampler::getSamplerState() const
{ {
return mSamplerState; return mSamplerState;
......
...@@ -62,6 +62,9 @@ class Sampler final : public RefCountObject, public LabeledObject ...@@ -62,6 +62,9 @@ class Sampler final : public RefCountObject, public LabeledObject
void setCompareFunc(GLenum compareFunc); void setCompareFunc(GLenum compareFunc);
GLenum getCompareFunc() const; GLenum getCompareFunc() const;
void setSRGBDecode(GLenum sRGBDecode);
GLenum getSRGBDecode() const;
const SamplerState &getSamplerState() const; const SamplerState &getSamplerState() const;
rx::SamplerImpl *getImplementation() const; rx::SamplerImpl *getImplementation() const;
......
...@@ -683,6 +683,17 @@ GLenum Texture::getCompareFunc() const ...@@ -683,6 +683,17 @@ GLenum Texture::getCompareFunc() const
return mState.mSamplerState.compareFunc; return mState.mSamplerState.compareFunc;
} }
void Texture::setSRGBDecode(GLenum sRGBDecode)
{
mState.mSamplerState.sRGBDecode = sRGBDecode;
mDirtyBits.set(DIRTY_BIT_SRGB_DECODE);
}
GLenum Texture::getSRGBDecode() const
{
return mState.mSamplerState.sRGBDecode;
}
const SamplerState &Texture::getSamplerState() const const SamplerState &Texture::getSamplerState() const
{ {
return mState.mSamplerState; return mState.mSamplerState;
......
...@@ -217,6 +217,9 @@ class Texture final : public egl::ImageSibling, ...@@ -217,6 +217,9 @@ class Texture final : public egl::ImageSibling,
void setCompareFunc(GLenum compareFunc); void setCompareFunc(GLenum compareFunc);
GLenum getCompareFunc() const; GLenum getCompareFunc() const;
void setSRGBDecode(GLenum sRGBDecode);
GLenum getSRGBDecode() const;
const SamplerState &getSamplerState() const; const SamplerState &getSamplerState() const;
void setBaseLevel(GLuint baseLevel); void setBaseLevel(GLuint baseLevel);
...@@ -330,6 +333,7 @@ class Texture final : public egl::ImageSibling, ...@@ -330,6 +333,7 @@ class Texture final : public egl::ImageSibling,
DIRTY_BIT_MAX_LOD, DIRTY_BIT_MAX_LOD,
DIRTY_BIT_COMPARE_MODE, DIRTY_BIT_COMPARE_MODE,
DIRTY_BIT_COMPARE_FUNC, DIRTY_BIT_COMPARE_FUNC,
DIRTY_BIT_SRGB_DECODE,
// Texture state // Texture state
DIRTY_BIT_SWIZZLE_RED, DIRTY_BIT_SWIZZLE_RED,
......
...@@ -49,7 +49,8 @@ SamplerState::SamplerState() ...@@ -49,7 +49,8 @@ SamplerState::SamplerState()
minLod(-1000.0f), minLod(-1000.0f),
maxLod(1000.0f), maxLod(1000.0f),
compareMode(GL_NONE), compareMode(GL_NONE),
compareFunc(GL_LEQUAL) compareFunc(GL_LEQUAL),
sRGBDecode(GL_DECODE_EXT)
{ {
} }
......
...@@ -192,6 +192,8 @@ struct SamplerState ...@@ -192,6 +192,8 @@ struct SamplerState
GLenum compareMode; GLenum compareMode;
GLenum compareFunc; GLenum compareFunc;
GLenum sRGBDecode;
}; };
bool operator==(const SamplerState &a, const SamplerState &b); bool operator==(const SamplerState &a, const SamplerState &b);
......
...@@ -89,6 +89,9 @@ void QueryTexParameterBase(const Texture *texture, GLenum pname, ParamType *para ...@@ -89,6 +89,9 @@ void QueryTexParameterBase(const Texture *texture, GLenum pname, ParamType *para
case GL_TEXTURE_COMPARE_FUNC: case GL_TEXTURE_COMPARE_FUNC:
*params = ConvertFromGLenum<ParamType>(texture->getCompareFunc()); *params = ConvertFromGLenum<ParamType>(texture->getCompareFunc());
break; break;
case GL_TEXTURE_SRGB_DECODE_EXT:
*params = ConvertFromGLenum<ParamType>(texture->getSRGBDecode());
break;
default: default:
UNREACHABLE(); UNREACHABLE();
break; break;
...@@ -153,6 +156,9 @@ void SetTexParameterBase(Texture *texture, GLenum pname, const ParamType *params ...@@ -153,6 +156,9 @@ void SetTexParameterBase(Texture *texture, GLenum pname, const ParamType *params
case GL_TEXTURE_MAX_LOD: case GL_TEXTURE_MAX_LOD:
texture->setMaxLod(ConvertToGLfloat(params[0])); texture->setMaxLod(ConvertToGLfloat(params[0]));
break; break;
case GL_TEXTURE_SRGB_DECODE_EXT:
texture->setSRGBDecode(ConvertToGLenum(params[0]));
break;
default: default:
UNREACHABLE(); UNREACHABLE();
break; break;
...@@ -194,6 +200,9 @@ void QuerySamplerParameterBase(const Sampler *sampler, GLenum pname, ParamType * ...@@ -194,6 +200,9 @@ void QuerySamplerParameterBase(const Sampler *sampler, GLenum pname, ParamType *
case GL_TEXTURE_COMPARE_FUNC: case GL_TEXTURE_COMPARE_FUNC:
*params = ConvertFromGLenum<ParamType>(sampler->getCompareFunc()); *params = ConvertFromGLenum<ParamType>(sampler->getCompareFunc());
break; break;
case GL_TEXTURE_SRGB_DECODE_EXT:
*params = ConvertFromGLenum<ParamType>(sampler->getSRGBDecode());
break;
default: default:
UNREACHABLE(); UNREACHABLE();
break; break;
...@@ -235,6 +244,9 @@ void SetSamplerParameterBase(Sampler *sampler, GLenum pname, const ParamType *pa ...@@ -235,6 +244,9 @@ void SetSamplerParameterBase(Sampler *sampler, GLenum pname, const ParamType *pa
case GL_TEXTURE_MAX_LOD: case GL_TEXTURE_MAX_LOD:
sampler->setMaxLod(ConvertToGLfloat(params[0])); sampler->setMaxLod(ConvertToGLfloat(params[0]));
break; break;
case GL_TEXTURE_SRGB_DECODE_EXT:
sampler->setSRGBDecode(ConvertToGLenum(params[0]));
break;
default: default:
UNREACHABLE(); UNREACHABLE();
break; break;
......
...@@ -62,6 +62,7 @@ void SamplerGL::syncState(const gl::SamplerState &samplerState) const ...@@ -62,6 +62,7 @@ void SamplerGL::syncState(const gl::SamplerState &samplerState) const
SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_MAX_LOD, &gl::SamplerState::maxLod); SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_MAX_LOD, &gl::SamplerState::maxLod);
SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_COMPARE_MODE, &gl::SamplerState::compareMode); SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_COMPARE_MODE, &gl::SamplerState::compareMode);
SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_COMPARE_FUNC, &gl::SamplerState::compareFunc); SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_COMPARE_FUNC, &gl::SamplerState::compareFunc);
SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_SRGB_DECODE_EXT, &gl::SamplerState::sRGBDecode);
// clang-format on // clang-format on
} }
......
...@@ -858,6 +858,10 @@ void TextureGL::syncState(const gl::Texture::DirtyBits &dirtyBits) ...@@ -858,6 +858,10 @@ void TextureGL::syncState(const gl::Texture::DirtyBits &dirtyBits)
mFunctions->texParameteri(mState.mTarget, GL_TEXTURE_COMPARE_FUNC, mFunctions->texParameteri(mState.mTarget, GL_TEXTURE_COMPARE_FUNC,
mState.getSamplerState().compareFunc); mState.getSamplerState().compareFunc);
break; break;
case gl::Texture::DIRTY_BIT_SRGB_DECODE:
mFunctions->texParameteri(mState.mTarget, GL_TEXTURE_SRGB_DECODE_EXT,
mState.getSamplerState().sRGBDecode);
break;
// Texture state // Texture state
case gl::Texture::DIRTY_BIT_SWIZZLE_RED: case gl::Texture::DIRTY_BIT_SWIZZLE_RED:
......
...@@ -871,6 +871,20 @@ void GenerateCaps(const FunctionsGL *functions, gl::Caps *caps, gl::TextureCapsM ...@@ -871,6 +871,20 @@ void GenerateCaps(const FunctionsGL *functions, gl::Caps *caps, gl::TextureCapsM
functions->isAtLeastGLES(gl::Version(3, 1)); functions->isAtLeastGLES(gl::Version(3, 1));
extensions->pathRendering = canEnableGLPathRendering || canEnableESPathRendering; extensions->pathRendering = canEnableGLPathRendering || canEnableESPathRendering;
extensions->textureSRGBDecode = functions->hasGLExtension("GL_EXT_texture_sRGB_decode") ||
functions->hasGLESExtension("GL_EXT_texture_sRGB_decode");
#if defined(ANGLE_PLATFORM_APPLE)
VendorID vendor = GetVendorID(functions);
if ((vendor == VENDOR_ID_AMD || vendor == VENDOR_ID_INTEL) &&
*maxSupportedESVersion >= gl::Version(3, 0))
{
// Apple Intel/AMD drivers do not correctly use the TEXTURE_SRGB_DECODE property of sampler
// states. Disable this extension when we would advertise any ES version that has samplers.
extensions->textureSRGBDecode = false;
}
#endif
} }
void GenerateWorkarounds(const FunctionsGL *functions, WorkaroundsGL *workarounds) void GenerateWorkarounds(const FunctionsGL *functions, WorkaroundsGL *workarounds)
......
...@@ -471,6 +471,15 @@ bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, ...@@ -471,6 +471,15 @@ bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname,
} }
break; break;
case GL_TEXTURE_SRGB_DECODE_EXT:
if (!context->getExtensions().textureSRGBDecode)
{
context->handleError(
Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
return false;
}
break;
default: default:
context->handleError(Error(GL_INVALID_ENUM, "Unknown pname.")); context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
return false; return false;
...@@ -603,6 +612,29 @@ bool ValidateTextureCompareFuncValue(Context *context, ParamType *params) ...@@ -603,6 +612,29 @@ bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
} }
template <typename ParamType> template <typename ParamType>
bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
{
if (!context->getExtensions().textureSRGBDecode)
{
context->handleError(Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
return false;
}
switch (ConvertToGLenum(params[0]))
{
case GL_DECODE_EXT:
case GL_SKIP_DECODE_EXT:
break;
default:
context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
return false;
}
return true;
}
template <typename ParamType>
bool ValidateTexParameterBase(Context *context, bool ValidateTexParameterBase(Context *context,
GLenum target, GLenum target,
GLenum pname, GLenum pname,
...@@ -777,6 +809,13 @@ bool ValidateTexParameterBase(Context *context, ...@@ -777,6 +809,13 @@ bool ValidateTexParameterBase(Context *context,
} }
break; break;
case GL_TEXTURE_SRGB_DECODE_EXT:
if (!ValidateTextureSRGBDecodeValue(context, params))
{
return false;
}
break;
default: default:
context->handleError(Error(GL_INVALID_ENUM, "Unknown pname.")); context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
return false; return false;
...@@ -857,6 +896,13 @@ bool ValidateSamplerParameterBase(Context *context, ...@@ -857,6 +896,13 @@ bool ValidateSamplerParameterBase(Context *context,
} }
break; break;
case GL_TEXTURE_SRGB_DECODE_EXT:
if (!ValidateTextureSRGBDecodeValue(context, params))
{
return false;
}
break;
default: default:
context->handleError(Error(GL_INVALID_ENUM, "Unknown pname.")); context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
return false; return false;
...@@ -901,6 +947,15 @@ bool ValidateGetSamplerParameterBase(Context *context, ...@@ -901,6 +947,15 @@ bool ValidateGetSamplerParameterBase(Context *context,
case GL_TEXTURE_COMPARE_FUNC: case GL_TEXTURE_COMPARE_FUNC:
break; break;
case GL_TEXTURE_SRGB_DECODE_EXT:
if (!context->getExtensions().textureSRGBDecode)
{
context->handleError(
Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
return false;
}
break;
default: default:
context->handleError(Error(GL_INVALID_ENUM, "Unknown pname.")); context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
return false; return false;
......
...@@ -5,10 +5,9 @@ ...@@ -5,10 +5,9 @@
// //
#include "test_utils/ANGLETest.h" #include "test_utils/ANGLETest.h"
#include "test_utils/gl_raii.h"
using namespace angle; namespace angle
namespace
{ {
class SRGBTextureTest : public ANGLETest class SRGBTextureTest : public ANGLETest
...@@ -27,12 +26,44 @@ class SRGBTextureTest : public ANGLETest ...@@ -27,12 +26,44 @@ class SRGBTextureTest : public ANGLETest
void SetUp() override void SetUp() override
{ {
ANGLETest::SetUp(); ANGLETest::SetUp();
const std::string vs =
"precision highp float;\n"
"attribute vec4 position;\n"
"varying vec2 texcoord;\n"
"\n"
"void main()\n"
"{\n"
" gl_Position = vec4(position.xy, 0.0, 1.0);\n"
" texcoord = (position.xy * 0.5) + 0.5;\n"
"}\n";
const std::string fs =
"precision highp float;\n"
"uniform sampler2D tex;\n"
"varying vec2 texcoord;\n"
"\n"
"void main()\n"
"{\n"
" gl_FragColor = texture2D(tex, texcoord);\n"
"}\n";
mProgram = CompileProgram(vs, fs);
ASSERT_NE(0u, mProgram);
mTextureLocation = glGetUniformLocation(mProgram, "tex");
ASSERT_NE(-1, mTextureLocation);
} }
void TearDown() override void TearDown() override
{ {
glDeleteProgram(mProgram);
ANGLETest::TearDown(); ANGLETest::TearDown();
} }
GLuint mProgram = 0;
GLint mTextureLocation = -1;
}; };
TEST_P(SRGBTextureTest, SRGBValidation) TEST_P(SRGBTextureTest, SRGBValidation)
...@@ -143,12 +174,95 @@ TEST_P(SRGBTextureTest, SRGBARenderbuffer) ...@@ -143,12 +174,95 @@ TEST_P(SRGBTextureTest, SRGBARenderbuffer)
glDeleteRenderbuffers(1, &rbo); glDeleteRenderbuffers(1, &rbo);
} }
// Verify that if the srgb decode extension is available, srgb textures are too
TEST_P(SRGBTextureTest, SRGBDecodeExtensionAvailability)
{
bool hasSRGBDecode = extensionEnabled("GL_EXT_texture_sRGB_decode");
if (hasSRGBDecode)
{
bool hasSRGBTextures = extensionEnabled("GL_EXT_sRGB") || getClientMajorVersion() >= 3;
EXPECT_TRUE(hasSRGBTextures);
}
}
// Test basic functionality of SRGB decode using the texture parameter
TEST_P(SRGBTextureTest, SRGBDecodeTextureParameter)
{
if (!extensionEnabled("GL_EXT_texture_sRGB_decode"))
{
std::cout << "Test skipped because GL_EXT_texture_sRGB_decode is not available."
<< std::endl;
return;
}
GLColor linearColor(64, 127, 191, 255);
GLColor srgbColor(13, 54, 133, 255);
GLTexture tex;
glBindTexture(GL_TEXTURE_2D, tex.get());
glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB_ALPHA_EXT, 1, 1, 0, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE,
&linearColor);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT);
ASSERT_GL_NO_ERROR();
glUseProgram(mProgram);
glUniform1i(mTextureLocation, 0);
glDisable(GL_DEPTH_TEST);
drawQuad(mProgram, "position", 0.5f);
EXPECT_PIXEL_COLOR_NEAR(0, 0, srgbColor, 1.0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
drawQuad(mProgram, "position", 0.5f);
EXPECT_PIXEL_COLOR_NEAR(0, 0, linearColor, 1.0);
}
// Test basic functionality of SRGB decode using the sampler parameter
TEST_P(SRGBTextureTest, SRGBDecodeSamplerParameter)
{
if (!extensionEnabled("GL_EXT_texture_sRGB_decode") || getClientMajorVersion() < 3)
{
std::cout << "Test skipped because GL_EXT_texture_sRGB_decode or ES3 is not available."
<< std::endl;
return;
}
GLColor linearColor(64, 127, 191, 255);
GLColor srgbColor(13, 54, 133, 255);
GLTexture tex;
glBindTexture(GL_TEXTURE_2D, tex.get());
glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB_ALPHA_EXT, 1, 1, 0, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE,
&linearColor);
ASSERT_GL_NO_ERROR();
GLSampler sampler;
glBindSampler(0, sampler.get());
glSamplerParameteri(sampler.get(), GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT);
glUseProgram(mProgram);
glUniform1i(mTextureLocation, 0);
glDisable(GL_DEPTH_TEST);
drawQuad(mProgram, "position", 0.5f);
EXPECT_PIXEL_COLOR_NEAR(0, 0, srgbColor, 1.0);
glSamplerParameteri(sampler.get(), GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
drawQuad(mProgram, "position", 0.5f);
EXPECT_PIXEL_COLOR_NEAR(0, 0, linearColor, 1.0);
}
// 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(SRGBTextureTest, ANGLE_INSTANTIATE_TEST(SRGBTextureTest,
ES2_D3D9(), ES2_D3D9(),
ES2_D3D11(), ES2_D3D11(),
ES3_D3D11(), ES3_D3D11(),
ES2_OPENGL(), ES2_OPENGL(),
ES2_OPENGLES()); ES3_OPENGL(),
ES2_OPENGLES(),
ES3_OPENGLES());
} // namespace } // namespace
...@@ -46,6 +46,7 @@ using GLBuffer = GLWrapper<glGenBuffers, glDeleteBuffers>; ...@@ -46,6 +46,7 @@ using GLBuffer = GLWrapper<glGenBuffers, glDeleteBuffers>;
using GLTexture = GLWrapper<glGenTextures, glDeleteTextures>; using GLTexture = GLWrapper<glGenTextures, glDeleteTextures>;
using GLFramebuffer = GLWrapper<glGenFramebuffers, glDeleteFramebuffers>; using GLFramebuffer = GLWrapper<glGenFramebuffers, glDeleteFramebuffers>;
using GLRenderbuffer = GLWrapper<glGenRenderbuffers, glDeleteRenderbuffers>; using GLRenderbuffer = GLWrapper<glGenRenderbuffers, glDeleteRenderbuffers>;
using GLSampler = GLWrapper<glGenSamplers, glDeleteSamplers>;
class GLProgram class GLProgram
{ {
......
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