Mercurial > sdl-ios-xcode
comparison src/video/ps3/SDL_ps3render.c @ 3142:c146645a770e gsoc2009_ps3
Roughly working framebuffer.
author | Martin Lowinski <martin@goldtopf.org> |
---|---|
date | Thu, 04 Jun 2009 07:02:15 +0000 |
parents | 3df74541339b |
children | 8fdabaa064c3 |
comparison
equal
deleted
inserted
replaced
3141:3df74541339b | 3142:c146645a770e |
---|---|
23 | 23 |
24 #include "SDL_video.h" | 24 #include "SDL_video.h" |
25 #include "../SDL_sysvideo.h" | 25 #include "../SDL_sysvideo.h" |
26 #include "../SDL_yuv_sw_c.h" | 26 #include "../SDL_yuv_sw_c.h" |
27 #include "../SDL_renderer_sw.h" | 27 #include "../SDL_renderer_sw.h" |
28 | |
29 #include "SDL_ps3video.h" | |
30 #include "spulibs/spu_common.h" | |
31 | |
32 #include <fcntl.h> | |
33 #include <stdlib.h> | |
34 #include <sys/ioctl.h> | |
35 #include <linux/kd.h> | |
36 #include <linux/fb.h> | |
37 #include <sys/mman.h> | |
38 | |
39 #include <asm/ps3fb.h> | |
28 | 40 |
29 /* Debugging | 41 /* Debugging |
30 * 0: No debug messages | 42 * 0: No debug messages |
31 * 1: Video debug messages | 43 * 1: Video debug messages |
32 * 2: SPE debug messages | 44 * 2: SPE debug messages |
62 const SDL_Rect * srcrect, | 74 const SDL_Rect * srcrect, |
63 const SDL_Rect * dstrect); | 75 const SDL_Rect * dstrect); |
64 static void SDL_PS3_RenderPresent(SDL_Renderer * renderer); | 76 static void SDL_PS3_RenderPresent(SDL_Renderer * renderer); |
65 static void SDL_PS3_DestroyRenderer(SDL_Renderer * renderer); | 77 static void SDL_PS3_DestroyRenderer(SDL_Renderer * renderer); |
66 | 78 |
79 /* Texture */ | |
80 static int PS3_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture); | |
81 static void PS3_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture); | |
82 | |
67 | 83 |
68 SDL_RenderDriver SDL_PS3_RenderDriver = { | 84 SDL_RenderDriver SDL_PS3_RenderDriver = { |
69 SDL_PS3_CreateRenderer, | 85 SDL_PS3_CreateRenderer, |
70 { | 86 { |
71 "ps3", | 87 "ps3", |
72 (/*SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY |*/ | 88 (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTVSYNC | |
73 SDL_RENDERER_PRESENTFLIP2 /*| SDL_RENDERER_PRESENTFLIP3 | | 89 SDL_RENDERER_PRESENTFLIP2) |
74 SDL_RENDERER_PRESENTDISCARD*/), | 90 /* (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY | |
91 SDL_RENDERER_PRESENTFLIP2 | SDL_RENDERER_PRESENTFLIP3 | | |
92 SDL_RENDERER_PRESENTDISCARD) */, | |
75 } | 93 } |
76 }; | 94 }; |
77 | 95 |
78 typedef struct | 96 typedef struct |
79 { | 97 { |
80 int current_screen; | 98 int current_screen; |
81 SDL_Surface *screens[3]; | 99 SDL_Surface *screens[3]; |
100 SDL_VideoDisplay *display; | |
101 uint8_t *center[2]; | |
102 | |
103 /* width of input (bounded by writeable width) */ | |
104 unsigned int bounded_width; | |
105 /* height of input (bounded by writeable height) */ | |
106 unsigned int bounded_height; | |
107 /* offset from the left side (used for centering) */ | |
108 unsigned int offset_left; | |
109 /* offset from the upper side (used for centering) */ | |
110 unsigned int offset_top; | |
111 /* width of screen which is writeable */ | |
112 unsigned int wr_width; | |
113 /* width of screen which is writeable */ | |
114 unsigned int wr_height; | |
115 /* size of a screen line: width * bpp/8 */ | |
116 unsigned int line_length; | |
117 | |
118 /* Use two buffers in fb? res < 720p */ | |
119 unsigned int double_buffering; | |
82 } SDL_PS3_RenderData; | 120 } SDL_PS3_RenderData; |
121 | |
122 typedef struct | |
123 { | |
124 void *pixels; | |
125 int pitch; | |
126 int bpp; | |
127 } PS3_TextureData; | |
83 | 128 |
84 SDL_Renderer * | 129 SDL_Renderer * |
85 SDL_PS3_CreateRenderer(SDL_Window * window, Uint32 flags) | 130 SDL_PS3_CreateRenderer(SDL_Window * window, Uint32 flags) |
86 { | 131 { |
87 deprintf(1, "SDL_PS3_CreateRenderer()\n"); | 132 deprintf(1, "SDL_PS3_CreateRenderer()\n"); |
111 SDL_OutOfMemory(); | 156 SDL_OutOfMemory(); |
112 return NULL; | 157 return NULL; |
113 } | 158 } |
114 SDL_zerop(data); | 159 SDL_zerop(data); |
115 | 160 |
161 renderer->CreateTexture = PS3_CreateTexture; | |
162 renderer->DestroyTexture = PS3_DestroyTexture; | |
116 renderer->RenderPoint = SDL_PS3_RenderPoint; | 163 renderer->RenderPoint = SDL_PS3_RenderPoint; |
117 renderer->RenderLine = SDL_PS3_RenderLine; | 164 renderer->RenderLine = SDL_PS3_RenderLine; |
118 renderer->RenderFill = SDL_PS3_RenderFill; | 165 renderer->RenderFill = SDL_PS3_RenderFill; |
119 renderer->RenderCopy = SDL_PS3_RenderCopy; | 166 renderer->RenderCopy = SDL_PS3_RenderCopy; |
120 renderer->RenderPresent = SDL_PS3_RenderPresent; | 167 renderer->RenderPresent = SDL_PS3_RenderPresent; |
123 renderer->info.flags = 0; | 170 renderer->info.flags = 0; |
124 renderer->window = window->id; | 171 renderer->window = window->id; |
125 renderer->driverdata = data; | 172 renderer->driverdata = data; |
126 Setup_SoftwareRenderer(renderer); | 173 Setup_SoftwareRenderer(renderer); |
127 | 174 |
175 data->double_buffering = 0; | |
176 | |
128 if (flags & SDL_RENDERER_PRESENTFLIP2) { | 177 if (flags & SDL_RENDERER_PRESENTFLIP2) { |
129 renderer->info.flags |= SDL_RENDERER_PRESENTFLIP2; | 178 renderer->info.flags |= SDL_RENDERER_PRESENTFLIP2; |
130 n = 2; | 179 n = 2; |
131 } else if (flags & SDL_RENDERER_PRESENTFLIP3) { | 180 data->double_buffering = 1; |
132 renderer->info.flags |= SDL_RENDERER_PRESENTFLIP3; | |
133 n = 3; | |
134 } else { | 181 } else { |
135 renderer->info.flags |= SDL_RENDERER_PRESENTCOPY; | 182 renderer->info.flags |= SDL_RENDERER_PRESENTCOPY; |
136 n = 1; | 183 n = 1; |
137 } | 184 } |
138 for (i = 0; i < n; ++i) { | 185 for (i = 0; i < n; ++i) { |
158 | 205 |
159 return renderer; | 206 return renderer; |
160 } | 207 } |
161 | 208 |
162 static int | 209 static int |
210 PS3_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) { | |
211 deprintf(1, "PS3_CreateTexture()\n"); | |
212 PS3_TextureData *data; | |
213 data = (PS3_TextureData *) SDL_calloc(1, sizeof(*data)); | |
214 if (!data) { | |
215 SDL_OutOfMemory(); | |
216 return -1; | |
217 } | |
218 | |
219 data->pitch = (texture->w * SDL_BYTESPERPIXEL(texture->format)); | |
220 | |
221 data->pixels = NULL; | |
222 data->pixels = (void *)memalign(16, texture->h * data->pitch); | |
223 if (!data->pixels) { | |
224 PS3_DestroyTexture(renderer, texture); | |
225 SDL_OutOfMemory(); | |
226 return -1; | |
227 } | |
228 | |
229 texture->driverdata = data; | |
230 return 0; | |
231 } | |
232 | |
233 static void | |
234 PS3_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) | |
235 { | |
236 PS3_TextureData *data = (PS3_TextureData *) texture->driverdata; | |
237 | |
238 if (!data) { | |
239 return; | |
240 } | |
241 | |
242 free(data->pixels); | |
243 } | |
244 | |
245 static int | |
163 SDL_PS3_RenderPoint(SDL_Renderer * renderer, int x, int y) | 246 SDL_PS3_RenderPoint(SDL_Renderer * renderer, int x, int y) |
164 { | 247 { |
165 SDL_PS3_RenderData *data = | 248 SDL_PS3_RenderData *data = |
166 (SDL_PS3_RenderData *) renderer->driverdata; | 249 (SDL_PS3_RenderData *) renderer->driverdata; |
167 SDL_Surface *target = data->screens[data->current_screen]; | 250 SDL_Surface *target = data->screens[data->current_screen]; |
236 deprintf(1, "SDL_PS3_RenderCopy()\n"); | 319 deprintf(1, "SDL_PS3_RenderCopy()\n"); |
237 SDL_PS3_RenderData *data = | 320 SDL_PS3_RenderData *data = |
238 (SDL_PS3_RenderData *) renderer->driverdata; | 321 (SDL_PS3_RenderData *) renderer->driverdata; |
239 SDL_Window *window = SDL_GetWindowFromID(renderer->window); | 322 SDL_Window *window = SDL_GetWindowFromID(renderer->window); |
240 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); | 323 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); |
324 PS3_TextureData *txdata = (PS3_TextureData *) texture->driverdata; | |
325 SDL_VideoData *devdata = display->device->driverdata; | |
241 | 326 |
242 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { | 327 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { |
328 deprintf(1, "SDL_ISPIXELFORMAT_FOURCC = true\n"); | |
243 SDL_Surface *target = data->screens[data->current_screen]; | 329 SDL_Surface *target = data->screens[data->current_screen]; |
244 void *pixels = | 330 void *pixels = |
245 (Uint8 *) target->pixels + dstrect->y * target->pitch + | 331 (Uint8 *) target->pixels + dstrect->y * target->pitch + |
246 dstrect->x * target->format->BytesPerPixel; | 332 dstrect->x * target->format->BytesPerPixel; |
247 return SDL_SW_CopyYUVToRGB((SDL_SW_YUVTexture *) texture->driverdata, | 333 return SDL_SW_CopyYUVToRGB((SDL_SW_YUVTexture *) texture->driverdata, |
248 srcrect, display->current_mode.format, | 334 srcrect, display->current_mode.format, |
249 dstrect->w, dstrect->h, pixels, | 335 dstrect->w, dstrect->h, pixels, |
250 target->pitch); | 336 target->pitch); |
251 } else { | 337 } else { |
338 deprintf(1, "SDL_ISPIXELFORMAT_FOURCC = false\n"); | |
252 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; | 339 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; |
253 SDL_Surface *target = data->screens[data->current_screen]; | 340 SDL_Surface *target = data->screens[data->current_screen]; |
254 SDL_Rect real_srcrect = *srcrect; | 341 SDL_Rect real_srcrect = *srcrect; |
255 SDL_Rect real_dstrect = *dstrect; | 342 SDL_Rect real_dstrect = *dstrect; |
256 | 343 |
344 /* For testing */ | |
345 int width = 1280; | |
346 int height = 720; | |
347 void *pixels = (void *)memalign(16, height * data->screens[0]->pitch); | |
348 SDL_memset(pixels, 0x42, height * data->screens[0]->pitch); | |
349 | |
350 /* Get screeninfo */ | |
351 struct fb_fix_screeninfo fb_finfo; | |
352 if (ioctl(devdata->fbdev, FBIOGET_FSCREENINFO, &fb_finfo)) { | |
353 SDL_SetError("[PS3] Can't get fixed screeninfo"); | |
354 return -1; | |
355 } | |
356 struct fb_var_screeninfo fb_vinfo; | |
357 if (ioctl(devdata->fbdev, FBIOGET_VSCREENINFO, &fb_vinfo)) { | |
358 SDL_SetError("[PS3] Can't get VSCREENINFO"); | |
359 return -1; | |
360 } | |
361 /* 16 and 15 bpp is reported as 16 bpp */ | |
362 txdata->bpp = fb_vinfo.bits_per_pixel; | |
363 if (txdata->bpp == 16) | |
364 txdata->bpp = fb_vinfo.red.length + fb_vinfo.green.length + fb_vinfo.blue.length; | |
365 | |
366 /* Adjust centering */ | |
367 data->bounded_width = width < fb_vinfo.xres ? width : fb_vinfo.xres; | |
368 data->bounded_height = height < fb_vinfo.yres ? height : fb_vinfo.yres; | |
369 data->offset_left = (fb_vinfo.xres - data->bounded_width) >> 1; | |
370 data->offset_top = (fb_vinfo.yres - data->bounded_height) >> 1; | |
371 data->center[0] = devdata->frame_buffer + data->offset_left * txdata->bpp/8 + | |
372 data->offset_top * fb_finfo.line_length; | |
373 data->center[1] = data->center[0] + fb_vinfo.yres * fb_finfo.line_length; | |
374 | |
375 /* Set SPU parms for copying the surface to framebuffer */ | |
376 devdata->fb_parms->data = (unsigned char *)pixels; | |
377 devdata->fb_parms->center = data->center[data->current_screen]; | |
378 devdata->fb_parms->out_line_stride = fb_finfo.line_length; | |
379 devdata->fb_parms->in_line_stride = surface->w * txdata->bpp / 8; | |
380 devdata->fb_parms->bounded_input_height = data->bounded_height; | |
381 devdata->fb_parms->bounded_input_width = data->bounded_width; | |
382 devdata->fb_parms->fb_pixel_size = txdata->bpp / 8; | |
383 | |
384 deprintf(3, "[PS3->SPU] fb_thread_data->argp = 0x%x\n", devdata->fb_thread_data->argp); | |
385 | |
386 /* Copying.. */ | |
387 SPE_SendMsg(devdata->fb_thread_data, SPU_START); | |
388 SPE_SendMsg(devdata->fb_thread_data, (unsigned int)devdata->fb_thread_data->argp); | |
389 | |
390 SPE_WaitForMsg(devdata->fb_thread_data, SPU_FIN); | |
391 free(pixels); | |
392 | |
257 return SDL_LowerBlit(surface, &real_srcrect, target, &real_dstrect); | 393 return SDL_LowerBlit(surface, &real_srcrect, target, &real_dstrect); |
258 } | 394 } |
259 } | 395 } |
260 | 396 |
261 static void | 397 static void |
263 { | 399 { |
264 deprintf(1, "SDL_PS3_RenderPresent()\n"); | 400 deprintf(1, "SDL_PS3_RenderPresent()\n"); |
265 static int frame_number; | 401 static int frame_number; |
266 SDL_PS3_RenderData *data = | 402 SDL_PS3_RenderData *data = |
267 (SDL_PS3_RenderData *) renderer->driverdata; | 403 (SDL_PS3_RenderData *) renderer->driverdata; |
404 SDL_Window *window = SDL_GetWindowFromID(renderer->window); | |
405 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); | |
406 SDL_VideoData *devdata = display->device->driverdata; | |
268 | 407 |
269 /* Send the data to the display */ | 408 /* Send the data to the display */ |
270 if (SDL_getenv("SDL_VIDEO_PS3_SAVE_FRAMES")) { | 409 if (SDL_getenv("SDL_VIDEO_PS3_SAVE_FRAMES")) { |
271 char file[128]; | 410 char file[128]; |
272 SDL_snprintf(file, sizeof(file), "SDL_window%d-%8.8d.bmp", | 411 SDL_snprintf(file, sizeof(file), "SDL_window%d-%8.8d.bmp", |
273 renderer->window, ++frame_number); | 412 renderer->window, ++frame_number); |
274 SDL_SaveBMP(data->screens[data->current_screen], file); | 413 SDL_SaveBMP(data->screens[data->current_screen], file); |
275 } | 414 } |
276 | 415 |
416 /* Wait for vsync */ | |
417 if (renderer->info.flags & SDL_RENDERER_PRESENTVSYNC) { | |
418 unsigned long crt = 0; | |
419 deprintf(1, "[PS3] Wait for vsync\n"); | |
420 ioctl(devdata->fbdev, FBIO_WAITFORVSYNC, &crt); | |
421 } | |
422 | |
423 /* Page flip */ | |
424 deprintf(1, "[PS3] Page flip to buffer #%u 0x%x\n", data->current_screen, data->center[data->current_screen]); | |
425 ioctl(devdata->fbdev, PS3FB_IOCTL_FSEL, (unsigned long)&data->current_screen); | |
426 | |
277 /* Update the flipping chain, if any */ | 427 /* Update the flipping chain, if any */ |
278 if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) { | 428 if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2 && data->double_buffering) { |
279 data->current_screen = (data->current_screen + 1) % 2; | 429 data->current_screen = (data->current_screen + 1) % 2; |
280 } else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP3) { | 430 } |
281 data->current_screen = (data->current_screen + 1) % 3; | |
282 } | |
283 | |
284 /* How to access the framebuffer from here? | |
285 unsigned long crt = 0; | |
286 unsigned int s_center_index = 0; | |
287 unsigned int * s_center[2]; | |
288 s_center[0] = frame_buffer; | |
289 // Wait for vsync | |
290 deprintf(1, "[PS3] Wait for vsync\n"); | |
291 ioctl(fbdev, FBIO_WAITFORVSYNC, &crt); | |
292 // Page flip | |
293 deprintf(1, "[PS3] Page flip to buffer #%u 0x%x\n", s_center_index, s_center[s_center_index]); | |
294 ioctl(fbdev, PS3FB_IOCTL_FSEL, (unsigned long)&s_center_index); | |
295 */ | |
296 } | 431 } |
297 | 432 |
298 static void | 433 static void |
299 SDL_PS3_DestroyRenderer(SDL_Renderer * renderer) | 434 SDL_PS3_DestroyRenderer(SDL_Renderer * renderer) |
300 { | 435 { |