diff --git a/src/modules/graphics/opengl/Canvas.cpp b/src/modules/graphics/opengl/Canvas.cpp index f27cf87d1..dbde24e1e 100644 --- a/src/modules/graphics/opengl/Canvas.cpp +++ b/src/modules/graphics/opengl/Canvas.cpp @@ -149,12 +149,11 @@ struct FramebufferStrategyCorePacked : public FramebufferStrategy return true; } - virtual bool createMSAABuffer(int width, int height, int &samples, GLenum internalformat, GLuint &buffer) + virtual bool createMSAABuffer(int width, int height, int &samples, GLenum iformat, GLuint &buffer) { glGenRenderbuffers(1, &buffer); glBindRenderbuffer(GL_RENDERBUFFER, buffer); - glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, internalformat, - width, height); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, iformat, width, height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, buffer); glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &samples); @@ -1020,7 +1019,10 @@ bool Canvas::resolveMSAA() previous = current->fbo; // Do the MSAA resolve by blitting the MSAA renderbuffer to the texture. - if (GLAD_ES_VERSION_3_0 || GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_object) + // For many of the extensions that add suffixes to the functions, we assign + // function pointers in OpenGL.cpp so we can call the core functions. + if (GLAD_ES_VERSION_3_0 || GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_object + || GLAD_ANGLE_framebuffer_multisample) { glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolve_fbo); @@ -1034,6 +1036,12 @@ bool Canvas::resolveMSAA() glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST); } + else if (GLAD_APPLE_framebuffer_multisample) + { + glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolve_fbo); + glResolveMultisampleFramebufferAPPLE(); + } else return false; diff --git a/src/modules/graphics/opengl/OpenGL.cpp b/src/modules/graphics/opengl/OpenGL.cpp index 7a5768a0d..91c20c042 100644 --- a/src/modules/graphics/opengl/OpenGL.cpp +++ b/src/modules/graphics/opengl/OpenGL.cpp @@ -108,12 +108,12 @@ void OpenGL::setupContext() state.pointSize = 1.0f; // Initialize multiple texture unit support for shaders. - state.textureUnits.clear(); + state.boundTextures.clear(); GLint maxtextureunits; glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxtextureunits); - state.textureUnits.resize(maxtextureunits, 0); + state.boundTextures.resize(maxtextureunits, 0); GLenum curgltextureunit; glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint *) &curgltextureunit); @@ -121,10 +121,10 @@ void OpenGL::setupContext() state.curTextureUnit = (int) curgltextureunit - GL_TEXTURE0; // Retrieve currently bound textures for each texture unit. - for (int i = 0; i < (int) state.textureUnits.size(); i++) + for (int i = 0; i < (int) state.boundTextures.size(); i++) { glActiveTexture(GL_TEXTURE0 + i); - glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint *) &state.textureUnits[i]); + glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint *) &state.boundTextures[i]); } glActiveTexture(curgltextureunit); @@ -176,7 +176,7 @@ void OpenGL::initVendor() vendor = VENDOR_INTEL; else if (strstr(vstr, "Mesa")) vendor = VENDOR_MESA_SOFT; - else if (strstr(vstr, "Apple Computer")) + else if (strstr(vstr, "Apple Computer") || strstr(vstr, "Apple Inc.")) vendor = VENDOR_APPLE; else if (strstr(vstr, "Microsoft")) vendor = VENDOR_MICROSOFT; @@ -196,6 +196,18 @@ void OpenGL::initVendor() void OpenGL::initOpenGLFunctions() { + if (!(GLAD_ES_VERSION_3_0 || GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_object)) + { + // There are like 100 different suffixed versions of glRenderbufferStorageMultisample, + // so we'll just assign all the ones we use to the core function pointer. + if (GLAD_APPLE_framebuffer_multisample) + fp_glRenderbufferStorageMultisample = (pfn_glRenderbufferStorageMultisample) fp_glRenderbufferStorageMultisampleAPPLE; + else if (GLAD_ANGLE_framebuffer_multisample) + fp_glRenderbufferStorageMultisample = (pfn_glRenderbufferStorageMultisample) fp_glRenderbufferStorageMultisampleANGLE; + + if (GLAD_ANGLE_framebuffer_blit) + fp_glBlitFramebuffer = (pfn_glBlitFramebuffer) fp_glBlitFramebufferANGLE; + } } void OpenGL::initMaxValues() @@ -219,8 +231,12 @@ void OpenGL::initMaxValues() maxRenderTargets = std::min(maxattachments, maxdrawbuffers); - if (GLAD_ES_VERSION_3_0 || GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_object || GLAD_EXT_framebuffer_multisample) + if (GLAD_ES_VERSION_3_0 || GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_object + || GLAD_EXT_framebuffer_multisample || GLAD_APPLE_framebuffer_multisample + || GLAD_ANGLE_framebuffer_multisample) + { glGetIntegerv(GL_MAX_SAMPLES, &maxRenderbufferSamples); + } else maxRenderbufferSamples = 0; } @@ -241,7 +257,7 @@ void OpenGL::createDefaultTexture() // primitives, which would create the need to use different "passthrough" // shaders for untextured primitives vs images. - GLuint curtexture = state.textureUnits[state.curTextureUnit]; + GLuint curtexture = state.boundTextures[state.curTextureUnit]; glGenTextures(1, &state.defaultTexture); bindTexture(state.defaultTexture); @@ -446,7 +462,7 @@ GLuint OpenGL::getDefaultTexture() const void OpenGL::setTextureUnit(int textureunit) { - if (textureunit < 0 || (size_t) textureunit >= state.textureUnits.size()) + if (textureunit < 0 || (size_t) textureunit >= state.boundTextures.size()) throw love::Exception("Invalid texture unit index (%d).", textureunit); if (textureunit != state.curTextureUnit) @@ -457,24 +473,24 @@ void OpenGL::setTextureUnit(int textureunit) void OpenGL::bindTexture(GLuint texture) { - if (texture != state.textureUnits[state.curTextureUnit]) + if (texture != state.boundTextures[state.curTextureUnit]) { - state.textureUnits[state.curTextureUnit] = texture; + state.boundTextures[state.curTextureUnit] = texture; glBindTexture(GL_TEXTURE_2D, texture); } } void OpenGL::bindTextureToUnit(GLuint texture, int textureunit, bool restoreprev) { - if (textureunit < 0 || (size_t) textureunit >= state.textureUnits.size()) + if (textureunit < 0 || (size_t) textureunit >= state.boundTextures.size()) throw love::Exception("Invalid texture unit index."); - if (texture != state.textureUnits[textureunit]) + if (texture != state.boundTextures[textureunit]) { int oldtextureunit = state.curTextureUnit; setTextureUnit(textureunit); - state.textureUnits[textureunit] = texture; + state.boundTextures[textureunit] = texture; glBindTexture(GL_TEXTURE_2D, texture); if (restoreprev) @@ -486,7 +502,7 @@ void OpenGL::deleteTexture(GLuint texture) { // glDeleteTextures binds texture 0 to all texture units the deleted texture // was bound to before deletion. - for (GLuint &texid : state.textureUnits) + for (GLuint &texid : state.boundTextures) { if (texid == texture) texid = 0; diff --git a/src/modules/graphics/opengl/OpenGL.h b/src/modules/graphics/opengl/OpenGL.h index 7814cd49d..b432f9d6b 100644 --- a/src/modules/graphics/opengl/OpenGL.h +++ b/src/modules/graphics/opengl/OpenGL.h @@ -77,7 +77,7 @@ public: VENDOR_NVIDIA, VENDOR_INTEL, VENDOR_MESA_SOFT, // Software renderer. - VENDOR_APPLE, // Software renderer. + VENDOR_APPLE, // Software renderer on desktops. VENDOR_MICROSOFT, // Software renderer. VENDOR_IMGTEC, VENDOR_ARM, @@ -353,7 +353,7 @@ private: Color clearColor; // Texture unit state (currently bound texture for each texture unit.) - std::vector textureUnits; + std::vector boundTextures; // Currently active texture unit. int curTextureUnit;