diff options
Diffstat (limited to 'apps/plugins/sdl/src/video/ps2gs/SDL_gsvideo.c')
-rw-r--r-- | apps/plugins/sdl/src/video/ps2gs/SDL_gsvideo.c | 689 |
1 files changed, 689 insertions, 0 deletions
diff --git a/apps/plugins/sdl/src/video/ps2gs/SDL_gsvideo.c b/apps/plugins/sdl/src/video/ps2gs/SDL_gsvideo.c new file mode 100644 index 0000000000..e172c60dc1 --- /dev/null +++ b/apps/plugins/sdl/src/video/ps2gs/SDL_gsvideo.c | |||
@@ -0,0 +1,689 @@ | |||
1 | /* | ||
2 | SDL - Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2012 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 | /* Framebuffer console based SDL video driver implementation. | ||
25 | */ | ||
26 | |||
27 | #include <fcntl.h> | ||
28 | #include <unistd.h> | ||
29 | #include <sys/ioctl.h> | ||
30 | #include <sys/mman.h> | ||
31 | |||
32 | #include "SDL_video.h" | ||
33 | #include "SDL_mouse.h" | ||
34 | #include "../SDL_sysvideo.h" | ||
35 | #include "../SDL_pixels_c.h" | ||
36 | #include "../../events/SDL_events_c.h" | ||
37 | #include "../SDL_cursor_c.h" | ||
38 | #include "SDL_gsvideo.h" | ||
39 | #include "SDL_gsmouse_c.h" | ||
40 | #include "SDL_gsevents_c.h" | ||
41 | #include "SDL_gsyuv_c.h" | ||
42 | |||
43 | |||
44 | /* Initialization/Query functions */ | ||
45 | static int GS_VideoInit(_THIS, SDL_PixelFormat *vformat); | ||
46 | static SDL_Rect **GS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); | ||
47 | static SDL_Surface *GS_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); | ||
48 | static int GS_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); | ||
49 | static void GS_VideoQuit(_THIS); | ||
50 | |||
51 | /* Hardware surface functions */ | ||
52 | static int GS_AllocHWSurface(_THIS, SDL_Surface *surface); | ||
53 | static int GS_LockHWSurface(_THIS, SDL_Surface *surface); | ||
54 | static void GS_UnlockHWSurface(_THIS, SDL_Surface *surface); | ||
55 | static void GS_FreeHWSurface(_THIS, SDL_Surface *surface); | ||
56 | |||
57 | /* GS driver bootstrap functions */ | ||
58 | |||
59 | static int GS_Available(void) | ||
60 | { | ||
61 | int console, memory; | ||
62 | |||
63 | console = open(PS2_DEV_GS, O_RDWR, 0); | ||
64 | if ( console >= 0 ) { | ||
65 | close(console); | ||
66 | } | ||
67 | memory = open(PS2_DEV_MEM, O_RDWR, 0); | ||
68 | if ( memory >= 0 ) { | ||
69 | close(memory); | ||
70 | } | ||
71 | return((console >= 0) && (memory >= 0)); | ||
72 | } | ||
73 | |||
74 | static void GS_DeleteDevice(SDL_VideoDevice *device) | ||
75 | { | ||
76 | SDL_free(device->hidden); | ||
77 | SDL_free(device); | ||
78 | } | ||
79 | |||
80 | static SDL_VideoDevice *GS_CreateDevice(int devindex) | ||
81 | { | ||
82 | SDL_VideoDevice *this; | ||
83 | |||
84 | /* Initialize all variables that we clean on shutdown */ | ||
85 | this = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); | ||
86 | if ( this ) { | ||
87 | SDL_memset(this, 0, (sizeof *this)); | ||
88 | this->hidden = (struct SDL_PrivateVideoData *) | ||
89 | SDL_malloc((sizeof *this->hidden)); | ||
90 | } | ||
91 | if ( (this == NULL) || (this->hidden == NULL) ) { | ||
92 | SDL_OutOfMemory(); | ||
93 | if ( this ) { | ||
94 | SDL_free(this); | ||
95 | } | ||
96 | return(0); | ||
97 | } | ||
98 | SDL_memset(this->hidden, 0, (sizeof *this->hidden)); | ||
99 | mouse_fd = -1; | ||
100 | keyboard_fd = -1; | ||
101 | |||
102 | /* Set the function pointers */ | ||
103 | this->VideoInit = GS_VideoInit; | ||
104 | this->ListModes = GS_ListModes; | ||
105 | this->SetVideoMode = GS_SetVideoMode; | ||
106 | this->CreateYUVOverlay = GS_CreateYUVOverlay; | ||
107 | this->SetColors = GS_SetColors; | ||
108 | this->UpdateRects = NULL; | ||
109 | this->VideoQuit = GS_VideoQuit; | ||
110 | this->AllocHWSurface = GS_AllocHWSurface; | ||
111 | this->CheckHWBlit = NULL; | ||
112 | this->FillHWRect = NULL; | ||
113 | this->SetHWColorKey = NULL; | ||
114 | this->SetHWAlpha = NULL; | ||
115 | this->LockHWSurface = GS_LockHWSurface; | ||
116 | this->UnlockHWSurface = GS_UnlockHWSurface; | ||
117 | this->FlipHWSurface = NULL; | ||
118 | this->FreeHWSurface = GS_FreeHWSurface; | ||
119 | this->SetIcon = NULL; | ||
120 | this->SetCaption = NULL; | ||
121 | this->GetWMInfo = NULL; | ||
122 | this->FreeWMCursor = GS_FreeWMCursor; | ||
123 | this->CreateWMCursor = GS_CreateWMCursor; | ||
124 | this->ShowWMCursor = GS_ShowWMCursor; | ||
125 | this->MoveWMCursor = GS_MoveWMCursor; | ||
126 | this->InitOSKeymap = GS_InitOSKeymap; | ||
127 | this->PumpEvents = GS_PumpEvents; | ||
128 | |||
129 | this->free = GS_DeleteDevice; | ||
130 | |||
131 | return this; | ||
132 | } | ||
133 | |||
134 | VideoBootStrap PS2GS_bootstrap = { | ||
135 | "ps2gs", "PlayStation 2 Graphics Synthesizer", | ||
136 | GS_Available, GS_CreateDevice | ||
137 | }; | ||
138 | |||
139 | /* These are the pixel formats for the 32, 24, and 16 bit video modes */ | ||
140 | static struct { | ||
141 | int bpp; | ||
142 | Uint32 r; | ||
143 | Uint32 g; | ||
144 | Uint32 b; | ||
145 | } GS_pixelmasks[] = { | ||
146 | { 32, 0x000000FF, /* RGB little-endian */ | ||
147 | 0x0000FF00, | ||
148 | 0x00FF0000 }, | ||
149 | { 24, 0x000000FF, /* RGB little-endian */ | ||
150 | 0x0000FF00, | ||
151 | 0x00FF0000 }, | ||
152 | { 16, 0x0000001f, /* RGB little-endian */ | ||
153 | 0x000003e0, | ||
154 | 0x00007c00 }, | ||
155 | }; | ||
156 | /* This is a mapping from SDL bytes-per-pixel to GS pixel format */ | ||
157 | static int GS_formatmap[] = { | ||
158 | -1, /* 0 bpp, not a legal value */ | ||
159 | -1, /* 8 bpp, not supported (yet?) */ | ||
160 | PS2_GS_PSMCT16, /* 16 bpp */ | ||
161 | PS2_GS_PSMCT24, /* 24 bpp */ | ||
162 | PS2_GS_PSMCT32 /* 32 bpp */ | ||
163 | }; | ||
164 | |||
165 | static unsigned long long head_tags[] __attribute__((aligned(16))) = { | ||
166 | 4 | (1LL << 60), /* GIFtag */ | ||
167 | 0x0e, /* A+D */ | ||
168 | 0, /* 2 */ | ||
169 | PS2_GS_BITBLTBUF, | ||
170 | 0, /* 4 */ | ||
171 | PS2_GS_TRXPOS, | ||
172 | 0, /* 6 */ | ||
173 | PS2_GS_TRXREG, | ||
174 | 0, /* 8 */ | ||
175 | PS2_GS_TRXDIR | ||
176 | }; | ||
177 | |||
178 | #define MAXIMG (32767 * 16) | ||
179 | #define MAXTAGS 8 | ||
180 | |||
181 | static inline int loadimage_nonblock(int fd, struct ps2_image *image, int size, | ||
182 | unsigned long long *hm, | ||
183 | unsigned long long *im) | ||
184 | { | ||
185 | struct ps2_plist plist; | ||
186 | struct ps2_packet packet[1 + MAXTAGS * 2]; | ||
187 | int isize; | ||
188 | int pnum, it, eop; | ||
189 | char *data; | ||
190 | |||
191 | /* initialize the variables */ | ||
192 | data = (char *)image->ptr; | ||
193 | pnum = it = eop = 0; | ||
194 | plist.packet = packet; | ||
195 | |||
196 | /* make BITBLT packet */ | ||
197 | packet[pnum].ptr = hm; | ||
198 | packet[pnum].len = sizeof(head_tags); | ||
199 | pnum++; | ||
200 | hm[2] = ((unsigned long long)image->fbp << 32) | | ||
201 | ((unsigned long long)image->fbw << 48) | | ||
202 | ((unsigned long long)image->psm << 56); | ||
203 | hm[4] = ((unsigned long long)image->x << 32) | | ||
204 | ((unsigned long long)image->y << 48); | ||
205 | hm[6] = (unsigned long long)image->w | | ||
206 | ((unsigned long long)image->h << 32); | ||
207 | |||
208 | /* make image mode tags */ | ||
209 | while (!eop) { | ||
210 | isize = size > MAXIMG ? MAXIMG : size; | ||
211 | size -= isize; | ||
212 | eop = (size == 0); | ||
213 | |||
214 | packet[pnum].ptr = &im[it]; | ||
215 | packet[pnum].len = sizeof(unsigned long long) * 2; | ||
216 | pnum++; | ||
217 | im[it++] = (isize >> 4) | (eop ? (1 << 15) : 0) | (2LL << 58); | ||
218 | im[it++] = 0; | ||
219 | |||
220 | packet[pnum].ptr = (void *)data; | ||
221 | packet[pnum].len = isize; | ||
222 | pnum++; | ||
223 | data += isize; | ||
224 | } | ||
225 | plist.num = pnum; | ||
226 | |||
227 | return ioctl(fd, PS2IOC_SENDL, &plist); | ||
228 | } | ||
229 | |||
230 | static unsigned long long tex_tags[] __attribute__((aligned(16))) = { | ||
231 | 3 | (1LL << 60), /* GIFtag */ | ||
232 | 0x0e, /* A+D */ | ||
233 | 0, /* 2 */ | ||
234 | PS2_GS_TEX0_1, | ||
235 | (1 << 5) + (1 << 6), | ||
236 | PS2_GS_TEX1_1, | ||
237 | 0, | ||
238 | PS2_GS_TEXFLUSH | ||
239 | }; | ||
240 | static unsigned long long scale_tags[] __attribute__((aligned(16))) = { | ||
241 | 5 | (1LL << 60), /* GIFtag */ | ||
242 | 0x0e, /* A+D */ | ||
243 | 6 + (1 << 4) + (1 << 8), | ||
244 | PS2_GS_PRIM, | ||
245 | ((unsigned long long)0 * 16) + (((unsigned long long)0 * 16) << 16), | ||
246 | PS2_GS_UV, | ||
247 | ((unsigned long long)0 * 16) + (((unsigned long long)0 * 16) << 16), | ||
248 | PS2_GS_XYZ2, | ||
249 | 0, /* 8 */ | ||
250 | PS2_GS_UV, | ||
251 | 0, /* 10 */ | ||
252 | PS2_GS_XYZ2 | ||
253 | }; | ||
254 | |||
255 | |||
256 | int scaleimage_nonblock(int fd, unsigned long long *tm, unsigned long long *sm) | ||
257 | { | ||
258 | struct ps2_plist plist; | ||
259 | struct ps2_packet packet[2]; | ||
260 | |||
261 | /* initialize the variables */ | ||
262 | plist.num = 2; | ||
263 | plist.packet = packet; | ||
264 | |||
265 | packet[0].ptr = tm; | ||
266 | packet[0].len = sizeof(tex_tags); | ||
267 | packet[1].ptr = sm; | ||
268 | packet[1].len = sizeof(scale_tags); | ||
269 | |||
270 | return ioctl(fd, PS2IOC_SENDL, &plist); | ||
271 | } | ||
272 | |||
273 | static int power_of_2(int value) | ||
274 | { | ||
275 | int shift; | ||
276 | |||
277 | for ( shift = 0; (1<<shift) < value; ++shift ) { | ||
278 | /* Keep looking */ ; | ||
279 | } | ||
280 | return(shift); | ||
281 | } | ||
282 | |||
283 | static int GS_VideoInit(_THIS, SDL_PixelFormat *vformat) | ||
284 | { | ||
285 | struct ps2_screeninfo vinfo; | ||
286 | |||
287 | /* Initialize the library */ | ||
288 | console_fd = open(PS2_DEV_GS, O_RDWR, 0); | ||
289 | if ( console_fd < 0 ) { | ||
290 | SDL_SetError("Unable to open %s", PS2_DEV_GS); | ||
291 | return(-1); | ||
292 | } | ||
293 | memory_fd = open(PS2_DEV_MEM, O_RDWR, 0); | ||
294 | if ( memory_fd < 0 ) { | ||
295 | close(console_fd); | ||
296 | console_fd = -1; | ||
297 | SDL_SetError("Unable to open %s", PS2_DEV_MEM); | ||
298 | return(-1); | ||
299 | } | ||
300 | |||
301 | if ( ioctl(console_fd, PS2IOC_GSCREENINFO, &vinfo) < 0 ) { | ||
302 | close(memory_fd); | ||
303 | close(console_fd); | ||
304 | console_fd = -1; | ||
305 | SDL_SetError("Couldn't get console pixel format"); | ||
306 | return(-1); | ||
307 | } | ||
308 | |||
309 | /* Determine the current screen size */ | ||
310 | this->info.current_w = vinfo.w; | ||
311 | this->info.current_h = vinfo.h; | ||
312 | |||
313 | /* Determine the current screen depth */ | ||
314 | switch (vinfo.psm) { | ||
315 | /* Supported pixel formats */ | ||
316 | case PS2_GS_PSMCT32: | ||
317 | case PS2_GS_PSMCT24: | ||
318 | case PS2_GS_PSMCT16: | ||
319 | break; | ||
320 | default: | ||
321 | GS_VideoQuit(this); | ||
322 | SDL_SetError("Unknown console pixel format: %d", vinfo.psm); | ||
323 | return(-1); | ||
324 | } | ||
325 | vformat->BitsPerPixel = GS_pixelmasks[vinfo.psm].bpp; | ||
326 | vformat->Rmask = GS_pixelmasks[vinfo.psm].r; | ||
327 | vformat->Gmask = GS_pixelmasks[vinfo.psm].g; | ||
328 | vformat->Bmask = GS_pixelmasks[vinfo.psm].b; | ||
329 | saved_vinfo = vinfo; | ||
330 | |||
331 | /* Enable mouse and keyboard support */ | ||
332 | if ( GS_OpenKeyboard(this) < 0 ) { | ||
333 | GS_VideoQuit(this); | ||
334 | SDL_SetError("Unable to open keyboard"); | ||
335 | return(-1); | ||
336 | } | ||
337 | if ( GS_OpenMouse(this) < 0 ) { | ||
338 | const char *sdl_nomouse; | ||
339 | |||
340 | sdl_nomouse = SDL_getenv("SDL_NOMOUSE"); | ||
341 | if ( ! sdl_nomouse ) { | ||
342 | GS_VideoQuit(this); | ||
343 | SDL_SetError("Unable to open mouse"); | ||
344 | return(-1); | ||
345 | } | ||
346 | } | ||
347 | |||
348 | /* We're done! */ | ||
349 | return(0); | ||
350 | } | ||
351 | |||
352 | static SDL_Rect **GS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) | ||
353 | { | ||
354 | static SDL_Rect GS_vesa_mode_list[] = { | ||
355 | { 0, 0, 1280, 1024 }, | ||
356 | { 0, 0, 1024, 768 }, | ||
357 | { 0, 0, 800, 600 }, | ||
358 | { 0, 0, 640, 480 } | ||
359 | }; | ||
360 | static SDL_Rect *GS_vesa_modes[] = { | ||
361 | &GS_vesa_mode_list[0], | ||
362 | &GS_vesa_mode_list[1], | ||
363 | &GS_vesa_mode_list[2], | ||
364 | &GS_vesa_mode_list[3], | ||
365 | NULL | ||
366 | }; | ||
367 | static SDL_Rect GS_tvout_stretch; | ||
368 | static SDL_Rect GS_tvout_mode; | ||
369 | static SDL_Rect *GS_tvout_modes[3]; | ||
370 | SDL_Rect **modes = NULL; | ||
371 | |||
372 | switch (format->BitsPerPixel) { | ||
373 | case 16: | ||
374 | case 24: | ||
375 | case 32: | ||
376 | if ( saved_vinfo.mode == PS2_GS_VESA ) { | ||
377 | modes = GS_vesa_modes; | ||
378 | } else { | ||
379 | int i, j = 0; | ||
380 | |||
381 | // FIXME - what's wrong with the stretch code at 16 bpp? | ||
382 | if ( format->BitsPerPixel != 32 ) break; | ||
383 | /* Add a mode that we could possibly stretch to */ | ||
384 | for ( i=0; GS_vesa_modes[i]; ++i ) { | ||
385 | if ( (GS_vesa_modes[i]->w == saved_vinfo.w) && | ||
386 | (GS_vesa_modes[i]->h != saved_vinfo.h) ) { | ||
387 | GS_tvout_stretch.w=GS_vesa_modes[i]->w; | ||
388 | GS_tvout_stretch.h=GS_vesa_modes[i]->h; | ||
389 | GS_tvout_modes[j++] = &GS_tvout_stretch; | ||
390 | break; | ||
391 | } | ||
392 | } | ||
393 | /* Add the current TV video mode */ | ||
394 | GS_tvout_mode.w = saved_vinfo.w; | ||
395 | GS_tvout_mode.h = saved_vinfo.h; | ||
396 | GS_tvout_modes[j++] = &GS_tvout_mode; | ||
397 | GS_tvout_modes[j++] = NULL; | ||
398 | |||
399 | /* Return the created list of modes */ | ||
400 | modes = GS_tvout_modes; | ||
401 | } | ||
402 | break; | ||
403 | default: | ||
404 | break; | ||
405 | } | ||
406 | return(modes); | ||
407 | } | ||
408 | |||
409 | /* Various screen update functions available */ | ||
410 | static void GS_DMAFullUpdate(_THIS, int numrects, SDL_Rect *rects); | ||
411 | |||
412 | static SDL_Surface *GS_SetVideoMode(_THIS, SDL_Surface *current, | ||
413 | int width, int height, int bpp, Uint32 flags) | ||
414 | { | ||
415 | struct ps2_screeninfo vinfo; | ||
416 | |||
417 | /* Set the terminal into graphics mode */ | ||
418 | if ( GS_EnterGraphicsMode(this) < 0 ) { | ||
419 | return(NULL); | ||
420 | } | ||
421 | |||
422 | /* Set the video mode and get the final screen format */ | ||
423 | if ( ioctl(console_fd, PS2IOC_GSCREENINFO, &vinfo) < 0 ) { | ||
424 | SDL_SetError("Couldn't get console screen info"); | ||
425 | return(NULL); | ||
426 | } | ||
427 | if ( (vinfo.w != width) || (vinfo.h != height) || | ||
428 | (GS_pixelmasks[vinfo.psm].bpp != bpp) ) { | ||
429 | /* If we're not in VESA mode, we have to scale resolution */ | ||
430 | if ( saved_vinfo.mode == PS2_GS_VESA ) { | ||
431 | switch (width) { | ||
432 | case 640: | ||
433 | vinfo.res = PS2_GS_640x480; | ||
434 | break; | ||
435 | case 800: | ||
436 | vinfo.res = PS2_GS_800x600; | ||
437 | break; | ||
438 | case 1024: | ||
439 | vinfo.res = PS2_GS_1024x768; | ||
440 | break; | ||
441 | case 1280: | ||
442 | vinfo.res = PS2_GS_1280x1024; | ||
443 | break; | ||
444 | default: | ||
445 | SDL_SetError("Unsupported resolution: %dx%d\n", | ||
446 | width, height); | ||
447 | return(NULL); | ||
448 | } | ||
449 | vinfo.res |= (PS2_GS_75Hz << 8); | ||
450 | vinfo.w = width; | ||
451 | vinfo.h = height; | ||
452 | } | ||
453 | vinfo.fbp = 0; | ||
454 | vinfo.psm = GS_formatmap[bpp/8]; | ||
455 | if ( vinfo.psm < 0 ) { | ||
456 | SDL_SetError("Unsupported depth: %d bpp\n", bpp); | ||
457 | return(NULL); | ||
458 | } | ||
459 | if ( ioctl(console_fd, PS2IOC_SSCREENINFO, &vinfo) < 0 ) { | ||
460 | SDL_SetError("Couldn't set console screen info"); | ||
461 | return(NULL); | ||
462 | } | ||
463 | |||
464 | /* Unmap the previous DMA buffer */ | ||
465 | if ( mapped_mem ) { | ||
466 | munmap(mapped_mem, mapped_len); | ||
467 | mapped_mem = NULL; | ||
468 | } | ||
469 | } | ||
470 | if ( ! SDL_ReallocFormat(current, GS_pixelmasks[vinfo.psm].bpp, | ||
471 | GS_pixelmasks[vinfo.psm].r, | ||
472 | GS_pixelmasks[vinfo.psm].g, | ||
473 | GS_pixelmasks[vinfo.psm].b, 0) ) { | ||
474 | return(NULL); | ||
475 | } | ||
476 | |||
477 | /* Set up the new mode framebuffer */ | ||
478 | current->flags = SDL_FULLSCREEN; | ||
479 | current->w = width; | ||
480 | current->h = height; | ||
481 | current->pitch = SDL_CalculatePitch(current); | ||
482 | |||
483 | /* Memory map the DMA area for block memory transfer */ | ||
484 | if ( ! mapped_mem ) { | ||
485 | pixels_len = height * current->pitch; | ||
486 | mapped_len = pixels_len + | ||
487 | /* Screen update DMA command area */ | ||
488 | sizeof(head_tags) + ((2 * MAXTAGS) * 16); | ||
489 | if ( saved_vinfo.mode != PS2_GS_VESA ) { | ||
490 | mapped_len += sizeof(tex_tags) + sizeof(scale_tags); | ||
491 | } | ||
492 | mapped_mem = mmap(0, mapped_len, PROT_READ|PROT_WRITE, | ||
493 | MAP_SHARED, memory_fd, 0); | ||
494 | if ( mapped_mem == MAP_FAILED ) { | ||
495 | SDL_SetError("Unable to map %d bytes for DMA", | ||
496 | mapped_len); | ||
497 | mapped_mem = NULL; | ||
498 | return(NULL); | ||
499 | } | ||
500 | |||
501 | /* Set up the entire screen for DMA transfer */ | ||
502 | screen_image.ptr = mapped_mem; | ||
503 | screen_image.fbp = 0; | ||
504 | screen_image.fbw = (vinfo.w + 63) / 64; | ||
505 | screen_image.psm = vinfo.psm; | ||
506 | screen_image.x = 0; | ||
507 | if ( vinfo.h == height ) { | ||
508 | screen_image.y = 0; | ||
509 | } else { | ||
510 | /* Put image offscreen and scale to screen height */ | ||
511 | screen_image.y = vinfo.h; | ||
512 | } | ||
513 | screen_image.w = current->w; | ||
514 | screen_image.h = current->h; | ||
515 | |||
516 | /* get screen image data size (qword aligned) */ | ||
517 | screen_image_size = (screen_image.w * screen_image.h); | ||
518 | switch (screen_image.psm) { | ||
519 | case PS2_GS_PSMCT32: | ||
520 | screen_image_size *= 4; | ||
521 | break; | ||
522 | case PS2_GS_PSMCT24: | ||
523 | screen_image_size *= 3; | ||
524 | break; | ||
525 | case PS2_GS_PSMCT16: | ||
526 | screen_image_size *= 2; | ||
527 | break; | ||
528 | } | ||
529 | screen_image_size = (screen_image_size + 15) & ~15; | ||
530 | |||
531 | /* Set up the memory for screen update DMA commands */ | ||
532 | head_tags_mem = (unsigned long long *) | ||
533 | (mapped_mem + pixels_len); | ||
534 | image_tags_mem = (unsigned long long *) | ||
535 | ((caddr_t)head_tags_mem + sizeof(head_tags)); | ||
536 | SDL_memcpy(head_tags_mem, head_tags, sizeof(head_tags)); | ||
537 | if ( saved_vinfo.mode != PS2_GS_VESA ) { | ||
538 | tex_tags_mem = (unsigned long long *) | ||
539 | ((caddr_t)image_tags_mem + ((2*MAXTAGS)*16)); | ||
540 | scale_tags_mem = (unsigned long long *) | ||
541 | ((caddr_t)tex_tags_mem + sizeof(tex_tags)); | ||
542 | SDL_memcpy(tex_tags_mem, tex_tags, sizeof(tex_tags)); | ||
543 | tex_tags_mem[2] = | ||
544 | (vinfo.h * vinfo.w) / 64 + | ||
545 | ((unsigned long long)screen_image.fbw << 14) + | ||
546 | ((unsigned long long)screen_image.psm << 20) + | ||
547 | ((unsigned long long)power_of_2(screen_image.w) << 26) + | ||
548 | ((unsigned long long)power_of_2(screen_image.h) << 30) + | ||
549 | ((unsigned long long)1 << 34) + | ||
550 | ((unsigned long long)1 << 35); | ||
551 | SDL_memcpy(scale_tags_mem, scale_tags, sizeof(scale_tags)); | ||
552 | scale_tags_mem[8] = | ||
553 | ((unsigned long long)screen_image.w * 16) + | ||
554 | (((unsigned long long)screen_image.h * 16) << 16); | ||
555 | scale_tags_mem[10] = | ||
556 | ((unsigned long long)vinfo.w * 16) + | ||
557 | (((unsigned long long)vinfo.h * 16) << 16); | ||
558 | } | ||
559 | } | ||
560 | current->pixels = NULL; | ||
561 | if ( SDL_getenv("SDL_FULLSCREEN_UPDATE") ) { | ||
562 | /* Correct semantics */ | ||
563 | current->flags |= SDL_ASYNCBLIT; | ||
564 | } else { | ||
565 | /* We lie here - the screen memory isn't really the visible | ||
566 | display memory and still requires an update, but this | ||
567 | has the desired effect for most applications. | ||
568 | */ | ||
569 | current->flags |= SDL_HWSURFACE; | ||
570 | } | ||
571 | |||
572 | /* Set the update rectangle function */ | ||
573 | this->UpdateRects = GS_DMAFullUpdate; | ||
574 | |||
575 | /* We're done */ | ||
576 | return(current); | ||
577 | } | ||
578 | |||
579 | /* We don't support hardware surfaces yet */ | ||
580 | static int GS_AllocHWSurface(_THIS, SDL_Surface *surface) | ||
581 | { | ||
582 | return(-1); | ||
583 | } | ||
584 | static void GS_FreeHWSurface(_THIS, SDL_Surface *surface) | ||
585 | { | ||
586 | return; | ||
587 | } | ||
588 | static int GS_LockHWSurface(_THIS, SDL_Surface *surface) | ||
589 | { | ||
590 | if ( surface == this->screen ) { | ||
591 | /* Since mouse motion affects 'pixels', lock it */ | ||
592 | SDL_LockCursor(); | ||
593 | |||
594 | /* Make sure any pending DMA has completed */ | ||
595 | if ( dma_pending ) { | ||
596 | ioctl(console_fd, PS2IOC_SENDQCT, 1); | ||
597 | dma_pending = 0; | ||
598 | } | ||
599 | |||
600 | /* If the cursor is drawn on the DMA area, remove it */ | ||
601 | if ( cursor_drawn ) { | ||
602 | surface->pixels = mapped_mem + surface->offset; | ||
603 | SDL_EraseCursorNoLock(this->screen); | ||
604 | cursor_drawn = 0; | ||
605 | } | ||
606 | |||
607 | /* Set the surface pixels to the base of the DMA area */ | ||
608 | surface->pixels = mapped_mem; | ||
609 | |||
610 | /* We're finished! */ | ||
611 | SDL_UnlockCursor(); | ||
612 | } | ||
613 | return(0); | ||
614 | } | ||
615 | static void GS_UnlockHWSurface(_THIS, SDL_Surface *surface) | ||
616 | { | ||
617 | if ( surface == this->screen ) { | ||
618 | /* Since mouse motion affects 'pixels', lock it */ | ||
619 | SDL_LockCursor(); | ||
620 | surface->pixels = NULL; | ||
621 | SDL_UnlockCursor(); | ||
622 | } | ||
623 | } | ||
624 | |||
625 | static void GS_DMAFullUpdate(_THIS, int numrects, SDL_Rect *rects) | ||
626 | { | ||
627 | /* Lock so we aren't interrupted by a mouse update */ | ||
628 | SDL_LockCursor(); | ||
629 | |||
630 | /* Make sure any pending DMA has completed */ | ||
631 | if ( dma_pending ) { | ||
632 | ioctl(console_fd, PS2IOC_SENDQCT, 1); | ||
633 | dma_pending = 0; | ||
634 | } | ||
635 | |||
636 | /* If the mouse is visible, draw it on the DMA area */ | ||
637 | if ( (SDL_cursorstate & CURSOR_VISIBLE) && !cursor_drawn ) { | ||
638 | this->screen->pixels = mapped_mem + this->screen->offset; | ||
639 | SDL_DrawCursorNoLock(this->screen); | ||
640 | this->screen->pixels = NULL; | ||
641 | cursor_drawn = 1; | ||
642 | } | ||
643 | |||
644 | /* Put the image onto the screen */ | ||
645 | loadimage_nonblock(console_fd, | ||
646 | &screen_image, screen_image_size, | ||
647 | head_tags_mem, image_tags_mem); | ||
648 | if ( screen_image.y > 0 ) { | ||
649 | /* Need to scale offscreen image to TV output */ | ||
650 | ioctl(console_fd, PS2IOC_SENDQCT, 1); | ||
651 | dma_pending = 0; | ||
652 | scaleimage_nonblock(console_fd, tex_tags_mem, scale_tags_mem); | ||
653 | } else { | ||
654 | dma_pending = 1; | ||
655 | } | ||
656 | |||
657 | /* We're finished! */ | ||
658 | SDL_UnlockCursor(); | ||
659 | } | ||
660 | |||
661 | static int GS_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) | ||
662 | { | ||
663 | return(0); | ||
664 | } | ||
665 | |||
666 | static void GS_VideoQuit(_THIS) | ||
667 | { | ||
668 | /* Close console and input file descriptors */ | ||
669 | if ( console_fd > 0 ) { | ||
670 | /* Unmap the video framebuffer */ | ||
671 | if ( mapped_mem ) { | ||
672 | /* Unmap the video framebuffer */ | ||
673 | munmap(mapped_mem, mapped_len); | ||
674 | mapped_mem = NULL; | ||
675 | } | ||
676 | close(memory_fd); | ||
677 | |||
678 | /* Restore the original video mode */ | ||
679 | if ( GS_InGraphicsMode(this) ) { | ||
680 | ioctl(console_fd, PS2IOC_SSCREENINFO, &saved_vinfo); | ||
681 | } | ||
682 | |||
683 | /* We're all done with the graphics device */ | ||
684 | close(console_fd); | ||
685 | console_fd = -1; | ||
686 | } | ||
687 | GS_CloseMouse(this); | ||
688 | GS_CloseKeyboard(this); | ||
689 | } | ||