comparison render_sdl.c @ 488:32f053ad9b02 opengl

Basic OpenGL rendering is working
author Mike Pavone <pavone@retrodev.com>
date Sun, 27 Oct 2013 01:29:50 -0700
parents c08a4efeee7f
children e97b80e3bd76
comparison
equal deleted inserted replaced
487:c08a4efeee7f 488:32f053ad9b02
8 #include "render.h" 8 #include "render.h"
9 #include "blastem.h" 9 #include "blastem.h"
10 #include "io.h" 10 #include "io.h"
11 11
12 #ifndef DISABLE_OPENGL 12 #ifndef DISABLE_OPENGL
13 #define GL_GLEXT_PROTOTYPES 13 #include <GL/glew.h>
14 #include <GL/gl.h>
15 #include <GL/glext.h>
16 #endif 14 #endif
17 15
18 SDL_Surface *screen; 16 SDL_Surface *screen;
19 uint8_t render_dbg = 0; 17 uint8_t render_dbg = 0;
20 uint8_t debug_pal = 0; 18 uint8_t debug_pal = 0;
91 } 89 }
92 90
93 uint32_t render_map_color(uint8_t r, uint8_t g, uint8_t b) 91 uint32_t render_map_color(uint8_t r, uint8_t g, uint8_t b)
94 { 92 {
95 if (render_gl) { 93 if (render_gl) {
96 return b << 24 | g << 16 | r << 8 | 255; 94 return 255 << 24 | r << 16 | g << 8 | b;
97 } else { 95 } else {
98 return SDL_MapRGB(screen->format, r, g, b); 96 return SDL_MapRGB(screen->format, r, g, b);
99 } 97 }
100 } 98 }
101 99
102 GLuint textures[3], buffers[2]; 100 GLuint textures[3], buffers[2], vshader, fshader, program, un_textures[2], at_pos;
103 101
104 const GLfloat vertex_data[] = { 102 const GLfloat vertex_data[] = {
105 -1.0f, -1.0f, 103 -1.0f, -1.0f,
106 1.0f, -1.0f, 104 1.0f, -1.0f,
107 -1.0f, 1.0f, 105 -1.0f, 1.0f,
108 1.0f, 1.0f 106 1.0f, 1.0f
109 }; 107 };
110 108
111 const GLushort element_data[] = {0, 1, 2, 3}; 109 const GLushort element_data[] = {0, 1, 2, 3};
110
111 GLuint load_shader(char * fname, GLenum shader_type)
112 {
113 FILE * f = fopen(fname, "r");
114 if (!f) {
115 fprintf(stderr, "Failed to open shader file %s for reading\n", fname);
116 return 0;
117 }
118 fseek(f, 0, SEEK_END);
119 long fsize = ftell(f);
120 fseek(f, 0, SEEK_SET);
121 GLchar * text = malloc(fsize);
122 if (fread(text, 1, fsize, f) != fsize) {
123 fprintf(stderr, "Error reading from shader file %s\n", fname);
124 free(text);
125 return 0;
126 }
127 GLuint ret = glCreateShader(shader_type);
128 glShaderSource(ret, 1, (const GLchar **)&text, (const GLint *)&fsize);
129 free(text);
130 glCompileShader(ret);
131 GLint compile_status, loglen;
132 glGetShaderiv(ret, GL_COMPILE_STATUS, &compile_status);
133 if (!compile_status) {
134 fprintf(stderr, "Shader %s failed to compile\n", fname);
135 glGetShaderiv(ret, GL_INFO_LOG_LENGTH, &loglen);
136 text = malloc(loglen);
137 glGetShaderInfoLog(ret, loglen, NULL, text);
138 fputs(text, stderr);
139 free(text);
140 glDeleteShader(ret);
141 return 0;
142 }
143 return ret;
144 }
112 145
113 void render_alloc_surfaces(vdp_context * context) 146 void render_alloc_surfaces(vdp_context * context)
114 { 147 {
115 if (render_gl) { 148 if (render_gl) {
116 context->oddbuf = context->framebuf = malloc(320 * 240 * 4 * 2); 149 context->oddbuf = context->framebuf = malloc(320 * 240 * 4 * 2);
132 } 165 }
133 } 166 }
134 glGenBuffers(2, buffers); 167 glGenBuffers(2, buffers);
135 glBindBuffer(GL_ARRAY_BUFFER, buffers[0]); 168 glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
136 glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW); 169 glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW);
137 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[0]); 170 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
138 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(element_data), element_data, GL_STATIC_DRAW); 171 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(element_data), element_data, GL_STATIC_DRAW);
172 vshader = load_shader("default.v.glsl", GL_VERTEX_SHADER);
173 fshader = load_shader("default.f.glsl", GL_FRAGMENT_SHADER);
174 program = glCreateProgram();
175 glAttachShader(program, vshader);
176 glAttachShader(program, fshader);
177 glLinkProgram(program);
178 GLint link_status;
179 glGetProgramiv(program, GL_LINK_STATUS, &link_status);
180 if (!link_status) {
181 fputs("Failed to link shader program\n", stderr);
182 exit(1);
183 }
184 un_textures[0] = glGetUniformLocation(program, "textures[0]");
185 un_textures[1] = glGetUniformLocation(program, "textures[1]");
186 at_pos = glGetAttribLocation(program, "pos");
139 } else { 187 } else {
140 context->oddbuf = context->framebuf = malloc(320 * 240 * screen->format->BytesPerPixel * 2); 188 context->oddbuf = context->framebuf = malloc(320 * 240 * screen->format->BytesPerPixel * 2);
141 context->evenbuf = ((char *)context->oddbuf) + 320 * 240 * screen->format->BytesPerPixel; 189 context->evenbuf = ((char *)context->oddbuf) + 320 * 240 * screen->format->BytesPerPixel;
142 } 190 }
143 } 191 }
157 } 205 }
158 atexit(SDL_Quit); 206 atexit(SDL_Quit);
159 atexit(render_close_audio); 207 atexit(render_close_audio);
160 printf("width: %d, height: %d\n", width, height); 208 printf("width: %d, height: %d\n", width, height);
161 uint32_t flags = SDL_ANYFORMAT; 209 uint32_t flags = SDL_ANYFORMAT;
210
162 #ifndef DISABLE_OPENGL 211 #ifndef DISABLE_OPENGL
163 if (use_gl) 212 if (use_gl)
164 { 213 {
165 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); 214 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
166 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5); 215 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
186 if (!use_gl && screen->format->BytesPerPixel != 2 && screen->format->BytesPerPixel != 4) { 235 if (!use_gl && screen->format->BytesPerPixel != 2 && screen->format->BytesPerPixel != 4) {
187 fprintf(stderr, "BlastEm requires a 16-bit or 32-bit surface, SDL returned a %d-bit surface\n", screen->format->BytesPerPixel * 8); 236 fprintf(stderr, "BlastEm requires a 16-bit or 32-bit surface, SDL returned a %d-bit surface\n", screen->format->BytesPerPixel * 8);
188 exit(1); 237 exit(1);
189 } 238 }
190 #ifndef DISABLE_OPENGL 239 #ifndef DISABLE_OPENGL
191 //TODO: Fallback to plain SDL if OpenGL 2.0 not available 240 //TODO: fallback on standard rendering if OpenGL 2.0 is unavailable or if init fails
241 if (use_gl)
242 {
243 GLenum res = glewInit();
244 if (res != GLEW_OK)
245 {
246 fprintf(stderr, "Initialization of GLEW failed with code %d\n", res);
247 exit(1);
248 }
249 if (!GLEW_VERSION_2_0)
250 {
251 fputs("OpenGL 2.0 is unable, falling back to standard SDL rendering\n", stderr);
252 exit(1);
253 }
254 }
192 render_gl = use_gl; 255 render_gl = use_gl;
193 #endif 256 #endif
194 SDL_WM_SetCaption(title, title); 257 SDL_WM_SetCaption(title, title);
195 caption = title; 258 caption = title;
196 min_delay = 0; 259 min_delay = 0;
260 glBindTexture(GL_TEXTURE_2D, textures[context->framebuf == context->oddbuf ? 0 : 1]); 323 glBindTexture(GL_TEXTURE_2D, textures[context->framebuf == context->oddbuf ? 0 : 1]);
261 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 320, 240, GL_BGRA, GL_UNSIGNED_BYTE, context->framebuf);; 324 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 320, 240, GL_BGRA, GL_UNSIGNED_BYTE, context->framebuf);;
262 325
263 glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 326 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
264 glClear(GL_COLOR_BUFFER_BIT); 327 glClear(GL_COLOR_BUFFER_BIT);
328
329 glUseProgram(program);
330 glActiveTexture(GL_TEXTURE0);
331 glBindTexture(GL_TEXTURE_2D, textures[0]);
332 glUniform1i(un_textures[0], 0);
333
334 glActiveTexture(GL_TEXTURE1);
335 //TODO: Select appropriate texture based on status of interlace
336 glBindTexture(GL_TEXTURE_2D, textures[1]);
337 glUniform1i(un_textures[1], 1);
338
339 glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
340 glVertexAttribPointer(at_pos, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat[2]), (void *)0);
341 glEnableVertexAttribArray(at_pos);
342
343 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
344 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, (void *)0);
345
346 glDisableVertexAttribArray(at_pos);
347
348 SDL_GL_SwapBuffers();
265 349
266 } 350 }
267 351
268 uint32_t blankbuf[320*240]; 352 uint32_t blankbuf[320*240];
269 353