comparison src/video/SDL_video.c @ 5157:fb424691cfc7

Moved the rendering code out to a separate directory in the hope that it can someday be completely decoupled from the rest of the library and be expanded to an awesome 2D on 3D library.
author Sam Lantinga <slouken@libsdl.org>
date Wed, 02 Feb 2011 14:34:54 -0800
parents 1435f8a6425c
children 2b1989f59674
comparison
equal deleted inserted replaced
5156:3e4086b3bcd2 5157:fb424691cfc7
26 #include "SDL.h" 26 #include "SDL.h"
27 #include "SDL_video.h" 27 #include "SDL_video.h"
28 #include "SDL_sysvideo.h" 28 #include "SDL_sysvideo.h"
29 #include "SDL_blit.h" 29 #include "SDL_blit.h"
30 #include "SDL_pixels_c.h" 30 #include "SDL_pixels_c.h"
31 #include "SDL_renderer_gl.h"
32 #include "SDL_renderer_gles.h"
33 #include "SDL_renderer_sw.h"
34 #include "../events/SDL_events_c.h" 31 #include "../events/SDL_events_c.h"
35
36 #if SDL_VIDEO_DRIVER_WINDOWS
37 #include "windows/SDL_windowsvideo.h"
38 extern void IME_Present(SDL_VideoData *videodata);
39 #endif
40 32
41 #if SDL_VIDEO_OPENGL_ES 33 #if SDL_VIDEO_OPENGL_ES
42 #include "SDL_opengles.h" 34 #include "SDL_opengles.h"
43 #endif /* SDL_VIDEO_OPENGL_ES */ 35 #endif /* SDL_VIDEO_OPENGL_ES */
44 36
98 if (!window || window->magic != &_this->window_magic) { \ 90 if (!window || window->magic != &_this->window_magic) { \
99 SDL_SetError("Invalid window"); \ 91 SDL_SetError("Invalid window"); \
100 return retval; \ 92 return retval; \
101 } 93 }
102 94
103 #define CHECK_RENDERER_MAGIC(renderer, retval) \
104 if (!renderer || renderer->magic != &_this->renderer_magic) { \
105 SDL_SetError("Invalid renderer"); \
106 return retval; \
107 }
108
109 #define CHECK_TEXTURE_MAGIC(texture, retval) \
110 if (!_this) { \
111 SDL_UninitializedVideo(); \
112 return retval; \
113 } \
114 if (!texture || texture->magic != &_this->texture_magic) { \
115 SDL_SetError("Invalid texture"); \
116 return retval; \
117 }
118
119 /* Various local functions */ 95 /* Various local functions */
120 static void SDL_UpdateWindowGrab(SDL_Window * window); 96 static void SDL_UpdateWindowGrab(SDL_Window * window);
121 97
122 static int 98 static int
123 cmpmodes(const void *A, const void *B) 99 cmpmodes(const void *A, const void *B)
256 if (_this->num_displays == 0) { 232 if (_this->num_displays == 0) {
257 SDL_SetError("The video driver did not add any displays"); 233 SDL_SetError("The video driver did not add any displays");
258 SDL_VideoQuit(); 234 SDL_VideoQuit();
259 return (-1); 235 return (-1);
260 } 236 }
261 /* The software renderer is always available */
262 for (i = 0; i < _this->num_displays; ++i) {
263 SDL_VideoDisplay *display = &_this->displays[i];
264 if (_this->GL_CreateContext) {
265 #if SDL_VIDEO_RENDER_OGL
266 SDL_AddRenderDriver(display, &GL_RenderDriver);
267 #endif
268 #if SDL_VIDEO_RENDER_OGL_ES
269 SDL_AddRenderDriver(display, &GL_ES_RenderDriver);
270 #endif
271 }
272 if (display->num_render_drivers > 0) {
273 SDL_AddRenderDriver(display, &SW_RenderDriver);
274 }
275 }
276 237
277 /* We're ready to go! */ 238 /* We're ready to go! */
278 return 0; 239 return 0;
279 } 240 }
280 241
721 *mode = fullscreen_mode; 682 *mode = fullscreen_mode;
722 } 683 }
723 return 0; 684 return 0;
724 } 685 }
725 686
687 Uint32
688 SDL_GetWindowPixelFormat(SDL_Window * window)
689 {
690 SDL_VideoDisplay *display = window->display;
691 SDL_DisplayMode *displayMode = &display->current_mode;
692 return displayMode->format;
693 }
694
726 static void 695 static void
727 SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool attempt) 696 SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool attempt)
728 { 697 {
729 SDL_VideoDisplay *display = window->display; 698 SDL_VideoDisplay *display = window->display;
730 699
1353 } 1322 }
1354 1323
1355 SDL_free(window); 1324 SDL_free(window);
1356 } 1325 }
1357 1326
1358 void
1359 SDL_AddRenderDriver(SDL_VideoDisplay * display, const SDL_RenderDriver * driver)
1360 {
1361 SDL_RenderDriver *render_drivers;
1362
1363 render_drivers =
1364 SDL_realloc(display->render_drivers,
1365 (display->num_render_drivers +
1366 1) * sizeof(*render_drivers));
1367 if (render_drivers) {
1368 render_drivers[display->num_render_drivers] = *driver;
1369 display->render_drivers = render_drivers;
1370 display->num_render_drivers++;
1371 }
1372 }
1373
1374 int
1375 SDL_GetNumRenderDrivers(void)
1376 {
1377 if (_this) {
1378 return SDL_CurrentDisplay->num_render_drivers;
1379 }
1380 return 0;
1381 }
1382
1383 int
1384 SDL_GetRenderDriverInfo(int index, SDL_RendererInfo * info)
1385 {
1386 if (!_this) {
1387 SDL_UninitializedVideo();
1388 return -1;
1389 }
1390 if (index < 0 || index >= SDL_GetNumRenderDrivers()) {
1391 SDL_SetError("index must be in the range of 0 - %d",
1392 SDL_GetNumRenderDrivers() - 1);
1393 return -1;
1394 }
1395 *info = SDL_CurrentDisplay->render_drivers[index].info;
1396 return 0;
1397 }
1398
1399 static int
1400 SDL_RendererEventWatch(void *userdata, SDL_Event *event)
1401 {
1402 SDL_Renderer *renderer = (SDL_Renderer *)userdata;
1403
1404 if (event->type == SDL_WINDOWEVENT && renderer->WindowEvent) {
1405 SDL_Window *window = SDL_GetWindowFromID(event->window.windowID);
1406 if (window == renderer->window) {
1407 renderer->WindowEvent(renderer, &event->window);
1408 }
1409 }
1410 return 0;
1411 }
1412
1413 SDL_Renderer *
1414 SDL_CreateRenderer(SDL_Window * window, int index, Uint32 flags)
1415 {
1416 SDL_Renderer *renderer = NULL;
1417
1418 CHECK_WINDOW_MAGIC(window, NULL);
1419
1420 if (index < 0) {
1421 char *override = SDL_getenv("SDL_VIDEO_RENDERER");
1422 int n = SDL_GetNumRenderDrivers();
1423
1424 #if SDL_VIDEO_RENDER_OGL
1425 if (!override && (window->flags & SDL_WINDOW_OPENGL)) {
1426 override = "opengl";
1427 }
1428 #endif /* SDL_VIDEO_RENDER_OGL */
1429 #if SDL_VIDEO_RENDER_OGL_ES
1430 if (!override && (window->flags & SDL_WINDOW_OPENGL)) {
1431 override = "opengl_es";
1432 }
1433 #endif /* SDL_VIDEO_RENDER_OGL_ES */
1434 if (override) {
1435 for (index = 0; index < n; ++index) {
1436 SDL_RenderDriver *driver =
1437 &SDL_CurrentDisplay->render_drivers[index];
1438
1439 if (SDL_strcasecmp(override, driver->info.name) == 0) {
1440 /* Create a new renderer instance */
1441 renderer = driver->CreateRenderer(window, flags);
1442 break;
1443 }
1444 }
1445 } else {
1446 for (index = 0; index < n; ++index) {
1447 SDL_RenderDriver *driver =
1448 &SDL_CurrentDisplay->render_drivers[index];
1449
1450 if ((driver->info.flags & flags) == flags) {
1451 /* Create a new renderer instance */
1452 renderer = driver->CreateRenderer(window, flags);
1453 if (renderer) {
1454 /* Yay, we got one! */
1455 break;
1456 }
1457 }
1458 }
1459 }
1460 if (index == n) {
1461 SDL_SetError("Couldn't find matching render driver");
1462 return NULL;
1463 }
1464 } else {
1465 if (index >= SDL_GetNumRenderDrivers()) {
1466 SDL_SetError("index must be -1 or in the range of 0 - %d",
1467 SDL_GetNumRenderDrivers() - 1);
1468 return NULL;
1469 }
1470 /* Create a new renderer instance */
1471 renderer = SDL_CurrentDisplay->render_drivers[index].CreateRenderer(window, flags);
1472 }
1473
1474 if (renderer) {
1475 renderer->magic = &_this->renderer_magic;
1476
1477 SDL_AddEventWatch(SDL_RendererEventWatch, renderer);
1478 }
1479 return renderer;
1480 }
1481
1482 int
1483 SDL_GetRendererInfo(SDL_Renderer * renderer, SDL_RendererInfo * info)
1484 {
1485 CHECK_RENDERER_MAGIC(renderer, -1);
1486
1487 *info = renderer->info;
1488 return 0;
1489 }
1490
1491 SDL_Texture *
1492 SDL_CreateTexture(SDL_Renderer * renderer, Uint32 format, int access, int w, int h)
1493 {
1494 SDL_Texture *texture;
1495
1496 CHECK_RENDERER_MAGIC(renderer, NULL);
1497
1498 if (w <= 0 || h <= 0) {
1499 SDL_SetError("Texture dimensions can't be 0");
1500 return 0;
1501 }
1502 texture = (SDL_Texture *) SDL_calloc(1, sizeof(*texture));
1503 if (!texture) {
1504 SDL_OutOfMemory();
1505 return 0;
1506 }
1507 texture->magic = &_this->texture_magic;
1508 texture->format = format;
1509 texture->access = access;
1510 texture->w = w;
1511 texture->h = h;
1512 texture->r = 255;
1513 texture->g = 255;
1514 texture->b = 255;
1515 texture->a = 255;
1516 texture->renderer = renderer;
1517 texture->next = renderer->textures;
1518 if (renderer->textures) {
1519 renderer->textures->prev = texture;
1520 }
1521 renderer->textures = texture;
1522
1523 if (renderer->CreateTexture(renderer, texture) < 0) {
1524 SDL_DestroyTexture(texture);
1525 return 0;
1526 }
1527 return texture;
1528 }
1529
1530 SDL_Texture *
1531 SDL_CreateTextureFromSurface(SDL_Renderer * renderer, Uint32 format, SDL_Surface * surface)
1532 {
1533 SDL_Texture *texture;
1534 Uint32 requested_format = format;
1535 SDL_PixelFormat *fmt;
1536 int bpp;
1537 Uint32 Rmask, Gmask, Bmask, Amask;
1538
1539 CHECK_RENDERER_MAGIC(renderer, NULL);
1540
1541 if (!surface) {
1542 SDL_SetError("SDL_CreateTextureFromSurface() passed NULL surface");
1543 return NULL;
1544 }
1545 fmt = surface->format;
1546
1547 if (format) {
1548 if (!SDL_PixelFormatEnumToMasks
1549 (format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
1550 SDL_SetError("Unknown pixel format");
1551 return 0;
1552 }
1553 } else {
1554 if (surface->format->Amask
1555 || !(surface->map->info.flags &
1556 (SDL_COPY_COLORKEY | SDL_COPY_BLEND))) {
1557 Uint32 it;
1558 int pfmt;
1559
1560 /* Pixel formats, sorted by best first */
1561 static const Uint32 sdl_pformats[] = {
1562 SDL_PIXELFORMAT_ARGB8888,
1563 SDL_PIXELFORMAT_RGBA8888,
1564 SDL_PIXELFORMAT_ABGR8888,
1565 SDL_PIXELFORMAT_BGRA8888,
1566 SDL_PIXELFORMAT_RGB888,
1567 SDL_PIXELFORMAT_BGR888,
1568 SDL_PIXELFORMAT_RGB24,
1569 SDL_PIXELFORMAT_BGR24,
1570 SDL_PIXELFORMAT_RGB565,
1571 SDL_PIXELFORMAT_BGR565,
1572 SDL_PIXELFORMAT_ARGB1555,
1573 SDL_PIXELFORMAT_RGBA5551,
1574 SDL_PIXELFORMAT_ABGR1555,
1575 SDL_PIXELFORMAT_BGRA5551,
1576 SDL_PIXELFORMAT_RGB555,
1577 SDL_PIXELFORMAT_BGR555,
1578 SDL_PIXELFORMAT_ARGB4444,
1579 SDL_PIXELFORMAT_RGBA4444,
1580 SDL_PIXELFORMAT_ABGR4444,
1581 SDL_PIXELFORMAT_BGRA4444,
1582 SDL_PIXELFORMAT_RGB444,
1583 SDL_PIXELFORMAT_ARGB2101010,
1584 SDL_PIXELFORMAT_RGB332,
1585 SDL_PIXELFORMAT_UNKNOWN
1586 };
1587
1588 bpp = fmt->BitsPerPixel;
1589 Rmask = fmt->Rmask;
1590 Gmask = fmt->Gmask;
1591 Bmask = fmt->Bmask;
1592 Amask = fmt->Amask;
1593
1594 format =
1595 SDL_MasksToPixelFormatEnum(bpp, Rmask, Gmask, Bmask, Amask);
1596 if (!format) {
1597 SDL_SetError("Unknown pixel format");
1598 return 0;
1599 }
1600
1601 /* Search requested format in the supported texture */
1602 /* formats by current renderer */
1603 for (it = 0; it < renderer->info.num_texture_formats; it++) {
1604 if (renderer->info.texture_formats[it] == format) {
1605 break;
1606 }
1607 }
1608
1609 /* If requested format can't be found, search any best */
1610 /* format which renderer provides */
1611 if (it == renderer->info.num_texture_formats) {
1612 pfmt = 0;
1613 for (;;) {
1614 if (sdl_pformats[pfmt] == SDL_PIXELFORMAT_UNKNOWN) {
1615 break;
1616 }
1617
1618 for (it = 0; it < renderer->info.num_texture_formats;
1619 it++) {
1620 if (renderer->info.texture_formats[it] ==
1621 sdl_pformats[pfmt]) {
1622 break;
1623 }
1624 }
1625
1626 if (it != renderer->info.num_texture_formats) {
1627 /* The best format has been found */
1628 break;
1629 }
1630 pfmt++;
1631 }
1632
1633 /* If any format can't be found, then return an error */
1634 if (it == renderer->info.num_texture_formats) {
1635 SDL_SetError
1636 ("Any of the supported pixel formats can't be found");
1637 return 0;
1638 }
1639
1640 /* Convert found pixel format back to color masks */
1641 if (SDL_PixelFormatEnumToMasks
1642 (renderer->info.texture_formats[it], &bpp, &Rmask, &Gmask,
1643 &Bmask, &Amask) != SDL_TRUE) {
1644 SDL_SetError("Unknown pixel format");
1645 return 0;
1646 }
1647 }
1648 } else {
1649 /* Need a format with alpha */
1650 Uint32 it;
1651 int apfmt;
1652
1653 /* Pixel formats with alpha, sorted by best first */
1654 static const Uint32 sdl_alpha_pformats[] = {
1655 SDL_PIXELFORMAT_ARGB8888,
1656 SDL_PIXELFORMAT_RGBA8888,
1657 SDL_PIXELFORMAT_ABGR8888,
1658 SDL_PIXELFORMAT_BGRA8888,
1659 SDL_PIXELFORMAT_ARGB1555,
1660 SDL_PIXELFORMAT_RGBA5551,
1661 SDL_PIXELFORMAT_ABGR1555,
1662 SDL_PIXELFORMAT_BGRA5551,
1663 SDL_PIXELFORMAT_ARGB4444,
1664 SDL_PIXELFORMAT_RGBA4444,
1665 SDL_PIXELFORMAT_ABGR4444,
1666 SDL_PIXELFORMAT_BGRA4444,
1667 SDL_PIXELFORMAT_ARGB2101010,
1668 SDL_PIXELFORMAT_UNKNOWN
1669 };
1670
1671 if (surface->format->Amask) {
1672 /* If surface already has alpha, then try an original */
1673 /* surface format first */
1674 bpp = fmt->BitsPerPixel;
1675 Rmask = fmt->Rmask;
1676 Gmask = fmt->Gmask;
1677 Bmask = fmt->Bmask;
1678 Amask = fmt->Amask;
1679 } else {
1680 bpp = 32;
1681 Rmask = 0x00FF0000;
1682 Gmask = 0x0000FF00;
1683 Bmask = 0x000000FF;
1684 Amask = 0xFF000000;
1685 }
1686
1687 format =
1688 SDL_MasksToPixelFormatEnum(bpp, Rmask, Gmask, Bmask, Amask);
1689 if (!format) {
1690 SDL_SetError("Unknown pixel format");
1691 return 0;
1692 }
1693
1694 /* Search this format in the supported texture formats */
1695 /* by current renderer */
1696 for (it = 0; it < renderer->info.num_texture_formats; it++) {
1697 if (renderer->info.texture_formats[it] == format) {
1698 break;
1699 }
1700 }
1701
1702 /* If this format can't be found, search any best */
1703 /* compatible format with alpha which renderer provides */
1704 if (it == renderer->info.num_texture_formats) {
1705 apfmt = 0;
1706 for (;;) {
1707 if (sdl_alpha_pformats[apfmt] == SDL_PIXELFORMAT_UNKNOWN) {
1708 break;
1709 }
1710
1711 for (it = 0; it < renderer->info.num_texture_formats;
1712 it++) {
1713 if (renderer->info.texture_formats[it] ==
1714 sdl_alpha_pformats[apfmt]) {
1715 break;
1716 }
1717 }
1718
1719 if (it != renderer->info.num_texture_formats) {
1720 /* Compatible format has been found */
1721 break;
1722 }
1723 apfmt++;
1724 }
1725
1726 /* If compatible format can't be found, then return an error */
1727 if (it == renderer->info.num_texture_formats) {
1728 SDL_SetError("Compatible pixel format can't be found");
1729 return 0;
1730 }
1731
1732 /* Convert found pixel format back to color masks */
1733 if (SDL_PixelFormatEnumToMasks
1734 (renderer->info.texture_formats[it], &bpp, &Rmask, &Gmask,
1735 &Bmask, &Amask) != SDL_TRUE) {
1736 SDL_SetError("Unknown pixel format");
1737 return 0;
1738 }
1739 }
1740 }
1741
1742 format = SDL_MasksToPixelFormatEnum(bpp, Rmask, Gmask, Bmask, Amask);
1743 if (!format) {
1744 SDL_SetError("Unknown pixel format");
1745 return 0;
1746 }
1747 }
1748
1749 texture =
1750 SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_STATIC,
1751 surface->w, surface->h);
1752 if (!texture && !requested_format) {
1753 SDL_DisplayMode desktop_mode;
1754 SDL_GetDesktopDisplayMode(&desktop_mode);
1755 format = desktop_mode.format;
1756 texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_STATIC,
1757 surface->w, surface->h);
1758 }
1759 if (!texture) {
1760 return 0;
1761 }
1762 if (bpp == fmt->BitsPerPixel && Rmask == fmt->Rmask && Gmask == fmt->Gmask
1763 && Bmask == fmt->Bmask && Amask == fmt->Amask) {
1764 if (SDL_MUSTLOCK(surface)) {
1765 SDL_LockSurface(surface);
1766 SDL_UpdateTexture(texture, NULL, surface->pixels,
1767 surface->pitch);
1768 SDL_UnlockSurface(surface);
1769 } else {
1770 SDL_UpdateTexture(texture, NULL, surface->pixels,
1771 surface->pitch);
1772 }
1773 } else {
1774 SDL_PixelFormat dst_fmt;
1775 SDL_Surface *dst = NULL;
1776
1777 /* Set up a destination surface for the texture update */
1778 SDL_InitFormat(&dst_fmt, bpp, Rmask, Gmask, Bmask, Amask);
1779 dst = SDL_ConvertSurface(surface, &dst_fmt, 0);
1780 if (dst) {
1781 SDL_UpdateTexture(texture, NULL, dst->pixels, dst->pitch);
1782 SDL_FreeSurface(dst);
1783 }
1784 if (!dst) {
1785 SDL_DestroyTexture(texture);
1786 return 0;
1787 }
1788 }
1789
1790 {
1791 Uint8 r, g, b, a;
1792 SDL_BlendMode blendMode;
1793
1794 SDL_GetSurfaceColorMod(surface, &r, &g, &b);
1795 SDL_SetTextureColorMod(texture, r, g, b);
1796
1797 SDL_GetSurfaceAlphaMod(surface, &a);
1798 SDL_SetTextureAlphaMod(texture, a);
1799
1800 if (surface->map->info.flags & SDL_COPY_COLORKEY) {
1801 /* We converted to a texture with alpha format */
1802 SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
1803 } else {
1804 SDL_GetSurfaceBlendMode(surface, &blendMode);
1805 SDL_SetTextureBlendMode(texture, blendMode);
1806 }
1807 }
1808 return texture;
1809 }
1810
1811 int
1812 SDL_QueryTexture(SDL_Texture * texture, Uint32 * format, int *access,
1813 int *w, int *h)
1814 {
1815 CHECK_TEXTURE_MAGIC(texture, -1);
1816
1817 if (format) {
1818 *format = texture->format;
1819 }
1820 if (access) {
1821 *access = texture->access;
1822 }
1823 if (w) {
1824 *w = texture->w;
1825 }
1826 if (h) {
1827 *h = texture->h;
1828 }
1829 return 0;
1830 }
1831
1832 int
1833 SDL_QueryTexturePixels(SDL_Texture * texture, void **pixels, int *pitch)
1834 {
1835 SDL_Renderer *renderer;
1836
1837 CHECK_TEXTURE_MAGIC(texture, -1);
1838
1839 renderer = texture->renderer;
1840 if (!renderer->QueryTexturePixels) {
1841 SDL_Unsupported();
1842 return -1;
1843 }
1844 return renderer->QueryTexturePixels(renderer, texture, pixels, pitch);
1845 }
1846
1847 int
1848 SDL_SetTextureColorMod(SDL_Texture * texture, Uint8 r, Uint8 g, Uint8 b)
1849 {
1850 SDL_Renderer *renderer;
1851
1852 CHECK_TEXTURE_MAGIC(texture, -1);
1853
1854 renderer = texture->renderer;
1855 if (r < 255 || g < 255 || b < 255) {
1856 texture->modMode |= SDL_TEXTUREMODULATE_COLOR;
1857 } else {
1858 texture->modMode &= ~SDL_TEXTUREMODULATE_COLOR;
1859 }
1860 texture->r = r;
1861 texture->g = g;
1862 texture->b = b;
1863 if (renderer->SetTextureColorMod) {
1864 return renderer->SetTextureColorMod(renderer, texture);
1865 } else {
1866 return 0;
1867 }
1868 }
1869
1870 int
1871 SDL_GetTextureColorMod(SDL_Texture * texture, Uint8 * r, Uint8 * g,
1872 Uint8 * b)
1873 {
1874 SDL_Renderer *renderer;
1875
1876 CHECK_TEXTURE_MAGIC(texture, -1);
1877
1878 renderer = texture->renderer;
1879 if (r) {
1880 *r = texture->r;
1881 }
1882 if (g) {
1883 *g = texture->g;
1884 }
1885 if (b) {
1886 *b = texture->b;
1887 }
1888 return 0;
1889 }
1890
1891 int
1892 SDL_SetTextureAlphaMod(SDL_Texture * texture, Uint8 alpha)
1893 {
1894 SDL_Renderer *renderer;
1895
1896 CHECK_TEXTURE_MAGIC(texture, -1);
1897
1898 renderer = texture->renderer;
1899 if (alpha < 255) {
1900 texture->modMode |= SDL_TEXTUREMODULATE_ALPHA;
1901 } else {
1902 texture->modMode &= ~SDL_TEXTUREMODULATE_ALPHA;
1903 }
1904 texture->a = alpha;
1905 if (renderer->SetTextureAlphaMod) {
1906 return renderer->SetTextureAlphaMod(renderer, texture);
1907 } else {
1908 return 0;
1909 }
1910 }
1911
1912 int
1913 SDL_GetTextureAlphaMod(SDL_Texture * texture, Uint8 * alpha)
1914 {
1915 CHECK_TEXTURE_MAGIC(texture, -1);
1916
1917 if (alpha) {
1918 *alpha = texture->a;
1919 }
1920 return 0;
1921 }
1922
1923 int
1924 SDL_SetTextureBlendMode(SDL_Texture * texture, SDL_BlendMode blendMode)
1925 {
1926 SDL_Renderer *renderer;
1927
1928 CHECK_TEXTURE_MAGIC(texture, -1);
1929
1930 renderer = texture->renderer;
1931 texture->blendMode = blendMode;
1932 if (renderer->SetTextureBlendMode) {
1933 return renderer->SetTextureBlendMode(renderer, texture);
1934 } else {
1935 return 0;
1936 }
1937 }
1938
1939 int
1940 SDL_GetTextureBlendMode(SDL_Texture * texture, SDL_BlendMode *blendMode)
1941 {
1942 CHECK_TEXTURE_MAGIC(texture, -1);
1943
1944 if (blendMode) {
1945 *blendMode = texture->blendMode;
1946 }
1947 return 0;
1948 }
1949
1950 int
1951 SDL_UpdateTexture(SDL_Texture * texture, const SDL_Rect * rect,
1952 const void *pixels, int pitch)
1953 {
1954 SDL_Renderer *renderer;
1955 SDL_Rect full_rect;
1956
1957 CHECK_TEXTURE_MAGIC(texture, -1);
1958
1959 renderer = texture->renderer;
1960 if (!renderer->UpdateTexture) {
1961 SDL_Unsupported();
1962 return -1;
1963 }
1964 if (!rect) {
1965 full_rect.x = 0;
1966 full_rect.y = 0;
1967 full_rect.w = texture->w;
1968 full_rect.h = texture->h;
1969 rect = &full_rect;
1970 }
1971 return renderer->UpdateTexture(renderer, texture, rect, pixels, pitch);
1972 }
1973
1974 int
1975 SDL_LockTexture(SDL_Texture * texture, const SDL_Rect * rect, int markDirty,
1976 void **pixels, int *pitch)
1977 {
1978 SDL_Renderer *renderer;
1979 SDL_Rect full_rect;
1980
1981 CHECK_TEXTURE_MAGIC(texture, -1);
1982
1983 if (texture->access != SDL_TEXTUREACCESS_STREAMING) {
1984 SDL_SetError("SDL_LockTexture(): texture must be streaming");
1985 return -1;
1986 }
1987 renderer = texture->renderer;
1988 if (!renderer->LockTexture) {
1989 SDL_Unsupported();
1990 return -1;
1991 }
1992 if (!rect) {
1993 full_rect.x = 0;
1994 full_rect.y = 0;
1995 full_rect.w = texture->w;
1996 full_rect.h = texture->h;
1997 rect = &full_rect;
1998 }
1999 return renderer->LockTexture(renderer, texture, rect, markDirty, pixels,
2000 pitch);
2001 }
2002
2003 void
2004 SDL_UnlockTexture(SDL_Texture * texture)
2005 {
2006 SDL_Renderer *renderer;
2007
2008 CHECK_TEXTURE_MAGIC(texture, );
2009
2010 if (texture->access != SDL_TEXTUREACCESS_STREAMING) {
2011 return;
2012 }
2013 renderer = texture->renderer;
2014 if (!renderer->UnlockTexture) {
2015 return;
2016 }
2017 renderer->UnlockTexture(renderer, texture);
2018 }
2019
2020 void
2021 SDL_DirtyTexture(SDL_Texture * texture, int numrects,
2022 const SDL_Rect * rects)
2023 {
2024 SDL_Renderer *renderer;
2025
2026 CHECK_TEXTURE_MAGIC(texture, );
2027
2028 if (texture->access != SDL_TEXTUREACCESS_STREAMING) {
2029 return;
2030 }
2031 renderer = texture->renderer;
2032 if (!renderer->DirtyTexture) {
2033 return;
2034 }
2035 renderer->DirtyTexture(renderer, texture, numrects, rects);
2036 }
2037
2038 int
2039 SDL_SetRenderDrawColor(SDL_Renderer * renderer,
2040 Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2041 {
2042 CHECK_RENDERER_MAGIC(renderer, -1);
2043
2044 renderer->r = r;
2045 renderer->g = g;
2046 renderer->b = b;
2047 renderer->a = a;
2048 return 0;
2049 }
2050
2051 int
2052 SDL_GetRenderDrawColor(SDL_Renderer * renderer,
2053 Uint8 * r, Uint8 * g, Uint8 * b, Uint8 * a)
2054 {
2055 CHECK_RENDERER_MAGIC(renderer, -1);
2056
2057 if (r) {
2058 *r = renderer->r;
2059 }
2060 if (g) {
2061 *g = renderer->g;
2062 }
2063 if (b) {
2064 *b = renderer->b;
2065 }
2066 if (a) {
2067 *a = renderer->a;
2068 }
2069 return 0;
2070 }
2071
2072 int
2073 SDL_SetRenderDrawBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
2074 {
2075 CHECK_RENDERER_MAGIC(renderer, -1);
2076
2077 renderer->blendMode = blendMode;
2078 return 0;
2079 }
2080
2081 int
2082 SDL_GetRenderDrawBlendMode(SDL_Renderer * renderer, SDL_BlendMode *blendMode)
2083 {
2084 CHECK_RENDERER_MAGIC(renderer, -1);
2085
2086 *blendMode = renderer->blendMode;
2087 return 0;
2088 }
2089
2090 int
2091 SDL_RenderClear(SDL_Renderer * renderer)
2092 {
2093 CHECK_RENDERER_MAGIC(renderer, -1);
2094
2095 if (!renderer->RenderClear) {
2096 SDL_BlendMode blendMode = renderer->blendMode;
2097 int status;
2098
2099 if (blendMode >= SDL_BLENDMODE_BLEND) {
2100 SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
2101 }
2102
2103 status = SDL_RenderFillRect(renderer, NULL);
2104
2105 if (blendMode >= SDL_BLENDMODE_BLEND) {
2106 SDL_SetRenderDrawBlendMode(renderer, blendMode);
2107 }
2108 return status;
2109 }
2110 return renderer->RenderClear(renderer);
2111 }
2112
2113 int
2114 SDL_RenderDrawPoint(SDL_Renderer * renderer, int x, int y)
2115 {
2116 SDL_Point point;
2117
2118 point.x = x;
2119 point.y = y;
2120 return SDL_RenderDrawPoints(renderer, &point, 1);
2121 }
2122
2123 int
2124 SDL_RenderDrawPoints(SDL_Renderer * renderer,
2125 const SDL_Point * points, int count)
2126 {
2127 CHECK_RENDERER_MAGIC(renderer, -1);
2128
2129 if (!points) {
2130 SDL_SetError("SDL_RenderDrawPoints(): Passed NULL points");
2131 return -1;
2132 }
2133 if (count < 1) {
2134 return 0;
2135 }
2136 return renderer->RenderDrawPoints(renderer, points, count);
2137 }
2138
2139 int
2140 SDL_RenderDrawLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2)
2141 {
2142 SDL_Point points[2];
2143
2144 points[0].x = x1;
2145 points[0].y = y1;
2146 points[1].x = x2;
2147 points[1].y = y2;
2148 return SDL_RenderDrawLines(renderer, points, 2);
2149 }
2150
2151 int
2152 SDL_RenderDrawLines(SDL_Renderer * renderer,
2153 const SDL_Point * points, int count)
2154 {
2155 CHECK_RENDERER_MAGIC(renderer, -1);
2156
2157 if (!points) {
2158 SDL_SetError("SDL_RenderDrawLines(): Passed NULL points");
2159 return -1;
2160 }
2161 if (count < 2) {
2162 return 0;
2163 }
2164 return renderer->RenderDrawLines(renderer, points, count);
2165 }
2166
2167 int
2168 SDL_RenderDrawRect(SDL_Renderer * renderer, const SDL_Rect * rect)
2169 {
2170 SDL_Rect full_rect;
2171 SDL_Point points[5];
2172
2173 CHECK_RENDERER_MAGIC(renderer, -1);
2174
2175 /* If 'rect' == NULL, then outline the whole surface */
2176 if (!rect) {
2177 SDL_Window *window = renderer->window;
2178
2179 full_rect.x = 0;
2180 full_rect.y = 0;
2181 full_rect.w = window->w;
2182 full_rect.h = window->h;
2183 rect = &full_rect;
2184 }
2185
2186 points[0].x = rect->x;
2187 points[0].y = rect->y;
2188 points[1].x = rect->x+rect->w-1;
2189 points[1].y = rect->y;
2190 points[2].x = rect->x+rect->w-1;
2191 points[2].y = rect->y+rect->h-1;
2192 points[3].x = rect->x;
2193 points[3].y = rect->y+rect->h-1;
2194 points[4].x = rect->x;
2195 points[4].y = rect->y;
2196 return SDL_RenderDrawLines(renderer, points, 5);
2197 }
2198
2199 int
2200 SDL_RenderDrawRects(SDL_Renderer * renderer,
2201 const SDL_Rect ** rects, int count)
2202 {
2203 int i;
2204
2205 CHECK_RENDERER_MAGIC(renderer, -1);
2206
2207 if (!rects) {
2208 SDL_SetError("SDL_RenderDrawRects(): Passed NULL rects");
2209 return -1;
2210 }
2211 if (count < 1) {
2212 return 0;
2213 }
2214
2215 /* Check for NULL rect, which means fill entire window */
2216 for (i = 0; i < count; ++i) {
2217 if (SDL_RenderDrawRect(renderer, rects[i]) < 0) {
2218 return -1;
2219 }
2220 }
2221 return 0;
2222 }
2223
2224 int
2225 SDL_RenderFillRect(SDL_Renderer * renderer, const SDL_Rect * rect)
2226 {
2227 return SDL_RenderFillRects(renderer, &rect, 1);
2228 }
2229
2230 int
2231 SDL_RenderFillRects(SDL_Renderer * renderer,
2232 const SDL_Rect ** rects, int count)
2233 {
2234 int i;
2235
2236 CHECK_RENDERER_MAGIC(renderer, -1);
2237
2238 if (!rects) {
2239 SDL_SetError("SDL_RenderFillRects(): Passed NULL rects");
2240 return -1;
2241 }
2242 if (count < 1) {
2243 return 0;
2244 }
2245
2246 /* Check for NULL rect, which means fill entire window */
2247 for (i = 0; i < count; ++i) {
2248 if (rects[i] == NULL) {
2249 SDL_Window *window = renderer->window;
2250 SDL_Rect full_rect;
2251 const SDL_Rect *rect;
2252
2253 full_rect.x = 0;
2254 full_rect.y = 0;
2255 full_rect.w = window->w;
2256 full_rect.h = window->h;
2257 rect = &full_rect;
2258 return renderer->RenderFillRects(renderer, &rect, 1);
2259 }
2260 }
2261 return renderer->RenderFillRects(renderer, rects, count);
2262 }
2263
2264 int
2265 SDL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
2266 const SDL_Rect * srcrect, const SDL_Rect * dstrect)
2267 {
2268 SDL_Window *window;
2269 SDL_Rect real_srcrect;
2270 SDL_Rect real_dstrect;
2271
2272 CHECK_RENDERER_MAGIC(renderer, -1);
2273 CHECK_TEXTURE_MAGIC(texture, -1);
2274
2275 if (renderer != texture->renderer) {
2276 SDL_SetError("Texture was not created with this renderer");
2277 return -1;
2278 }
2279 window = renderer->window;
2280
2281 real_srcrect.x = 0;
2282 real_srcrect.y = 0;
2283 real_srcrect.w = texture->w;
2284 real_srcrect.h = texture->h;
2285 if (srcrect) {
2286 if (!SDL_IntersectRect(srcrect, &real_srcrect, &real_srcrect)) {
2287 return 0;
2288 }
2289 }
2290
2291 real_dstrect.x = 0;
2292 real_dstrect.y = 0;
2293 real_dstrect.w = window->w;
2294 real_dstrect.h = window->h;
2295 if (dstrect) {
2296 if (!SDL_IntersectRect(dstrect, &real_dstrect, &real_dstrect)) {
2297 return 0;
2298 }
2299 /* Clip srcrect by the same amount as dstrect was clipped */
2300 if (dstrect->w != real_dstrect.w) {
2301 int deltax = (real_dstrect.x - dstrect->x);
2302 int deltaw = (real_dstrect.w - dstrect->w);
2303 real_srcrect.x += (deltax * real_srcrect.w) / dstrect->w;
2304 real_srcrect.w += (deltaw * real_srcrect.w) / dstrect->w;
2305 }
2306 if (dstrect->h != real_dstrect.h) {
2307 int deltay = (real_dstrect.y - dstrect->y);
2308 int deltah = (real_dstrect.h - dstrect->h);
2309 real_srcrect.y += (deltay * real_srcrect.h) / dstrect->h;
2310 real_srcrect.h += (deltah * real_srcrect.h) / dstrect->h;
2311 }
2312 }
2313
2314 return renderer->RenderCopy(renderer, texture, &real_srcrect,
2315 &real_dstrect);
2316 }
2317
2318 int
2319 SDL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
2320 Uint32 format, void * pixels, int pitch)
2321 {
2322 SDL_Window *window;
2323 SDL_Rect real_rect;
2324
2325 CHECK_RENDERER_MAGIC(renderer, -1);
2326
2327 if (!renderer->RenderReadPixels) {
2328 SDL_Unsupported();
2329 return -1;
2330 }
2331 window = renderer->window;
2332
2333 if (!format) {
2334 format = window->display->current_mode.format;
2335 }
2336
2337 real_rect.x = 0;
2338 real_rect.y = 0;
2339 real_rect.w = window->w;
2340 real_rect.h = window->h;
2341 if (rect) {
2342 if (!SDL_IntersectRect(rect, &real_rect, &real_rect)) {
2343 return 0;
2344 }
2345 if (real_rect.y > rect->y) {
2346 pixels = (Uint8 *)pixels + pitch * (real_rect.y - rect->y);
2347 }
2348 if (real_rect.x > rect->x) {
2349 Uint32 format = SDL_CurrentDisplay->current_mode.format;
2350 int bpp = SDL_BYTESPERPIXEL(format);
2351 pixels = (Uint8 *)pixels + bpp * (real_rect.x - rect->x);
2352 }
2353 }
2354
2355 return renderer->RenderReadPixels(renderer, &real_rect,
2356 format, pixels, pitch);
2357 }
2358
2359 int
2360 SDL_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
2361 Uint32 format, const void * pixels, int pitch)
2362 {
2363 SDL_Window *window;
2364 SDL_Rect real_rect;
2365
2366 CHECK_RENDERER_MAGIC(renderer, -1);
2367
2368 if (!renderer->RenderWritePixels) {
2369 SDL_Unsupported();
2370 return -1;
2371 }
2372 window = renderer->window;
2373
2374 if (!format) {
2375 format = window->display->current_mode.format;
2376 }
2377
2378 real_rect.x = 0;
2379 real_rect.y = 0;
2380 real_rect.w = window->w;
2381 real_rect.h = window->h;
2382 if (rect) {
2383 if (!SDL_IntersectRect(rect, &real_rect, &real_rect)) {
2384 return 0;
2385 }
2386 if (real_rect.y > rect->y) {
2387 pixels = (const Uint8 *)pixels + pitch * (real_rect.y - rect->y);
2388 }
2389 if (real_rect.x > rect->x) {
2390 Uint32 format = SDL_CurrentDisplay->current_mode.format;
2391 int bpp = SDL_BYTESPERPIXEL(format);
2392 pixels = (const Uint8 *)pixels + bpp * (real_rect.x - rect->x);
2393 }
2394 }
2395
2396 return renderer->RenderWritePixels(renderer, &real_rect,
2397 format, pixels, pitch);
2398 }
2399
2400 void
2401 SDL_RenderPresent(SDL_Renderer * renderer)
2402 {
2403 CHECK_RENDERER_MAGIC(renderer, );
2404
2405 #if SDL_VIDEO_DRIVER_WINDOWS
2406 IME_Present((SDL_VideoData *)_this->driverdata);
2407 #endif
2408 renderer->RenderPresent(renderer);
2409 }
2410
2411 void
2412 SDL_DestroyTexture(SDL_Texture * texture)
2413 {
2414 SDL_Renderer *renderer;
2415
2416 CHECK_TEXTURE_MAGIC(texture, );
2417 texture->magic = NULL;
2418
2419 renderer = texture->renderer;
2420 if (texture->next) {
2421 texture->next->prev = texture->prev;
2422 }
2423 if (texture->prev) {
2424 texture->prev->next = texture->next;
2425 } else {
2426 renderer->textures = texture->next;
2427 }
2428
2429 renderer->DestroyTexture(renderer, texture);
2430 SDL_free(texture);
2431 }
2432
2433 void
2434 SDL_DestroyRenderer(SDL_Renderer * renderer)
2435 {
2436 CHECK_RENDERER_MAGIC(renderer, );
2437
2438 SDL_DelEventWatch(SDL_RendererEventWatch, renderer);
2439
2440 /* Free existing textures for this renderer */
2441 while (renderer->textures) {
2442 SDL_DestroyTexture(renderer->textures);
2443 }
2444
2445 /* It's no longer magical... */
2446 renderer->magic = NULL;
2447
2448 /* Free the renderer instance */
2449 renderer->DestroyRenderer(renderer);
2450 }
2451
2452 SDL_bool 1327 SDL_bool
2453 SDL_IsScreenSaverEnabled() 1328 SDL_IsScreenSaverEnabled()
2454 { 1329 {
2455 if (!_this) { 1330 if (!_this) {
2456 return SDL_TRUE; 1331 return SDL_TRUE;
2509 for (i = _this->num_displays; i--;) { 1384 for (i = _this->num_displays; i--;) {
2510 SDL_VideoDisplay *display = &_this->displays[i]; 1385 SDL_VideoDisplay *display = &_this->displays[i];
2511 while (display->windows) { 1386 while (display->windows) {
2512 SDL_DestroyWindow(display->windows); 1387 SDL_DestroyWindow(display->windows);
2513 } 1388 }
2514 if (display->render_drivers) {
2515 SDL_free(display->render_drivers);
2516 display->render_drivers = NULL;
2517 }
2518 display->num_render_drivers = 0;
2519 } 1389 }
2520 _this->VideoQuit(_this); 1390 _this->VideoQuit(_this);
2521 1391
2522 for (i = _this->num_displays; i--;) { 1392 for (i = _this->num_displays; i--;) {
2523 SDL_VideoDisplay *display = &_this->displays[i]; 1393 SDL_VideoDisplay *display = &_this->displays[i];