OpenGL.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. /**
  2. * Copyright (c) 2006-2016 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 "graphics/Color.h"
  26. #include "graphics/Texture.h"
  27. #include "common/Matrix.h"
  28. // GLAD
  29. #include "libraries/glad/gladfuncs.hpp"
  30. // C++
  31. #include <vector>
  32. #include <stack>
  33. // The last argument to AttribPointer takes a buffer offset casted to a pointer.
  34. #define BUFFER_OFFSET(i) ((char *) NULL + (i))
  35. namespace love
  36. {
  37. namespace graphics
  38. {
  39. namespace opengl
  40. {
  41. // Awful, but the library uses the namespace in order to use the functions sanely
  42. // with proper autocomplete in IDEs while having name mangling safety -
  43. // no clashes with other GL libraries when linking, etc.
  44. using namespace glad;
  45. // Vertex attribute indices used in shaders by LOVE. The values map to OpenGL
  46. // generic vertex attribute indices.
  47. enum VertexAttribID
  48. {
  49. ATTRIB_POS = 0,
  50. ATTRIB_TEXCOORD,
  51. ATTRIB_COLOR,
  52. ATTRIB_CONSTANTCOLOR,
  53. ATTRIB_MAX_ENUM
  54. };
  55. enum VertexAttribFlags
  56. {
  57. ATTRIBFLAG_POS = 1 << ATTRIB_POS,
  58. ATTRIBFLAG_TEXCOORD = 1 << ATTRIB_TEXCOORD,
  59. ATTRIBFLAG_COLOR = 1 << ATTRIB_COLOR,
  60. ATTRIBFLAG_CONSTANTCOLOR = 1 << ATTRIB_CONSTANTCOLOR
  61. };
  62. /**
  63. * Thin layer between OpenGL and the rest of the program.
  64. * Internally shadows some OpenGL context state for improved efficiency and
  65. * accuracy (compared to glGet etc.)
  66. * A class is more convenient and readable than plain namespaced functions, but
  67. * typically only one OpenGL object should be used (singleton.)
  68. **/
  69. class OpenGL
  70. {
  71. public:
  72. // OpenGL GPU vendors.
  73. enum Vendor
  74. {
  75. VENDOR_AMD,
  76. VENDOR_NVIDIA,
  77. VENDOR_INTEL,
  78. VENDOR_MESA_SOFT, // Software renderer.
  79. VENDOR_APPLE, // Software renderer on desktops.
  80. VENDOR_MICROSOFT, // Software renderer.
  81. VENDOR_IMGTEC,
  82. VENDOR_ARM,
  83. VENDOR_QUALCOMM,
  84. VENDOR_BROADCOM,
  85. VENDOR_VIVANTE,
  86. VENDOR_UNKNOWN
  87. };
  88. // A rectangle representing an OpenGL viewport or a scissor box.
  89. struct Viewport
  90. {
  91. int x, y;
  92. int w, h;
  93. bool operator == (const Viewport &rhs) const
  94. {
  95. return x == rhs.x && y == rhs.y && w == rhs.w && h == rhs.h;
  96. }
  97. };
  98. struct
  99. {
  100. std::vector<Matrix4> transform;
  101. std::vector<Matrix4> projection;
  102. } matrices;
  103. class TempTransform
  104. {
  105. public:
  106. TempTransform(OpenGL &gl)
  107. : gl(gl)
  108. {
  109. gl.pushTransform();
  110. }
  111. ~TempTransform()
  112. {
  113. gl.popTransform();
  114. }
  115. Matrix4 &get()
  116. {
  117. return gl.getTransform();
  118. }
  119. private:
  120. OpenGL &gl;
  121. };
  122. class TempDebugGroup
  123. {
  124. public:
  125. #if defined(LOVE_IOS)
  126. TempDebugGroup(const char *name)
  127. {
  128. if (GLAD_EXT_debug_marker)
  129. glPushGroupMarkerEXT(0, (const GLchar *) name);
  130. }
  131. #else
  132. TempDebugGroup(const char *) {}
  133. #endif
  134. #if defined(LOVE_IOS)
  135. ~TempDebugGroup()
  136. {
  137. if (GLAD_EXT_debug_marker)
  138. glPopGroupMarkerEXT();
  139. }
  140. #endif
  141. };
  142. struct Stats
  143. {
  144. size_t textureMemory;
  145. int drawCalls;
  146. int framebufferBinds;
  147. } stats;
  148. struct Bugs
  149. {
  150. /**
  151. * On AMD's Windows (and probably Linux) drivers,
  152. * glBindFramebuffer + glClear + glBindFramebuffer + draw(fbo_tex) won't
  153. * work unless there's some kind of draw or state change which causes
  154. * the driver to update the texture's contents (just drawing the texture
  155. * won't always do it, with this driver bug).
  156. * Activating shader program 0 and then activating the actual program
  157. * seems to always 'fix' it for me.
  158. * Bug observed January 2016 with multiple AMD GPUs and driver versions.
  159. * https://love2d.org/forums/viewtopic.php?f=4&t=81496
  160. **/
  161. bool clearRequiresDriverTextureStateUpdate;
  162. /**
  163. * Other bugs which have workarounds that don't use conditional code at
  164. * the moment:
  165. *
  166. * Kepler nvidia GPUs in at least OS X 10.10 and 10.11 fail to render
  167. * geometry with glDrawElements if index data comes from a Buffer Object
  168. * and vertex data doesn't. One workaround is to use a CPU-side index
  169. * array when there's also a CPU-side vertex array.
  170. * https://love2d.org/forums/viewtopic.php?f=4&t=81401&start=10
  171. *
  172. * Some android drivers don't seem to initialize the sampler index
  173. * values of sampler uniforms in shaders to 0 (which is required by the
  174. * GLSL ES specification) when linking the shader program. One
  175. * workaround is to always set the values of said sampler uniforms to 0
  176. * just after linking the shader program.
  177. * https://love2d.org/forums/viewtopic.php?f=4&t=81458
  178. **/
  179. } bugs;
  180. OpenGL();
  181. /**
  182. * Initializes the active OpenGL context.
  183. **/
  184. bool initContext();
  185. /**
  186. * Sets up some required context state based on current and default OpenGL
  187. * state. Call this directly after initializing an OpenGL context!
  188. **/
  189. void setupContext();
  190. /**
  191. * Marks current context state as invalid and deletes OpenGL objects owned
  192. * by this class instance. Call this directly before potentially deleting
  193. * an OpenGL context!
  194. **/
  195. void deInitContext();
  196. void pushTransform();
  197. void popTransform();
  198. Matrix4 &getTransform();
  199. /**
  200. * Set up necessary state (LOVE-provided shader uniforms, etc.) for drawing.
  201. * This *MUST* be called directly before OpenGL drawing functions.
  202. **/
  203. void prepareDraw();
  204. /**
  205. * glDrawArrays and glDrawElements which increment the draw-call counter by
  206. * themselves.
  207. **/
  208. void drawArrays(GLenum mode, GLint first, GLsizei count);
  209. void drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices);
  210. /**
  211. * Sets the enabled vertex attribute arrays based on the specified attribute
  212. * bits. Each bit in the uint32 represents an enabled attribute array index.
  213. * For example, useVertexAttribArrays(1 << 0) will enable attribute index 0.
  214. * See the VertexAttribFlags enum for the standard vertex attributes.
  215. * This function *must* be used instead of glEnable/DisableVertexAttribArray.
  216. **/
  217. void useVertexAttribArrays(uint32 arraybits);
  218. /**
  219. * Sets the OpenGL rendering viewport to the specified rectangle.
  220. * The y-coordinate starts at the top.
  221. **/
  222. void setViewport(const Viewport &v);
  223. /**
  224. * Gets the current OpenGL rendering viewport rectangle.
  225. **/
  226. Viewport getViewport() const;
  227. /**
  228. * Sets the scissor box to the specified rectangle.
  229. * The y-coordinate starts at the top and is flipped internally.
  230. **/
  231. void setScissor(const Viewport &v);
  232. /**
  233. * Gets the current scissor box (regardless of whether scissoring is enabled.)
  234. **/
  235. Viewport getScissor() const;
  236. /**
  237. * Sets the global point size.
  238. **/
  239. void setPointSize(float size);
  240. /**
  241. * Gets the global point size.
  242. **/
  243. float getPointSize() const;
  244. /**
  245. * Calls glEnable/glDisable(GL_FRAMEBUFFER_SRGB).
  246. **/
  247. void setFramebufferSRGB(bool enable);
  248. /**
  249. * Equivalent to glIsEnabled(GL_FRAMEBUFFER_SRGB).
  250. **/
  251. bool hasFramebufferSRGB() const;
  252. /**
  253. * Binds a Framebuffer Object to the specified target.
  254. **/
  255. void bindFramebuffer(GLenum target, GLuint framebuffer);
  256. /**
  257. * This will usually be 0 (system drawable), but some platforms require a
  258. * non-zero FBO for rendering.
  259. **/
  260. GLuint getDefaultFBO() const;
  261. /**
  262. * Gets the ID for love's default texture (used for "untextured" primitives.)
  263. **/
  264. GLuint getDefaultTexture() const;
  265. /**
  266. * Helper for setting the active texture unit.
  267. *
  268. * @param textureunit Index in the range of [0, maxtextureunits-1]
  269. **/
  270. void setTextureUnit(int textureunit);
  271. /**
  272. * Helper for binding an OpenGL texture.
  273. * Makes sure we aren't redundantly binding textures.
  274. **/
  275. void bindTexture(GLuint texture);
  276. /**
  277. * Helper for binding a texture to a specific texture unit.
  278. *
  279. * @param textureunit Index in the range of [0, maxtextureunits-1]
  280. * @param restoreprev Restore previously bound texture unit when done.
  281. **/
  282. void bindTextureToUnit(GLuint texture, int textureunit, bool restoreprev);
  283. /**
  284. * Helper for deleting an OpenGL texture.
  285. * Cleans up if the texture is currently bound.
  286. **/
  287. void deleteTexture(GLuint texture);
  288. /**
  289. * Sets the texture filter mode for the currently bound texture.
  290. * The anisotropy parameter of the argument is set to the actual amount of
  291. * anisotropy that was used.
  292. **/
  293. void setTextureFilter(graphics::Texture::Filter &f);
  294. /**
  295. * Sets the texture wrap mode for the currently bound texture.
  296. **/
  297. void setTextureWrap(const graphics::Texture::Wrap &w);
  298. bool isClampZeroTextureWrapSupported() const;
  299. /**
  300. * Returns the maximum supported width or height of a texture.
  301. **/
  302. int getMaxTextureSize() const;
  303. /**
  304. * Returns the maximum supported number of simultaneous render targets.
  305. **/
  306. int getMaxRenderTargets() const;
  307. /**
  308. * Returns the maximum supported number of MSAA samples for renderbuffers.
  309. **/
  310. int getMaxRenderbufferSamples() const;
  311. /**
  312. * Returns the maximum number of accessible texture units.
  313. **/
  314. int getMaxTextureUnits() const;
  315. void updateTextureMemorySize(size_t oldsize, size_t newsize);
  316. /**
  317. * Get the GPU vendor of this OpenGL context.
  318. **/
  319. Vendor getVendor() const;
  320. static const char *errorString(GLenum errorcode);
  321. // Get human-readable strings for debug info.
  322. static const char *debugSeverityString(GLenum severity);
  323. static const char *debugSourceString(GLenum source);
  324. static const char *debugTypeString(GLenum type);
  325. private:
  326. void initVendor();
  327. void initOpenGLFunctions();
  328. void initMaxValues();
  329. void initMatrices();
  330. void createDefaultTexture();
  331. GLint getGLWrapMode(Texture::WrapMode wmode);
  332. bool contextInitialized;
  333. float maxAnisotropy;
  334. int maxTextureSize;
  335. int maxRenderTargets;
  336. int maxRenderbufferSamples;
  337. int maxTextureUnits;
  338. Vendor vendor;
  339. // Tracked OpenGL state.
  340. struct
  341. {
  342. // Texture unit state (currently bound texture for each texture unit.)
  343. std::vector<GLuint> boundTextures;
  344. // Currently active texture unit.
  345. int curTextureUnit;
  346. uint32 enabledAttribArrays;
  347. Viewport viewport;
  348. Viewport scissor;
  349. float pointSize;
  350. bool framebufferSRGBEnabled;
  351. GLuint defaultTexture;
  352. Matrix4 lastProjectionMatrix;
  353. Matrix4 lastTransformMatrix;
  354. } state;
  355. }; // OpenGL
  356. // OpenGL class instance singleton.
  357. extern OpenGL gl;
  358. } // opengl
  359. } // graphics
  360. } // love
  361. #endif // LOVE_GRAPHICS_OPENGL_OPENGL_H