comparison src/video/x11/SDL_x11render.c @ 2828:7e5ff6cd05bf

Added very slow software scaling to the X11 renderer
author Sam Lantinga <slouken@libsdl.org>
date Wed, 03 Dec 2008 12:10:51 +0000
parents aec4399c507a
children 99210400e8b9
comparison
equal deleted inserted replaced
2827:aec4399c507a 2828:7e5ff6cd05bf
95 XImage *image; 95 XImage *image;
96 #ifndef NO_SHARED_MEMORY 96 #ifndef NO_SHARED_MEMORY
97 /* MIT shared memory extension information */ 97 /* MIT shared memory extension information */
98 XShmSegmentInfo shminfo; 98 XShmSegmentInfo shminfo;
99 #endif 99 #endif
100 XImage *scaling_image;
100 void *pixels; 101 void *pixels;
101 int pitch; 102 int pitch;
102 } X11_TextureData; 103 } X11_TextureData;
103 104
104 #ifndef NO_SHARED_MEMORY 105 #ifndef NO_SHARED_MEMORY
127 rect.y = 0; 128 rect.y = 0;
128 rect.w = texture->w; 129 rect.w = texture->w;
129 rect.h = texture->h; 130 rect.h = texture->h;
130 SDL_SW_CopyYUVToRGB(data->yuv, &rect, data->format, texture->w, 131 SDL_SW_CopyYUVToRGB(data->yuv, &rect, data->format, texture->w,
131 texture->h, data->pixels, data->pitch); 132 texture->h, data->pixels, data->pitch);
133 }
134
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;
132 } 148 }
133 149
134 static Uint32 150 static Uint32
135 X11_GetPixelFormatFromDepth(Display * display, int screen, int depth, int bpp) 151 X11_GetPixelFormatFromDepth(Display * display, int screen, int depth, int bpp)
136 { 152 {
383 X11_RenderData *renderdata = (X11_RenderData *) renderer->driverdata; 399 X11_RenderData *renderdata = (X11_RenderData *) renderer->driverdata;
384 SDL_Window *window = SDL_GetWindowFromID(renderer->window); 400 SDL_Window *window = SDL_GetWindowFromID(renderer->window);
385 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); 401 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
386 X11_TextureData *data; 402 X11_TextureData *data;
387 XWindowAttributes attributes; 403 XWindowAttributes attributes;
388 int depth, order; 404 int depth;
389 405
390 data = (X11_TextureData *) SDL_calloc(1, sizeof(*data)); 406 data = (X11_TextureData *) SDL_calloc(1, sizeof(*data));
391 if (!data) { 407 if (!data) {
392 SDL_OutOfMemory(); 408 SDL_OutOfMemory();
393 return -1; 409 return -1;
407 } 423 }
408 data->pitch = texture->w * SDL_BYTESPERPIXEL(data->format); 424 data->pitch = texture->w * SDL_BYTESPERPIXEL(data->format);
409 425
410 XGetWindowAttributes(renderdata->display, renderdata->window, 426 XGetWindowAttributes(renderdata->display, renderdata->window,
411 &attributes); 427 &attributes);
412 depth = SDL_BITSPERPIXEL(data->format); 428 depth = X11_GetDepthFromPixelFormat(data->format);
413 order = SDL_PIXELORDER(data->format);
414 if (depth == 32
415 && (order == SDL_PACKEDORDER_XRGB || order == SDL_PACKEDORDER_RGBX
416 || SDL_PACKEDORDER_XBGR || order == SDL_PACKEDORDER_BGRX)) {
417 depth = 24;
418 }
419 429
420 if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING) { 430 if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING) {
421 #ifndef NO_SHARED_MEMORY 431 #ifndef NO_SHARED_MEMORY
422 XShmSegmentInfo *shminfo = &data->shminfo; 432 XShmSegmentInfo *shminfo = &data->shminfo;
423 433
530 } 540 }
531 541
532 static int 542 static int
533 X11_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture) 543 X11_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture)
534 { 544 {
545 X11_TextureData *data = (X11_TextureData *) texture->driverdata;
546
535 switch (texture->scaleMode) { 547 switch (texture->scaleMode) {
536 case SDL_TEXTURESCALEMODE_NONE: 548 case SDL_TEXTURESCALEMODE_NONE:
537 return 0; 549 return 0;
550 case SDL_TEXTURESCALEMODE_FAST:
551 /* We can sort of fake it for streaming textures */
552 if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING) {
553 return 0;
554 }
555 /* Fall through to unsupported case */
538 default: 556 default:
539 SDL_Unsupported(); 557 SDL_Unsupported();
540 texture->scaleMode = SDL_TEXTURESCALEMODE_NONE; 558 texture->scaleMode = SDL_TEXTURESCALEMODE_NONE;
541 return -1; 559 return -1;
542 } 560 }
644 X11_TextureData *texturedata = (X11_TextureData *) texture->driverdata; 662 X11_TextureData *texturedata = (X11_TextureData *) texture->driverdata;
645 663
646 if (data->makedirty) { 664 if (data->makedirty) {
647 SDL_AddDirtyRect(&data->dirty, dstrect); 665 SDL_AddDirtyRect(&data->dirty, dstrect);
648 } 666 }
667 if (srcrect->w == dstrect->w && srcrect->h == dstrect->h) {
649 #ifndef NO_SHARED_MEMORY 668 #ifndef NO_SHARED_MEMORY
650 if (texturedata->shminfo.shmaddr) { 669 if (texturedata->shminfo.shmaddr) {
651 XShmPutImage(data->display, data->drawable, data->gc, 670 XShmPutImage(data->display, data->drawable, data->gc,
652 texturedata->image, srcrect->x, srcrect->y, dstrect->x, 671 texturedata->image, srcrect->x, srcrect->y,
653 dstrect->y, srcrect->w, srcrect->h, False); 672 dstrect->x, dstrect->y, srcrect->w, srcrect->h,
654 } else 673 False);
674 } else
655 #endif 675 #endif
656 if (texturedata->pixels) { 676 if (texturedata->pixels) {
657 XPutImage(data->display, data->drawable, data->gc, texturedata->image, 677 XPutImage(data->display, data->drawable, data->gc,
658 srcrect->x, srcrect->y, dstrect->x, dstrect->y, srcrect->w, 678 texturedata->image, srcrect->x, srcrect->y, dstrect->x,
659 srcrect->h); 679 dstrect->y, srcrect->w, srcrect->h);
680 } else {
681 XCopyArea(data->display, texturedata->pixmap, data->drawable,
682 data->gc, srcrect->x, srcrect->y, dstrect->w,
683 dstrect->h, srcrect->x, srcrect->y);
684 }
685 } else if (texturedata->yuv
686 || texture->access == SDL_TEXTUREACCESS_STREAMING) {
687 SDL_Surface src, dst;
688 SDL_PixelFormat fmt;
689 SDL_Rect rect;
690 XImage *image = texturedata->scaling_image;
691
692 if (!image) {
693 XWindowAttributes attributes;
694 int depth;
695 void *pixels;
696 int pitch;
697
698 XGetWindowAttributes(data->display, data->window, &attributes);
699
700 pitch = dstrect->w * SDL_BYTESPERPIXEL(texturedata->format);
701 pixels = SDL_malloc(dstrect->h * pitch);
702 if (!pixels) {
703 SDL_OutOfMemory();
704 return -1;
705 }
706
707 depth = X11_GetDepthFromPixelFormat(texturedata->format);
708 image =
709 XCreateImage(data->display, attributes.visual, depth, ZPixmap,
710 0, pixels, dstrect->w, dstrect->h,
711 SDL_BYTESPERPIXEL(texturedata->format) * 8,
712 pitch);
713 if (!image) {
714 SDL_SetError("XCreateImage() failed");
715 return -1;
716 }
717 texturedata->scaling_image = image;
718
719 } else if (image->width != dstrect->w || image->height != dstrect->h
720 || !image->data) {
721 image->width = dstrect->w;
722 image->height = dstrect->h;
723 image->bytes_per_line =
724 image->width * SDL_BYTESPERPIXEL(texturedata->format);
725 image->data =
726 (char *) SDL_realloc(image->data,
727 image->height * image->bytes_per_line);
728 if (!image->data) {
729 SDL_OutOfMemory();
730 return -1;
731 }
732 }
733
734 /* Set up fake surfaces for SDL_SoftStretch() */
735 src.format = &fmt;
736 src.w = texture->w;
737 src.h = texture->h;
738 #ifndef NO_SHARED_MEMORY
739 if (texturedata->shminfo.shmaddr) {
740 src.pixels = texturedata->shminfo.shmaddr;
741 } else
742 #endif
743 src.pixels = texturedata->pixels;
744 src.pitch = texturedata->pitch;
745
746 dst.format = &fmt;
747 dst.w = image->width;
748 dst.h = image->height;
749 dst.pixels = image->data;
750 dst.pitch = image->bytes_per_line;
751
752 fmt.BytesPerPixel = SDL_BYTESPERPIXEL(texturedata->format);
753
754 rect.x = 0;
755 rect.y = 0;
756 rect.w = dstrect->w;
757 rect.h = dstrect->h;
758 if (SDL_SoftStretch(&src, srcrect, &dst, &rect) < 0) {
759 return -1;
760 }
761 XPutImage(data->display, data->drawable, data->gc, image, 0, 0,
762 dstrect->x, dstrect->y, dstrect->w, dstrect->h);
660 } else { 763 } else {
661 XCopyArea(data->display, texturedata->pixmap, data->drawable, 764 XCopyArea(data->display, texturedata->pixmap, data->drawable,
662 data->gc, srcrect->x, srcrect->y, dstrect->w, dstrect->h, 765 data->gc, srcrect->x, srcrect->y, dstrect->w, dstrect->h,
663 srcrect->x, srcrect->y); 766 srcrect->x, srcrect->y);
664 } 767 }
718 XSync(renderdata->display, False); 821 XSync(renderdata->display, False);
719 shmdt(data->shminfo.shmaddr); 822 shmdt(data->shminfo.shmaddr);
720 data->pixels = NULL; 823 data->pixels = NULL;
721 } 824 }
722 #endif 825 #endif
826 if (data->scaling_image) {
827 SDL_free(data->scaling_image->data);
828 data->scaling_image->data = NULL;
829 XDestroyImage(data->scaling_image);
830 }
723 if (data->pixels) { 831 if (data->pixels) {
724 SDL_free(data->pixels); 832 SDL_free(data->pixels);
725 } 833 }
726 SDL_free(data); 834 SDL_free(data);
727 texture->driverdata = NULL; 835 texture->driverdata = NULL;