comparison src/video/ps2gs/SDL_gsvideo.c @ 136:717f739d6ec1

Added hardware stretching code to scale 640x480 to TV resolution There's a bug of some kind in the 16bpp code. ??
author Sam Lantinga <slouken@libsdl.org>
date Wed, 01 Aug 2001 08:41:45 +0000
parents 0bfcf0d2b874
children e8157fcb3114
comparison
equal deleted inserted replaced
135:0bfcf0d2b874 136:717f739d6ec1
233 plist.num = pnum; 233 plist.num = pnum;
234 234
235 return ioctl(fd, PS2IOC_SENDL, &plist); 235 return ioctl(fd, PS2IOC_SENDL, &plist);
236 } 236 }
237 237
238 static unsigned long long tex_tags[] __attribute__((aligned(16))) = {
239 3 | (1LL << 60), /* GIFtag */
240 0x0e, /* A+D */
241 0, /* 2 */
242 PS2_GS_TEX0_1,
243 (1 << 5) + (1 << 6),
244 PS2_GS_TEX1_1,
245 0,
246 PS2_GS_TEXFLUSH
247 };
248 static unsigned long long scale_tags[] __attribute__((aligned(16))) = {
249 5 | (1LL << 60), /* GIFtag */
250 0x0e, /* A+D */
251 6 + (1 << 4) + (1 << 8),
252 PS2_GS_PRIM,
253 ((unsigned long long)0 * 16) + (((unsigned long long)0 * 16) << 16),
254 PS2_GS_UV,
255 ((unsigned long long)0 * 16) + (((unsigned long long)0 * 16) << 16),
256 PS2_GS_XYZ2,
257 0, /* 8 */
258 PS2_GS_UV,
259 0, /* 10 */
260 PS2_GS_XYZ2
261 };
262
263
264 int scaleimage_nonblock(int fd, unsigned long long *tm, unsigned long long *sm)
265 {
266 struct ps2_plist plist;
267 struct ps2_packet packet[2];
268
269 /* initialize the variables */
270 plist.num = 2;
271 plist.packet = packet;
272
273 packet[0].ptr = tm;
274 packet[0].len = sizeof(tex_tags);
275 packet[1].ptr = sm;
276 packet[1].len = sizeof(scale_tags);
277
278 return ioctl(fd, PS2IOC_SENDL, &plist);
279 }
280
281 static int power_of_2(int value)
282 {
283 int shift;
284
285 for ( shift = 0; (1<<shift) < value; ++shift ) {
286 /* Keep looking */ ;
287 }
288 return(shift);
289 }
290
238 static int GS_VideoInit(_THIS, SDL_PixelFormat *vformat) 291 static int GS_VideoInit(_THIS, SDL_PixelFormat *vformat)
239 { 292 {
240 struct ps2_screeninfo vinfo; 293 struct ps2_screeninfo vinfo;
241 294
242 /* Initialize the library */ 295 /* Initialize the library */
259 close(console_fd); 312 close(console_fd);
260 console_fd = -1; 313 console_fd = -1;
261 SDL_SetError("Couldn't get console pixel format"); 314 SDL_SetError("Couldn't get console pixel format");
262 return(-1); 315 return(-1);
263 } 316 }
264 #if 0
265 if ( vinfo.mode != PS2_GS_VESA ) {
266 GS_VideoQuit(this);
267 SDL_SetError("Console must be in VESA video mode");
268 return(-1);
269 }
270 #endif
271 switch (vinfo.psm) { 317 switch (vinfo.psm) {
272 /* Supported pixel formats */ 318 /* Supported pixel formats */
273 case PS2_GS_PSMCT32: 319 case PS2_GS_PSMCT32:
274 case PS2_GS_PSMCT24: 320 case PS2_GS_PSMCT24:
275 case PS2_GS_PSMCT16: 321 case PS2_GS_PSMCT16:
306 return(0); 352 return(0);
307 } 353 }
308 354
309 static SDL_Rect **GS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) 355 static SDL_Rect **GS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
310 { 356 {
311 static SDL_Rect GS_tvout_mode;
312 static SDL_Rect *GS_tvout_modes[] = {
313 &GS_tvout_mode,
314 NULL
315 };
316 static SDL_Rect GS_vesa_mode_list[] = { 357 static SDL_Rect GS_vesa_mode_list[] = {
317 { 0, 0, 1280, 1024 }, 358 { 0, 0, 1280, 1024 },
318 { 0, 0, 1024, 768 }, 359 { 0, 0, 1024, 768 },
319 { 0, 0, 800, 600 }, 360 { 0, 0, 800, 600 },
320 { 0, 0, 640, 480 } 361 { 0, 0, 640, 480 }
324 &GS_vesa_mode_list[1], 365 &GS_vesa_mode_list[1],
325 &GS_vesa_mode_list[2], 366 &GS_vesa_mode_list[2],
326 &GS_vesa_mode_list[3], 367 &GS_vesa_mode_list[3],
327 NULL 368 NULL
328 }; 369 };
370 static SDL_Rect GS_tvout_stretch;
371 static SDL_Rect GS_tvout_mode;
372 static SDL_Rect *GS_tvout_modes[3];
329 SDL_Rect **modes = NULL; 373 SDL_Rect **modes = NULL;
330 374
331 if ( saved_vinfo.mode == PS2_GS_VESA ) { 375 switch (format->BitsPerPixel) {
332 switch (format->BitsPerPixel) { 376 case 16:
333 case 16: 377 case 24:
334 case 24: 378 case 32:
335 case 32: 379 if ( saved_vinfo.mode == PS2_GS_VESA ) {
336 modes = GS_vesa_modes; 380 modes = GS_vesa_modes;
337 break; 381 } else {
338 default: 382 int i, j = 0;
339 break; 383
340 } 384 // FIXME - what's wrong with the stretch code at 16 bpp?
341 } else { 385 if ( format->BitsPerPixel != 32 ) break;
342 if ( GS_formatmap[format->BitsPerPixel/8] == saved_vinfo.psm ) { 386 /* Add a mode that we could possibly stretch to */
387 for ( i=0; GS_vesa_modes[i]; ++i ) {
388 if ( (GS_vesa_modes[i]->w == saved_vinfo.w) &&
389 (GS_vesa_modes[i]->h != saved_vinfo.h) ) {
390 GS_tvout_stretch.w=GS_vesa_modes[i]->w;
391 GS_tvout_stretch.h=GS_vesa_modes[i]->h;
392 GS_tvout_modes[j++] = &GS_tvout_stretch;
393 break;
394 }
395 }
396 /* Add the current TV video mode */
343 GS_tvout_mode.w = saved_vinfo.w; 397 GS_tvout_mode.w = saved_vinfo.w;
344 GS_tvout_mode.h = saved_vinfo.h; 398 GS_tvout_mode.h = saved_vinfo.h;
399 GS_tvout_modes[j++] = &GS_tvout_mode;
400 GS_tvout_modes[j++] = NULL;
401
402 /* Return the created list of modes */
345 modes = GS_tvout_modes; 403 modes = GS_tvout_modes;
346 } 404 }
405 break;
406 default:
407 break;
347 } 408 }
348 return(modes); 409 return(modes);
349 } 410 }
350 411
351 /* Various screen update functions available */ 412 /* Various screen update functions available */
366 SDL_SetError("Couldn't get console screen info"); 427 SDL_SetError("Couldn't get console screen info");
367 return(NULL); 428 return(NULL);
368 } 429 }
369 if ( (vinfo.w != width) || (vinfo.h != height) || 430 if ( (vinfo.w != width) || (vinfo.h != height) ||
370 (GS_pixelmasks[vinfo.psm].bpp != bpp) ) { 431 (GS_pixelmasks[vinfo.psm].bpp != bpp) ) {
371 switch (width) { 432 /* If we're not in VESA mode, we have to scale resolution */
372 case 640: 433 if ( saved_vinfo.mode == PS2_GS_VESA ) {
373 vinfo.res = PS2_GS_640x480; 434 switch (width) {
374 break; 435 case 640:
375 case 800: 436 vinfo.res = PS2_GS_640x480;
376 vinfo.res = PS2_GS_800x600; 437 break;
377 break; 438 case 800:
378 case 1024: 439 vinfo.res = PS2_GS_800x600;
379 vinfo.res = PS2_GS_1024x768; 440 break;
380 break; 441 case 1024:
381 case 1280: 442 vinfo.res = PS2_GS_1024x768;
382 vinfo.res = PS2_GS_1280x1024; 443 break;
383 break; 444 case 1280:
384 default: 445 vinfo.res = PS2_GS_1280x1024;
385 SDL_SetError("Unsupported resolution: %dx%d\n", 446 break;
386 width, height); 447 default:
387 return(NULL); 448 SDL_SetError("Unsupported resolution: %dx%d\n",
388 } 449 width, height);
389 vinfo.res |= (PS2_GS_75Hz << 8); 450 return(NULL);
390 vinfo.w = width; 451 }
391 vinfo.h = height; 452 vinfo.res |= (PS2_GS_75Hz << 8);
453 vinfo.w = width;
454 vinfo.h = height;
455 }
392 vinfo.fbp = 0; 456 vinfo.fbp = 0;
393 vinfo.psm = GS_formatmap[bpp/8]; 457 vinfo.psm = GS_formatmap[bpp/8];
394 if ( vinfo.psm < 0 ) { 458 if ( vinfo.psm < 0 ) {
395 SDL_SetError("Unsupported depth: %d bpp\n", bpp); 459 SDL_SetError("Unsupported depth: %d bpp\n", bpp);
396 return(NULL); 460 return(NULL);
413 return(NULL); 477 return(NULL);
414 } 478 }
415 479
416 /* Set up the new mode framebuffer */ 480 /* Set up the new mode framebuffer */
417 current->flags = SDL_FULLSCREEN; 481 current->flags = SDL_FULLSCREEN;
418 current->w = vinfo.w; 482 current->w = width;
419 current->h = vinfo.h; 483 current->h = height;
420 current->pitch = SDL_CalculatePitch(current); 484 current->pitch = SDL_CalculatePitch(current);
421 485
422 /* Memory map the DMA area for block memory transfer */ 486 /* Memory map the DMA area for block memory transfer */
423 if ( ! mapped_mem ) { 487 if ( ! mapped_mem ) {
424 pixels_len = height * current->pitch; 488 pixels_len = height * current->pitch;
425 mapped_len = pixels_len + 489 mapped_len = pixels_len +
426 /* Screen update DMA command area */ 490 /* Screen update DMA command area */
427 sizeof(head_tags) + ((2 * MAXTAGS) * 16); 491 sizeof(head_tags) + ((2 * MAXTAGS) * 16);
492 if ( saved_vinfo.mode != PS2_GS_VESA ) {
493 mapped_len += sizeof(tex_tags) + sizeof(scale_tags);
494 }
428 mapped_mem = mmap(0, mapped_len, PROT_READ|PROT_WRITE, 495 mapped_mem = mmap(0, mapped_len, PROT_READ|PROT_WRITE,
429 MAP_SHARED, memory_fd, 0); 496 MAP_SHARED, memory_fd, 0);
430 if ( mapped_mem == MAP_FAILED ) { 497 if ( mapped_mem == MAP_FAILED ) {
431 SDL_SetError("Unable to map %d bytes for DMA", 498 SDL_SetError("Unable to map %d bytes for DMA",
432 mapped_len); 499 mapped_len);
438 screen_image.ptr = mapped_mem; 505 screen_image.ptr = mapped_mem;
439 screen_image.fbp = 0; 506 screen_image.fbp = 0;
440 screen_image.fbw = (vinfo.w + 63) / 64; 507 screen_image.fbw = (vinfo.w + 63) / 64;
441 screen_image.psm = vinfo.psm; 508 screen_image.psm = vinfo.psm;
442 screen_image.x = 0; 509 screen_image.x = 0;
443 screen_image.y = 0; 510 if ( vinfo.h == height ) {
444 screen_image.w = vinfo.w; 511 screen_image.y = 0;
445 screen_image.h = vinfo.h; 512 } else {
513 /* Put image offscreen and scale to screen height */
514 screen_image.y = vinfo.h;
515 }
516 screen_image.w = current->w;
517 screen_image.h = current->h;
446 518
447 /* get screen image data size (qword aligned) */ 519 /* get screen image data size (qword aligned) */
448 screen_image_size = (vinfo.w * vinfo.h); 520 screen_image_size = (screen_image.w * screen_image.h);
449 switch (screen_image.psm) { 521 switch (screen_image.psm) {
450 case PS2_GS_PSMCT32: 522 case PS2_GS_PSMCT32:
451 screen_image_size *= 4; 523 screen_image_size *= 4;
452 break; 524 break;
453 case PS2_GS_PSMCT24: 525 case PS2_GS_PSMCT24:
463 head_tags_mem = (unsigned long long *) 535 head_tags_mem = (unsigned long long *)
464 (mapped_mem + pixels_len); 536 (mapped_mem + pixels_len);
465 image_tags_mem = (unsigned long long *) 537 image_tags_mem = (unsigned long long *)
466 ((caddr_t)head_tags_mem + sizeof(head_tags)); 538 ((caddr_t)head_tags_mem + sizeof(head_tags));
467 memcpy(head_tags_mem, head_tags, sizeof(head_tags)); 539 memcpy(head_tags_mem, head_tags, sizeof(head_tags));
540 if ( saved_vinfo.mode != PS2_GS_VESA ) {
541 tex_tags_mem = (unsigned long long *)
542 ((caddr_t)image_tags_mem + ((2*MAXTAGS)*16));
543 scale_tags_mem = (unsigned long long *)
544 ((caddr_t)tex_tags_mem + sizeof(tex_tags));
545 memcpy(tex_tags_mem, tex_tags, sizeof(tex_tags));
546 tex_tags_mem[2] =
547 (vinfo.h * vinfo.w) / 64 +
548 ((unsigned long long)screen_image.fbw << 14) +
549 ((unsigned long long)screen_image.psm << 20) +
550 ((unsigned long long)power_of_2(screen_image.w) << 26) +
551 ((unsigned long long)power_of_2(screen_image.h) << 30) +
552 ((unsigned long long)1 << 34) +
553 ((unsigned long long)1 << 35);
554 memcpy(scale_tags_mem, scale_tags, sizeof(scale_tags));
555 scale_tags_mem[8] =
556 ((unsigned long long)screen_image.w * 16) +
557 (((unsigned long long)screen_image.h * 16) << 16);
558 scale_tags_mem[10] =
559 ((unsigned long long)vinfo.w * 16) +
560 (((unsigned long long)vinfo.h * 16) << 16);
561 }
468 } 562 }
469 current->pixels = NULL; 563 current->pixels = NULL;
470 if ( getenv("SDL_FULLSCREEN_UPDATE") ) { 564 if ( getenv("SDL_FULLSCREEN_UPDATE") ) {
471 /* Correct semantics */ 565 /* Correct semantics */
472 current->flags |= SDL_ASYNCBLIT; 566 current->flags |= SDL_ASYNCBLIT;
552 646
553 /* Put the image onto the screen */ 647 /* Put the image onto the screen */
554 loadimage_nonblock(console_fd, 648 loadimage_nonblock(console_fd,
555 &screen_image, screen_image_size, 649 &screen_image, screen_image_size,
556 head_tags_mem, image_tags_mem); 650 head_tags_mem, image_tags_mem);
557 dma_pending = 1; 651 if ( screen_image.y > 0 ) {
652 /* Need to scale offscreen image to TV output */
653 ioctl(console_fd, PS2IOC_SENDQCT, 1);
654 dma_pending = 0;
655 scaleimage_nonblock(console_fd, tex_tags_mem, scale_tags_mem);
656 } else {
657 dma_pending = 1;
658 }
558 659
559 /* We're finished! */ 660 /* We're finished! */
560 SDL_UnlockCursor(); 661 SDL_UnlockCursor();
561 } 662 }
562 663