GL.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. /*
  2. * Copyright (c) 2023, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #define GL_GLEXT_PROTOTYPES
  7. #include <LibAccelGfx/GL.h>
  8. #include <LibGfx/Bitmap.h>
  9. #include <LibGfx/Rect.h>
  10. namespace AccelGfx::GL {
  11. static void verify_no_error()
  12. {
  13. VERIFY(glGetError() == GL_NO_ERROR);
  14. }
  15. void set_viewport(Gfx::IntRect rect)
  16. {
  17. glViewport(rect.left(), rect.top(), rect.width(), rect.height());
  18. verify_no_error();
  19. }
  20. void enable_blending()
  21. {
  22. glEnable(GL_BLEND);
  23. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  24. verify_no_error();
  25. }
  26. void read_pixels(Gfx::IntRect rect, Gfx::Bitmap& bitmap)
  27. {
  28. VERIFY(bitmap.format() == Gfx::BitmapFormat::BGRA8888);
  29. glPixelStorei(GL_PACK_ALIGNMENT, 1);
  30. glReadPixels(rect.left(), rect.top(), rect.width(), rect.height(), GL_BGRA, GL_UNSIGNED_BYTE, bitmap.scanline(0));
  31. verify_no_error();
  32. }
  33. Shader create_shader(ShaderType type, char const* source)
  34. {
  35. GLuint shader = glCreateShader(type == ShaderType::Vertex ? GL_VERTEX_SHADER : GL_FRAGMENT_SHADER);
  36. glShaderSource(shader, 1, &source, nullptr);
  37. glCompileShader(shader);
  38. int success;
  39. glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
  40. if (!success) {
  41. char buffer[512];
  42. glGetShaderInfoLog(shader, sizeof(buffer), nullptr, buffer);
  43. dbgln("GLSL shader compilation failed: {}", buffer);
  44. VERIFY_NOT_REACHED();
  45. }
  46. verify_no_error();
  47. return { shader };
  48. }
  49. Program create_program(Shader const& vertex_shader, Shader const& fragment_shader)
  50. {
  51. GLuint program = glCreateProgram();
  52. glAttachShader(program, vertex_shader.id);
  53. glAttachShader(program, fragment_shader.id);
  54. glLinkProgram(program);
  55. int linked;
  56. glGetProgramiv(program, GL_LINK_STATUS, &linked);
  57. if (!linked) {
  58. char buffer[512];
  59. glGetProgramInfoLog(program, sizeof(buffer), nullptr, buffer);
  60. dbgln("GLSL program linking failed: {}", buffer);
  61. VERIFY_NOT_REACHED();
  62. }
  63. glDeleteShader(vertex_shader.id);
  64. glDeleteShader(fragment_shader.id);
  65. verify_no_error();
  66. return { program };
  67. }
  68. void use_program(Program const& program)
  69. {
  70. glUseProgram(program.id);
  71. verify_no_error();
  72. }
  73. VertexAttribute get_attribute_location(Program const& program, char const* name)
  74. {
  75. auto id = glGetAttribLocation(program.id, name);
  76. verify_no_error();
  77. return { id };
  78. }
  79. Uniform get_uniform_location(Program const& program, char const* name)
  80. {
  81. auto id = glGetUniformLocation(program.id, name);
  82. verify_no_error();
  83. return { id };
  84. }
  85. void delete_program(Program const& program)
  86. {
  87. glDeleteProgram(program.id);
  88. verify_no_error();
  89. }
  90. Texture create_texture()
  91. {
  92. GLuint texture;
  93. glGenTextures(1, &texture);
  94. verify_no_error();
  95. return { texture };
  96. }
  97. void bind_texture(Texture const& texture)
  98. {
  99. glBindTexture(GL_TEXTURE_2D, texture.id);
  100. verify_no_error();
  101. }
  102. void upload_texture_data(Texture const& texture, Gfx::Bitmap const& bitmap)
  103. {
  104. VERIFY(bitmap.format() == Gfx::BitmapFormat::BGRx8888 || bitmap.format() == Gfx::BitmapFormat::BGRA8888);
  105. bind_texture(texture);
  106. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap.width(), bitmap.height(), 0, GL_BGRA, GL_UNSIGNED_BYTE, bitmap.scanline(0));
  107. verify_no_error();
  108. }
  109. void delete_texture(Texture const& texture)
  110. {
  111. glDeleteTextures(1, &texture.id);
  112. verify_no_error();
  113. }
  114. void set_uniform(Uniform const& uniform, float value1, float value2, float value3, float value4)
  115. {
  116. glUniform4f(uniform.id, value1, value2, value3, value4);
  117. verify_no_error();
  118. }
  119. void set_vertex_attribute(VertexAttribute const& attribute, u32 offset, int number_of_components)
  120. {
  121. glVertexAttribPointer(attribute.id, number_of_components, GL_FLOAT, GL_FALSE, number_of_components * sizeof(float), reinterpret_cast<void*>(offset));
  122. glEnableVertexAttribArray(attribute.id);
  123. verify_no_error();
  124. }
  125. void set_texture_scale_mode(ScalingMode scaling_mode)
  126. {
  127. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, scaling_mode == ScalingMode::Nearest ? GL_NEAREST : GL_LINEAR);
  128. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, scaling_mode == ScalingMode::Nearest ? GL_NEAREST : GL_LINEAR);
  129. verify_no_error();
  130. }
  131. void clear_color(Gfx::Color const& color)
  132. {
  133. glClearColor(color.red() / 255.0f, color.green() / 255.0f, color.blue() / 255.0f, color.alpha() / 255.0f);
  134. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  135. verify_no_error();
  136. }
  137. void draw_arrays(DrawPrimitive draw_primitive, size_t count)
  138. {
  139. GLenum mode = GL_TRIANGLES;
  140. if (draw_primitive == DrawPrimitive::TriangleFan)
  141. mode = GL_TRIANGLE_FAN;
  142. glDrawArrays(mode, 0, count);
  143. verify_no_error();
  144. }
  145. Buffer create_buffer()
  146. {
  147. GLuint buffer;
  148. glGenBuffers(1, &buffer);
  149. verify_no_error();
  150. return { buffer };
  151. }
  152. void bind_buffer(Buffer const& buffer)
  153. {
  154. glBindBuffer(GL_ARRAY_BUFFER, buffer.id);
  155. verify_no_error();
  156. }
  157. void upload_to_buffer(Buffer const& buffer, Span<float> values)
  158. {
  159. glBindBuffer(GL_ARRAY_BUFFER, buffer.id);
  160. glBufferData(GL_ARRAY_BUFFER, values.size() * sizeof(float), values.data(), GL_STATIC_DRAW);
  161. verify_no_error();
  162. }
  163. void delete_buffer(Buffer const& buffer)
  164. {
  165. glDeleteBuffers(1, &buffer.id);
  166. verify_no_error();
  167. }
  168. VertexArray create_vertex_array()
  169. {
  170. GLuint vertex_array;
  171. glGenVertexArrays(1, &vertex_array);
  172. verify_no_error();
  173. return { vertex_array };
  174. }
  175. void bind_vertex_array(VertexArray const& vertex_array)
  176. {
  177. glBindVertexArray(vertex_array.id);
  178. verify_no_error();
  179. }
  180. void delete_vertex_array(VertexArray const& vertex_array)
  181. {
  182. glDeleteVertexArrays(1, &vertex_array.id);
  183. verify_no_error();
  184. }
  185. Framebuffer create_framebuffer(Gfx::IntSize size)
  186. {
  187. GLuint texture;
  188. glGenTextures(1, &texture);
  189. glBindTexture(GL_TEXTURE_2D, texture);
  190. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size.width(), size.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
  191. GLuint fbo;
  192. glGenFramebuffers(1, &fbo);
  193. glBindFramebuffer(GL_FRAMEBUFFER, fbo);
  194. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
  195. if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
  196. VERIFY_NOT_REACHED();
  197. }
  198. verify_no_error();
  199. return { fbo, texture };
  200. }
  201. void bind_framebuffer(Framebuffer const& framebuffer)
  202. {
  203. glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.fbo_id);
  204. verify_no_error();
  205. }
  206. void delete_framebuffer(Framebuffer const& framebuffer)
  207. {
  208. glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.fbo_id);
  209. glDeleteFramebuffers(1, &framebuffer.fbo_id);
  210. glDeleteTextures(1, &framebuffer.texture_id);
  211. verify_no_error();
  212. }
  213. }