Commit 9c126183 authored by Sam Lantinga's avatar Sam Lantinga

Removed partially functional renderers

--HG--
extra : rebase_source : 3fc2560c02393bf9e7c46360fc24f2585c9409be
parent 886e9476
...@@ -855,14 +855,6 @@ ...@@ -855,14 +855,6 @@
RelativePath="..\..\src\video\SDL_gamma.c" RelativePath="..\..\src\video\SDL_gamma.c"
> >
</File> </File>
<File
RelativePath="..\..\src\video\windows\SDL_gdirender.c"
>
</File>
<File
RelativePath="..\..\src\video\windows\SDL_gdirender.h"
>
</File>
<File <File
RelativePath="..\..\src\events\SDL_gesture.c" RelativePath="..\..\src\events\SDL_gesture.c"
> >
......
...@@ -842,14 +842,6 @@ ...@@ -842,14 +842,6 @@
RelativePath="..\..\src\video\SDL_gamma.c" RelativePath="..\..\src\video\SDL_gamma.c"
> >
</File> </File>
<File
RelativePath="..\..\src\video\windows\SDL_gdirender.c"
>
</File>
<File
RelativePath="..\..\src\video\windows\SDL_gdirender.h"
>
</File>
<File <File
RelativePath="..\..\src\events\SDL_gesture.c" RelativePath="..\..\src\events\SDL_gesture.c"
> >
......
...@@ -296,7 +296,6 @@ echo #define SDL_REVISION "hg-0:baadf00d" &gt;"$(ProjectDir)\..\..\include\SDL_r ...@@ -296,7 +296,6 @@ echo #define SDL_REVISION "hg-0:baadf00d" &gt;"$(ProjectDir)\..\..\include\SDL_r
<ClInclude Include="..\..\src\SDL_error_c.h" /> <ClInclude Include="..\..\src\SDL_error_c.h" />
<ClInclude Include="..\..\src\events\SDL_events_c.h" /> <ClInclude Include="..\..\src\events\SDL_events_c.h" />
<ClInclude Include="..\..\src\SDL_fatal.h" /> <ClInclude Include="..\..\src\SDL_fatal.h" />
<ClInclude Include="..\..\src\video\windows\SDL_gdirender.h" />
<ClInclude Include="..\..\src\video\SDL_glesfuncs.h" /> <ClInclude Include="..\..\src\video\SDL_glesfuncs.h" />
<ClInclude Include="..\..\src\video\SDL_glfuncs.h" /> <ClInclude Include="..\..\src\video\SDL_glfuncs.h" />
<ClInclude Include="..\..\src\joystick\SDL_joystick_c.h" /> <ClInclude Include="..\..\src\joystick\SDL_joystick_c.h" />
...@@ -401,7 +400,6 @@ echo #define SDL_REVISION "hg-0:baadf00d" &gt;"$(ProjectDir)\..\..\include\SDL_r ...@@ -401,7 +400,6 @@ echo #define SDL_REVISION "hg-0:baadf00d" &gt;"$(ProjectDir)\..\..\include\SDL_r
<ClCompile Include="..\..\src\SDL_fatal.c" /> <ClCompile Include="..\..\src\SDL_fatal.c" />
<ClCompile Include="..\..\src\video\SDL_fillrect.c" /> <ClCompile Include="..\..\src\video\SDL_fillrect.c" />
<ClCompile Include="..\..\src\video\SDL_gamma.c" /> <ClCompile Include="..\..\src\video\SDL_gamma.c" />
<ClCompile Include="..\..\src\video\windows\SDL_gdirender.c" />
<ClCompile Include="..\..\src\stdlib\SDL_getenv.c" /> <ClCompile Include="..\..\src\stdlib\SDL_getenv.c" />
<ClCompile Include="..\..\src\haptic\SDL_haptic.c" /> <ClCompile Include="..\..\src\haptic\SDL_haptic.c" />
<ClCompile Include="..\..\src\stdlib\SDL_iconv.c" /> <ClCompile Include="..\..\src\stdlib\SDL_iconv.c" />
......
...@@ -1322,12 +1322,6 @@ AC_HELP_STRING([--enable-video-x11-xdamage-xfixes], [enable X11 Xdamage and Xfix ...@@ -1322,12 +1322,6 @@ AC_HELP_STRING([--enable-video-x11-xdamage-xfixes], [enable X11 Xdamage and Xfix
AC_DEFINE(SDL_VIDEO_DRIVER_X11_XDAMAGE) AC_DEFINE(SDL_VIDEO_DRIVER_X11_XDAMAGE)
AC_DEFINE(SDL_VIDEO_DRIVER_X11_XFIXES) AC_DEFINE(SDL_VIDEO_DRIVER_X11_XFIXES)
fi fi
AC_ARG_ENABLE(render-x11,
AC_HELP_STRING([--enable-render-x11], [enable the X11 render driver [[default=yes]]]),
, enable_render_x11=yes)
if test x$enable_render_x11 = xyes; then
AC_DEFINE(SDL_VIDEO_RENDER_X11)
fi
fi fi
fi fi
} }
...@@ -2351,12 +2345,6 @@ case "$host" in ...@@ -2351,12 +2345,6 @@ case "$host" in
AC_DEFINE(SDL_VIDEO_DRIVER_WINDOWS) AC_DEFINE(SDL_VIDEO_DRIVER_WINDOWS)
SOURCES="$SOURCES $srcdir/src/video/windows/*.c" SOURCES="$SOURCES $srcdir/src/video/windows/*.c"
have_video=yes have_video=yes
AC_ARG_ENABLE(render-gdi,
AC_HELP_STRING([--enable-render-gdi], [enable the GDI render driver [[default=yes]]]),
, enable_render_gdi=yes)
if test x$enable_render_gdi = xyes; then
AC_DEFINE(SDL_VIDEO_RENDER_GDI)
fi
AC_ARG_ENABLE(render-gapi, AC_ARG_ENABLE(render-gapi,
AC_HELP_STRING([--enable-render-gapi], [enable the GAPI/RAWFRAMEBUFFER render driver [[default=yes]]]), AC_HELP_STRING([--enable-render-gapi], [enable the GAPI/RAWFRAMEBUFFER render driver [[default=yes]]]),
, enable_render_gapi=yes) , enable_render_gapi=yes)
...@@ -2457,12 +2445,6 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau ...@@ -2457,12 +2445,6 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
AC_DEFINE(SDL_VIDEO_DRIVER_WINDOWS) AC_DEFINE(SDL_VIDEO_DRIVER_WINDOWS)
SOURCES="$SOURCES $srcdir/src/video/windows/*.c" SOURCES="$SOURCES $srcdir/src/video/windows/*.c"
have_video=yes have_video=yes
AC_ARG_ENABLE(render-gdi,
AC_HELP_STRING([--enable-render-gdi], [enable the GDI render driver [[default=yes]]]),
, enable_render_gdi=yes)
if test x$enable_render_gdi = xyes; then
AC_DEFINE(SDL_VIDEO_RENDER_GDI)
fi
AC_ARG_ENABLE(render-d3d, AC_ARG_ENABLE(render-d3d,
AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[default=yes]]]), AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[default=yes]]]),
, enable_render_d3d=yes) , enable_render_d3d=yes)
......
...@@ -285,10 +285,8 @@ ...@@ -285,10 +285,8 @@
#undef SDL_VIDEO_DRIVER_X11_XSHAPE #undef SDL_VIDEO_DRIVER_X11_XSHAPE
#undef SDL_VIDEO_RENDER_D3D #undef SDL_VIDEO_RENDER_D3D
#undef SDL_VIDEO_RENDER_GDI
#undef SDL_VIDEO_RENDER_OGL #undef SDL_VIDEO_RENDER_OGL
#undef SDL_VIDEO_RENDER_OGL_ES #undef SDL_VIDEO_RENDER_OGL_ES
#undef SDL_VIDEO_RENDER_X11
#undef SDL_VIDEO_RENDER_GAPI #undef SDL_VIDEO_RENDER_GAPI
#undef SDL_VIDEO_RENDER_DDRAW #undef SDL_VIDEO_RENDER_DDRAW
......
...@@ -151,9 +151,6 @@ ...@@ -151,9 +151,6 @@
#ifndef SDL_VIDEO_RENDER_OGL #ifndef SDL_VIDEO_RENDER_OGL
#define SDL_VIDEO_RENDER_OGL 1 #define SDL_VIDEO_RENDER_OGL 1
#endif #endif
#ifndef SDL_VIDEO_RENDER_X11
#define SDL_VIDEO_RENDER_X11 1
#endif
/* Enable OpenGL support */ /* Enable OpenGL support */
#ifndef SDL_VIDEO_OPENGL #ifndef SDL_VIDEO_OPENGL
......
...@@ -187,9 +187,6 @@ typedef unsigned int uintptr_t; ...@@ -187,9 +187,6 @@ typedef unsigned int uintptr_t;
#define SDL_VIDEO_RENDER_D3D 1 #define SDL_VIDEO_RENDER_D3D 1
#endif #endif
#endif #endif
#ifndef SDL_VIDEO_RENDER_GDI
#define SDL_VIDEO_RENDER_GDI 1
#endif
/* Enable OpenGL support */ /* Enable OpenGL support */
#ifndef _WIN32_WCE #ifndef _WIN32_WCE
......
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
#if SDL_VIDEO_RENDER_GDI
#include "SDL_windowsvideo.h"
#include "../SDL_rect_c.h"
#include "../SDL_yuv_sw_c.h"
#include "../SDL_alphamult.h"
#ifdef _WIN32_WCE
#define NO_GETDIBBITS 1
#endif
/* GDI renderer implementation */
static SDL_Renderer *GDI_CreateRenderer(SDL_Window * window, Uint32 flags);
static int GDI_DisplayModeChanged(SDL_Renderer * renderer);
static int GDI_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
static int GDI_QueryTexturePixels(SDL_Renderer * renderer,
SDL_Texture * texture, void **pixels,
int *pitch);
static int GDI_SetTexturePalette(SDL_Renderer * renderer,
SDL_Texture * texture,
const SDL_Color * colors, int firstcolor,
int ncolors);
static int GDI_GetTexturePalette(SDL_Renderer * renderer,
SDL_Texture * texture, SDL_Color * colors,
int firstcolor, int ncolors);
static int GDI_SetTextureAlphaMod(SDL_Renderer * renderer,
SDL_Texture * texture);
static int GDI_SetTextureBlendMode(SDL_Renderer * renderer,
SDL_Texture * texture);
static int GDI_SetTextureScaleMode(SDL_Renderer * renderer,
SDL_Texture * texture);
static int GDI_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, const void *pixels,
int pitch);
static int GDI_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, int markDirty,
void **pixels, int *pitch);
static void GDI_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
static int GDI_SetDrawBlendMode(SDL_Renderer * renderer);
static int GDI_RenderDrawPoints(SDL_Renderer * renderer,
const SDL_Point * points, int count);
static int GDI_RenderDrawLines(SDL_Renderer * renderer,
const SDL_Point * points, int count);
static int GDI_RenderDrawRects(SDL_Renderer * renderer,
const SDL_Rect ** rects, int count);
static int GDI_RenderFillRects(SDL_Renderer * renderer,
const SDL_Rect ** rects, int count);
static int GDI_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_Rect * dstrect);
static int GDI_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
Uint32 format, void * pixels, int pitch);
static int GDI_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
Uint32 format, const void * pixels, int pitch);
static void GDI_RenderPresent(SDL_Renderer * renderer);
static void GDI_DestroyTexture(SDL_Renderer * renderer,
SDL_Texture * texture);
static void GDI_DestroyRenderer(SDL_Renderer * renderer);
SDL_RenderDriver GDI_RenderDriver = {
GDI_CreateRenderer,
{
"gdi",
(SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY |
SDL_RENDERER_PRESENTFLIP2 | SDL_RENDERER_PRESENTFLIP3 |
SDL_RENDERER_PRESENTDISCARD | SDL_RENDERER_ACCELERATED),
(SDL_TEXTUREMODULATE_NONE | SDL_TEXTUREMODULATE_ALPHA),
(SDL_BLENDMODE_NONE | SDL_BLENDMODE_MASK),
(SDL_SCALEMODE_NONE | SDL_SCALEMODE_FAST),
14,
{
SDL_PIXELFORMAT_INDEX8,
SDL_PIXELFORMAT_RGB555,
SDL_PIXELFORMAT_RGB565,
SDL_PIXELFORMAT_RGB888,
SDL_PIXELFORMAT_BGR888,
SDL_PIXELFORMAT_ARGB8888,
SDL_PIXELFORMAT_RGBA8888,
SDL_PIXELFORMAT_ABGR8888,
SDL_PIXELFORMAT_BGRA8888,
SDL_PIXELFORMAT_YV12,
SDL_PIXELFORMAT_IYUV,
SDL_PIXELFORMAT_YUY2,
SDL_PIXELFORMAT_UYVY,
SDL_PIXELFORMAT_YVYU},
0,
0}
};
typedef struct
{
HWND hwnd;
HDC window_hdc;
HDC render_hdc;
HDC memory_hdc;
HDC current_hdc;
#ifndef NO_GETDIBBITS
LPBITMAPINFO bmi;
#endif
HBITMAP hbm[3];
int current_hbm;
SDL_DirtyRectList dirty;
SDL_bool makedirty;
} GDI_RenderData;
typedef struct
{
SDL_SW_YUVTexture *yuv;
Uint32 format;
HPALETTE hpal;
HBITMAP hbm;
void *pixels;
int pitch;
SDL_bool premultiplied;
} GDI_TextureData;
static void
UpdateYUVTextureData(SDL_Texture * texture)
{
GDI_TextureData *data = (GDI_TextureData *) texture->driverdata;
SDL_Rect rect;
rect.x = 0;
rect.y = 0;
rect.w = texture->w;
rect.h = texture->h;
SDL_SW_CopyYUVToRGB(data->yuv, &rect, data->format, texture->w,
texture->h, data->pixels, data->pitch);
}
void
GDI_AddRenderDriver(_THIS)
{
int i;
for (i = 0; i < _this->num_displays; ++i) {
SDL_AddRenderDriver(&_this->displays[i], &GDI_RenderDriver);
}
}
SDL_Renderer *
GDI_CreateRenderer(SDL_Window * window, Uint32 flags)
{
SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata;
SDL_Renderer *renderer;
GDI_RenderData *data;
#ifndef NO_GETDIBBITS
int bmi_size;
HBITMAP hbm;
#endif
int i, n;
renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
if (!renderer) {
SDL_OutOfMemory();
return NULL;
}
data = (GDI_RenderData *) SDL_calloc(1, sizeof(*data));
if (!data) {
GDI_DestroyRenderer(renderer);
SDL_OutOfMemory();
return NULL;
}
windowdata->videodata->render = RENDER_GDI;
renderer->DisplayModeChanged = GDI_DisplayModeChanged;
renderer->CreateTexture = GDI_CreateTexture;
renderer->QueryTexturePixels = GDI_QueryTexturePixels;
renderer->SetTexturePalette = GDI_SetTexturePalette;
renderer->GetTexturePalette = GDI_GetTexturePalette;
renderer->SetTextureAlphaMod = GDI_SetTextureAlphaMod;
renderer->SetTextureBlendMode = GDI_SetTextureBlendMode;
renderer->SetTextureScaleMode = GDI_SetTextureScaleMode;
renderer->UpdateTexture = GDI_UpdateTexture;
renderer->LockTexture = GDI_LockTexture;
renderer->UnlockTexture = GDI_UnlockTexture;
renderer->SetDrawBlendMode = GDI_SetDrawBlendMode;
renderer->RenderDrawPoints = GDI_RenderDrawPoints;
renderer->RenderDrawLines = GDI_RenderDrawLines;
renderer->RenderDrawRects = GDI_RenderDrawRects;
renderer->RenderFillRects = GDI_RenderFillRects;
renderer->RenderCopy = GDI_RenderCopy;
renderer->RenderReadPixels = GDI_RenderReadPixels;
renderer->RenderWritePixels = GDI_RenderWritePixels;
renderer->RenderPresent = GDI_RenderPresent;
renderer->DestroyTexture = GDI_DestroyTexture;
renderer->DestroyRenderer = GDI_DestroyRenderer;
renderer->info = GDI_RenderDriver.info;
renderer->window = window;
renderer->driverdata = data;
renderer->info.flags = SDL_RENDERER_ACCELERATED;
data->hwnd = windowdata->hwnd;
data->window_hdc = windowdata->hdc;
data->render_hdc = CreateCompatibleDC(data->window_hdc);
data->memory_hdc = CreateCompatibleDC(data->window_hdc);
#ifndef NO_GETDIBBITS
/* Fill in the compatible bitmap info */
bmi_size = sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
data->bmi = (LPBITMAPINFO) SDL_calloc(1, bmi_size);
if (!data->bmi) {
GDI_DestroyRenderer(renderer);
SDL_OutOfMemory();
return NULL;
}
data->bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
hbm = CreateCompatibleBitmap(data->window_hdc, 1, 1);
GetDIBits(data->window_hdc, hbm, 0, 1, NULL, data->bmi, DIB_RGB_COLORS);
GetDIBits(data->window_hdc, hbm, 0, 1, NULL, data->bmi, DIB_RGB_COLORS);
DeleteObject(hbm);
#endif
if (flags & SDL_RENDERER_SINGLEBUFFER) {
renderer->info.flags |=
(SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY);
n = 0;
} else if (flags & SDL_RENDERER_PRESENTFLIP2) {
renderer->info.flags |= SDL_RENDERER_PRESENTFLIP2;
n = 2;
} else if (flags & SDL_RENDERER_PRESENTFLIP3) {
renderer->info.flags |= SDL_RENDERER_PRESENTFLIP3;
n = 3;
} else {
renderer->info.flags |= SDL_RENDERER_PRESENTCOPY;
n = 1;
}
for (i = 0; i < n; ++i) {
data->hbm[i] =
CreateCompatibleBitmap(data->window_hdc, window->w, window->h);
if (!data->hbm[i]) {
GDI_DestroyRenderer(renderer);
WIN_SetError("CreateCompatibleBitmap()");
return NULL;
}
}
if (n > 0) {
SelectObject(data->render_hdc, data->hbm[0]);
data->current_hdc = data->render_hdc;
data->makedirty = SDL_TRUE;
} else {
data->current_hdc = data->window_hdc;
data->makedirty = SDL_FALSE;
}
data->current_hbm = 0;
#ifdef _WIN32_WCE
// check size for GDI fullscreen and rotate
if((window->flags & SDL_WINDOW_FULLSCREEN) &&
GetSystemMetrics(SM_CXSCREEN) != GetSystemMetrics(SM_CYSCREEN) &&
((GetSystemMetrics(SM_CXSCREEN) < GetSystemMetrics(SM_CYSCREEN) && window->w > window->h) ||
(GetSystemMetrics(SM_CXSCREEN) > GetSystemMetrics(SM_CYSCREEN) && window->w < window->h)))
{
int orientation = WINCE_GetDMOrientation();
switch(orientation)
{
case DMDO_0: orientation = DMDO_90; break;
case DMDO_270: orientation = DMDO_180; break;
case DMDO_90: orientation = DMDO_0; break;
case DMDO_180: orientation = DMDO_270; break;
default:
GDI_DestroyRenderer(renderer);
return NULL;
}
if(0 > WINCE_SetDMOrientation(orientation))
{
GDI_DestroyRenderer(renderer);
return NULL;
}
}
#endif
return renderer;
}
static int
GDI_DisplayModeChanged(SDL_Renderer * renderer)
{
GDI_RenderData *data = (GDI_RenderData *) renderer->driverdata;
SDL_Window *window = renderer->window;
int i, n;
if (renderer->info.flags & SDL_RENDERER_SINGLEBUFFER) {
n = 0;
} else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) {
n = 2;
} else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP3) {
n = 3;
} else {
n = 1;
}
for (i = 0; i < n; ++i) {
if (data->hbm[i]) {
DeleteObject(data->hbm[i]);
data->hbm[i] = NULL;
}
}
for (i = 0; i < n; ++i) {
data->hbm[i] =
CreateCompatibleBitmap(data->window_hdc, window->w, window->h);
if (!data->hbm[i]) {
WIN_SetError("CreateCompatibleBitmap()");
return -1;
}
}
if (n > 0) {
SelectObject(data->render_hdc, data->hbm[0]);
}
data->current_hbm = 0;
return 0;
}
static HBITMAP
GDI_CreateDIBSection(HDC hdc, int w, int h, int pitch, Uint32 format,
HPALETTE * hpal, void ** pixels)
{
int bmi_size;
LPBITMAPINFO bmi;
bmi_size = sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
bmi = (LPBITMAPINFO) SDL_calloc(1, bmi_size);
if (!bmi) {
SDL_OutOfMemory();
return NULL;
}
bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi->bmiHeader.biWidth = w;
bmi->bmiHeader.biHeight = -h; /* topdown bitmap */
bmi->bmiHeader.biPlanes = 1;
bmi->bmiHeader.biSizeImage = h * pitch;
bmi->bmiHeader.biXPelsPerMeter = 0;
bmi->bmiHeader.biYPelsPerMeter = 0;
bmi->bmiHeader.biClrUsed = 0;
bmi->bmiHeader.biClrImportant = 0;
bmi->bmiHeader.biBitCount = SDL_BYTESPERPIXEL(format) * 8;
if (SDL_ISPIXELFORMAT_INDEXED(format)) {
bmi->bmiHeader.biCompression = BI_RGB;
if (hpal) {
int i, ncolors;
LOGPALETTE *palette;
ncolors = (1 << SDL_BITSPERPIXEL(format));
palette =
(LOGPALETTE *) SDL_malloc(sizeof(*palette) +
ncolors * sizeof(PALETTEENTRY));
if (!palette) {
SDL_free(bmi);
SDL_OutOfMemory();
return NULL;
}
palette->palVersion = 0x300;
palette->palNumEntries = ncolors;
for (i = 0; i < ncolors; ++i) {
palette->palPalEntry[i].peRed = 0xFF;
palette->palPalEntry[i].peGreen = 0xFF;
palette->palPalEntry[i].peBlue = 0xFF;
palette->palPalEntry[i].peFlags = 0;
}
*hpal = CreatePalette(palette);
SDL_free(palette);
}
} else {
int bpp;
Uint32 Rmask, Gmask, Bmask, Amask;
bmi->bmiHeader.biCompression = BI_BITFIELDS;
SDL_PixelFormatEnumToMasks(format, &bpp, &Rmask, &Gmask, &Bmask,
&Amask);
((Uint32 *) bmi->bmiColors)[0] = Rmask;
((Uint32 *) bmi->bmiColors)[1] = Gmask;
((Uint32 *) bmi->bmiColors)[2] = Bmask;
if (hpal) {
*hpal = NULL;
}
}
return CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, pixels, NULL, 0);
}
static int
GDI_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
{
GDI_RenderData *renderdata = (GDI_RenderData *) renderer->driverdata;
SDL_Window *window = renderer->window;
SDL_VideoDisplay *display = window->display;
GDI_TextureData *data;
data = (GDI_TextureData *) SDL_calloc(1, sizeof(*data));
if (!data) {
SDL_OutOfMemory();
return -1;
}
texture->driverdata = data;
if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
data->yuv =
SDL_SW_CreateYUVTexture(texture->format, texture->w, texture->h);
if (!data->yuv) {
return -1;
}
data->format = display->current_mode.format;
} else {
data->format = texture->format;
}
data->pitch = (texture->w * SDL_BYTESPERPIXEL(data->format));
if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING
|| texture->format != display->current_mode.format) {
data->hbm = GDI_CreateDIBSection(renderdata->memory_hdc,
texture->w, texture->h,
data->pitch, data->format,
&data->hpal, &data->pixels);
} else {
data->hbm = CreateCompatibleBitmap(renderdata->window_hdc,
texture->w, texture->h);
}
if (!data->hbm) {
WIN_SetError("Couldn't create bitmap");
return -1;
}
return 0;
}
static int
GDI_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
void **pixels, int *pitch)
{
GDI_TextureData *data = (GDI_TextureData *) texture->driverdata;
if (data->yuv) {
return SDL_SW_QueryYUVTexturePixels(data->yuv, pixels, pitch);
} else {
*pixels = data->pixels;
*pitch = data->pitch;
return 0;
}
}
static int
GDI_SetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Color * colors, int firstcolor, int ncolors)
{
GDI_RenderData *renderdata = (GDI_RenderData *) renderer->driverdata;
GDI_TextureData *data = (GDI_TextureData *) texture->driverdata;
if (data->yuv) {
SDL_SetError("YUV textures don't have a palette");
return -1;
} else {
PALETTEENTRY entries[256];
int i;
for (i = 0; i < ncolors; ++i) {
entries[i].peRed = colors[i].r;
entries[i].peGreen = colors[i].g;
entries[i].peBlue = colors[i].b;
entries[i].peFlags = 0;
}
if (!SetPaletteEntries(data->hpal, firstcolor, ncolors, entries)) {
WIN_SetError("SetPaletteEntries()");
return -1;
}
return 0;
}
}
static int
GDI_GetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
SDL_Color * colors, int firstcolor, int ncolors)
{
GDI_TextureData *data = (GDI_TextureData *) texture->driverdata;
if (data->yuv) {
SDL_SetError("YUV textures don't have a palette");
return -1;
} else {
PALETTEENTRY entries[256];
int i;
if (!GetPaletteEntries(data->hpal, firstcolor, ncolors, entries)) {
WIN_SetError("GetPaletteEntries()");
return -1;
}
for (i = 0; i < ncolors; ++i) {
colors[i].r = entries[i].peRed;
colors[i].g = entries[i].peGreen;
colors[i].b = entries[i].peBlue;
}
return 0;
}
}
static int
GDI_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
{
return 0;
}
static int
GDI_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
{
GDI_TextureData *data = (GDI_TextureData *) texture->driverdata;
switch (texture->blendMode) {
case SDL_BLENDMODE_NONE:
if (data->premultiplied) {
/* Crap, we've lost the original pixel data... *sigh* */
}
return 0;
#ifndef _WIN32_WCE /* WinCE has no alphablend */
case SDL_BLENDMODE_MASK:
case SDL_BLENDMODE_BLEND:
if (!data->premultiplied && data->pixels) {
switch (texture->format) {
case SDL_PIXELFORMAT_ARGB8888:
SDL_PreMultiplyAlphaARGB8888(texture->w, texture->h,
(Uint32 *) data->pixels,
data->pitch);
data->premultiplied = SDL_TRUE;
break;
case SDL_PIXELFORMAT_RGBA8888:
SDL_PreMultiplyAlphaRGBA8888(texture->w, texture->h,
(Uint32 *) data->pixels,
data->pitch);
data->premultiplied = SDL_TRUE;
break;
case SDL_PIXELFORMAT_ABGR8888:
SDL_PreMultiplyAlphaABGR8888(texture->w, texture->h,
(Uint32 *) data->pixels,
data->pitch);
data->premultiplied = SDL_TRUE;
break;
case SDL_PIXELFORMAT_BGRA8888:
SDL_PreMultiplyAlphaBGRA8888(texture->w, texture->h,
(Uint32 *) data->pixels,
data->pitch);
data->premultiplied = SDL_TRUE;
break;
}
}
return 0;
#endif
default:
SDL_Unsupported();
texture->blendMode = SDL_BLENDMODE_NONE;
return -1;
}
}
static int
GDI_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture)
{
switch (texture->scaleMode) {
case SDL_SCALEMODE_NONE:
case SDL_SCALEMODE_FAST:
return 0;
case SDL_SCALEMODE_SLOW:
case SDL_SCALEMODE_BEST:
SDL_Unsupported();
texture->scaleMode = SDL_SCALEMODE_FAST;
return -1;
default:
SDL_Unsupported();
texture->scaleMode = SDL_SCALEMODE_NONE;
return -1;
}
return 0;
}
static int
GDI_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, const void *pixels, int pitch)
{
GDI_TextureData *data = (GDI_TextureData *) texture->driverdata;
if (data->yuv) {
if (SDL_SW_UpdateYUVTexture(data->yuv, rect, pixels, pitch) < 0) {
return -1;
}
UpdateYUVTextureData(texture);
return 0;
} else {
GDI_RenderData *renderdata = (GDI_RenderData *) renderer->driverdata;
if (data->pixels) {
Uint8 *src, *dst;
int row;
size_t length;
src = (Uint8 *) pixels;
dst =
(Uint8 *) data->pixels + rect->y * data->pitch +
rect->x * SDL_BYTESPERPIXEL(texture->format);
length = rect->w * SDL_BYTESPERPIXEL(texture->format);
for (row = 0; row < rect->h; ++row) {
SDL_memcpy(dst, src, length);
src += pitch;
dst += data->pitch;
}
if (data->premultiplied) {
Uint32 *pixels =
(Uint32 *) data->pixels + rect->y * (data->pitch / 4) +
rect->x;
switch (texture->format) {
case SDL_PIXELFORMAT_ARGB8888:
SDL_PreMultiplyAlphaARGB8888(rect->w, rect->h, pixels,
data->pitch);
break;
case SDL_PIXELFORMAT_RGBA8888:
SDL_PreMultiplyAlphaRGBA8888(rect->w, rect->h, pixels,
data->pitch);
break;
case SDL_PIXELFORMAT_ABGR8888:
SDL_PreMultiplyAlphaABGR8888(rect->w, rect->h, pixels,
data->pitch);
break;
case SDL_PIXELFORMAT_BGRA8888:
SDL_PreMultiplyAlphaBGRA8888(rect->w, rect->h, pixels,
data->pitch);
break;
}
}
} else if (rect->w == texture->w && pitch == data->pitch) {
#ifndef NO_GETDIBBITS
if (!SetDIBits
(renderdata->window_hdc, data->hbm, rect->y, rect->h, pixels,
renderdata->bmi, DIB_RGB_COLORS)) {
WIN_SetError("SetDIBits()");
return -1;
}
#else
SDL_SetError("FIXME: Update Texture");
return -1;
#endif
} else {
SDL_SetError
("FIXME: Need to allocate temporary memory and do GetDIBits() followed by SetDIBits(), since we can only set blocks of scanlines at a time");
return -1;
}
return 0;
}
}
static int
GDI_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, int markDirty, void **pixels,
int *pitch)
{
GDI_TextureData *data = (GDI_TextureData *) texture->driverdata;
if (data->yuv) {
return SDL_SW_LockYUVTexture(data->yuv, rect, markDirty, pixels,
pitch);
} else if (data->pixels) {
#ifndef _WIN32_WCE
/* WinCE has no GdiFlush */
GdiFlush();
#endif
*pixels =
(void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
rect->x * SDL_BYTESPERPIXEL(texture->format));
*pitch = data->pitch;
return 0;
} else {
SDL_SetError("No pixels available");
return -1;
}
}
static void
GDI_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
{
GDI_TextureData *data = (GDI_TextureData *) texture->driverdata;
if (data->yuv) {
SDL_SW_UnlockYUVTexture(data->yuv);
UpdateYUVTextureData(texture);
}
}
static int
GDI_SetDrawBlendMode(SDL_Renderer * renderer)
{
switch (renderer->blendMode) {
case SDL_BLENDMODE_NONE:
return 0;
default:
SDL_Unsupported();
renderer->blendMode = SDL_BLENDMODE_NONE;
return -1;
}
}
static int
GDI_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points,
int count)
{
GDI_RenderData *data = (GDI_RenderData *) renderer->driverdata;
int i;
COLORREF color;
if (data->makedirty) {
/* Get the smallest rectangle that contains everything */
SDL_Window *window = renderer->window;
SDL_Rect rect;
rect.x = 0;
rect.y = 0;
rect.w = window->w;
rect.h = window->h;
if (!SDL_EnclosePoints(points, count, &rect, &rect)) {
/* Nothing to draw */
return 0;
}
SDL_AddDirtyRect(&data->dirty, &rect);
}
color = RGB(renderer->r, renderer->g, renderer->b);
for (i = 0; i < count; ++i) {
SetPixel(data->current_hdc, points[i].x, points[i].y, color);
}
return 0;
}
static int
GDI_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points,
int count)
{
GDI_RenderData *data = (GDI_RenderData *) renderer->driverdata;
HPEN pen;
BOOL status;
if (data->makedirty) {
/* Get the smallest rectangle that contains everything */
SDL_Window *window = renderer->window;
SDL_Rect clip, rect;
clip.x = 0;
clip.y = 0;
clip.w = window->w;
clip.h = window->h;
SDL_EnclosePoints(points, count, NULL, &rect);
if (!SDL_IntersectRect(&rect, &clip, &rect)) {
/* Nothing to draw */
return 0;
}
SDL_AddDirtyRect(&data->dirty, &rect);
}
/* Should we cache the pen? .. it looks like GDI does for us. :) */
pen = CreatePen(PS_SOLID, 1, RGB(renderer->r, renderer->g, renderer->b));
SelectObject(data->current_hdc, pen);
{
LPPOINT p = SDL_stack_alloc(POINT, count);
int i;
for (i = 0; i < count; ++i) {
p[i].x = points[i].x;
p[i].y = points[i].y;
}
status = Polyline(data->current_hdc, p, count);
SDL_stack_free(p);
}
DeleteObject(pen);
/* Need to close the endpoint of the line */
if (points[0].x != points[count-1].x || points[0].y != points[count-1].y) {
SetPixel(data->current_hdc, points[count-1].x, points[count-1].y,
RGB(renderer->r, renderer->g, renderer->b));
}
if (!status) {
WIN_SetError("Polyline()");
return -1;
}
return 0;
}
static int
GDI_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects,
int count)
{
GDI_RenderData *data = (GDI_RenderData *) renderer->driverdata;
HPEN pen;
POINT vertices[5];
int i, status = 1;
if (data->makedirty) {
SDL_Window *window = renderer->window;
SDL_Rect clip, rect;
clip.x = 0;
clip.y = 0;
clip.w = window->w;
clip.h = window->h;
for (i = 0; i < count; ++i) {
if (SDL_IntersectRect(rects[i], &clip, &rect)) {
SDL_AddDirtyRect(&data->dirty, &rect);
}
}
}
/* Should we cache the pen? .. it looks like GDI does for us. :) */
pen = CreatePen(PS_SOLID, 1, RGB(renderer->r, renderer->g, renderer->b));
SelectObject(data->current_hdc, pen);
for (i = 0; i < count; ++i) {
const SDL_Rect *rect = rects[i];
vertices[0].x = rect->x;
vertices[0].y = rect->y;
vertices[1].x = rect->x+rect->w-1;
vertices[1].y = rect->y;
vertices[2].x = rect->x+rect->w-1;
vertices[2].y = rect->y+rect->h-1;
vertices[3].x = rect->x;
vertices[3].y = rect->y+rect->h-1;
vertices[4].x = rect->x;
vertices[4].y = rect->y;
status &= Polyline(data->current_hdc, vertices, 5);
}
DeleteObject(pen);
if (!status) {
WIN_SetError("Polyline()");
return -1;
}
return 0;
}
static int
GDI_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects,
int count)
{
GDI_RenderData *data = (GDI_RenderData *) renderer->driverdata;
RECT rc;
HBRUSH brush;
int i, status = 1;
if (data->makedirty) {
SDL_Window *window = renderer->window;
SDL_Rect clip, rect;
clip.x = 0;
clip.y = 0;
clip.w = window->w;
clip.h = window->h;
for (i = 0; i < count; ++i) {
if (SDL_IntersectRect(rects[i], &clip, &rect)) {
SDL_AddDirtyRect(&data->dirty, &rect);
}
}
}
/* Should we cache the brushes? .. it looks like GDI does for us. :) */
brush = CreateSolidBrush(RGB(renderer->r, renderer->g, renderer->b));
SelectObject(data->current_hdc, brush);
for (i = 0; i < count; ++i) {
const SDL_Rect *rect = rects[i];
rc.left = rect->x;
rc.top = rect->y;
rc.right = rect->x + rect->w;
rc.bottom = rect->y + rect->h;
status &= FillRect(data->current_hdc, &rc, brush);
}
DeleteObject(brush);
if (!status) {
WIN_SetError("FillRect()");
return -1;
}
return 0;
}
static int
GDI_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_Rect * dstrect)
{
GDI_RenderData *data = (GDI_RenderData *) renderer->driverdata;
GDI_TextureData *texturedata = (GDI_TextureData *) texture->driverdata;
if (data->makedirty) {
SDL_AddDirtyRect(&data->dirty, dstrect);
}
SelectObject(data->memory_hdc, texturedata->hbm);
if (texturedata->hpal) {
SelectPalette(data->memory_hdc, texturedata->hpal, TRUE);
RealizePalette(data->memory_hdc);
}
if (texture->blendMode & (SDL_BLENDMODE_MASK | SDL_BLENDMODE_BLEND)) {
#ifdef _WIN32_WCE
SDL_SetError("Texture has blendmode not supported under WinCE");
return -1;
#else
BLENDFUNCTION blendFunc = {
AC_SRC_OVER,
0,
texture->a,
AC_SRC_ALPHA
};
if (!AlphaBlend
(data->current_hdc, dstrect->x, dstrect->y, dstrect->w,
dstrect->h, data->memory_hdc, srcrect->x, srcrect->y, srcrect->w,
srcrect->h, blendFunc)) {
WIN_SetError("AlphaBlend()");
return -1;
}
#endif
} else {
if (srcrect->w == dstrect->w && srcrect->h == dstrect->h) {
if (!BitBlt
(data->current_hdc, dstrect->x, dstrect->y, dstrect->w,
srcrect->h, data->memory_hdc, srcrect->x, srcrect->y,
SRCCOPY)) {
WIN_SetError("BitBlt()");
return -1;
}
} else {
if (!StretchBlt
(data->current_hdc, dstrect->x, dstrect->y, dstrect->w,
dstrect->h, data->memory_hdc, srcrect->x, srcrect->y,
srcrect->w, srcrect->h, SRCCOPY)) {
WIN_SetError("StretchBlt()");
return -1;
}
}
}
return 0;
}
static int
GDI_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
Uint32 format, void * pixels, int pitch)
{
GDI_RenderData *renderdata = (GDI_RenderData *) renderer->driverdata;
SDL_Window *window = renderer->window;
SDL_VideoDisplay *display = window->display;
struct {
HBITMAP hbm;
void *pixels;
int pitch;
Uint32 format;
} data;
data.format = display->current_mode.format;
data.pitch = (rect->w * SDL_BYTESPERPIXEL(data.format));
data.hbm = GDI_CreateDIBSection(renderdata->memory_hdc, rect->w, rect->h,
data.pitch, data.format, NULL,
&data.pixels);
if (!data.hbm) {
WIN_SetError("Couldn't create bitmap");
return -1;
}
SelectObject(renderdata->memory_hdc, data.hbm);
if (!BitBlt(renderdata->memory_hdc, 0, 0, rect->w, rect->h,
renderdata->current_hdc, rect->x, rect->y, SRCCOPY)) {
WIN_SetError("BitBlt()");
DeleteObject(data.hbm);
return -1;
}
SDL_ConvertPixels(rect->w, rect->h,
data.format, data.pixels, data.pitch,
format, pixels, pitch);
DeleteObject(data.hbm);
return 0;
}
static int
GDI_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
Uint32 format, const void * pixels, int pitch)
{
GDI_RenderData *renderdata = (GDI_RenderData *) renderer->driverdata;
SDL_Window *window = renderer->window;
SDL_VideoDisplay *display = window->display;
struct {
HBITMAP hbm;
void *pixels;
int pitch;
Uint32 format;
} data;
data.format = display->current_mode.format;
data.pitch = (rect->w * SDL_BYTESPERPIXEL(data.format));
data.hbm = GDI_CreateDIBSection(renderdata->memory_hdc, rect->w, rect->h,
data.pitch, data.format,
NULL, &data.pixels);
if (!data.hbm) {
WIN_SetError("Couldn't create bitmap");
return -1;
}
SDL_ConvertPixels(rect->w, rect->h, format, pixels, pitch,
data.format, data.pixels, data.pitch);
SelectObject(renderdata->memory_hdc, data.hbm);
if (!BitBlt(renderdata->current_hdc, rect->x, rect->y, rect->w, rect->h,
renderdata->memory_hdc, 0, 0, SRCCOPY)) {
WIN_SetError("BitBlt()");
DeleteObject(data.hbm);
return -1;
}
DeleteObject(data.hbm);
return 0;
}
static void
GDI_RenderPresent(SDL_Renderer * renderer)
{
GDI_RenderData *data = (GDI_RenderData *) renderer->driverdata;
SDL_DirtyRect *dirty;
/* Send the data to the display */
if (!(renderer->info.flags & SDL_RENDERER_SINGLEBUFFER)) {
for (dirty = data->dirty.list; dirty; dirty = dirty->next) {
const SDL_Rect *rect = &dirty->rect;
BitBlt(data->window_hdc, rect->x, rect->y, rect->w, rect->h,
data->render_hdc, rect->x, rect->y, SRCCOPY);
}
SDL_ClearDirtyRects(&data->dirty);
}
/* Update the flipping chain, if any */
if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) {
data->current_hbm = (data->current_hbm + 1) % 2;
SelectObject(data->render_hdc, data->hbm[data->current_hbm]);
} else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP3) {
data->current_hbm = (data->current_hbm + 1) % 3;
SelectObject(data->render_hdc, data->hbm[data->current_hbm]);
}
}
static void
GDI_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
{
GDI_TextureData *data = (GDI_TextureData *) texture->driverdata;
if (!data) {
return;
}
if (data->yuv) {
SDL_SW_DestroyYUVTexture(data->yuv);
}
if (data->hpal) {
DeleteObject(data->hpal);
}
if (data->hbm) {
DeleteObject(data->hbm);
}
SDL_free(data);
texture->driverdata = NULL;
}
static void
GDI_DestroyRenderer(SDL_Renderer * renderer)
{
GDI_RenderData *data = (GDI_RenderData *) renderer->driverdata;
int i;
if (data) {
DeleteDC(data->render_hdc);
DeleteDC(data->memory_hdc);
#ifndef NO_GETDIBBITS
if (data->bmi) {
SDL_free(data->bmi);
}
#endif
for (i = 0; i < SDL_arraysize(data->hbm); ++i) {
if (data->hbm[i]) {
DeleteObject(data->hbm[i]);
}
}
SDL_FreeDirtyRects(&data->dirty);
SDL_free(data);
}
SDL_free(renderer);
}
#endif /* SDL_VIDEO_RENDER_GDI */
/* vi: set ts=4 sw=4 expandtab: */
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
/* SDL surface based renderer implementation */
#if SDL_VIDEO_RENDER_GDI
extern void GDI_AddRenderDriver(_THIS);
#endif
/* vi: set ts=4 sw=4 expandtab: */
...@@ -225,9 +225,6 @@ WIN_VideoInit(_THIS) ...@@ -225,9 +225,6 @@ WIN_VideoInit(_THIS)
#if SDL_VIDEO_RENDER_DDRAW #if SDL_VIDEO_RENDER_DDRAW
DDRAW_AddRenderDriver(_this); DDRAW_AddRenderDriver(_this);
#endif #endif
#if SDL_VIDEO_RENDER_GDI
GDI_AddRenderDriver(_this);
#endif
#if SDL_VIDEO_RENDER_GAPI #if SDL_VIDEO_RENDER_GAPI
WINCE_AddRenderDriver(_this); WINCE_AddRenderDriver(_this);
#endif #endif
......
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
#if SDL_VIDEO_RENDER_X11
#include <limits.h> /* For INT_MIN and INT_MAX */
#include "SDL_x11video.h"
#include "SDL_x11render.h"
#include "../SDL_rect_c.h"
#include "../SDL_pixels_c.h"
#include "../SDL_yuv_sw_c.h"
/* X11 renderer implementation */
static SDL_Renderer *X11_CreateRenderer(SDL_Window * window, Uint32 flags);
static int X11_DisplayModeChanged(SDL_Renderer * renderer);
static int X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
static int X11_QueryTexturePixels(SDL_Renderer * renderer,
SDL_Texture * texture, void **pixels,
int *pitch);
static int X11_SetTextureRGBAMod(SDL_Renderer * renderer,
SDL_Texture * texture);
static int X11_SetTextureBlendMode(SDL_Renderer * renderer,
SDL_Texture * texture);
static int X11_SetTextureScaleMode(SDL_Renderer * renderer,
SDL_Texture * texture);
static int X11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, const void *pixels,
int pitch);
static int X11_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, int markDirty,
void **pixels, int *pitch);
static void X11_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
static int X11_SetDrawBlendMode(SDL_Renderer * renderer);
static int X11_RenderDrawPoints(SDL_Renderer * renderer,
const SDL_Point * points, int count);
static int X11_RenderDrawLines(SDL_Renderer * renderer,
const SDL_Point * points, int count);
static int X11_RenderDrawRects(SDL_Renderer * renderer,
const SDL_Rect ** rects, int count);
static int X11_RenderFillRects(SDL_Renderer * renderer,
const SDL_Rect ** rects, int count);
static int X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_Rect * dstrect);
static int X11_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
Uint32 format, void * pixels, int pitch);
static int X11_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
Uint32 format, const void * pixels, int pitch);
static void X11_RenderPresent(SDL_Renderer * renderer);
static void X11_DestroyTexture(SDL_Renderer * renderer,
SDL_Texture * texture);
static void X11_DestroyRenderer(SDL_Renderer * renderer);
SDL_RenderDriver X11_RenderDriver = {
X11_CreateRenderer,
{
"x11",
(SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY |
SDL_RENDERER_PRESENTFLIP2 | SDL_RENDERER_PRESENTFLIP3 |
SDL_RENDERER_PRESENTDISCARD | SDL_RENDERER_ACCELERATED),
SDL_TEXTUREMODULATE_NONE,
SDL_BLENDMODE_NONE,
SDL_SCALEMODE_NONE,
0,
{0},
0,
0}
};
typedef struct
{
Display *display;
int screen;
Visual *visual;
int depth;
int scanline_pad;
Window xwindow;
Pixmap pixmaps[3];
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
Pixmap stencil;
Pixmap brush;
Picture brush_pict;
Picture xwindow_pict;
Picture pixmap_picts[3];
Picture drawable_pict;
Picture stencil_pict;
int blend_op;
XRenderPictFormat *xwindow_pict_fmt;
XRenderPictFormat *drawable_pict_fmt;
GC stencil_gc;
SDL_bool use_xrender;
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
SDL_bool use_xdamage;
Damage stencil_damage;
XserverRegion stencil_parts;
#endif
#endif
int current_pixmap;
Drawable drawable;
SDL_PixelFormat format;
GC gc;
SDL_DirtyRectList dirty;
SDL_bool makedirty;
} X11_RenderData;
typedef struct
{
SDL_SW_YUVTexture *yuv;
Uint32 format;
Pixmap pixmap;
int depth;
Visual *visual;
GC gc;
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
Picture picture;
Pixmap modulated_pixmap;
Picture modulated_picture;
XRenderPictFormat* picture_fmt;
int blend_op;
const char* filter;
#endif
XImage *image;
#ifndef NO_SHARED_MEMORY
/* MIT shared memory extension information */
XShmSegmentInfo shminfo;
#endif
XImage *scaling_image;
void *pixels;
int pitch;
} X11_TextureData;
#ifndef NO_SHARED_MEMORY
/* Shared memory error handler routine */
static int shm_error;
static int (*X_handler) (Display *, XErrorEvent *) = NULL;
static int
shm_errhandler(Display * d, XErrorEvent * e)
{
if (e->error_code == BadAccess) {
shm_error = True;
return (0);
} else {
return (X_handler(d, e));
}
}
#endif /* ! NO_SHARED_MEMORY */
static void
UpdateYUVTextureData(SDL_Texture * texture)
{
X11_TextureData *data = (X11_TextureData *) texture->driverdata;
SDL_Rect rect;
rect.x = 0;
rect.y = 0;
rect.w = texture->w;
rect.h = texture->h;
SDL_SW_CopyYUVToRGB(data->yuv, &rect, data->format, texture->w,
texture->h, data->pixels, data->pitch);
}
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
static SDL_bool
CheckXRender(Display *display, int *major, int *minor)
{
const char *env;
*major = *minor = 0;
env = SDL_getenv("SDL_VIDEO_X11_XRENDER");
if (env && !SDL_atoi(env)) {
return SDL_FALSE;
}
if (!SDL_X11_HAVE_XRENDER) {
return SDL_FALSE;
}
if (!XRenderQueryVersion(display, major, minor)) {
return SDL_FALSE;
}
if (*major != 0 || *minor < 10) {
return SDL_FALSE;
}
return SDL_TRUE;
}
#endif
#ifdef SDL_VIDEO_DRIVER_X11_XFIXES
static SDL_bool
CheckXFixes(Display *display, int *major, int *minor)
{
const char *env;
*major = *minor = 0;
env = SDL_getenv("SDL_VIDEO_X11_XFIXES");
if (env && !SDL_atoi(env)) {
return SDL_FALSE;
}
if (!SDL_X11_HAVE_XFIXES) {
return SDL_FALSE;
}
if (!XFixesQueryVersion(display, major, minor)) {
return SDL_FALSE;
}
if (*major < 2) {
return SDL_FALSE;
}
return SDL_TRUE;
}
#endif
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
static SDL_bool
CheckXDamage(Display *display, int *major, int *minor)
{
const char *env;
*major = *minor = 0;
env = SDL_getenv("SDL_VIDEO_X11_XDAMAGE");
if (env && !SDL_atoi(env)) {
return SDL_FALSE;
}
if (!SDL_X11_HAVE_XDAMAGE) {
return SDL_FALSE;
}
if (!XDamageQueryVersion(display, major, minor)) {
return SDL_FALSE;
}
return SDL_TRUE;
}
#endif
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
static Uint32
XRenderPictFormatToSDLPixelFormatEnum(XRenderPictFormat *pict_format)
{
if (pict_format->type != PictTypeDirect) {
SDL_SetError("Indexed pict formats not supported ATM");
return 0;
}
Uint32 Amask, Rmask, Gmask, Bmask;
int bpp;
Rmask = pict_format->direct.redMask << pict_format->direct.red;
Gmask = pict_format->direct.greenMask << pict_format->direct.green;
Bmask = pict_format->direct.blueMask << pict_format->direct.blue;
Amask = pict_format->direct.alphaMask << pict_format->direct.alpha;
bpp = pict_format->depth;
Uint32 format;
format = SDL_MasksToPixelFormatEnum(bpp, Rmask, Gmask, Bmask, Amask);
return format;
}
#endif
void
X11_AddRenderDriver(_THIS)
{
SDL_RendererInfo *info = &X11_RenderDriver.info;
SDL_DisplayMode *mode = &SDL_CurrentDisplay->desktop_mode;
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
int i;
info->texture_formats[info->num_texture_formats++] = mode->format;
info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_YV12;
info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_IYUV;
info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_YUY2;
info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_UYVY;
info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_YVYU;
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
int major, minor;
if (CheckXRender(data->display, &major, &minor)) {
XRenderPictFormat templ;
templ.type = PictTypeDirect;
XRenderPictFormat *pict_format;
Uint32 format;
int i = 0;
/* Convert each XRenderPictFormat into appropriate
* SDLPixelFormatEnum. */
while (info->num_texture_formats < 50) {
pict_format =
XRenderFindFormat(data->display, PictFormatType, &templ, i++);
if (pict_format) {
format = XRenderPictFormatToSDLPixelFormatEnum(pict_format);
if (format != SDL_PIXELTYPE_UNKNOWN) {
info->texture_formats[info->num_texture_formats++] = format;
}
}
else
break;
}
/* Update the capabilities of the renderer. */
info->blend_modes |= (SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD |
SDL_BLENDMODE_MOD | SDL_BLENDMODE_MASK);
info->scale_modes |= (SDL_SCALEMODE_FAST | SDL_SCALEMODE_SLOW |
SDL_SCALEMODE_BEST);
info->mod_modes |= (SDL_TEXTUREMODULATE_COLOR | SDL_TEXTUREMODULATE_ALPHA);
}
#endif
for (i = 0; i < _this->num_displays; ++i) {
SDL_AddRenderDriver(&_this->displays[i], &X11_RenderDriver);
}
}
SDL_Renderer *
X11_CreateRenderer(SDL_Window * window, Uint32 flags)
{
SDL_VideoDisplay *display = window->display;
SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata;
SDL_Renderer *renderer;
X11_RenderData *data;
XGCValues gcv;
gcv.graphics_exposures = False;
int i, n;
int bpp;
Uint32 Rmask, Gmask, Bmask, Amask;
renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
if (!renderer) {
SDL_OutOfMemory();
return NULL;
}
data = (X11_RenderData *) SDL_calloc(1, sizeof(*data));
if (!data) {
X11_DestroyRenderer(renderer);
SDL_OutOfMemory();
return NULL;
}
data->display = windowdata->videodata->display;
data->screen = displaydata->screen;
data->visual = displaydata->visual;
data->depth = displaydata->depth;
data->scanline_pad = displaydata->scanline_pad;
data->xwindow = windowdata->xwindow;
renderer->DisplayModeChanged = X11_DisplayModeChanged;
renderer->CreateTexture = X11_CreateTexture;
renderer->QueryTexturePixels = X11_QueryTexturePixels;
renderer->SetTextureAlphaMod = X11_SetTextureRGBAMod;
renderer->SetTextureColorMod = X11_SetTextureRGBAMod;
renderer->SetTextureBlendMode = X11_SetTextureBlendMode;
renderer->SetTextureScaleMode = X11_SetTextureScaleMode;
renderer->UpdateTexture = X11_UpdateTexture;
renderer->LockTexture = X11_LockTexture;
renderer->UnlockTexture = X11_UnlockTexture;
renderer->SetDrawBlendMode = X11_SetDrawBlendMode;
renderer->RenderDrawPoints = X11_RenderDrawPoints;
renderer->RenderDrawLines = X11_RenderDrawLines;
renderer->RenderDrawRects = X11_RenderDrawRects;
renderer->RenderFillRects = X11_RenderFillRects;
renderer->RenderCopy = X11_RenderCopy;
renderer->RenderReadPixels = X11_RenderReadPixels;
renderer->RenderWritePixels = X11_RenderWritePixels;
renderer->RenderPresent = X11_RenderPresent;
renderer->DestroyTexture = X11_DestroyTexture;
renderer->DestroyRenderer = X11_DestroyRenderer;
renderer->info = X11_RenderDriver.info;
renderer->window = window;
renderer->driverdata = data;
renderer->info.flags = SDL_RENDERER_ACCELERATED;
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
int major, minor;
data->use_xrender = CheckXRender(data->display, &major, &minor);
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (CheckXDamage(data->display, &major, &minor)) {
if (CheckXFixes(data->display, &major, &minor)) {
data->use_xdamage = SDL_TRUE;
}
}
#endif
if (data->use_xrender) {
/* Find the PictFormat from the visual.
* Should be an RGB PictFormat most of the time. */
data->xwindow_pict_fmt = XRenderFindVisualFormat(data->display,
data->visual);
if (!data->xwindow_pict_fmt) {
SDL_SetError("XRenderFindVisualFormat() failed");
return NULL;
}
data->xwindow_pict = XRenderCreatePicture(data->display,
data->xwindow,
data->xwindow_pict_fmt,
0, NULL);
if (!data->xwindow_pict) {
SDL_SetError("XRenderCreatePicture() failed");
return NULL;
}
// FIXME: Clear the window. Is this required?
XRenderComposite(data->display,
PictOpClear,
data->xwindow_pict,
None,
data->xwindow_pict,
0, 0,
0, 0,
0, 0,
window->w, window->h);
/* Create a clip mask that is used for rendering primitives. */
data->stencil = XCreatePixmap(data->display, data->xwindow,
window->w, window->h, 32);
if (!data->stencil) {
SDL_SetError("XCreatePixmap() failed.");
return NULL;
}
/* Create the GC for the clip mask. */
data->stencil_gc = XCreateGC(data->display, data->stencil,
GCGraphicsExposures, &gcv);
/* Set the GC parameters. */
XSetBackground(data->display, data->stencil_gc, 0);
XSetForeground(data->display, data->stencil_gc, 0);
XFillRectangle(data->display, data->stencil, data->stencil_gc,
0, 0, window->w, window->h);
XSetForeground(data->display, data->stencil_gc, 0xFFFFFFFF);
/* Create an XRender Picture for the clip mask. */
data->stencil_pict =
XRenderCreatePicture(data->display, data->stencil,
XRenderFindStandardFormat(data->display,
PictStandardARGB32),
0, NULL);
if (!data->stencil_pict) {
SDL_SetError("XRenderCreatePicture() failed.");
return NULL;
}
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (data->use_xdamage) {
data->stencil_damage =
XDamageCreate(data->display, data->stencil, XDamageReportNonEmpty);
if (!data->stencil_damage) {
SDL_SetError("XDamageCreate() failed.");
return NULL;
}
XDamageSubtract(data->display, data->stencil_damage, None, data->stencil_parts);
}
#endif
/* Create a brush pixmap for the color being
* drawn at any given time. */
data->brush =
XCreatePixmap(data->display, data->xwindow, 1, 1, 32);
if (!data->brush) {
SDL_SetError("XCreatePixmap() failed.");
return NULL;
}
/* Set some parameters for the brush. */
XRenderPictureAttributes brush_attr;
brush_attr.repeat = RepeatNormal;
/* Create an XRender Picture for the brush
* with the above parameters. */
data->brush_pict =
XRenderCreatePicture(data->display, data->brush,
XRenderFindStandardFormat(data->display,
PictStandardARGB32),
CPRepeat, &brush_attr);
if (!data->brush_pict) {
SDL_SetError("XRenderCreatePicture() failed.");
return NULL;
}
// FIXME: Is the following necessary?
/* Set the default blending mode. */
renderer->blendMode = SDL_BLENDMODE_BLEND;
data->blend_op = PictOpOver;
}
#endif
if (flags & SDL_RENDERER_SINGLEBUFFER) {
renderer->info.flags |=
(SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY);
n = 0;
} else if (flags & SDL_RENDERER_PRESENTFLIP2) {
renderer->info.flags |= SDL_RENDERER_PRESENTFLIP2;
n = 2;
} else if (flags & SDL_RENDERER_PRESENTFLIP3) {
renderer->info.flags |= SDL_RENDERER_PRESENTFLIP3;
n = 3;
} else {
renderer->info.flags |= SDL_RENDERER_PRESENTCOPY;
n = 1;
}
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender) {
if (n > 0)
data->drawable_pict_fmt =
XRenderFindStandardFormat(data->display, PictStandardARGB32);
else
data->drawable_pict_fmt = data->xwindow_pict_fmt;
}
#endif
for (i = 0; i < n; ++i) {
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender) {
data->pixmaps[i] = XCreatePixmap(data->display,
data->xwindow,
window->w,
window->h,
32);
}
else
#endif
{
data->pixmaps[i] =
XCreatePixmap(data->display, data->xwindow, window->w, window->h,
displaydata->depth);
}
if (!data->pixmaps[i]) {
X11_DestroyRenderer(renderer);
SDL_SetError("XCreatePixmap() failed");
return NULL;
}
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender) {
/* Create XRender pictures for each of the pixmaps
* and clear the pixmaps. */
data->pixmap_picts[i] =
XRenderCreatePicture(data->display,
data->pixmaps[i],
XRenderFindStandardFormat(data->display,
PictStandardARGB32),
0, None);
if (!data->pixmap_picts[i]) {
SDL_SetError("XRenderCreatePicture() failed");
return NULL;
}
XRenderComposite(data->display,
PictOpClear,
data->pixmap_picts[i],
None,
data->pixmap_picts[i],
0, 0,
0, 0,
0, 0,
window->w, window->h);
}
#endif
}
if (n > 0) {
data->drawable = data->pixmaps[0];
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if(data->use_xrender == SDL_TRUE)
data->drawable_pict = data->pixmap_picts[0];
#endif
data->makedirty = SDL_TRUE;
} else {
data->drawable = data->xwindow;
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if(data->use_xrender == SDL_TRUE)
data->drawable_pict = data->xwindow_pict;
#endif
data->makedirty = SDL_FALSE;
}
data->current_pixmap = 0;
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
/* When using XRender the drawable format
* is not the same as the screen format. */
if (data->use_xrender) {
bpp = data->drawable_pict_fmt->depth;
Rmask = ((data->drawable_pict_fmt->direct.redMask)
<< (data->drawable_pict_fmt->direct.red));
Gmask = ((data->drawable_pict_fmt->direct.greenMask)
<< (data->drawable_pict_fmt->direct.green));
Bmask = ((data->drawable_pict_fmt->direct.blueMask)
<< (data->drawable_pict_fmt->direct.blue));
Amask = ((data->drawable_pict_fmt->direct.alphaMask)
<< (data->drawable_pict_fmt->direct.alpha));
}
else
#endif
{
/* Get the format of the window */
if (!SDL_PixelFormatEnumToMasks
(display->current_mode.format, &bpp, &Rmask, &Gmask, &Bmask,
&Amask)) {
SDL_SetError("Unknown display format");
X11_DestroyRenderer(renderer);
return NULL;
}
}
SDL_InitFormat(&data->format, bpp, Rmask, Gmask, Bmask, Amask);
/* Create the drawing context */
gcv.graphics_exposures = False;
data->gc =
XCreateGC(data->display, data->drawable, GCGraphicsExposures, &gcv);
if (!data->gc) {
X11_DestroyRenderer(renderer);
SDL_SetError("XCreateGC() failed");
return NULL;
}
return renderer;
}
static int
X11_DisplayModeChanged(SDL_Renderer * renderer)
{
X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
SDL_Window *window = renderer->window;
int i, n;
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender) {
XRenderFreePicture(data->display, data->xwindow_pict);
data->xwindow_pict_fmt =
XRenderFindVisualFormat(data->display, data->visual);
if (!data->xwindow_pict_fmt) {
SDL_SetError("XRenderFindVisualFormat() failed.");
return -1;
}
data->xwindow_pict =
XRenderCreatePicture(data->display, data->xwindow,
data->xwindow_pict_fmt, 0, NULL);
if (!data->xwindow_pict) {
SDL_SetError("XRenderCreatePicture() failed.");
return -1;
}
XRenderComposite(data->display,
PictOpClear,
data->xwindow_pict,
None,
data->xwindow_pict,
0, 0,
0, 0,
0, 0,
window->w, window->h);
XFreePixmap(data->display, data->stencil);
data->stencil = XCreatePixmap(data->display, data->xwindow,
window->w, window->h, 32);
if (!data->stencil) {
SDL_SetError("XCreatePixmap() failed.");
return -1;
}
XRenderFreePicture(data->display, data->stencil_pict);
data->stencil_pict =
XRenderCreatePicture(data->display, data->stencil,
XRenderFindStandardFormat(data->display,
PictStandardARGB32),
0, NULL);
if (!data->stencil_pict) {
SDL_SetError("XRenderCreatePicture() failed.");
return -1;
}
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (data->use_xdamage) {
XDamageDestroy(data->display, data->stencil_damage);
data->stencil_damage =
XDamageCreate(data->display, data->stencil, XDamageReportNonEmpty);
if (!data->stencil_damage) {
SDL_SetError("XDamageCreate() failed.");
return -1;
}
XDamageSubtract(data->display, data->stencil_damage, None, data->stencil_parts);
}
#endif
}
#endif
if (renderer->info.flags & SDL_RENDERER_SINGLEBUFFER) {
n = 0;
} else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) {
n = 2;
} else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP3) {
n = 3;
} else {
n = 1;
}
for (i = 0; i < n; ++i) {
if (data->pixmaps[i] != None) {
XFreePixmap(data->display, data->pixmaps[i]);
data->pixmaps[i] = None;
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
XRenderFreePicture(data->display, data->pixmap_picts[i]);
data->pixmap_picts[i] = None;
#endif
}
}
for (i = 0; i < n; ++i) {
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender) {
data->pixmaps[i] =
XCreatePixmap(data->display,
data->xwindow,
window->w,
window->h,
32);
}
else
#endif
{
data->pixmaps[i] =
XCreatePixmap(data->display, data->xwindow, window->w, window->h,
data->depth);
}
if (data->pixmaps[i] == None) {
SDL_SetError("XCreatePixmap() failed");
return -1;
}
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender) {
data->pixmap_picts[i] =
XRenderCreatePicture(data->display,
data->pixmaps[i],
XRenderFindStandardFormat(data->display,
PictStandardARGB32),
0, None);
if (!data->pixmap_picts[i]) {
SDL_SetError("XRenderCreatePicture() failed");
return -1;
}
XRenderComposite(data->display,
PictOpClear,
data->pixmap_picts[i],
None,
data->pixmap_picts[i],
0, 0,
0, 0,
0, 0,
window->w, window->h);
}
#endif
}
if (n > 0) {
data->drawable = data->pixmaps[0];
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
data->drawable_pict = data->pixmap_picts[0];
#endif
}
data->current_pixmap = 0;
return 0;
}
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
static void
SDLMaskToXRenderMask(Uint32 sdl_mask, short *comp, short *compMask)
{
if (sdl_mask == 0) {
*comp = 0;
*compMask = 0;
} else {
(*comp) = 0;
(*compMask) = 0;
while(!(sdl_mask & 1)) {
(*comp)++;
sdl_mask >>= 1;
}
while(sdl_mask & 1) {
(*compMask) = ((*compMask) << 1) | 1;
sdl_mask >>= 1;
}
}
}
static XRenderPictFormat*
PixelFormatEnumToXRenderPictFormat(SDL_Renderer * renderer, Uint32 format)
{
XRenderPictFormat* pict_fmt = NULL;
X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
if (data->use_xrender) {
int bpp;
Uint32 Amask, Rmask, Gmask, Bmask;
if(!SDL_PixelFormatEnumToMasks(format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
SDL_SetError("Unknown pixel format");
return NULL;
}
XRenderPictFormat templ;
unsigned long mask = (PictFormatType | PictFormatDepth | PictFormatRed |
PictFormatRedMask | PictFormatGreen | PictFormatGreenMask |
PictFormatBlue | PictFormatBlueMask | PictFormatAlpha |
PictFormatAlphaMask);
templ.type = PictTypeDirect;
templ.depth = bpp;
SDLMaskToXRenderMask(Amask, &(templ.direct.alpha), &(templ.direct.alphaMask));
SDLMaskToXRenderMask(Rmask, &(templ.direct.red), &(templ.direct.redMask));
SDLMaskToXRenderMask(Gmask, &(templ.direct.green), &(templ.direct.greenMask));
SDLMaskToXRenderMask(Bmask, &(templ.direct.blue), &(templ.direct.blueMask));
pict_fmt = XRenderFindFormat(data->display, mask, &templ, 0);
}
return pict_fmt;
}
static Visual*
PixelFormatEnumToVisual(SDL_Renderer * renderer, Uint32 format)
{
X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
if (data->use_xrender) {
int bpp;
Uint32 Amask, Rmask, Gmask, Bmask;
SDL_PixelFormatEnumToMasks(format, &bpp, &Rmask, &Gmask, &Bmask, &Amask);
XVisualInfo vinfo_templ;
long vinfo_mask;
int nitems_return;
vinfo_mask = (VisualDepthMask | VisualRedMaskMask |
VisualGreenMaskMask | VisualBlueMaskMask);
vinfo_templ.depth = bpp;
vinfo_templ.red_mask = Rmask;
vinfo_templ.green_mask = Gmask;
vinfo_templ.blue_mask = Bmask;
XVisualInfo * ret = XGetVisualInfo(data->display, vinfo_mask,
&vinfo_templ, &nitems_return);
if (nitems_return) {
return ret[0].visual;
}
}
return NULL;
}
static XRenderColor
SDLColorToXRenderColor(Uint8 r, Uint8 g, Uint8 b, Uint8 a)
{
double rd, gd, bd, ad;
XRenderColor ret;
rd = r / 255.0;
gd = g / 255.0;
bd = b / 255.0;
ad = a / 255.0;
ret.red = (unsigned short) (rd * ad * 0xFFFF);
ret.green = (unsigned short) (gd * ad * 0xFFFF);
ret.blue = (unsigned short) (bd * ad * 0xFFFF);
ret.alpha = (unsigned short) (ad * 0xFFFF);
return ret;
}
#endif
static int
X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
{
X11_RenderData *renderdata = (X11_RenderData *) renderer->driverdata;
SDL_Window *window = renderer->window;
SDL_VideoDisplay *display = window->display;
X11_TextureData *data;
int pitch_alignmask = ((renderdata->scanline_pad / 8) - 1);
XGCValues gcv;
data = (X11_TextureData *) SDL_calloc(1, sizeof(*data));
if (!data) {
SDL_OutOfMemory();
return -1;
}
data->depth = renderdata->depth;
data->visual = renderdata->visual;
data->gc = renderdata->gc;
texture->driverdata = data;
if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
data->yuv =
SDL_SW_CreateYUVTexture(texture->format, texture->w, texture->h);
if (!data->yuv) {
return -1;
}
data->format = display->current_mode.format;
} else {
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (renderdata->use_xrender)
{
Uint32 Amask, Rmask, Gmask, Bmask;
SDL_PixelFormatEnumToMasks(texture->format, &(data->depth),
&Rmask, &Gmask, &Bmask, &Amask);
data->visual = PixelFormatEnumToVisual(renderer, texture->format);
}
else
#endif
{
if (texture->format != display->current_mode.format)
{
SDL_SetError("Texture format doesn't match window format");
return -1;
}
}
data->format = texture->format;
}
if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING) {
#ifndef NO_SHARED_MEMORY
XShmSegmentInfo *shminfo = &data->shminfo;
shm_error = True;
if (SDL_X11_HAVE_SHM) {
data->image =
XShmCreateImage(renderdata->display, data->visual,
data->depth, ZPixmap, NULL,
shminfo, texture->w, texture->h);
if (data->image) {
shminfo->shmid =
shmget(IPC_PRIVATE, texture->h * data->image->bytes_per_line,
IPC_CREAT | 0777);
if (shminfo->shmid >= 0) {
shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0);
shminfo->readOnly = False;
if (shminfo->shmaddr != (char *) -1) {
shm_error = False;
X_handler = XSetErrorHandler(shm_errhandler);
XShmAttach(renderdata->display, shminfo);
XSync(renderdata->display, False);
XSetErrorHandler(X_handler);
if (shm_error) {
XShmDetach(renderdata->display, shminfo);
shmdt(shminfo->shmaddr);
XDestroyImage(data->image);
XSync(renderdata->display, False);
}
else {
data->pixels = data->image->data = shminfo->shmaddr;
shmctl(shminfo->shmid, IPC_RMID, NULL);
data->pixmap =
XCreatePixmap(renderdata->display, renderdata->xwindow,
texture->w, texture->h, data->depth);
if (!data->pixmap) {
SDL_SetError("XCreatePixmap() failed");
return -1;
}
}
}
}
}
}
if (shm_error) {
shminfo->shmaddr = NULL;
}
if (!data->image)
#endif /* not NO_SHARED_MEMORY */
{
data->image =
XCreateImage(renderdata->display, data->visual,
data->depth, ZPixmap, 0, NULL,
texture->w, texture->h,
SDL_BYTESPERPIXEL(data->format) * 8,
0);
if (!data->image) {
X11_DestroyTexture(renderer, texture);
SDL_SetError("XCreateImage() failed");
return -1;
}
data->pixels = SDL_malloc(texture->h * data->image->bytes_per_line);
if (!data->pixels) {
X11_DestroyTexture(renderer, texture);
SDL_OutOfMemory();
return -1;
}
data->image->data = data->pixels;
data->pixmap =
XCreatePixmap(renderdata->display, renderdata->xwindow, texture->w,
texture->h, data->depth);
if (data->pixmap == None) {
X11_DestroyTexture(renderer, texture);
SDL_SetError("XCreatePixmap() failed");
return -1;
}
}
} else {
data->image =
XCreateImage(renderdata->display, data->visual,
data->depth, ZPixmap, 0, NULL,
texture->w, texture->h,
SDL_BYTESPERPIXEL(data->format) * 8,
0);
if (!data->image) {
X11_DestroyTexture(renderer, texture);
SDL_SetError("XCreateImage() failed");
return -1;
}
data->pixmap =
XCreatePixmap(renderdata->display, renderdata->xwindow, texture->w,
texture->h, data->depth);
if (data->pixmap == None) {
X11_DestroyTexture(renderer, texture);
SDL_SetError("XCreatePixmap() failed");
return -1;
}
}
data->pitch = data->image->bytes_per_line;
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if(renderdata->use_xrender && !data->yuv) {
gcv.graphics_exposures = False;
data->gc =
XCreateGC(renderdata->display, data->pixmap, GCGraphicsExposures, &gcv);
if (!data->gc) {
SDL_SetError("XCreateGC() failed");
return -1;
}
data->picture_fmt =
PixelFormatEnumToXRenderPictFormat(renderer, texture->format);
if (data->picture_fmt == NULL) {
X11_DestroyTexture(renderer, texture);
SDL_SetError("Texture format not supported by driver");
return -1;
}
data->picture =
XRenderCreatePicture(renderdata->display, data->pixmap,
data->picture_fmt, 0, NULL);
if (!data->picture) {
X11_DestroyTexture(renderer, texture);
SDL_SetError("XRenderCreatePicture() failed");
return -1;
}
data->modulated_pixmap =
XCreatePixmap(renderdata->display, renderdata->xwindow,
texture->w, texture->h, data->depth);
if (!data->modulated_pixmap) {
X11_DestroyTexture(renderer, texture);
SDL_SetError("XCreatePixmap() failed");
return -1;
}
data->modulated_picture =
XRenderCreatePicture(renderdata->display, data->modulated_pixmap,
data->picture_fmt, 0, NULL);
if (!data->modulated_picture) {
X11_DestroyTexture(renderer, texture);
SDL_SetError("XRenderCreatePicture() failed");
return -1;
}
// FIXME: Is the following required?
/* Set the default blending and scaling modes. */
texture->blendMode = SDL_BLENDMODE_NONE;
texture->scaleMode = SDL_SCALEMODE_NONE;
data->blend_op = PictOpSrc;
data->filter = NULL;
}
#endif
return 0;
}
static int
X11_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
void **pixels, int *pitch)
{
X11_TextureData *data = (X11_TextureData *) texture->driverdata;
if (data->yuv) {
return SDL_SW_QueryYUVTexturePixels(data->yuv, pixels, pitch);
} else {
*pixels = data->pixels;
*pitch = data->pitch;
return 0;
}
}
static int
X11_SetTextureRGBAMod(SDL_Renderer * renderer, SDL_Texture * texture)
{
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
X11_TextureData *data = (X11_TextureData *) texture->driverdata;
X11_RenderData *renderdata = (X11_RenderData *) renderer->driverdata;
if (renderdata->use_xrender) {
Uint8 r = 0xFF, g = 0xFF, b = 0xFF, a = 0xFF;
/* Check if alpha modulation is required. */
if (texture->modMode & SDL_TEXTUREMODULATE_ALPHA) {
a = texture->a;
}
/* Check if color modulation is required. */
if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) {
r = texture->r;
g = texture->g;
b = texture->b;
}
/* We can save some labour if no modulation is required. */
if (texture->modMode != SDL_TEXTUREMODULATE_NONE) {
XRenderColor mod_color =
SDLColorToXRenderColor(r, g, b, a);
XRenderFillRectangle(renderdata->display, PictOpSrc,
renderdata->brush_pict, &mod_color,
0, 0, 1, 1);
}
/* We can save some labour dealing with component alpha
* if color modulation is not required. */
XRenderPictureAttributes attr;
if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) {
attr.component_alpha = True;
XRenderChangePicture(renderdata->display, renderdata->brush_pict,
CPComponentAlpha, &attr);
}
/* Again none of this is necessary is no modulation
* is required. */
if (texture->modMode != SDL_TEXTUREMODULATE_NONE) {
XRenderComposite(renderdata->display, PictOpSrc,
data->picture, renderdata->brush_pict,
data->modulated_picture,
0, 0, 0, 0, 0, 0, texture->w, texture->h);
}
/* We only need to reset the component alpha
* attribute if color modulation is required. */
if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) {
attr.component_alpha = False;
XRenderChangePicture(renderdata->display, renderdata->brush_pict,
CPComponentAlpha, &attr);
}
return 0;
} else {
SDL_Unsupported();
return -1;
}
#else
SDL_Unsupported();
return -1;
#endif
}
static int
X11_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
{
X11_TextureData *data = (X11_TextureData *) texture->driverdata;
X11_RenderData *renderdata = (X11_RenderData *) renderer->driverdata;
switch (texture->blendMode) {
case SDL_BLENDMODE_NONE:
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (renderdata->use_xrender) {
data->blend_op = PictOpSrc;
return 0;
}
case SDL_BLENDMODE_MOD:
case SDL_BLENDMODE_MASK:
case SDL_BLENDMODE_BLEND:
if (renderdata->use_xrender) {
data->blend_op = PictOpOver;
return 0;
}
case SDL_BLENDMODE_ADD:
if (renderdata->use_xrender) {
data->blend_op = PictOpAdd;
return 0;
}
#endif
return 0;
default:
SDL_Unsupported();
texture->blendMode = SDL_BLENDMODE_NONE;
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (renderdata->use_xrender) {
texture->blendMode = SDL_BLENDMODE_BLEND;
data->blend_op = PictOpOver;
}
#endif
return -1;
}
}
static int
X11_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture)
{
X11_TextureData *data = (X11_TextureData *) texture->driverdata;
X11_RenderData *renderdata = (X11_RenderData *) renderer->driverdata;
switch (texture->scaleMode) {
case SDL_SCALEMODE_NONE:
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (renderdata->use_xrender) {
data->filter = NULL;
}
#endif
return 0;
case SDL_SCALEMODE_FAST:
/* We can sort of fake it for streaming textures */
if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING) {
return 0;
}
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (renderdata->use_xrender) {
data->filter = FilterFast;
return 0;
}
case SDL_SCALEMODE_SLOW:
if (renderdata->use_xrender) {
data->filter = FilterGood;
return 0;
}
case SDL_SCALEMODE_BEST:
if (renderdata->use_xrender) {
data->filter = FilterBest;
return 0;
}
#endif
/* Fall through to unsupported case */
default:
SDL_Unsupported();
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (renderdata->use_xrender) {
texture->scaleMode = SDL_SCALEMODE_NONE;
data->filter = NULL;
}
else
#endif
texture->scaleMode = SDL_SCALEMODE_NONE;
return -1;
}
return 0;
}
static int
X11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, const void *pixels, int pitch)
{
X11_TextureData *data = (X11_TextureData *) texture->driverdata;
if (data->yuv) {
if (SDL_SW_UpdateYUVTexture(data->yuv, rect, pixels, pitch) < 0) {
return -1;
}
UpdateYUVTextureData(texture);
return 0;
} else {
X11_RenderData *renderdata = (X11_RenderData *) renderer->driverdata;
if (data->pixels) {
Uint8 *src, *dst;
int row;
size_t length;
src = (Uint8 *) pixels;
dst =
(Uint8 *) data->pixels + rect->y * data->pitch +
rect->x * SDL_BYTESPERPIXEL(texture->format);
length = rect->w * SDL_BYTESPERPIXEL(texture->format);
for (row = 0; row < rect->h; ++row) {
SDL_memcpy(dst, src, length);
src += pitch;
dst += data->pitch;
}
} else {
data->image->width = rect->w;
data->image->height = rect->h;
data->image->data = (char *) pixels;
data->image->bytes_per_line = pitch;
XPutImage(renderdata->display, data->pixmap, data->gc,
data->image, 0, 0, rect->x, rect->y, rect->w, rect->h);
}
return 0;
}
}
static int
X11_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, int markDirty, void **pixels,
int *pitch)
{
X11_TextureData *data = (X11_TextureData *) texture->driverdata;
if (data->yuv) {
return SDL_SW_LockYUVTexture(data->yuv, rect, markDirty, pixels,
pitch);
} else if (data->pixels) {
*pixels =
(void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
rect->x * SDL_BYTESPERPIXEL(texture->format));
*pitch = data->pitch;
return 0;
} else {
SDL_SetError("No pixels available");
return -1;
}
}
static void
X11_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
{
X11_TextureData *data = (X11_TextureData *) texture->driverdata;
if (data->yuv) {
SDL_SW_UnlockYUVTexture(data->yuv);
UpdateYUVTextureData(texture);
}
}
static int
X11_SetDrawBlendMode(SDL_Renderer * renderer)
{
X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
switch (renderer->blendMode) {
case SDL_BLENDMODE_NONE:
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
//PictOpSrc
data->blend_op = PictOpSrc;
return 0;
case SDL_BLENDMODE_MOD:
case SDL_BLENDMODE_MASK:
case SDL_BLENDMODE_BLEND: // PictOpOver
data->blend_op = PictOpOver;
return 0;
case SDL_BLENDMODE_ADD: // PictOpAdd
data->blend_op = PictOpAdd;
return 0;
/* FIXME case SDL_BLENDMODE_MOD: */
#endif
return 0;
default:
SDL_Unsupported();
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if(data->use_xrender) {
renderer->blendMode = SDL_BLENDMODE_BLEND;
data->blend_op = PictOpOver;
}
else
#endif
{
renderer->blendMode = SDL_BLENDMODE_NONE;
}
return -1;
}
}
static Uint32
renderdrawcolor(SDL_Renderer * renderer, int premult)
{
X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
Uint8 r = renderer->r;
Uint8 g = renderer->g;
Uint8 b = renderer->b;
Uint8 a = renderer->a;
if (premult)
return SDL_MapRGBA(&data->format, ((int) r * (int) a) / 255,
((int) g * (int) a) / 255,
((int) b * (int) a) / 255, 255);
else
return SDL_MapRGBA(&data->format, r, g, b, a);
}
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
static XRenderColor
xrenderdrawcolor(SDL_Renderer *renderer)
{
XRenderColor xrender_color;
if(renderer->blendMode == SDL_BLENDMODE_NONE) {
xrender_color =
SDLColorToXRenderColor(renderer->r, renderer->g, renderer->b, 0xFF);
}
else {
xrender_color =
SDLColorToXRenderColor(renderer->r, renderer->g, renderer->b, renderer->a);
}
return xrender_color;
}
#endif
static int
X11_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points,
int count)
{
X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
SDL_Window *window = renderer->window;
XPoint *xpoints, *xpoint;
int i, xcount;
SDL_Rect clip;
clip.x = 0;
clip.y = 0;
clip.w = window->w;
clip.h = window->h;
if (data->makedirty) {
SDL_Rect rect;
/* Get the smallest rectangle that contains everything */
rect.x = 0;
rect.y = 0;
rect.w = window->w;
rect.h = window->h;
if (!SDL_EnclosePoints(points, count, &rect, &rect)) {
/* Nothing to draw */
return 0;
}
SDL_AddDirtyRect(&data->dirty, &rect);
}
{
xpoint = xpoints = SDL_stack_alloc(XPoint, count);
xcount = 0;
for (i = 0; i < count; ++i) {
int x = points[i].x;
int y = points[i].y;
if (x < 0 || x >= window->w || y < 0 || y >= window->h) {
continue;
}
xpoint->x = (short)x;
xpoint->y = (short)y;
++xpoint;
++xcount;
}
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender &&
(renderer->blendMode != SDL_BLENDMODE_NONE) &&
!(renderer->a == 0xFF &&
renderer->blendMode != SDL_BLENDMODE_ADD &&
renderer->blendMode != SDL_BLENDMODE_MOD))
{
XSetForeground(data->display, data->stencil_gc, 0);
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (data->use_xdamage)
{
/* Update only those parts which were changed
* in the previous drawing operation */
XFixesSetGCClipRegion(data->display, data->stencil_gc,
0, 0, data->stencil_parts);
}
#endif
XFillRectangle(data->display, data->stencil, data->stencil_gc,
0, 0, window->w, window->h);
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (data->use_xdamage)
{
XFixesSetGCClipRegion(data->display, data->stencil_gc, 0, 0, None);
}
#endif
XSetForeground(data->display, data->stencil_gc, 0xFFFFFFFF);
XDrawPoints(data->display, data->stencil, data->stencil_gc, xpoints, xcount,
CoordModeOrigin);
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (data->use_xdamage)
{
/* Store the damaged region in stencil_parts */
XDamageSubtract(data->display, data->stencil_damage, None, data->stencil_parts);
}
#endif
}
#endif
}
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender &&
(renderer->blendMode != SDL_BLENDMODE_NONE) &&
!(renderer->a == 0xFF &&
renderer->blendMode != SDL_BLENDMODE_ADD &&
renderer->blendMode != SDL_BLENDMODE_MOD))
{
XRenderColor foreground;
foreground = xrenderdrawcolor(renderer);
XRenderFillRectangle(data->display, PictOpSrc, data->brush_pict,
&foreground, 0, 0, 1, 1);
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (data->use_xdamage)
{
/* Update only those parts which drawn
* to in the current drawing operation */
XFixesSetPictureClipRegion(data->display, data->drawable_pict,
0, 0, data->stencil_parts);
}
#endif
XRenderComposite(data->display, data->blend_op, data->brush_pict,
data->stencil_pict, data->drawable_pict,
0, 0, 0, 0, 0, 0, window->w, window->h);
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (data->use_xdamage)
{
XFixesSetPictureClipRegion(data->display, data->drawable_pict, 0, 0, None);
}
#endif
}
else
#endif
{
unsigned long foreground = renderdrawcolor(renderer, 1);
XSetForeground(data->display, data->gc, foreground);
if (xcount > 0) {
XDrawPoints(data->display, data->drawable, data->gc, xpoints, xcount,
CoordModeOrigin);
}
}
SDL_stack_free(xpoints);
return 0;
}
static int
X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points,
int count)
{
X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
SDL_Window *window = renderer->window;
SDL_Rect clip;
unsigned long foreground;
XPoint *xpoints, *xpoint;
int i, xcount;
int minx, miny;
int maxx, maxy;
clip.x = 0;
clip.y = 0;
clip.w = window->w;
clip.h = window->h;
{
Pixmap drawable;
GC gc;
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender &&
(renderer->blendMode != SDL_BLENDMODE_NONE) &&
!(renderer->a == 0xFF &&
renderer->blendMode != SDL_BLENDMODE_ADD &&
renderer->blendMode != SDL_BLENDMODE_MOD))
{
drawable = data->stencil;
gc = data->stencil_gc;
XSetForeground(data->display, data->stencil_gc, 0);
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (data->use_xdamage)
XFixesSetGCClipRegion(data->display, data->stencil_gc,
0, 0, data->stencil_parts);
#endif
XFillRectangle(data->display, data->stencil, data->stencil_gc,
0, 0, window->w, window->h);
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (data->use_xdamage)
XFixesSetGCClipRegion(data->display, data->stencil_gc,
0, 0, None);
#endif
XSetForeground(data->display, data->stencil_gc, 0xFFFFFFFF);
}
else
#endif
{
drawable = data->drawable;
gc = data->gc;
}
foreground = renderdrawcolor(renderer, 1);
XSetForeground(data->display, data->gc, foreground);
xpoint = xpoints = SDL_stack_alloc(XPoint, count);
xcount = 0;
minx = INT_MAX;
miny = INT_MAX;
maxx = INT_MIN;
maxy = INT_MIN;
for (i = 0; i < count; ++i) {
int x = points[i].x;
int y = points[i].y;
/* If the point is inside the window, add it to the list */
if (x >= 0 && x < window->w && y >= 0 && y < window->h) {
if (x < minx) {
minx = x;
} else if (x > maxx) {
maxx = x;
}
if (y < miny) {
miny = y;
} else if (y > maxy) {
maxy = y;
}
xpoint->x = (short)x;
xpoint->y = (short)y;
++xpoint;
++xcount;
continue;
}
/* We need to clip the line segments joined by this point */
if (xcount > 0) {
int x1 = xpoint[-1].x;
int y1 = xpoint[-1].y;
int x2 = x;
int y2 = y;
if (SDL_IntersectRectAndLine(&clip, &x1, &y1, &x2, &y2)) {
if (x2 < minx) {
minx = x2;
} else if (x2 > maxx) {
maxx = x2;
}
if (y2 < miny) {
miny = y2;
} else if (y2 > maxy) {
maxy = y2;
}
xpoint->x = (short)x2;
xpoint->y = (short)y2;
++xpoint;
++xcount;
}
XDrawLines(data->display, drawable, gc,
xpoints, xcount, CoordModeOrigin);
if (xpoints[0].x != x2 || xpoints[0].y != y2) {
XDrawPoint(data->display, drawable, gc, x2, y2);
}
if (data->makedirty) {
SDL_Rect rect;
rect.x = minx;
rect.y = miny;
rect.w = (maxx - minx) + 1;
rect.h = (maxy - miny) + 1;
SDL_AddDirtyRect(&data->dirty, &rect);
}
xpoint = xpoints;
xcount = 0;
minx = INT_MAX;
miny = INT_MAX;
maxx = INT_MIN;
maxy = INT_MIN;
}
if (i < (count-1)) {
int x1 = x;
int y1 = y;
int x2 = points[i+1].x;
int y2 = points[i+1].y;
if (SDL_IntersectRectAndLine(&clip, &x1, &y1, &x2, &y2)) {
if (x1 < minx) {
minx = x1;
} else if (x1 > maxx) {
maxx = x1;
}
if (y1 < miny) {
miny = y1;
} else if (y1 > maxy) {
maxy = y1;
}
xpoint->x = (short)x1;
xpoint->y = (short)y1;
++xpoint;
++xcount;
}
}
}
if (xcount > 1) {
int x2 = xpoint[-1].x;
int y2 = xpoint[-1].y;
XDrawLines(data->display, drawable, gc, xpoints, xcount,
CoordModeOrigin);
if (xpoints[0].x != x2 || xpoints[0].y != y2) {
XDrawPoint(data->display, drawable, gc, x2, y2);
}
if (data->makedirty) {
SDL_Rect rect;
rect.x = minx;
rect.y = miny;
rect.w = (maxx - minx) + 1;
rect.h = (maxy - miny) + 1;
SDL_AddDirtyRect(&data->dirty, &rect);
}
}
}
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender &&
(renderer->blendMode != SDL_BLENDMODE_NONE) &&
!(renderer->a == 0xFF &&
renderer->blendMode != SDL_BLENDMODE_ADD &&
renderer->blendMode != SDL_BLENDMODE_MOD))
{
XRenderColor xrforeground = xrenderdrawcolor(renderer);
XRenderFillRectangle(data->display, PictOpSrc, data->brush_pict,
&xrforeground, 0, 0, 1, 1);
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (data->use_xdamage)
{
XDamageSubtract(data->display, data->stencil_damage, None, data->stencil_parts);
XFixesSetPictureClipRegion(data->display, data->drawable_pict,
0, 0, data->stencil_parts);
}
#endif
XRenderComposite(data->display, data->blend_op, data->brush_pict,
data->stencil_pict, data->drawable_pict,
0, 0, 0, 0, 0, 0, window->w, window->h);
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (data->use_xdamage)
XFixesSetPictureClipRegion(data->display, data->drawable_pict,
0, 0, None);
#endif
}
#endif
SDL_stack_free(xpoints);
return 0;
}
static int
X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count)
{
X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
SDL_Window *window = renderer->window;
SDL_Rect clip, rect;
int i, xcount;
XRectangle *xrects, *xrect;
xrect = xrects = SDL_stack_alloc(XRectangle, count);
xcount = 0;
clip.x = 0;
clip.y = 0;
clip.w = window->w;
clip.h = window->h;
{
for (i = 0; i < count; ++i) {
if (!SDL_IntersectRect(rects[i], &clip, &rect)) {
continue;
}
xrect->x = (short)rect.x;
xrect->y = (short)rect.y;
xrect->width = (unsigned short)rect.w - 1;
xrect->height = (unsigned short)rect.h - 1;
++xrect;
++xcount;
if (data->makedirty) {
SDL_AddDirtyRect(&data->dirty, &rect);
}
}
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender &&
(renderer->blendMode != SDL_BLENDMODE_NONE) &&
!(renderer->a == 0xFF &&
renderer->blendMode != SDL_BLENDMODE_ADD &&
renderer->blendMode != SDL_BLENDMODE_MOD))
{
XSetForeground(data->display, data->stencil_gc, 0);
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (data->use_xdamage)
XFixesSetGCClipRegion(data->display, data->stencil_gc,
0, 0, data->stencil_parts);
#endif
XFillRectangle(data->display, data->stencil, data->stencil_gc,
0, 0, window->w, window->h);
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (data->use_xdamage)
XFixesSetGCClipRegion(data->display, data->stencil_gc,
0, 0, None);
#endif
XSetForeground(data->display, data->stencil_gc, 0xFFFFFFFF);
XDrawRectangles(data->display, data->stencil, data->stencil_gc, xrects, xcount);
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (data->use_xdamage)
XDamageSubtract(data->display, data->stencil_damage,
None, data->stencil_parts);
#endif
}
#endif
}
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender &&
(renderer->blendMode != SDL_BLENDMODE_NONE) &&
!(renderer->a == 0xFF &&
renderer->blendMode != SDL_BLENDMODE_ADD &&
renderer->blendMode != SDL_BLENDMODE_MOD))
{
XRenderColor foreground;
foreground = xrenderdrawcolor(renderer);
XRenderFillRectangle(data->display, PictOpSrc, data->brush_pict,
&foreground, 0, 0, 1, 1);
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (data->use_xdamage)
XFixesSetPictureClipRegion(data->display, data->drawable_pict,
0, 0, data->stencil_parts);
#endif
XRenderComposite(data->display, data->blend_op, data->brush_pict,
data->stencil_pict, data->drawable_pict,
0, 0, 0, 0, 0, 0, window->w, window->h);
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (data->use_xdamage)
XFixesSetPictureClipRegion(data->display, data->drawable_pict,
0, 0, None);
#endif
}
else
#endif
{
unsigned long foreground;
foreground = renderdrawcolor(renderer, 1);
XSetForeground(data->display, data->gc, foreground);
if (xcount > 0) {
XDrawRectangles(data->display, data->drawable, data->gc,
xrects, xcount);
}
}
SDL_stack_free(xrects);
return 0;
}
static int
X11_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count)
{
X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
SDL_Window *window = renderer->window;
SDL_Rect clip, rect;
clip.x = 0;
clip.y = 0;
clip.w = window->w;
clip.h = window->h;
int i, xcount;
XRectangle *xrects, *xrect;
xrect = xrects = SDL_stack_alloc(XRectangle, count);
xcount = 0;
for (i = 0; i < count; ++i) {
if (!SDL_IntersectRect(rects[i], &clip, &rect)) {
continue;
}
xrect->x = (short)rect.x;
xrect->y = (short)rect.y;
xrect->width = (unsigned short)rect.w;
xrect->height = (unsigned short)rect.h;
++xrect;
++xcount;
if (data->makedirty) {
SDL_AddDirtyRect(&data->dirty, &rect);
}
}
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender) {
XRenderColor foreground;
foreground = xrenderdrawcolor(renderer);
if (xcount == 1) {
XRenderFillRectangle(data->display, data->blend_op, data->drawable_pict,
&foreground, xrects[0].x, xrects[0].y,
xrects[0].width, xrects[0].height);
}
else if (xcount > 1) {
XRenderFillRectangles(data->display, data->blend_op, data->drawable_pict,
&foreground, xrects, xcount);
}
}
else
#endif
{
unsigned long foreground;
foreground = renderdrawcolor(renderer, 1);
XSetForeground(data->display, data->gc, foreground);
XFillRectangles(data->display, data->drawable, data->gc,
xrects, xcount);
}
SDL_stack_free(xrects);
return 0;
}
static int
X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_Rect * dstrect)
{
X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
X11_TextureData *texturedata = (X11_TextureData *) texture->driverdata;
if (data->makedirty) {
SDL_AddDirtyRect(&data->dirty, dstrect);
}
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender && !texturedata->yuv) {
if(texture->access == SDL_TEXTUREACCESS_STREAMING) {
#ifndef NO_SHARED_MEMORY
if(texturedata->shminfo.shmaddr) {
XShmPutImage(data->display, texturedata->pixmap, texturedata->gc,
texturedata->image, srcrect->x, srcrect->y,
srcrect->x, srcrect->y, srcrect->w, srcrect->h,
False);
}
else
#endif
if (texturedata->pixels) {
XPutImage(data->display, texturedata->pixmap, texturedata->gc,
texturedata->image, srcrect->x, srcrect->y, srcrect->x,
srcrect->y, srcrect->w, srcrect->h);
}
XSync(data->display, False);
}
Picture src, mask;
XRenderPictureAttributes attr;
const SDL_Rect *mrect;
/* mrect is the rectangular area of the mask
* picture that is aligned with the source. */
if (texture->modMode == SDL_TEXTUREMODULATE_NONE) {
src = texturedata->picture;
}
else {
src = texturedata->modulated_picture;
}
if(texture->blendMode == SDL_BLENDMODE_NONE)
{
mask = None;
mrect = srcrect;
}
else if (texture->blendMode == SDL_BLENDMODE_MOD)
{
/* SDL_BLENDMODE_MOD requires a temporary buffer
* i.e. stencil_pict */
mask = data->stencil_pict;
mrect = dstrect;
}
else
{
/* This trick allows on-the-fly multiplication
* of the src color channels with it's alpha
* channel. */
mask = src;
mrect = srcrect;
}
if(srcrect->w == dstrect->w && srcrect->h == dstrect->h) {
if (texture->blendMode == SDL_BLENDMODE_MOD) {
XRenderComposite(data->display, PictOpSrc, data->drawable_pict,
src, data->stencil_pict,
dstrect->x, dstrect->y, srcrect->x, srcrect->y,
dstrect->x, dstrect->y, dstrect->w, dstrect->h);
attr.component_alpha = True;
XRenderChangePicture(data->display, data->stencil_pict,
CPComponentAlpha, &attr);
}
XRenderComposite(data->display, texturedata->blend_op,
src, mask, data->drawable_pict, srcrect->x, srcrect->y,
mrect->x, mrect->y, dstrect->x, dstrect->y,
dstrect->w, dstrect->h);
} else {
/* The transformation is from the dst to src picture. */
double xscale = ((double) srcrect->w) / dstrect->w;
double yscale = ((double) srcrect->h) / dstrect->h;
XTransform xform = {{
{XDoubleToFixed(xscale), XDoubleToFixed(0), XDoubleToFixed(0)},
{XDoubleToFixed(0), XDoubleToFixed(yscale), XDoubleToFixed(0)},
{XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(1)}}};
XRenderSetPictureTransform(data->display, src, &xform);
/* Black magic follows. */
if (texture->blendMode == SDL_BLENDMODE_MOD) {
/* Copy the dst to a temp buffer. */
XRenderComposite(data->display, PictOpSrc, data->drawable_pict,
src, data->stencil_pict,
dstrect->x, dstrect->y, srcrect->x, srcrect->y,
dstrect->x, dstrect->y, dstrect->w, dstrect->h);
/* Set the compnent alpha flag on the temp buffer. */
attr.component_alpha = True;
XRenderChangePicture(data->display, data->stencil_pict,
CPComponentAlpha, &attr);
}
/* Set the picture filter only if a scaling mode is set. */
if (texture->scaleMode != SDL_SCALEMODE_NONE) {
XRenderSetPictureFilter(data->display, src,
texturedata->filter, 0, 0);
}
XRenderComposite(data->display, texturedata->blend_op,
src, mask, data->drawable_pict,
srcrect->x, srcrect->y, mrect->x, mrect->y,
dstrect->x, dstrect->y, dstrect->w, dstrect->h);
/* Set the texture transformation back to the identity matrix. */
XTransform identity = {{
{XDoubleToFixed(1), XDoubleToFixed(0), XDoubleToFixed(0)},
{XDoubleToFixed(0), XDoubleToFixed(1), XDoubleToFixed(0)},
{XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(1)}}};
XRenderSetPictureTransform(data->display, src, &identity);
}
/* Reset the component alpha flag only when
* the blending mode is SDL_BLENDMODE_MOD. */
if (renderer->blendMode == SDL_BLENDMODE_MOD) {
attr.component_alpha = False;
XRenderChangePicture(data->display, data->stencil_pict,
CPComponentAlpha, &attr);
}
}
else
#endif
{
if (srcrect->w == dstrect->w && srcrect->h == dstrect->h) {
#ifndef NO_SHARED_MEMORY
if (texturedata->shminfo.shmaddr) {
XShmPutImage(data->display, data->drawable, data->gc,
texturedata->image, srcrect->x, srcrect->y,
dstrect->x, dstrect->y, srcrect->w, srcrect->h,
False);
} else
#endif
if (texturedata->pixels) {
XPutImage(data->display, data->drawable, data->gc,
texturedata->image, srcrect->x, srcrect->y, dstrect->x,
dstrect->y, srcrect->w, srcrect->h);
} else {
XCopyArea(data->display, texturedata->pixmap, data->drawable,
data->gc, srcrect->x, srcrect->y, dstrect->w,
dstrect->h, dstrect->x, dstrect->y);
}
} else if (texturedata->yuv
|| texture->access == SDL_TEXTUREACCESS_STREAMING) {
SDL_Surface src, dst;
SDL_PixelFormat fmt;
SDL_Rect rect;
XImage *image = texturedata->scaling_image;
if (!image) {
void *pixels;
int pitch;
pitch = dstrect->w * SDL_BYTESPERPIXEL(texturedata->format);
pixels = SDL_malloc(dstrect->h * pitch);
if (!pixels) {
SDL_OutOfMemory();
return -1;
}
image =
XCreateImage(data->display, data->visual, data->depth,
ZPixmap, 0, pixels, dstrect->w, dstrect->h,
SDL_BYTESPERPIXEL(texturedata->format) * 8,
pitch);
if (!image) {
SDL_SetError("XCreateImage() failed");
return -1;
}
texturedata->scaling_image = image;
} else if (image->width != dstrect->w || image->height != dstrect->h
|| !image->data) {
image->width = dstrect->w;
image->height = dstrect->h;
image->bytes_per_line =
image->width * SDL_BYTESPERPIXEL(texturedata->format);
image->data =
(char *) SDL_realloc(image->data,
image->height * image->bytes_per_line);
if (!image->data) {
SDL_OutOfMemory();
return -1;
}
}
/* Set up fake surfaces for SDL_SoftStretch() */
SDL_zero(src);
src.format = &fmt;
src.w = texture->w;
src.h = texture->h;
#ifndef NO_SHARED_MEMORY
if (texturedata->shminfo.shmaddr) {
src.pixels = texturedata->shminfo.shmaddr;
} else
#endif
src.pixels = texturedata->pixels;
src.pitch = texturedata->pitch;
SDL_zero(dst);
dst.format = &fmt;
dst.w = image->width;
dst.h = image->height;
dst.pixels = image->data;
dst.pitch = image->bytes_per_line;
fmt.BytesPerPixel = SDL_BYTESPERPIXEL(texturedata->format);
rect.x = 0;
rect.y = 0;
rect.w = dstrect->w;
rect.h = dstrect->h;
if (SDL_SoftStretch(&src, srcrect, &dst, &rect) < 0) {
return -1;
}
XPutImage(data->display, data->drawable, data->gc, image, 0, 0,
dstrect->x, dstrect->y, dstrect->w, dstrect->h);
} else {
XCopyArea(data->display, texturedata->pixmap, data->drawable,
data->gc, srcrect->x, srcrect->y, dstrect->w, dstrect->h,
srcrect->x, srcrect->y);
}
}
return 0;
}
static int
X11_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
Uint32 format, void * pixels, int pitch)
{
X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
SDL_Window *window = renderer->window;
SDL_VideoDisplay *display = window->display;
Uint32 screen_format = display->current_mode.format;
XImage *image;
image = XGetImage(data->display, data->drawable, rect->x, rect->y,
rect->w, rect->h, AllPlanes, ZPixmap);
SDL_ConvertPixels(rect->w, rect->h,
screen_format, image->data, image->bytes_per_line,
format, pixels, pitch);
XDestroyImage(image);
return 0;
}
static int
X11_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
Uint32 format, const void * pixels, int pitch)
{
X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
SDL_Window *window = renderer->window;
SDL_VideoDisplay *display = window->display;
Uint32 screen_format = display->current_mode.format;
XImage *image;
void *image_pixels;
int image_pitch;
image_pitch = rect->w * SDL_BYTESPERPIXEL(screen_format);
image_pixels = SDL_malloc(rect->h * image_pitch);
if (!image_pixels) {
SDL_OutOfMemory();
return -1;
}
image = XCreateImage(data->display, data->visual,
data->depth, ZPixmap, 0, image_pixels,
rect->w, rect->h,
SDL_BYTESPERPIXEL(screen_format) * 8,
image_pitch);
if (!image) {
SDL_SetError("XCreateImage() failed");
return -1;
}
SDL_ConvertPixels(rect->w, rect->h,
format, pixels, pitch,
screen_format, image->data, image->bytes_per_line);
XPutImage(data->display, data->drawable, data->gc,
image, 0, 0, rect->x, rect->y, rect->w, rect->h);
image->data = NULL;
XDestroyImage(image);
SDL_free(image_pixels);
return 0;
}
static void
X11_RenderPresent(SDL_Renderer * renderer)
{
X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
SDL_DirtyRect *dirty;
/* Send the data to the display */
if (!(renderer->info.flags & SDL_RENDERER_SINGLEBUFFER)) {
for (dirty = data->dirty.list; dirty; dirty = dirty->next) {
const SDL_Rect *rect = &dirty->rect;
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender)
{
XRenderComposite(data->display,
data->blend_op,
data->drawable_pict,
None,
data->xwindow_pict,
rect->x, rect->y,
0, 0,
rect->x, rect->y,
rect->w, rect->h);
}
else
#endif
{
XCopyArea(data->display, data->drawable, data->xwindow,
data->gc, rect->x, rect->y, rect->w, rect->h,
rect->x, rect->y);
}
}
SDL_ClearDirtyRects(&data->dirty);
}
XSync(data->display, False);
/* Update the flipping chain, if any */
if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) {
data->current_pixmap = (data->current_pixmap + 1) % 2;
data->drawable = data->pixmaps[data->current_pixmap];
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
data->drawable_pict = data->pixmap_picts[data->current_pixmap];
#endif
} else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP3) {
data->current_pixmap = (data->current_pixmap + 1) % 3;
data->drawable = data->pixmaps[data->current_pixmap];
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
data->drawable_pict = data->pixmap_picts[data->current_pixmap];
#endif
}
}
static void
X11_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
{
X11_RenderData *renderdata = (X11_RenderData *) renderer->driverdata;
X11_TextureData *data = (X11_TextureData *) texture->driverdata;
if (!data) {
return;
}
if (data->yuv) {
SDL_SW_DestroyYUVTexture(data->yuv);
}
if (data->pixmap != None) {
XFreePixmap(renderdata->display, data->pixmap);
}
if (data->image) {
data->image->data = NULL;
XDestroyImage(data->image);
}
#ifndef NO_SHARED_MEMORY
if (data->shminfo.shmaddr) {
XShmDetach(renderdata->display, &data->shminfo);
XSync(renderdata->display, False);
shmdt(data->shminfo.shmaddr);
data->pixels = NULL;
}
#endif
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (renderdata->use_xrender) {
if (data->picture) {
XRenderFreePicture(renderdata->display, data->picture);
}
if (data->modulated_pixmap) {
XFreePixmap(renderdata->display, data->modulated_pixmap);
}
if (data->modulated_picture) {
XRenderFreePicture(renderdata->display, data->modulated_picture);
}
}
#endif
if (data->scaling_image) {
SDL_free(data->scaling_image->data);
data->scaling_image->data = NULL;
XDestroyImage(data->scaling_image);
}
if (data->pixels) {
SDL_free(data->pixels);
}
SDL_free(data);
texture->driverdata = NULL;
}
static void
X11_DestroyRenderer(SDL_Renderer * renderer)
{
X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
int i;
if (data) {
for (i = 0; i < SDL_arraysize(data->pixmaps); ++i) {
if (data->pixmaps[i] != None) {
XFreePixmap(data->display, data->pixmaps[i]);
}
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender && data->pixmap_picts[i]) {
XRenderFreePicture(data->display, data->pixmap_picts[i]);
}
#endif
}
if (data->gc) {
XFreeGC(data->display, data->gc);
}
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender) {
if (data->stencil_gc) {
XFreeGC(data->display, data->stencil_gc);
}
if (data->stencil) {
XFreePixmap(data->display, data->stencil);
}
if (data->stencil_pict) {
XRenderFreePicture(data->display, data->stencil_pict);
}
if (data->xwindow_pict) {
XRenderFreePicture(data->display, data->xwindow_pict);
}
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (data->use_xdamage && data->stencil_damage) {
XDamageDestroy(data->display, data->stencil_damage);
}
#endif
}
#endif
SDL_FreeDirtyRects(&data->dirty);
SDL_free(data);
}
SDL_free(renderer);
}
#endif /* SDL_VIDEO_RENDER_X11 */
/* vi: set ts=4 sw=4 expandtab: */
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
/* SDL surface based renderer implementation */
#if SDL_VIDEO_RENDER_X11
extern void X11_AddRenderDriver(_THIS);
#endif
/* vi: set ts=4 sw=4 expandtab: */
...@@ -350,10 +350,6 @@ X11_VideoInit(_THIS) ...@@ -350,10 +350,6 @@ X11_VideoInit(_THIS)
return -1; return -1;
} }
#if SDL_VIDEO_RENDER_X11
X11_AddRenderDriver(_this);
#endif
if (X11_InitKeyboard(_this) != 0) { if (X11_InitKeyboard(_this) != 0) {
return -1; return -1;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment