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