comparison src/SDL_compat.c @ 5172:ededa1ccf91c

Switched the SDL 1.2 compatibility to use the window surface, so it's fast even when there's no hardware acceleration available. This means that the YUV overlay now uses software, but that's okay since fast YUV code should be using the textures now anyway.
author Sam Lantinga <slouken@libsdl.org>
date Thu, 03 Feb 2011 21:13:55 -0800
parents 88c656ffea44
children 34e2d5115786
comparison
equal deleted inserted replaced
5171:db487f28419e 5172:ededa1ccf91c
26 #include "SDL.h" 26 #include "SDL.h"
27 #include "SDL_syswm.h" 27 #include "SDL_syswm.h"
28 28
29 #include "video/SDL_sysvideo.h" 29 #include "video/SDL_sysvideo.h"
30 #include "video/SDL_pixels_c.h" 30 #include "video/SDL_pixels_c.h"
31 #include "render/SDL_yuv_sw_c.h"
32
31 33
32 static SDL_Window *SDL_VideoWindow = NULL; 34 static SDL_Window *SDL_VideoWindow = NULL;
33 static SDL_Renderer *SDL_VideoRenderer = NULL;
34 static SDL_Texture *SDL_VideoTexture = NULL;
35 static SDL_Surface *SDL_VideoSurface = NULL; 35 static SDL_Surface *SDL_VideoSurface = NULL;
36 static SDL_Surface *SDL_ShadowSurface = NULL; 36 static SDL_Surface *SDL_ShadowSurface = NULL;
37 static SDL_Surface *SDL_PublicSurface = NULL; 37 static SDL_Surface *SDL_PublicSurface = NULL;
38 static SDL_GLContext *SDL_VideoContext = NULL; 38 static SDL_GLContext *SDL_VideoContext = NULL;
39 static Uint32 SDL_VideoFlags = 0; 39 static Uint32 SDL_VideoFlags = 0;
40 static char *wm_title = NULL; 40 static char *wm_title = NULL;
41 static SDL_Surface *SDL_VideoIcon; 41 static SDL_Surface *SDL_VideoIcon;
42 static int SDL_enabled_UNICODE = 0; 42 static int SDL_enabled_UNICODE = 0;
43 43
44 char * 44 const char *
45 SDL_AudioDriverName(char *namebuf, int maxlen) 45 SDL_AudioDriverName(char *namebuf, int maxlen)
46 { 46 {
47 const char *name = SDL_GetCurrentAudioDriver(); 47 const char *name = SDL_GetCurrentAudioDriver();
48 if (name) { 48 if (name) {
49 SDL_strlcpy(namebuf, name, maxlen); 49 if (namebuf) {
50 return namebuf; 50 SDL_strlcpy(namebuf, name, maxlen);
51 return namebuf;
52 } else {
53 return name;
54 }
51 } 55 }
52 return NULL; 56 return NULL;
53 } 57 }
54 58
55 char * 59 const char *
56 SDL_VideoDriverName(char *namebuf, int maxlen) 60 SDL_VideoDriverName(char *namebuf, int maxlen)
57 { 61 {
58 const char *name = SDL_GetCurrentVideoDriver(); 62 const char *name = SDL_GetCurrentVideoDriver();
59 if (name) { 63 if (name) {
60 if (namebuf) { 64 if (namebuf) {
342 *x = (mode.w - w) / 2; 346 *x = (mode.w - w) / 2;
343 *y = (mode.h - h) / 2; 347 *y = (mode.h - h) / 2;
344 } 348 }
345 } 349 }
346 350
347 static SDL_Surface *
348 CreateVideoSurface(SDL_Texture * texture)
349 {
350 Uint32 format;
351 int w, h;
352 int bpp;
353 Uint32 Rmask, Gmask, Bmask, Amask;
354
355 if (SDL_QueryTexture(texture, &format, NULL, &w, &h) < 0) {
356 return NULL;
357 }
358
359 if (!SDL_PixelFormatEnumToMasks
360 (format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
361 SDL_SetError("Unknown texture format");
362 return NULL;
363 }
364
365 return SDL_CreateRGBSurface(0, w, h, bpp, Rmask, Gmask, Bmask, Amask);
366 }
367
368 static void 351 static void
369 ClearVideoSurface() 352 ClearVideoSurface()
370 { 353 {
371 Uint32 black; 354 Uint32 black;
372 355
432 SDL_VideoSurface->h = height; 415 SDL_VideoSurface->h = height;
433 return 0; 416 return 0;
434 } 417 }
435 418
436 /* Destroy the screen texture and recreate it */ 419 /* Destroy the screen texture and recreate it */
437 SDL_QueryTexture(SDL_VideoTexture, &format, &access, &w, &h); 420 SDL_VideoSurface = SDL_GetWindowSurface(SDL_VideoWindow);
438 SDL_DestroyTexture(SDL_VideoTexture); 421 if (!SDL_VideoSurface) {
439 SDL_VideoTexture = SDL_CreateTexture(SDL_VideoRenderer, format,
440 access, width, height);
441 if (!SDL_VideoTexture) {
442 return -1; 422 return -1;
443 } 423 }
444
445 SDL_VideoSurface->w = width;
446 SDL_VideoSurface->h = height;
447 SDL_CalculatePitch(SDL_VideoSurface);
448 SDL_VideoSurface->pixels =
449 SDL_realloc(SDL_VideoSurface->pixels,
450 SDL_VideoSurface->h * SDL_VideoSurface->pitch);
451 SDL_SetClipRect(SDL_VideoSurface, NULL);
452 SDL_InvalidateMap(SDL_VideoSurface->map);
453 424
454 if (SDL_ShadowSurface) { 425 if (SDL_ShadowSurface) {
455 SDL_ShadowSurface->w = width; 426 SDL_ShadowSurface->w = width;
456 SDL_ShadowSurface->h = height; 427 SDL_ShadowSurface->h = height;
457 SDL_ShadowSurface->pitch = SDL_CalculatePitch(SDL_ShadowSurface); 428 SDL_ShadowSurface->pitch = SDL_CalculatePitch(SDL_ShadowSurface);
458 SDL_ShadowSurface->pixels = 429 SDL_ShadowSurface->pixels =
459 SDL_realloc(SDL_ShadowSurface->pixels, 430 SDL_realloc(SDL_ShadowSurface->pixels,
460 SDL_ShadowSurface->h * SDL_ShadowSurface->pitch); 431 SDL_ShadowSurface->h * SDL_ShadowSurface->pitch);
461 SDL_SetClipRect(SDL_ShadowSurface, NULL); 432 SDL_SetClipRect(SDL_ShadowSurface, NULL);
462 SDL_InvalidateMap(SDL_ShadowSurface->map); 433 SDL_InvalidateMap(SDL_ShadowSurface->map);
434 } else {
435 SDL_PublicSurface = SDL_VideoSurface;
463 } 436 }
464 437
465 ClearVideoSurface(); 438 ClearVideoSurface();
466 439
467 return 0; 440 return 0;
474 int window_x = SDL_WINDOWPOS_UNDEFINED; 447 int window_x = SDL_WINDOWPOS_UNDEFINED;
475 int window_y = SDL_WINDOWPOS_UNDEFINED; 448 int window_y = SDL_WINDOWPOS_UNDEFINED;
476 Uint32 window_flags; 449 Uint32 window_flags;
477 Uint32 surface_flags; 450 Uint32 surface_flags;
478 Uint32 i; 451 Uint32 i;
479 SDL_RendererInfo info;
480 Uint32 desired_format;
481 452
482 if (!SDL_GetVideoDevice()) { 453 if (!SDL_GetVideoDevice()) {
483 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) < 0) { 454 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) < 0) {
484 return NULL; 455 return NULL;
485 } 456 }
584 SDL_VideoSurface->flags |= surface_flags; 555 SDL_VideoSurface->flags |= surface_flags;
585 SDL_PublicSurface = SDL_VideoSurface; 556 SDL_PublicSurface = SDL_VideoSurface;
586 return SDL_PublicSurface; 557 return SDL_PublicSurface;
587 } 558 }
588 559
589 /* Create a renderer for the window */
590 SDL_VideoRenderer = SDL_CreateRenderer(SDL_VideoWindow, -1, 0);
591 if (!SDL_VideoRenderer) {
592 return NULL;
593 }
594
595 /* Create a texture for the screen surface */
596 SDL_GetRendererInfo(SDL_VideoRenderer, &info);
597 desired_format = info.texture_formats[0];
598 for (i = 0; i < info.num_texture_formats; ++i) {
599 if (!SDL_ISPIXELFORMAT_ALPHA(info.texture_formats[i])) {
600 desired_format = info.texture_formats[i];
601 break;
602 }
603 }
604 SDL_VideoTexture = SDL_CreateTexture(SDL_VideoRenderer, desired_format,
605 SDL_TEXTUREACCESS_STREAMING,
606 width, height);
607 if (!SDL_VideoTexture) {
608 return NULL;
609 }
610
611 /* Create the screen surface */ 560 /* Create the screen surface */
612 SDL_VideoSurface = CreateVideoSurface(SDL_VideoTexture); 561 SDL_VideoSurface = SDL_GetWindowSurface(SDL_VideoWindow);
613 if (!SDL_VideoSurface) { 562 if (!SDL_VideoSurface) {
614 return NULL; 563 return NULL;
615 } 564 }
616 SDL_VideoSurface->flags |= surface_flags; 565 SDL_VideoSurface->flags |= surface_flags;
617 566
772 721
773 /* Fall through to video surface update */ 722 /* Fall through to video surface update */
774 screen = SDL_VideoSurface; 723 screen = SDL_VideoSurface;
775 } 724 }
776 if (screen == SDL_VideoSurface) { 725 if (screen == SDL_VideoSurface) {
777 /* The surface memory needs to be copied to texture */ 726 SDL_UpdateWindowSurfaceRects(SDL_VideoWindow, numrects, rects);
778 int pitch = screen->pitch;
779 int psize = screen->format->BytesPerPixel;
780 for (i = 0; i < numrects; ++i) {
781 const SDL_Rect *rect = &rects[i];
782 void *pixels =
783 (Uint8 *) screen->pixels + rect->y * pitch +
784 rect->x * psize;
785 SDL_UpdateTexture(SDL_VideoTexture, rect, pixels, pitch);
786 }
787 rect.x = 0;
788 rect.y = 0;
789 rect.w = screen->w;
790 rect.h = screen->h;
791 SDL_RenderCopy(SDL_VideoRenderer, SDL_VideoTexture, &rect, &rect);
792 SDL_RenderPresent(SDL_VideoRenderer);
793 } 727 }
794 } 728 }
795 729
796 void 730 void
797 SDL_WM_SetCaption(const char *title, const char *icon) 731 SDL_WM_SetCaption(const char *title, const char *icon)
1393 } 1327 }
1394 #endif 1328 #endif
1395 1329
1396 struct private_yuvhwdata 1330 struct private_yuvhwdata
1397 { 1331 {
1398 Uint16 pitches[3]; 1332 SDL_SW_YUVTexture *texture;
1399 Uint8 *planes[3]; 1333 SDL_Surface *display;
1400 1334 Uint32 display_format;
1401 SDL_Texture *texture;
1402 Uint32 texture_format;
1403 }; 1335 };
1404 1336
1405 SDL_Overlay * 1337 SDL_Overlay *
1406 SDL_CreateYUVOverlay(int w, int h, Uint32 format, SDL_Surface * display) 1338 SDL_CreateYUVOverlay(int w, int h, Uint32 format, SDL_Surface * display)
1407 { 1339 {
1408 SDL_Overlay *overlay; 1340 SDL_Overlay *overlay;
1409 Uint32 texture_format; 1341 Uint32 texture_format;
1342 SDL_SW_YUVTexture *texture;
1410 1343
1411 if ((display->flags & SDL_OPENGL) == SDL_OPENGL) { 1344 if ((display->flags & SDL_OPENGL) == SDL_OPENGL) {
1412 SDL_SetError("YUV overlays are not supported in OpenGL mode"); 1345 SDL_SetError("YUV overlays are not supported in OpenGL mode");
1413 return NULL; 1346 return NULL;
1414 } 1347 }
1452 SDL_free(overlay); 1385 SDL_free(overlay);
1453 SDL_OutOfMemory(); 1386 SDL_OutOfMemory();
1454 return NULL; 1387 return NULL;
1455 } 1388 }
1456 1389
1390 texture = SDL_SW_CreateYUVTexture(texture_format, w, h);
1391 if (!texture) {
1392 SDL_free(overlay->hwdata);
1393 SDL_free(overlay);
1394 return NULL;
1395 }
1396 overlay->hwdata->texture = texture;
1397 overlay->hwdata->display = NULL;
1398 overlay->hwdata->display_format = SDL_PIXELFORMAT_UNKNOWN;
1399
1457 overlay->format = format; 1400 overlay->format = format;
1458 overlay->w = w; 1401 overlay->w = w;
1459 overlay->h = h; 1402 overlay->h = h;
1460 if (format == SDL_YV12_OVERLAY || format == SDL_IYUV_OVERLAY) { 1403 if (format == SDL_YV12_OVERLAY || format == SDL_IYUV_OVERLAY) {
1461 overlay->planes = 3; 1404 overlay->planes = 3;
1462 } else { 1405 } else {
1463 overlay->planes = 1; 1406 overlay->planes = 1;
1464 } 1407 }
1465 overlay->pitches = overlay->hwdata->pitches; 1408 overlay->pitches = texture->pitches;
1466 overlay->pixels = overlay->hwdata->planes; 1409 overlay->pixels = texture->planes;
1467
1468 switch (format) {
1469 case SDL_YV12_OVERLAY:
1470 case SDL_IYUV_OVERLAY:
1471 overlay->pitches[0] = overlay->w;
1472 overlay->pitches[1] = overlay->w / 2;
1473 overlay->pitches[2] = overlay->w / 2;
1474 break;
1475 case SDL_YUY2_OVERLAY:
1476 case SDL_UYVY_OVERLAY:
1477 case SDL_YVYU_OVERLAY:
1478 overlay->pitches[0] = overlay->w * 2;
1479 break;
1480 }
1481
1482 overlay->hwdata->texture =
1483 SDL_CreateTexture(SDL_VideoRenderer, texture_format,
1484 SDL_TEXTUREACCESS_STREAMING, w, h);
1485 if (!overlay->hwdata->texture) {
1486 SDL_FreeYUVOverlay(overlay);
1487 return NULL;
1488 }
1489 overlay->hwdata->texture_format = texture_format;
1490 1410
1491 return overlay; 1411 return overlay;
1492 } 1412 }
1493 1413
1494 int 1414 int
1495 SDL_LockYUVOverlay(SDL_Overlay * overlay) 1415 SDL_LockYUVOverlay(SDL_Overlay * overlay)
1496 { 1416 {
1417 SDL_Rect rect;
1497 void *pixels; 1418 void *pixels;
1498 int pitch; 1419 int pitch;
1499 1420
1500 if (!overlay) { 1421 if (!overlay) {
1501 SDL_SetError("Passed a NULL overlay"); 1422 SDL_SetError("Passed a NULL overlay");
1502 return -1; 1423 return -1;
1503 } 1424 }
1504 if (SDL_LockTexture(overlay->hwdata->texture, NULL, &pixels, &pitch) < 0) { 1425
1426 rect.x = 0;
1427 rect.y = 0;
1428 rect.w = overlay->w;
1429 rect.h = overlay->h;
1430
1431 if (SDL_SW_LockYUVTexture(overlay->hwdata->texture, &rect, &pixels, &pitch) < 0) {
1505 return -1; 1432 return -1;
1506 } 1433 }
1434
1507 overlay->pixels[0] = (Uint8 *) pixels; 1435 overlay->pixels[0] = (Uint8 *) pixels;
1508 overlay->pitches[0] = pitch; 1436 overlay->pitches[0] = pitch;
1509 switch (overlay->format) { 1437 switch (overlay->format) {
1510 case SDL_YV12_OVERLAY: 1438 case SDL_YV12_OVERLAY:
1511 case SDL_IYUV_OVERLAY: 1439 case SDL_IYUV_OVERLAY:
1528 SDL_UnlockYUVOverlay(SDL_Overlay * overlay) 1456 SDL_UnlockYUVOverlay(SDL_Overlay * overlay)
1529 { 1457 {
1530 if (!overlay) { 1458 if (!overlay) {
1531 return; 1459 return;
1532 } 1460 }
1533 SDL_UnlockTexture(overlay->hwdata->texture); 1461
1462 SDL_SW_UnlockYUVTexture(overlay->hwdata->texture);
1534 } 1463 }
1535 1464
1536 int 1465 int
1537 SDL_DisplayYUVOverlay(SDL_Overlay * overlay, SDL_Rect * dstrect) 1466 SDL_DisplayYUVOverlay(SDL_Overlay * overlay, SDL_Rect * dstrect)
1538 { 1467 {
1468 SDL_Surface *display;
1469 SDL_Rect src_rect;
1470 SDL_Rect dst_rect;
1471 void *pixels;
1472
1539 if (!overlay || !dstrect) { 1473 if (!overlay || !dstrect) {
1540 SDL_SetError("Passed a NULL overlay or dstrect"); 1474 SDL_SetError("Passed a NULL overlay or dstrect");
1541 return -1; 1475 return -1;
1542 } 1476 }
1543 if (SDL_RenderCopy(SDL_VideoRenderer, overlay->hwdata->texture, NULL, dstrect) < 0) { 1477
1478 display = overlay->hwdata->display;
1479 if (display != SDL_VideoSurface) {
1480 overlay->hwdata->display = display = SDL_VideoSurface;
1481 overlay->hwdata->display_format = SDL_MasksToPixelFormatEnum(
1482 display->format->BitsPerPixel,
1483 display->format->Rmask,
1484 display->format->Gmask,
1485 display->format->Bmask,
1486 display->format->Amask);
1487 }
1488
1489 src_rect.x = 0;
1490 src_rect.y = 0;
1491 src_rect.w = overlay->w;
1492 src_rect.h = overlay->h;
1493
1494 if (!SDL_IntersectRect(&display->clip_rect, dstrect, &dst_rect)) {
1495 return 0;
1496 }
1497
1498 pixels = (void *)((Uint8 *)display->pixels +
1499 dst_rect.y * display->pitch +
1500 dst_rect.x * display->format->BytesPerPixel);
1501
1502 if (SDL_SW_CopyYUVToRGB(overlay->hwdata->texture, &src_rect,
1503 overlay->hwdata->display_format,
1504 dst_rect.w, dst_rect.h,
1505 pixels, display->pitch) < 0) {
1544 return -1; 1506 return -1;
1545 } 1507 }
1546 SDL_RenderPresent(SDL_VideoRenderer); 1508 SDL_UpdateWindowSurface(SDL_VideoWindow);
1547 return 0; 1509 return 0;
1548 } 1510 }
1549 1511
1550 void 1512 void
1551 SDL_FreeYUVOverlay(SDL_Overlay * overlay) 1513 SDL_FreeYUVOverlay(SDL_Overlay * overlay)
1553 if (!overlay) { 1515 if (!overlay) {
1554 return; 1516 return;
1555 } 1517 }
1556 if (overlay->hwdata) { 1518 if (overlay->hwdata) {
1557 if (overlay->hwdata->texture) { 1519 if (overlay->hwdata->texture) {
1558 SDL_DestroyTexture(overlay->hwdata->texture); 1520 SDL_SW_DestroyYUVTexture(overlay->hwdata->texture);
1559 } 1521 }
1560 SDL_free(overlay->hwdata); 1522 SDL_free(overlay->hwdata);
1561 } 1523 }
1562 SDL_free(overlay); 1524 SDL_free(overlay);
1563 } 1525 }