comparison src/video/x11/SDL_x11render.c @ 4586:e479c1e57c52

SDL_Textures should work with XRender now provided that the texture format and screen format match. This is only a temporary limitation.
author Sunny Sachanandani <sunnysachanandani@gmail.com>
date Wed, 16 Jun 2010 10:50:01 +0530
parents 21600c6d6445
children 25391ccf16a0
comparison
equal deleted inserted replaced
4585:21600c6d6445 4586:e479c1e57c52
120 Uint32 format; 120 Uint32 format;
121 Pixmap pixmap; 121 Pixmap pixmap;
122 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER 122 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
123 Picture picture; 123 Picture picture;
124 XRenderPictFormat* picture_fmt; 124 XRenderPictFormat* picture_fmt;
125 XRenderPictureAttributes picture_attr;
126 unsigned int picture_attr_valuemask;
127 SDL_bool use_xrender; 125 SDL_bool use_xrender;
128 #endif 126 #endif
129 XImage *image; 127 XImage *image;
130 #ifndef NO_SHARED_MEMORY 128 #ifndef NO_SHARED_MEMORY
131 /* MIT shared memory extension information */ 129 /* MIT shared memory extension information */
433 can be no BadMatch error since Xrender takes care of that. 431 can be no BadMatch error since Xrender takes care of that.
434 */ 432 */
435 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER 433 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
436 // Assume the texture is supported by Xrender 434 // Assume the texture is supported by Xrender
437 data->use_xrender = SDL_TRUE; 435 data->use_xrender = SDL_TRUE;
438 if(renderdata->use_xrender == SDL_FALSE) { 436 if (renderdata->use_xrender == SDL_FALSE) {
439 if (texture->format != display->current_mode.format) { 437 if (texture->format != display->current_mode.format) {
440 SDL_SetError("Texture format doesn't match window format"); 438 SDL_SetError("Texture format doesn't match window format");
441 return -1; 439 return -1;
442 } 440 }
443 } 441 }
488 data->image = 486 data->image =
489 XShmCreateImage(renderdata->display, renderdata->visual, 487 XShmCreateImage(renderdata->display, renderdata->visual,
490 renderdata->depth, ZPixmap, shminfo->shmaddr, 488 renderdata->depth, ZPixmap, shminfo->shmaddr,
491 shminfo, texture->w, texture->h); 489 shminfo, texture->w, texture->h);
492 490
493 // This Pixmap is used by Xrender 491 if (!data->image) {
494 data->pixmap =
495 XShmCreatePixmap(renderdata->display, renderdata->xwindow, shminfo->shmaddr,
496 shminfo, texture->w, texture->h, renderdata->depth);
497
498 if (!(data->pixmap && data->image)) {
499 XShmDetach(renderdata->display, shminfo); 492 XShmDetach(renderdata->display, shminfo);
500 XSync(renderdata->display, False); 493 XSync(renderdata->display, False);
501 shmdt(shminfo->shmaddr); 494 shmdt(shminfo->shmaddr);
502 shm_error = True; 495 shm_error = True;
503 } 496 }
558 } 551 }
559 } 552 }
560 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER 553 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
561 if(renderdata->use_xrender && data->pixmap) { 554 if(renderdata->use_xrender && data->pixmap) {
562 data->use_xrender = SDL_TRUE; 555 data->use_xrender = SDL_TRUE;
563 unsigned long x11_fmt_mask; // Format mask 556 /*unsigned long x11_fmt_mask; // Format mask
564 XRenderPictFormat x11_templ_fmt; // Format template 557 XRenderPictFormat x11_templ_fmt; // Format template
565 x11_fmt_mask = 558 x11_fmt_mask =
566 (PictFormatDepth | PictFormatRedMask | PictFormatGreenMask 559 (PictFormatRedMask | PictFormatGreenMask
567 | PictFormatBlueMask); 560 | PictFormatBlueMask | PictFormatAlphaMask);
568 Uint32 Rmask, Gmask, Bmask, Amask; 561 Uint32 Rmask, Gmask, Bmask, Amask;
569 int bpp; 562 int bpp;
570 SDL_PixelFormatEnumToMasks(data->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask); 563 SDL_PixelFormatEnumToMasks(data->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask);
571 x11_templ_fmt.depth = bpp; 564 x11_templ_fmt.depth = bpp;
572 x11_templ_fmt.direct.redMask = Rmask; 565 x11_templ_fmt.type = PictTypeDirect;
573 x11_templ_fmt.direct.greenMask = Gmask; 566 x11_templ_fmt.direct.red = Rmask / 0xff;
574 x11_templ_fmt.direct.blueMask = Bmask; 567 x11_templ_fmt.direct.green = Gmask / 0xff;
575 x11_templ_fmt.direct.alphaMask = Amask; 568 x11_templ_fmt.direct.blue = Bmask / 0xff;
576 /* Return one matching XRenderPictFormat */ 569 x11_templ_fmt.direct.alpha = Amask / 0xff;
570 printf("%d %d %d %d\n", Rmask/0xff, Gmask/0xff, Bmask/0xff, Amask/0xff);
571 // Return a matching XRenderPictFormat
577 data->picture_fmt = 572 data->picture_fmt =
578 XRenderFindFormat(renderdata->display, x11_fmt_mask, &x11_templ_fmt, 1); 573 XRenderFindFormat(renderdata->display, x11_fmt_mask, &x11_templ_fmt, 0);*/
574 data->picture_fmt =
575 XRenderFindVisualFormat(renderdata->display, renderdata->visual);
579 if(!data->picture_fmt) { 576 if(!data->picture_fmt) {
577 printf("XRenderFindFormat failed!\n");
580 data->use_xrender = SDL_FALSE; 578 data->use_xrender = SDL_FALSE;
581 } 579 }
582 data->picture_attr_valuemask = CPGraphicsExposure;
583 (data->picture_attr).graphics_exposures = False;
584 data->picture = 580 data->picture =
585 XRenderCreatePicture(renderdata->display, data->pixmap, data->picture_fmt, 581 XRenderCreatePicture(renderdata->display, data->pixmap,
586 data->picture_attr_valuemask, &(data->picture_attr)); 582 data->picture_fmt, 0, NULL);
587 if(!data->picture) { 583 if(!data->picture) {
588 data->use_xrender = SDL_FALSE; 584 data->use_xrender = SDL_FALSE;
589 } 585 }
590 } 586 }
591 /* We thought we could render the texture with Xrender but this was 587 /* We thought we could render the texture with Xrender but this was
592 not possible for some reason. Now we must ensure that texture 588 not possible for some reason. Now we must ensure that texture
593 format and window format match to avoid a BadMatch error. 589 format and window format match to avoid a BadMatch error when
590 rendering using the old pipeline.
594 */ 591 */
595 if(data->use_xrender == SDL_FALSE) { 592 if(data->use_xrender == SDL_FALSE) {
596 if (texture->format != display->current_mode.format) { 593 if (texture->format != display->current_mode.format) {
597 SDL_SetError("Texture format doesn't match window format"); 594 SDL_SetError("Texture format doesn't match window format");
598 return -1; 595 return -1;
683 src += pitch; 680 src += pitch;
684 dst += data->pitch; 681 dst += data->pitch;
685 } 682 }
686 /* If this is a static texture we would use Xrender for it 683 /* If this is a static texture we would use Xrender for it
687 but this requires that the server side Pixmap associated 684 but this requires that the server side Pixmap associated
688 with this texture be updated with the data as well and 685 with this texture be updated with the data as well.
689 that the pixmap is not a shared memory pixmap.
690 Hopefully the user will not update static textures so 686 Hopefully the user will not update static textures so
691 frequently as to cause a slowdown. 687 frequently as to cause a slowdown.
692 */ 688 */
693 if (texture->access == SDL_TEXTUREACCESS_STATIC) { 689 if (texture->access == SDL_TEXTUREACCESS_STATIC) {
694 #ifndef NO_SHARED_MEMORY
695 if(!data->shminfo.shmaddr)
696 #endif
697 {
698 XPutImage(renderdata->display, data->pixmap, renderdata->gc, 690 XPutImage(renderdata->display, data->pixmap, renderdata->gc,
699 data->image, 0, 0, rect->x, rect->y, rect->w, rect->h); 691 data->image, 0, 0, rect->x, rect->y, rect->w, rect->h);
700 }
701 } 692 }
702 693
703 } else { 694 } else {
704 data->image->width = rect->w; 695 data->image->width = rect->w;
705 data->image->height = rect->h; 696 data->image->height = rect->h;
1209 X11_TextureData *texturedata = (X11_TextureData *) texture->driverdata; 1200 X11_TextureData *texturedata = (X11_TextureData *) texture->driverdata;
1210 1201
1211 if (data->makedirty) { 1202 if (data->makedirty) {
1212 SDL_AddDirtyRect(&data->dirty, dstrect); 1203 SDL_AddDirtyRect(&data->dirty, dstrect);
1213 } 1204 }
1214 if (srcrect->w == dstrect->w && srcrect->h == dstrect->h) { 1205 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
1206 if (data->use_xrender && texturedata->use_xrender && texture->access == SDL_TEXTUREACCESS_STATIC) {
1207 if(srcrect->w == dstrect->w && srcrect->h == dstrect->h) {
1208 XRenderComposite(data->display, PictOpOver, texturedata->picture, None, data->drawable_pict,
1209 srcrect->x, srcrect->y, 0, 0, dstrect->x, dstrect->y, srcrect->w, srcrect->h);
1210 } else {
1211 Pixmap scaling_pixmap =
1212 XCreatePixmap(data->display, texturedata->pixmap, dstrect->w, dstrect->h,
1213 data->depth);
1214 Picture scaling_picture =
1215 XRenderCreatePicture(data->display, scaling_pixmap, texturedata->picture_fmt,
1216 0, NULL);
1217 XRenderComposite(data->display, PictOpClear, scaling_picture, None, scaling_picture,
1218 0, 0, 0, 0, 0, 0, dstrect->w, dstrect->h);
1219 XRenderComposite(data->display, PictOpSrc, texturedata->picture, None, scaling_picture,
1220 srcrect->x, srcrect->y, 0, 0, 0, 0, srcrect->w, srcrect->h);
1221 double xscale = ((double) dstrect->w) / srcrect->w;
1222 double yscale = ((double) dstrect->h) / srcrect->h;
1223 XTransform xform =
1224 {{{XDoubleToFixed(xscale), XDoubleToFixed(0), XDoubleToFixed(0)},
1225 {XDoubleToFixed(0), XDoubleToFixed(yscale), XDoubleToFixed(0)},
1226 {XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(xscale * yscale)}}};
1227 XRenderSetPictureTransform(data->display, scaling_picture, &xform);
1228 XRenderComposite(data->display, PictOpOver, scaling_picture, None, data->drawable_pict,
1229 0, 0, 0, 0, dstrect->x, dstrect->y, dstrect->w, dstrect->h);
1230 XRenderFreePicture(data->display, scaling_picture);
1231 XFreePixmap(data->display, scaling_pixmap);
1232 }
1233 }
1234 else
1235 #endif
1236 {
1237 if (srcrect->w == dstrect->w && srcrect->h == dstrect->h) {
1215 #ifndef NO_SHARED_MEMORY 1238 #ifndef NO_SHARED_MEMORY
1216 if (texturedata->shminfo.shmaddr) { 1239 if (texturedata->shminfo.shmaddr) {
1217 XShmPutImage(data->display, data->drawable, data->gc, 1240 XShmPutImage(data->display, data->drawable, data->gc,
1218 texturedata->image, srcrect->x, srcrect->y, 1241 texturedata->image, srcrect->x, srcrect->y,
1219 dstrect->x, dstrect->y, srcrect->w, srcrect->h, 1242 dstrect->x, dstrect->y, srcrect->w, srcrect->h,
1220 False); 1243 False);
1221 } else 1244 } else
1222 #endif 1245 #endif
1223 if (texturedata->pixels) { 1246 if (texturedata->pixels) {
1224 XPutImage(data->display, data->drawable, data->gc, 1247 XPutImage(data->display, data->drawable, data->gc,
1225 texturedata->image, srcrect->x, srcrect->y, dstrect->x, 1248 texturedata->image, srcrect->x, srcrect->y, dstrect->x,
1226 dstrect->y, srcrect->w, srcrect->h); 1249 dstrect->y, srcrect->w, srcrect->h);
1250 } else {
1251 XCopyArea(data->display, texturedata->pixmap, data->drawable,
1252 data->gc, srcrect->x, srcrect->y, dstrect->w,
1253 dstrect->h, dstrect->x, dstrect->y);
1254 }
1255 } else if (texturedata->yuv
1256 || texture->access == SDL_TEXTUREACCESS_STREAMING) {
1257 SDL_Surface src, dst;
1258 SDL_PixelFormat fmt;
1259 SDL_Rect rect;
1260 XImage *image = texturedata->scaling_image;
1261
1262 if (!image) {
1263 void *pixels;
1264 int pitch;
1265
1266 pitch = dstrect->w * SDL_BYTESPERPIXEL(texturedata->format);
1267 pixels = SDL_malloc(dstrect->h * pitch);
1268 if (!pixels) {
1269 SDL_OutOfMemory();
1270 return -1;
1271 }
1272
1273 image =
1274 XCreateImage(data->display, data->visual, data->depth,
1275 ZPixmap, 0, pixels, dstrect->w, dstrect->h,
1276 SDL_BYTESPERPIXEL(texturedata->format) * 8,
1277 pitch);
1278 if (!image) {
1279 SDL_SetError("XCreateImage() failed");
1280 return -1;
1281 }
1282 texturedata->scaling_image = image;
1283
1284 } else if (image->width != dstrect->w || image->height != dstrect->h
1285 || !image->data) {
1286 image->width = dstrect->w;
1287 image->height = dstrect->h;
1288 image->bytes_per_line =
1289 image->width * SDL_BYTESPERPIXEL(texturedata->format);
1290 image->data =
1291 (char *) SDL_realloc(image->data,
1292 image->height * image->bytes_per_line);
1293 if (!image->data) {
1294 SDL_OutOfMemory();
1295 return -1;
1296 }
1297 }
1298
1299 /* Set up fake surfaces for SDL_SoftStretch() */
1300 SDL_zero(src);
1301 src.format = &fmt;
1302 src.w = texture->w;
1303 src.h = texture->h;
1304 #ifndef NO_SHARED_MEMORY
1305 if (texturedata->shminfo.shmaddr) {
1306 src.pixels = texturedata->shminfo.shmaddr;
1307 } else
1308 #endif
1309 src.pixels = texturedata->pixels;
1310 src.pitch = texturedata->pitch;
1311
1312 SDL_zero(dst);
1313 dst.format = &fmt;
1314 dst.w = image->width;
1315 dst.h = image->height;
1316 dst.pixels = image->data;
1317 dst.pitch = image->bytes_per_line;
1318
1319 fmt.BytesPerPixel = SDL_BYTESPERPIXEL(texturedata->format);
1320
1321 rect.x = 0;
1322 rect.y = 0;
1323 rect.w = dstrect->w;
1324 rect.h = dstrect->h;
1325 if (SDL_SoftStretch(&src, srcrect, &dst, &rect) < 0) {
1326 return -1;
1327 }
1328 XPutImage(data->display, data->drawable, data->gc, image, 0, 0,
1329 dstrect->x, dstrect->y, dstrect->w, dstrect->h);
1227 } else { 1330 } else {
1228 XCopyArea(data->display, texturedata->pixmap, data->drawable, 1331 XCopyArea(data->display, texturedata->pixmap, data->drawable,
1229 data->gc, srcrect->x, srcrect->y, dstrect->w, 1332 data->gc, srcrect->x, srcrect->y, dstrect->w, dstrect->h,
1230 dstrect->h, dstrect->x, dstrect->y); 1333 srcrect->x, srcrect->y);
1231 } 1334 }
1232 } else if (texturedata->yuv
1233 || texture->access == SDL_TEXTUREACCESS_STREAMING) {
1234 SDL_Surface src, dst;
1235 SDL_PixelFormat fmt;
1236 SDL_Rect rect;
1237 XImage *image = texturedata->scaling_image;
1238
1239 if (!image) {
1240 void *pixels;
1241 int pitch;
1242
1243 pitch = dstrect->w * SDL_BYTESPERPIXEL(texturedata->format);
1244 pixels = SDL_malloc(dstrect->h * pitch);
1245 if (!pixels) {
1246 SDL_OutOfMemory();
1247 return -1;
1248 }
1249
1250 image =
1251 XCreateImage(data->display, data->visual, data->depth,
1252 ZPixmap, 0, pixels, dstrect->w, dstrect->h,
1253 SDL_BYTESPERPIXEL(texturedata->format) * 8,
1254 pitch);
1255 if (!image) {
1256 SDL_SetError("XCreateImage() failed");
1257 return -1;
1258 }
1259 texturedata->scaling_image = image;
1260
1261 } else if (image->width != dstrect->w || image->height != dstrect->h
1262 || !image->data) {
1263 image->width = dstrect->w;
1264 image->height = dstrect->h;
1265 image->bytes_per_line =
1266 image->width * SDL_BYTESPERPIXEL(texturedata->format);
1267 image->data =
1268 (char *) SDL_realloc(image->data,
1269 image->height * image->bytes_per_line);
1270 if (!image->data) {
1271 SDL_OutOfMemory();
1272 return -1;
1273 }
1274 }
1275
1276 /* Set up fake surfaces for SDL_SoftStretch() */
1277 SDL_zero(src);
1278 src.format = &fmt;
1279 src.w = texture->w;
1280 src.h = texture->h;
1281 #ifndef NO_SHARED_MEMORY
1282 if (texturedata->shminfo.shmaddr) {
1283 src.pixels = texturedata->shminfo.shmaddr;
1284 } else
1285 #endif
1286 src.pixels = texturedata->pixels;
1287 src.pitch = texturedata->pitch;
1288
1289 SDL_zero(dst);
1290 dst.format = &fmt;
1291 dst.w = image->width;
1292 dst.h = image->height;
1293 dst.pixels = image->data;
1294 dst.pitch = image->bytes_per_line;
1295
1296 fmt.BytesPerPixel = SDL_BYTESPERPIXEL(texturedata->format);
1297
1298 rect.x = 0;
1299 rect.y = 0;
1300 rect.w = dstrect->w;
1301 rect.h = dstrect->h;
1302 if (SDL_SoftStretch(&src, srcrect, &dst, &rect) < 0) {
1303 return -1;
1304 }
1305 XPutImage(data->display, data->drawable, data->gc, image, 0, 0,
1306 dstrect->x, dstrect->y, dstrect->w, dstrect->h);
1307 } else {
1308 XCopyArea(data->display, texturedata->pixmap, data->drawable,
1309 data->gc, srcrect->x, srcrect->y, dstrect->w, dstrect->h,
1310 srcrect->x, srcrect->y);
1311 } 1335 }
1312 return 0; 1336 return 0;
1313 } 1337 }
1314 1338
1315 static int 1339 static int