comparison src/video/x11/SDL_x11render.c @ 4618:844b5ef4b149

Merged Sunny's XRender changes from SDL-gsoc2010_xrender
author Sam Lantinga <slouken@libsdl.org>
date Wed, 28 Jul 2010 00:54:23 -0700
parents 791b3256fb22 cfbb1ff4b8ec
children b9a205e6369f
comparison
equal deleted inserted replaced
4569:e1664f94f026 4618:844b5ef4b149
1 /* 1 /*
2
2 SDL - Simple DirectMedia Layer 3 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2010 Sam Lantinga 4 Copyright (C) 1997-2010 Sam Lantinga
4 5
5 This library is free software; you can redistribute it and/or 6 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public 7 modify it under the terms of the GNU Lesser General Public
37 static int X11_DisplayModeChanged(SDL_Renderer * renderer); 38 static int X11_DisplayModeChanged(SDL_Renderer * renderer);
38 static int X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture); 39 static int X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
39 static int X11_QueryTexturePixels(SDL_Renderer * renderer, 40 static int X11_QueryTexturePixels(SDL_Renderer * renderer,
40 SDL_Texture * texture, void **pixels, 41 SDL_Texture * texture, void **pixels,
41 int *pitch); 42 int *pitch);
43 static int X11_SetTextureRGBAMod(SDL_Renderer * renderer,
44 SDL_Texture * texture);
42 static int X11_SetTextureBlendMode(SDL_Renderer * renderer, 45 static int X11_SetTextureBlendMode(SDL_Renderer * renderer,
43 SDL_Texture * texture); 46 SDL_Texture * texture);
44 static int X11_SetTextureScaleMode(SDL_Renderer * renderer, 47 static int X11_SetTextureScaleMode(SDL_Renderer * renderer,
45 SDL_Texture * texture); 48 SDL_Texture * texture);
46 static int X11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, 49 static int X11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
94 Visual *visual; 97 Visual *visual;
95 int depth; 98 int depth;
96 int scanline_pad; 99 int scanline_pad;
97 Window xwindow; 100 Window xwindow;
98 Pixmap pixmaps[3]; 101 Pixmap pixmaps[3];
102 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
103 Pixmap stencil;
104 Pixmap brush;
105 Picture brush_pict;
106 Picture xwindow_pict;
107 Picture pixmap_picts[3];
108 Picture drawable_pict;
109 Picture stencil_pict;
110 int blend_op;
111 XRenderPictFormat *xwindow_pict_fmt;
112 XRenderPictFormat *drawable_pict_fmt;
113 GC stencil_gc;
114 SDL_bool use_xrender;
115 #ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
116 SDL_bool use_xdamage;
117 Damage stencil_damage;
118 XserverRegion stencil_parts;
119 #endif
120 #endif
99 int current_pixmap; 121 int current_pixmap;
100 Drawable drawable; 122 Drawable drawable;
101 SDL_PixelFormat format; 123 SDL_PixelFormat format;
102 GC gc; 124 GC gc;
103 SDL_DirtyRectList dirty; 125 SDL_DirtyRectList dirty;
107 typedef struct 129 typedef struct
108 { 130 {
109 SDL_SW_YUVTexture *yuv; 131 SDL_SW_YUVTexture *yuv;
110 Uint32 format; 132 Uint32 format;
111 Pixmap pixmap; 133 Pixmap pixmap;
134 int depth;
135 Visual *visual;
136 GC gc;
137 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
138 Picture picture;
139 Pixmap modulated_pixmap;
140 Picture modulated_picture;
141 XRenderPictFormat* picture_fmt;
142 int blend_op;
143 const char* filter;
144 #endif
112 XImage *image; 145 XImage *image;
113 #ifndef NO_SHARED_MEMORY 146 #ifndef NO_SHARED_MEMORY
114 /* MIT shared memory extension information */ 147 /* MIT shared memory extension information */
115 XShmSegmentInfo shminfo; 148 XShmSegmentInfo shminfo;
116 #endif 149 #endif
147 rect.h = texture->h; 180 rect.h = texture->h;
148 SDL_SW_CopyYUVToRGB(data->yuv, &rect, data->format, texture->w, 181 SDL_SW_CopyYUVToRGB(data->yuv, &rect, data->format, texture->w,
149 texture->h, data->pixels, data->pitch); 182 texture->h, data->pixels, data->pitch);
150 } 183 }
151 184
185 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
186 static SDL_bool
187 CheckXRender(Display *display, int *major, int *minor) {
188 const char *env;
189
190 *major = *minor = 0;
191
192 env = SDL_getenv("SDL_VIDEO_X11_XRENDER");
193
194 if (env && !SDL_atoi(env)) {
195 return SDL_FALSE;
196 }
197
198 if (!SDL_X11_HAVE_XRENDER) {
199 return SDL_FALSE;
200 }
201
202 if (!XRenderQueryVersion(display, major, minor)) {
203 return SDL_FALSE;
204 }
205
206 return SDL_TRUE;
207 }
208 #endif
209
210 #ifdef SDL_VIDEO_DRIVER_X11_XFIXES
211 static SDL_bool
212 CheckXFixes(Display *display, int *major, int *minor) {
213 const char *env;
214
215 *major = *minor = 0;
216
217 env = SDL_getenv("SDL_VIDEO_X11_XFIXES");
218
219 if (env && !SDL_atoi(env)) {
220 return SDL_FALSE;
221 }
222
223 if (!SDL_X11_HAVE_XFIXES) {
224 return SDL_FALSE;
225 }
226
227 if (!XFixesQueryVersion(display, major, minor)) {
228 return SDL_FALSE;
229 }
230
231 return SDL_TRUE;
232 }
233 #endif
234
235 #ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
236 static SDL_bool
237 CheckXDamage(Display *display, int *major, int *minor) {
238 const char *env;
239
240 *major = *minor = 0;
241
242 env = SDL_getenv("SDL_VIDEO_X11_XDAMAGE");
243
244 if (env && !SDL_atoi(env)) {
245 return SDL_FALSE;
246 }
247
248 if (!SDL_X11_HAVE_XDAMAGE) {
249 return SDL_FALSE;
250 }
251
252 if (!XDamageQueryVersion(display, major, minor)) {
253 return SDL_FALSE;
254 }
255
256 return SDL_TRUE;
257 }
258 #endif
259
260 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
261 static Uint32
262 XRenderPictFormatToSDLPixelFormatEnum(XRenderPictFormat *pict_format) {
263 if (pict_format->type != PictTypeDirect) {
264 SDL_SetError("Indexed pict formats not supported ATM");
265 return 0;
266 }
267 Uint32 Amask, Rmask, Gmask, Bmask;
268 int bpp;
269
270 Rmask = pict_format->direct.redMask << pict_format->direct.red;
271 Gmask = pict_format->direct.greenMask << pict_format->direct.green;
272 Bmask = pict_format->direct.blueMask << pict_format->direct.blue;
273 Amask = pict_format->direct.alphaMask << pict_format->direct.alpha;
274 bpp = pict_format->depth;
275
276 Uint32 format;
277 format = SDL_MasksToPixelFormatEnum(bpp, Rmask, Gmask, Bmask, Amask);
278 return format;
279 }
280 #endif
281
152 void 282 void
153 X11_AddRenderDriver(_THIS) 283 X11_AddRenderDriver(_THIS)
154 { 284 {
155 SDL_RendererInfo *info = &X11_RenderDriver.info; 285 SDL_RendererInfo *info = &X11_RenderDriver.info;
156 SDL_DisplayMode *mode = &SDL_CurrentDisplay->desktop_mode; 286 SDL_DisplayMode *mode = &SDL_CurrentDisplay->desktop_mode;
287 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
157 int i; 288 int i;
158 289
159 info->texture_formats[info->num_texture_formats++] = mode->format; 290 info->texture_formats[info->num_texture_formats++] = mode->format;
160 info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_YV12; 291 info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_YV12;
161 info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_IYUV; 292 info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_IYUV;
162 info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_YUY2; 293 info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_YUY2;
163 info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_UYVY; 294 info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_UYVY;
164 info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_YVYU; 295 info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_YVYU;
165 296
297 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
298 int major, minor;
299 if (CheckXRender(data->display, &major, &minor)) {
300 XRenderPictFormat templ;
301 templ.type = PictTypeDirect;
302 XRenderPictFormat *pict_format;
303 Uint32 format;
304 int i = 0;
305 while (info->num_texture_formats < 50) {
306 pict_format =
307 XRenderFindFormat(data->display, PictFormatType, &templ, i++);
308 if (pict_format) {
309 format = XRenderPictFormatToSDLPixelFormatEnum(pict_format);
310 if (format != SDL_PIXELTYPE_UNKNOWN) {
311 info->texture_formats[info->num_texture_formats++] = format;
312 }
313 }
314 else
315 break;
316 }
317 info->blend_modes |= (SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD |
318 SDL_BLENDMODE_MOD | SDL_BLENDMODE_MASK);
319 info->scale_modes |= (SDL_TEXTURESCALEMODE_FAST | SDL_TEXTURESCALEMODE_SLOW |
320 SDL_TEXTURESCALEMODE_BEST);
321 info->mod_modes |= (SDL_TEXTUREMODULATE_COLOR | SDL_TEXTUREMODULATE_ALPHA);
322 }
323 #endif
324
166 for (i = 0; i < _this->num_displays; ++i) { 325 for (i = 0; i < _this->num_displays; ++i) {
167 SDL_AddRenderDriver(&_this->displays[i], &X11_RenderDriver); 326 SDL_AddRenderDriver(&_this->displays[i], &X11_RenderDriver);
168 } 327 }
169 } 328 }
170 329
175 SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata; 334 SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
176 SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata; 335 SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata;
177 SDL_Renderer *renderer; 336 SDL_Renderer *renderer;
178 X11_RenderData *data; 337 X11_RenderData *data;
179 XGCValues gcv; 338 XGCValues gcv;
339 gcv.graphics_exposures = False;
180 int i, n; 340 int i, n;
181 int bpp; 341 int bpp;
182 Uint32 Rmask, Gmask, Bmask, Amask; 342 Uint32 Rmask, Gmask, Bmask, Amask;
183 343
184 renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer)); 344 renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
197 data->screen = displaydata->screen; 357 data->screen = displaydata->screen;
198 data->visual = displaydata->visual; 358 data->visual = displaydata->visual;
199 data->depth = displaydata->depth; 359 data->depth = displaydata->depth;
200 data->scanline_pad = displaydata->scanline_pad; 360 data->scanline_pad = displaydata->scanline_pad;
201 data->xwindow = windowdata->xwindow; 361 data->xwindow = windowdata->xwindow;
202 362
203 renderer->DisplayModeChanged = X11_DisplayModeChanged; 363 renderer->DisplayModeChanged = X11_DisplayModeChanged;
204 renderer->CreateTexture = X11_CreateTexture; 364 renderer->CreateTexture = X11_CreateTexture;
205 renderer->QueryTexturePixels = X11_QueryTexturePixels; 365 renderer->QueryTexturePixels = X11_QueryTexturePixels;
366 renderer->SetTextureAlphaMod = X11_SetTextureRGBAMod;
367 renderer->SetTextureColorMod = X11_SetTextureRGBAMod;
206 renderer->SetTextureBlendMode = X11_SetTextureBlendMode; 368 renderer->SetTextureBlendMode = X11_SetTextureBlendMode;
207 renderer->SetTextureScaleMode = X11_SetTextureScaleMode; 369 renderer->SetTextureScaleMode = X11_SetTextureScaleMode;
208 renderer->UpdateTexture = X11_UpdateTexture; 370 renderer->UpdateTexture = X11_UpdateTexture;
209 renderer->LockTexture = X11_LockTexture; 371 renderer->LockTexture = X11_LockTexture;
210 renderer->UnlockTexture = X11_UnlockTexture; 372 renderer->UnlockTexture = X11_UnlockTexture;
223 renderer->window = window; 385 renderer->window = window;
224 renderer->driverdata = data; 386 renderer->driverdata = data;
225 387
226 renderer->info.flags = SDL_RENDERER_ACCELERATED; 388 renderer->info.flags = SDL_RENDERER_ACCELERATED;
227 389
390 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
391 int major, minor;
392 data->use_xrender = CheckXRender(data->display, &major, &minor);
393 #ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
394 if (CheckXDamage(data->display, &major, &minor)) {
395 if (CheckXFixes(data->display, &major, &minor)) {
396 if (major >= 2)
397 data->use_xdamage = SDL_TRUE;
398 }
399 }
400 #endif
401 if (data->use_xrender) {
402 /* Find the PictFormat from the visual.
403 * Should be an RGB PictFormat most of the time. */
404 data->xwindow_pict_fmt = XRenderFindVisualFormat(data->display,
405 data->visual);
406 if (!data->xwindow_pict_fmt) {
407 SDL_SetError("XRenderFindVisualFormat() failed");
408 return NULL;
409 }
410 data->xwindow_pict = XRenderCreatePicture(data->display,
411 data->xwindow,
412 data->xwindow_pict_fmt,
413 0, NULL);
414 if (!data->xwindow_pict) {
415 SDL_SetError("XRenderCreatePicture() failed");
416 return NULL;
417 }
418 // FIXME: Clear the window. Is this required?
419 XRenderComposite(data->display,
420 PictOpClear,
421 data->xwindow_pict,
422 None,
423 data->xwindow_pict,
424 0, 0,
425 0, 0,
426 0, 0,
427 window->w, window->h);
428 /* Create a clip mask that is used for rendering primitives. */
429 data->stencil = XCreatePixmap(data->display, data->xwindow,
430 window->w, window->h, 32);
431
432 /* Create the GC for the clip mask. */
433 data->stencil_gc = XCreateGC(data->display, data->stencil,
434 GCGraphicsExposures, &gcv);
435 XSetBackground(data->display, data->stencil_gc, 0);
436 XSetForeground(data->display, data->stencil_gc, 0);
437 XFillRectangle(data->display, data->stencil, data->stencil_gc,
438 0, 0, window->w, window->h);
439 XSetForeground(data->display, data->stencil_gc, 0xFFFFFFFF);
440 data->stencil_pict =
441 XRenderCreatePicture(data->display, data->stencil,
442 XRenderFindStandardFormat(data->display,
443 PictStandardARGB32),
444 0, NULL);
445 #ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
446 if (data->use_xdamage) {
447 data->stencil_damage =
448 XDamageCreate(data->display, data->stencil, XDamageReportNonEmpty);
449 XDamageSubtract(data->display, data->stencil_damage, None, data->stencil_parts);
450 }
451 #endif
452 data->brush =
453 XCreatePixmap(data->display, data->xwindow, 1, 1, 32);
454 XRenderPictureAttributes brush_attr;
455 brush_attr.repeat = RepeatNormal;
456 data->brush_pict =
457 XRenderCreatePicture(data->display, data->brush,
458 XRenderFindStandardFormat(data->display,
459 PictStandardARGB32),
460 CPRepeat, &brush_attr);
461 // Set the default blending mode.
462 renderer->blendMode = SDL_BLENDMODE_BLEND;
463 data->blend_op = PictOpOver;
464 }
465 #endif
228 if (flags & SDL_RENDERER_SINGLEBUFFER) { 466 if (flags & SDL_RENDERER_SINGLEBUFFER) {
229 renderer->info.flags |= 467 renderer->info.flags |=
230 (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY); 468 (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY);
231 n = 0; 469 n = 0;
232 } else if (flags & SDL_RENDERER_PRESENTFLIP2) { 470 } else if (flags & SDL_RENDERER_PRESENTFLIP2) {
237 n = 3; 475 n = 3;
238 } else { 476 } else {
239 renderer->info.flags |= SDL_RENDERER_PRESENTCOPY; 477 renderer->info.flags |= SDL_RENDERER_PRESENTCOPY;
240 n = 1; 478 n = 1;
241 } 479 }
480 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
481 if (data->use_xrender) {
482 if (n > 0)
483 data->drawable_pict_fmt =
484 XRenderFindStandardFormat(data->display, PictStandardARGB32);
485 else
486 data->drawable_pict_fmt = data->xwindow_pict_fmt;
487 }
488 #endif
242 for (i = 0; i < n; ++i) { 489 for (i = 0; i < n; ++i) {
243 data->pixmaps[i] = 490 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
244 XCreatePixmap(data->display, data->xwindow, window->w, window->h, 491 if (data->use_xrender) {
245 displaydata->depth); 492 data->pixmaps[i] = XCreatePixmap(data->display,
493 data->xwindow,
494 window->w,
495 window->h,
496 32);
497 }
498 else
499 #endif
500 {
501 data->pixmaps[i] =
502 XCreatePixmap(data->display, data->xwindow, window->w, window->h,
503 displaydata->depth);
504 }
246 if (data->pixmaps[i] == None) { 505 if (data->pixmaps[i] == None) {
247 X11_DestroyRenderer(renderer); 506 X11_DestroyRenderer(renderer);
248 SDL_SetError("XCreatePixmap() failed"); 507 SDL_SetError("XCreatePixmap() failed");
249 return NULL; 508 return NULL;
250 } 509 }
510 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
511 if (data->use_xrender) {
512 /* Create xrender pictures for each of the pixmaps
513 * and clear the pixmaps. */
514 data->pixmap_picts[i] =
515 XRenderCreatePicture(data->display,
516 data->pixmaps[i],
517 XRenderFindStandardFormat(data->display,
518 PictStandardARGB32),
519 0, None);
520 if (!data->pixmap_picts[i]) {
521 SDL_SetError("XRenderCreatePicture() failed");
522 return NULL;
523 }
524
525 XRenderComposite(data->display,
526 PictOpClear,
527 data->pixmap_picts[i],
528 None,
529 data->pixmap_picts[i],
530 0, 0,
531 0, 0,
532 0, 0,
533 window->w, window->h);
534 }
535 #endif
251 } 536 }
252 if (n > 0) { 537 if (n > 0) {
253 data->drawable = data->pixmaps[0]; 538 data->drawable = data->pixmaps[0];
539 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
540 if(data->use_xrender == SDL_TRUE)
541 data->drawable_pict = data->pixmap_picts[0];
542 #endif
254 data->makedirty = SDL_TRUE; 543 data->makedirty = SDL_TRUE;
255 } else { 544 } else {
256 data->drawable = data->xwindow; 545 data->drawable = data->xwindow;
546 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
547 if(data->use_xrender == SDL_TRUE)
548 data->drawable_pict = data->xwindow_pict;
549 #endif
257 data->makedirty = SDL_FALSE; 550 data->makedirty = SDL_FALSE;
258 } 551 }
259 data->current_pixmap = 0; 552 data->current_pixmap = 0;
260 553
261 /* Get the format of the window */ 554 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
262 if (!SDL_PixelFormatEnumToMasks 555 if (data->use_xrender) {
263 (display->current_mode.format, &bpp, &Rmask, &Gmask, &Bmask, 556 bpp = data->drawable_pict_fmt->depth;
264 &Amask)) { 557 Rmask = ((data->drawable_pict_fmt->direct.redMask)
265 SDL_SetError("Unknown display format"); 558 << (data->drawable_pict_fmt->direct.red));
266 X11_DestroyRenderer(renderer); 559 Gmask = ((data->drawable_pict_fmt->direct.greenMask)
267 return NULL; 560 << (data->drawable_pict_fmt->direct.green));
561 Bmask = ((data->drawable_pict_fmt->direct.blueMask)
562 << (data->drawable_pict_fmt->direct.blue));
563 Amask = ((data->drawable_pict_fmt->direct.alphaMask)
564 << (data->drawable_pict_fmt->direct.alpha));
565 }
566 else
567 #endif
568 {
569 /* Get the format of the window */
570 if (!SDL_PixelFormatEnumToMasks
571 (display->current_mode.format, &bpp, &Rmask, &Gmask, &Bmask,
572 &Amask)) {
573 SDL_SetError("Unknown display format");
574 X11_DestroyRenderer(renderer);
575 return NULL;
576 }
268 } 577 }
269 SDL_InitFormat(&data->format, bpp, Rmask, Gmask, Bmask, Amask); 578 SDL_InitFormat(&data->format, bpp, Rmask, Gmask, Bmask, Amask);
270 579
271 /* Create the drawing context */ 580 /* Create the drawing context */
272 gcv.graphics_exposures = False; 581 gcv.graphics_exposures = False;
273 data->gc = 582 data->gc =
274 XCreateGC(data->display, data->xwindow, GCGraphicsExposures, &gcv); 583 XCreateGC(data->display, data->drawable, GCGraphicsExposures, &gcv);
275 if (!data->gc) { 584 if (!data->gc) {
276 X11_DestroyRenderer(renderer); 585 X11_DestroyRenderer(renderer);
277 SDL_SetError("XCreateGC() failed"); 586 SDL_SetError("XCreateGC() failed");
278 return NULL; 587 return NULL;
279 } 588 }
286 { 595 {
287 X11_RenderData *data = (X11_RenderData *) renderer->driverdata; 596 X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
288 SDL_Window *window = renderer->window; 597 SDL_Window *window = renderer->window;
289 int i, n; 598 int i, n;
290 599
600 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
601 if (data->use_xrender) {
602 XRenderFreePicture(data->display, data->xwindow_pict);
603
604 data->xwindow_pict_fmt =
605 XRenderFindVisualFormat(data->display, data->visual);
606 data->xwindow_pict =
607 XRenderCreatePicture(data->display, data->xwindow,
608 data->xwindow_pict_fmt, 0, NULL);
609
610 XRenderComposite(data->display,
611 PictOpClear,
612 data->xwindow_pict,
613 None,
614 data->xwindow_pict,
615 0, 0,
616 0, 0,
617 0, 0,
618 window->w, window->h);
619
620 XFreePixmap(data->display, data->stencil);
621 /* Create a clip mask that is used for rendering primitives. */
622 data->stencil = XCreatePixmap(data->display, data->xwindow,
623 window->w, window->h, 32);
624
625 XRenderFreePicture(data->display, data->stencil_pict);
626 data->stencil_pict =
627 XRenderCreatePicture(data->display, data->stencil,
628 XRenderFindStandardFormat(data->display,
629 PictStandardARGB32),
630 0, NULL);
631 #ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
632 XDamageDestroy(data->display, data->stencil_damage);
633 if (data->use_xdamage) {
634 data->stencil_damage =
635 XDamageCreate(data->display, data->stencil, XDamageReportNonEmpty);
636 XDamageSubtract(data->display, data->stencil_damage, None, data->stencil_parts);
637 }
638 #endif
639 }
640 #endif
291 if (renderer->info.flags & SDL_RENDERER_SINGLEBUFFER) { 641 if (renderer->info.flags & SDL_RENDERER_SINGLEBUFFER) {
292 n = 0; 642 n = 0;
293 } else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) { 643 } else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) {
294 n = 2; 644 n = 2;
295 } else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP3) { 645 } else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP3) {
299 } 649 }
300 for (i = 0; i < n; ++i) { 650 for (i = 0; i < n; ++i) {
301 if (data->pixmaps[i] != None) { 651 if (data->pixmaps[i] != None) {
302 XFreePixmap(data->display, data->pixmaps[i]); 652 XFreePixmap(data->display, data->pixmaps[i]);
303 data->pixmaps[i] = None; 653 data->pixmaps[i] = None;
654 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
655 XRenderFreePicture(data->display, data->pixmap_picts[i]);
656 data->pixmap_picts[i] = None;
657 #endif
304 } 658 }
305 } 659 }
306 for (i = 0; i < n; ++i) { 660 for (i = 0; i < n; ++i) {
307 data->pixmaps[i] = 661 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
308 XCreatePixmap(data->display, data->xwindow, window->w, window->h, 662 if (data->use_xrender) {
309 data->depth); 663 data->pixmaps[i] =
664 XCreatePixmap(data->display,
665 data->xwindow,
666 window->w,
667 window->h,
668 32);
669 }
670 else
671 #endif
672 {
673 data->pixmaps[i] =
674 XCreatePixmap(data->display, data->xwindow, window->w, window->h,
675 data->depth);
676 }
310 if (data->pixmaps[i] == None) { 677 if (data->pixmaps[i] == None) {
311 SDL_SetError("XCreatePixmap() failed"); 678 SDL_SetError("XCreatePixmap() failed");
312 return -1; 679 return -1;
313 } 680 }
681 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
682 if (data->use_xrender) {
683 data->pixmap_picts[i] =
684 XRenderCreatePicture(data->display,
685 data->pixmaps[i],
686 XRenderFindStandardFormat(data->display,
687 PictStandardARGB32),
688 0, None);
689 if (!data->pixmap_picts[i]) {
690 SDL_SetError("XRenderCreatePicture() failed");
691 return -1;
692 }
693 XRenderComposite(data->display,
694 PictOpClear,
695 data->pixmap_picts[i],
696 None,
697 data->pixmap_picts[i],
698 0, 0,
699 0, 0,
700 0, 0,
701 window->w, window->h);
702
703 }
704 #endif
314 } 705 }
315 if (n > 0) { 706 if (n > 0) {
316 data->drawable = data->pixmaps[0]; 707 data->drawable = data->pixmaps[0];
708 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
709 data->drawable_pict = data->pixmap_picts[0];
710 #endif
317 } 711 }
318 data->current_pixmap = 0; 712 data->current_pixmap = 0;
319 713
320 return 0; 714 return 0;
321 } 715 }
716
717 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
718 static void
719 SDLMaskToXRenderMask(Uint32 sdl_mask, short *comp, short *compMask) {
720 if (sdl_mask == 0) {
721 *comp = 0;
722 *compMask = 0;
723 } else {
724 (*comp) = 0;
725 (*compMask) = 0;
726 while(!(sdl_mask & 1)) {
727 (*comp)++;
728 sdl_mask >>= 1;
729 }
730 while(sdl_mask & 1) {
731 (*compMask) = ((*compMask) << 1) | 1;
732 sdl_mask >>= 1;
733 }
734 }
735 }
736
737 static XRenderPictFormat*
738 PixelFormatEnumToXRenderPictFormat(SDL_Renderer * renderer, Uint32 format) {
739 XRenderPictFormat* pict_fmt = NULL;
740 X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
741
742 if (data->use_xrender) {
743
744 int bpp;
745 Uint32 Amask, Rmask, Gmask, Bmask;
746 if(!SDL_PixelFormatEnumToMasks(format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
747 SDL_SetError("Unknown pixel format");
748 return NULL;
749 }
750 XRenderPictFormat templ;
751 unsigned long mask = (PictFormatType | PictFormatDepth | PictFormatRed |
752 PictFormatRedMask | PictFormatGreen | PictFormatGreenMask |
753 PictFormatBlue | PictFormatBlueMask | PictFormatAlpha |
754 PictFormatAlphaMask);
755
756 templ.type = PictTypeDirect;
757 templ.depth = bpp;
758 SDLMaskToXRenderMask(Amask, &(templ.direct.alpha), &(templ.direct.alphaMask));
759 SDLMaskToXRenderMask(Rmask, &(templ.direct.red), &(templ.direct.redMask));
760 SDLMaskToXRenderMask(Gmask, &(templ.direct.green), &(templ.direct.greenMask));
761 SDLMaskToXRenderMask(Bmask, &(templ.direct.blue), &(templ.direct.blueMask));
762 pict_fmt = XRenderFindFormat(data->display, mask, &templ, 0);
763 }
764
765 return pict_fmt;
766 }
767
768
769 static Visual*
770 PixelFormatEnumToVisual(SDL_Renderer * renderer, Uint32 format) {
771 X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
772
773 if (data->use_xrender) {
774 int bpp;
775 Uint32 Amask, Rmask, Gmask, Bmask;
776 SDL_PixelFormatEnumToMasks(format, &bpp, &Rmask, &Gmask, &Bmask, &Amask);
777
778 XVisualInfo vinfo_templ;
779 long vinfo_mask;
780 int nitems_return;
781
782 vinfo_mask = (VisualDepthMask | VisualRedMaskMask |
783 VisualGreenMaskMask | VisualBlueMaskMask);
784 vinfo_templ.depth = bpp;
785 vinfo_templ.red_mask = Rmask;
786 vinfo_templ.green_mask = Gmask;
787 vinfo_templ.blue_mask = Bmask;
788
789 XVisualInfo * ret = XGetVisualInfo(data->display, vinfo_mask,
790 &vinfo_templ, &nitems_return);
791
792 if (nitems_return) {
793 return ret[0].visual;
794 }
795 }
796
797 return NULL;
798 }
799
800 static XRenderColor
801 SDLColorToXRenderColor(Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
802 double rd, gd, bd, ad;
803 XRenderColor ret;
804 rd = r / 255.0;
805 gd = g / 255.0;
806 bd = b / 255.0;
807 ad = a / 255.0;
808
809 ret.red = (unsigned short) (rd * ad * 0xFFFF);
810 ret.green = (unsigned short) (gd * ad * 0xFFFF);
811 ret.blue = (unsigned short) (bd * ad * 0xFFFF);
812 ret.alpha = (unsigned short) (ad * 0xFFFF);
813
814 return ret;
815 }
816 #endif
322 817
323 static int 818 static int
324 X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) 819 X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
325 { 820 {
326 X11_RenderData *renderdata = (X11_RenderData *) renderer->driverdata; 821 X11_RenderData *renderdata = (X11_RenderData *) renderer->driverdata;
327 SDL_Window *window = renderer->window; 822 SDL_Window *window = renderer->window;
328 SDL_VideoDisplay *display = window->display; 823 SDL_VideoDisplay *display = window->display;
329 X11_TextureData *data; 824 X11_TextureData *data;
330 int pitch_alignmask = ((renderdata->scanline_pad / 8) - 1); 825 int pitch_alignmask = ((renderdata->scanline_pad / 8) - 1);
331 826 XGCValues gcv;
827
332 data = (X11_TextureData *) SDL_calloc(1, sizeof(*data)); 828 data = (X11_TextureData *) SDL_calloc(1, sizeof(*data));
333 if (!data) { 829 if (!data) {
334 SDL_OutOfMemory(); 830 SDL_OutOfMemory();
335 return -1; 831 return -1;
336 } 832 }
833 data->depth = renderdata->depth;
834 data->visual = renderdata->visual;
835 data->gc = renderdata->gc;
337 836
338 texture->driverdata = data; 837 texture->driverdata = data;
339
340 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { 838 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
341 data->yuv = 839 data->yuv =
342 SDL_SW_CreateYUVTexture(texture->format, texture->w, texture->h); 840 SDL_SW_CreateYUVTexture(texture->format, texture->w, texture->h);
343 if (!data->yuv) { 841 if (!data->yuv) {
344 return -1; 842 return -1;
345 } 843 }
346 data->format = display->current_mode.format; 844 data->format = display->current_mode.format;
347 } else { 845 } else {
348 /* The image/pixmap depth must be the same as the window or you 846 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
349 get a BadMatch error when trying to putimage or copyarea. 847 if (renderdata->use_xrender)
350 */ 848 {
351 if (texture->format != display->current_mode.format) { 849 Uint32 Amask, Rmask, Gmask, Bmask;
352 SDL_SetError("Texture format doesn't match window format"); 850 SDL_PixelFormatEnumToMasks(texture->format, &(data->depth),
353 return -1; 851 &Rmask, &Gmask, &Bmask, &Amask);
852 data->visual = PixelFormatEnumToVisual(renderer, texture->format);
853 }
854 else
855 #endif
856 {
857 if (texture->format != display->current_mode.format)
858 {
859 SDL_SetError("Texture format doesn't match window format");
860 return -1;
861 }
354 } 862 }
355 data->format = texture->format; 863 data->format = texture->format;
356 } 864 }
357 data->pitch = texture->w * SDL_BYTESPERPIXEL(data->format); 865
358 data->pitch = (data->pitch + pitch_alignmask) & ~pitch_alignmask;
359
360 if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING) { 866 if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING) {
361 #ifndef NO_SHARED_MEMORY 867 #ifndef NO_SHARED_MEMORY
362 XShmSegmentInfo *shminfo = &data->shminfo; 868 XShmSegmentInfo *shminfo = &data->shminfo;
363 869
364 shm_error = True; 870 shm_error = True;
365 871
366 if (SDL_X11_HAVE_SHM) { 872 if (SDL_X11_HAVE_SHM) {
367 shminfo->shmid = 873 data->image =
368 shmget(IPC_PRIVATE, texture->h * data->pitch, 874 XShmCreateImage(renderdata->display, data->visual,
369 IPC_CREAT | 0777); 875 data->depth, ZPixmap, NULL,
370 if (shminfo->shmid >= 0) { 876 shminfo, texture->w, texture->h);
371 shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0); 877 if (data->image) {
372 shminfo->readOnly = False; 878 shminfo->shmid =
373 if (shminfo->shmaddr != (char *) -1) { 879 shmget(IPC_PRIVATE, texture->h * data->image->bytes_per_line,
374 shm_error = False; 880 IPC_CREAT | 0777);
375 X_handler = XSetErrorHandler(shm_errhandler); 881 if (shminfo->shmid >= 0) {
376 XShmAttach(renderdata->display, shminfo); 882 shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0);
377 XSync(renderdata->display, False); 883 shminfo->readOnly = False;
378 XSetErrorHandler(X_handler); 884 if (shminfo->shmaddr != (char *) -1) {
379 if (shm_error) { 885 shm_error = False;
380 shmdt(shminfo->shmaddr); 886 X_handler = XSetErrorHandler(shm_errhandler);
887 XShmAttach(renderdata->display, shminfo);
888 XSync(renderdata->display, False);
889 XSetErrorHandler(X_handler);
890 if (shm_error) {
891 XShmDetach(renderdata->display, shminfo);
892 shmdt(shminfo->shmaddr);
893 XDestroyImage(data->image);
894 XSync(renderdata->display, False);
895 }
896 else {
897 data->pixels = data->image->data = shminfo->shmaddr;
898 shmctl(shminfo->shmid, IPC_RMID, NULL);
899 data->pixmap =
900 XCreatePixmap(renderdata->display, renderdata->xwindow,
901 texture->w, texture->h, data->depth);
902 if (!data->pixmap) {
903 SDL_SetError("XCreatePixmap() failed");
904 return -1;
905 }
906 }
381 } 907 }
382 } 908 }
383 shmctl(shminfo->shmid, IPC_RMID, NULL);
384 }
385 }
386 if (!shm_error) {
387 data->pixels = shminfo->shmaddr;
388
389 data->image =
390 XShmCreateImage(renderdata->display, renderdata->visual,
391 renderdata->depth, ZPixmap, shminfo->shmaddr,
392 shminfo, texture->w, texture->h);
393 if (!data->image) {
394 XShmDetach(renderdata->display, shminfo);
395 XSync(renderdata->display, False);
396 shmdt(shminfo->shmaddr);
397 shm_error = True;
398 } 909 }
399 } 910 }
400 if (shm_error) { 911 if (shm_error) {
401 shminfo->shmaddr = NULL; 912 shminfo->shmaddr = NULL;
402 } 913 }
403 if (!data->image) 914 if (!data->image)
404 #endif /* not NO_SHARED_MEMORY */ 915 #endif /* not NO_SHARED_MEMORY */
405 { 916 {
406 data->pixels = SDL_malloc(texture->h * data->pitch); 917 data->image =
918 XCreateImage(renderdata->display, data->visual,
919 data->depth, ZPixmap, 0, NULL,
920 texture->w, texture->h,
921 SDL_BYTESPERPIXEL(data->format) * 8,
922 0);
923 if (!data->image) {
924 X11_DestroyTexture(renderer, texture);
925 SDL_SetError("XCreateImage() failed");
926 return -1;
927 }
928 data->pixels = SDL_malloc(texture->h * data->image->bytes_per_line);
407 if (!data->pixels) { 929 if (!data->pixels) {
408 X11_DestroyTexture(renderer, texture); 930 X11_DestroyTexture(renderer, texture);
409 SDL_OutOfMemory(); 931 SDL_OutOfMemory();
410 return -1; 932 return -1;
411 } 933 }
412 934 data->image->data = data->pixels;
413 data->image = 935 data->pixmap =
414 XCreateImage(renderdata->display, renderdata->visual, 936 XCreatePixmap(renderdata->display, renderdata->xwindow, texture->w,
415 renderdata->depth, ZPixmap, 0, data->pixels, 937 texture->h, data->depth);
416 texture->w, texture->h, 938 if (data->pixmap == None) {
417 SDL_BYTESPERPIXEL(data->format) * 8,
418 data->pitch);
419 if (!data->image) {
420 X11_DestroyTexture(renderer, texture); 939 X11_DestroyTexture(renderer, texture);
421 SDL_SetError("XCreateImage() failed"); 940 SDL_SetError("XCreatePixmap() failed");
422 return -1; 941 return -1;
423 } 942 }
424 } 943 }
425 } else { 944 }
945 else {
946 data->image =
947 XCreateImage(renderdata->display, data->visual,
948 data->depth, ZPixmap, 0, NULL,
949 texture->w, texture->h,
950 SDL_BYTESPERPIXEL(data->format) * 8,
951 0);
952 if (!data->image) {
953 X11_DestroyTexture(renderer, texture);
954 SDL_SetError("XCreateImage() failed");
955 return -1;
956 }
426 data->pixmap = 957 data->pixmap =
427 XCreatePixmap(renderdata->display, renderdata->xwindow, texture->w, 958 XCreatePixmap(renderdata->display, renderdata->xwindow, texture->w,
428 texture->h, renderdata->depth); 959 texture->h, data->depth);
429 if (data->pixmap == None) { 960 if (data->pixmap == None) {
430 X11_DestroyTexture(renderer, texture); 961 X11_DestroyTexture(renderer, texture);
431 SDL_SetError("XCreatePixmap() failed"); 962 SDL_SetError("XCreatePixmap() failed");
432 return -1; 963 return -1;
433 } 964 }
434 965 }
435 data->image = 966
436 XCreateImage(renderdata->display, renderdata->visual, 967 data->pitch = data->image->bytes_per_line;
437 renderdata->depth, ZPixmap, 0, NULL, texture->w, 968
438 texture->h, SDL_BYTESPERPIXEL(data->format) * 8, 969 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
439 data->pitch); 970 if(renderdata->use_xrender) {
440 if (!data->image) { 971 gcv.graphics_exposures = False;
972 data->gc =
973 XCreateGC(renderdata->display, data->pixmap, GCGraphicsExposures, &gcv);
974 if (!data->gc) {
975 SDL_SetError("XCreateGC() failed");
976 return -1;
977 }
978 data->picture_fmt =
979 PixelFormatEnumToXRenderPictFormat(renderer, texture->format);
980 if (data->picture_fmt == NULL) {
441 X11_DestroyTexture(renderer, texture); 981 X11_DestroyTexture(renderer, texture);
442 SDL_SetError("XCreateImage() failed"); 982 SDL_SetError("Texture format not supported by driver");
443 return -1; 983 return -1;
444 } 984 }
445 } 985 data->picture =
446 986 XRenderCreatePicture(renderdata->display, data->pixmap,
987 data->picture_fmt, 0, NULL);
988 if (!data->picture) {
989 X11_DestroyTexture(renderer, texture);
990 SDL_SetError("XRenderCreatePicture() failed");
991 return -1;
992 }
993 data->modulated_pixmap =
994 XCreatePixmap(renderdata->display, renderdata->xwindow,
995 texture->w, texture->h, data->depth);
996 if (!data->modulated_pixmap) {
997 X11_DestroyTexture(renderer, texture);
998 SDL_SetError("XCreatePixmap() failed");
999 return -1;
1000 }
1001 data->modulated_picture =
1002 XRenderCreatePicture(renderdata->display, data->modulated_pixmap,
1003 data->picture_fmt, 0, NULL);
1004 if (!data->modulated_picture) {
1005 X11_DestroyTexture(renderer, texture);
1006 SDL_SetError("XRenderCreatePicture() failed");
1007 return -1;
1008 }
1009 texture->blendMode = SDL_BLENDMODE_NONE;
1010 data->blend_op = PictOpSrc;
1011 }
1012 #endif
447 return 0; 1013 return 0;
448 } 1014 }
449 1015
450 static int 1016 static int
451 X11_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture, 1017 X11_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
461 return 0; 1027 return 0;
462 } 1028 }
463 } 1029 }
464 1030
465 static int 1031 static int
1032 X11_SetTextureRGBAMod(SDL_Renderer * renderer, SDL_Texture * texture)
1033 {
1034
1035 X11_TextureData *data = (X11_TextureData *) texture->driverdata;
1036 X11_RenderData *renderdata = (X11_RenderData *) renderer->driverdata;
1037
1038 if (renderdata->use_xrender) {
1039
1040 Uint8 r = 0xFF, g = 0xFF, b = 0xFF, a = 0xFF;
1041
1042 /* Check if alpha modulation is required. */
1043 if (texture->modMode & SDL_TEXTUREMODULATE_ALPHA) {
1044 a = texture->a;
1045 }
1046
1047 /* Check if color modulation is required. */
1048 if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) {
1049 r = texture->r;
1050 g = texture->g;
1051 b = texture->b;
1052 }
1053
1054 /* We can save some labour if no modulation is required. */
1055 if (texture->modMode != SDL_TEXTUREMODULATE_NONE) {
1056 XRenderColor mod_color =
1057 SDLColorToXRenderColor(r, g, b, a);
1058 XRenderFillRectangle(renderdata->display, PictOpSrc,
1059 renderdata->brush_pict, &mod_color,
1060 0, 0, 1, 1);
1061 }
1062
1063 /* We can save some labour dealing with component alpha
1064 * if color modulation is not required. */
1065 XRenderPictureAttributes attr;
1066 if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) {
1067 attr.component_alpha = True;
1068 XRenderChangePicture(renderdata->display, renderdata->brush_pict,
1069 CPComponentAlpha, &attr);
1070 }
1071
1072 /* Again none of this is necessary is no modulation
1073 * is required. */
1074 if (texture->modMode != SDL_TEXTUREMODULATE_NONE) {
1075 XRenderComposite(renderdata->display, PictOpSrc,
1076 data->picture, renderdata->brush_pict,
1077 data->modulated_picture,
1078 0, 0, 0, 0, 0, 0, texture->w, texture->h);
1079 }
1080
1081 /* We only need to reset the component alpha
1082 * attribute if color modulation is required. */
1083 if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) {
1084 attr.component_alpha = False;
1085 XRenderChangePicture(renderdata->display, renderdata->brush_pict,
1086 CPComponentAlpha, &attr);
1087 }
1088
1089 return 0;
1090 }
1091 else {
1092 SDL_Unsupported();
1093 return -1;
1094 }
1095 }
1096
1097 static int
466 X11_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture) 1098 X11_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
467 { 1099 {
1100 X11_TextureData *data = (X11_TextureData *) texture->driverdata;
1101 X11_RenderData *renderdata = (X11_RenderData *) renderer->driverdata;
468 switch (texture->blendMode) { 1102 switch (texture->blendMode) {
469 case SDL_BLENDMODE_NONE: 1103 case SDL_BLENDMODE_NONE:
1104 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
1105 if (renderdata->use_xrender) {
1106 data->blend_op = PictOpSrc;
1107 return 0;
1108 }
1109 case SDL_BLENDMODE_MOD:
1110 case SDL_BLENDMODE_MASK:
1111 case SDL_BLENDMODE_BLEND:
1112 if (renderdata->use_xrender) {
1113 data->blend_op = PictOpOver;
1114 return 0;
1115 }
1116 case SDL_BLENDMODE_ADD:
1117 if (renderdata->use_xrender) {
1118 data->blend_op = PictOpAdd;
1119 return 0;
1120 }
1121 #endif
470 return 0; 1122 return 0;
471 default: 1123 default:
472 SDL_Unsupported(); 1124 SDL_Unsupported();
473 texture->blendMode = SDL_BLENDMODE_NONE; 1125 texture->blendMode = SDL_BLENDMODE_NONE;
1126 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
1127 if (renderdata->use_xrender) {
1128 texture->blendMode = SDL_BLENDMODE_BLEND;
1129 data->blend_op = PictOpOver;
1130 }
1131 #endif
474 return -1; 1132 return -1;
475 } 1133 }
476 } 1134 }
477 1135
478 static int 1136 static int
479 X11_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture) 1137 X11_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture)
480 { 1138 {
481 X11_TextureData *data = (X11_TextureData *) texture->driverdata; 1139 X11_TextureData *data = (X11_TextureData *) texture->driverdata;
1140 X11_RenderData *renderdata = (X11_RenderData *) renderer->driverdata;
482 1141
483 switch (texture->scaleMode) { 1142 switch (texture->scaleMode) {
484 case SDL_TEXTURESCALEMODE_NONE: 1143 case SDL_TEXTURESCALEMODE_NONE:
485 return 0; 1144 return 0;
486 case SDL_TEXTURESCALEMODE_FAST: 1145 case SDL_TEXTURESCALEMODE_FAST:
487 /* We can sort of fake it for streaming textures */ 1146 /* We can sort of fake it for streaming textures */
488 if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING) { 1147 if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING) {
489 return 0; 1148 return 0;
490 } 1149 }
491 /* Fall through to unsupported case */ 1150 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
1151 if (renderdata->use_xrender) {
1152 data->filter = FilterFast;
1153 return 0;
1154 }
1155 case SDL_TEXTURESCALEMODE_SLOW:
1156 if (renderdata->use_xrender) {
1157 data->filter = FilterGood;
1158 return 0;
1159 }
1160 case SDL_TEXTURESCALEMODE_BEST:
1161 if (renderdata->use_xrender) {
1162 data->filter = FilterBest;
1163 return 0;
1164 }
1165 #endif
1166 /* Fall through to unsupported case */
492 default: 1167 default:
493 SDL_Unsupported(); 1168 SDL_Unsupported();
494 texture->scaleMode = SDL_TEXTURESCALEMODE_NONE; 1169 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
1170 if (renderdata->use_xrender) {
1171 texture->scaleMode = SDL_TEXTURESCALEMODE_FAST;
1172 data->filter = FilterFast;
1173 }
1174 else
1175 #endif
1176 texture->scaleMode = SDL_TEXTURESCALEMODE_NONE;
495 return -1; 1177 return -1;
496 } 1178 }
497 return 0; 1179 return 0;
498 } 1180 }
499 1181
530 } else { 1212 } else {
531 data->image->width = rect->w; 1213 data->image->width = rect->w;
532 data->image->height = rect->h; 1214 data->image->height = rect->h;
533 data->image->data = (char *) pixels; 1215 data->image->data = (char *) pixels;
534 data->image->bytes_per_line = pitch; 1216 data->image->bytes_per_line = pitch;
535 XPutImage(renderdata->display, data->pixmap, renderdata->gc, 1217 XPutImage(renderdata->display, data->pixmap, data->gc,
536 data->image, 0, 0, rect->x, rect->y, rect->w, rect->h); 1218 data->image, 0, 0, rect->x, rect->y, rect->w, rect->h);
537 } 1219 }
538 return 0; 1220 return 0;
539 } 1221 }
540 } 1222 }
573 } 1255 }
574 1256
575 static int 1257 static int
576 X11_SetDrawBlendMode(SDL_Renderer * renderer) 1258 X11_SetDrawBlendMode(SDL_Renderer * renderer)
577 { 1259 {
1260 X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
578 switch (renderer->blendMode) { 1261 switch (renderer->blendMode) {
579 case SDL_BLENDMODE_NONE: 1262 case SDL_BLENDMODE_NONE:
1263 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
1264 //PictOpSrc
1265 data->blend_op = PictOpSrc;
1266 return 0;
1267 case SDL_BLENDMODE_MOD:
1268 case SDL_BLENDMODE_MASK:
1269 case SDL_BLENDMODE_BLEND: // PictOpOver
1270 data->blend_op = PictOpOver;
1271 return 0;
1272 case SDL_BLENDMODE_ADD: // PictOpAdd
1273 data->blend_op = PictOpAdd;
1274 return 0;
1275 /* FIXME case SDL_BLENDMODE_MOD: */
1276 #endif
580 return 0; 1277 return 0;
581 default: 1278 default:
582 SDL_Unsupported(); 1279 SDL_Unsupported();
583 renderer->blendMode = SDL_BLENDMODE_NONE; 1280 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
1281 if(data->use_xrender) {
1282 renderer->blendMode = SDL_BLENDMODE_BLEND;
1283 data->blend_op = PictOpOver;
1284 }
1285 else
1286 #endif
1287 {
1288 renderer->blendMode = SDL_BLENDMODE_NONE;
1289 }
584 return -1; 1290 return -1;
585 } 1291 }
586 } 1292 }
587 1293
588 static Uint32 1294 static Uint32
599 ((int) b * (int) a) / 255, 255); 1305 ((int) b * (int) a) / 255, 255);
600 else 1306 else
601 return SDL_MapRGBA(&data->format, r, g, b, a); 1307 return SDL_MapRGBA(&data->format, r, g, b, a);
602 } 1308 }
603 1309
1310 static XRenderColor
1311 xrenderdrawcolor(SDL_Renderer *renderer)
1312 {
1313 XRenderColor xrender_color;
1314 if(renderer->blendMode == SDL_BLENDMODE_NONE) {
1315 xrender_color =
1316 SDLColorToXRenderColor(renderer->r, renderer->g, renderer->b, 0xFF);
1317 }
1318 else {
1319 xrender_color =
1320 SDLColorToXRenderColor(renderer->r, renderer->g, renderer->b, renderer->a);
1321 }
1322 return xrender_color;
1323 }
1324
604 static int 1325 static int
605 X11_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, 1326 X11_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points,
606 int count) 1327 int count)
607 { 1328 {
608 X11_RenderData *data = (X11_RenderData *) renderer->driverdata; 1329 X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
609 SDL_Window *window = renderer->window; 1330 SDL_Window *window = renderer->window;
610 unsigned long foreground;
611 XPoint *xpoints, *xpoint; 1331 XPoint *xpoints, *xpoint;
612 int i, xcount; 1332 int i, xcount;
613 1333 SDL_Rect clip;
1334
1335 clip.x = 0;
1336 clip.y = 0;
1337 clip.w = window->w;
1338 clip.h = window->h;
614 if (data->makedirty) { 1339 if (data->makedirty) {
615 SDL_Rect rect; 1340 SDL_Rect rect;
616 1341
617 /* Get the smallest rectangle that contains everything */ 1342 /* Get the smallest rectangle that contains everything */
618 rect.x = 0; 1343 rect.x = 0;
623 /* Nothing to draw */ 1348 /* Nothing to draw */
624 return 0; 1349 return 0;
625 } 1350 }
626 SDL_AddDirtyRect(&data->dirty, &rect); 1351 SDL_AddDirtyRect(&data->dirty, &rect);
627 } 1352 }
628 1353 {
629 foreground = renderdrawcolor(renderer, 1); 1354 xpoint = xpoints = SDL_stack_alloc(XPoint, count);
630 XSetForeground(data->display, data->gc, foreground); 1355 xcount = 0;
631 1356 for (i = 0; i < count; ++i) {
632 xpoint = xpoints = SDL_stack_alloc(XPoint, count); 1357 int x = points[i].x;
633 xcount = 0; 1358 int y = points[i].y;
634 for (i = 0; i < count; ++i) { 1359 if (x < 0 || x >= window->w || y < 0 || y >= window->h) {
635 int x = points[i].x; 1360 continue;
636 int y = points[i].y; 1361 }
637 if (x < 0 || x >= window->w || y < 0 || y >= window->h) { 1362 xpoint->x = (short)x;
638 continue; 1363 xpoint->y = (short)y;
639 } 1364 ++xpoint;
640 xpoint->x = (short)x; 1365 ++xcount;
641 xpoint->y = (short)y; 1366 }
642 ++xpoint; 1367
643 ++xcount; 1368 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
644 } 1369 if (data->use_xrender &&
645 if (xcount > 0) { 1370 (renderer->blendMode != SDL_BLENDMODE_NONE) &&
646 XDrawPoints(data->display, data->drawable, data->gc, xpoints, xcount, 1371 !(renderer->a == 0xFF &&
647 CoordModeOrigin); 1372 renderer->blendMode != SDL_BLENDMODE_ADD &&
648 } 1373 renderer->blendMode != SDL_BLENDMODE_MOD))
1374 {
1375 XSetForeground(data->display, data->stencil_gc, 0);
1376 #ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
1377 if (data->use_xdamage)
1378 {
1379 /* Update only those parts which were changed
1380 * in the previous drawing operation */
1381 XFixesSetGCClipRegion(data->display, data->stencil_gc,
1382 0, 0, data->stencil_parts);
1383 }
1384 #endif
1385 XFillRectangle(data->display, data->stencil, data->stencil_gc,
1386 0, 0, window->w, window->h);
1387 #ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
1388 if (data->use_xdamage)
1389 {
1390 XFixesSetGCClipRegion(data->display, data->stencil_gc, 0, 0, None);
1391 }
1392 #endif
1393 XSetForeground(data->display, data->stencil_gc, 0xFFFFFFFF);
1394
1395 XDrawPoints(data->display, data->stencil, data->stencil_gc, xpoints, xcount,
1396 CoordModeOrigin);
1397 #ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
1398 if (data->use_xdamage)
1399 {
1400 /* Store the damaged region in stencil_parts */
1401 XDamageSubtract(data->display, data->stencil_damage, None, data->stencil_parts);
1402 }
1403 #endif
1404 }
1405 #endif
1406 }
1407
1408 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
1409 if (data->use_xrender &&
1410 (renderer->blendMode != SDL_BLENDMODE_NONE) &&
1411 !(renderer->a == 0xFF &&
1412 renderer->blendMode != SDL_BLENDMODE_ADD &&
1413 renderer->blendMode != SDL_BLENDMODE_MOD))
1414 {
1415 XRenderColor foreground;
1416 foreground = xrenderdrawcolor(renderer);
1417
1418 XRenderFillRectangle(data->display, PictOpSrc, data->brush_pict,
1419 &foreground, 0, 0, 1, 1);
1420 #ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
1421 if (data->use_xdamage)
1422 {
1423 /* Update only those parts which drawn
1424 * to in the current drawing operation */
1425 XFixesSetPictureClipRegion(data->display, data->drawable_pict,
1426 0, 0, data->stencil_parts);
1427 }
1428 #endif
1429 XRenderComposite(data->display, data->blend_op, data->brush_pict,
1430 data->stencil_pict, data->drawable_pict,
1431 0, 0, 0, 0, 0, 0, window->w, window->h);
1432 #ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
1433 if (data->use_xdamage)
1434 {
1435 XFixesSetPictureClipRegion(data->display, data->drawable_pict, 0, 0, None);
1436 }
1437 #endif
1438 }
1439 else
1440 #endif
1441 {
1442 unsigned long foreground = renderdrawcolor(renderer, 1);
1443 XSetForeground(data->display, data->gc, foreground);
1444
1445
1446 if (xcount > 0) {
1447 XDrawPoints(data->display, data->drawable, data->gc, xpoints, xcount,
1448 CoordModeOrigin);
1449 }
1450 }
1451
649 SDL_stack_free(xpoints); 1452 SDL_stack_free(xpoints);
650 1453
651 return 0; 1454 return 0;
652 } 1455 }
653 1456
666 1469
667 clip.x = 0; 1470 clip.x = 0;
668 clip.y = 0; 1471 clip.y = 0;
669 clip.w = window->w; 1472 clip.w = window->w;
670 clip.h = window->h; 1473 clip.h = window->h;
671 1474 {
672 foreground = renderdrawcolor(renderer, 1); 1475 Pixmap drawable;
673 XSetForeground(data->display, data->gc, foreground); 1476 GC gc;
674 1477 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
675 xpoint = xpoints = SDL_stack_alloc(XPoint, count); 1478 if (data->use_xrender &&
676 xcount = 0; 1479 (renderer->blendMode != SDL_BLENDMODE_NONE) &&
677 minx = INT_MAX; 1480 !(renderer->a == 0xFF &&
678 miny = INT_MAX; 1481 renderer->blendMode != SDL_BLENDMODE_ADD &&
679 maxx = INT_MIN; 1482 renderer->blendMode != SDL_BLENDMODE_MOD))
680 maxy = INT_MIN; 1483 {
681 for (i = 0; i < count; ++i) { 1484 drawable = data->stencil;
682 int x = points[i].x; 1485 gc = data->stencil_gc;
683 int y = points[i].y; 1486
684 1487 XSetForeground(data->display, data->stencil_gc, 0);
685 /* If the point is inside the window, add it to the list */ 1488 #ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
686 if (x >= 0 && x < window->w && y >= 0 && y < window->h) { 1489 if (data->use_xdamage)
687 if (x < minx) { 1490 XFixesSetGCClipRegion(data->display, data->stencil_gc,
688 minx = x; 1491 0, 0, data->stencil_parts);
689 } else if (x > maxx) { 1492 #endif
690 maxx = x; 1493 XFillRectangle(data->display, data->stencil, data->stencil_gc,
691 } 1494 0, 0, window->w, window->h);
692 if (y < miny) { 1495 #ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
693 miny = y; 1496 if (data->use_xdamage)
694 } else if (y > maxy) { 1497 XFixesSetGCClipRegion(data->display, data->stencil_gc,
695 maxy = y; 1498 0, 0, None);
696 } 1499 #endif
697 xpoint->x = (short)x; 1500 XSetForeground(data->display, data->stencil_gc, 0xFFFFFFFF);
698 xpoint->y = (short)y; 1501 }
699 ++xpoint; 1502 else
700 ++xcount; 1503 #endif
701 continue; 1504 {
702 } 1505 drawable = data->drawable;
703 1506 gc = data->gc;
704 /* We need to clip the line segments joined by this point */ 1507 }
705 if (xcount > 0) { 1508
706 int x1 = xpoint[-1].x; 1509 foreground = renderdrawcolor(renderer, 1);
707 int y1 = xpoint[-1].y; 1510 XSetForeground(data->display, data->gc, foreground);
708 int x2 = x; 1511
709 int y2 = y; 1512 xpoint = xpoints = SDL_stack_alloc(XPoint, count);
710 if (SDL_IntersectRectAndLine(&clip, &x1, &y1, &x2, &y2)) { 1513 xcount = 0;
711 if (x2 < minx) { 1514 minx = INT_MAX;
712 minx = x2; 1515 miny = INT_MAX;
713 } else if (x2 > maxx) { 1516 maxx = INT_MIN;
714 maxx = x2; 1517 maxy = INT_MIN;
1518 for (i = 0; i < count; ++i) {
1519 int x = points[i].x;
1520 int y = points[i].y;
1521
1522 /* If the point is inside the window, add it to the list */
1523 if (x >= 0 && x < window->w && y >= 0 && y < window->h) {
1524 if (x < minx) {
1525 minx = x;
1526 } else if (x > maxx) {
1527 maxx = x;
715 } 1528 }
716 if (y2 < miny) { 1529 if (y < miny) {
717 miny = y2; 1530 miny = y;
718 } else if (y2 > maxy) { 1531 } else if (y > maxy) {
719 maxy = y2; 1532 maxy = y;
720 } 1533 }
721 xpoint->x = (short)x2; 1534 xpoint->x = (short)x;
722 xpoint->y = (short)y2; 1535 xpoint->y = (short)y;
723 ++xpoint; 1536 ++xpoint;
724 ++xcount; 1537 ++xcount;
725 } 1538 continue;
726 XDrawLines(data->display, data->drawable, data->gc, 1539 }
727 xpoints, xcount, CoordModeOrigin); 1540
1541 /* We need to clip the line segments joined by this point */
1542 if (xcount > 0) {
1543 int x1 = xpoint[-1].x;
1544 int y1 = xpoint[-1].y;
1545 int x2 = x;
1546 int y2 = y;
1547 if (SDL_IntersectRectAndLine(&clip, &x1, &y1, &x2, &y2)) {
1548 if (x2 < minx) {
1549 minx = x2;
1550 } else if (x2 > maxx) {
1551 maxx = x2;
1552 }
1553 if (y2 < miny) {
1554 miny = y2;
1555 } else if (y2 > maxy) {
1556 maxy = y2;
1557 }
1558 xpoint->x = (short)x2;
1559 xpoint->y = (short)y2;
1560 ++xpoint;
1561 ++xcount;
1562 }
1563 XDrawLines(data->display, drawable, gc,
1564 xpoints, xcount, CoordModeOrigin);
1565 if (xpoints[0].x != x2 || xpoints[0].y != y2) {
1566 XDrawPoint(data->display, drawable, gc, x2, y2);
1567 }
1568 if (data->makedirty) {
1569 SDL_Rect rect;
1570
1571 rect.x = minx;
1572 rect.y = miny;
1573 rect.w = (maxx - minx) + 1;
1574 rect.h = (maxy - miny) + 1;
1575 SDL_AddDirtyRect(&data->dirty, &rect);
1576 }
1577 xpoint = xpoints;
1578 xcount = 0;
1579 minx = INT_MAX;
1580 miny = INT_MAX;
1581 maxx = INT_MIN;
1582 maxy = INT_MIN;
1583 }
1584 if (i < (count-1)) {
1585 int x1 = x;
1586 int y1 = y;
1587 int x2 = points[i+1].x;
1588 int y2 = points[i+1].y;
1589 if (SDL_IntersectRectAndLine(&clip, &x1, &y1, &x2, &y2)) {
1590 if (x1 < minx) {
1591 minx = x1;
1592 } else if (x1 > maxx) {
1593 maxx = x1;
1594 }
1595 if (y1 < miny) {
1596 miny = y1;
1597 } else if (y1 > maxy) {
1598 maxy = y1;
1599 }
1600 xpoint->x = (short)x1;
1601 xpoint->y = (short)y1;
1602 ++xpoint;
1603 ++xcount;
1604 }
1605 }
1606 }
1607 if (xcount > 1) {
1608 int x2 = xpoint[-1].x;
1609 int y2 = xpoint[-1].y;
1610 XDrawLines(data->display, drawable, gc, xpoints, xcount,
1611 CoordModeOrigin);
728 if (xpoints[0].x != x2 || xpoints[0].y != y2) { 1612 if (xpoints[0].x != x2 || xpoints[0].y != y2) {
729 XDrawPoint(data->display, data->drawable, data->gc, x2, y2); 1613 XDrawPoint(data->display, drawable, gc, x2, y2);
730 } 1614 }
731 if (data->makedirty) { 1615 if (data->makedirty) {
732 SDL_Rect rect; 1616 SDL_Rect rect;
733 1617
734 rect.x = minx; 1618 rect.x = minx;
735 rect.y = miny; 1619 rect.y = miny;
736 rect.w = (maxx - minx) + 1; 1620 rect.w = (maxx - minx) + 1;
737 rect.h = (maxy - miny) + 1; 1621 rect.h = (maxy - miny) + 1;
738 SDL_AddDirtyRect(&data->dirty, &rect); 1622 SDL_AddDirtyRect(&data->dirty, &rect);
739 } 1623 }
740 xpoint = xpoints; 1624 }
741 xcount = 0; 1625 }
742 minx = INT_MAX; 1626 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
743 miny = INT_MAX; 1627 if (data->use_xrender &&
744 maxx = INT_MIN; 1628 (renderer->blendMode != SDL_BLENDMODE_NONE) &&
745 maxy = INT_MIN; 1629 !(renderer->a == 0xFF &&
746 } 1630 renderer->blendMode != SDL_BLENDMODE_ADD &&
747 if (i < (count-1)) { 1631 renderer->blendMode != SDL_BLENDMODE_MOD))
748 int x1 = x; 1632 {
749 int y1 = y; 1633 XRenderColor xrforeground = xrenderdrawcolor(renderer);
750 int x2 = points[i+1].x; 1634 XRenderFillRectangle(data->display, PictOpSrc, data->brush_pict,
751 int y2 = points[i+1].y; 1635 &xrforeground, 0, 0, 1, 1);
752 if (SDL_IntersectRectAndLine(&clip, &x1, &y1, &x2, &y2)) { 1636 #ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
753 if (x1 < minx) { 1637 if (data->use_xdamage)
754 minx = x1; 1638 {
755 } else if (x1 > maxx) { 1639 XDamageSubtract(data->display, data->stencil_damage, None, data->stencil_parts);
756 maxx = x1; 1640
757 } 1641 XFixesSetPictureClipRegion(data->display, data->drawable_pict,
758 if (y1 < miny) { 1642 0, 0, data->stencil_parts);
759 miny = y1; 1643 }
760 } else if (y1 > maxy) { 1644 #endif
761 maxy = y1; 1645 XRenderComposite(data->display, data->blend_op, data->brush_pict,
762 } 1646 data->stencil_pict, data->drawable_pict,
763 xpoint->x = (short)x1; 1647 0, 0, 0, 0, 0, 0, window->w, window->h);
764 xpoint->y = (short)y1; 1648 #ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
765 ++xpoint; 1649 if (data->use_xdamage)
766 ++xcount; 1650 XFixesSetPictureClipRegion(data->display, data->drawable_pict,
767 } 1651 0, 0, None);
768 } 1652 #endif
769 } 1653 }
770 if (xcount > 1) { 1654 #endif
771 int x2 = xpoint[-1].x;
772 int y2 = xpoint[-1].y;
773 XDrawLines(data->display, data->drawable, data->gc, xpoints, xcount,
774 CoordModeOrigin);
775 if (xpoints[0].x != x2 || xpoints[0].y != y2) {
776 XDrawPoint(data->display, data->drawable, data->gc, x2, y2);
777 }
778 if (data->makedirty) {
779 SDL_Rect rect;
780
781 rect.x = minx;
782 rect.y = miny;
783 rect.w = (maxx - minx) + 1;
784 rect.h = (maxy - miny) + 1;
785 SDL_AddDirtyRect(&data->dirty, &rect);
786 }
787 }
788 SDL_stack_free(xpoints); 1655 SDL_stack_free(xpoints);
789 1656
790 return 0; 1657 return 0;
791 } 1658 }
792 1659
794 X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) 1661 X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count)
795 { 1662 {
796 X11_RenderData *data = (X11_RenderData *) renderer->driverdata; 1663 X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
797 SDL_Window *window = renderer->window; 1664 SDL_Window *window = renderer->window;
798 SDL_Rect clip, rect; 1665 SDL_Rect clip, rect;
799 unsigned long foreground; 1666 int i, xcount;
800 XRectangle *xrects, *xrect; 1667 XRectangle *xrects, *xrect;
801 int i, xcount; 1668 xrect = xrects = SDL_stack_alloc(XRectangle, count);
802 1669 xcount = 0;
1670
803 clip.x = 0; 1671 clip.x = 0;
804 clip.y = 0; 1672 clip.y = 0;
805 clip.w = window->w; 1673 clip.w = window->w;
806 clip.h = window->h; 1674 clip.h = window->h;
807 1675 {
808 foreground = renderdrawcolor(renderer, 1); 1676
809 XSetForeground(data->display, data->gc, foreground); 1677 for (i = 0; i < count; ++i) {
810 1678 if (!SDL_IntersectRect(rects[i], &clip, &rect)) {
1679 continue;
1680 }
1681
1682 xrect->x = (short)rect.x;
1683 xrect->y = (short)rect.y;
1684 xrect->width = (unsigned short)rect.w - 1;
1685 xrect->height = (unsigned short)rect.h - 1;
1686 ++xrect;
1687 ++xcount;
1688
1689 if (data->makedirty) {
1690 SDL_AddDirtyRect(&data->dirty, &rect);
1691 }
1692 }
1693 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
1694 if (data->use_xrender &&
1695 (renderer->blendMode != SDL_BLENDMODE_NONE) &&
1696 !(renderer->a == 0xFF &&
1697 renderer->blendMode != SDL_BLENDMODE_ADD &&
1698 renderer->blendMode != SDL_BLENDMODE_MOD))
1699 {
1700 XSetForeground(data->display, data->stencil_gc, 0);
1701 #ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
1702 if (data->use_xdamage)
1703 XFixesSetGCClipRegion(data->display, data->stencil_gc,
1704 0, 0, data->stencil_parts);
1705 #endif
1706 XFillRectangle(data->display, data->stencil, data->stencil_gc,
1707 0, 0, window->w, window->h);
1708 #ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
1709 if (data->use_xdamage)
1710 XFixesSetGCClipRegion(data->display, data->stencil_gc,
1711 0, 0, None);
1712 #endif
1713 XSetForeground(data->display, data->stencil_gc, 0xFFFFFFFF);
1714
1715 XDrawRectangles(data->display, data->stencil, data->stencil_gc, xrects, xcount);
1716
1717 #ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
1718 if (data->use_xdamage)
1719 XDamageSubtract(data->display, data->stencil_damage,
1720 None, data->stencil_parts);
1721 #endif
1722 }
1723 #endif
1724 }
1725 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
1726 if (data->use_xrender &&
1727 (renderer->blendMode != SDL_BLENDMODE_NONE) &&
1728 !(renderer->a == 0xFF &&
1729 renderer->blendMode != SDL_BLENDMODE_ADD &&
1730 renderer->blendMode != SDL_BLENDMODE_MOD))
1731 {
1732 XRenderColor foreground;
1733 foreground = xrenderdrawcolor(renderer);
1734 XRenderFillRectangle(data->display, PictOpSrc, data->brush_pict,
1735 &foreground, 0, 0, 1, 1);
1736 #ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
1737 if (data->use_xdamage)
1738 XFixesSetPictureClipRegion(data->display, data->drawable_pict,
1739 0, 0, data->stencil_parts);
1740 #endif
1741 XRenderComposite(data->display, data->blend_op, data->brush_pict,
1742 data->stencil_pict, data->drawable_pict,
1743 0, 0, 0, 0, 0, 0, window->w, window->h);
1744 #ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
1745 if (data->use_xdamage)
1746 XFixesSetPictureClipRegion(data->display, data->drawable_pict,
1747 0, 0, None);
1748 #endif
1749 }
1750 else
1751 #endif
1752 {
1753 unsigned long foreground;
1754
1755 foreground = renderdrawcolor(renderer, 1);
1756 XSetForeground(data->display, data->gc, foreground);
1757
1758 if (xcount > 0) {
1759 XDrawRectangles(data->display, data->drawable, data->gc,
1760 xrects, xcount);
1761 }
1762 }
1763 SDL_stack_free(xrects);
1764
1765 return 0;
1766 }
1767
1768 static int
1769 X11_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count)
1770 {
1771 X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
1772 SDL_Window *window = renderer->window;
1773 SDL_Rect clip, rect;
1774
1775 clip.x = 0;
1776 clip.y = 0;
1777 clip.w = window->w;
1778 clip.h = window->h;
1779
1780 int i, xcount;
1781 XRectangle *xrects, *xrect;
811 xrect = xrects = SDL_stack_alloc(XRectangle, count); 1782 xrect = xrects = SDL_stack_alloc(XRectangle, count);
812 xcount = 0; 1783 xcount = 0;
813 for (i = 0; i < count; ++i) { 1784 for (i = 0; i < count; ++i) {
814 if (!SDL_IntersectRect(rects[i], &clip, &rect)) { 1785 if (!SDL_IntersectRect(rects[i], &clip, &rect)) {
815 continue; 1786 continue;
824 1795
825 if (data->makedirty) { 1796 if (data->makedirty) {
826 SDL_AddDirtyRect(&data->dirty, &rect); 1797 SDL_AddDirtyRect(&data->dirty, &rect);
827 } 1798 }
828 } 1799 }
829 if (xcount > 0) { 1800
830 XDrawRectangles(data->display, data->drawable, data->gc, 1801 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
831 xrects, xcount); 1802 if (data->use_xrender) {
832 } 1803 XRenderColor foreground;
833 SDL_stack_free(xpoints); 1804 foreground = xrenderdrawcolor(renderer);
834 1805 if (xcount == 1) {
835 return 0; 1806 XRenderFillRectangle(data->display, data->blend_op, data->drawable_pict,
836 } 1807 &foreground, xrects[0].x, xrects[0].y,
837 1808 xrects[0].width, xrects[0].height);
838 static int 1809 }
839 X11_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) 1810 else if (xcount > 1) {
840 { 1811 XRenderFillRectangles(data->display, data->blend_op, data->drawable_pict,
841 X11_RenderData *data = (X11_RenderData *) renderer->driverdata; 1812 &foreground, xrects, xcount);
842 SDL_Window *window = renderer->window; 1813 }
843 SDL_Rect clip, rect; 1814 }
844 unsigned long foreground; 1815 else
845 XRectangle *xrects, *xrect; 1816 #endif
846 int i, xcount; 1817 {
847 1818 unsigned long foreground;
848 clip.x = 0; 1819
849 clip.y = 0; 1820 foreground = renderdrawcolor(renderer, 1);
850 clip.w = window->w; 1821 XSetForeground(data->display, data->gc, foreground);
851 clip.h = window->h; 1822
852
853 foreground = renderdrawcolor(renderer, 1);
854 XSetForeground(data->display, data->gc, foreground);
855
856 xrect = xrects = SDL_stack_alloc(XRectangle, count);
857 xcount = 0;
858 for (i = 0; i < count; ++i) {
859 if (!SDL_IntersectRect(rects[i], &clip, &rect)) {
860 continue;
861 }
862
863 xrect->x = (short)rect.x;
864 xrect->y = (short)rect.y;
865 xrect->width = (unsigned short)rect.w;
866 xrect->height = (unsigned short)rect.h;
867 ++xrect;
868 ++xcount;
869
870 if (data->makedirty) {
871 SDL_AddDirtyRect(&data->dirty, &rect);
872 }
873 }
874 if (xcount > 0) {
875 XFillRectangles(data->display, data->drawable, data->gc, 1823 XFillRectangles(data->display, data->drawable, data->gc,
876 xrects, xcount); 1824 xrects, xcount);
877 } 1825 }
878 SDL_stack_free(xpoints); 1826
879 1827 SDL_stack_free(xrects);
880 return 0; 1828 return 0;
881 } 1829 }
882 1830
883 static int 1831 static int
884 X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, 1832 X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
888 X11_TextureData *texturedata = (X11_TextureData *) texture->driverdata; 1836 X11_TextureData *texturedata = (X11_TextureData *) texture->driverdata;
889 1837
890 if (data->makedirty) { 1838 if (data->makedirty) {
891 SDL_AddDirtyRect(&data->dirty, dstrect); 1839 SDL_AddDirtyRect(&data->dirty, dstrect);
892 } 1840 }
893 if (srcrect->w == dstrect->w && srcrect->h == dstrect->h) { 1841 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
1842 if (data->use_xrender) {
1843 if(texture->access == SDL_TEXTUREACCESS_STREAMING) {
894 #ifndef NO_SHARED_MEMORY 1844 #ifndef NO_SHARED_MEMORY
895 if (texturedata->shminfo.shmaddr) { 1845 if(texturedata->shminfo.shmaddr) {
896 XShmPutImage(data->display, data->drawable, data->gc, 1846 XShmPutImage(data->display, texturedata->pixmap, texturedata->gc,
897 texturedata->image, srcrect->x, srcrect->y, 1847 texturedata->image, srcrect->x, srcrect->y,
898 dstrect->x, dstrect->y, srcrect->w, srcrect->h, 1848 srcrect->x, srcrect->y, srcrect->w, srcrect->h,
899 False); 1849 False);
900 } else 1850 }
901 #endif 1851 else
902 if (texturedata->pixels) { 1852 #endif
903 XPutImage(data->display, data->drawable, data->gc, 1853 if (texturedata->pixels) {
904 texturedata->image, srcrect->x, srcrect->y, dstrect->x, 1854 XPutImage(data->display, texturedata->pixmap, texturedata->gc,
905 dstrect->y, srcrect->w, srcrect->h); 1855 texturedata->image, srcrect->x, srcrect->y, srcrect->x,
1856 srcrect->y, srcrect->w, srcrect->h);
1857 }
1858 XSync(data->display, False);
1859 }
1860 Picture src, mask;
1861 XRenderPictureAttributes attr;
1862 const SDL_Rect *mrect;
1863
1864 if (texture->modMode == SDL_TEXTUREMODULATE_NONE) {
1865 src = texturedata->picture;
1866 }
1867 else {
1868 src = texturedata->modulated_picture;
1869 }
1870
1871 if(texture->blendMode == SDL_BLENDMODE_NONE)
1872 {
1873 mask = None;
1874 mrect = srcrect;
1875 }
1876 else if (texture->blendMode == SDL_BLENDMODE_MOD)
1877 {
1878 mask = data->stencil_pict;
1879 mrect = dstrect;
1880 }
1881 else
1882 {
1883 mask = texturedata->picture;
1884 mrect = srcrect;
1885 }
1886
1887 if(srcrect->w == dstrect->w && srcrect->h == dstrect->h) {
1888 if (texture->blendMode == SDL_BLENDMODE_MOD) {
1889 XRenderComposite(data->display, PictOpSrc, data->drawable_pict,
1890 src, data->stencil_pict,
1891 dstrect->x, dstrect->y, srcrect->x, srcrect->y,
1892 dstrect->x, dstrect->y, dstrect->w, dstrect->h);
1893 attr.component_alpha = True;
1894 XRenderChangePicture(data->display, data->stencil_pict,
1895 CPComponentAlpha, &attr);
1896 }
1897 XRenderComposite(data->display, texturedata->blend_op,
1898 src, mask, data->drawable_pict, srcrect->x, srcrect->y,
1899 mrect->x, mrect->y, dstrect->x, dstrect->y,
1900 dstrect->w, dstrect->h);
1901 } else {
1902 double xscale = ((double) dstrect->w) / srcrect->w;
1903 double yscale = ((double) dstrect->h) / srcrect->h;
1904 XTransform xform = {{
1905 {XDoubleToFixed(xscale), XDoubleToFixed(0), XDoubleToFixed(0)},
1906 {XDoubleToFixed(0), XDoubleToFixed(yscale), XDoubleToFixed(0)},
1907 {XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(xscale * yscale)}}};
1908 XRenderSetPictureTransform(data->display, src, &xform);
1909
1910 if (texture->blendMode == SDL_BLENDMODE_MOD) {
1911 XRenderComposite(data->display, PictOpSrc, data->drawable_pict,
1912 src, data->stencil_pict,
1913 dstrect->x, dstrect->y, srcrect->x, srcrect->y,
1914 dstrect->x, dstrect->y, dstrect->w, dstrect->h);
1915 attr.component_alpha = True;
1916 XRenderChangePicture(data->display, data->stencil_pict,
1917 CPComponentAlpha, &attr);
1918 }
1919
1920 XRenderSetPictureFilter(data->display, src,
1921 texturedata->filter, 0, 0);
1922
1923 XRenderComposite(data->display, texturedata->blend_op,
1924 src, mask, data->drawable_pict,
1925 srcrect->x, srcrect->y, mrect->x, mrect->y,
1926 dstrect->x, dstrect->y, dstrect->w, dstrect->h);
1927
1928 XTransform identity = {{
1929 {XDoubleToFixed(1), XDoubleToFixed(0), XDoubleToFixed(0)},
1930 {XDoubleToFixed(0), XDoubleToFixed(1), XDoubleToFixed(0)},
1931 {XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(1)}}};
1932 XRenderSetPictureTransform(data->display, src, &identity);
1933 }
1934 if (renderer->blendMode == SDL_BLENDMODE_MOD) {
1935 attr.component_alpha = False;
1936 XRenderChangePicture(data->display, data->stencil_pict,
1937 CPComponentAlpha, &attr);
1938 }
1939 }
1940 else
1941 #endif
1942 {
1943 if (srcrect->w == dstrect->w && srcrect->h == dstrect->h) {
1944 #ifndef NO_SHARED_MEMORY
1945 if (texturedata->shminfo.shmaddr) {
1946 XShmPutImage(data->display, data->drawable, data->gc,
1947 texturedata->image, srcrect->x, srcrect->y,
1948 dstrect->x, dstrect->y, srcrect->w, srcrect->h,
1949 False);
1950 } else
1951 #endif
1952 if (texturedata->pixels) {
1953 XPutImage(data->display, data->drawable, data->gc,
1954 texturedata->image, srcrect->x, srcrect->y, dstrect->x,
1955 dstrect->y, srcrect->w, srcrect->h);
1956 } else {
1957 XCopyArea(data->display, texturedata->pixmap, data->drawable,
1958 data->gc, srcrect->x, srcrect->y, dstrect->w,
1959 dstrect->h, dstrect->x, dstrect->y);
1960 }
1961 } else if (texturedata->yuv
1962 || texture->access == SDL_TEXTUREACCESS_STREAMING) {
1963 SDL_Surface src, dst;
1964 SDL_PixelFormat fmt;
1965 SDL_Rect rect;
1966 XImage *image = texturedata->scaling_image;
1967
1968 if (!image) {
1969 void *pixels;
1970 int pitch;
1971
1972 pitch = dstrect->w * SDL_BYTESPERPIXEL(texturedata->format);
1973 pixels = SDL_malloc(dstrect->h * pitch);
1974 if (!pixels) {
1975 SDL_OutOfMemory();
1976 return -1;
1977 }
1978
1979 image =
1980 XCreateImage(data->display, data->visual, data->depth,
1981 ZPixmap, 0, pixels, dstrect->w, dstrect->h,
1982 SDL_BYTESPERPIXEL(texturedata->format) * 8,
1983 pitch);
1984 if (!image) {
1985 SDL_SetError("XCreateImage() failed");
1986 return -1;
1987 }
1988 texturedata->scaling_image = image;
1989
1990 } else if (image->width != dstrect->w || image->height != dstrect->h
1991 || !image->data) {
1992 image->width = dstrect->w;
1993 image->height = dstrect->h;
1994 image->bytes_per_line =
1995 image->width * SDL_BYTESPERPIXEL(texturedata->format);
1996 image->data =
1997 (char *) SDL_realloc(image->data,
1998 image->height * image->bytes_per_line);
1999 if (!image->data) {
2000 SDL_OutOfMemory();
2001 return -1;
2002 }
2003 }
2004
2005 /* Set up fake surfaces for SDL_SoftStretch() */
2006 SDL_zero(src);
2007 src.format = &fmt;
2008 src.w = texture->w;
2009 src.h = texture->h;
2010 #ifndef NO_SHARED_MEMORY
2011 if (texturedata->shminfo.shmaddr) {
2012 src.pixels = texturedata->shminfo.shmaddr;
2013 } else
2014 #endif
2015 src.pixels = texturedata->pixels;
2016 src.pitch = texturedata->pitch;
2017
2018 SDL_zero(dst);
2019 dst.format = &fmt;
2020 dst.w = image->width;
2021 dst.h = image->height;
2022 dst.pixels = image->data;
2023 dst.pitch = image->bytes_per_line;
2024
2025 fmt.BytesPerPixel = SDL_BYTESPERPIXEL(texturedata->format);
2026
2027 rect.x = 0;
2028 rect.y = 0;
2029 rect.w = dstrect->w;
2030 rect.h = dstrect->h;
2031 if (SDL_SoftStretch(&src, srcrect, &dst, &rect) < 0) {
2032 return -1;
2033 }
2034 XPutImage(data->display, data->drawable, data->gc, image, 0, 0,
2035 dstrect->x, dstrect->y, dstrect->w, dstrect->h);
906 } else { 2036 } else {
907 XCopyArea(data->display, texturedata->pixmap, data->drawable, 2037 XCopyArea(data->display, texturedata->pixmap, data->drawable,
908 data->gc, srcrect->x, srcrect->y, dstrect->w, 2038 data->gc, srcrect->x, srcrect->y, dstrect->w, dstrect->h,
909 dstrect->h, dstrect->x, dstrect->y); 2039 srcrect->x, srcrect->y);
910 } 2040 }
911 } else if (texturedata->yuv
912 || texture->access == SDL_TEXTUREACCESS_STREAMING) {
913 SDL_Surface src, dst;
914 SDL_PixelFormat fmt;
915 SDL_Rect rect;
916 XImage *image = texturedata->scaling_image;
917
918 if (!image) {
919 void *pixels;
920 int pitch;
921
922 pitch = dstrect->w * SDL_BYTESPERPIXEL(texturedata->format);
923 pixels = SDL_malloc(dstrect->h * pitch);
924 if (!pixels) {
925 SDL_OutOfMemory();
926 return -1;
927 }
928
929 image =
930 XCreateImage(data->display, data->visual, data->depth,
931 ZPixmap, 0, pixels, dstrect->w, dstrect->h,
932 SDL_BYTESPERPIXEL(texturedata->format) * 8,
933 pitch);
934 if (!image) {
935 SDL_SetError("XCreateImage() failed");
936 return -1;
937 }
938 texturedata->scaling_image = image;
939
940 } else if (image->width != dstrect->w || image->height != dstrect->h
941 || !image->data) {
942 image->width = dstrect->w;
943 image->height = dstrect->h;
944 image->bytes_per_line =
945 image->width * SDL_BYTESPERPIXEL(texturedata->format);
946 image->data =
947 (char *) SDL_realloc(image->data,
948 image->height * image->bytes_per_line);
949 if (!image->data) {
950 SDL_OutOfMemory();
951 return -1;
952 }
953 }
954
955 /* Set up fake surfaces for SDL_SoftStretch() */
956 SDL_zero(src);
957 src.format = &fmt;
958 src.w = texture->w;
959 src.h = texture->h;
960 #ifndef NO_SHARED_MEMORY
961 if (texturedata->shminfo.shmaddr) {
962 src.pixels = texturedata->shminfo.shmaddr;
963 } else
964 #endif
965 src.pixels = texturedata->pixels;
966 src.pitch = texturedata->pitch;
967
968 SDL_zero(dst);
969 dst.format = &fmt;
970 dst.w = image->width;
971 dst.h = image->height;
972 dst.pixels = image->data;
973 dst.pitch = image->bytes_per_line;
974
975 fmt.BytesPerPixel = SDL_BYTESPERPIXEL(texturedata->format);
976
977 rect.x = 0;
978 rect.y = 0;
979 rect.w = dstrect->w;
980 rect.h = dstrect->h;
981 if (SDL_SoftStretch(&src, srcrect, &dst, &rect) < 0) {
982 return -1;
983 }
984 XPutImage(data->display, data->drawable, data->gc, image, 0, 0,
985 dstrect->x, dstrect->y, dstrect->w, dstrect->h);
986 } else {
987 XCopyArea(data->display, texturedata->pixmap, data->drawable,
988 data->gc, srcrect->x, srcrect->y, dstrect->w, dstrect->h,
989 srcrect->x, srcrect->y);
990 } 2041 }
991 return 0; 2042 return 0;
992 } 2043 }
993 2044
994 static int 2045 static int
1063 2114
1064 /* Send the data to the display */ 2115 /* Send the data to the display */
1065 if (!(renderer->info.flags & SDL_RENDERER_SINGLEBUFFER)) { 2116 if (!(renderer->info.flags & SDL_RENDERER_SINGLEBUFFER)) {
1066 for (dirty = data->dirty.list; dirty; dirty = dirty->next) { 2117 for (dirty = data->dirty.list; dirty; dirty = dirty->next) {
1067 const SDL_Rect *rect = &dirty->rect; 2118 const SDL_Rect *rect = &dirty->rect;
2119 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
2120 if (data->use_xrender)
2121 {
2122 XRenderComposite(data->display,
2123 data->blend_op,
2124 data->drawable_pict,
2125 None,
2126 data->xwindow_pict,
2127 rect->x, rect->y,
2128 0, 0,
2129 rect->x, rect->y,
2130 rect->w, rect->h);
2131 }
2132 else
2133 #endif
2134 {
1068 XCopyArea(data->display, data->drawable, data->xwindow, 2135 XCopyArea(data->display, data->drawable, data->xwindow,
1069 data->gc, rect->x, rect->y, rect->w, rect->h, 2136 data->gc, rect->x, rect->y, rect->w, rect->h,
1070 rect->x, rect->y); 2137 rect->x, rect->y);
2138 }
1071 } 2139 }
1072 SDL_ClearDirtyRects(&data->dirty); 2140 SDL_ClearDirtyRects(&data->dirty);
1073 } 2141 }
1074 XSync(data->display, False); 2142 XSync(data->display, False);
1075 2143
1076 /* Update the flipping chain, if any */ 2144 /* Update the flipping chain, if any */
1077 if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) { 2145 if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) {
1078 data->current_pixmap = (data->current_pixmap + 1) % 2; 2146 data->current_pixmap = (data->current_pixmap + 1) % 2;
1079 data->drawable = data->pixmaps[data->current_pixmap]; 2147 data->drawable = data->pixmaps[data->current_pixmap];
2148 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
2149 data->drawable_pict = data->pixmap_picts[data->current_pixmap];
2150 #endif
1080 } else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP3) { 2151 } else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP3) {
1081 data->current_pixmap = (data->current_pixmap + 1) % 3; 2152 data->current_pixmap = (data->current_pixmap + 1) % 3;
1082 data->drawable = data->pixmaps[data->current_pixmap]; 2153 data->drawable = data->pixmaps[data->current_pixmap];
2154 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
2155 data->drawable_pict = data->pixmap_picts[data->current_pixmap];
2156 #endif
1083 } 2157 }
1084 } 2158 }
1085 2159
1086 static void 2160 static void
1087 X11_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) 2161 X11_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
1108 XSync(renderdata->display, False); 2182 XSync(renderdata->display, False);
1109 shmdt(data->shminfo.shmaddr); 2183 shmdt(data->shminfo.shmaddr);
1110 data->pixels = NULL; 2184 data->pixels = NULL;
1111 } 2185 }
1112 #endif 2186 #endif
2187 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
2188 if (renderdata->use_xrender) {
2189 if (data->picture) {
2190 XRenderFreePicture(renderdata->display, data->picture);
2191 }
2192 if (data->modulated_pixmap) {
2193 XFreePixmap(renderdata->display, data->modulated_pixmap);
2194 }
2195 if (data->modulated_picture) {
2196 XRenderFreePicture(renderdata->display, data->modulated_picture);
2197 }
2198 }
2199 #endif
1113 if (data->scaling_image) { 2200 if (data->scaling_image) {
1114 SDL_free(data->scaling_image->data); 2201 SDL_free(data->scaling_image->data);
1115 data->scaling_image->data = NULL; 2202 data->scaling_image->data = NULL;
1116 XDestroyImage(data->scaling_image); 2203 XDestroyImage(data->scaling_image);
1117 } 2204 }
1131 if (data) { 2218 if (data) {
1132 for (i = 0; i < SDL_arraysize(data->pixmaps); ++i) { 2219 for (i = 0; i < SDL_arraysize(data->pixmaps); ++i) {
1133 if (data->pixmaps[i] != None) { 2220 if (data->pixmaps[i] != None) {
1134 XFreePixmap(data->display, data->pixmaps[i]); 2221 XFreePixmap(data->display, data->pixmaps[i]);
1135 } 2222 }
2223 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
2224 if (data->use_xrender && data->pixmap_picts[i]) {
2225 XRenderFreePicture(data->display, data->pixmap_picts[i]);
2226 }
2227 #endif
1136 } 2228 }
1137 if (data->gc) { 2229 if (data->gc) {
1138 XFreeGC(data->display, data->gc); 2230 XFreeGC(data->display, data->gc);
1139 } 2231 }
2232 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
2233 if (data->use_xrender) {
2234 if (data->stencil_gc) {
2235 XFreeGC(data->display, data->stencil_gc);
2236 }
2237 if (data->stencil) {
2238 XFreePixmap(data->display, data->stencil);
2239 }
2240 if (data->stencil_pict) {
2241 XRenderFreePicture(data->display, data->stencil_pict);
2242 }
2243 if (data->xwindow_pict) {
2244 XRenderFreePicture(data->display, data->xwindow_pict);
2245 }
2246 #ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
2247 if (data->use_xdamage && data->stencil_damage) {
2248 XDamageDestroy(data->display, data->stencil_damage);
2249 }
2250 #endif
2251 }
2252 #endif
1140 SDL_FreeDirtyRects(&data->dirty); 2253 SDL_FreeDirtyRects(&data->dirty);
1141 SDL_free(data); 2254 SDL_free(data);
1142 } 2255 }
1143 SDL_free(renderer); 2256 SDL_free(renderer);
1144 } 2257 }