Commit a4903b70 by Geoff Lang

Support multisampled framebuffers with the GL backend.

Move validation of sample counts into the Renderbuffer implementations because the exact supported sample counts are not always known. BUG=angleoproject:886 Change-Id: I9c90d9d435e940b852343a29a6aa11d6cb1ad23b Reviewed-on: https://chromium-review.googlesource.com/255513Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Tested-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 02bce6e5
...@@ -33,6 +33,7 @@ struct TextureCaps ...@@ -33,6 +33,7 @@ struct TextureCaps
// Support for being used as a framebuffer attachment or renderbuffer format // Support for being used as a framebuffer attachment or renderbuffer format
bool renderable; bool renderable;
// Set of supported sample counts, only guaranteed to be valid in ES3.
SupportedSampleSet sampleCounts; SupportedSampleSet sampleCounts;
// Get the maximum number of samples supported // Get the maximum number of samples supported
......
...@@ -1548,7 +1548,6 @@ void Context::initCaps(GLuint clientVersion) ...@@ -1548,7 +1548,6 @@ void Context::initCaps(GLuint clientVersion)
mCaps.maxFragmentInputComponents = std::min<GLuint>(mCaps.maxFragmentInputComponents, IMPLEMENTATION_MAX_VARYING_VECTORS * 4); mCaps.maxFragmentInputComponents = std::min<GLuint>(mCaps.maxFragmentInputComponents, IMPLEMENTATION_MAX_VARYING_VECTORS * 4);
GLuint maxSamples = 0;
mCaps.compressedTextureFormats.clear(); mCaps.compressedTextureFormats.clear();
const TextureCapsMap &rendererFormats = mRenderer->getRendererTextureCaps(); const TextureCapsMap &rendererFormats = mRenderer->getRendererTextureCaps();
...@@ -1569,7 +1568,6 @@ void Context::initCaps(GLuint clientVersion) ...@@ -1569,7 +1568,6 @@ void Context::initCaps(GLuint clientVersion)
{ {
formatCaps.sampleCounts.clear(); formatCaps.sampleCounts.clear();
} }
maxSamples = std::max(maxSamples, formatCaps.getMaxSamples());
if (formatCaps.texturable && formatInfo.compressed) if (formatCaps.texturable && formatInfo.compressed)
{ {
...@@ -1578,8 +1576,6 @@ void Context::initCaps(GLuint clientVersion) ...@@ -1578,8 +1576,6 @@ void Context::initCaps(GLuint clientVersion)
mTextureCaps.insert(format, formatCaps); mTextureCaps.insert(format, formatCaps);
} }
mCaps.maxSamples = maxSamples;
} }
Data Context::getData() const Data Context::getData() const
......
...@@ -41,6 +41,17 @@ gl::Error RenderbufferD3D::setStorageMultisample(size_t samples, GLenum internal ...@@ -41,6 +41,17 @@ gl::Error RenderbufferD3D::setStorageMultisample(size_t samples, GLenum internal
creationFormat = GL_DEPTH24_STENCIL8_OES; creationFormat = GL_DEPTH24_STENCIL8_OES;
} }
// ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
// the specified storage.
// Because ES 3.0 already knows the exact number of supported samples, it would already have been
// validated and generated GL_INVALID_VALUE.
const gl::TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(creationFormat);
if (samples > formatCaps.getMaxSamples())
{
return gl::Error(GL_OUT_OF_MEMORY, "Renderbuffer format does not support %u samples, %u is the maximum.",
samples, formatCaps.getMaxSamples());
}
RenderTargetD3D *newRT = NULL; RenderTargetD3D *newRT = NULL;
gl::Error error = mRenderer->createRenderTarget(width, height, creationFormat, samples, &newRT); gl::Error error = mRenderer->createRenderTarget(width, height, creationFormat, samples, &newRT);
if (error.isError()) if (error.isError())
......
...@@ -7,18 +7,89 @@ ...@@ -7,18 +7,89 @@
// FunctionsGL.cpp: Implements the FuntionsGL class to contain loaded GL functions // FunctionsGL.cpp: Implements the FuntionsGL class to contain loaded GL functions
#include "libANGLE/renderer/gl/FunctionsGL.h" #include "libANGLE/renderer/gl/FunctionsGL.h"
#include "libANGLE/renderer/gl/renderergl_utils.h"
namespace rx namespace rx
{ {
static void GetGLVersion(PFNGLGETSTRINGPROC getStringFunction, GLuint *outMajorVersion, GLuint *outMinorVersion,
bool *outIsES)
{
const std::string version = reinterpret_cast<const char*>(getStringFunction(GL_VERSION));
if (version.find("OpenGL ES") == std::string::npos)
{
// ES spec states that the GL_VERSION string will be in the following format:
// "OpenGL ES N.M vendor-specific information"
*outIsES = false;
*outMajorVersion = version[0] - '0';
*outMinorVersion = version[2] - '0';
}
else
{
// OpenGL spec states the GL_VERSION string will be in the following format:
// <version number><space><vendor-specific information>
// The version number is either of the form major number.minor number or major
// number.minor number.release number, where the numbers all have one or more
// digits
*outIsES = true;
*outMajorVersion = version[10] - '0';
*outMinorVersion = version[12] - '0';
}
}
static std::vector<std::string> GetNonIndexedExtensions(PFNGLGETSTRINGPROC getStringFunction)
{
std::vector<std::string> result;
std::istringstream stream(reinterpret_cast<const char*>(getStringFunction(GL_EXTENSIONS)));
std::string extension;
while (std::getline(stream, extension, ' '))
{
result.push_back(extension);
}
return result;
}
static std::vector<std::string> GetIndexedExtensions(PFNGLGETINTEGERVPROC getIntegerFunction, PFNGLGETSTRINGIPROC getStringIFunction)
{
std::vector<std::string> result;
GLint numExtensions;
getIntegerFunction(GL_NUM_EXTENSIONS, &numExtensions);
result.reserve(numExtensions);
for (GLint i = 0; i < numExtensions; i++)
{
result.push_back(reinterpret_cast<const char*>(getStringIFunction(GL_EXTENSIONS, i)));
}
return result;
}
template <typename T> template <typename T>
static void AssignGLEntryPoint(void *function, T *outFunction) static void AssignGLEntryPoint(void *function, T *outFunction)
{ {
*outFunction = reinterpret_cast<T>(function); *outFunction = reinterpret_cast<T>(function);
} }
template <typename T>
static void AssignGLExtensionEntryPoint(const std::vector<std::string> &extensions, const std::string &extension, void *function, T *outFunction)
{
if (std::find(extensions.begin(), extensions.end(), extension) != extensions.end())
{
*outFunction = reinterpret_cast<T>(function);
}
}
FunctionsGL::FunctionsGL() FunctionsGL::FunctionsGL()
: blendFunc(nullptr), : majorVersion(0),
minorVersion(0),
openGLES(false),
extensions(),
blendFunc(nullptr),
clear(nullptr), clear(nullptr),
clearColor(nullptr), clearColor(nullptr),
clearDepth(nullptr), clearDepth(nullptr),
...@@ -694,8 +765,24 @@ FunctionsGL::~FunctionsGL() ...@@ -694,8 +765,24 @@ FunctionsGL::~FunctionsGL()
{ {
} }
void FunctionsGL::initialize(GLuint majorVersion, GLuint minorVersion) void FunctionsGL::initialize()
{ {
// Grab the version number
AssignGLEntryPoint(loadProcAddress("glGetString"), &getString);
GetGLVersion(getString, &majorVersion, &minorVersion, &openGLES);
// Grab the GL extensions
if (majorVersion > 3 || majorVersion == 3 && minorVersion >= 0)
{
AssignGLEntryPoint(loadProcAddress("glGetIntegerv"), &getIntegerv);
AssignGLEntryPoint(loadProcAddress("glGetStringi"), &getStringi);
extensions = GetIndexedExtensions(getIntegerv, getStringi);
}
else
{
extensions = GetNonIndexedExtensions(getString);
}
// 1.0 // 1.0
if (majorVersion > 1 || majorVersion == 1 && minorVersion >= 0) if (majorVersion > 1 || majorVersion == 1 && minorVersion >= 0)
{ {
...@@ -1024,6 +1111,9 @@ void FunctionsGL::initialize(GLuint majorVersion, GLuint minorVersion) ...@@ -1024,6 +1111,9 @@ void FunctionsGL::initialize(GLuint majorVersion, GLuint minorVersion)
AssignGLEntryPoint(loadProcAddress("glVertexAttribI4uiv"), &vertexAttribI4uiv); AssignGLEntryPoint(loadProcAddress("glVertexAttribI4uiv"), &vertexAttribI4uiv);
AssignGLEntryPoint(loadProcAddress("glVertexAttribI4usv"), &vertexAttribI4usv); AssignGLEntryPoint(loadProcAddress("glVertexAttribI4usv"), &vertexAttribI4usv);
AssignGLEntryPoint(loadProcAddress("glVertexAttribIPointer"), &vertexAttribIPointer); AssignGLEntryPoint(loadProcAddress("glVertexAttribIPointer"), &vertexAttribIPointer);
// Extensions
AssignGLExtensionEntryPoint(extensions, "GL_ARB_internalformat_query", loadProcAddress("glGetInternalformativ"), &getInternalformativ);
} }
// 3.1 // 3.1
......
...@@ -22,8 +22,17 @@ class FunctionsGL ...@@ -22,8 +22,17 @@ class FunctionsGL
FunctionsGL(); FunctionsGL();
virtual ~FunctionsGL(); virtual ~FunctionsGL();
void initialize(GLuint majorVersion, GLuint minorVersion); void initialize();
// Version information
GLuint majorVersion;
GLuint minorVersion;
bool openGLES;
// Extensions
std::vector<std::string> extensions;
// Entry Points
// 1.0 // 1.0
PFNGLBLENDFUNCPROC blendFunc; PFNGLBLENDFUNCPROC blendFunc;
PFNGLCLEARPROC clear; PFNGLCLEARPROC clear;
......
...@@ -9,17 +9,20 @@ ...@@ -9,17 +9,20 @@
#include "libANGLE/renderer/gl/RenderbufferGL.h" #include "libANGLE/renderer/gl/RenderbufferGL.h"
#include "common/debug.h" #include "common/debug.h"
#include "libANGLE/Caps.h"
#include "libANGLE/angletypes.h" #include "libANGLE/angletypes.h"
#include "libANGLE/renderer/gl/FunctionsGL.h" #include "libANGLE/renderer/gl/FunctionsGL.h"
#include "libANGLE/renderer/gl/StateManagerGL.h" #include "libANGLE/renderer/gl/StateManagerGL.h"
#include "libANGLE/renderer/gl/renderergl_utils.h"
namespace rx namespace rx
{ {
RenderbufferGL::RenderbufferGL(const FunctionsGL *functions, StateManagerGL *stateManager) RenderbufferGL::RenderbufferGL(const FunctionsGL *functions, StateManagerGL *stateManager, const gl::TextureCapsMap &textureCaps)
: RenderbufferImpl(), : RenderbufferImpl(),
mFunctions(functions), mFunctions(functions),
mStateManager(stateManager), mStateManager(stateManager),
mTextureCaps(textureCaps),
mRenderbufferID(0) mRenderbufferID(0)
{ {
mFunctions->genRenderbuffers(1, &mRenderbufferID); mFunctions->genRenderbuffers(1, &mRenderbufferID);
...@@ -45,6 +48,25 @@ gl::Error RenderbufferGL::setStorageMultisample(size_t samples, GLenum internalf ...@@ -45,6 +48,25 @@ gl::Error RenderbufferGL::setStorageMultisample(size_t samples, GLenum internalf
{ {
mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mRenderbufferID); mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mRenderbufferID);
mFunctions->renderbufferStorageMultisample(GL_RENDERBUFFER, samples, internalformat, width, height); mFunctions->renderbufferStorageMultisample(GL_RENDERBUFFER, samples, internalformat, width, height);
const gl::TextureCaps &formatCaps = mTextureCaps.get(internalformat);
if (samples > formatCaps.getMaxSamples())
{
// Before version 4.2, it is unknown if the specific internal format can support the requested number
// of samples. It is expected that GL_OUT_OF_MEMORY is returned if the renderbuffer cannot be created.
GLenum error = GL_NO_ERROR;
do
{
GLenum error = mFunctions->getError();
if (error == GL_OUT_OF_MEMORY)
{
return gl::Error(GL_OUT_OF_MEMORY);
}
ASSERT(error == GL_NO_ERROR);
} while (error != GL_NO_ERROR);
}
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
} }
......
...@@ -11,6 +11,11 @@ ...@@ -11,6 +11,11 @@
#include "libANGLE/renderer/RenderbufferImpl.h" #include "libANGLE/renderer/RenderbufferImpl.h"
namespace gl
{
class TextureCapsMap;
}
namespace rx namespace rx
{ {
...@@ -20,7 +25,7 @@ class StateManagerGL; ...@@ -20,7 +25,7 @@ class StateManagerGL;
class RenderbufferGL : public RenderbufferImpl class RenderbufferGL : public RenderbufferImpl
{ {
public: public:
RenderbufferGL(const FunctionsGL *functions, StateManagerGL *stateManager); RenderbufferGL(const FunctionsGL *functions, StateManagerGL *stateManager, const gl::TextureCapsMap &textureCaps);
~RenderbufferGL() override; ~RenderbufferGL() override;
virtual gl::Error setStorage(GLenum internalformat, size_t width, size_t height) override; virtual gl::Error setStorage(GLenum internalformat, size_t width, size_t height) override;
...@@ -31,6 +36,7 @@ class RenderbufferGL : public RenderbufferImpl ...@@ -31,6 +36,7 @@ class RenderbufferGL : public RenderbufferImpl
private: private:
const FunctionsGL *mFunctions; const FunctionsGL *mFunctions;
StateManagerGL *mStateManager; StateManagerGL *mStateManager;
const gl::TextureCapsMap &mTextureCaps;
GLuint mRenderbufferID; GLuint mRenderbufferID;
}; };
......
...@@ -124,7 +124,7 @@ TextureImpl *RendererGL::createTexture(GLenum target) ...@@ -124,7 +124,7 @@ TextureImpl *RendererGL::createTexture(GLenum target)
RenderbufferImpl *RendererGL::createRenderbuffer() RenderbufferImpl *RendererGL::createRenderbuffer()
{ {
return new RenderbufferGL(mFunctions, mStateManager); return new RenderbufferGL(mFunctions, mStateManager, getRendererTextureCaps());
} }
BufferImpl *RendererGL::createBuffer() BufferImpl *RendererGL::createBuffer()
...@@ -196,18 +196,13 @@ std::string RendererGL::getRendererDescription() const ...@@ -196,18 +196,13 @@ std::string RendererGL::getRendererDescription() const
std::string nativeVendorString(reinterpret_cast<const char*>(mFunctions->getString(GL_VENDOR))); std::string nativeVendorString(reinterpret_cast<const char*>(mFunctions->getString(GL_VENDOR)));
std::string nativeRendererString(reinterpret_cast<const char*>(mFunctions->getString(GL_RENDERER))); std::string nativeRendererString(reinterpret_cast<const char*>(mFunctions->getString(GL_RENDERER)));
GLuint major;
GLuint minor;
bool isES;
nativegl::GetGLVersion(mFunctions->getString, &major, &minor, &isES);
std::ostringstream rendererString; std::ostringstream rendererString;
rendererString << nativeVendorString << " " << nativeRendererString << " OpenGL"; rendererString << nativeVendorString << " " << nativeRendererString << " OpenGL";
if (isES) if (mFunctions->openGLES)
{ {
rendererString << " ES"; rendererString << " ES";
} }
rendererString << " " << major << "." << minor; rendererString << " " << mFunctions->majorVersion << "." << mFunctions->minorVersion;
return rendererString.str(); return rendererString.str();
} }
......
...@@ -21,62 +21,35 @@ ...@@ -21,62 +21,35 @@
namespace rx namespace rx
{ {
namespace nativegl
{
void GetGLVersion(PFNGLGETSTRINGPROC getStringFunction, GLuint *outMajorVersion, GLuint *outMinorVersion,
bool *outIsES)
{
const std::string version = reinterpret_cast<const char*>(getStringFunction(GL_VERSION));
if (version.find("OpenGL ES") == std::string::npos)
{
// ES spec states that the GL_VERSION string will be in the following format:
// "OpenGL ES N.M vendor-specific information"
*outIsES = false;
*outMajorVersion = version[0] - '0';
*outMinorVersion = version[2] - '0';
}
else
{
// OpenGL spec states the GL_VERSION string will be in the following format:
// <version number><space><vendor-specific information>
// The version number is either of the form major number.minor number or major
// number.minor number.release number, where the numbers all have one or more
// digits
*outIsES = true;
*outMajorVersion = version[10] - '0';
*outMinorVersion = version[12] - '0';
}
}
std::vector<std::string> GetGLExtensions(PFNGLGETSTRINGPROC getStringFunction)
{
std::vector<std::string> result;
std::istringstream stream(reinterpret_cast<const char*>(getStringFunction(GL_EXTENSIONS)));
std::string extension;
while (std::getline(stream, extension, ' '))
{
result.push_back(extension);
}
return result;
}
}
namespace nativegl_gl namespace nativegl_gl
{ {
static gl::TextureCaps GenerateTextureFormatCaps(const FunctionsGL *functions, GLenum internalFormat, GLuint majorVersion, GLuint minorVersion, static gl::TextureCaps GenerateTextureFormatCaps(const FunctionsGL *functions, GLenum internalFormat)
const std::vector<std::string> &extensions)
{ {
gl::TextureCaps textureCaps; gl::TextureCaps textureCaps;
const nativegl::InternalFormat &formatInfo = nativegl::GetInternalFormatInfo(internalFormat); const nativegl::InternalFormat &formatInfo = nativegl::GetInternalFormatInfo(internalFormat);
textureCaps.texturable = formatInfo.textureSupport(majorVersion, minorVersion, extensions); textureCaps.texturable = formatInfo.textureSupport(functions->majorVersion, functions->minorVersion, functions->extensions);
textureCaps.renderable = formatInfo.renderSupport(majorVersion, minorVersion, extensions); textureCaps.renderable = formatInfo.renderSupport(functions->majorVersion, functions->minorVersion, functions->extensions);
textureCaps.filterable = formatInfo.filterSupport(majorVersion, minorVersion, extensions); textureCaps.filterable = formatInfo.filterSupport(functions->majorVersion, functions->minorVersion, functions->extensions);
// glGetInternalformativ is not available until version 4.2 but may be available through the 3.0
// extension GL_ARB_internalformat_query
if (textureCaps.renderable && functions->getInternalformativ)
{
GLint numSamples = 0;
functions->getInternalformativ(GL_RENDERBUFFER, internalFormat, GL_NUM_SAMPLE_COUNTS, 1, &numSamples);
if (numSamples > 0)
{
std::vector<GLint> samples(numSamples);
functions->getInternalformativ(GL_RENDERBUFFER, internalFormat, GL_SAMPLES, samples.size(), &samples[0]);
for (size_t sampleIndex = 0; sampleIndex < samples.size(); sampleIndex++)
{
textureCaps.sampleCounts.insert(samples[sampleIndex]);
}
}
}
return textureCaps; return textureCaps;
} }
...@@ -91,23 +64,13 @@ static GLint QuerySingleGLInt(const FunctionsGL *functions, GLenum name) ...@@ -91,23 +64,13 @@ static GLint QuerySingleGLInt(const FunctionsGL *functions, GLenum name)
void GenerateCaps(const FunctionsGL *functions, gl::Caps *caps, gl::TextureCapsMap *textureCapsMap, void GenerateCaps(const FunctionsGL *functions, gl::Caps *caps, gl::TextureCapsMap *textureCapsMap,
gl::Extensions *extensions) gl::Extensions *extensions)
{ {
GLuint majorVersion = 0;
GLuint minorVersion = 0;
bool isES = false;
nativegl::GetGLVersion(functions->getString, &majorVersion, &minorVersion, &isES);
std::vector<std::string> nativeExtensions = nativegl::GetGLExtensions(functions->getString);
// Texture format support checks // Texture format support checks
GLuint maxSamples = 0;
const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats(); const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats();
for (GLenum internalFormat : allFormats) for (GLenum internalFormat : allFormats)
{ {
gl::TextureCaps textureCaps = GenerateTextureFormatCaps(functions, internalFormat, majorVersion, minorVersion, nativeExtensions); gl::TextureCaps textureCaps = GenerateTextureFormatCaps(functions, internalFormat);
textureCapsMap->insert(internalFormat, textureCaps); textureCapsMap->insert(internalFormat, textureCaps);
maxSamples = std::max(maxSamples, textureCaps.getMaxSamples());
if (gl::GetInternalFormatInfo(internalFormat).compressed) if (gl::GetInternalFormatInfo(internalFormat).compressed)
{ {
caps->compressedTextureFormats.push_back(internalFormat); caps->compressedTextureFormats.push_back(internalFormat);
...@@ -184,13 +147,14 @@ void GenerateCaps(const FunctionsGL *functions, gl::Caps *caps, gl::TextureCapsM ...@@ -184,13 +147,14 @@ void GenerateCaps(const FunctionsGL *functions, gl::Caps *caps, gl::TextureCapsM
caps->maxTransformFeedbackSeparateComponents = 4; caps->maxTransformFeedbackSeparateComponents = 4;
// Table 6.35, Framebuffer Dependent Values // Table 6.35, Framebuffer Dependent Values
caps->maxSamples = 4; caps->maxSamples = QuerySingleGLInt(functions, GL_MAX_SAMPLES);
// Extension support // Extension support
extensions->setTextureExtensionSupport(*textureCapsMap); extensions->setTextureExtensionSupport(*textureCapsMap);
extensions->textureNPOT = true; extensions->textureNPOT = true;
extensions->textureStorage = true; extensions->textureStorage = true;
extensions->fboRenderMipmap = true; extensions->fboRenderMipmap = true;
extensions->framebufferMultisample = caps->maxSamples > 0;
} }
} }
......
...@@ -25,14 +25,6 @@ namespace rx ...@@ -25,14 +25,6 @@ namespace rx
{ {
class FunctionsGL; class FunctionsGL;
namespace nativegl
{
void GetGLVersion(PFNGLGETSTRINGPROC getStringFunction, GLuint *outMajorVersion, GLuint *outMinorVersion, bool *outIsES);
std::vector<std::string> GetGLExtensions(PFNGLGETSTRINGPROC getStringFunction);
}
namespace nativegl_gl namespace nativegl_gl
{ {
......
...@@ -58,8 +58,6 @@ class FunctionsGLWindows : public FunctionsGL ...@@ -58,8 +58,6 @@ class FunctionsGLWindows : public FunctionsGL
DisplayWGL::DisplayWGL() DisplayWGL::DisplayWGL()
: DisplayGL(), : DisplayGL(),
mOpenGLModule(nullptr), mOpenGLModule(nullptr),
mGLVersionMajor(0),
mGLVersionMinor(0),
mFunctionsWGL(nullptr), mFunctionsWGL(nullptr),
mFunctionsGL(nullptr), mFunctionsGL(nullptr),
mWindowClass(0), mWindowClass(0),
...@@ -186,12 +184,6 @@ egl::Error DisplayWGL::initialize(egl::Display *display) ...@@ -186,12 +184,6 @@ egl::Error DisplayWGL::initialize(egl::Display *display)
return egl::Error(EGL_NOT_INITIALIZED, "Failed to get glGetString pointer."); return egl::Error(EGL_NOT_INITIALIZED, "Failed to get glGetString pointer.");
} }
GLuint maxGLVersionMajor = 0;
GLuint maxGLVersionMinor = 0;
bool isES = false;
nativegl::GetGLVersion(getString, &maxGLVersionMajor, &maxGLVersionMinor, &isES);
ASSERT(!isES);
// Reinitialize the wgl functions to grab the extensions // Reinitialize the wgl functions to grab the extensions
mFunctionsWGL->intialize(mOpenGLModule, dummyDeviceContext); mFunctionsWGL->intialize(mOpenGLModule, dummyDeviceContext);
...@@ -283,9 +275,6 @@ egl::Error DisplayWGL::initialize(egl::Display *display) ...@@ -283,9 +275,6 @@ egl::Error DisplayWGL::initialize(egl::Display *display)
if (!mWGLContext) if (!mWGLContext)
{ {
// Don't have control over GL versions // Don't have control over GL versions
mGLVersionMajor = maxGLVersionMajor;
mGLVersionMinor = maxGLVersionMinor;
mWGLContext = mFunctionsWGL->createContext(mDeviceContext); mWGLContext = mFunctionsWGL->createContext(mDeviceContext);
} }
...@@ -299,11 +288,8 @@ egl::Error DisplayWGL::initialize(egl::Display *display) ...@@ -299,11 +288,8 @@ egl::Error DisplayWGL::initialize(egl::Display *display)
return egl::Error(EGL_NOT_INITIALIZED, "Failed to make the intermediate WGL context current."); return egl::Error(EGL_NOT_INITIALIZED, "Failed to make the intermediate WGL context current.");
} }
nativegl::GetGLVersion(getString, &mGLVersionMajor, &mGLVersionMinor, &isES);
ASSERT(!isES);
mFunctionsGL = new FunctionsGLWindows(mOpenGLModule, mFunctionsWGL->getProcAddress); mFunctionsGL = new FunctionsGLWindows(mOpenGLModule, mFunctionsWGL->getProcAddress);
mFunctionsGL->initialize(mGLVersionMajor, mGLVersionMinor); mFunctionsGL->initialize();
return DisplayGL::initialize(display); return DisplayGL::initialize(display);
} }
......
...@@ -55,8 +55,6 @@ class DisplayWGL : public DisplayGL ...@@ -55,8 +55,6 @@ class DisplayWGL : public DisplayGL
void generateCaps(egl::Caps *outCaps) const override; void generateCaps(egl::Caps *outCaps) const override;
HMODULE mOpenGLModule; HMODULE mOpenGLModule;
GLuint mGLVersionMajor;
GLuint mGLVersionMinor;
FunctionsWGL *mFunctionsWGL; FunctionsWGL *mFunctionsWGL;
FunctionsGL *mFunctionsGL; FunctionsGL *mFunctionsGL;
......
...@@ -362,11 +362,15 @@ bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context, GLenum tar ...@@ -362,11 +362,15 @@ bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context, GLenum tar
// ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
// the specified storage. This is different than ES 3.0 in which a sample number higher // the specified storage. This is different than ES 3.0 in which a sample number higher
// than the maximum sample number supported by this format generates a GL_INVALID_VALUE. // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat); // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples()) if (context->getClientVersion() >= 3)
{ {
context->recordError(Error(GL_OUT_OF_MEMORY)); const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
return false; if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
{
context->recordError(Error(GL_OUT_OF_MEMORY));
return false;
}
} }
return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height); return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height);
......
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