comparison src/video/ps2gs/SDL_gsyuv.c @ 1668:4da1ee79c9af SDL-1.3

more tweaking indent options
author Sam Lantinga <slouken@libsdl.org>
date Mon, 29 May 2006 04:04:35 +0000
parents 782fd950bd46
children
comparison
equal deleted inserted replaced
1667:1fddae038bc8 1668:4da1ee79c9af
62 Uint16 pitches[3]; 62 Uint16 pitches[3];
63 Uint8 *planes[3]; 63 Uint8 *planes[3];
64 }; 64 };
65 65
66 static int 66 static int
67 power_of_2 (int value) 67 power_of_2(int value)
68 { 68 {
69 int shift; 69 int shift;
70 70
71 for (shift = 0; (1 << shift) < value; ++shift) { 71 for (shift = 0; (1 << shift) < value; ++shift) {
72 /* Keep looking */ ; 72 /* Keep looking */ ;
73 } 73 }
74 return (shift); 74 return (shift);
75 } 75 }
76 76
77 SDL_Overlay * 77 SDL_Overlay *
78 GS_CreateYUVOverlay (_THIS, int width, int height, Uint32 format, 78 GS_CreateYUVOverlay(_THIS, int width, int height, Uint32 format,
79 SDL_Surface * display) 79 SDL_Surface * display)
80 { 80 {
81 SDL_Overlay *overlay; 81 SDL_Overlay *overlay;
82 struct private_yuvhwdata *hwdata; 82 struct private_yuvhwdata *hwdata;
83 int map_offset; 83 int map_offset;
84 unsigned long long *tags; 84 unsigned long long *tags;
90 struct ps2_packet *packet; 90 struct ps2_packet *packet;
91 struct ps2_packet tex_packet; 91 struct ps2_packet tex_packet;
92 92
93 /* We can only decode blocks of 16x16 pixels */ 93 /* We can only decode blocks of 16x16 pixels */
94 if ((width & 15) || (height & 15)) { 94 if ((width & 15) || (height & 15)) {
95 SDL_SetError ("Overlay width/height must be multiples of 16"); 95 SDL_SetError("Overlay width/height must be multiples of 16");
96 return (NULL); 96 return (NULL);
97 } 97 }
98 /* Make sure the image isn't too large for a single DMA transfer */ 98 /* Make sure the image isn't too large for a single DMA transfer */
99 if (((width / 16) * (height / 16)) > MAX_MACROBLOCKS) { 99 if (((width / 16) * (height / 16)) > MAX_MACROBLOCKS) {
100 SDL_SetError ("Overlay too large (maximum size: %d pixels)", 100 SDL_SetError("Overlay too large (maximum size: %d pixels)",
101 MAX_MACROBLOCKS * 16 * 16); 101 MAX_MACROBLOCKS * 16 * 16);
102 return (NULL); 102 return (NULL);
103 } 103 }
104 104
105 /* Double-check the requested format. For simplicity, we'll only 105 /* Double-check the requested format. For simplicity, we'll only
106 support planar YUV formats. 106 support planar YUV formats.
109 case SDL_YV12_OVERLAY: 109 case SDL_YV12_OVERLAY:
110 case SDL_IYUV_OVERLAY: 110 case SDL_IYUV_OVERLAY:
111 /* Supported planar YUV format */ 111 /* Supported planar YUV format */
112 break; 112 break;
113 default: 113 default:
114 SDL_SetError ("Unsupported YUV format"); 114 SDL_SetError("Unsupported YUV format");
115 return (NULL); 115 return (NULL);
116 } 116 }
117 117
118 /* Create the overlay structure */ 118 /* Create the overlay structure */
119 overlay = (SDL_Overlay *) SDL_malloc (sizeof *overlay); 119 overlay = (SDL_Overlay *) SDL_malloc(sizeof *overlay);
120 if (overlay == NULL) { 120 if (overlay == NULL) {
121 SDL_OutOfMemory (); 121 SDL_OutOfMemory();
122 return (NULL); 122 return (NULL);
123 } 123 }
124 SDL_memset (overlay, 0, (sizeof *overlay)); 124 SDL_memset(overlay, 0, (sizeof *overlay));
125 125
126 /* Fill in the basic members */ 126 /* Fill in the basic members */
127 overlay->format = format; 127 overlay->format = format;
128 overlay->w = width; 128 overlay->w = width;
129 overlay->h = height; 129 overlay->h = height;
131 /* Set up the YUV surface function structure */ 131 /* Set up the YUV surface function structure */
132 overlay->hwfuncs = &gs_yuvfuncs; 132 overlay->hwfuncs = &gs_yuvfuncs;
133 overlay->hw_overlay = 1; 133 overlay->hw_overlay = 1;
134 134
135 /* Create the pixel data */ 135 /* Create the pixel data */
136 hwdata = (struct private_yuvhwdata *) SDL_malloc (sizeof *hwdata); 136 hwdata = (struct private_yuvhwdata *) SDL_malloc(sizeof *hwdata);
137 overlay->hwdata = hwdata; 137 overlay->hwdata = hwdata;
138 if (hwdata == NULL) { 138 if (hwdata == NULL) {
139 SDL_FreeYUVOverlay (overlay); 139 SDL_FreeYUVOverlay(overlay);
140 SDL_OutOfMemory (); 140 SDL_OutOfMemory();
141 return (NULL); 141 return (NULL);
142 } 142 }
143 hwdata->ipu_fd = -1; 143 hwdata->ipu_fd = -1;
144 hwdata->pixels = (Uint8 *) SDL_malloc (width * height * 2); 144 hwdata->pixels = (Uint8 *) SDL_malloc(width * height * 2);
145 if (hwdata->pixels == NULL) { 145 if (hwdata->pixels == NULL) {
146 SDL_FreeYUVOverlay (overlay); 146 SDL_FreeYUVOverlay(overlay);
147 SDL_OutOfMemory (); 147 SDL_OutOfMemory();
148 return (NULL); 148 return (NULL);
149 } 149 }
150 hwdata->macroblocks = (width / 16) * (height / 16); 150 hwdata->macroblocks = (width / 16) * (height / 16);
151 151
152 /* Find the pitch and offset values for the overlay */ 152 /* Find the pitch and offset values for the overlay */
173 /* Theoretically we could support several concurrent decode 173 /* Theoretically we could support several concurrent decode
174 streams queueing up on the same file descriptor, but for 174 streams queueing up on the same file descriptor, but for
175 simplicity we'll support only one. Opening the IPU more 175 simplicity we'll support only one. Opening the IPU more
176 than once will fail with EBUSY. 176 than once will fail with EBUSY.
177 */ 177 */
178 hwdata->ipu_fd = open ("/dev/ps2ipu", O_RDWR); 178 hwdata->ipu_fd = open("/dev/ps2ipu", O_RDWR);
179 if (hwdata->ipu_fd < 0) { 179 if (hwdata->ipu_fd < 0) {
180 SDL_FreeYUVOverlay (overlay); 180 SDL_FreeYUVOverlay(overlay);
181 SDL_SetError ("Playstation 2 IPU busy"); 181 SDL_SetError("Playstation 2 IPU busy");
182 return (NULL); 182 return (NULL);
183 } 183 }
184 184
185 /* Allocate a DMA area for pixel conversion */ 185 /* Allocate a DMA area for pixel conversion */
186 bpp = this->screen->format->BytesPerPixel; 186 bpp = this->screen->format->BytesPerPixel;
187 map_offset = (mapped_len + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); 187 map_offset = (mapped_len + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
188 hwdata->dma_len = hwdata->macroblocks * (16 * 16 + 8 * 8 + 8 * 8) + 188 hwdata->dma_len = hwdata->macroblocks * (16 * 16 + 8 * 8 + 8 * 8) +
189 width * height * bpp + 189 width * height * bpp +
190 hwdata->macroblocks * (16 * sizeof (long long)) + 190 hwdata->macroblocks * (16 * sizeof(long long)) +
191 12 * sizeof (long long); 191 12 * sizeof(long long);
192 hwdata->dma_mem = mmap (0, hwdata->dma_len, PROT_READ | PROT_WRITE, 192 hwdata->dma_mem = mmap(0, hwdata->dma_len, PROT_READ | PROT_WRITE,
193 MAP_SHARED, memory_fd, map_offset); 193 MAP_SHARED, memory_fd, map_offset);
194 if (hwdata->dma_mem == MAP_FAILED) { 194 if (hwdata->dma_mem == MAP_FAILED) {
195 hwdata->ipu_imem = (caddr_t) 0; 195 hwdata->ipu_imem = (caddr_t) 0;
196 SDL_FreeYUVOverlay (overlay); 196 SDL_FreeYUVOverlay(overlay);
197 SDL_SetError ("Unable to map %d bytes for DMA", hwdata->dma_len); 197 SDL_SetError("Unable to map %d bytes for DMA", hwdata->dma_len);
198 return (NULL); 198 return (NULL);
199 } 199 }
200 hwdata->ipu_imem = hwdata->dma_mem; 200 hwdata->ipu_imem = hwdata->dma_mem;
201 hwdata->ipu_omem = hwdata->ipu_imem + 201 hwdata->ipu_omem = hwdata->ipu_imem +
202 hwdata->macroblocks * (16 * 16 + 8 * 8 + 8 * 8); 202 hwdata->macroblocks * (16 * 16 + 8 * 8 + 8 * 8);
203 hwdata->dma_tags = hwdata->ipu_omem + width * height * bpp; 203 hwdata->dma_tags = hwdata->ipu_omem + width * height * bpp;
204 204
205 /* Allocate memory for the DMA packets */ 205 /* Allocate memory for the DMA packets */
206 hwdata->plist.num = hwdata->macroblocks * 4 + 1; 206 hwdata->plist.num = hwdata->macroblocks * 4 + 1;
207 hwdata->plist.packet = 207 hwdata->plist.packet =
208 (struct ps2_packet *) SDL_malloc (hwdata->plist.num * 208 (struct ps2_packet *) SDL_malloc(hwdata->plist.num *
209 sizeof (struct ps2_packet)); 209 sizeof(struct ps2_packet));
210 if (!hwdata->plist.packet) { 210 if (!hwdata->plist.packet) {
211 SDL_FreeYUVOverlay (overlay); 211 SDL_FreeYUVOverlay(overlay);
212 SDL_OutOfMemory (); 212 SDL_OutOfMemory();
213 return (NULL); 213 return (NULL);
214 } 214 }
215 pnum = 0; 215 pnum = 0;
216 packet = hwdata->plist.packet; 216 packet = hwdata->plist.packet;
217 217
225 for (h = height / 16; h; --h) { 225 for (h = height / 16; h; --h) {
226 x = 0; /* Visible video memory */ 226 x = 0; /* Visible video memory */
227 for (w = width / 16; w; --w) { 227 for (w = width / 16; w; --w) {
228 /* The head tag */ 228 /* The head tag */
229 packet[pnum].ptr = &tags[0]; 229 packet[pnum].ptr = &tags[0];
230 packet[pnum].len = 10 * sizeof (*tags); 230 packet[pnum].len = 10 * sizeof(*tags);
231 ++pnum; 231 ++pnum;
232 tags[0] = 4 | (1LL << 60); /* GIFtag */ 232 tags[0] = 4 | (1LL << 60); /* GIFtag */
233 tags[1] = 0x0e; /* A+D */ 233 tags[1] = 0x0e; /* A+D */
234 tags[2] = ((unsigned long long) fbp << 32) | 234 tags[2] = ((unsigned long long) fbp << 32) |
235 ((unsigned long long) fbw << 48) | 235 ((unsigned long long) fbw << 48) |
243 tags[7] = PS2_GS_TRXREG; 243 tags[7] = PS2_GS_TRXREG;
244 tags[8] = 0; 244 tags[8] = 0;
245 tags[9] = PS2_GS_TRXDIR; 245 tags[9] = PS2_GS_TRXDIR;
246 /* Now the actual image data */ 246 /* Now the actual image data */
247 packet[pnum].ptr = &tags[10]; 247 packet[pnum].ptr = &tags[10];
248 packet[pnum].len = 2 * sizeof (*tags); 248 packet[pnum].len = 2 * sizeof(*tags);
249 ++pnum; 249 ++pnum;
250 tags[10] = ((16 * 16 * bpp) >> 4) | (2LL << 58); 250 tags[10] = ((16 * 16 * bpp) >> 4) | (2LL << 58);
251 tags[11] = 0; 251 tags[11] = 0;
252 packet[pnum].ptr = (void *) base; 252 packet[pnum].ptr = (void *) base;
253 packet[pnum].len = 16 * 16 * bpp; 253 packet[pnum].len = 16 * 16 * bpp;
254 ++pnum; 254 ++pnum;
255 packet[pnum].ptr = &tags[12]; 255 packet[pnum].ptr = &tags[12];
256 packet[pnum].len = 2 * sizeof (*tags); 256 packet[pnum].len = 2 * sizeof(*tags);
257 ++pnum; 257 ++pnum;
258 tags[12] = (0 >> 4) | (1 << 15) | (2LL << 58); 258 tags[12] = (0 >> 4) | (1 << 15) | (2LL << 58);
259 tags[13] = 0; 259 tags[13] = 0;
260 260
261 tags += 16; 261 tags += 16;
266 y += 16; 266 y += 16;
267 } 267 }
268 268
269 /* Set up the texture memory area for the video */ 269 /* Set up the texture memory area for the video */
270 tex_packet.ptr = tags; 270 tex_packet.ptr = tags;
271 tex_packet.len = 8 * sizeof (*tags); 271 tex_packet.len = 8 * sizeof(*tags);
272 tags[0] = 3 | (1LL << 60); /* GIFtag */ 272 tags[0] = 3 | (1LL << 60); /* GIFtag */
273 tags[1] = 0x0e; /* A+D */ 273 tags[1] = 0x0e; /* A+D */
274 tags[2] = ((screen_image.y + screen_image.h) * screen_image.w) / 64 + 274 tags[2] = ((screen_image.y + screen_image.h) * screen_image.w) / 64 +
275 ((unsigned long long) fbw << 14) + 275 ((unsigned long long) fbw << 14) +
276 ((unsigned long long) psm << 20) + 276 ((unsigned long long) psm << 20) +
277 ((unsigned long long) power_of_2 (width) << 26) + 277 ((unsigned long long) power_of_2(width) << 26) +
278 ((unsigned long long) power_of_2 (height) << 30) + 278 ((unsigned long long) power_of_2(height) << 30) +
279 ((unsigned long long) 1 << 34) + ((unsigned long long) 1 << 35); 279 ((unsigned long long) 1 << 34) + ((unsigned long long) 1 << 35);
280 tags[3] = PS2_GS_TEX0_1; 280 tags[3] = PS2_GS_TEX0_1;
281 tags[4] = (1 << 5) + (1 << 6); 281 tags[4] = (1 << 5) + (1 << 6);
282 tags[5] = PS2_GS_TEX1_1; 282 tags[5] = PS2_GS_TEX1_1;
283 tags[6] = 0; 283 tags[6] = 0;
284 tags[7] = PS2_GS_TEXFLUSH; 284 tags[7] = PS2_GS_TEXFLUSH;
285 ioctl (console_fd, PS2IOC_SEND, &tex_packet); 285 ioctl(console_fd, PS2IOC_SEND, &tex_packet);
286 286
287 /* Set up the tags for scaling the image */ 287 /* Set up the tags for scaling the image */
288 packet[pnum].ptr = tags; 288 packet[pnum].ptr = tags;
289 packet[pnum].len = 12 * sizeof (*tags); 289 packet[pnum].len = 12 * sizeof(*tags);
290 ++pnum; 290 ++pnum;
291 tags[0] = 5 | (1LL << 60); /* GIFtag */ 291 tags[0] = 5 | (1LL << 60); /* GIFtag */
292 tags[1] = 0x0e; /* A+D */ 292 tags[1] = 0x0e; /* A+D */
293 tags[2] = 6 + (1 << 4) + (1 << 8); 293 tags[2] = 6 + (1 << 4) + (1 << 8);
294 tags[3] = PS2_GS_PRIM; 294 tags[3] = PS2_GS_PRIM;
308 /* We're all done.. */ 308 /* We're all done.. */
309 return (overlay); 309 return (overlay);
310 } 310 }
311 311
312 int 312 int
313 GS_LockYUVOverlay (_THIS, SDL_Overlay * overlay) 313 GS_LockYUVOverlay(_THIS, SDL_Overlay * overlay)
314 { 314 {
315 return (0); 315 return (0);
316 } 316 }
317 317
318 void 318 void
319 GS_UnlockYUVOverlay (_THIS, SDL_Overlay * overlay) 319 GS_UnlockYUVOverlay(_THIS, SDL_Overlay * overlay)
320 { 320 {
321 return; 321 return;
322 } 322 }
323 323
324 int 324 int
325 GS_DisplayYUVOverlay (_THIS, SDL_Overlay * overlay, SDL_Rect * src, 325 GS_DisplayYUVOverlay(_THIS, SDL_Overlay * overlay, SDL_Rect * src,
326 SDL_Rect * dst) 326 SDL_Rect * dst)
327 { 327 {
328 struct private_yuvhwdata *hwdata; 328 struct private_yuvhwdata *hwdata;
329 __u32 cmd; 329 __u32 cmd;
330 struct ps2_packet packet; 330 struct ps2_packet packet;
331 int h, w, i; 331 int h, w, i;
348 case SDL_IYUV_OVERLAY: 348 case SDL_IYUV_OVERLAY:
349 lum = (Uint32 *) overlay->pixels[0]; 349 lum = (Uint32 *) overlay->pixels[0];
350 Cr = (Uint32 *) overlay->pixels[2]; 350 Cr = (Uint32 *) overlay->pixels[2];
351 Cb = (Uint32 *) overlay->pixels[1]; 351 Cb = (Uint32 *) overlay->pixels[1];
352 default: 352 default:
353 SDL_SetError ("Unsupported YUV format in blit (?)"); 353 SDL_SetError("Unsupported YUV format in blit (?)");
354 return (-1); 354 return (-1);
355 } 355 }
356 dstp = (Uint32 *) hwdata->ipu_imem; 356 dstp = (Uint32 *) hwdata->ipu_imem;
357 lum_pitch = overlay->w / 4; 357 lum_pitch = overlay->w / 4;
358 crb_pitch = (overlay->w / 2) / 4; 358 crb_pitch = (overlay->w / 2) / 4;
395 Cb += crb_pitch * 8; 395 Cb += crb_pitch * 8;
396 } 396 }
397 397
398 /* Send the macroblock data to the IPU */ 398 /* Send the macroblock data to the IPU */
399 #ifdef DEBUG_YUV 399 #ifdef DEBUG_YUV
400 fprintf (stderr, "Sending data to IPU..\n"); 400 fprintf(stderr, "Sending data to IPU..\n");
401 #endif 401 #endif
402 packet.ptr = hwdata->ipu_imem; 402 packet.ptr = hwdata->ipu_imem;
403 packet.len = hwdata->macroblocks * (16 * 16 + 8 * 8 + 8 * 8); 403 packet.len = hwdata->macroblocks * (16 * 16 + 8 * 8 + 8 * 8);
404 ioctl (hwdata->ipu_fd, PS2IOC_SENDA, &packet); 404 ioctl(hwdata->ipu_fd, PS2IOC_SENDA, &packet);
405 405
406 /* Trigger the DMA to the IPU for conversion */ 406 /* Trigger the DMA to the IPU for conversion */
407 #ifdef DEBUG_YUV 407 #ifdef DEBUG_YUV
408 fprintf (stderr, "Trigging conversion command\n"); 408 fprintf(stderr, "Trigging conversion command\n");
409 #endif 409 #endif
410 cmd = (7 << 28) + hwdata->macroblocks; 410 cmd = (7 << 28) + hwdata->macroblocks;
411 if (screen_image.psm == PS2_GS_PSMCT16) { 411 if (screen_image.psm == PS2_GS_PSMCT16) {
412 cmd += (1 << 27) + /* Output RGB 555 */ 412 cmd += (1 << 27) + /* Output RGB 555 */
413 (1 << 26); /* Dither output */ 413 (1 << 26); /* Dither output */
414 } 414 }
415 ioctl (hwdata->ipu_fd, PS2IOC_SIPUCMD, &cmd); 415 ioctl(hwdata->ipu_fd, PS2IOC_SIPUCMD, &cmd);
416 416
417 /* Retrieve the converted image from the IPU */ 417 /* Retrieve the converted image from the IPU */
418 #ifdef DEBUG_YUV 418 #ifdef DEBUG_YUV
419 fprintf (stderr, "Retrieving data from IPU..\n"); 419 fprintf(stderr, "Retrieving data from IPU..\n");
420 #endif 420 #endif
421 packet.ptr = hwdata->ipu_omem; 421 packet.ptr = hwdata->ipu_omem;
422 packet.len = overlay->w * overlay->h * 422 packet.len = overlay->w * overlay->h *
423 this->screen->format->BytesPerPixel; 423 this->screen->format->BytesPerPixel;
424 ioctl (hwdata->ipu_fd, PS2IOC_RECV, &packet); 424 ioctl(hwdata->ipu_fd, PS2IOC_RECV, &packet);
425 425
426 #ifdef DEBUG_YUV 426 #ifdef DEBUG_YUV
427 fprintf (stderr, "Copying image to screen..\n"); 427 fprintf(stderr, "Copying image to screen..\n");
428 #endif 428 #endif
429 /* Wait for previous DMA to complete */ 429 /* Wait for previous DMA to complete */
430 ioctl (console_fd, PS2IOC_SENDQCT, 1); 430 ioctl(console_fd, PS2IOC_SENDQCT, 1);
431 431
432 /* Send the current image to the screen and scale it */ 432 /* Send the current image to the screen and scale it */
433 screen = this->screen; 433 screen = this->screen;
434 x = (unsigned int) dst->x; 434 x = (unsigned int) dst->x;
435 y = (unsigned int) dst->y; 435 y = (unsigned int) dst->y;
440 y += screen_image.y; 440 y += screen_image.y;
441 *hwdata->stretch_x1y1 = (x * 16) + ((y * 16) << 16); 441 *hwdata->stretch_x1y1 = (x * 16) + ((y * 16) << 16);
442 x += (unsigned int) dst->w; 442 x += (unsigned int) dst->w;
443 y += (unsigned int) dst->h; 443 y += (unsigned int) dst->h;
444 *hwdata->stretch_x2y2 = (x * 16) + ((y * 16) << 16); 444 *hwdata->stretch_x2y2 = (x * 16) + ((y * 16) << 16);
445 return ioctl (console_fd, PS2IOC_SENDL, &hwdata->plist); 445 return ioctl(console_fd, PS2IOC_SENDL, &hwdata->plist);
446 } 446 }
447 447
448 void 448 void
449 GS_FreeYUVOverlay (_THIS, SDL_Overlay * overlay) 449 GS_FreeYUVOverlay(_THIS, SDL_Overlay * overlay)
450 { 450 {
451 struct private_yuvhwdata *hwdata; 451 struct private_yuvhwdata *hwdata;
452 452
453 hwdata = overlay->hwdata; 453 hwdata = overlay->hwdata;
454 if (hwdata) { 454 if (hwdata) {
455 if (hwdata->ipu_fd >= 0) { 455 if (hwdata->ipu_fd >= 0) {
456 close (hwdata->ipu_fd); 456 close(hwdata->ipu_fd);
457 } 457 }
458 if (hwdata->dma_mem) { 458 if (hwdata->dma_mem) {
459 munmap (hwdata->dma_mem, hwdata->dma_len); 459 munmap(hwdata->dma_mem, hwdata->dma_len);
460 } 460 }
461 if (hwdata->plist.packet) { 461 if (hwdata->plist.packet) {
462 SDL_free (hwdata->plist.packet); 462 SDL_free(hwdata->plist.packet);
463 } 463 }
464 if (hwdata->pixels) { 464 if (hwdata->pixels) {
465 SDL_free (hwdata->pixels); 465 SDL_free(hwdata->pixels);
466 } 466 }
467 SDL_free (hwdata); 467 SDL_free(hwdata);
468 } 468 }
469 } 469 }
470 470
471 /* vi: set ts=4 sw=4 expandtab: */ 471 /* vi: set ts=4 sw=4 expandtab: */