Mercurial > sdl-ios-xcode
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"); |