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