Mercurial > sdl-ios-xcode
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 |