123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426 |
- /**
- * Copyright (c) 2006-2017 LOVE Development Team
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgment in the product documentation would be
- * appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- * misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- **/
- #ifndef LOVE_GRAPHICS_OPENGL_OPENGL_H
- #define LOVE_GRAPHICS_OPENGL_OPENGL_H
- // LOVE
- #include "common/config.h"
- #include "common/int.h"
- #include "common/math.h"
- #include "graphics/Color.h"
- #include "graphics/Texture.h"
- #include "graphics/vertex.h"
- #include "common/Matrix.h"
- // GLAD
- #include "libraries/glad/gladfuncs.hpp"
- // C++
- #include <vector>
- #include <stack>
- // The last argument to AttribPointer takes a buffer offset casted to a pointer.
- #define BUFFER_OFFSET(i) ((char *) NULL + (i))
- namespace love
- {
- namespace graphics
- {
- namespace opengl
- {
- // Awful, but the library uses the namespace in order to use the functions sanely
- // with proper autocomplete in IDEs while having name mangling safety -
- // no clashes with other GL libraries when linking, etc.
- using namespace glad;
- /**
- * Thin layer between OpenGL and the rest of the program.
- * Internally shadows some OpenGL context state for improved efficiency and
- * accuracy (compared to glGet etc.)
- * A class is more convenient and readable than plain namespaced functions, but
- * typically only one OpenGL object should be used (singleton.)
- **/
- class OpenGL
- {
- public:
- // OpenGL GPU vendors.
- enum Vendor
- {
- VENDOR_AMD,
- VENDOR_NVIDIA,
- VENDOR_INTEL,
- VENDOR_MESA_SOFT, // Software renderer.
- VENDOR_APPLE, // Software renderer on desktops.
- VENDOR_MICROSOFT, // Software renderer.
- VENDOR_IMGTEC,
- VENDOR_ARM,
- VENDOR_QUALCOMM,
- VENDOR_BROADCOM,
- VENDOR_VIVANTE,
- VENDOR_UNKNOWN
- };
- enum FramebufferTarget
- {
- FRAMEBUFFER_READ = (1 << 0),
- FRAMEBUFFER_DRAW = (1 << 1),
- FRAMEBUFFER_ALL = (FRAMEBUFFER_READ | FRAMEBUFFER_DRAW),
- };
- struct TextureFormat
- {
- GLenum internalformat = 0;
- GLenum externalformat = 0;
- GLenum type = 0;
- bool swizzled = false;
- GLint swizzle[4];
- };
- class TempDebugGroup
- {
- public:
- TempDebugGroup(const char *name);
- ~TempDebugGroup();
- };
- struct Stats
- {
- size_t textureMemory;
- int drawCalls;
- int shaderSwitches;
- } stats;
- struct Bugs
- {
- /**
- * On AMD's Windows (and probably Linux) drivers,
- * glBindFramebuffer + glClear + glBindFramebuffer + draw(fbo_tex) won't
- * work unless there's some kind of draw or state change which causes
- * the driver to update the texture's contents (just drawing the texture
- * won't always do it, with this driver bug).
- * Activating shader program 0 and then activating the actual program
- * seems to always 'fix' it for me.
- * Bug observed January 2016 with multiple AMD GPUs and driver versions.
- * https://love2d.org/forums/viewtopic.php?f=4&t=81496
- **/
- bool clearRequiresDriverTextureStateUpdate;
- /**
- * AMD's Windows drivers don't always properly generate mipmaps unless
- * glEnable(GL_TEXTURE_2D) is called directly before glGenerateMipmap.
- * This only applies to legacy and Compatibility Profile contexts, of
- * course.
- * https://www.opengl.org/wiki/Common_Mistakes#Automatic_mipmap_generation
- **/
- bool generateMipmapsRequiresTexture2DEnable;
- /**
- * Other bugs which have workarounds that don't use conditional code at
- * the moment:
- *
- * Kepler nvidia GPUs in at least OS X 10.10 and 10.11 fail to render
- * geometry with glDrawElements if index data comes from a Buffer Object
- * and vertex data doesn't. One workaround is to use a CPU-side index
- * array when there's also a CPU-side vertex array.
- * https://love2d.org/forums/viewtopic.php?f=4&t=81401&start=10
- *
- * Some android drivers don't seem to initialize the sampler index
- * values of sampler uniforms in shaders to 0 (which is required by the
- * GLSL ES specification) when linking the shader program. One
- * workaround is to always set the values of said sampler uniforms to 0
- * just after linking the shader program.
- * https://love2d.org/forums/viewtopic.php?f=4&t=81458
- **/
- } bugs;
- OpenGL();
- /**
- * Initializes the active OpenGL context.
- **/
- bool initContext();
- /**
- * Sets up some required context state based on current and default OpenGL
- * state. Call this directly after initializing an OpenGL context!
- **/
- void setupContext();
- /**
- * Marks current context state as invalid and deletes OpenGL objects owned
- * by this class instance. Call this directly before potentially deleting
- * an OpenGL context!
- **/
- void deInitContext();
- /**
- * Set up necessary state (LOVE-provided shader uniforms, etc.) for drawing.
- * This *MUST* be called directly before OpenGL drawing functions.
- **/
- void prepareDraw();
- /**
- * State-tracked glBindBuffer.
- * NOTE: This does not account for multiple VAOs being used! Index buffer
- * bindings are per-VAO in OpenGL, but this doesn't know about that.
- **/
- void bindBuffer(BufferType type, GLuint buffer);
- /**
- * glDeleteBuffers which updates our shadowed state.
- **/
- void deleteBuffer(GLuint buffer);
- /**
- * glDrawArrays and glDrawElements which increment the draw-call counter by
- * themselves.
- **/
- void drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instancecount = 1);
- void drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount = 1);
- /**
- * Sets the enabled vertex attribute arrays based on the specified attribute
- * bits. Each bit in the uint32 represents an enabled attribute array index.
- * For example, useVertexAttribArrays(1 << 0) will enable attribute index 0.
- * See the VertexAttribFlags enum for the standard vertex attributes.
- * This function *must* be used instead of glEnable/DisableVertexAttribArray.
- **/
- void useVertexAttribArrays(uint32 arraybits, uint32 instancedbits = 0);
- /**
- * Sets the OpenGL rendering viewport to the specified rectangle.
- * The y-coordinate starts at the top.
- **/
- void setViewport(const Rect &v);
- Rect getViewport() const;
- /**
- * Sets the scissor box to the specified rectangle.
- * The y-coordinate starts at the top and is flipped internally.
- **/
- void setScissor(const Rect &v, bool canvasActive);
- /**
- * Sets the constant color (vertex attribute). This may be applied
- * internally at draw-time. This gets gamma-corrected internally as well.
- **/
- void setConstantColor(const Colorf &color);
- const Colorf &getConstantColor() const;
- /**
- * Sets the global point size.
- **/
- void setPointSize(float size);
- float getPointSize() const;
- /**
- * Calls glEnable/glDisable(GL_FRAMEBUFFER_SRGB).
- **/
- void setFramebufferSRGB(bool enable);
- bool hasFramebufferSRGB() const;
- /**
- * Binds a Framebuffer Object to the specified target.
- **/
- void bindFramebuffer(FramebufferTarget target, GLuint framebuffer);
- GLuint getFramebuffer(FramebufferTarget target) const;
- void deleteFramebuffer(GLuint framebuffer);
- /**
- * Calls glUseProgram.
- **/
- void useProgram(GLuint program);
- /**
- * This will usually be 0 (system drawable), but some platforms require a
- * non-zero FBO for rendering.
- **/
- GLuint getDefaultFBO() const;
- /**
- * Gets the ID for love's default texture (used for "untextured" primitives.)
- **/
- GLuint getDefaultTexture() const;
- /**
- * Helper for setting the active texture unit.
- *
- * @param textureunit Index in the range of [0, maxtextureunits-1]
- **/
- void setTextureUnit(int textureunit);
- /**
- * Helper for binding a texture to a specific texture unit.
- *
- * @param textureunit Index in the range of [0, maxtextureunits-1]
- * @param restoreprev Restore previously bound texture unit when done.
- **/
- void bindTextureToUnit(GLuint texture, int textureunit, bool restoreprev);
- void bindTextureToUnit(Texture *texture, int textureunit, bool restoreprev);
- /**
- * Helper for deleting an OpenGL texture.
- * Cleans up if the texture is currently bound.
- **/
- void deleteTexture(GLuint texture);
- /**
- * Sets the texture filter mode for the currently bound texture.
- * The anisotropy parameter of the argument is set to the actual amount of
- * anisotropy that was used.
- **/
- void setTextureFilter(graphics::Texture::Filter &f);
- /**
- * Sets the texture wrap mode for the currently bound texture.
- **/
- void setTextureWrap(const graphics::Texture::Wrap &w);
- bool isClampZeroTextureWrapSupported() const;
- bool isPixelShaderHighpSupported() const;
- bool isInstancingSupported() const;
- /**
- * Returns the maximum supported width or height of a texture.
- **/
- int getMaxTextureSize() const;
- /**
- * Returns the maximum supported number of simultaneous render targets.
- **/
- int getMaxRenderTargets() const;
- /**
- * Returns the maximum supported number of MSAA samples for renderbuffers.
- **/
- int getMaxRenderbufferSamples() const;
- /**
- * Returns the maximum number of accessible texture units.
- **/
- int getMaxTextureUnits() const;
- /**
- * Returns the maximum point size.
- **/
- float getMaxPointSize() const;
- /**
- * Returns the maximum anisotropic filtering value that can be used for
- * Texture filtering.
- **/
- float getMaxAnisotropy() const;
- void updateTextureMemorySize(size_t oldsize, size_t newsize);
- /**
- * Gets whether the context is Core Profile OpenGL 3.2+.
- **/
- bool isCoreProfile() const;
- /**
- * Get the GPU vendor of this OpenGL context.
- **/
- Vendor getVendor() const;
- static GLenum getGLBufferType(BufferType type);
- static GLenum getGLIndexDataType(IndexDataType type);
- static GLenum getGLBufferUsage(vertex::Usage usage);
- static GLint getGLWrapMode(Texture::WrapMode wmode);
- static TextureFormat convertPixelFormat(PixelFormat pixelformat, bool renderbuffer, bool &isSRGB);
- static bool isPixelFormatSupported(PixelFormat pixelformat, bool rendertarget, bool isSRGB);
- static bool hasTextureFilteringSupport(PixelFormat pixelformat);
- static const char *errorString(GLenum errorcode);
- static const char *framebufferStatusString(GLenum status);
- // Get human-readable strings for debug info.
- static const char *debugSeverityString(GLenum severity);
- static const char *debugSourceString(GLenum source);
- static const char *debugTypeString(GLenum type);
- private:
- void initVendor();
- void initOpenGLFunctions();
- void initMaxValues();
- void createDefaultTexture();
- bool contextInitialized;
- bool pixelShaderHighpSupported;
- float maxAnisotropy;
- int maxTextureSize;
- int maxRenderTargets;
- int maxRenderbufferSamples;
- int maxTextureUnits;
- float maxPointSize;
- bool coreProfile;
- Vendor vendor;
- // Tracked OpenGL state.
- struct
- {
- GLuint boundBuffers[BUFFER_MAX_ENUM];
- // Texture unit state (currently bound texture for each texture unit.)
- std::vector<GLuint> boundTextures;
- // Currently active texture unit.
- int curTextureUnit;
- uint32 enabledAttribArrays;
- uint32 instancedAttribArrays;
- Colorf constantColor;
- Colorf lastConstantColor;
- Rect viewport;
- Rect scissor;
- float pointSize;
- GLuint boundFramebuffers[2];
- bool framebufferSRGBEnabled;
- GLuint defaultTexture;
- } state;
- }; // OpenGL
- // OpenGL class instance singleton.
- extern OpenGL gl;
- } // opengl
- } // graphics
- } // love
- #endif // LOVE_GRAPHICS_OPENGL_OPENGL_H
|