1 /*
2 * This software is licensed under the terms of the MIT License.
3 * See COPYING for further information.
4 * ---
5 * Copyright (c) 2011-2019, Lukas Weber <laochailan@web.de>.
6 * Copyright (c) 2012-2019, Andrei Alexeyev <akari@taisei-project.org>.
7 */
8
9 #include "taisei.h"
10
11 #include "gl33.h"
12 #include "../api.h"
13 #include "../common/matstack.h"
14 #include "../common/backend.h"
15 #include "../common/sprite_batch.h"
16 #include "texture.h"
17 #include "shader_object.h"
18 #include "shader_program.h"
19 #include "framebuffer.h"
20 #include "common_buffer.h"
21 #include "vertex_buffer.h"
22 #include "index_buffer.h"
23 #include "vertex_array.h"
24 #include "../glcommon/debug.h"
25 #include "../glcommon/vtable.h"
26 #include "resource/resource.h"
27 #include "resource/model.h"
28 #include "util/glm.h"
29 #include "util/env.h"
30
31 // #define GL33_DEBUG_TEXUNITS
32
33 typedef struct TextureUnit {
34 LIST_INTERFACE(struct TextureUnit);
35
36 struct {
37 GLuint gl_handle;
38 Texture *active;
39 Texture *pending;
40 bool locked;
41 } tex2d;
42 } TextureUnit;
43
44 #define TU_INDEX(unit) ((ptrdiff_t)((unit) - R.texunits.array))
45
46 static struct {
47 struct {
48 TextureUnit *array;
49 LIST_ANCHOR(TextureUnit) list;
50 TextureUnit *active;
51 TextureUnit *pending;
52 GLint limit;
53 } texunits;
54
55 struct {
56 Framebuffer *active;
57 Framebuffer *pending;
58 } framebuffer;
59
60 struct {
61 GLuint active;
62 GLuint pending;
63 } buffer_objects[GL33_NUM_BUFFER_BINDINGS];
64
65 struct {
66 GLuint active;
67 GLuint pending;
68 } vao;
69
70 struct {
71 GLuint gl_prog;
72 ShaderProgram *active;
73 ShaderProgram *pending;
74 } progs;
75
76 struct {
77 struct {
78 BlendMode active;
79 BlendMode pending;
80 } mode;
81 bool enabled;
82 } blend;
83
84 struct {
85 struct {
86 CullFaceMode active;
87 CullFaceMode pending;
88 } mode;
89 } cull_face;
90
91 struct {
92 struct {
93 DepthTestFunc active;
94 DepthTestFunc pending;
95 } func;
96 } depth_test;
97
98 struct {
99 r_capability_bits_t active;
100 r_capability_bits_t pending;
101 } capabilities;
102
103 struct {
104 FloatRect active;
105 FloatRect default_framebuffer;
106 } viewport;
107
108 Color color;
109 Color clear_color;
110 float clear_depth;
111 r_feature_bits_t features;
112
113 SDL_GLContext *gl_context;
114 SDL_Window *window;
115
116 #ifdef GL33_DRAW_STATS
117 struct {
118 hrtime_t last_draw;
119 hrtime_t draw_time;
120 uint draw_calls;
121 } stats;
122 #endif
123 } R;
124
125 /*
126 * Internal functions
127 */
128
blendop_to_gl_blendop(BlendOp op)129 static GLenum blendop_to_gl_blendop(BlendOp op) {
130 switch(op) {
131 case BLENDOP_ADD: return GL_FUNC_ADD;
132 case BLENDOP_SUB: return GL_FUNC_SUBTRACT;
133 case BLENDOP_REV_SUB: return GL_FUNC_REVERSE_SUBTRACT;
134 case BLENDOP_MAX: return GL_MAX;
135 case BLENDOP_MIN: return GL_MIN;
136 }
137
138 UNREACHABLE;
139 }
140
blendfactor_to_gl_blendfactor(BlendFactor factor)141 static GLenum blendfactor_to_gl_blendfactor(BlendFactor factor) {
142 switch(factor) {
143 case BLENDFACTOR_DST_ALPHA: return GL_DST_ALPHA;
144 case BLENDFACTOR_INV_DST_ALPHA: return GL_ONE_MINUS_DST_ALPHA;
145 case BLENDFACTOR_DST_COLOR: return GL_DST_COLOR;
146 case BLENDFACTOR_INV_DST_COLOR: return GL_ONE_MINUS_DST_COLOR;
147 case BLENDFACTOR_INV_SRC_ALPHA: return GL_ONE_MINUS_SRC_ALPHA;
148 case BLENDFACTOR_INV_SRC_COLOR: return GL_ONE_MINUS_SRC_COLOR;
149 case BLENDFACTOR_ONE: return GL_ONE;
150 case BLENDFACTOR_SRC_ALPHA: return GL_SRC_ALPHA;
151 case BLENDFACTOR_SRC_COLOR: return GL_SRC_COLOR;
152 case BLENDFACTOR_ZERO: return GL_ZERO;
153 }
154
155 UNREACHABLE;
156 }
157
r_cull_to_gl_cull(CullFaceMode mode)158 static inline GLenum r_cull_to_gl_cull(CullFaceMode mode) {
159 switch(mode) {
160 case CULL_BACK:
161 return GL_BACK;
162
163 case CULL_FRONT:
164 return GL_FRONT;
165
166 case CULL_BOTH:
167 return GL_FRONT_AND_BACK;
168
169 default: UNREACHABLE;
170 }
171 }
172
gl33_stats_pre_draw(void)173 static inline void gl33_stats_pre_draw(void) {
174 #ifdef GL33_DRAW_STATS
175 R.stats.last_draw = time_get();
176 R.stats.draw_calls++;
177 #endif
178 }
179
gl33_stats_post_draw(void)180 static inline void gl33_stats_post_draw(void) {
181 #ifdef GL33_DRAW_STATS
182 R.stats.draw_time += (time_get() - R.stats.last_draw);
183 #endif
184 }
185
gl33_stats_post_frame(void)186 static inline void gl33_stats_post_frame(void) {
187 #ifdef GL33_DRAW_STATS
188 log_debug("%.20gs spent in %u draw calls", (double)R.stats.draw_time, R.stats.draw_calls);
189 memset(&R.stats, 0, sizeof(R.stats));
190 #endif
191 }
192
gl33_init_texunits(void)193 static void gl33_init_texunits(void) {
194 GLint texunits_available, texunits_capped, texunits_max, texunits_min = 4;
195 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &texunits_available);
196
197 if(texunits_available < texunits_min) {
198 log_fatal("GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS is %i; at least %i is expected.", texunits_available, texunits_min);
199 }
200
201 texunits_max = env_get_int("GL33_MAX_NUM_TEXUNITS", 32);
202
203 if(texunits_max == 0) {
204 texunits_max = texunits_available;
205 } else {
206 texunits_max = iclamp(texunits_max, texunits_min, texunits_available);
207 }
208
209 texunits_capped = imin(texunits_max, texunits_available);
210 R.texunits.limit = env_get_int("GL33_NUM_TEXUNITS", texunits_capped);
211
212 if(R.texunits.limit == 0) {
213 R.texunits.limit = texunits_available;
214 } else {
215 R.texunits.limit = iclamp(R.texunits.limit, texunits_min, texunits_available);
216 }
217
218 R.texunits.array = calloc(R.texunits.limit, sizeof(TextureUnit));
219 R.texunits.active = R.texunits.array;
220
221 for(int i = 0; i < R.texunits.limit; ++i) {
222 TextureUnit *u = R.texunits.array + i;
223 alist_append(&R.texunits.list, u);
224 }
225
226 log_info("Using %i texturing units (%i available)", R.texunits.limit, texunits_available);
227 }
228
gl33_get_viewport(FloatRect * vp)229 static void gl33_get_viewport(FloatRect *vp) {
230 IntRect vp_int;
231 glGetIntegerv(GL_VIEWPORT, &vp_int.x);
232 vp->x = vp_int.x;
233 vp->y = vp_int.y;
234 vp->w = vp_int.w;
235 vp->h = vp_int.h;
236 }
237
gl33_set_viewport(const FloatRect * vp)238 static void gl33_set_viewport(const FloatRect *vp) {
239 glViewport(vp->x, vp->y, vp->w, vp->h);
240 }
241
242 #ifndef STATIC_GLES3
gl41_get_viewport(FloatRect * vp)243 static void gl41_get_viewport(FloatRect *vp) {
244 glGetFloati_v(GL_VIEWPORT, 0, &vp->x);
245 }
246
gl41_set_viewport(const FloatRect * vp)247 static void gl41_set_viewport(const FloatRect *vp) {
248 glViewportIndexedfv(0, &vp->x);
249 }
250 #endif
251
gl33_init_context(SDL_Window * window)252 static void gl33_init_context(SDL_Window *window) {
253 R.gl_context = SDL_GL_CreateContext(window);
254
255 if(!R.gl_context) {
256 log_fatal("Could not create the OpenGL context: %s", SDL_GetError());
257 }
258
259 glcommon_load_functions();
260 glcommon_check_capabilities();
261
262 if(glcommon_debug_requested()) {
263 glcommon_debug_enable();
264 }
265
266 gl33_init_texunits();
267 gl33_set_clear_depth(1);
268 gl33_set_clear_color(RGBA(0, 0, 0, 0));
269
270 #ifdef STATIC_GLES3
271 GLVT.get_viewport = gl33_get_viewport;
272 GLVT.set_viewport = gl33_set_viewport;
273 #else
274 if(glext.viewport_array) {
275 GLVT.get_viewport = gl41_get_viewport;
276 GLVT.set_viewport = gl41_set_viewport;
277 } else {
278 GLVT.get_viewport = gl33_get_viewport;
279 GLVT.set_viewport = gl33_set_viewport;
280 }
281 #endif
282
283 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
284 glPixelStorei(GL_PACK_ALIGNMENT, 1);
285 GLVT.get_viewport(&R.viewport.default_framebuffer);
286
287 if(HAVE_GL_FUNC(glReadBuffer)) {
288 glReadBuffer(GL_BACK);
289 }
290
291 R.viewport.active = R.viewport.default_framebuffer;
292
293 if(glext.instanced_arrays) {
294 R.features |= r_feature_bit(RFEAT_DRAW_INSTANCED);
295 }
296
297 if(glext.depth_texture) {
298 R.features |= r_feature_bit(RFEAT_DEPTH_TEXTURE);
299 }
300
301 if(glext.draw_buffers) {
302 R.features |= r_feature_bit(RFEAT_FRAMEBUFFER_MULTIPLE_OUTPUTS);
303 }
304
305 R.features |= r_feature_bit(RFEAT_TEXTURE_BOTTOMLEFT_ORIGIN);
306
307 if(glext.clear_texture) {
308 _r_backend.funcs.texture_clear = gl44_texture_clear;
309 }
310 }
311
gl33_apply_capability(RendererCapability cap,bool value)312 static void gl33_apply_capability(RendererCapability cap, bool value) {
313 switch(cap) {
314 case RCAP_DEPTH_TEST:
315 (value ? glEnable : glDisable)(GL_DEPTH_TEST);
316 break;
317
318 case RCAP_DEPTH_WRITE:
319 glDepthMask(value);
320 break;
321
322 case RCAP_CULL_FACE:
323 (value ? glEnable : glDisable)(GL_CULL_FACE);
324 break;
325
326 default: UNREACHABLE;
327 }
328 }
329
transform_viewport_origin(Framebuffer * fb,FloatRect * vp)330 static void transform_viewport_origin(Framebuffer *fb, FloatRect *vp) {
331 int fb_height = 0;
332
333 if(fb == NULL) {
334 SDL_Window *win = SDL_GL_GetCurrentWindow();
335 assume(win != NULL);
336 SDL_GL_GetDrawableSize(win, NULL, &fb_height);
337 } else {
338 for(FramebufferAttachment a = FRAMEBUFFER_ATTACH_COLOR0; a < FRAMEBUFFER_MAX_ATTACHMENTS; ++a) {
339 if(fb->attachments[a] != NULL) {
340 fb_height = fb->attachments[a]->params.height;
341 break;
342 }
343 }
344 }
345
346 assert(fb_height > 0);
347 vp->y = fb_height - vp->y - vp->h;
348 }
349
get_framebuffer_viewport(Framebuffer * fb)350 static inline FloatRect* get_framebuffer_viewport(Framebuffer *fb) {
351 if(fb == NULL) {
352 return &R.viewport.default_framebuffer;
353 }
354
355 return &fb->viewport;
356 }
357
gl33_sync_viewport(void)358 static void gl33_sync_viewport(void) {
359 FloatRect *vp = get_framebuffer_viewport(R.framebuffer.pending);
360
361 if(memcmp(&R.viewport.active, vp, sizeof(R.viewport.active))) {
362 R.viewport.active = *vp;
363 GLVT.set_viewport(vp);
364 }
365 }
366
gl33_sync_state(void)367 static void gl33_sync_state(void) {
368 gl33_sync_capabilities();
369 gl33_sync_shader();
370 r_uniform_mat4("r_modelViewMatrix", *_r_matrices.modelview.head);
371 r_uniform_mat4("r_projectionMatrix", *_r_matrices.projection.head);
372 r_uniform_mat4("r_textureMatrix", *_r_matrices.texture.head);
373 r_uniform_vec4_rgba("r_color", &R.color);
374 gl33_sync_uniforms(R.progs.active);
375 gl33_sync_texunits(true);
376 gl33_sync_framebuffer();
377 gl33_sync_viewport();
378 gl33_sync_vao();
379 gl33_sync_blend_mode();
380
381 if(R.capabilities.active & r_capability_bit(RCAP_CULL_FACE)) {
382 gl33_sync_cull_face_mode();
383 }
384
385 if(R.capabilities.active & r_capability_bit(RCAP_DEPTH_TEST)) {
386 gl33_sync_depth_test_func();
387 }
388 }
389
390 /*
391 * Exported functions
392 */
393
gl33_prim_to_gl_prim(Primitive prim)394 GLenum gl33_prim_to_gl_prim(Primitive prim) {
395 static GLenum map[] = {
396 [PRIM_POINTS] = GL_POINTS,
397 [PRIM_LINE_STRIP] = GL_LINE_STRIP,
398 [PRIM_LINE_LOOP] = GL_LINE_LOOP,
399 [PRIM_LINES] = GL_LINES,
400 [PRIM_TRIANGLE_STRIP] = GL_TRIANGLE_STRIP,
401 [PRIM_TRIANGLES] = GL_TRIANGLES,
402 };
403
404 assert((uint)prim < sizeof(map)/sizeof(*map));
405 return map[prim];
406 }
407
gl33_sync_capabilities(void)408 void gl33_sync_capabilities(void) {
409 if(R.capabilities.active == R.capabilities.pending) {
410 return;
411 }
412
413 for(RendererCapability cap = 0; cap < NUM_RCAPS; ++cap) {
414 r_capability_bits_t flag = r_capability_bit(cap);
415 bool pending = R.capabilities.pending & flag;
416 bool active = R.capabilities.active & flag;
417
418 if(pending != active) {
419 gl33_apply_capability(cap, pending);
420 }
421 }
422
423 R.capabilities.active = R.capabilities.pending;
424 }
425
426 attr_nonnull(1)
gl33_activate_texunit(TextureUnit * unit)427 static void gl33_activate_texunit(TextureUnit *unit) {
428 assert(unit >= R.texunits.array && unit < R.texunits.array + R.texunits.limit);
429
430 if(R.texunits.active != unit) {
431 glActiveTexture(GL_TEXTURE0 + TU_INDEX(unit));
432 R.texunits.active = unit;
433 #ifdef GL33_DEBUG_TEXUNITS
434 log_debug("Activated unit %i", (uint)TU_INDEX(unit));
435 #endif
436 }
437 }
438
gl33_texunit_priority(TextureUnit * u)439 static int gl33_texunit_priority(TextureUnit *u) {
440 if(u->tex2d.locked) {
441 assert(u->tex2d.pending);
442 return 3;
443 }
444
445 if(u->tex2d.pending) {
446 return 2;
447 }
448
449 if(u->tex2d.active) {
450 return 1;
451 }
452
453 return 0;
454 }
455
gl33_texunit_priority_callback(List * elem)456 static int gl33_texunit_priority_callback(List *elem) {
457 TextureUnit *u = (TextureUnit*)elem;
458 return gl33_texunit_priority(u);
459 }
460
texture_str(Texture * tex,char * buf,size_t bufsize)461 attr_unused static void texture_str(Texture *tex, char *buf, size_t bufsize) {
462 if(tex == NULL) {
463 snprintf(buf, bufsize, "None");
464 } else {
465 snprintf(buf, bufsize, "\"%s\" (#%i; at %p)", tex->debug_label, tex->gl_handle, (void*)tex);
466 }
467 }
468
gl33_dump_texunits(void)469 attr_unused static void gl33_dump_texunits(void) {
470 log_debug("=== BEGIN DUMP ===");
471
472 for(TextureUnit *u = R.texunits.list.first; u; u = u->next) {
473 char buf1[128], buf2[128];
474 texture_str(u->tex2d.active, buf1, sizeof(buf1));
475 texture_str(u->tex2d.pending, buf2, sizeof(buf2));
476 log_debug("[Unit %u | %i] bound: %s; pending: %s", (uint)TU_INDEX(u), gl33_texunit_priority(u), buf1, buf2);
477 }
478
479 log_debug("=== END DUMP ===");
480 }
481
gl33_relocate_texuint(TextureUnit * unit)482 static void gl33_relocate_texuint(TextureUnit *unit) {
483 int prio = gl33_texunit_priority(unit);
484
485 alist_unlink(&R.texunits.list, unit);
486
487 if(prio > 1) {
488 alist_insert_at_priority_tail(&R.texunits.list, unit, prio, gl33_texunit_priority_callback);
489 } else {
490 alist_insert_at_priority_head(&R.texunits.list, unit, prio, gl33_texunit_priority_callback);
491 }
492
493 #ifdef GL33_DEBUG_TEXUNITS
494 // gl33_dump_texunits();
495 // log_debug("Relocated unit %u", (uint)TU_INDEX(unit));
496 #endif
497 }
498
499 attr_nonnull(1)
gl33_set_texunit_binding(TextureUnit * unit,Texture * tex,bool lock)500 static void gl33_set_texunit_binding(TextureUnit *unit, Texture *tex, bool lock) {
501 assert(!unit->tex2d.locked);
502
503 if(unit->tex2d.pending == tex) {
504 if(tex) {
505 tex->binding_unit = unit;
506 }
507
508 if(lock) {
509 unit->tex2d.locked = true;
510 }
511
512 // gl33_relocate_texuint(unit);
513 return;
514 }
515
516 if(unit->tex2d.pending != NULL) {
517 // assert(unit->tex2d.pending->binding_unit == unit);
518
519 if(unit->tex2d.pending->binding_unit == unit) {
520 // FIXME: should we search through the units for a matching binding,
521 // just in case another unit had the same texture bound?
522 unit->tex2d.pending->binding_unit = NULL;
523 }
524 }
525
526 unit->tex2d.pending = tex;
527
528 if(tex) {
529 tex->binding_unit = unit;
530 }
531
532 if(lock) {
533 unit->tex2d.locked = true;
534 }
535
536 gl33_relocate_texuint(unit);
537 }
538
gl33_sync_texunit(TextureUnit * unit,bool prepare_rendering,bool ensure_active)539 void gl33_sync_texunit(TextureUnit *unit, bool prepare_rendering, bool ensure_active) {
540 Texture *tex = unit->tex2d.pending;
541
542 #ifdef GL33_DEBUG_TEXUNITS
543 if(unit->tex2d.pending != unit->tex2d.active) {
544 attr_unused char buf1[128], buf2[128];
545 texture_str(unit->tex2d.active, buf1, sizeof(buf1));
546 texture_str(unit->tex2d.pending, buf2, sizeof(buf2));
547 log_debug("[Unit %u] %s ===> %s", (uint)TU_INDEX(unit), buf1, buf2);
548 }
549 #endif
550
551 if(tex == NULL) {
552 if(unit->tex2d.gl_handle != 0) {
553 gl33_activate_texunit(unit);
554 glBindTexture(GL_TEXTURE_2D, 0);
555 unit->tex2d.gl_handle = 0;
556 unit->tex2d.active = NULL;
557 gl33_relocate_texuint(unit);
558 }
559 } else if(unit->tex2d.gl_handle != tex->gl_handle) {
560 gl33_activate_texunit(unit);
561 glBindTexture(GL_TEXTURE_2D, tex->gl_handle);
562 unit->tex2d.gl_handle = tex->gl_handle;
563
564 if(unit->tex2d.active == NULL) {
565 unit->tex2d.active = tex;
566 gl33_relocate_texuint(unit);
567 } else {
568 unit->tex2d.active = tex;
569 }
570 } else if(ensure_active) {
571 gl33_activate_texunit(unit);
572 }
573
574 if(prepare_rendering && unit->tex2d.active != NULL) {
575 gl33_texture_prepare(unit->tex2d.active);
576 unit->tex2d.locked = false;
577 }
578 }
579
gl33_sync_texunits(bool prepare_rendering)580 void gl33_sync_texunits(bool prepare_rendering) {
581 for(TextureUnit *u = R.texunits.array; u < R.texunits.array + R.texunits.limit; ++u) {
582 gl33_sync_texunit(u, prepare_rendering, false);
583 }
584 }
585
gl33_sync_vao(void)586 void gl33_sync_vao(void) {
587 if(R.vao.active != R.vao.pending) {
588 R.vao.active = R.vao.pending;
589 glBindVertexArray(R.vao.active);
590 }
591 }
592
gl33_bindidx_to_glenum(BufferBindingIndex bindidx)593 GLenum gl33_bindidx_to_glenum(BufferBindingIndex bindidx) {
594 if(bindidx == GL33_BUFFER_BINDING_ELEMENT_ARRAY) {
595 return GL_ELEMENT_ARRAY_BUFFER;
596 }
597
598 static GLenum map[] = {
599 [GL33_BUFFER_BINDING_ARRAY] = GL_ARRAY_BUFFER,
600 [GL33_BUFFER_BINDING_COPY_WRITE] = GL_COPY_WRITE_BUFFER,
601 [GL33_BUFFER_BINDING_PIXEL_UNPACK] = GL_PIXEL_UNPACK_BUFFER,
602 };
603
604 static_assert(sizeof(map) == sizeof(GLenum) * GL33_NUM_BUFFER_BINDINGS, "Fix the lookup table");
605 assert((uint)bindidx < GL33_NUM_BUFFER_BINDINGS);
606 return map[bindidx];
607 }
608
gl33_sync_buffer(BufferBindingIndex bindidx)609 void gl33_sync_buffer(BufferBindingIndex bindidx) {
610 assert((uint)bindidx < GL33_NUM_BUFFER_BINDINGS);
611
612 if(R.buffer_objects[bindidx].active != R.buffer_objects[bindidx].pending) {
613 R.buffer_objects[bindidx].active = R.buffer_objects[bindidx].pending;
614 glBindBuffer(gl33_bindidx_to_glenum(bindidx), R.buffer_objects[bindidx].active);
615 }
616 }
617
gl33_sync_cull_face_mode(void)618 void gl33_sync_cull_face_mode(void) {
619 if(R.cull_face.mode.pending != R.cull_face.mode.active) {
620 GLenum glcull = r_cull_to_gl_cull(R.cull_face.mode.pending);
621 glCullFace(glcull);
622 R.cull_face.mode.active = R.cull_face.mode.pending;
623 }
624 }
625
gl33_sync_depth_test_func(void)626 void gl33_sync_depth_test_func(void) {
627 DepthTestFunc func = R.depth_test.func.pending;
628
629 static GLenum func_to_glfunc[] = {
630 [DEPTH_NEVER] = GL_NEVER,
631 [DEPTH_ALWAYS] = GL_ALWAYS,
632 [DEPTH_EQUAL] = GL_EQUAL,
633 [DEPTH_NOTEQUAL] = GL_NOTEQUAL,
634 [DEPTH_LESS] = GL_LESS,
635 [DEPTH_LEQUAL] = GL_LEQUAL,
636 [DEPTH_GREATER] = GL_GREATER,
637 [DEPTH_GEQUAL] = GL_GEQUAL,
638 };
639
640 uint32_t idx = func;
641 assert(idx < sizeof(func_to_glfunc)/sizeof(GLenum));
642
643 if(R.depth_test.func.active != func) {
644 glDepthFunc(func_to_glfunc[idx]);
645 R.depth_test.func.active = func;
646 }
647 }
648
fbo_num(Framebuffer * fb)649 static inline GLuint fbo_num(Framebuffer *fb) {
650 if(fb == NULL) {
651 return 0;
652 }
653
654 assert(fb->gl_fbo != 0);
655 return fb->gl_fbo;
656 }
657
gl33_sync_framebuffer(void)658 void gl33_sync_framebuffer(void) {
659 if(fbo_num(R.framebuffer.active) != fbo_num(R.framebuffer.pending)) {
660 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_num(R.framebuffer.pending));
661 R.framebuffer.active = R.framebuffer.pending;
662 }
663
664 if(R.framebuffer.active) {
665 gl33_framebuffer_prepare(R.framebuffer.active);
666 }
667 }
668
gl33_sync_shader(void)669 void gl33_sync_shader(void) {
670 if(R.progs.pending && R.progs.gl_prog != R.progs.pending->gl_handle) {
671 glUseProgram(R.progs.pending->gl_handle);
672 R.progs.gl_prog = R.progs.pending->gl_handle;
673 R.progs.active = R.progs.pending;
674 }
675 }
676
gl33_sync_blend_mode(void)677 void gl33_sync_blend_mode(void) {
678 BlendMode mode = R.blend.mode.pending;
679
680 if(mode == BLEND_NONE) {
681 if(R.blend.enabled) {
682 glDisable(GL_BLEND);
683 R.blend.enabled = false;
684 }
685
686 return;
687 }
688
689 if(!R.blend.enabled) {
690 R.blend.enabled = true;
691 glEnable(GL_BLEND);
692 }
693
694 if(mode != R.blend.mode.active) {
695 static UnpackedBlendMode umode;
696 r_blend_unpack(mode, &umode);
697 R.blend.mode.active = mode;
698
699 // TODO: maybe cache the funcs and factors separately,
700 // because the blend funcs change a lot less frequently.
701
702 glBlendEquationSeparate(
703 blendop_to_gl_blendop(umode.color.op),
704 blendop_to_gl_blendop(umode.alpha.op)
705 );
706
707 glBlendFuncSeparate(
708 blendfactor_to_gl_blendfactor(umode.color.src),
709 blendfactor_to_gl_blendfactor(umode.color.dst),
710 blendfactor_to_gl_blendfactor(umode.alpha.src),
711 blendfactor_to_gl_blendfactor(umode.alpha.dst)
712 );
713 }
714 }
715
gl33_bind_texture(Texture * texture,bool for_rendering,int preferred_unit)716 uint gl33_bind_texture(Texture *texture, bool for_rendering, int preferred_unit) {
717 if(glext.issues.avoid_sampler_uniform_updates && preferred_unit >= 0) {
718 assert(preferred_unit < R.texunits.limit);
719 TextureUnit *u = &R.texunits.array[preferred_unit];
720
721 if(u->tex2d.pending == texture) {
722 u->tex2d.locked |= for_rendering;
723 } else {
724 gl33_set_texunit_binding(u, texture, for_rendering);
725 }
726
727 // In this case the texture may be bound to more than one unit.
728 // This is fine though, and we just always update binding_unit to the
729 // most recent binding.
730 texture->binding_unit = u;
731 } else if(!texture->binding_unit) {
732 // assert(R.texunits.list.first->tex2d.pending != texture);
733
734 if(
735 R.texunits.list.first->tex2d.pending &&
736 R.texunits.list.first->tex2d.pending != R.texunits.list.first->tex2d.active
737 ) {
738 log_warn("Ran out of texturing units, expect rendering errors!");
739 }
740
741 gl33_set_texunit_binding(R.texunits.list.first, texture, for_rendering);
742 } else /* if(for_rendering) */ {
743 texture->binding_unit->tex2d.locked |= for_rendering;
744 gl33_relocate_texuint(texture->binding_unit);
745 }
746
747 assert(texture->binding_unit->tex2d.pending == texture);
748 return TU_INDEX(texture->binding_unit);
749 }
750
gl33_bind_buffer(BufferBindingIndex bindidx,GLuint gl_handle)751 void gl33_bind_buffer(BufferBindingIndex bindidx, GLuint gl_handle) {
752 R.buffer_objects[bindidx].pending = gl_handle;
753 }
754
gl33_bind_vao(GLuint vao)755 void gl33_bind_vao(GLuint vao) {
756 R.vao.pending = vao;
757 }
758
gl33_buffer_current(BufferBindingIndex bindidx)759 GLuint gl33_buffer_current(BufferBindingIndex bindidx) {
760 return R.buffer_objects[bindidx].pending;
761 }
762
gl33_vao_current(void)763 GLuint gl33_vao_current(void) {
764 return R.vao.pending;
765 }
766
gl33_texture_deleted(Texture * tex)767 void gl33_texture_deleted(Texture *tex) {
768 _r_sprite_batch_texture_deleted(tex);
769 gl33_unref_texture_from_samplers(tex);
770
771 for(TextureUnit *unit = R.texunits.array; unit < R.texunits.array + R.texunits.limit; ++unit) {
772 bool bump = false;
773
774 if(unit->tex2d.pending == tex) {
775 unit->tex2d.pending = NULL;
776 unit->tex2d.locked = false;
777 bump = true;
778 }
779
780 if(unit->tex2d.active == tex) {
781 assert(unit->tex2d.gl_handle == tex->gl_handle);
782 unit->tex2d.active = NULL;
783 unit->tex2d.gl_handle = 0;
784 bump = true;
785 } else {
786 assert(unit->tex2d.gl_handle != tex->gl_handle);
787 }
788
789 if(bump) {
790 gl33_relocate_texuint(unit);
791 }
792 }
793
794 if(R.buffer_objects[GL33_BUFFER_BINDING_PIXEL_UNPACK].pending == tex->pbo) {
795 R.buffer_objects[GL33_BUFFER_BINDING_PIXEL_UNPACK].pending = 0;
796 }
797
798 if(R.buffer_objects[GL33_BUFFER_BINDING_PIXEL_UNPACK].active == tex->pbo) {
799 R.buffer_objects[GL33_BUFFER_BINDING_PIXEL_UNPACK].active = 0;
800 }
801 }
802
gl33_framebuffer_deleted(Framebuffer * fb)803 void gl33_framebuffer_deleted(Framebuffer *fb) {
804 if(R.framebuffer.pending == fb) {
805 R.framebuffer.pending = NULL;
806 }
807
808 if(R.framebuffer.active == fb) {
809 R.framebuffer.active = NULL;
810 }
811 }
812
gl33_shader_deleted(ShaderProgram * prog)813 void gl33_shader_deleted(ShaderProgram *prog) {
814 if(R.progs.active == NULL) {
815 R.progs.active = NULL;
816 }
817
818 if(R.progs.pending == prog) {
819 R.progs.pending = NULL;
820 r_shader_standard();
821 }
822
823 if(R.progs.gl_prog == prog->gl_handle) {
824 R.progs.gl_prog = 0;
825 }
826 }
827
gl33_buffer_deleted(CommonBuffer * cbuf)828 void gl33_buffer_deleted(CommonBuffer *cbuf) {
829 if(R.buffer_objects[cbuf->bindidx].active == cbuf->gl_handle) {
830 R.buffer_objects[cbuf->bindidx].active = 0;
831 }
832
833 if(R.buffer_objects[cbuf->bindidx].pending == cbuf->gl_handle) {
834 R.buffer_objects[cbuf->bindidx].pending = 0;
835 }
836 }
837
gl33_vertex_buffer_deleted(VertexBuffer * vbuf)838 void gl33_vertex_buffer_deleted(VertexBuffer *vbuf) {
839 if(R.buffer_objects[GL33_BUFFER_BINDING_ARRAY].active == vbuf->cbuf.gl_handle) {
840 R.buffer_objects[GL33_BUFFER_BINDING_ARRAY].active = 0;
841 }
842
843 if(R.buffer_objects[GL33_BUFFER_BINDING_ARRAY].pending == vbuf->cbuf.gl_handle) {
844 R.buffer_objects[GL33_BUFFER_BINDING_ARRAY].pending = 0;
845 }
846 }
847
gl33_vertex_array_deleted(VertexArray * varr)848 void gl33_vertex_array_deleted(VertexArray *varr) {
849 if(R.vao.active == varr->gl_handle) {
850 R.vao.active = 0;
851 }
852
853 if(R.vao.pending == varr->gl_handle) {
854 R.vao.pending = 0;
855 }
856 }
857
858 /*
859 * Renderer interface implementation
860 */
861
gl33_init(void)862 static void gl33_init(void) {
863 SDL_GLprofile profile;
864 SDL_GLcontextFlag flags = 0;
865
866 if(env_get("TAISEI_GL33_CORE_PROFILE", true)) {
867 profile = SDL_GL_CONTEXT_PROFILE_CORE;
868 } else {
869 profile = SDL_GL_CONTEXT_PROFILE_COMPATIBILITY;
870 }
871
872 if(env_get("TAISEI_GL33_FORWARD_COMPATIBLE", true)) {
873 flags |= SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG;
874 }
875
876 int major = env_get("TAISEI_GL33_VERSION_MAJOR", 3);
877 int minor = env_get("TAISEI_GL33_VERSION_MINOR", 3);
878
879 glcommon_setup_attributes(profile, major, minor, flags);
880 glcommon_load_library();
881 }
882
gl33_post_init(void)883 static void gl33_post_init(void) {
884
885 }
886
gl33_shutdown(void)887 static void gl33_shutdown(void) {
888 glcommon_unload_library();
889 SDL_GL_DeleteContext(R.gl_context);
890 }
891
gl33_create_window(const char * title,int x,int y,int w,int h,uint32_t flags)892 static SDL_Window* gl33_create_window(const char *title, int x, int y, int w, int h, uint32_t flags) {
893 SDL_Window *window = SDL_CreateWindow(title, x, y, w, h, flags | SDL_WINDOW_OPENGL);
894
895 if(R.gl_context) {
896 SDL_GL_MakeCurrent(window, R.gl_context);
897 } else {
898 GLVT.init_context(window);
899 }
900
901 R.window = window;
902 return window;
903 }
904
gl33_features(void)905 static r_feature_bits_t gl33_features(void) {
906 return R.features;
907 }
908
gl33_capabilities(r_capability_bits_t capbits)909 static void gl33_capabilities(r_capability_bits_t capbits) {
910 R.capabilities.pending = capbits;
911 }
912
gl33_capabilities_current(void)913 static r_capability_bits_t gl33_capabilities_current(void) {
914 return R.capabilities.pending;
915 }
916
gl33_vsync(VsyncMode mode)917 static void gl33_vsync(VsyncMode mode) {
918 int interval = 0, result;
919
920 switch(mode) {
921 case VSYNC_NONE: interval = 0; break;
922 case VSYNC_NORMAL: interval = 1; break;
923 case VSYNC_ADAPTIVE: interval = -1; break;
924 default:
925 log_fatal("Unknown mode 0x%x", mode);
926 }
927
928 set_interval:
929 result = SDL_GL_SetSwapInterval(interval);
930
931 if(result < 0) {
932 log_warn("SDL_GL_SetSwapInterval(%i) failed: %s", interval, SDL_GetError());
933
934 // if adaptive vsync failed, try normal vsync
935 if(interval < 0) {
936 interval = 1;
937 goto set_interval;
938 }
939 }
940 }
941
gl33_vsync_current(void)942 static VsyncMode gl33_vsync_current(void) {
943 int interval = SDL_GL_GetSwapInterval();
944
945 if(interval == 0) {
946 return VSYNC_NONE;
947 }
948
949 return interval > 0 ? VSYNC_NORMAL : VSYNC_ADAPTIVE;
950 }
951
gl33_color4(float r,float g,float b,float a)952 static void gl33_color4(float r, float g, float b, float a) {
953 R.color.r = r;
954 R.color.g = g;
955 R.color.b = b;
956 R.color.a = a;
957 }
958
gl33_color_current(void)959 static const Color* gl33_color_current(void) {
960 return &R.color;
961 }
962
gl33_begin_draw(VertexArray * varr,void ** state)963 void gl33_begin_draw(VertexArray *varr, void **state) {
964 gl33_stats_pre_draw();
965 r_flush_sprites();
966 GLuint prev_vao = gl33_vao_current();
967 gl33_bind_vao(varr->gl_handle);
968 gl33_sync_state();
969 gl33_vertex_array_flush_buffers(varr);
970 *state = (void*)(uintptr_t)prev_vao;
971 }
972
gl33_end_draw(void * state)973 void gl33_end_draw(void *state) {
974 if(R.framebuffer.active) {
975 gl33_framebuffer_taint(R.framebuffer.active);
976 }
977
978 gl33_bind_vao((uintptr_t)state);
979 gl33_stats_post_draw();
980 }
981
gl33_draw(VertexArray * varr,Primitive prim,uint firstvert,uint count,uint instances,uint base_instance)982 static void gl33_draw(VertexArray *varr, Primitive prim, uint firstvert, uint count, uint instances, uint base_instance) {
983 assert(count > 0);
984 assert(base_instance == 0);
985 GLuint gl_prim = gl33_prim_to_gl_prim(prim);
986
987 void *state;
988 gl33_begin_draw(varr, &state);
989
990 if(instances) {
991 glDrawArraysInstanced(gl_prim, firstvert, count, instances);
992 } else {
993 glDrawArrays(gl_prim, firstvert, count);
994 }
995
996 gl33_end_draw(state);
997 }
998
gl33_draw_indexed(VertexArray * varr,Primitive prim,uint firstidx,uint count,uint instances,uint base_instance)999 static void gl33_draw_indexed(VertexArray *varr, Primitive prim, uint firstidx, uint count, uint instances, uint base_instance) {
1000 assert(count > 0);
1001 assert(base_instance == 0);
1002 assert(varr->index_attachment != NULL);
1003 GLuint gl_prim = gl33_prim_to_gl_prim(prim);
1004
1005 void *state;
1006 gl33_begin_draw(varr, &state);
1007
1008 uintptr_t iofs = firstidx * sizeof(gl33_ibo_index_t);
1009
1010 if(instances) {
1011 glDrawElementsInstanced(gl_prim, count, GL33_IBO_GL_DATATYPE, (void*)iofs, instances);
1012 } else {
1013 glDrawElements(gl_prim, count, GL33_IBO_GL_DATATYPE, (void*)iofs);
1014 }
1015
1016 gl33_end_draw(state);
1017 }
1018
gl33_framebuffer(Framebuffer * fb)1019 static void gl33_framebuffer(Framebuffer *fb) {
1020 R.framebuffer.pending = fb;
1021 }
1022
gl33_framebuffer_current(void)1023 static Framebuffer *gl33_framebuffer_current(void) {
1024 return R.framebuffer.pending;
1025 }
1026
gl33_framebuffer_viewport(Framebuffer * fb,FloatRect vp)1027 static void gl33_framebuffer_viewport(Framebuffer *fb, FloatRect vp) {
1028 transform_viewport_origin(fb, &vp);
1029 memcpy(get_framebuffer_viewport(fb), &vp, sizeof(vp));
1030 }
1031
gl33_framebuffer_viewport_current(Framebuffer * fb,FloatRect * out_rect)1032 static void gl33_framebuffer_viewport_current(Framebuffer *fb, FloatRect *out_rect) {
1033 *out_rect = *get_framebuffer_viewport(fb);
1034 transform_viewport_origin(fb, out_rect);
1035 }
1036
gl33_framebuffer_get_size(Framebuffer * fb)1037 static IntExtent gl33_framebuffer_get_size(Framebuffer *fb) {
1038 IntExtent fb_size;
1039
1040 if(fb == NULL) {
1041 // TODO: cache this at window creation time and refresh on resize events?
1042 SDL_GL_GetDrawableSize(R.window, &fb_size.w, &fb_size.h);
1043 } else {
1044 fb_size = gl33_framebuffer_get_effective_size(fb);
1045 }
1046
1047 return fb_size;
1048 }
1049
gl33_shader(ShaderProgram * prog)1050 static void gl33_shader(ShaderProgram *prog) {
1051 assert(prog->gl_handle != 0);
1052
1053 R.progs.pending = prog;
1054 }
1055
gl33_shader_current(void)1056 static ShaderProgram *gl33_shader_current(void) {
1057 return R.progs.pending;
1058 }
1059
gl33_set_clear_color(const Color * color)1060 void gl33_set_clear_color(const Color *color) {
1061 if(memcmp(&R.clear_color, color, sizeof(*color))) {
1062 memcpy(&R.clear_color, color, sizeof(*color));
1063 glClearColor(color->r, color->g, color->b, color->a);
1064 }
1065 }
1066
gl33_set_clear_depth(float depth)1067 void gl33_set_clear_depth(float depth) {
1068 if(R.clear_depth != depth) {
1069 R.clear_depth = depth;
1070 glClearDepth(depth);
1071 }
1072 }
1073
gl33_swap(SDL_Window * window)1074 static void gl33_swap(SDL_Window *window) {
1075 r_flush_sprites();
1076
1077 Framebuffer *prev_fb = r_framebuffer_current();
1078 r_framebuffer(NULL);
1079 gl33_sync_framebuffer();
1080 #ifndef __EMSCRIPTEN__
1081 SDL_GL_SwapWindow(window);
1082 #endif
1083 r_framebuffer(prev_fb);
1084
1085 gl33_stats_post_frame();
1086
1087 // We can't rely on viewport being preserved across frames,
1088 // so force the next frame to set one on the first draw call.
1089 // The viewport might get updated externally when e.g. going
1090 // fullscreen, and we can't catch that in the resize event.
1091 memset(&R.viewport.active, 0, sizeof(R.viewport.active));
1092 }
1093
gl33_blend(BlendMode mode)1094 static void gl33_blend(BlendMode mode) {
1095 R.blend.mode.pending = mode;
1096 }
1097
gl33_blend_current(void)1098 static BlendMode gl33_blend_current(void) {
1099 return R.blend.mode.pending;
1100 }
1101
gl33_cull(CullFaceMode mode)1102 static void gl33_cull(CullFaceMode mode) {
1103 R.cull_face.mode.pending = mode;
1104 }
1105
gl33_cull_current(void)1106 static CullFaceMode gl33_cull_current(void) {
1107 return R.cull_face.mode.pending;
1108 }
1109
gl33_depth_func(DepthTestFunc func)1110 static void gl33_depth_func(DepthTestFunc func) {
1111 R.depth_test.func.pending = func;
1112 }
1113
gl33_depth_func_current(void)1114 static DepthTestFunc gl33_depth_func_current(void) {
1115 return R.depth_test.func.pending;
1116 }
1117
gl33_screenshot(Pixmap * out)1118 static bool gl33_screenshot(Pixmap *out) {
1119 FloatRect *vp = &R.viewport.default_framebuffer;
1120 out->width = vp->w;
1121 out->height = vp->h;
1122 out->format = PIXMAP_FORMAT_RGB8;
1123 out->origin = PIXMAP_ORIGIN_BOTTOMLEFT;
1124 out->data.untyped = pixmap_alloc_buffer_for_copy(out);
1125 glReadPixels(vp->x, vp->y, vp->w, vp->h, GL_RGB, GL_UNSIGNED_BYTE, out->data.untyped);
1126 return true;
1127 }
1128
1129 RendererBackend _r_backend_gl33 = {
1130 .name = "gl33",
1131 .funcs = {
1132 .init = gl33_init,
1133 .post_init = gl33_post_init,
1134 .shutdown = gl33_shutdown,
1135 .create_window = gl33_create_window,
1136 .features = gl33_features,
1137 .capabilities = gl33_capabilities,
1138 .capabilities_current = gl33_capabilities_current,
1139 .draw = gl33_draw,
1140 .draw_indexed = gl33_draw_indexed,
1141 .color4 = gl33_color4,
1142 .color_current = gl33_color_current,
1143 .blend = gl33_blend,
1144 .blend_current = gl33_blend_current,
1145 .cull = gl33_cull,
1146 .cull_current = gl33_cull_current,
1147 .depth_func = gl33_depth_func,
1148 .depth_func_current = gl33_depth_func_current,
1149 .shader_language_supported = gl33_shader_language_supported,
1150 .shader_object_compile = gl33_shader_object_compile,
1151 .shader_object_destroy = gl33_shader_object_destroy,
1152 .shader_object_set_debug_label = gl33_shader_object_set_debug_label,
1153 .shader_object_get_debug_label = gl33_shader_object_get_debug_label,
1154 .shader_program_link = gl33_shader_program_link,
1155 .shader_program_destroy = gl33_shader_program_destroy,
1156 .shader_program_set_debug_label = gl33_shader_program_set_debug_label,
1157 .shader_program_get_debug_label = gl33_shader_program_get_debug_label,
1158 .shader = gl33_shader,
1159 .shader_current = gl33_shader_current,
1160 .shader_uniform = gl33_shader_uniform,
1161 .uniform = gl33_uniform,
1162 .uniform_type = gl33_uniform_type,
1163 .texture_create = gl33_texture_create,
1164 .texture_get_size = gl33_texture_get_size,
1165 .texture_get_params = gl33_texture_get_params,
1166 .texture_get_debug_label = gl33_texture_get_debug_label,
1167 .texture_set_debug_label = gl33_texture_set_debug_label,
1168 .texture_set_filter = gl33_texture_set_filter,
1169 .texture_set_wrap = gl33_texture_set_wrap,
1170 .texture_destroy = gl33_texture_destroy,
1171 .texture_invalidate = gl33_texture_invalidate,
1172 .texture_fill = gl33_texture_fill,
1173 .texture_fill_region = gl33_texture_fill_region,
1174 .texture_clear = gl33_texture_clear,
1175 .framebuffer_create = gl33_framebuffer_create,
1176 .framebuffer_destroy = gl33_framebuffer_destroy,
1177 .framebuffer_attach = gl33_framebuffer_attach,
1178 .framebuffer_get_debug_label = gl33_framebuffer_get_debug_label,
1179 .framebuffer_set_debug_label = gl33_framebuffer_set_debug_label,
1180 .framebuffer_get_attachment = gl33_framebuffer_get_attachment,
1181 .framebuffer_get_attachment_mipmap = gl33_framebuffer_get_attachment_mipmap,
1182 .framebuffer_viewport = gl33_framebuffer_viewport,
1183 .framebuffer_viewport_current = gl33_framebuffer_viewport_current,
1184 .framebuffer = gl33_framebuffer,
1185 .framebuffer_current = gl33_framebuffer_current,
1186 .framebuffer_clear = gl33_framebuffer_clear,
1187 .framebuffer_get_size = gl33_framebuffer_get_size,
1188 .vertex_buffer_create = gl33_vertex_buffer_create,
1189 .vertex_buffer_set_debug_label = gl33_vertex_buffer_set_debug_label,
1190 .vertex_buffer_get_debug_label = gl33_vertex_buffer_get_debug_label,
1191 .vertex_buffer_destroy = gl33_vertex_buffer_destroy,
1192 .vertex_buffer_invalidate = gl33_vertex_buffer_invalidate,
1193 .vertex_buffer_get_stream = gl33_vertex_buffer_get_stream,
1194 .index_buffer_create = gl33_index_buffer_create,
1195 .index_buffer_get_capacity = gl33_index_buffer_get_capacity,
1196 .index_buffer_get_debug_label = gl33_index_buffer_get_debug_label,
1197 .index_buffer_set_debug_label = gl33_index_buffer_set_debug_label,
1198 .index_buffer_set_offset = gl33_index_buffer_set_offset,
1199 .index_buffer_get_offset = gl33_index_buffer_get_offset,
1200 .index_buffer_add_indices = gl33_index_buffer_add_indices,
1201 .index_buffer_destroy = gl33_index_buffer_destroy,
1202 .vertex_array_destroy = gl33_vertex_array_destroy,
1203 .vertex_array_create = gl33_vertex_array_create,
1204 .vertex_array_set_debug_label = gl33_vertex_array_set_debug_label,
1205 .vertex_array_get_debug_label = gl33_vertex_array_get_debug_label,
1206 .vertex_array_layout = gl33_vertex_array_layout,
1207 .vertex_array_attach_vertex_buffer = gl33_vertex_array_attach_vertex_buffer,
1208 .vertex_array_get_vertex_attachment = gl33_vertex_array_get_vertex_attachment,
1209 .vertex_array_attach_index_buffer = gl33_vertex_array_attach_index_buffer,
1210 .vertex_array_get_index_attachment = gl33_vertex_array_get_index_attachment,
1211 .vsync = gl33_vsync,
1212 .vsync_current = gl33_vsync_current,
1213 .swap = gl33_swap,
1214 .screenshot = gl33_screenshot,
1215 },
1216 .custom = &(GLBackendData) {
1217 .vtable = {
1218 .texture_type_info = gl33_texture_type_info,
1219 .texture_format_caps = gl33_texture_format_caps,
1220 .init_context = gl33_init_context,
1221 }
1222 },
1223 };
1224