comparison src/video/x11/SDL_x11render.c @ 2870:b801df19835f

The X11 window and all pixmaps and images share the same visual and depth.
author Sam Lantinga <slouken@libsdl.org>
date Sun, 14 Dec 2008 04:36:32 +0000
parents 3b595278f813
children 36e312e0fac0
comparison
equal deleted inserted replaced
2869:2fe507a2ef7d 2870:b801df19835f
75 75
76 typedef struct 76 typedef struct
77 { 77 {
78 Display *display; 78 Display *display;
79 int screen; 79 int screen;
80 Visual *visual;
81 int depth;
80 Window window; 82 Window window;
81 Pixmap pixmaps[3]; 83 Pixmap pixmaps[3];
82 int current_pixmap; 84 int current_pixmap;
83 Drawable drawable; 85 Drawable drawable;
84 SDL_PixelFormat *format; 86 SDL_PixelFormat *format;
130 rect.h = texture->h; 132 rect.h = texture->h;
131 SDL_SW_CopyYUVToRGB(data->yuv, &rect, data->format, texture->w, 133 SDL_SW_CopyYUVToRGB(data->yuv, &rect, data->format, texture->w,
132 texture->h, data->pixels, data->pitch); 134 texture->h, data->pixels, data->pitch);
133 } 135 }
134 136
135 static int
136 X11_GetDepthFromPixelFormat(Uint32 format)
137 {
138 int depth, order;
139
140 depth = SDL_BITSPERPIXEL(format);
141 order = SDL_PIXELORDER(format);
142 if (depth == 32
143 && (order == SDL_PACKEDORDER_XRGB || order == SDL_PACKEDORDER_RGBX
144 || SDL_PACKEDORDER_XBGR || order == SDL_PACKEDORDER_BGRX)) {
145 depth = 24;
146 }
147 return depth;
148 }
149
150 static Uint32
151 X11_GetPixelFormatFromDepth(Display * display, int screen, int depth, int bpp)
152 {
153 XVisualInfo vinfo;
154
155 if (XMatchVisualInfo(display, screen, depth, DirectColor, &vinfo) ||
156 XMatchVisualInfo(display, screen, depth, TrueColor, &vinfo)) {
157 Uint32 Rmask, Gmask, Bmask, Amask;
158
159 Rmask = vinfo.visual->red_mask;
160 Gmask = vinfo.visual->green_mask;
161 Bmask = vinfo.visual->blue_mask;
162 if (vinfo.depth == 32) {
163 Amask = (0xFFFFFFFF & ~(Rmask | Gmask | Bmask));
164 } else {
165 Amask = 0;
166 }
167 return SDL_MasksToPixelFormatEnum(bpp, Rmask, Gmask, Bmask, Amask);
168 }
169
170 /* No matching visual, try to pick a safe default */
171 switch (depth) {
172 case 15:
173 return SDL_PIXELFORMAT_RGB555;
174 case 16:
175 return SDL_PIXELFORMAT_RGB565;
176 default:
177 break;
178 }
179 return SDL_PIXELFORMAT_UNKNOWN;
180 }
181
182 void 137 void
183 X11_AddRenderDriver(_THIS) 138 X11_AddRenderDriver(_THIS)
184 { 139 {
185 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; 140 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
186 SDL_RendererInfo *info = &X11_RenderDriver.info; 141 SDL_RendererInfo *info = &X11_RenderDriver.info;
187 XPixmapFormatValues *pixmapFormats; 142 SDL_DisplayMode *mode = &SDL_CurrentDisplay.desktop_mode;
188 int i, n, bpp; 143
189 144 info->texture_formats[info->num_texture_formats++] = mode->format;
190 /* Query the available texture formats */ 145 info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_YV12;
191 pixmapFormats = XListPixmapFormats(data->display, &n); 146 info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_IYUV;
192 if (pixmapFormats) { 147 info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_YUY2;
193 info->num_texture_formats = 0; 148 info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_UYVY;
194 for (i = 0; i < n; ++i) { 149 info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_YVYU;
195 Uint32 format;
196
197 if (pixmapFormats[i].depth == 24) {
198 bpp = pixmapFormats[i].bits_per_pixel;
199 } else {
200 bpp = pixmapFormats[i].depth;
201 }
202 format =
203 X11_GetPixelFormatFromDepth(data->display,
204 DefaultScreen(data->display),
205 pixmapFormats[i].depth, bpp);
206 if (format != SDL_PIXELFORMAT_UNKNOWN) {
207 info->texture_formats[info->num_texture_formats++] = format;
208 }
209 }
210 XFree(pixmapFormats);
211
212 if (info->num_texture_formats == 0) {
213 return;
214 }
215 info->texture_formats[info->num_texture_formats++] =
216 SDL_PIXELFORMAT_YV12;
217 info->texture_formats[info->num_texture_formats++] =
218 SDL_PIXELFORMAT_IYUV;
219 info->texture_formats[info->num_texture_formats++] =
220 SDL_PIXELFORMAT_YUY2;
221 info->texture_formats[info->num_texture_formats++] =
222 SDL_PIXELFORMAT_UYVY;
223 info->texture_formats[info->num_texture_formats++] =
224 SDL_PIXELFORMAT_YVYU;
225 }
226 150
227 SDL_AddRenderDriver(0, &X11_RenderDriver); 151 SDL_AddRenderDriver(0, &X11_RenderDriver);
228 } 152 }
229 153
230 SDL_Renderer * 154 SDL_Renderer *
231 X11_CreateRenderer(SDL_Window * window, Uint32 flags) 155 X11_CreateRenderer(SDL_Window * window, Uint32 flags)
232 { 156 {
233 SDL_DisplayData *displaydata = 157 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
234 (SDL_DisplayData *) SDL_GetDisplayFromWindow(window)->driverdata; 158 SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
235 SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata; 159 SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata;
236 SDL_Renderer *renderer; 160 SDL_Renderer *renderer;
237 SDL_RendererInfo *info; 161 SDL_RendererInfo *info;
238 X11_RenderData *data; 162 X11_RenderData *data;
239 XWindowAttributes attributes;
240 XGCValues gcv; 163 XGCValues gcv;
241 int i, n; 164 int i, n;
242 int bpp; 165 int bpp;
243 Uint32 Rmask, Gmask, Bmask, Amask; 166 Uint32 Rmask, Gmask, Bmask, Amask;
244 167
254 SDL_OutOfMemory(); 177 SDL_OutOfMemory();
255 return NULL; 178 return NULL;
256 } 179 }
257 data->display = windowdata->videodata->display; 180 data->display = windowdata->videodata->display;
258 data->screen = displaydata->screen; 181 data->screen = displaydata->screen;
182 data->visual = displaydata->visual;
183 data->depth = displaydata->depth;
259 data->window = windowdata->window; 184 data->window = windowdata->window;
260 185
261 renderer->DisplayModeChanged = X11_DisplayModeChanged; 186 renderer->DisplayModeChanged = X11_DisplayModeChanged;
262 renderer->CreateTexture = X11_CreateTexture; 187 renderer->CreateTexture = X11_CreateTexture;
263 renderer->QueryTexturePixels = X11_QueryTexturePixels; 188 renderer->QueryTexturePixels = X11_QueryTexturePixels;
289 n = 3; 214 n = 3;
290 } else { 215 } else {
291 renderer->info.flags |= SDL_RENDERER_PRESENTCOPY; 216 renderer->info.flags |= SDL_RENDERER_PRESENTCOPY;
292 n = 1; 217 n = 1;
293 } 218 }
294 XGetWindowAttributes(data->display, data->window, &attributes);
295 for (i = 0; i < n; ++i) { 219 for (i = 0; i < n; ++i) {
296 data->pixmaps[i] = 220 data->pixmaps[i] =
297 XCreatePixmap(data->display, data->window, window->w, window->h, 221 XCreatePixmap(data->display, data->window, window->w, window->h,
298 attributes.depth); 222 displaydata->depth);
299 if (data->pixmaps[i] == None) { 223 if (data->pixmaps[i] == None) {
300 X11_DestroyRenderer(renderer); 224 X11_DestroyRenderer(renderer);
301 SDL_SetError("XCreatePixmap() failed"); 225 SDL_SetError("XCreatePixmap() failed");
302 return NULL; 226 return NULL;
303 } 227 }
310 data->makedirty = SDL_FALSE; 234 data->makedirty = SDL_FALSE;
311 } 235 }
312 data->current_pixmap = 0; 236 data->current_pixmap = 0;
313 237
314 /* Get the format of the window */ 238 /* Get the format of the window */
315 bpp = attributes.depth; 239 if (!SDL_PixelFormatEnumToMasks(display->current_mode.format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
316 if (bpp == 24) { 240 SDL_SetError("Unknown display format");
317 XPixmapFormatValues *p = XListPixmapFormats(data->display, &n); 241 X11_DestroyRenderer(renderer);
318 if (p) { 242 return NULL;
319 for (i = 0; i < n; ++i) {
320 if (p[i].depth == 24) {
321 bpp = p[i].bits_per_pixel;
322 break;
323 }
324 }
325 XFree(p);
326 }
327 }
328 Rmask = attributes.visual->red_mask;
329 Gmask = attributes.visual->green_mask;
330 Bmask = attributes.visual->blue_mask;
331 if (attributes.depth == 32) {
332 Amask = (0xFFFFFFFF & ~(Rmask | Gmask | Bmask));
333 } else {
334 Amask = 0;
335 } 243 }
336 data->format = SDL_AllocFormat(bpp, Rmask, Gmask, Bmask, Amask); 244 data->format = SDL_AllocFormat(bpp, Rmask, Gmask, Bmask, Amask);
337 if (!data->format) { 245 if (!data->format) {
338 X11_DestroyRenderer(renderer); 246 X11_DestroyRenderer(renderer);
339 return NULL; 247 return NULL;
355 static int 263 static int
356 X11_DisplayModeChanged(SDL_Renderer * renderer) 264 X11_DisplayModeChanged(SDL_Renderer * renderer)
357 { 265 {
358 X11_RenderData *data = (X11_RenderData *) renderer->driverdata; 266 X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
359 SDL_Window *window = SDL_GetWindowFromID(renderer->window); 267 SDL_Window *window = SDL_GetWindowFromID(renderer->window);
360 XWindowAttributes attributes;
361 int i, n; 268 int i, n;
362 269
363 if (renderer->info.flags & SDL_RENDERER_SINGLEBUFFER) { 270 if (renderer->info.flags & SDL_RENDERER_SINGLEBUFFER) {
364 n = 0; 271 n = 0;
365 } else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) { 272 } else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) {
373 if (data->pixmaps[i] != None) { 280 if (data->pixmaps[i] != None) {
374 XFreePixmap(data->display, data->pixmaps[i]); 281 XFreePixmap(data->display, data->pixmaps[i]);
375 data->pixmaps[i] = None; 282 data->pixmaps[i] = None;
376 } 283 }
377 } 284 }
378 XGetWindowAttributes(data->display, data->window, &attributes);
379 for (i = 0; i < n; ++i) { 285 for (i = 0; i < n; ++i) {
380 data->pixmaps[i] = 286 data->pixmaps[i] =
381 XCreatePixmap(data->display, data->window, window->w, window->h, 287 XCreatePixmap(data->display, data->window, window->w, window->h,
382 attributes.depth); 288 data->depth);
383 if (data->pixmaps[i] == None) { 289 if (data->pixmaps[i] == None) {
384 SDL_SetError("XCreatePixmap() failed"); 290 SDL_SetError("XCreatePixmap() failed");
385 return -1; 291 return -1;
386 } 292 }
387 } 293 }
398 { 304 {
399 X11_RenderData *renderdata = (X11_RenderData *) renderer->driverdata; 305 X11_RenderData *renderdata = (X11_RenderData *) renderer->driverdata;
400 SDL_Window *window = SDL_GetWindowFromID(renderer->window); 306 SDL_Window *window = SDL_GetWindowFromID(renderer->window);
401 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); 307 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
402 X11_TextureData *data; 308 X11_TextureData *data;
403 XWindowAttributes attributes;
404 int depth;
405 309
406 data = (X11_TextureData *) SDL_calloc(1, sizeof(*data)); 310 data = (X11_TextureData *) SDL_calloc(1, sizeof(*data));
407 if (!data) { 311 if (!data) {
408 SDL_OutOfMemory(); 312 SDL_OutOfMemory();
409 return -1; 313 return -1;
417 if (!data->yuv) { 321 if (!data->yuv) {
418 return -1; 322 return -1;
419 } 323 }
420 data->format = display->current_mode.format; 324 data->format = display->current_mode.format;
421 } else { 325 } else {
326 /* The image/pixmap depth must be the same as the window or you
327 get a BadMatch error when trying to putimage or copyarea.
328 */
329 if (texture->format != display->current_mode.format) {
330 SDL_SetError("Texture format doesn't match window format");
331 return -1;
332 }
422 data->format = texture->format; 333 data->format = texture->format;
423 } 334 }
424 data->pitch = texture->w * SDL_BYTESPERPIXEL(data->format); 335 data->pitch = texture->w * SDL_BYTESPERPIXEL(data->format);
425
426 XGetWindowAttributes(renderdata->display, renderdata->window,
427 &attributes);
428 depth = X11_GetDepthFromPixelFormat(data->format);
429
430 /* The image/pixmap depth must be the same as the window or you
431 get a BadMatch error when trying to putimage or copyarea.
432 */
433 if (depth != attributes.depth) {
434 X11_DestroyTexture(renderer, texture);
435 SDL_SetError("Texture format doesn't match window format");
436 return -1;
437 }
438 336
439 if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING) { 337 if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING) {
440 #ifndef NO_SHARED_MEMORY 338 #ifndef NO_SHARED_MEMORY
441 XShmSegmentInfo *shminfo = &data->shminfo; 339 XShmSegmentInfo *shminfo = &data->shminfo;
442 340
464 } 362 }
465 if (!shm_error) { 363 if (!shm_error) {
466 data->pixels = shminfo->shmaddr; 364 data->pixels = shminfo->shmaddr;
467 365
468 data->image = 366 data->image =
469 XShmCreateImage(renderdata->display, attributes.visual, depth, 367 XShmCreateImage(renderdata->display, renderdata->visual, renderdata->depth, ZPixmap, shminfo->shmaddr, shminfo, texture->w, texture->h);
470 ZPixmap, shminfo->shmaddr, shminfo,
471 texture->w, texture->h);
472 if (!data->image) { 368 if (!data->image) {
473 XShmDetach(renderdata->display, shminfo); 369 XShmDetach(renderdata->display, shminfo);
474 XSync(renderdata->display, False); 370 XSync(renderdata->display, False);
475 shmdt(shminfo->shmaddr); 371 shmdt(shminfo->shmaddr);
476 shm_error = True; 372 shm_error = True;
488 SDL_OutOfMemory(); 384 SDL_OutOfMemory();
489 return -1; 385 return -1;
490 } 386 }
491 387
492 data->image = 388 data->image =
493 XCreateImage(renderdata->display, attributes.visual, depth, 389 XCreateImage(renderdata->display, renderdata->visual, renderdata->depth, ZPixmap, 0, data->pixels, texture->w, texture->h, SDL_BYTESPERPIXEL(data->format) * 8, data->pitch);
494 ZPixmap, 0, data->pixels, texture->w, texture->h,
495 SDL_BYTESPERPIXEL(data->format) * 8,
496 data->pitch);
497 if (!data->image) { 390 if (!data->image) {
498 X11_DestroyTexture(renderer, texture); 391 X11_DestroyTexture(renderer, texture);
499 SDL_SetError("XCreateImage() failed"); 392 SDL_SetError("XCreateImage() failed");
500 return -1; 393 return -1;
501 } 394 }
502 } 395 }
503 } else { 396 } else {
504 data->pixmap = 397 data->pixmap =
505 XCreatePixmap(renderdata->display, renderdata->window, texture->w, 398 XCreatePixmap(renderdata->display, renderdata->window, texture->w,
506 texture->h, depth); 399 texture->h, renderdata->depth);
507 if (data->pixmap == None) { 400 if (data->pixmap == None) {
508 X11_DestroyTexture(renderer, texture); 401 X11_DestroyTexture(renderer, texture);
509 SDL_SetError("XCteatePixmap() failed"); 402 SDL_SetError("XCteatePixmap() failed");
510 return -1; 403 return -1;
511 } 404 }
512 405
513 data->image = 406 data->image =
514 XCreateImage(renderdata->display, attributes.visual, depth, 407 XCreateImage(renderdata->display, renderdata->visual, renderdata->depth, ZPixmap, 0, NULL, texture->w, texture->h, SDL_BYTESPERPIXEL(data->format) * 8, data->pitch);
515 ZPixmap, 0, NULL, texture->w, texture->h,
516 SDL_BYTESPERPIXEL(data->format) * 8, data->pitch);
517 if (!data->image) { 408 if (!data->image) {
518 X11_DestroyTexture(renderer, texture); 409 X11_DestroyTexture(renderer, texture);
519 SDL_SetError("XCreateImage() failed"); 410 SDL_SetError("XCreateImage() failed");
520 return -1; 411 return -1;
521 } 412 }
701 SDL_PixelFormat fmt; 592 SDL_PixelFormat fmt;
702 SDL_Rect rect; 593 SDL_Rect rect;
703 XImage *image = texturedata->scaling_image; 594 XImage *image = texturedata->scaling_image;
704 595
705 if (!image) { 596 if (!image) {
706 XWindowAttributes attributes;
707 int depth; 597 int depth;
708 void *pixels; 598 void *pixels;
709 int pitch; 599 int pitch;
710
711 XGetWindowAttributes(data->display, data->window, &attributes);
712 600
713 pitch = dstrect->w * SDL_BYTESPERPIXEL(texturedata->format); 601 pitch = dstrect->w * SDL_BYTESPERPIXEL(texturedata->format);
714 pixels = SDL_malloc(dstrect->h * pitch); 602 pixels = SDL_malloc(dstrect->h * pitch);
715 if (!pixels) { 603 if (!pixels) {
716 SDL_OutOfMemory(); 604 SDL_OutOfMemory();
717 return -1; 605 return -1;
718 } 606 }
719 607
720 depth = X11_GetDepthFromPixelFormat(texturedata->format);
721 image = 608 image =
722 XCreateImage(data->display, attributes.visual, depth, ZPixmap, 609 XCreateImage(data->display, data->visual, data->depth, ZPixmap,
723 0, pixels, dstrect->w, dstrect->h, 610 0, pixels, dstrect->w, dstrect->h,
724 SDL_BYTESPERPIXEL(texturedata->format) * 8, 611 SDL_BYTESPERPIXEL(texturedata->format) * 8,
725 pitch); 612 pitch);
726 if (!image) { 613 if (!image) {
727 SDL_SetError("XCreateImage() failed"); 614 SDL_SetError("XCreateImage() failed");