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 {