Mercurial > repos > blastem
comparison render_sdl.c @ 744:fc68992cf18d
Merge windows branch with latest changes
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Thu, 28 May 2015 21:19:55 -0700 |
parents | 2e1b3b258523 019d27995e32 |
children | daa31ee7d8cd |
comparison
equal
deleted
inserted
replaced
743:cf78cb045fa4 | 744:fc68992cf18d |
---|---|
9 #include "render.h" | 9 #include "render.h" |
10 #include "blastem.h" | 10 #include "blastem.h" |
11 #include "io.h" | 11 #include "io.h" |
12 #include "util.h" | 12 #include "util.h" |
13 | 13 |
14 #ifndef DISABLE_OPENGL | |
15 #include <GL/glew.h> | 14 #include <GL/glew.h> |
16 #endif | 15 |
17 | 16 SDL_Window *main_window; |
18 SDL_Surface *screen; | 17 SDL_GLContext *main_context; |
19 uint8_t render_dbg = 0; | 18 uint8_t render_dbg = 0; |
20 uint8_t debug_pal = 0; | 19 uint8_t debug_pal = 0; |
21 uint8_t render_gl = 1; | |
22 | 20 |
23 uint32_t last_frame = 0; | 21 uint32_t last_frame = 0; |
24 | 22 |
25 uint32_t min_delay; | 23 uint32_t min_delay; |
26 uint32_t frame_delay = 1000/60; | 24 uint32_t frame_delay = 1000/60; |
90 return num_joysticks; | 88 return num_joysticks; |
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 return 255 << 24 | r << 16 | g << 8 | b; |
96 return 255 << 24 | r << 16 | g << 8 | b; | 94 } |
97 } else { | 95 |
98 return SDL_MapRGB(screen->format, r, g, b); | |
99 } | |
100 } | |
101 | |
102 #ifndef DISABLE_OPENGL | |
103 GLuint textures[3], buffers[2], vshader, fshader, program, un_textures[2], un_width, at_pos; | 96 GLuint textures[3], buffers[2], vshader, fshader, program, un_textures[2], un_width, at_pos; |
104 | 97 |
105 GLfloat vertex_data[] = { | 98 GLfloat vertex_data[] = { |
106 -1.0f, -1.0f, | 99 -1.0f, -1.0f, |
107 1.0f, -1.0f, | 100 1.0f, -1.0f, |
111 | 104 |
112 const GLushort element_data[] = {0, 1, 2, 3}; | 105 const GLushort element_data[] = {0, 1, 2, 3}; |
113 | 106 |
114 GLuint load_shader(char * fname, GLenum shader_type) | 107 GLuint load_shader(char * fname, GLenum shader_type) |
115 { | 108 { |
116 char * parts[] = {get_home_dir(), "/.config/blastem/shaders/", fname}; | 109 char * parts[] = {getenv("HOME"), "/.config/blastem/shaders/", fname}; |
117 char * shader_path = alloc_concat_m(3, parts); | 110 char * shader_path = alloc_concat_m(3, parts); |
118 printf("Trying to find shader at %s\n", shader_path); | |
119 FILE * f = fopen(shader_path, "r"); | 111 FILE * f = fopen(shader_path, "r"); |
120 free(shader_path); | 112 free(shader_path); |
121 if (!f) { | 113 if (!f) { |
122 #ifdef _WIN32 | |
123 parts[0] = "shaders/"; | |
124 parts[1] = fname; | |
125 shader_path = alloc_concat_m(2, parts); | |
126 #else | |
127 parts[0] = get_exe_dir(); | 114 parts[0] = get_exe_dir(); |
128 parts[1] = "/shaders/"; | 115 parts[1] = "/shaders/"; |
129 shader_path = alloc_concat_m(3, parts); | 116 shader_path = alloc_concat_m(3, parts); |
130 #endif | |
131 printf("Trying to find shader at %s\n", shader_path); | |
132 f = fopen(shader_path, "r"); | 117 f = fopen(shader_path, "r"); |
133 free(shader_path); | 118 free(shader_path); |
134 if (!f) { | 119 if (!f) { |
135 fprintf(stderr, "Failed to open shader file %s for reading\n", fname); | 120 fprintf(stderr, "Failed to open shader file %s for reading\n", fname); |
136 return 0; | 121 return 0; |
137 } | 122 } |
138 } | 123 } |
139 puts("reading shader"); | |
140 long fsize = file_size(f); | 124 long fsize = file_size(f); |
141 GLchar * text = malloc(fsize); | 125 GLchar * text = malloc(fsize); |
142 if (fread(text, 1, fsize, f) != fsize) { | 126 if (fread(text, 1, fsize, f) != fsize) { |
143 fprintf(stderr, "Error reading from shader file %s\n", fname); | 127 fprintf(stderr, "Error reading from shader file %s\n", fname); |
144 free(text); | 128 free(text); |
145 return 0; | 129 return 0; |
146 } | 130 } |
147 GLuint ret = glCreateShader(shader_type); | 131 GLuint ret = glCreateShader(shader_type); |
148 glShaderSource(ret, 1, (const GLchar **)&text, (const GLint *)&fsize); | 132 glShaderSource(ret, 1, (const GLchar **)&text, (const GLint *)&fsize); |
149 free(text); | 133 free(text); |
150 puts("compiling shader"); | |
151 glCompileShader(ret); | 134 glCompileShader(ret); |
152 GLint compile_status, loglen; | 135 GLint compile_status, loglen; |
153 glGetShaderiv(ret, GL_COMPILE_STATUS, &compile_status); | 136 glGetShaderiv(ret, GL_COMPILE_STATUS, &compile_status); |
154 if (!compile_status) { | 137 if (!compile_status) { |
155 fprintf(stderr, "Shader %s failed to compile\n", fname); | 138 fprintf(stderr, "Shader %s failed to compile\n", fname); |
161 glDeleteShader(ret); | 144 glDeleteShader(ret); |
162 return 0; | 145 return 0; |
163 } | 146 } |
164 return ret; | 147 return ret; |
165 } | 148 } |
166 #endif | |
167 | 149 |
168 void render_alloc_surfaces(vdp_context * context) | 150 void render_alloc_surfaces(vdp_context * context) |
169 { | 151 { |
170 #ifndef DISABLE_OPENGL | 152 context->oddbuf = context->framebuf = malloc(512 * 256 * 4 * 2); |
171 if (render_gl) { | 153 memset(context->oddbuf, 0, 512 * 256 * 4 * 2); |
172 context->oddbuf = context->framebuf = malloc(512 * 256 * 4 * 2); | 154 context->evenbuf = ((char *)context->oddbuf) + 512 * 256 * 4; |
173 memset(context->oddbuf, 0, 512 * 256 * 4 * 2); | 155 glGenTextures(3, textures); |
174 context->evenbuf = ((char *)context->oddbuf) + 512 * 256 * 4; | 156 for (int i = 0; i < 3; i++) |
175 puts("generating textures"); | 157 { |
176 glGenTextures(3, textures); | 158 glBindTexture(GL_TEXTURE_2D, textures[i]); |
177 for (int i = 0; i < 3; i++) | 159 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
178 { | 160 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
179 glBindTexture(GL_TEXTURE_2D, textures[i]); | 161 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
180 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 162 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
181 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 163 if (i < 2) { |
182 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 164 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 512, 256, 0, GL_BGRA, GL_UNSIGNED_BYTE, i ? context->evenbuf : context->oddbuf); |
183 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 165 } else { |
184 if (i < 2) { | 166 uint32_t blank = 255 << 24; |
185 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 512, 256, 0, GL_BGRA, GL_UNSIGNED_BYTE, i ? context->evenbuf : context->oddbuf); | 167 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_BGRA, GL_UNSIGNED_BYTE, &blank); |
186 } else { | 168 } |
187 uint32_t blank = 255 << 24; | 169 } |
188 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_BGRA, GL_UNSIGNED_BYTE, &blank); | 170 glGenBuffers(2, buffers); |
189 } | 171 glBindBuffer(GL_ARRAY_BUFFER, buffers[0]); |
190 } | 172 glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW); |
191 glGenBuffers(2, buffers); | 173 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]); |
192 glBindBuffer(GL_ARRAY_BUFFER, buffers[0]); | 174 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(element_data), element_data, GL_STATIC_DRAW); |
193 glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW); | 175 vshader = load_shader(tern_find_ptr_default(config, "videovertex_shader", "default.v.glsl"), GL_VERTEX_SHADER); |
194 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]); | 176 fshader = load_shader(tern_find_ptr_default(config, "videofragment_shader", "default.f.glsl"), GL_FRAGMENT_SHADER); |
195 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(element_data), element_data, GL_STATIC_DRAW); | 177 program = glCreateProgram(); |
196 puts("Loading vertex shader"); | 178 glAttachShader(program, vshader); |
197 vshader = load_shader(tern_find_ptr_default(config, "videovertex_shader", "default.v.glsl"), GL_VERTEX_SHADER); | 179 glAttachShader(program, fshader); |
198 puts("loading fragment shader"); | 180 glLinkProgram(program); |
199 fshader = load_shader(tern_find_ptr_default(config, "videofragment_shader", "default.f.glsl"), GL_FRAGMENT_SHADER); | 181 GLint link_status; |
200 puts("creating program"); | 182 glGetProgramiv(program, GL_LINK_STATUS, &link_status); |
201 program = glCreateProgram(); | 183 if (!link_status) { |
202 glAttachShader(program, vshader); | 184 fputs("Failed to link shader program\n", stderr); |
203 glAttachShader(program, fshader); | 185 exit(1); |
204 puts("linking program"); | 186 } |
205 glLinkProgram(program); | 187 un_textures[0] = glGetUniformLocation(program, "textures[0]"); |
206 GLint link_status; | 188 un_textures[1] = glGetUniformLocation(program, "textures[1]"); |
207 glGetProgramiv(program, GL_LINK_STATUS, &link_status); | 189 un_width = glGetUniformLocation(program, "width"); |
208 if (!link_status) { | 190 at_pos = glGetAttribLocation(program, "pos"); |
209 fputs("Failed to link shader program\n", stderr); | |
210 exit(1); | |
211 } | |
212 un_textures[0] = glGetUniformLocation(program, "textures[0]"); | |
213 un_textures[1] = glGetUniformLocation(program, "textures[1]"); | |
214 un_width = glGetUniformLocation(program, "width"); | |
215 at_pos = glGetAttribLocation(program, "pos"); | |
216 } else { | |
217 #endif | |
218 context->oddbuf = context->framebuf = malloc(320 * 240 * screen->format->BytesPerPixel * 2); | |
219 context->evenbuf = ((char *)context->oddbuf) + 320 * 240 * screen->format->BytesPerPixel; | |
220 #ifndef DISABLE_OPENGL | |
221 } | |
222 #endif | |
223 puts("alloc surfaces done"); | |
224 } | |
225 | |
226 uint8_t render_depth() | |
227 { | |
228 return screen->format->BytesPerPixel * 8; | |
229 } | 191 } |
230 | 192 |
231 char * caption = NULL; | 193 char * caption = NULL; |
232 | 194 |
233 void render_init(int width, int height, char * title, uint32_t fps, uint8_t fullscreen, uint8_t use_gl) | 195 void render_init(int width, int height, char * title, uint32_t fps, uint8_t fullscreen) |
234 { | 196 { |
235 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0) { | 197 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0) { |
236 fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError()); | 198 fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError()); |
237 exit(1); | 199 exit(1); |
238 } | 200 } |
239 atexit(SDL_Quit); | |
240 atexit(render_close_audio); | |
241 printf("width: %d, height: %d\n", width, height); | 201 printf("width: %d, height: %d\n", width, height); |
242 uint32_t flags = SDL_ANYFORMAT; | 202 uint32_t flags = SDL_WINDOW_OPENGL; |
243 | 203 |
244 #ifndef DISABLE_OPENGL | 204 |
245 if (use_gl) | 205 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); |
246 { | 206 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5); |
247 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); | 207 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); |
248 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5); | 208 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0); |
249 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); | 209 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); |
250 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0); | 210 if (fullscreen) { |
251 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); | 211 flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; |
252 flags = SDL_OPENGL; | 212 SDL_DisplayMode mode; |
253 if (fullscreen) { | 213 //TODO: Multiple monitor support |
254 flags |= SDL_FULLSCREEN; | 214 SDL_GetCurrentDisplayMode(0, &mode); |
255 } | 215 //the SDL2 migration guide suggests setting width and height to 0 when using SDL_WINDOW_FULLSCREEN_DESKTOP |
256 } else { | 216 //but that doesn't seem to work right when using OpenGL, at least on Linux anyway |
257 #else | 217 width = mode.w; |
258 { | 218 height = mode.h; |
259 #endif | 219 } |
260 if (fullscreen) { | 220 main_window = SDL_CreateWindow(title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, flags); |
261 flags |= SDL_FULLSCREEN | SDL_HWSURFACE | SDL_DOUBLEBUF; | 221 if (!main_window) { |
262 } else { | 222 fprintf(stderr, "Unable to create SDL window: %s\n", SDL_GetError()); |
263 flags |= SDL_SWSURFACE; | 223 SDL_Quit(); |
264 } | |
265 } | |
266 screen = SDL_SetVideoMode(width, height, 32, flags); | |
267 if (!screen) { | |
268 fprintf(stderr, "Unable to get SDL surface: %s\n", SDL_GetError()); | |
269 exit(1); | 224 exit(1); |
270 } | 225 } |
271 if (!use_gl && screen->format->BytesPerPixel != 2 && screen->format->BytesPerPixel != 4) { | 226 SDL_GetWindowSize(main_window, &width, &height); |
272 fprintf(stderr, "BlastEm requires a 16-bit or 32-bit surface, SDL returned a %d-bit surface\n", screen->format->BytesPerPixel * 8); | 227 printf("Window created with size: %d x %d\n", width, height); |
228 main_context = SDL_GL_CreateContext(main_window); | |
229 GLenum res = glewInit(); | |
230 if (res != GLEW_OK) { | |
231 fprintf(stderr, "Initialization of GLEW failed with code %d\n", res); | |
232 SDL_Quit(); | |
273 exit(1); | 233 exit(1); |
274 } | 234 } |
275 #ifndef DISABLE_OPENGL | 235 if (!GLEW_VERSION_2_0) { |
276 //TODO: fallback on standard rendering if OpenGL 2.0 is unavailable or if init fails | 236 fputs("BlastEm requires at least OpenGL 2.0, but it is unavailable\n", stderr); |
277 if (use_gl) | 237 SDL_Quit(); |
278 { | 238 exit(1); |
279 GLenum res = glewInit(); | 239 } |
280 if (res != GLEW_OK) { | 240 float aspect = (float)width / height; |
281 fprintf(stderr, "Initialization of GLEW failed with code %d\n", res); | 241 if (fabs(aspect - 4.0/3.0) > 0.01 && strcmp(tern_find_ptr_default(config, "videoaspect", "normal"), "stretch")) { |
282 exit(1); | 242 for (int i = 0; i < 4; i++) |
283 } | 243 { |
284 if (!GLEW_VERSION_2_0) { | 244 if (aspect > 4.0/3.0) { |
285 fputs("OpenGL 2.0 is unable, falling back to standard SDL rendering\n", stderr); | 245 vertex_data[i*2] *= (4.0/3.0)/aspect; |
286 exit(1); | 246 } else { |
287 } | 247 vertex_data[i*2+1] *= aspect/(4.0/3.0); |
288 float aspect = (float)width / height; | 248 } |
289 if (fabs(aspect - 4.0/3.0) > 0.01 && strcmp(tern_find_ptr_default(config, "videoaspect", "normal"), "stretch")) { | 249 } |
290 for (int i = 0; i < 4; i++) | 250 } |
291 { | |
292 if (aspect > 4.0/3.0) { | |
293 vertex_data[i*2] *= (4.0/3.0)/aspect; | |
294 } else { | |
295 vertex_data[i*2+1] *= aspect/(4.0/3.0); | |
296 } | |
297 } | |
298 } | |
299 } | |
300 render_gl = use_gl; | |
301 #endif | |
302 SDL_WM_SetCaption(title, title); | |
303 caption = title; | 251 caption = title; |
304 min_delay = 0; | 252 min_delay = 0; |
305 for (int i = 0; i < 100; i++) { | 253 for (int i = 0; i < 100; i++) { |
306 uint32_t start = SDL_GetTicks(); | 254 uint32_t start = SDL_GetTicks(); |
307 SDL_Delay(1); | 255 SDL_Delay(1); |
341 desired.callback = audio_callback; | 289 desired.callback = audio_callback; |
342 desired.userdata = NULL; | 290 desired.userdata = NULL; |
343 | 291 |
344 if (SDL_OpenAudio(&desired, &actual) < 0) { | 292 if (SDL_OpenAudio(&desired, &actual) < 0) { |
345 fprintf(stderr, "Unable to open SDL audio: %s\n", SDL_GetError()); | 293 fprintf(stderr, "Unable to open SDL audio: %s\n", SDL_GetError()); |
294 SDL_Quit(); | |
346 exit(1); | 295 exit(1); |
347 } | 296 } |
348 buffer_samples = actual.samples; | 297 buffer_samples = actual.samples; |
349 sample_rate = actual.freq; | 298 sample_rate = actual.freq; |
350 printf("Initialized audio at frequency %d with a %d sample buffer\n", actual.freq, actual.samples); | 299 printf("Initialized audio at frequency %d with a %d sample buffer\n", actual.freq, actual.samples); |
352 num_joysticks = SDL_NumJoysticks(); | 301 num_joysticks = SDL_NumJoysticks(); |
353 if (num_joysticks > MAX_JOYSTICKS) { | 302 if (num_joysticks > MAX_JOYSTICKS) { |
354 num_joysticks = MAX_JOYSTICKS; | 303 num_joysticks = MAX_JOYSTICKS; |
355 } | 304 } |
356 for (int i = 0; i < num_joysticks; i++) { | 305 for (int i = 0; i < num_joysticks; i++) { |
357 printf("Joystick %d: %s\n", i, SDL_JoystickName(i)); | |
358 SDL_Joystick * joy = joysticks[i] = SDL_JoystickOpen(i); | 306 SDL_Joystick * joy = joysticks[i] = SDL_JoystickOpen(i); |
307 printf("Joystick %d: %s\n", i, SDL_JoystickName(joy)); | |
359 if (joy) { | 308 if (joy) { |
360 printf("\tNum Axes: %d\n\tNum Buttons: %d\n\tNum Hats: %d\n", SDL_JoystickNumAxes(joy), SDL_JoystickNumButtons(joy), SDL_JoystickNumHats(joy)); | 309 printf("\tNum Axes: %d\n\tNum Buttons: %d\n\tNum Hats: %d\n", SDL_JoystickNumAxes(joy), SDL_JoystickNumButtons(joy), SDL_JoystickNumHats(joy)); |
361 } | 310 } |
362 } | 311 } |
363 SDL_JoystickEventState(SDL_ENABLE); | 312 SDL_JoystickEventState(SDL_ENABLE); |
364 } | 313 |
365 #ifndef DISABLE_OPENGL | 314 atexit(SDL_Quit); |
366 void render_context_gl(vdp_context * context) | 315 atexit(render_close_audio); |
367 { | 316 } |
317 | |
318 void render_context(vdp_context * context) | |
319 { | |
320 last_frame = SDL_GetTicks(); | |
321 | |
368 glBindTexture(GL_TEXTURE_2D, textures[context->framebuf == context->oddbuf ? 0 : 1]); | 322 glBindTexture(GL_TEXTURE_2D, textures[context->framebuf == context->oddbuf ? 0 : 1]); |
369 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 320, 240, GL_BGRA, GL_UNSIGNED_BYTE, context->framebuf);; | 323 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 320, 240, GL_BGRA, GL_UNSIGNED_BYTE, context->framebuf);; |
370 | 324 |
371 glClearColor(0.0f, 0.0f, 0.0f, 1.0f); | 325 glClearColor(0.0f, 0.0f, 0.0f, 1.0f); |
372 glClear(GL_COLOR_BUFFER_BIT); | 326 glClear(GL_COLOR_BUFFER_BIT); |
378 | 332 |
379 glActiveTexture(GL_TEXTURE1); | 333 glActiveTexture(GL_TEXTURE1); |
380 glBindTexture(GL_TEXTURE_2D, (context->regs[REG_MODE_4] & BIT_INTERLACE) ? textures[1] : textures[2]); | 334 glBindTexture(GL_TEXTURE_2D, (context->regs[REG_MODE_4] & BIT_INTERLACE) ? textures[1] : textures[2]); |
381 glUniform1i(un_textures[1], 1); | 335 glUniform1i(un_textures[1], 1); |
382 | 336 |
383 glUniform1f(un_width, context->latched_mode & BIT_H40 ? 320.0f : 256.0f); | 337 glUniform1f(un_width, context->regs[REG_MODE_4] & BIT_H40 ? 320.0f : 256.0f); |
384 | 338 |
385 glBindBuffer(GL_ARRAY_BUFFER, buffers[0]); | 339 glBindBuffer(GL_ARRAY_BUFFER, buffers[0]); |
386 glVertexAttribPointer(at_pos, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat[2]), (void *)0); | 340 glVertexAttribPointer(at_pos, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat[2]), (void *)0); |
387 glEnableVertexAttribArray(at_pos); | 341 glEnableVertexAttribArray(at_pos); |
388 | 342 |
389 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]); | 343 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]); |
390 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, (void *)0); | 344 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, (void *)0); |
391 | 345 |
392 glDisableVertexAttribArray(at_pos); | 346 glDisableVertexAttribArray(at_pos); |
393 | 347 |
394 SDL_GL_SwapBuffers(); | 348 SDL_GL_SwapWindow(main_window); |
395 if (context->regs[REG_MODE_4] & BIT_INTERLACE) | |
396 { | |
397 context->framebuf = context->framebuf == context->oddbuf ? context->evenbuf : context->oddbuf; | |
398 } | |
399 } | |
400 #endif | |
401 | |
402 uint32_t blankbuf[320*240]; | |
403 | |
404 void render_context(vdp_context * context) | |
405 { | |
406 uint16_t *buf_16; | |
407 uint32_t *buf_32; | |
408 uint8_t b,g,r; | |
409 last_frame = SDL_GetTicks(); | |
410 #ifndef DISABLE_OPENGL | |
411 if (render_gl) | |
412 { | |
413 render_context_gl(context); | |
414 return; | |
415 } | |
416 #endif | |
417 if (SDL_MUSTLOCK(screen)) { | |
418 if (SDL_LockSurface(screen) < 0) { | |
419 return; | |
420 } | |
421 } | |
422 uint16_t repeat_x = screen->clip_rect.w / 320; | |
423 uint16_t repeat_y = screen->clip_rect.h / 240; | |
424 if (repeat_x > repeat_y) { | |
425 repeat_x = repeat_y; | |
426 } else { | |
427 repeat_y = repeat_x; | |
428 } | |
429 int othermask = repeat_y >> 1; | |
430 | |
431 if (screen->format->BytesPerPixel == 2) { | |
432 uint16_t *otherbuf = (context->regs[REG_MODE_4] & BIT_INTERLACE) ? context->evenbuf : (uint16_t *)blankbuf; | |
433 uint16_t * oddbuf = context->oddbuf; | |
434 buf_16 = (uint16_t *)screen->pixels; | |
435 for (int y = 0; y < 240; y++) { | |
436 for (int i = 0; i < repeat_y; i++,buf_16 += screen->pitch/2) { | |
437 uint16_t *line = buf_16; | |
438 uint16_t *src_line = (i & othermask ? otherbuf : oddbuf) + y * 320; | |
439 for (int x = 0; x < 320; x++) { | |
440 uint16_t color = *(src_line++); | |
441 for (int j = 0; j < repeat_x; j++) { | |
442 *(line++) = color; | |
443 } | |
444 } | |
445 } | |
446 } | |
447 } else { | |
448 uint32_t *otherbuf = (context->regs[REG_MODE_4] & BIT_INTERLACE) ? context->evenbuf : (uint32_t *)blankbuf; | |
449 uint32_t * oddbuf = context->oddbuf; | |
450 buf_32 = (uint32_t *)screen->pixels; | |
451 for (int y = 0; y < 240; y++) { | |
452 for (int i = 0; i < repeat_y; i++,buf_32 += screen->pitch/4) { | |
453 uint32_t *line = buf_32; | |
454 uint32_t *src_line = (i & othermask ? otherbuf : oddbuf) + y * 320; | |
455 for (int x = 0; x < 320; x++) { | |
456 uint32_t color = *(src_line++); | |
457 for (int j = 0; j < repeat_x; j++) { | |
458 *(line++) = color; | |
459 } | |
460 } | |
461 } | |
462 } | |
463 } | |
464 if ( SDL_MUSTLOCK(screen) ) { | |
465 SDL_UnlockSurface(screen); | |
466 } | |
467 //SDL_UpdateRect(screen, 0, 0, screen->clip_rect.w, screen->clip_rect.h); | |
468 SDL_Flip(screen); | |
469 if (context->regs[REG_MODE_4] & BIT_INTERLACE) | 349 if (context->regs[REG_MODE_4] & BIT_INTERLACE) |
470 { | 350 { |
471 context->framebuf = context->framebuf == context->oddbuf ? context->evenbuf : context->oddbuf; | 351 context->framebuf = context->framebuf == context->oddbuf ? context->evenbuf : context->oddbuf; |
472 } | 352 } |
473 } | 353 } |
576 } | 456 } |
577 } | 457 } |
578 } | 458 } |
579 render_context(context); | 459 render_context(context); |
580 | 460 |
581 | |
582 //TODO: Figure out why this causes segfaults | |
583 frame_counter++; | 461 frame_counter++; |
584 if ((last_frame - start) > 1000) { | 462 if ((last_frame - start) > 1000) { |
585 if (start && (last_frame-start)) { | 463 if (start && (last_frame-start)) { |
586 if (!fps_caption) { | 464 if (!fps_caption) { |
587 fps_caption = malloc(strlen(caption) + strlen(" - 1000.1 fps") + 1); | 465 fps_caption = malloc(strlen(caption) + strlen(" - 1000.1 fps") + 1); |
588 } | 466 } |
589 sprintf(fps_caption, "%s - %.1f fps", caption, ((float)frame_counter) / (((float)(last_frame-start)) / 1000.0)); | 467 sprintf(fps_caption, "%s - %.1f fps", caption, ((float)frame_counter) / (((float)(last_frame-start)) / 1000.0)); |
590 SDL_WM_SetCaption(fps_caption, caption); | 468 SDL_SetWindowTitle(main_window, fps_caption); |
591 fflush(stdout); | |
592 } | 469 } |
593 start = last_frame; | 470 start = last_frame; |
594 frame_counter = 0; | 471 frame_counter = 0; |
595 } | 472 } |
596 return ret; | 473 return ret; |