Mercurial > repos > blastem
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 } |