comparison src/video/ps2gs/SDL_gsyuv.c @ 1895:c121d94672cb

SDL 1.2 is moving to a branch, and SDL 1.3 is becoming the head.
author Sam Lantinga <slouken@libsdl.org>
date Mon, 10 Jul 2006 21:04:37 +0000
parents 3d138844ceab
children 99210400e8b9
comparison
equal deleted inserted replaced
1894:c69cee13dd76 1895:c121d94672cb
25 25
26 #include <fcntl.h> 26 #include <fcntl.h>
27 #include <unistd.h> 27 #include <unistd.h>
28 #include <sys/ioctl.h> 28 #include <sys/ioctl.h>
29 #include <sys/mman.h> 29 #include <sys/mman.h>
30 #include <asm/page.h> /* For definition of PAGE_SIZE */ 30 #include <asm/page.h> /* For definition of PAGE_SIZE */
31 31
32 #include "SDL_video.h" 32 #include "SDL_video.h"
33 #include "SDL_gsyuv_c.h" 33 #include "SDL_gsyuv_c.h"
34 #include "../SDL_yuvfuncs.h" 34 #include "../SDL_yuvfuncs.h"
35 35
36 /* The maximum number of 16x16 pixel block converted at once */ 36 /* The maximum number of 16x16 pixel block converted at once */
37 #define MAX_MACROBLOCKS 1024 /* 2^10 macroblocks at once */ 37 #define MAX_MACROBLOCKS 1024 /* 2^10 macroblocks at once */
38 38
39 /* The functions used to manipulate video overlays */ 39 /* The functions used to manipulate video overlays */
40 static struct private_yuvhwfuncs gs_yuvfuncs = { 40 static struct private_yuvhwfuncs gs_yuvfuncs = {
41 GS_LockYUVOverlay, 41 GS_LockYUVOverlay,
42 GS_UnlockYUVOverlay, 42 GS_UnlockYUVOverlay,
43 GS_DisplayYUVOverlay, 43 GS_DisplayYUVOverlay,
44 GS_FreeYUVOverlay 44 GS_FreeYUVOverlay
45 }; 45 };
46 46
47 struct private_yuvhwdata { 47 struct private_yuvhwdata
48 int ipu_fd; 48 {
49 Uint8 *pixels; 49 int ipu_fd;
50 int macroblocks; 50 Uint8 *pixels;
51 int dma_len; 51 int macroblocks;
52 caddr_t dma_mem; 52 int dma_len;
53 caddr_t ipu_imem; 53 caddr_t dma_mem;
54 caddr_t ipu_omem; 54 caddr_t ipu_imem;
55 caddr_t dma_tags; 55 caddr_t ipu_omem;
56 unsigned long long *stretch_x1y1; 56 caddr_t dma_tags;
57 unsigned long long *stretch_x2y2; 57 unsigned long long *stretch_x1y1;
58 struct ps2_plist plist; 58 unsigned long long *stretch_x2y2;
59 59 struct ps2_plist plist;
60 /* These are just so we don't have to allocate them separately */ 60
61 Uint16 pitches[3]; 61 /* These are just so we don't have to allocate them separately */
62 Uint8 *planes[3]; 62 Uint16 pitches[3];
63 Uint8 *planes[3];
63 }; 64 };
64 65
65 static int power_of_2(int value) 66 static int
66 { 67 power_of_2(int value)
67 int shift; 68 {
68 69 int shift;
69 for ( shift = 0; (1<<shift) < value; ++shift ) { 70
70 /* Keep looking */ ; 71 for (shift = 0; (1 << shift) < value; ++shift) {
71 } 72 /* Keep looking */ ;
72 return(shift); 73 }
73 } 74 return (shift);
74 75 }
75 SDL_Overlay *GS_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display) 76
76 { 77 SDL_Overlay *
77 SDL_Overlay *overlay; 78 GS_CreateYUVOverlay(_THIS, int width, int height, Uint32 format,
78 struct private_yuvhwdata *hwdata; 79 SDL_Surface * display)
79 int map_offset; 80 {
80 unsigned long long *tags; 81 SDL_Overlay *overlay;
81 caddr_t base; 82 struct private_yuvhwdata *hwdata;
82 int bpp; 83 int map_offset;
83 int fbp, fbw, psm; 84 unsigned long long *tags;
84 int x, y, w, h; 85 caddr_t base;
85 int pnum; 86 int bpp;
86 struct ps2_packet *packet; 87 int fbp, fbw, psm;
87 struct ps2_packet tex_packet; 88 int x, y, w, h;
88 89 int pnum;
89 /* We can only decode blocks of 16x16 pixels */ 90 struct ps2_packet *packet;
90 if ( (width & 15) || (height & 15) ) { 91 struct ps2_packet tex_packet;
91 SDL_SetError("Overlay width/height must be multiples of 16"); 92
92 return(NULL); 93 /* We can only decode blocks of 16x16 pixels */
93 } 94 if ((width & 15) || (height & 15)) {
94 /* Make sure the image isn't too large for a single DMA transfer */ 95 SDL_SetError("Overlay width/height must be multiples of 16");
95 if ( ((width/16) * (height/16)) > MAX_MACROBLOCKS ) { 96 return (NULL);
96 SDL_SetError("Overlay too large (maximum size: %d pixels)", 97 }
97 MAX_MACROBLOCKS * 16 * 16); 98 /* Make sure the image isn't too large for a single DMA transfer */
98 return(NULL); 99 if (((width / 16) * (height / 16)) > MAX_MACROBLOCKS) {
99 } 100 SDL_SetError("Overlay too large (maximum size: %d pixels)",
100 101 MAX_MACROBLOCKS * 16 * 16);
101 /* Double-check the requested format. For simplicity, we'll only 102 return (NULL);
102 support planar YUV formats. 103 }
103 */ 104
104 switch (format) { 105 /* Double-check the requested format. For simplicity, we'll only
105 case SDL_YV12_OVERLAY: 106 support planar YUV formats.
106 case SDL_IYUV_OVERLAY: 107 */
107 /* Supported planar YUV format */ 108 switch (format) {
108 break; 109 case SDL_YV12_OVERLAY:
109 default: 110 case SDL_IYUV_OVERLAY:
110 SDL_SetError("Unsupported YUV format"); 111 /* Supported planar YUV format */
111 return(NULL); 112 break;
112 } 113 default:
113 114 SDL_SetError("Unsupported YUV format");
114 /* Create the overlay structure */ 115 return (NULL);
115 overlay = (SDL_Overlay *)SDL_malloc(sizeof *overlay); 116 }
116 if ( overlay == NULL ) { 117
117 SDL_OutOfMemory(); 118 /* Create the overlay structure */
118 return(NULL); 119 overlay = (SDL_Overlay *) SDL_malloc(sizeof *overlay);
119 } 120 if (overlay == NULL) {
120 SDL_memset(overlay, 0, (sizeof *overlay)); 121 SDL_OutOfMemory();
121 122 return (NULL);
122 /* Fill in the basic members */ 123 }
123 overlay->format = format; 124 SDL_memset(overlay, 0, (sizeof *overlay));
124 overlay->w = width; 125
125 overlay->h = height; 126 /* Fill in the basic members */
126 127 overlay->format = format;
127 /* Set up the YUV surface function structure */ 128 overlay->w = width;
128 overlay->hwfuncs = &gs_yuvfuncs; 129 overlay->h = height;
129 overlay->hw_overlay = 1; 130
130 131 /* Set up the YUV surface function structure */
131 /* Create the pixel data */ 132 overlay->hwfuncs = &gs_yuvfuncs;
132 hwdata = (struct private_yuvhwdata *)SDL_malloc(sizeof *hwdata); 133 overlay->hw_overlay = 1;
133 overlay->hwdata = hwdata; 134
134 if ( hwdata == NULL ) { 135 /* Create the pixel data */
135 SDL_FreeYUVOverlay(overlay); 136 hwdata = (struct private_yuvhwdata *) SDL_malloc(sizeof *hwdata);
136 SDL_OutOfMemory(); 137 overlay->hwdata = hwdata;
137 return(NULL); 138 if (hwdata == NULL) {
138 } 139 SDL_FreeYUVOverlay(overlay);
139 hwdata->ipu_fd = -1; 140 SDL_OutOfMemory();
140 hwdata->pixels = (Uint8 *)SDL_malloc(width*height*2); 141 return (NULL);
141 if ( hwdata->pixels == NULL ) { 142 }
142 SDL_FreeYUVOverlay(overlay); 143 hwdata->ipu_fd = -1;
143 SDL_OutOfMemory(); 144 hwdata->pixels = (Uint8 *) SDL_malloc(width * height * 2);
144 return(NULL); 145 if (hwdata->pixels == NULL) {
145 } 146 SDL_FreeYUVOverlay(overlay);
146 hwdata->macroblocks = (width/16) * (height/16); 147 SDL_OutOfMemory();
147 148 return (NULL);
148 /* Find the pitch and offset values for the overlay */ 149 }
149 overlay->pitches = hwdata->pitches; 150 hwdata->macroblocks = (width / 16) * (height / 16);
150 overlay->pixels = hwdata->planes; 151
151 switch (format) { 152 /* Find the pitch and offset values for the overlay */
152 case SDL_YV12_OVERLAY: 153 overlay->pitches = hwdata->pitches;
153 case SDL_IYUV_OVERLAY: 154 overlay->pixels = hwdata->planes;
154 overlay->pitches[0] = overlay->w; 155 switch (format) {
155 overlay->pitches[1] = overlay->pitches[0] / 2; 156 case SDL_YV12_OVERLAY:
156 overlay->pitches[2] = overlay->pitches[0] / 2; 157 case SDL_IYUV_OVERLAY:
157 overlay->pixels[0] = hwdata->pixels; 158 overlay->pitches[0] = overlay->w;
158 overlay->pixels[1] = overlay->pixels[0] + 159 overlay->pitches[1] = overlay->pitches[0] / 2;
159 overlay->pitches[0] * overlay->h; 160 overlay->pitches[2] = overlay->pitches[0] / 2;
160 overlay->pixels[2] = overlay->pixels[1] + 161 overlay->pixels[0] = hwdata->pixels;
161 overlay->pitches[1] * overlay->h / 2; 162 overlay->pixels[1] = overlay->pixels[0] +
162 overlay->planes = 3; 163 overlay->pitches[0] * overlay->h;
163 break; 164 overlay->pixels[2] = overlay->pixels[1] +
164 default: 165 overlay->pitches[1] * overlay->h / 2;
165 /* We should never get here (caught above) */ 166 overlay->planes = 3;
166 break; 167 break;
167 } 168 default:
168 169 /* We should never get here (caught above) */
169 /* Theoretically we could support several concurrent decode 170 break;
170 streams queueing up on the same file descriptor, but for 171 }
171 simplicity we'll support only one. Opening the IPU more 172
172 than once will fail with EBUSY. 173 /* Theoretically we could support several concurrent decode
173 */ 174 streams queueing up on the same file descriptor, but for
174 hwdata->ipu_fd = open("/dev/ps2ipu", O_RDWR); 175 simplicity we'll support only one. Opening the IPU more
175 if ( hwdata->ipu_fd < 0 ) { 176 than once will fail with EBUSY.
176 SDL_FreeYUVOverlay(overlay); 177 */
177 SDL_SetError("Playstation 2 IPU busy"); 178 hwdata->ipu_fd = open("/dev/ps2ipu", O_RDWR);
178 return(NULL); 179 if (hwdata->ipu_fd < 0) {
179 } 180 SDL_FreeYUVOverlay(overlay);
180 181 SDL_SetError("Playstation 2 IPU busy");
181 /* Allocate a DMA area for pixel conversion */ 182 return (NULL);
182 bpp = this->screen->format->BytesPerPixel; 183 }
183 map_offset = (mapped_len + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); 184
184 hwdata->dma_len = hwdata->macroblocks * (16 * 16 + 8 * 8 + 8 * 8) + 185 /* Allocate a DMA area for pixel conversion */
185 width * height * bpp + 186 bpp = this->screen->format->BytesPerPixel;
186 hwdata->macroblocks * (16 * sizeof(long long)) + 187 map_offset = (mapped_len + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
187 12 * sizeof(long long); 188 hwdata->dma_len = hwdata->macroblocks * (16 * 16 + 8 * 8 + 8 * 8) +
188 hwdata->dma_mem = mmap(0, hwdata->dma_len, PROT_READ|PROT_WRITE, 189 width * height * bpp +
189 MAP_SHARED, memory_fd, map_offset); 190 hwdata->macroblocks * (16 * sizeof(long long)) +
190 if ( hwdata->dma_mem == MAP_FAILED ) { 191 12 * sizeof(long long);
191 hwdata->ipu_imem = (caddr_t)0; 192 hwdata->dma_mem = mmap(0, hwdata->dma_len, PROT_READ | PROT_WRITE,
192 SDL_FreeYUVOverlay(overlay); 193 MAP_SHARED, memory_fd, map_offset);
193 SDL_SetError("Unable to map %d bytes for DMA", hwdata->dma_len); 194 if (hwdata->dma_mem == MAP_FAILED) {
194 return(NULL); 195 hwdata->ipu_imem = (caddr_t) 0;
195 } 196 SDL_FreeYUVOverlay(overlay);
196 hwdata->ipu_imem = hwdata->dma_mem; 197 SDL_SetError("Unable to map %d bytes for DMA", hwdata->dma_len);
197 hwdata->ipu_omem = hwdata->ipu_imem + 198 return (NULL);
198 hwdata->macroblocks * (16 * 16 + 8 * 8 + 8 * 8); 199 }
199 hwdata->dma_tags = hwdata->ipu_omem + width * height * bpp; 200 hwdata->ipu_imem = hwdata->dma_mem;
200 201 hwdata->ipu_omem = hwdata->ipu_imem +
201 /* Allocate memory for the DMA packets */ 202 hwdata->macroblocks * (16 * 16 + 8 * 8 + 8 * 8);
202 hwdata->plist.num = hwdata->macroblocks * 4 + 1; 203 hwdata->dma_tags = hwdata->ipu_omem + width * height * bpp;
203 hwdata->plist.packet = (struct ps2_packet *)SDL_malloc( 204
204 hwdata->plist.num*sizeof(struct ps2_packet)); 205 /* Allocate memory for the DMA packets */
205 if ( ! hwdata->plist.packet ) { 206 hwdata->plist.num = hwdata->macroblocks * 4 + 1;
206 SDL_FreeYUVOverlay(overlay); 207 hwdata->plist.packet =
207 SDL_OutOfMemory(); 208 (struct ps2_packet *) SDL_malloc(hwdata->plist.num *
208 return(NULL); 209 sizeof(struct ps2_packet));
209 } 210 if (!hwdata->plist.packet) {
210 pnum = 0; 211 SDL_FreeYUVOverlay(overlay);
211 packet = hwdata->plist.packet; 212 SDL_OutOfMemory();
212 213 return (NULL);
213 /* Set up the tags to send the image to the screen */ 214 }
214 tags = (unsigned long long *)hwdata->dma_tags; 215 pnum = 0;
215 base = hwdata->ipu_omem; 216 packet = hwdata->plist.packet;
216 fbp = screen_image.fbp; 217
217 fbw = screen_image.fbw; 218 /* Set up the tags to send the image to the screen */
218 psm = screen_image.psm; 219 tags = (unsigned long long *) hwdata->dma_tags;
219 y = screen_image.y + screen_image.h; /* Offscreen video memory */ 220 base = hwdata->ipu_omem;
220 for ( h=height/16; h; --h ) { 221 fbp = screen_image.fbp;
221 x = 0; /* Visible video memory */ 222 fbw = screen_image.fbw;
222 for ( w=width/16; w; --w ) { 223 psm = screen_image.psm;
223 /* The head tag */ 224 y = screen_image.y + screen_image.h; /* Offscreen video memory */
224 packet[pnum].ptr = &tags[0]; 225 for (h = height / 16; h; --h) {
225 packet[pnum].len = 10 * sizeof(*tags); 226 x = 0; /* Visible video memory */
226 ++pnum; 227 for (w = width / 16; w; --w) {
227 tags[0] = 4 | (1LL << 60); /* GIFtag */ 228 /* The head tag */
228 tags[1] = 0x0e; /* A+D */ 229 packet[pnum].ptr = &tags[0];
229 tags[2] = ((unsigned long long)fbp << 32) | 230 packet[pnum].len = 10 * sizeof(*tags);
230 ((unsigned long long)fbw << 48) | 231 ++pnum;
231 ((unsigned long long)psm << 56); 232 tags[0] = 4 | (1LL << 60); /* GIFtag */
232 tags[3] = PS2_GS_BITBLTBUF; 233 tags[1] = 0x0e; /* A+D */
233 tags[4] = ((unsigned long long)x << 32) | 234 tags[2] = ((unsigned long long) fbp << 32) |
234 ((unsigned long long)y << 48); 235 ((unsigned long long) fbw << 48) |
235 tags[5] = PS2_GS_TRXPOS; 236 ((unsigned long long) psm << 56);
236 tags[6] = (unsigned long long)16 | 237 tags[3] = PS2_GS_BITBLTBUF;
237 ((unsigned long long)16 << 32); 238 tags[4] = ((unsigned long long) x << 32) |
238 tags[7] = PS2_GS_TRXREG; 239 ((unsigned long long) y << 48);
239 tags[8] = 0; 240 tags[5] = PS2_GS_TRXPOS;
240 tags[9] = PS2_GS_TRXDIR; 241 tags[6] = (unsigned long long) 16 |
241 /* Now the actual image data */ 242 ((unsigned long long) 16 << 32);
242 packet[pnum].ptr = &tags[10]; 243 tags[7] = PS2_GS_TRXREG;
243 packet[pnum].len = 2 * sizeof(*tags); 244 tags[8] = 0;
244 ++pnum; 245 tags[9] = PS2_GS_TRXDIR;
245 tags[10] = ((16*16*bpp) >> 4) | (2LL << 58); 246 /* Now the actual image data */
246 tags[11] = 0; 247 packet[pnum].ptr = &tags[10];
247 packet[pnum].ptr = (void *)base; 248 packet[pnum].len = 2 * sizeof(*tags);
248 packet[pnum].len = 16 * 16 * bpp; 249 ++pnum;
249 ++pnum; 250 tags[10] = ((16 * 16 * bpp) >> 4) | (2LL << 58);
250 packet[pnum].ptr = &tags[12]; 251 tags[11] = 0;
251 packet[pnum].len = 2 * sizeof(*tags); 252 packet[pnum].ptr = (void *) base;
252 ++pnum; 253 packet[pnum].len = 16 * 16 * bpp;
253 tags[12] = (0 >> 4) | (1 << 15) | (2LL << 58); 254 ++pnum;
254 tags[13] = 0; 255 packet[pnum].ptr = &tags[12];
255 256 packet[pnum].len = 2 * sizeof(*tags);
256 tags += 16; 257 ++pnum;
257 base += 16 * 16 * bpp; 258 tags[12] = (0 >> 4) | (1 << 15) | (2LL << 58);
258 259 tags[13] = 0;
259 x += 16; 260
260 } 261 tags += 16;
261 y += 16; 262 base += 16 * 16 * bpp;
262 } 263
263 264 x += 16;
264 /* Set up the texture memory area for the video */ 265 }
265 tex_packet.ptr = tags; 266 y += 16;
266 tex_packet.len = 8 * sizeof(*tags); 267 }
267 tags[0] = 3 | (1LL << 60); /* GIFtag */ 268
268 tags[1] = 0x0e; /* A+D */ 269 /* Set up the texture memory area for the video */
269 tags[2] = ((screen_image.y + screen_image.h) * screen_image.w) / 64 + 270 tex_packet.ptr = tags;
270 ((unsigned long long)fbw << 14) + 271 tex_packet.len = 8 * sizeof(*tags);
271 ((unsigned long long)psm << 20) + 272 tags[0] = 3 | (1LL << 60); /* GIFtag */
272 ((unsigned long long)power_of_2(width) << 26) + 273 tags[1] = 0x0e; /* A+D */
273 ((unsigned long long)power_of_2(height) << 30) + 274 tags[2] = ((screen_image.y + screen_image.h) * screen_image.w) / 64 +
274 ((unsigned long long)1 << 34) + 275 ((unsigned long long) fbw << 14) +
275 ((unsigned long long)1 << 35); 276 ((unsigned long long) psm << 20) +
276 tags[3] = PS2_GS_TEX0_1; 277 ((unsigned long long) power_of_2(width) << 26) +
277 tags[4] = (1 << 5) + (1 << 6); 278 ((unsigned long long) power_of_2(height) << 30) +
278 tags[5] = PS2_GS_TEX1_1; 279 ((unsigned long long) 1 << 34) + ((unsigned long long) 1 << 35);
279 tags[6] = 0; 280 tags[3] = PS2_GS_TEX0_1;
280 tags[7] = PS2_GS_TEXFLUSH; 281 tags[4] = (1 << 5) + (1 << 6);
281 ioctl(console_fd, PS2IOC_SEND, &tex_packet); 282 tags[5] = PS2_GS_TEX1_1;
282 283 tags[6] = 0;
283 /* Set up the tags for scaling the image */ 284 tags[7] = PS2_GS_TEXFLUSH;
284 packet[pnum].ptr = tags; 285 ioctl(console_fd, PS2IOC_SEND, &tex_packet);
285 packet[pnum].len = 12 * sizeof(*tags); 286
286 ++pnum; 287 /* Set up the tags for scaling the image */
287 tags[0] = 5 | (1LL << 60); /* GIFtag */ 288 packet[pnum].ptr = tags;
288 tags[1] = 0x0e; /* A+D */ 289 packet[pnum].len = 12 * sizeof(*tags);
289 tags[2] = 6 + (1 << 4) + (1 << 8); 290 ++pnum;
290 tags[3] = PS2_GS_PRIM; 291 tags[0] = 5 | (1LL << 60); /* GIFtag */
291 tags[4] = ((unsigned long long)0 * 16) + 292 tags[1] = 0x0e; /* A+D */
292 (((unsigned long long)0 * 16) << 16); 293 tags[2] = 6 + (1 << 4) + (1 << 8);
293 tags[5] = PS2_GS_UV; 294 tags[3] = PS2_GS_PRIM;
294 tags[6] = 0; /* X1, Y1 */ 295 tags[4] = ((unsigned long long) 0 * 16) +
295 tags[7] = PS2_GS_XYZ2; 296 (((unsigned long long) 0 * 16) << 16);
296 hwdata->stretch_x1y1 = &tags[6]; 297 tags[5] = PS2_GS_UV;
297 tags[8] = ((unsigned long long)overlay->w * 16) + 298 tags[6] = 0; /* X1, Y1 */
298 (((unsigned long long)overlay->h * 16) << 16); 299 tags[7] = PS2_GS_XYZ2;
299 tags[9] = PS2_GS_UV; 300 hwdata->stretch_x1y1 = &tags[6];
300 tags[10] = 0; /* X2, Y2 */ 301 tags[8] = ((unsigned long long) overlay->w * 16) +
301 tags[11] = PS2_GS_XYZ2; 302 (((unsigned long long) overlay->h * 16) << 16);
302 hwdata->stretch_x2y2 = &tags[10]; 303 tags[9] = PS2_GS_UV;
303 304 tags[10] = 0; /* X2, Y2 */
304 /* We're all done.. */ 305 tags[11] = PS2_GS_XYZ2;
305 return(overlay); 306 hwdata->stretch_x2y2 = &tags[10];
306 } 307
307 308 /* We're all done.. */
308 int GS_LockYUVOverlay(_THIS, SDL_Overlay *overlay) 309 return (overlay);
309 { 310 }
310 return(0); 311
311 } 312 int
312 313 GS_LockYUVOverlay(_THIS, SDL_Overlay * overlay)
313 void GS_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay) 314 {
314 { 315 return (0);
315 return; 316 }
316 } 317
317 318 void
318 int GS_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst) 319 GS_UnlockYUVOverlay(_THIS, SDL_Overlay * overlay)
319 { 320 {
320 struct private_yuvhwdata *hwdata; 321 return;
321 __u32 cmd; 322 }
322 struct ps2_packet packet; 323
323 int h, w, i; 324 int
324 Uint32 *lum, *Cr, *Cb; 325 GS_DisplayYUVOverlay(_THIS, SDL_Overlay * overlay, SDL_Rect * src,
325 int lum_pitch; 326 SDL_Rect * dst)
326 int crb_pitch; 327 {
327 Uint32 *lum_src, *Cr_src, *Cb_src; 328 struct private_yuvhwdata *hwdata;
328 Uint32 *srcp, *dstp; 329 __u32 cmd;
329 unsigned int x, y; 330 struct ps2_packet packet;
330 SDL_Surface *screen; 331 int h, w, i;
331 332 Uint32 *lum, *Cr, *Cb;
332 /* Find out where the various portions of the image are */ 333 int lum_pitch;
333 hwdata = overlay->hwdata; 334 int crb_pitch;
334 switch (overlay->format) { 335 Uint32 *lum_src, *Cr_src, *Cb_src;
335 case SDL_YV12_OVERLAY: 336 Uint32 *srcp, *dstp;
336 lum = (Uint32 *)overlay->pixels[0]; 337 unsigned int x, y;
337 Cr = (Uint32 *)overlay->pixels[1]; 338 SDL_Surface *screen;
338 Cb = (Uint32 *)overlay->pixels[2]; 339
339 break; 340 /* Find out where the various portions of the image are */
340 case SDL_IYUV_OVERLAY: 341 hwdata = overlay->hwdata;
341 lum = (Uint32 *)overlay->pixels[0]; 342 switch (overlay->format) {
342 Cr = (Uint32 *)overlay->pixels[2]; 343 case SDL_YV12_OVERLAY:
343 Cb = (Uint32 *)overlay->pixels[1]; 344 lum = (Uint32 *) overlay->pixels[0];
344 default: 345 Cr = (Uint32 *) overlay->pixels[1];
345 SDL_SetError("Unsupported YUV format in blit (?)"); 346 Cb = (Uint32 *) overlay->pixels[2];
346 return(-1); 347 break;
347 } 348 case SDL_IYUV_OVERLAY:
348 dstp = (Uint32 *)hwdata->ipu_imem; 349 lum = (Uint32 *) overlay->pixels[0];
349 lum_pitch = overlay->w/4; 350 Cr = (Uint32 *) overlay->pixels[2];
350 crb_pitch = (overlay->w/2)/4; 351 Cb = (Uint32 *) overlay->pixels[1];
351 352 default:
352 /* Copy blocks of 16x16 pixels to the DMA area */ 353 SDL_SetError("Unsupported YUV format in blit (?)");
353 for ( h=overlay->h/16; h; --h ) { 354 return (-1);
354 lum_src = lum; 355 }
355 Cr_src = Cr; 356 dstp = (Uint32 *) hwdata->ipu_imem;
356 Cb_src = Cb; 357 lum_pitch = overlay->w / 4;
357 for ( w=overlay->w/16; w; --w ) { 358 crb_pitch = (overlay->w / 2) / 4;
358 srcp = lum_src; 359
359 for ( i=0; i<16; ++i ) { 360 /* Copy blocks of 16x16 pixels to the DMA area */
360 dstp[0] = srcp[0]; 361 for (h = overlay->h / 16; h; --h) {
361 dstp[1] = srcp[1]; 362 lum_src = lum;
362 dstp[2] = srcp[2]; 363 Cr_src = Cr;
363 dstp[3] = srcp[3]; 364 Cb_src = Cb;
364 srcp += lum_pitch; 365 for (w = overlay->w / 16; w; --w) {
365 dstp += 4; 366 srcp = lum_src;
366 } 367 for (i = 0; i < 16; ++i) {
367 srcp = Cb_src; 368 dstp[0] = srcp[0];
368 for ( i=0; i<8; ++i ) { 369 dstp[1] = srcp[1];
369 dstp[0] = srcp[0]; 370 dstp[2] = srcp[2];
370 dstp[1] = srcp[1]; 371 dstp[3] = srcp[3];
371 srcp += crb_pitch; 372 srcp += lum_pitch;
372 dstp += 2; 373 dstp += 4;
373 } 374 }
374 srcp = Cr_src; 375 srcp = Cb_src;
375 for ( i=0; i<8; ++i ) { 376 for (i = 0; i < 8; ++i) {
376 dstp[0] = srcp[0]; 377 dstp[0] = srcp[0];
377 dstp[1] = srcp[1]; 378 dstp[1] = srcp[1];
378 srcp += crb_pitch; 379 srcp += crb_pitch;
379 dstp += 2; 380 dstp += 2;
380 } 381 }
381 lum_src += 16 / 4; 382 srcp = Cr_src;
382 Cb_src += 8 / 4; 383 for (i = 0; i < 8; ++i) {
383 Cr_src += 8 / 4; 384 dstp[0] = srcp[0];
384 } 385 dstp[1] = srcp[1];
385 lum += lum_pitch * 16; 386 srcp += crb_pitch;
386 Cr += crb_pitch * 8; 387 dstp += 2;
387 Cb += crb_pitch * 8; 388 }
388 } 389 lum_src += 16 / 4;
389 390 Cb_src += 8 / 4;
390 /* Send the macroblock data to the IPU */ 391 Cr_src += 8 / 4;
392 }
393 lum += lum_pitch * 16;
394 Cr += crb_pitch * 8;
395 Cb += crb_pitch * 8;
396 }
397
398 /* Send the macroblock data to the IPU */
391 #ifdef DEBUG_YUV 399 #ifdef DEBUG_YUV
392 fprintf(stderr, "Sending data to IPU..\n"); 400 fprintf(stderr, "Sending data to IPU..\n");
393 #endif 401 #endif
394 packet.ptr = hwdata->ipu_imem; 402 packet.ptr = hwdata->ipu_imem;
395 packet.len = hwdata->macroblocks * (16 * 16 + 8 * 8 + 8 * 8); 403 packet.len = hwdata->macroblocks * (16 * 16 + 8 * 8 + 8 * 8);
396 ioctl(hwdata->ipu_fd, PS2IOC_SENDA, &packet); 404 ioctl(hwdata->ipu_fd, PS2IOC_SENDA, &packet);
397 405
398 /* Trigger the DMA to the IPU for conversion */ 406 /* Trigger the DMA to the IPU for conversion */
399 #ifdef DEBUG_YUV 407 #ifdef DEBUG_YUV
400 fprintf(stderr, "Trigging conversion command\n"); 408 fprintf(stderr, "Trigging conversion command\n");
401 #endif 409 #endif
402 cmd = (7 << 28) + hwdata->macroblocks; 410 cmd = (7 << 28) + hwdata->macroblocks;
403 if ( screen_image.psm == PS2_GS_PSMCT16 ) { 411 if (screen_image.psm == PS2_GS_PSMCT16) {
404 cmd += (1 << 27) + /* Output RGB 555 */ 412 cmd += (1 << 27) + /* Output RGB 555 */
405 (1 << 26); /* Dither output */ 413 (1 << 26); /* Dither output */
406 } 414 }
407 ioctl(hwdata->ipu_fd, PS2IOC_SIPUCMD, &cmd); 415 ioctl(hwdata->ipu_fd, PS2IOC_SIPUCMD, &cmd);
408 416
409 /* Retrieve the converted image from the IPU */ 417 /* Retrieve the converted image from the IPU */
410 #ifdef DEBUG_YUV 418 #ifdef DEBUG_YUV
411 fprintf(stderr, "Retrieving data from IPU..\n"); 419 fprintf(stderr, "Retrieving data from IPU..\n");
412 #endif 420 #endif
413 packet.ptr = hwdata->ipu_omem; 421 packet.ptr = hwdata->ipu_omem;
414 packet.len = overlay->w * overlay->h * 422 packet.len = overlay->w * overlay->h *
415 this->screen->format->BytesPerPixel; 423 this->screen->format->BytesPerPixel;
416 ioctl(hwdata->ipu_fd, PS2IOC_RECV, &packet); 424 ioctl(hwdata->ipu_fd, PS2IOC_RECV, &packet);
417 425
418 #ifdef DEBUG_YUV 426 #ifdef DEBUG_YUV
419 fprintf(stderr, "Copying image to screen..\n"); 427 fprintf(stderr, "Copying image to screen..\n");
420 #endif 428 #endif
421 /* Wait for previous DMA to complete */ 429 /* Wait for previous DMA to complete */
422 ioctl(console_fd, PS2IOC_SENDQCT, 1); 430 ioctl(console_fd, PS2IOC_SENDQCT, 1);
423 431
424 /* Send the current image to the screen and scale it */ 432 /* Send the current image to the screen and scale it */
425 screen = this->screen; 433 screen = this->screen;
426 x = (unsigned int)dst->x; 434 x = (unsigned int) dst->x;
427 y = (unsigned int)dst->y; 435 y = (unsigned int) dst->y;
428 if ( screen->offset ) { 436 if (screen->offset) {
429 x += (screen->offset % screen->pitch) / 437 x += (screen->offset % screen->pitch) / screen->format->BytesPerPixel;
430 screen->format->BytesPerPixel; 438 y += (screen->offset / screen->pitch);
431 y += (screen->offset / screen->pitch); 439 }
432 } 440 y += screen_image.y;
433 y += screen_image.y; 441 *hwdata->stretch_x1y1 = (x * 16) + ((y * 16) << 16);
434 *hwdata->stretch_x1y1 = (x * 16) + ((y * 16) << 16); 442 x += (unsigned int) dst->w;
435 x += (unsigned int)dst->w; 443 y += (unsigned int) dst->h;
436 y += (unsigned int)dst->h; 444 *hwdata->stretch_x2y2 = (x * 16) + ((y * 16) << 16);
437 *hwdata->stretch_x2y2 = (x * 16) + ((y * 16) << 16); 445 return ioctl(console_fd, PS2IOC_SENDL, &hwdata->plist);
438 return ioctl(console_fd, PS2IOC_SENDL, &hwdata->plist); 446 }
439 } 447
440 448 void
441 void GS_FreeYUVOverlay(_THIS, SDL_Overlay *overlay) 449 GS_FreeYUVOverlay(_THIS, SDL_Overlay * overlay)
442 { 450 {
443 struct private_yuvhwdata *hwdata; 451 struct private_yuvhwdata *hwdata;
444 452
445 hwdata = overlay->hwdata; 453 hwdata = overlay->hwdata;
446 if ( hwdata ) { 454 if (hwdata) {
447 if ( hwdata->ipu_fd >= 0 ) { 455 if (hwdata->ipu_fd >= 0) {
448 close(hwdata->ipu_fd); 456 close(hwdata->ipu_fd);
449 } 457 }
450 if ( hwdata->dma_mem ) { 458 if (hwdata->dma_mem) {
451 munmap(hwdata->dma_mem, hwdata->dma_len); 459 munmap(hwdata->dma_mem, hwdata->dma_len);
452 } 460 }
453 if ( hwdata->plist.packet ) { 461 if (hwdata->plist.packet) {
454 SDL_free(hwdata->plist.packet); 462 SDL_free(hwdata->plist.packet);
455 } 463 }
456 if ( hwdata->pixels ) { 464 if (hwdata->pixels) {
457 SDL_free(hwdata->pixels); 465 SDL_free(hwdata->pixels);
458 } 466 }
459 SDL_free(hwdata); 467 SDL_free(hwdata);
460 } 468 }
461 } 469 }
470
471 /* vi: set ts=4 sw=4 expandtab: */