1 /******************************************************************************
2 Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16 ******************************************************************************/
17
18 #pragma once
19
20 #include <util/darray.h>
21 #include <util/threading.h>
22 #include <graphics/graphics.h>
23 #include <graphics/device-exports.h>
24 #include <graphics/matrix4.h>
25
26 #include <glad/glad.h>
27
28 #include "gl-helpers.h"
29
30 struct gl_platform;
31 struct gl_windowinfo;
32
33 enum copy_type { COPY_TYPE_ARB, COPY_TYPE_NV, COPY_TYPE_FBO_BLIT };
34
convert_gs_format(enum gs_color_format format)35 static inline GLenum convert_gs_format(enum gs_color_format format)
36 {
37 switch (format) {
38 case GS_A8:
39 return GL_RED;
40 case GS_R8:
41 return GL_RED;
42 case GS_RGBA:
43 return GL_RGBA;
44 case GS_BGRX:
45 return GL_BGRA;
46 case GS_BGRA:
47 return GL_BGRA;
48 case GS_R10G10B10A2:
49 return GL_RGBA;
50 case GS_RGBA16:
51 return GL_RGBA;
52 case GS_R16:
53 return GL_RED;
54 case GS_RGBA16F:
55 return GL_RGBA;
56 case GS_RGBA32F:
57 return GL_RGBA;
58 case GS_RG16F:
59 return GL_RG;
60 case GS_RG32F:
61 return GL_RG;
62 case GS_R8G8:
63 return GL_RG;
64 case GS_R16F:
65 return GL_RED;
66 case GS_R32F:
67 return GL_RED;
68 case GS_DXT1:
69 return GL_RGB;
70 case GS_DXT3:
71 return GL_RGBA;
72 case GS_DXT5:
73 return GL_RGBA;
74 case GS_RGBA_UNORM:
75 return GL_RGBA;
76 case GS_BGRX_UNORM:
77 return GL_BGRA;
78 case GS_BGRA_UNORM:
79 return GL_BGRA;
80 case GS_UNKNOWN:
81 return 0;
82 }
83
84 return 0;
85 }
86
convert_gs_internal_format(enum gs_color_format format)87 static inline GLenum convert_gs_internal_format(enum gs_color_format format)
88 {
89 switch (format) {
90 case GS_A8:
91 return GL_R8; /* NOTE: use GL_TEXTURE_SWIZZLE_x */
92 case GS_R8:
93 return GL_R8;
94 case GS_RGBA:
95 return GL_SRGB8_ALPHA8;
96 case GS_BGRX:
97 return GL_SRGB8;
98 case GS_BGRA:
99 return GL_SRGB8_ALPHA8;
100 case GS_R10G10B10A2:
101 return GL_RGB10_A2;
102 case GS_RGBA16:
103 return GL_RGBA16;
104 case GS_R16:
105 return GL_R16;
106 case GS_RGBA16F:
107 return GL_RGBA16F;
108 case GS_RGBA32F:
109 return GL_RGBA32F;
110 case GS_RG16F:
111 return GL_RG16F;
112 case GS_RG32F:
113 return GL_RG32F;
114 case GS_R8G8:
115 return GL_RG8;
116 case GS_R16F:
117 return GL_R16F;
118 case GS_R32F:
119 return GL_R32F;
120 case GS_DXT1:
121 return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
122 case GS_DXT3:
123 return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
124 case GS_DXT5:
125 return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
126 case GS_RGBA_UNORM:
127 return GL_RGBA;
128 case GS_BGRX_UNORM:
129 return GL_RGB;
130 case GS_BGRA_UNORM:
131 return GL_RGBA;
132 case GS_UNKNOWN:
133 return 0;
134 }
135
136 return 0;
137 }
138
get_gl_format_type(enum gs_color_format format)139 static inline GLenum get_gl_format_type(enum gs_color_format format)
140 {
141 switch (format) {
142 case GS_A8:
143 return GL_UNSIGNED_BYTE;
144 case GS_R8:
145 return GL_UNSIGNED_BYTE;
146 case GS_RGBA:
147 return GL_UNSIGNED_BYTE;
148 case GS_BGRX:
149 return GL_UNSIGNED_BYTE;
150 case GS_BGRA:
151 return GL_UNSIGNED_BYTE;
152 case GS_R10G10B10A2:
153 return GL_UNSIGNED_INT_2_10_10_10_REV;
154 case GS_RGBA16:
155 return GL_UNSIGNED_SHORT;
156 case GS_R16:
157 return GL_UNSIGNED_SHORT;
158 case GS_RGBA16F:
159 return GL_HALF_FLOAT;
160 case GS_RGBA32F:
161 return GL_FLOAT;
162 case GS_RG16F:
163 return GL_HALF_FLOAT;
164 case GS_RG32F:
165 return GL_FLOAT;
166 case GS_R8G8:
167 return GL_UNSIGNED_BYTE;
168 case GS_R16F:
169 return GL_HALF_FLOAT;
170 case GS_R32F:
171 return GL_FLOAT;
172 case GS_DXT1:
173 return GL_UNSIGNED_BYTE;
174 case GS_DXT3:
175 return GL_UNSIGNED_BYTE;
176 case GS_DXT5:
177 return GL_UNSIGNED_BYTE;
178 case GS_RGBA_UNORM:
179 return GL_UNSIGNED_BYTE;
180 case GS_BGRX_UNORM:
181 return GL_UNSIGNED_BYTE;
182 case GS_BGRA_UNORM:
183 return GL_UNSIGNED_BYTE;
184 case GS_UNKNOWN:
185 return 0;
186 }
187
188 return GL_UNSIGNED_BYTE;
189 }
190
convert_zstencil_format(enum gs_zstencil_format format)191 static inline GLenum convert_zstencil_format(enum gs_zstencil_format format)
192 {
193 switch (format) {
194 case GS_Z16:
195 return GL_DEPTH_COMPONENT16;
196 case GS_Z24_S8:
197 return GL_DEPTH24_STENCIL8;
198 case GS_Z32F:
199 return GL_DEPTH_COMPONENT32F;
200 case GS_Z32F_S8X24:
201 return GL_DEPTH32F_STENCIL8;
202 case GS_ZS_NONE:
203 return 0;
204 }
205
206 return 0;
207 }
208
convert_gs_depth_test(enum gs_depth_test test)209 static inline GLenum convert_gs_depth_test(enum gs_depth_test test)
210 {
211 switch (test) {
212 case GS_NEVER:
213 return GL_NEVER;
214 case GS_LESS:
215 return GL_LESS;
216 case GS_LEQUAL:
217 return GL_LEQUAL;
218 case GS_EQUAL:
219 return GL_EQUAL;
220 case GS_GEQUAL:
221 return GL_GEQUAL;
222 case GS_GREATER:
223 return GL_GREATER;
224 case GS_NOTEQUAL:
225 return GL_NOTEQUAL;
226 case GS_ALWAYS:
227 return GL_ALWAYS;
228 }
229
230 return GL_NEVER;
231 }
232
convert_gs_stencil_op(enum gs_stencil_op_type op)233 static inline GLenum convert_gs_stencil_op(enum gs_stencil_op_type op)
234 {
235 switch (op) {
236 case GS_KEEP:
237 return GL_KEEP;
238 case GS_ZERO:
239 return GL_ZERO;
240 case GS_REPLACE:
241 return GL_REPLACE;
242 case GS_INCR:
243 return GL_INCR;
244 case GS_DECR:
245 return GL_DECR;
246 case GS_INVERT:
247 return GL_INVERT;
248 }
249
250 return GL_KEEP;
251 }
252
convert_gs_stencil_side(enum gs_stencil_side side)253 static inline GLenum convert_gs_stencil_side(enum gs_stencil_side side)
254 {
255 switch (side) {
256 case GS_STENCIL_FRONT:
257 return GL_FRONT;
258 case GS_STENCIL_BACK:
259 return GL_BACK;
260 case GS_STENCIL_BOTH:
261 return GL_FRONT_AND_BACK;
262 }
263
264 return GL_FRONT;
265 }
266
convert_gs_blend_type(enum gs_blend_type type)267 static inline GLenum convert_gs_blend_type(enum gs_blend_type type)
268 {
269 switch (type) {
270 case GS_BLEND_ZERO:
271 return GL_ZERO;
272 case GS_BLEND_ONE:
273 return GL_ONE;
274 case GS_BLEND_SRCCOLOR:
275 return GL_SRC_COLOR;
276 case GS_BLEND_INVSRCCOLOR:
277 return GL_ONE_MINUS_SRC_COLOR;
278 case GS_BLEND_SRCALPHA:
279 return GL_SRC_ALPHA;
280 case GS_BLEND_INVSRCALPHA:
281 return GL_ONE_MINUS_SRC_ALPHA;
282 case GS_BLEND_DSTCOLOR:
283 return GL_DST_COLOR;
284 case GS_BLEND_INVDSTCOLOR:
285 return GL_ONE_MINUS_DST_COLOR;
286 case GS_BLEND_DSTALPHA:
287 return GL_DST_ALPHA;
288 case GS_BLEND_INVDSTALPHA:
289 return GL_ONE_MINUS_DST_ALPHA;
290 case GS_BLEND_SRCALPHASAT:
291 return GL_SRC_ALPHA_SATURATE;
292 }
293
294 return GL_ONE;
295 }
296
convert_shader_type(enum gs_shader_type type)297 static inline GLenum convert_shader_type(enum gs_shader_type type)
298 {
299 switch (type) {
300 case GS_SHADER_VERTEX:
301 return GL_VERTEX_SHADER;
302 case GS_SHADER_PIXEL:
303 return GL_FRAGMENT_SHADER;
304 }
305
306 return GL_VERTEX_SHADER;
307 }
308
convert_filter(enum gs_sample_filter filter,GLint * min_filter,GLint * mag_filter)309 static inline void convert_filter(enum gs_sample_filter filter,
310 GLint *min_filter, GLint *mag_filter)
311 {
312 switch (filter) {
313 case GS_FILTER_POINT:
314 *min_filter = GL_NEAREST_MIPMAP_NEAREST;
315 *mag_filter = GL_NEAREST;
316 return;
317 case GS_FILTER_LINEAR:
318 *min_filter = GL_LINEAR_MIPMAP_LINEAR;
319 *mag_filter = GL_LINEAR;
320 return;
321 case GS_FILTER_MIN_MAG_POINT_MIP_LINEAR:
322 *min_filter = GL_NEAREST_MIPMAP_LINEAR;
323 *mag_filter = GL_NEAREST;
324 return;
325 case GS_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT:
326 *min_filter = GL_NEAREST_MIPMAP_NEAREST;
327 *mag_filter = GL_LINEAR;
328 return;
329 case GS_FILTER_MIN_POINT_MAG_MIP_LINEAR:
330 *min_filter = GL_NEAREST_MIPMAP_LINEAR;
331 *mag_filter = GL_LINEAR;
332 return;
333 case GS_FILTER_MIN_LINEAR_MAG_MIP_POINT:
334 *min_filter = GL_LINEAR_MIPMAP_NEAREST;
335 *mag_filter = GL_NEAREST;
336 return;
337 case GS_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR:
338 *min_filter = GL_LINEAR_MIPMAP_LINEAR;
339 *mag_filter = GL_NEAREST;
340 return;
341 case GS_FILTER_MIN_MAG_LINEAR_MIP_POINT:
342 *min_filter = GL_LINEAR_MIPMAP_NEAREST;
343 *mag_filter = GL_LINEAR;
344 return;
345 case GS_FILTER_ANISOTROPIC:
346 *min_filter = GL_LINEAR_MIPMAP_LINEAR;
347 *mag_filter = GL_LINEAR;
348 return;
349 }
350
351 *min_filter = GL_NEAREST_MIPMAP_NEAREST;
352 *mag_filter = GL_NEAREST;
353 }
354
convert_address_mode(enum gs_address_mode mode)355 static inline GLint convert_address_mode(enum gs_address_mode mode)
356 {
357 switch (mode) {
358 case GS_ADDRESS_WRAP:
359 return GL_REPEAT;
360 case GS_ADDRESS_CLAMP:
361 return GL_CLAMP_TO_EDGE;
362 case GS_ADDRESS_MIRROR:
363 return GL_MIRRORED_REPEAT;
364 case GS_ADDRESS_BORDER:
365 return GL_CLAMP_TO_BORDER;
366 case GS_ADDRESS_MIRRORONCE:
367 return GL_MIRROR_CLAMP_EXT;
368 }
369
370 return GL_REPEAT;
371 }
372
convert_gs_topology(enum gs_draw_mode mode)373 static inline GLenum convert_gs_topology(enum gs_draw_mode mode)
374 {
375 switch (mode) {
376 case GS_POINTS:
377 return GL_POINTS;
378 case GS_LINES:
379 return GL_LINES;
380 case GS_LINESTRIP:
381 return GL_LINE_STRIP;
382 case GS_TRIS:
383 return GL_TRIANGLES;
384 case GS_TRISTRIP:
385 return GL_TRIANGLE_STRIP;
386 }
387
388 return GL_POINTS;
389 }
390
391 extern void convert_sampler_info(struct gs_sampler_state *sampler,
392 const struct gs_sampler_info *info);
393
394 struct gs_sampler_state {
395 gs_device_t *device;
396 volatile long ref;
397
398 GLint min_filter;
399 GLint mag_filter;
400 GLint address_u;
401 GLint address_v;
402 GLint address_w;
403 GLint max_anisotropy;
404 };
405
samplerstate_addref(gs_samplerstate_t * ss)406 static inline void samplerstate_addref(gs_samplerstate_t *ss)
407 {
408 os_atomic_inc_long(&ss->ref);
409 }
410
samplerstate_release(gs_samplerstate_t * ss)411 static inline void samplerstate_release(gs_samplerstate_t *ss)
412 {
413 if (os_atomic_dec_long(&ss->ref) == 0)
414 bfree(ss);
415 }
416
417 struct gs_timer {
418 GLuint queries[2];
419 };
420
421 struct gs_shader_param {
422 enum gs_shader_param_type type;
423
424 char *name;
425 gs_shader_t *shader;
426 gs_samplerstate_t *next_sampler;
427 GLint texture_id;
428 size_t sampler_id;
429 int array_count;
430
431 struct gs_texture *texture;
432 bool srgb;
433
434 DARRAY(uint8_t) cur_value;
435 DARRAY(uint8_t) def_value;
436 bool changed;
437 };
438
439 enum attrib_type {
440 ATTRIB_POSITION,
441 ATTRIB_NORMAL,
442 ATTRIB_TANGENT,
443 ATTRIB_COLOR,
444 ATTRIB_TEXCOORD,
445 ATTRIB_TARGET
446 };
447
448 struct shader_attrib {
449 char *name;
450 size_t index;
451 enum attrib_type type;
452 };
453
454 struct gs_shader {
455 gs_device_t *device;
456 enum gs_shader_type type;
457 GLuint obj;
458
459 struct gs_shader_param *viewproj;
460 struct gs_shader_param *world;
461
462 DARRAY(struct shader_attrib) attribs;
463 DARRAY(struct gs_shader_param) params;
464 DARRAY(gs_samplerstate_t *) samplers;
465 };
466
467 struct program_param {
468 GLint obj;
469 struct gs_shader_param *param;
470 };
471
472 struct gs_program {
473 gs_device_t *device;
474 GLuint obj;
475 struct gs_shader *vertex_shader;
476 struct gs_shader *pixel_shader;
477
478 DARRAY(struct program_param) params;
479 DARRAY(GLint) attribs;
480
481 struct gs_program **prev_next;
482 struct gs_program *next;
483 };
484
485 extern struct gs_program *gs_program_create(struct gs_device *device);
486 extern void gs_program_destroy(struct gs_program *program);
487 extern void program_update_params(struct gs_program *shader);
488
489 struct gs_vertex_buffer {
490 GLuint vao;
491 GLuint vertex_buffer;
492 GLuint normal_buffer;
493 GLuint tangent_buffer;
494 GLuint color_buffer;
495 DARRAY(GLuint) uv_buffers;
496 DARRAY(size_t) uv_sizes;
497
498 gs_device_t *device;
499 size_t num;
500 bool dynamic;
501 struct gs_vb_data *data;
502 };
503
504 extern bool load_vb_buffers(struct gs_program *program,
505 struct gs_vertex_buffer *vb,
506 struct gs_index_buffer *ib);
507
508 struct gs_index_buffer {
509 GLuint buffer;
510 enum gs_index_type type;
511 GLuint gl_type;
512
513 gs_device_t *device;
514 void *data;
515 size_t num;
516 size_t width;
517 size_t size;
518 bool dynamic;
519 };
520
521 struct gs_texture {
522 gs_device_t *device;
523 enum gs_texture_type type;
524 enum gs_color_format format;
525 GLenum gl_format;
526 GLenum gl_target;
527 GLenum gl_internal_format;
528 GLenum gl_type;
529 GLuint texture;
530 uint32_t levels;
531 bool is_dynamic;
532 bool is_render_target;
533 bool is_dummy;
534 bool gen_mipmaps;
535
536 gs_samplerstate_t *cur_sampler;
537 struct fbo_info *fbo;
538 };
539
540 struct gs_texture_2d {
541 struct gs_texture base;
542
543 uint32_t width;
544 uint32_t height;
545 bool gen_mipmaps;
546 GLuint unpack_buffer;
547 };
548
549 struct gs_texture_3d {
550 struct gs_texture base;
551
552 uint32_t width;
553 uint32_t height;
554 uint32_t depth;
555 bool gen_mipmaps;
556 GLuint unpack_buffer;
557 };
558
559 struct gs_texture_cube {
560 struct gs_texture base;
561
562 uint32_t size;
563 };
564
565 struct gs_stage_surface {
566 gs_device_t *device;
567
568 enum gs_color_format format;
569 uint32_t width;
570 uint32_t height;
571
572 uint32_t bytes_per_pixel;
573 GLenum gl_format;
574 GLint gl_internal_format;
575 GLenum gl_type;
576 GLuint pack_buffer;
577 };
578
579 struct gs_zstencil_buffer {
580 gs_device_t *device;
581 GLuint buffer;
582 GLuint attachment;
583 GLenum format;
584 };
585
586 struct gs_swap_chain {
587 gs_device_t *device;
588 struct gl_windowinfo *wi;
589 struct gs_init_data info;
590 };
591
592 struct fbo_info {
593 GLuint fbo;
594 uint32_t width;
595 uint32_t height;
596 enum gs_color_format format;
597
598 gs_texture_t *cur_render_target;
599 int cur_render_side;
600 gs_zstencil_t *cur_zstencil_buffer;
601 };
602
fbo_info_destroy(struct fbo_info * fbo)603 static inline void fbo_info_destroy(struct fbo_info *fbo)
604 {
605 if (fbo) {
606 glDeleteFramebuffers(1, &fbo->fbo);
607 gl_success("glDeleteFramebuffers");
608
609 bfree(fbo);
610 }
611 }
612
613 struct gs_device {
614 struct gl_platform *plat;
615 enum copy_type copy_type;
616
617 GLuint empty_vao;
618 gs_samplerstate_t *raw_load_sampler;
619
620 gs_texture_t *cur_render_target;
621 gs_zstencil_t *cur_zstencil_buffer;
622 int cur_render_side;
623 gs_texture_t *cur_textures[GS_MAX_TEXTURES];
624 gs_samplerstate_t *cur_samplers[GS_MAX_TEXTURES];
625 gs_vertbuffer_t *cur_vertex_buffer;
626 gs_indexbuffer_t *cur_index_buffer;
627 gs_shader_t *cur_vertex_shader;
628 gs_shader_t *cur_pixel_shader;
629 gs_swapchain_t *cur_swap;
630 struct gs_program *cur_program;
631
632 struct gs_program *first_program;
633
634 enum gs_cull_mode cur_cull_mode;
635 struct gs_rect cur_viewport;
636
637 struct matrix4 cur_proj;
638 struct matrix4 cur_view;
639 struct matrix4 cur_viewproj;
640
641 DARRAY(struct matrix4) proj_stack;
642
643 struct fbo_info *cur_fbo;
644 };
645
646 extern struct fbo_info *get_fbo(gs_texture_t *tex, uint32_t width,
647 uint32_t height);
648
649 extern void gl_update(gs_device_t *device);
650 extern void gl_clear_context(gs_device_t *device);
651
652 extern struct gl_platform *gl_platform_create(gs_device_t *device,
653 uint32_t adapter);
654 extern void gl_platform_destroy(struct gl_platform *platform);
655
656 extern bool gl_platform_init_swapchain(struct gs_swap_chain *swap);
657 extern void gl_platform_cleanup_swapchain(struct gs_swap_chain *swap);
658
659 extern struct gl_windowinfo *
660 gl_windowinfo_create(const struct gs_init_data *info);
661 extern void gl_windowinfo_destroy(struct gl_windowinfo *wi);
662
663 extern void gl_getclientsize(const struct gs_swap_chain *swap, uint32_t *width,
664 uint32_t *height);
665