comparison render_sdl.c @ 1658:fa9ae059e4d3

Added support for GLES in addition to desktop GL
author Mike Pavone <pavone@retrodev.com>
date Sun, 30 Dec 2018 21:10:44 -0800
parents b500e971da75
children 19331a21da3a
comparison
equal deleted inserted replaced
1657:774096402918 1658:fa9ae059e4d3
17 #include "png.h" 17 #include "png.h"
18 #include "config.h" 18 #include "config.h"
19 #include "controller_info.h" 19 #include "controller_info.h"
20 20
21 #ifndef DISABLE_OPENGL 21 #ifndef DISABLE_OPENGL
22 #ifdef USE_GLES
23 #include <SDL_opengles2.h>
24 #else
22 #include <GL/glew.h> 25 #include <GL/glew.h>
26 #endif
23 #endif 27 #endif
24 28
25 #define MAX_EVENT_POLL_PER_FRAME 2 29 #define MAX_EVENT_POLL_PER_FRAME 2
26 30
27 static SDL_Window *main_window; 31 static SDL_Window *main_window;
435 return is_fullscreen; 439 return is_fullscreen;
436 } 440 }
437 441
438 uint32_t render_map_color(uint8_t r, uint8_t g, uint8_t b) 442 uint32_t render_map_color(uint8_t r, uint8_t g, uint8_t b)
439 { 443 {
444 #ifdef USE_GLES
445 return 255 << 24 | b << 16 | g << 8 | r;
446 #else
440 return 255 << 24 | r << 16 | g << 8 | b; 447 return 255 << 24 | r << 16 | g << 8 | b;
448 #endif
441 } 449 }
442 450
443 #ifndef DISABLE_OPENGL 451 #ifndef DISABLE_OPENGL
444 static GLuint textures[3], buffers[2], vshader, fshader, program, un_textures[2], un_width, un_height, at_pos; 452 static GLuint textures[3], buffers[2], vshader, fshader, program, un_textures[2], un_width, un_height, at_pos;
445 453
451 }; 459 };
452 460
453 static GLfloat vertex_data[8]; 461 static GLfloat vertex_data[8];
454 462
455 static const GLushort element_data[] = {0, 1, 2, 3}; 463 static const GLushort element_data[] = {0, 1, 2, 3};
464
465 static const GLchar shader_prefix[] =
466 #ifdef USE_GLES
467 "#version 100\n";
468 #else
469 "#version 110\n"
470 "#define lowp\n"
471 "#define mediump\n"
472 "#define highp\n";
473 #endif
456 474
457 static GLuint load_shader(char * fname, GLenum shader_type) 475 static GLuint load_shader(char * fname, GLenum shader_type)
458 { 476 {
459 char const * parts[] = {get_home_dir(), "/.config/blastem/shaders/", fname}; 477 char const * parts[] = {get_home_dir(), "/.config/blastem/shaders/", fname};
460 char * shader_path = alloc_concat_m(3, parts); 478 char * shader_path = alloc_concat_m(3, parts);
475 GLchar * text = malloc(fsize); 493 GLchar * text = malloc(fsize);
476 if (fread(text, 1, fsize, f) != fsize) { 494 if (fread(text, 1, fsize, f) != fsize) {
477 warning("Error reading from shader file %s\n", fname); 495 warning("Error reading from shader file %s\n", fname);
478 free(text); 496 free(text);
479 return 0; 497 return 0;
498 }
499 if (strncmp(text, "#version", strlen("#version"))) {
500 GLchar *tmp = text;
501 text = alloc_concat(shader_prefix, tmp);
502 free(tmp);
503 fsize += strlen(shader_prefix);
480 } 504 }
481 GLuint ret = glCreateShader(shader_type); 505 GLuint ret = glCreateShader(shader_type);
482 glShaderSource(ret, 1, (const GLchar **)&text, (const GLint *)&fsize); 506 glShaderSource(ret, 1, (const GLchar **)&text, (const GLint *)&fsize);
483 free(text); 507 free(text);
484 glCompileShader(ret); 508 glCompileShader(ret);
497 } 521 }
498 #endif 522 #endif
499 523
500 static uint32_t texture_buf[512 * 513]; 524 static uint32_t texture_buf[512 * 513];
501 #ifndef DISABLE_OPENGL 525 #ifndef DISABLE_OPENGL
526 #ifdef USE_GLES
527 #define INTERNAL_FORMAT GL_RGBA
528 #define SRC_FORMAT GL_RGBA
529 #define RENDER_FORMAT SDL_PIXELFORMAT_ABGR8888
530 #else
531 #define INTERNAL_FORMAT GL_RGBA8
532 #define SRC_FORMAT GL_BGRA
533 #define RENDER_FORMAT SDL_PIXELFORMAT_ARGB8888
534 #endif
502 static void gl_setup() 535 static void gl_setup()
503 { 536 {
504 tern_val def = {.ptrval = "linear"}; 537 tern_val def = {.ptrval = "linear"};
505 char *scaling = tern_find_path_default(config, "video\0scaling\0", def, TVAL_PTR).ptrval; 538 char *scaling = tern_find_path_default(config, "video\0scaling\0", def, TVAL_PTR).ptrval;
506 GLint filter = strcmp(scaling, "linear") ? GL_NEAREST : GL_LINEAR; 539 GLint filter = strcmp(scaling, "linear") ? GL_NEAREST : GL_LINEAR;
512 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); 545 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
513 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 546 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
514 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 547 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
515 if (i < 2) { 548 if (i < 2) {
516 //TODO: Fixme for PAL + invalid display mode 549 //TODO: Fixme for PAL + invalid display mode
517 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 512, 512, 0, GL_BGRA, GL_UNSIGNED_BYTE, texture_buf); 550 glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, 512, 512, 0, SRC_FORMAT, GL_UNSIGNED_BYTE, texture_buf);
518 } else { 551 } else {
519 uint32_t blank = 255 << 24; 552 uint32_t blank = 255 << 24;
520 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_BGRA, GL_UNSIGNED_BYTE, &blank); 553 glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, 1, 1, 0, SRC_FORMAT, GL_UNSIGNED_BYTE, &blank);
521 } 554 }
522 } 555 }
523 glGenBuffers(2, buffers); 556 glGenBuffers(2, buffers);
524 glBindBuffer(GL_ARRAY_BUFFER, buffers[0]); 557 glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
525 glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW); 558 glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW);
573 #endif 606 #endif
574 tern_val def = {.ptrval = "linear"}; 607 tern_val def = {.ptrval = "linear"};
575 char *scaling = tern_find_path_default(config, "video\0scaling\0", def, TVAL_PTR).ptrval; 608 char *scaling = tern_find_path_default(config, "video\0scaling\0", def, TVAL_PTR).ptrval;
576 SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, scaling); 609 SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, scaling);
577 //TODO: Fixme for invalid display mode 610 //TODO: Fixme for invalid display mode
578 sdl_textures[0] = sdl_textures[1] = SDL_CreateTexture(main_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, LINEBUF_SIZE, 588); 611 sdl_textures[0] = sdl_textures[1] = SDL_CreateTexture(main_renderer, RENDER_FORMAT, SDL_TEXTUREACCESS_STREAMING, LINEBUF_SIZE, 588);
579 #ifndef DISABLE_OPENGL 612 #ifndef DISABLE_OPENGL
580 } 613 }
581 #endif 614 #endif
582 } 615 }
583 616
1064 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); 1097 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
1065 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5); 1098 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
1066 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); 1099 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
1067 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0); 1100 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);
1068 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); 1101 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
1102 #ifdef USE_GLES
1103 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
1104 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
1105 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
1106 #endif
1069 } 1107 }
1070 #endif 1108 #endif
1071 main_window = SDL_CreateWindow(caption, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, main_width, main_height, flags); 1109 main_window = SDL_CreateWindow(caption, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, main_width, main_height, flags);
1072 if (!main_window) { 1110 if (!main_window) {
1073 fatal_error("Unable to create SDL window: %s\n", SDL_GetError()); 1111 fatal_error("Unable to create SDL window: %s\n", SDL_GetError());
1074 } 1112 }
1075 #ifndef DISABLE_OPENGL 1113 #ifndef DISABLE_OPENGL
1076 if (gl_enabled) 1114 if (gl_enabled)
1077 { 1115 {
1078 main_context = SDL_GL_CreateContext(main_window); 1116 main_context = SDL_GL_CreateContext(main_window);
1117 #ifdef USE_GLES
1118 int major_version;
1119 if (SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major_version) == 0 && major_version >= 2) {
1120 #else
1079 GLenum res = glewInit(); 1121 GLenum res = glewInit();
1080 if (res != GLEW_OK) { 1122 if (res != GLEW_OK) {
1081 warning("Initialization of GLEW failed with code %d\n", res); 1123 warning("Initialization of GLEW failed with code %d\n", res);
1082 } 1124 }
1083 1125
1084 if (res == GLEW_OK && GLEW_VERSION_2_0) { 1126 if (res == GLEW_OK && GLEW_VERSION_2_0) {
1127 #endif
1085 render_gl = 1; 1128 render_gl = 1;
1129 SDL_GL_MakeCurrent(main_window, main_context);
1086 if (!strcmp("tear", vsync)) { 1130 if (!strcmp("tear", vsync)) {
1087 if (SDL_GL_SetSwapInterval(-1) < 0) { 1131 if (SDL_GL_SetSwapInterval(-1) < 0) {
1088 warning("late tear is not available (%s), using normal vsync\n", SDL_GetError()); 1132 warning("late tear is not available (%s), using normal vsync\n", SDL_GetError());
1089 vsync = "on"; 1133 vsync = "on";
1090 } else { 1134 } else {
1109 main_renderer = SDL_CreateRenderer(main_window, -1, flags); 1153 main_renderer = SDL_CreateRenderer(main_window, -1, flags);
1110 1154
1111 if (!main_renderer) { 1155 if (!main_renderer) {
1112 fatal_error("unable to create SDL renderer: %s\n", SDL_GetError()); 1156 fatal_error("unable to create SDL renderer: %s\n", SDL_GetError());
1113 } 1157 }
1158 SDL_RendererInfo rinfo;
1159 SDL_GetRendererInfo(main_renderer, &rinfo);
1160 printf("SDL2 Render Driver: %s\n", rinfo.name);
1114 main_clip.x = main_clip.y = 0; 1161 main_clip.x = main_clip.y = 0;
1115 main_clip.w = main_width; 1162 main_clip.w = main_width;
1116 main_clip.h = main_height; 1163 main_clip.h = main_height;
1117 #ifndef DISABLE_OPENGL 1164 #ifndef DISABLE_OPENGL
1118 } 1165 }
1482 width -= overscan_left[video_standard] + overscan_right[video_standard]; 1529 width -= overscan_left[video_standard] + overscan_right[video_standard];
1483 #ifndef DISABLE_OPENGL 1530 #ifndef DISABLE_OPENGL
1484 if (render_gl && which <= FRAMEBUFFER_EVEN) { 1531 if (render_gl && which <= FRAMEBUFFER_EVEN) {
1485 SDL_GL_MakeCurrent(main_window, main_context); 1532 SDL_GL_MakeCurrent(main_window, main_context);
1486 glBindTexture(GL_TEXTURE_2D, textures[which]); 1533 glBindTexture(GL_TEXTURE_2D, textures[which]);
1487 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, LINEBUF_SIZE, height, GL_BGRA, GL_UNSIGNED_BYTE, texture_buf + overscan_left[video_standard] + LINEBUF_SIZE * overscan_top[video_standard]); 1534 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, LINEBUF_SIZE, height, SRC_FORMAT, GL_UNSIGNED_BYTE, texture_buf + overscan_left[video_standard] + LINEBUF_SIZE * overscan_top[video_standard]);
1488 1535
1489 if (screenshot_file) { 1536 if (screenshot_file) {
1490 //properly supporting interlaced modes here is non-trivial, so only save the odd field for now 1537 //properly supporting interlaced modes here is non-trivial, so only save the odd field for now
1491 #ifndef DISABLE_ZLIB 1538 #ifndef DISABLE_ZLIB
1492 if (!strcasecmp(ext, "png")) { 1539 if (!strcasecmp(ext, "png")) {