OpenGL.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. /**
  2. * Copyright (c) 2006-2017 LOVE Development Team
  3. *
  4. * This software is provided 'as-is', without any express or implied
  5. * warranty. In no event will the authors be held liable for any damages
  6. * arising from the use of this software.
  7. *
  8. * Permission is granted to anyone to use this software for any purpose,
  9. * including commercial applications, and to alter it and redistribute it
  10. * freely, subject to the following restrictions:
  11. *
  12. * 1. The origin of this software must not be misrepresented; you must not
  13. * claim that you wrote the original software. If you use this software
  14. * in a product, an acknowledgment in the product documentation would be
  15. * appreciated but is not required.
  16. * 2. Altered source versions must be plainly marked as such, and must not be
  17. * misrepresented as being the original software.
  18. * 3. This notice may not be removed or altered from any source distribution.
  19. **/
  20. #ifndef LOVE_GRAPHICS_OPENGL_OPENGL_H
  21. #define LOVE_GRAPHICS_OPENGL_OPENGL_H
  22. // LOVE
  23. #include "common/config.h"
  24. #include "common/int.h"
  25. #include "common/math.h"
  26. #include "graphics/Color.h"
  27. #include "graphics/Texture.h"
  28. #include "graphics/vertex.h"
  29. #include "common/Matrix.h"
  30. // GLAD
  31. #include "libraries/glad/gladfuncs.hpp"
  32. // C++
  33. #include <vector>
  34. #include <stack>
  35. // The last argument to AttribPointer takes a buffer offset casted to a pointer.
  36. #define BUFFER_OFFSET(i) ((char *) NULL + (i))
  37. namespace love
  38. {
  39. namespace graphics
  40. {
  41. class Buffer;
  42. namespace opengl
  43. {
  44. // Awful, but the library uses the namespace in order to use the functions sanely
  45. // with proper autocomplete in IDEs while having name mangling safety -
  46. // no clashes with other GL libraries when linking, etc.
  47. using namespace glad;
  48. /**
  49. * Thin layer between OpenGL and the rest of the program.
  50. * Internally shadows some OpenGL context state for improved efficiency and
  51. * accuracy (compared to glGet etc.)
  52. * A class is more convenient and readable than plain namespaced functions, but
  53. * typically only one OpenGL object should be used (singleton.)
  54. **/
  55. class OpenGL
  56. {
  57. public:
  58. // OpenGL GPU vendors.
  59. enum Vendor
  60. {
  61. VENDOR_AMD,
  62. VENDOR_NVIDIA,
  63. VENDOR_INTEL,
  64. VENDOR_MESA_SOFT, // Software renderer.
  65. VENDOR_APPLE, // Software renderer on desktops.
  66. VENDOR_MICROSOFT, // Software renderer.
  67. VENDOR_IMGTEC,
  68. VENDOR_ARM,
  69. VENDOR_QUALCOMM,
  70. VENDOR_BROADCOM,
  71. VENDOR_VIVANTE,
  72. VENDOR_UNKNOWN
  73. };
  74. enum FramebufferTarget
  75. {
  76. FRAMEBUFFER_READ = (1 << 0),
  77. FRAMEBUFFER_DRAW = (1 << 1),
  78. FRAMEBUFFER_ALL = (FRAMEBUFFER_READ | FRAMEBUFFER_DRAW),
  79. };
  80. struct TextureFormat
  81. {
  82. GLenum internalformat = 0;
  83. GLenum externalformat = 0;
  84. GLenum type = 0;
  85. bool swizzled = false;
  86. GLint swizzle[4];
  87. };
  88. class TempDebugGroup
  89. {
  90. public:
  91. TempDebugGroup(const char *name);
  92. ~TempDebugGroup();
  93. };
  94. struct Stats
  95. {
  96. size_t textureMemory;
  97. int drawCalls;
  98. int shaderSwitches;
  99. } stats;
  100. struct Bugs
  101. {
  102. /**
  103. * On AMD's Windows (and probably Linux) drivers,
  104. * glBindFramebuffer + glClear + glBindFramebuffer + draw(fbo_tex) won't
  105. * work unless there's some kind of draw or state change which causes
  106. * the driver to update the texture's contents (just drawing the texture
  107. * won't always do it, with this driver bug).
  108. * Activating shader program 0 and then activating the actual program
  109. * seems to always 'fix' it for me.
  110. * Bug observed January 2016 with multiple AMD GPUs and driver versions.
  111. * https://love2d.org/forums/viewtopic.php?f=4&t=81496
  112. **/
  113. bool clearRequiresDriverTextureStateUpdate;
  114. /**
  115. * AMD's Windows drivers don't always properly generate mipmaps unless
  116. * glEnable(GL_TEXTURE_2D) is called directly before glGenerateMipmap.
  117. * This only applies to legacy and Compatibility Profile contexts, of
  118. * course.
  119. * https://www.opengl.org/wiki/Common_Mistakes#Automatic_mipmap_generation
  120. **/
  121. bool generateMipmapsRequiresTexture2DEnable;
  122. /**
  123. * Other bugs which have workarounds that don't use conditional code at
  124. * the moment:
  125. *
  126. * Kepler nvidia GPUs in at least OS X 10.10 and 10.11 fail to render
  127. * geometry with glDrawElements if index data comes from a Buffer Object
  128. * and vertex data doesn't. One workaround is to use a CPU-side index
  129. * array when there's also a CPU-side vertex array.
  130. * https://love2d.org/forums/viewtopic.php?f=4&t=81401&start=10
  131. *
  132. * Some android drivers don't seem to initialize the sampler index
  133. * values of sampler uniforms in shaders to 0 (which is required by the
  134. * GLSL ES specification) when linking the shader program. One
  135. * workaround is to always set the values of said sampler uniforms to 0
  136. * just after linking the shader program.
  137. * https://love2d.org/forums/viewtopic.php?f=4&t=81458
  138. **/
  139. } bugs;
  140. OpenGL();
  141. /**
  142. * Initializes the active OpenGL context.
  143. **/
  144. bool initContext();
  145. /**
  146. * Sets up some required context state based on current and default OpenGL
  147. * state. Call this directly after initializing an OpenGL context!
  148. **/
  149. void setupContext();
  150. /**
  151. * Marks current context state as invalid and deletes OpenGL objects owned
  152. * by this class instance. Call this directly before potentially deleting
  153. * an OpenGL context!
  154. **/
  155. void deInitContext();
  156. /**
  157. * Set up necessary state (LOVE-provided shader uniforms, etc.) for drawing.
  158. * This *MUST* be called directly before OpenGL drawing functions.
  159. **/
  160. void prepareDraw();
  161. /**
  162. * State-tracked glBindBuffer.
  163. * NOTE: This does not account for multiple VAOs being used! Index buffer
  164. * bindings are per-VAO in OpenGL, but this doesn't know about that.
  165. **/
  166. void bindBuffer(BufferType type, GLuint buffer);
  167. /**
  168. * glDeleteBuffers which updates our shadowed state.
  169. **/
  170. void deleteBuffer(GLuint buffer);
  171. /**
  172. * glDrawArrays and glDrawElements which increment the draw-call counter by
  173. * themselves.
  174. **/
  175. void drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instancecount = 1);
  176. void drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount = 1);
  177. /**
  178. * Sets the enabled vertex attribute arrays based on the specified attribute
  179. * bits. Each bit in the uint32 represents an enabled attribute array index.
  180. * For example, useVertexAttribArrays(1 << 0) will enable attribute index 0.
  181. * See the VertexAttribFlags enum for the standard vertex attributes.
  182. * This function *must* be used instead of glEnable/DisableVertexAttribArray.
  183. **/
  184. void useVertexAttribArrays(uint32 arraybits, uint32 instancedbits = 0);
  185. /**
  186. * Calls glVertexAttribPointer appropriately for each attribute used in the
  187. * specified format.
  188. **/
  189. void setVertexPointers(vertex::CommonFormat format, size_t offset);
  190. void setVertexPointers(vertex::CommonFormat format, size_t stride, size_t offset);
  191. void setVertexPointers(vertex::CommonFormat format, love::graphics::Buffer *buffer, size_t offset);
  192. void setVertexPointers(vertex::CommonFormat format, love::graphics::Buffer *buffer, size_t stride, size_t offset);
  193. /**
  194. * Sets the OpenGL rendering viewport to the specified rectangle.
  195. * The y-coordinate starts at the top.
  196. **/
  197. void setViewport(const Rect &v);
  198. Rect getViewport() const;
  199. /**
  200. * Sets the scissor box to the specified rectangle.
  201. * The y-coordinate starts at the top and is flipped internally.
  202. **/
  203. void setScissor(const Rect &v, bool canvasActive);
  204. /**
  205. * Sets the constant color (vertex attribute). This may be applied
  206. * internally at draw-time. This gets gamma-corrected internally as well.
  207. **/
  208. void setConstantColor(const Colorf &color);
  209. const Colorf &getConstantColor() const;
  210. /**
  211. * Sets the global point size.
  212. **/
  213. void setPointSize(float size);
  214. float getPointSize() const;
  215. /**
  216. * Calls glEnable/glDisable(GL_FRAMEBUFFER_SRGB).
  217. **/
  218. void setFramebufferSRGB(bool enable);
  219. bool hasFramebufferSRGB() const;
  220. /**
  221. * Binds a Framebuffer Object to the specified target.
  222. **/
  223. void bindFramebuffer(FramebufferTarget target, GLuint framebuffer);
  224. GLuint getFramebuffer(FramebufferTarget target) const;
  225. void deleteFramebuffer(GLuint framebuffer);
  226. void framebufferTexture(GLenum attachment, TextureType texType, GLuint texture, int level, int layer = 0, int face = 0);
  227. /**
  228. * Calls glUseProgram.
  229. **/
  230. void useProgram(GLuint program);
  231. /**
  232. * This will usually be 0 (system drawable), but some platforms require a
  233. * non-zero FBO for rendering.
  234. **/
  235. GLuint getDefaultFBO() const;
  236. /**
  237. * Gets the ID for love's default texture (used for "untextured" primitives.)
  238. **/
  239. GLuint getDefaultTexture(TextureType type) const;
  240. /**
  241. * Helper for setting the active texture unit.
  242. *
  243. * @param textureunit Index in the range of [0, maxtextureunits-1]
  244. **/
  245. void setTextureUnit(int textureunit);
  246. /**
  247. * Helper for binding a texture to a specific texture unit.
  248. *
  249. * @param textureunit Index in the range of [0, maxtextureunits-1]
  250. * @param restoreprev Restore previously bound texture unit when done.
  251. **/
  252. void bindTextureToUnit(TextureType target, GLuint texture, int textureunit, bool restoreprev);
  253. void bindTextureToUnit(Texture *texture, int textureunit, bool restoreprev);
  254. /**
  255. * Helper for deleting an OpenGL texture.
  256. * Cleans up if the texture is currently bound.
  257. **/
  258. void deleteTexture(GLuint texture);
  259. /**
  260. * Sets the texture filter mode for the currently bound texture.
  261. * The anisotropy parameter of the argument is set to the actual amount of
  262. * anisotropy that was used.
  263. **/
  264. void setTextureFilter(TextureType target, graphics::Texture::Filter &f);
  265. /**
  266. * Sets the texture wrap mode for the currently bound texture.
  267. **/
  268. void setTextureWrap(TextureType target, const graphics::Texture::Wrap &w);
  269. /**
  270. * Equivalent to glTexStorage2D/3D on platforms that support it. Equivalent
  271. * to glTexImage2D/3D for all levels and slices of a texture otherwise.
  272. * NOTE: this does not handle compressed texture formats.
  273. **/
  274. bool rawTexStorage(TextureType target, int levels, PixelFormat pixelformat, bool &isSRGB, int width, int height, int depth = 1);
  275. bool isTextureTypeSupported(TextureType type) const;
  276. bool isClampZeroTextureWrapSupported() const;
  277. bool isPixelShaderHighpSupported() const;
  278. bool isInstancingSupported() const;
  279. /**
  280. * Returns the maximum supported width or height of a texture.
  281. **/
  282. int getMax2DTextureSize() const;
  283. int getMax3DTextureSize() const;
  284. int getMaxCubeTextureSize() const;
  285. int getMaxTextureLayers() const;
  286. /**
  287. * Returns the maximum supported number of simultaneous render targets.
  288. **/
  289. int getMaxRenderTargets() const;
  290. /**
  291. * Returns the maximum supported number of MSAA samples for renderbuffers.
  292. **/
  293. int getMaxRenderbufferSamples() const;
  294. /**
  295. * Returns the maximum number of accessible texture units.
  296. **/
  297. int getMaxTextureUnits() const;
  298. /**
  299. * Returns the maximum point size.
  300. **/
  301. float getMaxPointSize() const;
  302. /**
  303. * Returns the maximum anisotropic filtering value that can be used for
  304. * Texture filtering.
  305. **/
  306. float getMaxAnisotropy() const;
  307. void updateTextureMemorySize(size_t oldsize, size_t newsize);
  308. /**
  309. * Gets whether the context is Core Profile OpenGL 3.2+.
  310. **/
  311. bool isCoreProfile() const;
  312. /**
  313. * Get the GPU vendor of this OpenGL context.
  314. **/
  315. Vendor getVendor() const;
  316. static GLenum getGLBufferType(BufferType type);
  317. static GLenum getGLIndexDataType(IndexDataType type);
  318. static GLenum getGLBufferUsage(vertex::Usage usage);
  319. static GLenum getGLTextureType(TextureType type);
  320. static GLint getGLWrapMode(Texture::WrapMode wmode);
  321. static TextureFormat convertPixelFormat(PixelFormat pixelformat, bool renderbuffer, bool &isSRGB);
  322. static bool isTexStorageSupported();
  323. static bool isPixelFormatSupported(PixelFormat pixelformat, bool rendertarget, bool isSRGB);
  324. static bool hasTextureFilteringSupport(PixelFormat pixelformat);
  325. static const char *errorString(GLenum errorcode);
  326. static const char *framebufferStatusString(GLenum status);
  327. // Get human-readable strings for debug info.
  328. static const char *debugSeverityString(GLenum severity);
  329. static const char *debugSourceString(GLenum source);
  330. static const char *debugTypeString(GLenum type);
  331. private:
  332. void initVendor();
  333. void initOpenGLFunctions();
  334. void initMaxValues();
  335. void createDefaultTexture();
  336. bool contextInitialized;
  337. bool pixelShaderHighpSupported;
  338. float maxAnisotropy;
  339. int max2DTextureSize;
  340. int max3DTextureSize;
  341. int maxCubeTextureSize;
  342. int maxTextureArrayLayers;
  343. int maxRenderTargets;
  344. int maxRenderbufferSamples;
  345. int maxTextureUnits;
  346. float maxPointSize;
  347. bool coreProfile;
  348. Vendor vendor;
  349. // Tracked OpenGL state.
  350. struct
  351. {
  352. GLuint boundBuffers[BUFFER_MAX_ENUM];
  353. // Texture unit state (currently bound texture for each texture unit.)
  354. std::vector<GLuint> boundTextures[TEXTURE_MAX_ENUM];
  355. // Currently active texture unit.
  356. int curTextureUnit;
  357. uint32 enabledAttribArrays;
  358. uint32 instancedAttribArrays;
  359. Colorf constantColor;
  360. Colorf lastConstantColor;
  361. Rect viewport;
  362. Rect scissor;
  363. float pointSize;
  364. GLuint boundFramebuffers[2];
  365. bool framebufferSRGBEnabled;
  366. GLuint defaultTexture[TEXTURE_MAX_ENUM];
  367. } state;
  368. }; // OpenGL
  369. // OpenGL class instance singleton.
  370. extern OpenGL gl;
  371. } // opengl
  372. } // graphics
  373. } // love
  374. #endif // LOVE_GRAPHICS_OPENGL_OPENGL_H