comparison render_sdl.c @ 797:65181c3ee560

Add pure SDL2 renderer
author =?UTF-8?q?Higor=20Eur=C3=ADpedes?= <heuripedes@gmail.com>
date Sun, 26 Jul 2015 13:05:05 -0700
parents 1b2f8280ba81
children 062a2199daf6
comparison
equal deleted inserted replaced
796:41f73c76b978 797:65181c3ee560
13 #include "util.h" 13 #include "util.h"
14 14
15 #include <GL/glew.h> 15 #include <GL/glew.h>
16 16
17 SDL_Window *main_window; 17 SDL_Window *main_window;
18 #ifdef DISABLE_OPENGL
19 SDL_Renderer *main_renderer;
20 SDL_Texture *main_texture;
21 SDL_Rect main_clip;
22 #else
18 SDL_GLContext *main_context; 23 SDL_GLContext *main_context;
24 #endif
25
19 uint8_t render_dbg = 0; 26 uint8_t render_dbg = 0;
20 uint8_t debug_pal = 0; 27 uint8_t debug_pal = 0;
21 28
22 uint32_t last_frame = 0; 29 uint32_t last_frame = 0;
23 30
151 void render_alloc_surfaces(vdp_context * context) 158 void render_alloc_surfaces(vdp_context * context)
152 { 159 {
153 context->oddbuf = context->framebuf = malloc(512 * 256 * 4 * 2); 160 context->oddbuf = context->framebuf = malloc(512 * 256 * 4 * 2);
154 memset(context->oddbuf, 0, 512 * 256 * 4 * 2); 161 memset(context->oddbuf, 0, 512 * 256 * 4 * 2);
155 context->evenbuf = ((char *)context->oddbuf) + 512 * 256 * 4; 162 context->evenbuf = ((char *)context->oddbuf) + 512 * 256 * 4;
163
164 #ifdef DISABLE_OPENGL
165 /* height=480 to fit interlaced output */
166 main_texture = SDL_CreateTexture(main_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 320, 480);
167 #else
156 glGenTextures(3, textures); 168 glGenTextures(3, textures);
157 for (int i = 0; i < 3; i++) 169 for (int i = 0; i < 3; i++)
158 { 170 {
159 glBindTexture(GL_TEXTURE_2D, textures[i]); 171 glBindTexture(GL_TEXTURE_2D, textures[i]);
160 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 172 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
189 } 201 }
190 un_textures[0] = glGetUniformLocation(program, "textures[0]"); 202 un_textures[0] = glGetUniformLocation(program, "textures[0]");
191 un_textures[1] = glGetUniformLocation(program, "textures[1]"); 203 un_textures[1] = glGetUniformLocation(program, "textures[1]");
192 un_width = glGetUniformLocation(program, "width"); 204 un_width = glGetUniformLocation(program, "width");
193 at_pos = glGetAttribLocation(program, "pos"); 205 at_pos = glGetAttribLocation(program, "pos");
206 #endif
194 } 207 }
195 208
196 char * caption = NULL; 209 char * caption = NULL;
210
211 static void render_quit()
212 {
213 render_close_audio();
214 #ifdef DISABLE_OPENGL
215 SDL_DestroyTexture(main_texture);
216 #endif
217 SDL_Quit();
218 }
197 219
198 void render_init(int width, int height, char * title, uint32_t fps, uint8_t fullscreen) 220 void render_init(int width, int height, char * title, uint32_t fps, uint8_t fullscreen)
199 { 221 {
200 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0) { 222 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0) {
201 fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError()); 223 fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
202 exit(1); 224 exit(1);
203 } 225 }
204 printf("width: %d, height: %d\n", width, height); 226 printf("width: %d, height: %d\n", width, height);
205 uint32_t flags = SDL_WINDOW_OPENGL; 227
206 228 uint32_t flags = 0;
207 229
208 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
209 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
210 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
211 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);
212 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
213 if (fullscreen) { 230 if (fullscreen) {
214 flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; 231 flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
215 SDL_DisplayMode mode; 232 SDL_DisplayMode mode;
216 //TODO: Multiple monitor support 233 //TODO: Multiple monitor support
217 SDL_GetCurrentDisplayMode(0, &mode); 234 SDL_GetCurrentDisplayMode(0, &mode);
218 //the SDL2 migration guide suggests setting width and height to 0 when using SDL_WINDOW_FULLSCREEN_DESKTOP 235 //the SDL2 migration guide suggests setting width and height to 0 when using SDL_WINDOW_FULLSCREEN_DESKTOP
219 //but that doesn't seem to work right when using OpenGL, at least on Linux anyway 236 //but that doesn't seem to work right when using OpenGL, at least on Linux anyway
220 width = mode.w; 237 width = mode.w;
221 height = mode.h; 238 height = mode.h;
222 } 239 }
240
241 #ifdef DISABLE_OPENGL
242 SDL_CreateWindowAndRenderer(width, height, flags, &main_window, &main_renderer);
243
244 if (!main_window || !main_renderer) {
245 fprintf(stderr, "unable to create SDL window: %s\n", SDL_GetError());
246 SDL_Quit();
247 exit(1);
248 }
249 main_clip.x = main_clip.y = 0;
250 main_clip.w = width;
251 main_clip.h = height;
252 #else
253 flags |= SDL_WINDOW_OPENGL;
254 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
255 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
256 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
257 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);
258 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
223 main_window = SDL_CreateWindow(title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, flags); 259 main_window = SDL_CreateWindow(title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, flags);
224 if (!main_window) { 260 if (!main_window) {
225 fprintf(stderr, "Unable to create SDL window: %s\n", SDL_GetError()); 261 fprintf(stderr, "Unable to create SDL window: %s\n", SDL_GetError());
226 SDL_Quit(); 262 SDL_Quit();
227 exit(1); 263 exit(1);
228 } 264 }
229 SDL_GetWindowSize(main_window, &width, &height);
230 printf("Window created with size: %d x %d\n", width, height);
231 main_context = SDL_GL_CreateContext(main_window); 265 main_context = SDL_GL_CreateContext(main_window);
232 GLenum res = glewInit(); 266 GLenum res = glewInit();
233 if (res != GLEW_OK) { 267 if (res != GLEW_OK) {
234 fprintf(stderr, "Initialization of GLEW failed with code %d\n", res); 268 fprintf(stderr, "Initialization of GLEW failed with code %d\n", res);
235 SDL_Quit(); 269 SDL_Quit();
238 if (!GLEW_VERSION_2_0) { 272 if (!GLEW_VERSION_2_0) {
239 fputs("BlastEm requires at least OpenGL 2.0, but it is unavailable\n", stderr); 273 fputs("BlastEm requires at least OpenGL 2.0, but it is unavailable\n", stderr);
240 SDL_Quit(); 274 SDL_Quit();
241 exit(1); 275 exit(1);
242 } 276 }
243 float aspect = (float)width / height; 277 #endif
278 SDL_GetWindowSize(main_window, &width, &height);
279 printf("Window created with size: %d x %d\n", width, height);
280 float src_aspect = 4.0/3.0;
281 float aspect = (float)width / height;
244 tern_val def = {.ptrval = "normal"}; 282 tern_val def = {.ptrval = "normal"};
245 if (fabs(aspect - 4.0/3.0) > 0.01 && strcmp(tern_find_path_default(config, "video\0aspect\0", def).ptrval, "stretch")) { 283 int stretch = fabs(aspect - src_aspect) > 0.01 && !strcmp(tern_find_path_default(config, "video\0aspect\0", def).ptrval, "stretch");
284
285 #ifdef DISABLE_OPENGL
286 if (!stretch) {
287 float scale_x = (float)width / 320.0;
288 float scale_y = (float)height / 240.0;
289 float scale = scale_x > scale_y ? scale_y : scale_x;
290 main_clip.w = 320.0 * scale;
291 main_clip.h = 240.0 * scale;
292 main_clip.x = (width - main_clip.w) / 2;
293 main_clip.y = (height - main_clip.h) / 2;
294 }
295 #else
296 if (!stretch) {
246 for (int i = 0; i < 4; i++) 297 for (int i = 0; i < 4; i++)
247 { 298 {
248 if (aspect > 4.0/3.0) { 299 if (aspect > src_aspect) {
249 vertex_data[i*2] *= (4.0/3.0)/aspect; 300 vertex_data[i*2] *= src_aspect/aspect;
250 } else { 301 } else {
251 vertex_data[i*2+1] *= aspect/(4.0/3.0); 302 vertex_data[i*2+1] *= aspect/src_aspect;
252 } 303 }
253 } 304 }
254 } 305 }
306 #endif
255 caption = title; 307 caption = title;
256 min_delay = 0; 308 min_delay = 0;
257 for (int i = 0; i < 100; i++) { 309 for (int i = 0; i < 100; i++) {
258 uint32_t start = SDL_GetTicks(); 310 uint32_t start = SDL_GetTicks();
259 SDL_Delay(1); 311 SDL_Delay(1);
313 printf("\tNum Axes: %d\n\tNum Buttons: %d\n\tNum Hats: %d\n", SDL_JoystickNumAxes(joy), SDL_JoystickNumButtons(joy), SDL_JoystickNumHats(joy)); 365 printf("\tNum Axes: %d\n\tNum Buttons: %d\n\tNum Hats: %d\n", SDL_JoystickNumAxes(joy), SDL_JoystickNumButtons(joy), SDL_JoystickNumHats(joy));
314 } 366 }
315 } 367 }
316 SDL_JoystickEventState(SDL_ENABLE); 368 SDL_JoystickEventState(SDL_ENABLE);
317 369
318 atexit(SDL_Quit); 370 atexit(render_quit);
319 atexit(render_close_audio);
320 } 371 }
321 372
322 void render_context(vdp_context * context) 373 void render_context(vdp_context * context)
323 { 374 {
375 int width = context->regs[REG_MODE_4] & BIT_H40 ? 320.0f : 256.0f;
376 int height = 240;
377
324 last_frame = SDL_GetTicks(); 378 last_frame = SDL_GetTicks();
325 379 #ifdef DISABLE_OPENGL
380 SDL_Rect area;
381
382 area.x = area.y = 0;
383 area.w = width;
384 area.h = height;
385
386 if (context->regs[REG_MODE_4] & BIT_INTERLACE)
387 {
388 unsigned skip;
389 uint32_t *src = (uint32_t*)context->framebuf;
390 uint8_t *dst;
391 int i;
392
393 area.h *= 2;
394
395 SDL_LockTexture(main_texture, &area, (void**)&dst, &skip);
396
397 if (context->framebuf == context->evenbuf)
398 dst += skip;
399
400 skip *= 2;
401
402 for (i = 0; i < 240; ++i)
403 {
404 memcpy(dst, src, width*sizeof(uint32_t));
405 src += 320;
406 dst += skip;
407 }
408
409 SDL_UnlockTexture(main_texture);
410 }
411 else /* possibly faster path for non-interlaced output */
412 SDL_UpdateTexture(main_texture, &area, context->framebuf, 320*sizeof(uint32_t));
413
414 SDL_RenderClear(main_renderer);
415 SDL_RenderCopy(main_renderer, main_texture, &area, &main_clip);
416 SDL_RenderPresent(main_renderer);
417 #else
326 glBindTexture(GL_TEXTURE_2D, textures[context->framebuf == context->oddbuf ? 0 : 1]); 418 glBindTexture(GL_TEXTURE_2D, textures[context->framebuf == context->oddbuf ? 0 : 1]);
327 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 320, 240, GL_BGRA, GL_UNSIGNED_BYTE, context->framebuf);; 419 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 320, 240, GL_BGRA, GL_UNSIGNED_BYTE, context->framebuf);;
328 420
329 glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 421 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
330 glClear(GL_COLOR_BUFFER_BIT); 422 glClear(GL_COLOR_BUFFER_BIT);
336 428
337 glActiveTexture(GL_TEXTURE1); 429 glActiveTexture(GL_TEXTURE1);
338 glBindTexture(GL_TEXTURE_2D, (context->regs[REG_MODE_4] & BIT_INTERLACE) ? textures[1] : textures[2]); 430 glBindTexture(GL_TEXTURE_2D, (context->regs[REG_MODE_4] & BIT_INTERLACE) ? textures[1] : textures[2]);
339 glUniform1i(un_textures[1], 1); 431 glUniform1i(un_textures[1], 1);
340 432
341 glUniform1f(un_width, context->regs[REG_MODE_4] & BIT_H40 ? 320.0f : 256.0f); 433 glUniform1f(un_width, width);
342 434
343 glBindBuffer(GL_ARRAY_BUFFER, buffers[0]); 435 glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
344 glVertexAttribPointer(at_pos, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat[2]), (void *)0); 436 glVertexAttribPointer(at_pos, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat[2]), (void *)0);
345 glEnableVertexAttribArray(at_pos); 437 glEnableVertexAttribArray(at_pos);
346 438
348 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, (void *)0); 440 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, (void *)0);
349 441
350 glDisableVertexAttribArray(at_pos); 442 glDisableVertexAttribArray(at_pos);
351 443
352 SDL_GL_SwapWindow(main_window); 444 SDL_GL_SwapWindow(main_window);
445 #endif
353 if (context->regs[REG_MODE_4] & BIT_INTERLACE) 446 if (context->regs[REG_MODE_4] & BIT_INTERLACE)
354 { 447 {
355 context->framebuf = context->framebuf == context->oddbuf ? context->evenbuf : context->oddbuf; 448 context->framebuf = context->framebuf == context->oddbuf ? context->evenbuf : context->oddbuf;
356 } 449 }
357 } 450 }