comparison render_sdl.c @ 449:7696d824489d opengl

Started work on OpenGL support in new branch
author Mike Pavone <pavone@retrodev.com>
date Tue, 23 Jul 2013 23:01:03 -0700
parents add9e2f5c0e3
children c08a4efeee7f
comparison
equal deleted inserted replaced
428:006008a3f370 449:7696d824489d
2 #include <stdio.h> 2 #include <stdio.h>
3 #include "render.h" 3 #include "render.h"
4 #include "blastem.h" 4 #include "blastem.h"
5 #include "io.h" 5 #include "io.h"
6 6
7 #ifndef DISABLE_OPENGL
8 #include <GL/gl.h>
9 #endif
10
7 SDL_Surface *screen; 11 SDL_Surface *screen;
8 uint8_t render_dbg = 0; 12 uint8_t render_dbg = 0;
9 uint8_t debug_pal = 0; 13 uint8_t debug_pal = 0;
14 uint8_t render_gl;
10 15
11 uint32_t last_frame = 0; 16 uint32_t last_frame = 0;
12 17
13 uint32_t min_delay; 18 uint32_t min_delay;
14 uint32_t frame_delay = 1000/60; 19 uint32_t frame_delay = 1000/60;
73 SDL_Joystick * joysticks[MAX_JOYSTICKS]; 78 SDL_Joystick * joysticks[MAX_JOYSTICKS];
74 int num_joysticks; 79 int num_joysticks;
75 80
76 uint32_t render_map_color(uint8_t r, uint8_t g, uint8_t b) 81 uint32_t render_map_color(uint8_t r, uint8_t g, uint8_t b)
77 { 82 {
78 return SDL_MapRGB(screen->format, r, g, b); 83 if (render_gl) {
84 return b << 24 | g << 16 | r << 8 | 255;
85 } else {
86 return SDL_MapRGB(screen->format, r, g, b);
87 }
88 }
89
90 GLuint textures[3], buffers[2];
91
92 const GLfloat vertex_data[] = {
93 -1.0f, -1.0f,
94 1.0f, -1.0f,
95 -1.0f, 1.0f,
96 1.0f, 1.0f
97 };
98
99 const GLushort element_data[] = {0, 1, 2, 3};
100
101 void render_alloc_surfaces(vdp_context * context)
102 {
103 if (render_gl) {
104 context->oddbuf = context->framebuf = malloc(320 * 240 * 4 * 2);
105 memset(context->oddbuf, 0, 320 * 240 * 4 * 2);
106 context->evenbuf = ((char *)context->oddbuf) + 320 * 240 * 4;
107 glGenTextures(3, textures);
108 for (int i = 0; i < 3; i++)
109 {
110 glBindTexture(GL_TEXTURE_2D, textures[i]);
111 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
112 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
113 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
114 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
115 if (i < 2) {
116 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8​, 512, 256, 0, GL_BGRA, GL_UNSIGNED_BYTE, i ? context->evenbuf : context->oddbuf);
117 } else {
118 uint32_t blank = 255;
119 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_BGRA, GL_UNSIGNED_BYTE, &blank);
120 }
121 }
122 glGenBuffers(2, buffers);
123 glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
124 glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW);
125 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[0]);
126 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(element_data), element_data, GL_STATIC_DRAW);
127 } else {
128 context->oddbuf = context->framebuf = malloc(320 * 240 * screen->format->BytesPerPixel * 2);
129 context->evenbuf = ((char *)context->oddbuf) + 320 * 240 * screen->format->BytesPerPixel;
130 }
79 } 131 }
80 132
81 uint8_t render_depth() 133 uint8_t render_depth()
82 { 134 {
83 return screen->format->BytesPerPixel * 8; 135 return screen->format->BytesPerPixel * 8;
84 } 136 }
85 137
86 void render_init(int width, int height, char * title, uint32_t fps) 138 void render_init(int width, int height, char * title, uint32_t fps, uint8_t use_gl)
87 { 139 {
88 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0) { 140 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0) {
89 fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError()); 141 fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
90 exit(1); 142 exit(1);
91 } 143 }
92 atexit(SDL_Quit); 144 atexit(SDL_Quit);
93 atexit(render_close_audio); 145 atexit(render_close_audio);
94 printf("width: %d, height: %d\n", width, height); 146 printf("width: %d, height: %d\n", width, height);
95 screen = SDL_SetVideoMode(width, height, 32, SDL_SWSURFACE | SDL_ANYFORMAT); 147 uint32_t flags
96 if (!screen) { 148 #ifndef DISABLE_OPENGL
97 fprintf(stderr, "Unable to get SDL surface: %s\n", SDL_GetError()); 149 if (use_gl)
98 exit(1); 150 {
99 } 151 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
100 if (screen->format->BytesPerPixel != 2 && screen->format->BytesPerPixel != 4) { 152 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
101 fprintf(stderr, "BlastEm requires a 16-bit or 32-bit surface, SDL returned a %d-bit surface\n", screen->format->BytesPerPixel * 8); 153 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
102 exit(1); 154 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);
103 } 155 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
104 SDL_WM_SetCaption(title, title); 156 flags = SDL_OPENGL;
105 min_delay = 0; 157 } else {
106 for (int i = 0; i < 100; i++) { 158 #else
107 uint32_t start = SDL_GetTicks(); 159 {
108 SDL_Delay(1); 160 #endif
109 uint32_t delay = SDL_GetTicks()-start; 161 flags = SDL_SWSURFACE | SDL_ANYFORMAT;
110 if (delay > min_delay) { 162 }
111 min_delay = delay; 163 screen = SDL_SetVideoMode(width, height, 32, flags);
112 } 164 if (!screen) {
113 } 165 fprintf(stderr, "Unable to get SDL surface: %s\n", SDL_GetError());
114 if (!min_delay) { 166 exit(1);
115 min_delay = 1; 167 }
116 } 168 if (!use_gl && screen->format->BytesPerPixel != 2 && screen->format->BytesPerPixel != 4) {
117 printf("minimum delay: %d\n", min_delay); 169 fprintf(stderr, "BlastEm requires a 16-bit or 32-bit surface, SDL returned a %d-bit surface\n", screen->format->BytesPerPixel * 8);
118 170 exit(1);
119 frame_delay = 1000/fps; 171 }
120 172 #ifndef DISABLE_OPENGL
121 audio_mutex = SDL_CreateMutex(); 173 //TODO: Fallback to plain SDL if OpenGL 2.0 not available
122 psg_cond = SDL_CreateCond(); 174 render_gl = use_gl;
123 ym_cond = SDL_CreateCond(); 175 #endif
124 audio_ready = SDL_CreateCond(); 176 SDL_WM_SetCaption(title, title);
125 177 min_delay = 0;
126 SDL_AudioSpec desired, actual; 178 for (int i = 0; i < 100; i++) {
127 desired.freq = 48000; 179 uint32_t start = SDL_GetTicks();
128 desired.format = AUDIO_S16SYS; 180 SDL_Delay(1);
129 desired.channels = 2; 181 uint32_t delay = SDL_GetTicks()-start;
130 desired.samples = 2048;//1024; 182 if (delay > min_delay) {
131 desired.callback = audio_callback; 183 min_delay = delay;
132 desired.userdata = NULL; 184 }
133 185 }
134 if (SDL_OpenAudio(&desired, &actual) < 0) { 186 if (!min_delay) {
135 fprintf(stderr, "Unable to open SDL audio: %s\n", SDL_GetError()); 187 min_delay = 1;
136 exit(1); 188 }
137 } 189 printf("minimum delay: %d\n", min_delay);
138 buffer_samples = actual.samples; 190
139 sample_rate = actual.freq; 191 frame_delay = 1000/fps;
140 printf("Initialized audio at frequency %d with a %d sample buffer\n", actual.freq, actual.samples); 192
141 SDL_PauseAudio(0); 193 audio_mutex = SDL_CreateMutex();
142 num_joysticks = SDL_NumJoysticks(); 194 psg_cond = SDL_CreateCond();
143 if (num_joysticks > MAX_JOYSTICKS) { 195 ym_cond = SDL_CreateCond();
144 num_joysticks = MAX_JOYSTICKS; 196 audio_ready = SDL_CreateCond();
145 } 197
146 for (int i = 0; i < num_joysticks; i++) { 198 SDL_AudioSpec desired, actual;
147 printf("Joystick %d: %s\n", i, SDL_JoystickName(i)); 199 desired.freq = 48000;
148 SDL_Joystick * joy = joysticks[i] = SDL_JoystickOpen(i); 200 desired.format = AUDIO_S16SYS;
149 if (joy) { 201 desired.channels = 2;
150 printf("\tNum Axes: %d\n\tNum Buttons: %d\n\tNum Hats: %d\n", SDL_JoystickNumAxes(joy), SDL_JoystickNumButtons(joy), SDL_JoystickNumHats(joy)); 202 desired.samples = 2048;//1024;
151 } 203 desired.callback = audio_callback;
152 } 204 desired.userdata = NULL;
153 SDL_JoystickEventState(SDL_ENABLE); 205
206 if (SDL_OpenAudio(&desired, &actual) < 0) {
207 fprintf(stderr, "Unable to open SDL audio: %s\n", SDL_GetError());
208 exit(1);
209 }
210 buffer_samples = actual.samples;
211 sample_rate = actual.freq;
212 printf("Initialized audio at frequency %d with a %d sample buffer\n", actual.freq, actual.samples);
213 SDL_PauseAudio(0);
214 num_joysticks = SDL_NumJoysticks();
215 if (num_joysticks > MAX_JOYSTICKS) {
216 num_joysticks = MAX_JOYSTICKS;
217 }
218 for (int i = 0; i < num_joysticks; i++) {
219 printf("Joystick %d: %s\n", i, SDL_JoystickName(i));
220 SDL_Joystick * joy = joysticks[i] = SDL_JoystickOpen(i);
221 if (joy) {
222 printf("\tNum Axes: %d\n\tNum Buttons: %d\n\tNum Hats: %d\n", SDL_JoystickNumAxes(joy), SDL_JoystickNumButtons(joy), SDL_JoystickNumHats(joy));
223 }
224 }
225 SDL_JoystickEventState(SDL_ENABLE);
226 }
227
228 void render_context_gl(vdp_context * context)
229 {
230 glBindTexture(GL_TEXTURE_2D, textures[context->framebuf == context->oddbuf ? 0 : 1]);
231 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 320, 240, GL_BGRA, GL_UNSIGNED_BYTE, context->framebuf);;
232
233 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
234 glClear(GL_COLOR_BUFFER_BIT);
235
154 } 236 }
155 237
156 uint32_t blankbuf[320*240]; 238 uint32_t blankbuf[320*240];
157 239
158 void render_context(vdp_context * context) 240 void render_context(vdp_context * context)
159 { 241 {
160 uint16_t *buf_16; 242 uint16_t *buf_16;
161 uint32_t *buf_32; 243 uint32_t *buf_32;
162 uint8_t b,g,r; 244 uint8_t b,g,r;
163 last_frame = SDL_GetTicks(); 245 last_frame = SDL_GetTicks();
246 if (render_gl)
247 {
248 render_context_gl(context);
249 return;
250 }
164 if (SDL_MUSTLOCK(screen)) { 251 if (SDL_MUSTLOCK(screen)) {
165 if (SDL_LockSurface(screen) < 0) { 252 if (SDL_LockSurface(screen) < 0) {
166 return; 253 return;
167 } 254 }
168 } 255 }
169 uint16_t repeat_x = screen->clip_rect.w / 320; 256 uint16_t repeat_x = screen->clip_rect.w / 320;
170 uint16_t repeat_y = screen->clip_rect.h / 240; 257 uint16_t repeat_y = screen->clip_rect.h / 240;
171 if (repeat_x > repeat_y) { 258 if (repeat_x > repeat_y) {
172 repeat_x = repeat_y; 259 repeat_x = repeat_y;
173 } else { 260 } else {
174 repeat_y = repeat_x; 261 repeat_y = repeat_x;
175 } 262 }
176 int othermask = repeat_y >> 1; 263 int othermask = repeat_y >> 1;
177 264
178 if (screen->format->BytesPerPixel == 2) { 265 if (screen->format->BytesPerPixel == 2) {
179 uint16_t *otherbuf = (context->regs[REG_MODE_4] & BIT_INTERLACE) ? context->evenbuf : (uint16_t *)blankbuf; 266 uint16_t *otherbuf = (context->regs[REG_MODE_4] & BIT_INTERLACE) ? context->evenbuf : (uint16_t *)blankbuf;
180 uint16_t * oddbuf = context->oddbuf; 267 uint16_t * oddbuf = context->oddbuf;
181 buf_16 = (uint16_t *)screen->pixels; 268 buf_16 = (uint16_t *)screen->pixels;
182 for (int y = 0; y < 240; y++) { 269 for (int y = 0; y < 240; y++) {
183 for (int i = 0; i < repeat_y; i++,buf_16 += screen->pitch/2) { 270 for (int i = 0; i < repeat_y; i++,buf_16 += screen->pitch/2) {
184 uint16_t *line = buf_16; 271 uint16_t *line = buf_16;
185 uint16_t *src_line = (i & othermask ? otherbuf : oddbuf) + y * 320; 272 uint16_t *src_line = (i & othermask ? otherbuf : oddbuf) + y * 320;
186 for (int x = 0; x < 320; x++) { 273 for (int x = 0; x < 320; x++) {
187 uint16_t color = *(src_line++); 274 uint16_t color = *(src_line++);
188 for (int j = 0; j < repeat_x; j++) { 275 for (int j = 0; j < repeat_x; j++) {
189 *(line++) = color; 276 *(line++) = color;
190 } 277 }
191 } 278 }
192 } 279 }
193 } 280 }
194 } else { 281 } else {
195 uint32_t *otherbuf = (context->regs[REG_MODE_4] & BIT_INTERLACE) ? context->evenbuf : (uint32_t *)blankbuf; 282 uint32_t *otherbuf = (context->regs[REG_MODE_4] & BIT_INTERLACE) ? context->evenbuf : (uint32_t *)blankbuf;
196 uint32_t * oddbuf = context->oddbuf; 283 uint32_t * oddbuf = context->oddbuf;
197 buf_32 = (uint32_t *)screen->pixels; 284 buf_32 = (uint32_t *)screen->pixels;
198 for (int y = 0; y < 240; y++) { 285 for (int y = 0; y < 240; y++) {
199 for (int i = 0; i < repeat_y; i++,buf_32 += screen->pitch/4) { 286 for (int i = 0; i < repeat_y; i++,buf_32 += screen->pitch/4) {
200 uint32_t *line = buf_32; 287 uint32_t *line = buf_32;
201 uint32_t *src_line = (i & othermask ? otherbuf : oddbuf) + y * 320; 288 uint32_t *src_line = (i & othermask ? otherbuf : oddbuf) + y * 320;
202 for (int x = 0; x < 320; x++) { 289 for (int x = 0; x < 320; x++) {
203 uint32_t color = *(src_line++); 290 uint32_t color = *(src_line++);
204 for (int j = 0; j < repeat_x; j++) { 291 for (int j = 0; j < repeat_x; j++) {
205 *(line++) = color; 292 *(line++) = color;
206 } 293 }
207 } 294 }
208 } 295 }
209 } 296 }
210 } 297 }
211 if ( SDL_MUSTLOCK(screen) ) { 298 if ( SDL_MUSTLOCK(screen) ) {
212 SDL_UnlockSurface(screen); 299 SDL_UnlockSurface(screen);
213 } 300 }
214 SDL_UpdateRect(screen, 0, 0, screen->clip_rect.w, screen->clip_rect.h); 301 SDL_UpdateRect(screen, 0, 0, screen->clip_rect.w, screen->clip_rect.h);
215 if (context->regs[REG_MODE_4] & BIT_INTERLACE) 302 if (context->regs[REG_MODE_4] & BIT_INTERLACE)
216 { 303 {
217 context->framebuf = context->framebuf == context->oddbuf ? context->evenbuf : context->oddbuf; 304 context->framebuf = context->framebuf == context->oddbuf ? context->evenbuf : context->oddbuf;
218 } 305 }
219 } 306 }
220 307
221 int render_joystick_num_buttons(int joystick) 308 int render_joystick_num_buttons(int joystick)
222 { 309 {
223 if (joystick >= num_joysticks) { 310 if (joystick >= num_joysticks) {
319 while ((desired) >= SDL_GetTicks()) { 406 while ((desired) >= SDL_GetTicks()) {
320 } 407 }
321 } 408 }
322 } 409 }
323 render_context(context); 410 render_context(context);
324 411
325 412
326 //TODO: Figure out why this causes segfaults 413 //TODO: Figure out why this causes segfaults
327 /*frame_counter++; 414 /*frame_counter++;
328 if ((last_frame - start) > 1000) { 415 if ((last_frame - start) > 1000) {
329 if (start && (last_frame-start)) { 416 if (start && (last_frame-start)) {
330 printf("\r%f fps", ((float)frame_counter) / (((float)(last_frame-start)) / 1000.0)); 417 printf("\r%f fps", ((float)frame_counter) / (((float)(last_frame-start)) / 1000.0));