comparison src/video/ps3/SDL_ps3render.c @ 3257:94fb40a4a9a7

Merged Martin's code changes from Google Summer of Code 2009
author Sam Lantinga <slouken@libsdl.org>
date Mon, 07 Sep 2009 04:51:29 +0000
parents
children f638ded38b8a
comparison
equal deleted inserted replaced
3256:83c87f2b2aab 3257:94fb40a4a9a7
1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2009 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21 */
22 #include "SDL_config.h"
23
24 #include "SDL_video.h"
25 #include "../SDL_sysvideo.h"
26 #include "../SDL_yuv_sw_c.h"
27 #include "../SDL_renderer_sw.h"
28
29 #include "SDL_ps3video.h"
30 #include "SDL_ps3spe_c.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 #include <asm/ps3fb.h>
39
40
41 /* Stores the executable name */
42 extern spe_program_handle_t yuv2rgb_spu;
43 extern spe_program_handle_t bilin_scaler_spu;
44
45 /* SDL surface based renderer implementation */
46 static SDL_Renderer *SDL_PS3_CreateRenderer(SDL_Window * window,
47 Uint32 flags);
48 static int SDL_PS3_DisplayModeChanged(SDL_Renderer * renderer);
49 static int SDL_PS3_ActivateRenderer(SDL_Renderer * renderer);
50 static int SDL_PS3_RenderPoint(SDL_Renderer * renderer, int x, int y);
51 static int SDL_PS3_RenderLine(SDL_Renderer * renderer, int x1, int y1,
52 int x2, int y2);
53 static int SDL_PS3_RenderFill(SDL_Renderer * renderer,
54 const SDL_Rect * rect);
55 static int SDL_PS3_RenderCopy(SDL_Renderer * renderer,
56 SDL_Texture * texture,
57 const SDL_Rect * srcrect,
58 const SDL_Rect * dstrect);
59 static void SDL_PS3_RenderPresent(SDL_Renderer * renderer);
60 static void SDL_PS3_DestroyRenderer(SDL_Renderer * renderer);
61
62 /* Texture */
63 static int PS3_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
64 static int PS3_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture, void **pixels, int *pitch);
65 static int PS3_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * rect, const void *pixels, int pitch);
66 static int PS3_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * rect, int markDirty, void **pixels, int *pitch);
67 static void PS3_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
68 static void PS3_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
69
70
71 SDL_RenderDriver SDL_PS3_RenderDriver = {
72 SDL_PS3_CreateRenderer,
73 {
74 "ps3",
75 (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTVSYNC |
76 SDL_RENDERER_PRESENTFLIP2 | SDL_RENDERER_PRESENTDISCARD |
77 SDL_RENDERER_ACCELERATED),
78 (SDL_TEXTUREMODULATE_NONE),
79 (SDL_BLENDMODE_NONE),
80 /* We use bilinear scaling on the SPE for YV12 & IYUV
81 * (width and height % 8 = 0) */
82 (SDL_TEXTURESCALEMODE_SLOW)
83 }
84 };
85
86 typedef struct
87 {
88 int current_screen;
89 SDL_Surface *screen;
90 SDL_VideoDisplay *display;
91 /* adress of the centered image in the framebuffer (double buffered) */
92 uint8_t *center[2];
93
94 /* width of input (bounded by writeable width) */
95 unsigned int bounded_width;
96 /* height of input (bounded by writeable height) */
97 unsigned int bounded_height;
98 /* offset from the left side (used for centering) */
99 unsigned int offset_left;
100 /* offset from the upper side (used for centering) */
101 unsigned int offset_top;
102 /* width of screen which is writeable */
103 unsigned int wr_width;
104 /* width of screen which is writeable */
105 unsigned int wr_height;
106 /* size of a screen line: width * bpp/8 */
107 unsigned int line_length;
108
109 /* Is the kernels fb size bigger than ~12MB
110 * double buffering will work for 1080p */
111 unsigned int double_buffering;
112
113 /* SPE threading stuff */
114 spu_data_t *converter_thread_data;
115 spu_data_t *scaler_thread_data;
116
117 /* YUV converting transfer data */
118 volatile struct yuv2rgb_parms_t * converter_parms __attribute__((aligned(128)));
119 /* Scaler transfer data */
120 volatile struct scale_parms_t * scaler_parms __attribute__((aligned(128)));
121 } SDL_PS3_RenderData;
122
123 typedef struct
124 {
125 int pitch;
126 /* Image data */
127 volatile void *pixels;
128 /* Use software renderer for not supported formats */
129 SDL_SW_YUVTexture *yuv;
130 } PS3_TextureData;
131
132 SDL_Renderer *
133 SDL_PS3_CreateRenderer(SDL_Window * window, Uint32 flags)
134 {
135 deprintf(1, "+SDL_PS3_CreateRenderer()\n");
136 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
137 SDL_DisplayMode *displayMode = &display->current_mode;
138 SDL_VideoData *devdata = display->device->driverdata;
139 SDL_Renderer *renderer;
140 SDL_PS3_RenderData *data;
141 struct ps3fb_ioctl_res res;
142 int i, n;
143 int bpp;
144 Uint32 Rmask, Gmask, Bmask, Amask;
145
146 if (!SDL_PixelFormatEnumToMasks
147 (displayMode->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
148 SDL_SetError("Unknown display format");
149 return NULL;
150 }
151
152 renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
153 if (!renderer) {
154 SDL_OutOfMemory();
155 return NULL;
156 }
157
158 data = (SDL_PS3_RenderData *) SDL_malloc(sizeof(*data));
159 if (!data) {
160 SDL_PS3_DestroyRenderer(renderer);
161 SDL_OutOfMemory();
162 return NULL;
163 }
164 SDL_zerop(data);
165
166 renderer->CreateTexture = PS3_CreateTexture;
167 renderer->DestroyTexture = PS3_DestroyTexture;
168 renderer->QueryTexturePixels = PS3_QueryTexturePixels;
169 renderer->UpdateTexture = PS3_UpdateTexture;
170 renderer->LockTexture = PS3_LockTexture;
171 renderer->UnlockTexture = PS3_UnlockTexture;
172 renderer->ActivateRenderer = SDL_PS3_ActivateRenderer;
173 renderer->DisplayModeChanged = SDL_PS3_DisplayModeChanged;
174 renderer->RenderPoint = SDL_PS3_RenderPoint;
175 renderer->RenderLine = SDL_PS3_RenderLine;
176 renderer->RenderFill = SDL_PS3_RenderFill;
177 renderer->RenderCopy = SDL_PS3_RenderCopy;
178 renderer->RenderPresent = SDL_PS3_RenderPresent;
179 renderer->DestroyRenderer = SDL_PS3_DestroyRenderer;
180 renderer->info.name = SDL_PS3_RenderDriver.info.name;
181 renderer->info.flags = 0;
182 renderer->window = window->id;
183 renderer->driverdata = data;
184
185 deprintf(1, "window->w = %u\n", window->w);
186 deprintf(1, "window->h = %u\n", window->h);
187
188 data->double_buffering = 0;
189
190 /* Get ps3 screeninfo */
191 if (ioctl(devdata->fbdev, PS3FB_IOCTL_SCREENINFO, (unsigned long)&res) < 0) {
192 SDL_SetError("[PS3] PS3FB_IOCTL_SCREENINFO failed");
193 }
194 deprintf(2, "res.num_frames = %d\n", res.num_frames);
195
196 /* Only use double buffering if enough fb memory is available */
197 if (res.num_frames > 1) {
198 renderer->info.flags |= SDL_RENDERER_PRESENTFLIP2;
199 n = 2;
200 data->double_buffering = 1;
201 } else {
202 renderer->info.flags |= SDL_RENDERER_PRESENTCOPY;
203 n = 1;
204 }
205
206 data->screen =
207 SDL_CreateRGBSurface(0, window->w, window->h, bpp, Rmask, Gmask,
208 Bmask, Amask);
209 if (!data->screen) {
210 SDL_PS3_DestroyRenderer(renderer);
211 return NULL;
212 }
213 /* Allocate aligned memory for pixels */
214 SDL_free(data->screen->pixels);
215 data->screen->pixels = (void *)memalign(16, data->screen->h * data->screen->pitch);
216 if (!data->screen->pixels) {
217 SDL_FreeSurface(data->screen);
218 SDL_OutOfMemory();
219 return NULL;
220 }
221 SDL_memset(data->screen->pixels, 0, data->screen->h * data->screen->pitch);
222 SDL_SetSurfacePalette(data->screen, display->palette);
223
224 data->current_screen = 0;
225
226 /* Create SPU parms structure */
227 data->converter_parms = (struct yuv2rgb_parms_t *) memalign(16, sizeof(struct yuv2rgb_parms_t));
228 data->scaler_parms = (struct scale_parms_t *) memalign(16, sizeof(struct scale_parms_t));
229 if (data->converter_parms == NULL || data->scaler_parms == NULL) {
230 SDL_PS3_DestroyRenderer(renderer);
231 SDL_OutOfMemory();
232 return NULL;
233 }
234
235 /* Set up the SPE threading data */
236 data->converter_thread_data = (spu_data_t *) malloc(sizeof(spu_data_t));
237 data->scaler_thread_data = (spu_data_t *) malloc(sizeof(spu_data_t));
238 if (data->converter_thread_data == NULL || data->scaler_thread_data == NULL) {
239 SDL_PS3_DestroyRenderer(renderer);
240 SDL_OutOfMemory();
241 return NULL;
242 }
243
244 /* Set up the SPE scaler (booted) */
245 data->scaler_thread_data->program = bilin_scaler_spu;
246 data->scaler_thread_data->program_name = "bilin_scaler_spu";
247 data->scaler_thread_data->keepalive = 0;
248 data->scaler_thread_data->booted = 0;
249
250 /* Set up the SPE converter (always running) */
251 data->converter_thread_data->program = yuv2rgb_spu;
252 data->converter_thread_data->program_name = "yuv2rgb_spu";
253 data->converter_thread_data->keepalive = 1;
254 data->converter_thread_data->booted = 0;
255
256 SPE_Start(data->converter_thread_data);
257
258 deprintf(1, "-SDL_PS3_CreateRenderer()\n");
259 return renderer;
260 }
261
262 static int
263 SDL_PS3_ActivateRenderer(SDL_Renderer * renderer)
264 {
265 deprintf(1, "+PS3_ActivateRenderer()\n");
266 SDL_PS3_RenderData *data = (SDL_PS3_RenderData *) renderer->driverdata;
267
268 deprintf(1, "-PS3_ActivateRenderer()\n");
269 return 0;
270 }
271
272 static int SDL_PS3_DisplayModeChanged(SDL_Renderer * renderer) {
273 deprintf(1, "+PS3_DisplayModeChanged()\n");
274 SDL_PS3_RenderData *data = (SDL_PS3_RenderData *) renderer->driverdata;
275
276 deprintf(1, "-PS3_DisplayModeChanged()\n");
277 return 0;
278 }
279
280 static int
281 PS3_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) {
282 deprintf(1, "+PS3_CreateTexture()\n");
283 PS3_TextureData *data;
284 data = (PS3_TextureData *) SDL_calloc(1, sizeof(*data));
285 if (!data) {
286 SDL_OutOfMemory();
287 return -1;
288 }
289 data->pitch = (texture->w * SDL_BYTESPERPIXEL(texture->format));
290
291 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
292 /* Use SDLs SW_YUVTexture */
293 data->yuv =
294 SDL_SW_CreateYUVTexture(texture->format, texture->w, texture->h);
295 if (!data->yuv) {
296 SDL_OutOfMemory();
297 return -1;
298 }
299 /* but align pixels */
300 SDL_free(data->yuv->pixels);
301 data->yuv->pixels = (Uint8 *)memalign(16, texture->w * texture->h * 2);
302 if (!data->yuv->pixels) {
303 SDL_OutOfMemory();
304 return -1;
305 }
306
307 /* Redo: Find the pitch and offset values for the overlay */
308 SDL_SW_YUVTexture *swdata = (SDL_SW_YUVTexture *) data->yuv;
309 switch (texture->format) {
310 case SDL_PIXELFORMAT_YV12:
311 case SDL_PIXELFORMAT_IYUV:
312 swdata->pitches[0] = texture->w;
313 swdata->pitches[1] = swdata->pitches[0] / 2;
314 swdata->pitches[2] = swdata->pitches[0] / 2;
315 swdata->planes[0] = swdata->pixels;
316 swdata->planes[1] = swdata->planes[0] + swdata->pitches[0] * texture->h;
317 swdata->planes[2] = swdata->planes[1] + swdata->pitches[1] * texture->h / 2;
318 break;
319 case SDL_PIXELFORMAT_YUY2:
320 case SDL_PIXELFORMAT_UYVY:
321 case SDL_PIXELFORMAT_YVYU:
322 swdata->pitches[0] = texture->w * 2;
323 swdata->planes[0] = swdata->pixels;
324 break;
325 default:
326 /* We should never get here (caught above) */
327 break;
328 }
329 } else {
330 data->pixels = NULL;
331 data->pixels = SDL_malloc(texture->h * data->pitch);
332 if (!data->pixels) {
333 PS3_DestroyTexture(renderer, texture);
334 SDL_OutOfMemory();
335 return -1;
336 }
337 }
338 texture->driverdata = data;
339 deprintf(1, "-PS3_CreateTexture()\n");
340 return 0;
341 }
342
343 static int
344 PS3_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
345 void **pixels, int *pitch)
346 {
347 deprintf(1, "+PS3_QueryTexturePixels()\n");
348 PS3_TextureData *data = (PS3_TextureData *) texture->driverdata;
349
350 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
351 return SDL_SW_QueryYUVTexturePixels(data->yuv, pixels, pitch);
352 } else {
353 *pixels = (void *)data->pixels;
354 *pitch = data->pitch;
355 }
356
357 deprintf(1, "-PS3_QueryTexturePixels()\n");
358 return 0;
359 }
360
361 static int
362 PS3_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
363 const SDL_Rect * rect, const void *pixels, int pitch)
364 {
365 deprintf(1, "+PS3_UpdateTexture()\n");
366 PS3_TextureData *data = (PS3_TextureData *) texture->driverdata;
367
368 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
369 return SDL_SW_UpdateYUVTexture(data->yuv, rect, pixels, pitch);
370 } else {
371 Uint8 *src, *dst;
372 int row;
373 size_t length;
374 Uint8 *dstpixels;
375
376 src = (Uint8 *) pixels;
377 dst = (Uint8 *) dstpixels + rect->y * data->pitch + rect->x
378 * SDL_BYTESPERPIXEL(texture->format);
379 length = rect->w * SDL_BYTESPERPIXEL(texture->format);
380 /* Update the texture */
381 for (row = 0; row < rect->h; ++row) {
382 SDL_memcpy(dst, src, length);
383 src += pitch;
384 dst += data->pitch;
385 }
386 }
387 deprintf(1, "-PS3_UpdateTexture()\n");
388 return 0;
389 }
390
391 static int
392 PS3_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
393 const SDL_Rect * rect, int markDirty, void **pixels,
394 int *pitch)
395 {
396 deprintf(1, "+PS3_LockTexture()\n");
397 PS3_TextureData *data = (PS3_TextureData *) texture->driverdata;
398
399 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
400 deprintf(1, "-PS3_LockTexture()\n");
401 return SDL_SW_LockYUVTexture(data->yuv, rect, markDirty, pixels, pitch);
402 } else {
403 *pixels =
404 (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
405 rect->x * SDL_BYTESPERPIXEL(texture->format));
406 *pitch = data->pitch;
407 deprintf(1, "-PS3_LockTexture()\n");
408 return 0;
409 }
410 }
411
412 static void
413 PS3_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
414 {
415 deprintf(1, "+PS3_UnlockTexture()\n");
416 PS3_TextureData *data = (PS3_TextureData *) texture->driverdata;
417
418 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
419 SDL_SW_UnlockYUVTexture(data->yuv);
420 }
421 deprintf(1, "-PS3_UnlockTexture()\n");
422 }
423
424 static void
425 PS3_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
426 {
427 deprintf(1, "+PS3_DestroyTexture()\n");
428 PS3_TextureData *data = (PS3_TextureData *) texture->driverdata;
429
430 if (!data) {
431 return;
432 }
433 if (data->yuv) {
434 SDL_SW_DestroyYUVTexture(data->yuv);
435 }
436 if (data->pixels) {
437 SDL_free((void *)data->pixels);
438 }
439 deprintf(1, "-PS3_DestroyTexture()\n");
440 }
441
442 static int
443 SDL_PS3_RenderPoint(SDL_Renderer * renderer, int x, int y)
444 {
445 SDL_PS3_RenderData *data =
446 (SDL_PS3_RenderData *) renderer->driverdata;
447 SDL_Surface *target = data->screen;
448 int status;
449
450 if (renderer->blendMode == SDL_BLENDMODE_NONE ||
451 renderer->blendMode == SDL_BLENDMODE_MASK) {
452 Uint32 color =
453 SDL_MapRGBA(target->format, renderer->r, renderer->g, renderer->b,
454 renderer->a);
455
456 status = SDL_DrawPoint(target, x, y, color);
457 } else {
458 status =
459 SDL_BlendPoint(target, x, y, renderer->blendMode, renderer->r,
460 renderer->g, renderer->b, renderer->a);
461 }
462 return status;
463 }
464
465 static int
466 SDL_PS3_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2)
467 {
468 SDL_PS3_RenderData *data =
469 (SDL_PS3_RenderData *) renderer->driverdata;
470 SDL_Surface *target = data->screen;
471 int status;
472
473 if (renderer->blendMode == SDL_BLENDMODE_NONE ||
474 renderer->blendMode == SDL_BLENDMODE_MASK) {
475 Uint32 color =
476 SDL_MapRGBA(target->format, renderer->r, renderer->g, renderer->b,
477 renderer->a);
478
479 status = SDL_DrawLine(target, x1, y1, x2, y2, color);
480 } else {
481 status =
482 SDL_BlendLine(target, x1, y1, x2, y2, renderer->blendMode,
483 renderer->r, renderer->g, renderer->b, renderer->a);
484 }
485 return status;
486 }
487
488 static int
489 SDL_PS3_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect)
490 {
491 deprintf(1, "SDL_PS3_RenderFill()\n");
492 SDL_PS3_RenderData *data =
493 (SDL_PS3_RenderData *) renderer->driverdata;
494 SDL_Surface *target = data->screen;
495 SDL_Rect real_rect = *rect;
496 int status;
497
498 if (renderer->blendMode == SDL_BLENDMODE_NONE) {
499 Uint32 color =
500 SDL_MapRGBA(target->format, renderer->r, renderer->g, renderer->b,
501 renderer->a);
502
503 status = SDL_FillRect(target, &real_rect, color);
504 } else {
505 status =
506 SDL_BlendRect(target, &real_rect, renderer->blendMode,
507 renderer->r, renderer->g, renderer->b, renderer->a);
508 }
509 return status;
510 }
511
512 static int
513 SDL_PS3_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
514 const SDL_Rect * srcrect, const SDL_Rect * dstrect)
515 {
516 deprintf(1, "+SDL_PS3_RenderCopy()\n");
517 SDL_PS3_RenderData *data =
518 (SDL_PS3_RenderData *) renderer->driverdata;
519 SDL_Window *window = SDL_GetWindowFromID(renderer->window);
520 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
521 PS3_TextureData *txdata = (PS3_TextureData *) texture->driverdata;
522 SDL_VideoData *devdata = display->device->driverdata;
523
524 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
525 deprintf(1, "Texture is in a FOURCC format\n");
526 if ((texture->format == SDL_PIXELFORMAT_YV12 || texture->format == SDL_PIXELFORMAT_IYUV)
527 && texture->w % 8 == 0 && texture->h % 8 == 0
528 && dstrect->w % 8 == 0 && dstrect->h % 8 == 0) {
529 deprintf(1, "Use SPE for scaling/converting\n");
530
531 SDL_SW_YUVTexture *swdata = (SDL_SW_YUVTexture *) txdata->yuv;
532 Uint8 *lum, *Cr, *Cb;
533 Uint8 *scaler_out = NULL;
534 Uint8 *dstpixels;
535 switch (texture->format) {
536 case SDL_PIXELFORMAT_YV12:
537 lum = swdata->planes[0];
538 Cr = swdata->planes[1];
539 Cb = swdata->planes[2];
540 break;
541 case SDL_PIXELFORMAT_IYUV:
542 lum = swdata->planes[0];
543 Cr = swdata->planes[2];
544 Cb = swdata->planes[1];
545 break;
546 default:
547 /* We should never get here (caught above) */
548 return -1;
549 }
550
551 if (srcrect->w != dstrect->w || srcrect->h != dstrect->h) {
552 deprintf(1, "We need to scale the texture from %u x %u to %u x %u\n",
553 srcrect->w, srcrect->h, dstrect->w, dstrect->h);
554 /* Alloc mem for scaled YUV picture */
555 scaler_out = (Uint8 *) memalign(16, dstrect->w * dstrect->h + ((dstrect->w * dstrect->h) >> 1));
556 if (scaler_out == NULL) {
557 SDL_OutOfMemory();
558 return -1;
559 }
560
561 /* Set parms for scaling */
562 data->scaler_parms->src_pixel_width = srcrect->w;
563 data->scaler_parms->src_pixel_height = srcrect->h;
564 data->scaler_parms->dst_pixel_width = dstrect->w;
565 data->scaler_parms->dst_pixel_height = dstrect->h;
566 data->scaler_parms->y_plane = lum;
567 data->scaler_parms->v_plane = Cr;
568 data->scaler_parms->u_plane = Cb;
569 data->scaler_parms->dstBuffer = scaler_out;
570 data->scaler_thread_data->argp = (void *)data->scaler_parms;
571
572 /* Scale the YUV overlay to given size */
573 SPE_Start(data->scaler_thread_data);
574 SPE_Stop(data->scaler_thread_data);
575
576 /* Set parms for converting after scaling */
577 data->converter_parms->y_plane = scaler_out;
578 data->converter_parms->v_plane = scaler_out + dstrect->w * dstrect->h;
579 data->converter_parms->u_plane = scaler_out + dstrect->w * dstrect->h + ((dstrect->w * dstrect->h) >> 2);
580 } else {
581 data->converter_parms->y_plane = lum;
582 data->converter_parms->v_plane = Cr;
583 data->converter_parms->u_plane = Cb;
584 }
585
586 dstpixels = (Uint8 *) data->screen->pixels + dstrect->y * data->screen->pitch + dstrect->x
587 * SDL_BYTESPERPIXEL(texture->format);
588 data->converter_parms->src_pixel_width = dstrect->w;
589 data->converter_parms->src_pixel_height = dstrect->h;
590 data->converter_parms->dstBuffer = dstpixels/*(Uint8 *)data->screen->pixels*/;
591 data->converter_thread_data->argp = (void *)data->converter_parms;
592
593 /* Convert YUV texture to RGB */
594 SPE_SendMsg(data->converter_thread_data, SPU_START);
595 SPE_SendMsg(data->converter_thread_data, (unsigned int)data->converter_thread_data->argp);
596
597 /* We can probably move that to RenderPresent() */
598 SPE_WaitForMsg(data->converter_thread_data, SPU_FIN);
599 if (scaler_out) {
600 free(scaler_out);
601 }
602 } else {
603 deprintf(1, "Use software for scaling/converting\n");
604 Uint8 *dst;
605 /* FIXME: Not good */
606 dst = (Uint8 *) data->screen->pixels + dstrect->y * data->screen->pitch + dstrect->x
607 * SDL_BYTESPERPIXEL(texture->format);
608 return SDL_SW_CopyYUVToRGB(txdata->yuv, srcrect, display->current_mode.format,
609 dstrect->w, dstrect->h, dst/*data->screen->pixels*/,
610 data->screen->pitch);
611 }
612 } else {
613 deprintf(1, "SDL_ISPIXELFORMAT_FOURCC = false\n");
614
615 Uint8 *src, *dst;
616 int row;
617 size_t length;
618 Uint8 *dstpixels;
619
620 src = (Uint8 *) txdata->pixels;
621 dst = (Uint8 *) data->screen->pixels + dstrect->y * data->screen->pitch + dstrect->x
622 * SDL_BYTESPERPIXEL(texture->format);
623 length = dstrect->w * SDL_BYTESPERPIXEL(texture->format);
624 for (row = 0; row < dstrect->h; ++row) {
625 SDL_memcpy(dst, src, length);
626 src += txdata->pitch;
627 dst += data->screen->pitch;
628 }
629 }
630
631 deprintf(1, "-SDL_PS3_RenderCopy()\n");
632 return 0;
633 }
634
635 static void
636 SDL_PS3_RenderPresent(SDL_Renderer * renderer)
637 {
638 deprintf(1, "+SDL_PS3_RenderPresent()\n");
639 SDL_PS3_RenderData *data =
640 (SDL_PS3_RenderData *) renderer->driverdata;
641 SDL_Window *window = SDL_GetWindowFromID(renderer->window);
642 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
643 SDL_VideoData *devdata = display->device->driverdata;
644
645 /* Send the data to the screen */
646 /* Get screeninfo */
647 struct fb_fix_screeninfo fb_finfo;
648 if (ioctl(devdata->fbdev, FBIOGET_FSCREENINFO, &fb_finfo)) {
649 SDL_SetError("[PS3] Can't get fixed screeninfo");
650 }
651 struct fb_var_screeninfo fb_vinfo;
652 if (ioctl(devdata->fbdev, FBIOGET_VSCREENINFO, &fb_vinfo)) {
653 SDL_SetError("[PS3] Can't get VSCREENINFO");
654 }
655
656 /* 16 and 15 bpp is reported as 16 bpp */
657 //txdata->bpp = fb_vinfo.bits_per_pixel;
658 //if (txdata->bpp == 16)
659 // txdata->bpp = fb_vinfo.red.length + fb_vinfo.green.length + fb_vinfo.blue.length;
660
661 /* Adjust centering */
662 data->bounded_width = window->w < fb_vinfo.xres ? window->w : fb_vinfo.xres;
663 data->bounded_height = window->h < fb_vinfo.yres ? window->h : fb_vinfo.yres;
664 /* We could use SDL's CENTERED flag for centering */
665 data->offset_left = (fb_vinfo.xres - data->bounded_width) >> 1;
666 data->offset_top = (fb_vinfo.yres - data->bounded_height) >> 1;
667 data->center[0] = devdata->frame_buffer + data->offset_left * /*txdata->bpp/8*/ 4 +
668 data->offset_top * fb_finfo.line_length;
669 data->center[1] = data->center[0] + fb_vinfo.yres * fb_finfo.line_length;
670
671 deprintf(1, "offset_left = %u\n", data->offset_left);
672 deprintf(1, "offset_top = %u\n", data->offset_top);
673
674 /* Set SPU parms for copying the surface to framebuffer */
675 devdata->fb_parms->data = (unsigned char *)data->screen->pixels;
676 devdata->fb_parms->center = data->center[data->current_screen];
677 devdata->fb_parms->out_line_stride = fb_finfo.line_length;
678 devdata->fb_parms->in_line_stride = window->w * /*txdata->bpp / 8*/4;
679 devdata->fb_parms->bounded_input_height = data->bounded_height;
680 devdata->fb_parms->bounded_input_width = data->bounded_width;
681 //devdata->fb_parms->fb_pixel_size = txdata->bpp / 8;
682 devdata->fb_parms->fb_pixel_size = 4;//SDL_BYTESPERPIXEL(window->format);
683
684 deprintf(3, "[PS3->SPU] fb_thread_data->argp = 0x%x\n", devdata->fb_thread_data->argp);
685
686 /* Copying.. */
687 SPE_SendMsg(devdata->fb_thread_data, SPU_START);
688 SPE_SendMsg(devdata->fb_thread_data, (unsigned int)devdata->fb_thread_data->argp);
689
690 SPE_WaitForMsg(devdata->fb_thread_data, SPU_FIN);
691
692 /* Wait for vsync */
693 if (renderer->info.flags & SDL_RENDERER_PRESENTVSYNC) {
694 unsigned long crt = 0;
695 deprintf(1, "[PS3] Wait for vsync\n");
696 ioctl(devdata->fbdev, FBIO_WAITFORVSYNC, &crt);
697 }
698
699 /* Page flip */
700 deprintf(1, "[PS3] Page flip to buffer #%u 0x%x\n", data->current_screen, data->center[data->current_screen]);
701 ioctl(devdata->fbdev, PS3FB_IOCTL_FSEL, (unsigned long)&data->current_screen);
702
703 /* Update the flipping chain, if any */
704 if (data->double_buffering) {
705 data->current_screen = (data->current_screen + 1) % 2;
706 }
707 deprintf(1, "-SDL_PS3_RenderPresent()\n");
708 }
709
710 static void
711 SDL_PS3_DestroyRenderer(SDL_Renderer * renderer)
712 {
713 deprintf(1, "+SDL_PS3_DestroyRenderer()\n");
714 SDL_PS3_RenderData *data =
715 (SDL_PS3_RenderData *) renderer->driverdata;
716 int i;
717
718 if (data) {
719 for (i = 0; i < SDL_arraysize(data->screen); ++i) {
720 if (data->screen) {
721 SDL_FreeSurface(data->screen);
722 }
723 }
724
725 /* Shutdown SPE and release related resources */
726 if (data->scaler_thread_data) {
727 free((void *)data->scaler_thread_data);
728 }
729 if (data->scaler_parms) {
730 free((void *)data->scaler_parms);
731 }
732 if (data->converter_thread_data) {
733 SPE_Shutdown(data->converter_thread_data);
734 free((void *)data->converter_thread_data);
735 }
736 if (data->converter_parms) {
737 free((void *)data->converter_parms);
738 }
739
740 SDL_free(data);
741 }
742 SDL_free(renderer);
743 deprintf(1, "-SDL_PS3_DestroyRenderer()\n");
744 }
745
746 /* vi: set ts=4 sw=4 expandtab: */