Mercurial > repos > blastem
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")) { |