diff --git a/acconfig.h b/acconfig.h index a1ec4531..40c1895b 100644 --- a/acconfig.h +++ b/acconfig.h @@ -86,8 +86,11 @@ /* define if your X server has XConvertCase() */ #undef HAVE_XCONVERTCASE -/* define if you want Hermes support */ -#undef HAVE_HERMES +/* define if processor is x86 */ +#undef ASM_X86 + +/* define if processor is x86 with MMX(tm) support */ +#undef ASM_X86_MMX /* define if you have vsnprintf with C99 semantics */ #undef HAVE_C99_VSNPRINTF diff --git a/configure.ac b/configure.ac index c2bfcd43..64688676 100644 --- a/configure.ac +++ b/configure.ac @@ -189,7 +189,49 @@ AC_C_CONST #AC_TYPE_PID_T AC_TYPE_SIGNAL - + + +dnl Compiler/architecture specific optimizations +dnl ============================================ + + +dnl GCC/as with MMX support +dnl ----------------------- + +# until we fix it, leave it disabled +asm_support=no +mmx_support=no +if test "$ac_cv_prog_gcc" = yes; then + x86=0 + changequote(,)dnl + case "$host_cpu" in + i[3456]86) x86=1 + ;; + esac + changequote([,])dnl + + if test "$host_os" != "linux" -a "$host_os" != "linux-gnu" ; then + x86=0 + fi + + if test $x86 = 1; then + AC_DEFINE(ASM_X86) + asm_support=yes + + AC_CACHE_CHECK(whether gcc supports MMX(tm) inline asm, + ac_cv_c_inline_mmx, + [AC_TRY_LINK(,[asm ("movq %mm0, %mm1");], + ac_cv_c_inline_mmx=yes, + ac_cv_c_inline_mmx=no)]) + + if test "x$ac_cv_c_inline_mmx" = xyes; then + AC_DEFINE(ASM_X86_MMX) + mmx_support=yes + fi + fi +fi + + dnl gettext dnl ======= @@ -550,28 +592,6 @@ dnl =============================================== -dnl Hermes Support -dnl ============== - -AC_ARG_ENABLE(hermes, - [ --disable-hermes disable Hermes support for wrlib ], - hermes=$enableval, hermes=yes) - -if test x$hermes = xyes; then - WM_CHECK_LIB(Hermes, Hermes_ConverterRequest, []) - - if test x$ac_cv_lib_Hermes_Hermes_ConverterRequest = xyes; then - WM_CHECK_HEADER(Hermes/Hermes.h) - if test x$ac_cv_header_Hermes_Hermes_h = xyes; then - GFXLIBS="$GFXLIBS -lHermes" - AC_DEFINE(HAVE_HERMES) - hermes_support=yes - fi - fi -fi - - - dnl PNG Support dnl =========== png=yes @@ -974,9 +994,8 @@ echo "Installation path prefix: $prefix" echo "Installation path prefix for binaries: $_bindir" echo "Installation path for WPrefs.app: $wprefsdir" | sed -e 's|\$(prefix)|'"$prefix|" echo "Graphic format libraries: $supported_gfx" -if test x$hermes_support = xyes; then - echo "Hermes support for wrlib enabled" -fi +echo "Use assembly routines for wrlib: $asm_support" +echo "Use inline MMX(tm) x86 assembly: $mmx_support" dnl echo "Sound support: yes" echo "Translated message files to install: $mof" if test "x$MOFILES" != "x"; then diff --git a/wrlib/ChangeLog b/wrlib/ChangeLog index 5f785b7b..1abd13de 100644 --- a/wrlib/ChangeLog +++ b/wrlib/ChangeLog @@ -1,3 +1,7 @@ +- removed obsoleted RDestroyImage() +- removed Hermes code. +- Put back asm/mmx optimized code. + - fixed a bug in RCombineAreaWithOpaqueness() (Brad ) - Added retain/release mechanism to RImage by adding RRetainImage() and diff --git a/wrlib/Makefile.am b/wrlib/Makefile.am index 4bdc71be..8241f3da 100644 --- a/wrlib/Makefile.am +++ b/wrlib/Makefile.am @@ -4,7 +4,7 @@ AUTOMAKE_OPTIONS = no-dependencies lib_LTLIBRARIES = libwraster.la -libwraster_la_LDFLAGS = -version-info 4:0:2 +libwraster_la_LDFLAGS = -version-info 5:0:3 bin_SCRIPTS = get-wraster-flags @@ -20,7 +20,6 @@ libwraster_la_SOURCES = \ CrCmap.c \ DelCmap.c \ CmapAlloc.c \ - wrasterP.h \ raster.c \ draw.c \ color.c \ @@ -29,6 +28,7 @@ libwraster_la_SOURCES = \ gradient.c \ xpixmap.c \ convert.c \ + x86_specific.c \ context.c \ misc.c \ scale.c \ @@ -44,6 +44,16 @@ libwraster_la_SOURCES = \ gif.c +LTCOMPILE2=`echo $(LTCOMPILE) | sed -e s/-fomit-frame-pointer//` +COMPILE2=`echo $(COMPILE) | sed -e s/-fomit-frame-pointer//` + +# cant compile asm stuff with optimizations +x86_specific.lo: x86_specific.c + $(LTCOMPILE2) -O0 -c $< + +x86_specific.o: x86_specific.c + $(COMPILE2) -O0 -c $< + INCLUDES = $(DFLAGS) @HEADER_SEARCH_PATH@ diff --git a/wrlib/TODO b/wrlib/TODO index a000d6a5..5dd2e037 100644 --- a/wrlib/TODO +++ b/wrlib/TODO @@ -2,4 +2,4 @@ supports PseudoColor and TrueColor in some depths) - Gimp's xcf format? - add clipping code to RCombineArea() -- figure out what is producing those speckles when dithering is used. +- remake and optimize converters diff --git a/wrlib/context.c b/wrlib/context.c index 2bcc23f5..06ad5667 100644 --- a/wrlib/context.c +++ b/wrlib/context.c @@ -32,12 +32,6 @@ #include -#include "wrasterP.h" - -#ifdef HAVE_HERMES -#include -#endif - #include "StdCmap.h" #include "wraster.h" @@ -706,66 +700,17 @@ RCreateContext(Display *dpy, int screen_number, RContextAttributes *attribs) context->copy_gc = XCreateGC(dpy, context->drawable, GCFunction |GCGraphicsExposures, &gcv); -#ifdef HAVE_HERMES - context->hermes_data = malloc(sizeof(RHermesData)); - if (!context->hermes_data) { - RErrorCode = RERR_NOMEMORY; - free(context); - return NULL; - } - - Hermes_Init(); - - context->hermes_data->palette = Hermes_PaletteInstance(); - { - unsigned long flags = 0; - - if (context->attribs->render_mode == RDitheredRendering) { - flags |= HERMES_CONVERT_DITHER; - } - context->hermes_data->converter = Hermes_ConverterInstance(flags); - } -#endif - if (context->vclass == PseudoColor || context->vclass == StaticColor) { if (!setupPseudoColorColormap(context)) { free(context); return NULL; } -#ifdef HAVE_HERMES - { - int32 palette[256]; - int i; - - for (i = 0; i < context->ncolors; i++) { - palette[i] = ((context->colors[i].red >> 8) << 16) || - ((context->colors[i].green >> 8) << 8) || - ((context->colors[i].blue >> 8)); - } - - Hermes_PaletteSet(context->hermes_data->palette, palette); - } -#endif } else if (context->vclass == GrayScale || context->vclass == StaticGray) { context->colors = allocateGrayScale(context); if (!context->colors) { free(context); return NULL; } -#ifdef HAVE_HERMES - { - int32 palette[256]; - int i; - - for (i = 0; i < context->ncolors; i++) { - palette[i] = ((context->colors[i].red >> 8) << 16) || - ((context->colors[i].green >> 8) << 8) || - ((context->colors[i].blue >> 8)); - } - - Hermes_PaletteSet(context->hermes_data->palette, palette); - } -#endif } else if (context->vclass == TrueColor) { /* calc offsets to create a TrueColor pixel */ context->red_offset = count_offset(context->visual->red_mask); @@ -776,10 +721,7 @@ RCreateContext(Display *dpy, int screen_number, RContextAttributes *attribs) context->attribs->render_mode = RBestMatchRendering; } -#ifdef HAVE_HERMES - -#endif - + /* check avaiability of MIT-SHM */ #ifdef XSHM if (!(context->attribs->flags & RC_UseSharedMemory)) { diff --git a/wrlib/convert.c b/wrlib/convert.c index c53a252e..e626b5fd 100644 --- a/wrlib/convert.c +++ b/wrlib/convert.c @@ -40,7 +40,7 @@ #include "bench.h" #endif -#include "wrasterP.h" +#include "wraster.h" #ifdef XSHM extern Pixmap R_CreateXImageMappedPixmap(RContext *context, RXImage *ximage); @@ -48,6 +48,41 @@ extern Pixmap R_CreateXImageMappedPixmap(RContext *context, RXImage *ximage); #endif +#ifdef ASM_X86 +extern void x86_PseudoColor_32_to_8(unsigned char *image, + unsigned char *ximage, + char *err, char *nerr, + short *ctable, + int dr, int dg, int db, + unsigned long *pixels, + int cpc, + int width, int height, + int bytesPerPixel, + int line_offset); +#endif /* ASM_X86 */ + +#ifdef ASM_X86_MMX + +extern int x86_check_mmx(); + +extern void x86_mmx_TrueColor_32_to_16(unsigned char *image, + unsigned short *ximage, + short *err, short *nerr, + short *rtable, short *gtable, + short *btable, + int dr, int dg, int db, + unsigned int roffs, + unsigned int goffs, + unsigned int boffs, + int width, int height, + int line_offset); + + + +#endif /* ASM_X86_MMX */ + +#define NFREE(n) if (n) free(n) + #define HAS_ALPHA(I) ((I)->format == RRGBAFormat) @@ -153,7 +188,7 @@ convertTrueColor_generic(RXImage *ximg, RImage *image, int pixel; int rer, ger, ber; unsigned char *ptr = image->data; - int channels = (image->format == RRGBAFormat ? 4 : 3); + int channels = (HAS_ALPHA(image) ? 4 : 3); /* convert and dither the image to XImage */ for (y=0; yheight; y++) { @@ -272,7 +307,7 @@ image2TrueColor(RContext *ctx, RImage *image) unsigned short rmask, gmask, bmask; unsigned short roffs, goffs, boffs; unsigned short *rtable, *gtable, *btable; - int channels = (image->format == RRGBAFormat ? 4 : 3); + int channels = (HAS_ALPHA(image) ? 4 : 3); ximg = RCreateXImage(ctx, ctx->depth, image->width, image->height); if (!ximg) { @@ -340,17 +375,48 @@ image2TrueColor(RContext *ctx, RImage *image) #ifdef DEBUG puts("true color dither"); -#endif +#endif + +#ifdef ASM_X86_MMX + if (ctx->depth==16 && HAS_ALPHA(image) && x86_check_mmx()) { + short *err; + short *nerr; + + err = malloc(8*(image->width+3)); + nerr = malloc(8*(image->width+3)); + if (!err || !nerr) { + NFREE(err); + NFREE(nerr); + RErrorCode = RERR_NOMEMORY; + RDestroyXImage(ctx, ximg); + return NULL; + } + memset(err, 0, 8*(image->width+3)); + memset(nerr, 0, 8*(image->width+3)); + + x86_mmx_TrueColor_32_to_16(image->data, + (unsigned short*)ximg->image->data, + err+8, nerr+8, + rtable, gtable, btable, + dr, dg, db, + roffs, goffs, boffs, + image->width, image->height, + ximg->image->bytes_per_line - 2*image->width); + + free(err); + free(nerr); + } else +#endif /* ASM_X86_MMX */ { char *err; char *nerr; - int ch = (image->format == RRGBAFormat ? 4 : 3); + int ch = (HAS_ALPHA(image) ? 4 : 3); err = malloc(ch*(image->width+2)); nerr = malloc(ch*(image->width+2)); if (!err || !nerr) { - if (nerr) - free(nerr); + NFREE(err); + NFREE(nerr); RErrorCode = RERR_NOMEMORY; RDestroyXImage(ctx, ximg); return NULL; @@ -394,7 +460,7 @@ convertPseudoColor_to_8(RXImage *ximg, RImage *image, int rer, ger, ber; unsigned char *ptr = image->data; unsigned char *optr = ximg->image->data; - int channels = (image->format == RRGBAFormat ? 4 : 3); + int channels = (HAS_ALPHA(image) ? 4 : 3); int cpcpc = cpc*cpc; /* convert and dither the image to XImage */ @@ -469,7 +535,7 @@ image2PseudoColor(RContext *ctx, RImage *image) const unsigned short bmask = rmask; unsigned short *rtable, *gtable, *btable; const int cpccpc = cpc*cpc; - int channels = (image->format == RRGBAFormat ? 4 : 3); + int channels = (HAS_ALPHA(image) ? 4 : 3); ximg = RCreateXImage(ctx, ctx->depth, image->width, image->height); if (!ximg) { @@ -520,8 +586,8 @@ image2PseudoColor(RContext *ctx, RImage *image) err = malloc(4*(image->width+3)); nerr = malloc(4*(image->width+3)); if (!err || !nerr) { - if (nerr) - free(nerr); + NFREE(err); + NFREE(nerr); RErrorCode = RERR_NOMEMORY; RDestroyXImage(ctx, ximg); return NULL; @@ -529,9 +595,20 @@ image2PseudoColor(RContext *ctx, RImage *image) memset(err, 0, 4*(image->width+3)); memset(nerr, 0, 4*(image->width+3)); - convertPseudoColor_to_8(ximg, image, err+4, nerr+4, - rtable, gtable, btable, - dr, dg, db, ctx->pixels, cpc); +/*#ifdef ASM_X86*/ +#if 0 + x86_PseudoColor_32_to_8(image->data, ximg->image->data, + err+4, nerr+4, + rtable, + dr, dg, db, ctx->pixels, cpc, + image->width, image->height, + channels, + ximg->image->bytes_per_line - image->width); +#else + convertPseudoColor_to_8(ximg, image, err+4, nerr+4, + rtable, gtable, btable, + dr, dg, db, ctx->pixels, cpc); +#endif free(err); free(nerr); @@ -554,7 +631,7 @@ image2StandardPseudoColor(RContext *ctx, RImage *image) unsigned char *data; unsigned int *rtable, *gtable, *btable; unsigned int base_pixel = ctx->std_rgb_map->base_pixel; - int channels = (image->format == RRGBAFormat ? 4 : 3); + int channels = (HAS_ALPHA(image) ? 4 : 3); ximg = RCreateXImage(ctx, ctx->depth, image->width, image->height); @@ -606,10 +683,8 @@ image2StandardPseudoColor(RContext *ctx, RImage *image) err = (short*)malloc(3*(image->width+2)*sizeof(short)); nerr = (short*)malloc(3*(image->width+2)*sizeof(short)); if (!err || !nerr) { - if (err) - free(err); - if (nerr) - free(nerr); + NFREE(err); + NFREE(nerr); RErrorCode = RERR_NOMEMORY; RDestroyXImage(ctx, ximg); return NULL; @@ -702,7 +777,7 @@ image2GrayScale(RContext *ctx, RImage *image) unsigned short gmask; unsigned short *table; unsigned char *data; - int channels = (image->format == RRGBAFormat ? 4 : 3); + int channels = (HAS_ALPHA(image) ? 4 : 3); ximg = RCreateXImage(ctx, ctx->depth, image->width, image->height); @@ -755,8 +830,8 @@ image2GrayScale(RContext *ctx, RImage *image) gerr = (short*)malloc((image->width+2)*sizeof(short)); ngerr = (short*)malloc((image->width+2)*sizeof(short)); if (!gerr || !ngerr) { - if (ngerr) - free(ngerr); + NFREE(gerr); + NFREE(ngerr); RErrorCode = RERR_NOMEMORY; RDestroyXImage(ctx, ximg); return NULL; @@ -834,89 +909,6 @@ image2Bitmap(RContext *ctx, RImage *image, int threshold) } -#ifdef HAVE_HERMES - -static RXImage* -hermesConvert(RContext *context, RImage *image) -{ - HermesFormat source; - HermesFormat dest; - RXImage *ximage; - - - ximage = RCreateXImage(context, context->depth, - image->width, image->height); - if (!ximage) { - return NULL; - } - - /* The masks look weird for images with alpha. but they work this way. - * wth does hermes do internally? - */ - source.bits = (HAS_ALPHA(image) ? 32 : 24); - if (ximage->image->byte_order==LSBFirst) { - source.r = 0xff0000; - source.g = 0x00ff00; - source.b = 0x0000ff; - } else { - if (source.bits == 32) { - source.r = 0xff000000; - source.g = 0x00ff0000; - source.b = 0x0000ff00; - } else { - source.r = 0xff0000; - source.g = 0x00ff00; - source.b = 0x0000ff; - } - } - source.a = 0; /* Don't care about alpha */ - source.indexed = 0; - source.has_colorkey = 0; - - /* This is a hack and certainly looks weird, but it works :P - * it assumes though that green is inbetween red and blue (the mask) */ - if (ximage->image->byte_order==LSBFirst) { - dest.r = context->visual->blue_mask; - dest.g = context->visual->green_mask; - dest.b = context->visual->red_mask; - } else { - dest.r = context->visual->red_mask; - dest.g = context->visual->green_mask; - dest.b = context->visual->blue_mask; - } - dest.a = 0; - dest.bits = ximage->image->bits_per_pixel; - if (context->vclass == TrueColor) - dest.indexed = 0; - else - dest.indexed = 1; - dest.has_colorkey = 0; - - /*printf("source r=0x%x, g=0x%x, b=0x%x, a=0x%x, b=%d, i=%d, c=%d\n", - source.r, source.g, source.b, source.a, - source.bits, source.indexed, source.has_colorkey); - printf("dest r=0x%x, g=0x%x, b=0x%x, a=0x%x, b=%d, i=%d, c=%d\n", - dest.r, dest.g, dest.b, dest.a, - dest.bits, dest.indexed, dest.has_colorkey); - */ - - Hermes_ConverterRequest(context->hermes_data->converter, &source, &dest); - - Hermes_ConverterPalette(context->hermes_data->converter, - context->hermes_data->palette, 0); - - Hermes_ConverterCopy(context->hermes_data->converter, - image->data, 0, 0, image->width, image->height, - image->width * (image->format == RRGBFormat ? 3 : 4), - ximage->image->data, 0, 0, - image->width, image->height, - ximage->image->bytes_per_line); - - return ximage; -} -#endif /* HAVE_HERMES */ - - int RConvertImage(RContext *context, RImage *image, Pixmap *pixmap) { @@ -931,20 +923,17 @@ RConvertImage(RContext *context, RImage *image, Pixmap *pixmap) switch (context->vclass) { case TrueColor: -#ifdef HAVE_HERMES - if (context->attribs->render_mode == RBestMatchRendering) { - ximg = hermesConvert(context, image); - } else { - ximg = image2TrueColor(context, image); - } -#else /* !HAVE_HERMES */ +#ifdef BENCH + cycle_bench(1); +#endif ximg = image2TrueColor(context, image); +#ifdef BENCH + cycle_bench(0); #endif break; case PseudoColor: case StaticColor: - /* For StaticColor we can also use hermes, but it doesn't dither */ #ifdef BENCH cycle_bench(1); #endif @@ -970,7 +959,7 @@ RConvertImage(RContext *context, RImage *image, Pixmap *pixmap) *pixmap = XCreatePixmap(context->dpy, context->drawable, image->width, image->height, context->depth); - + #ifdef XSHM if (context->flags.use_shared_pixmap && ximg->is_shared) tmp = R_CreateXImageMappedPixmap(context, ximg); diff --git a/wrlib/raster.c b/wrlib/raster.c index a6340d1a..590d8ce8 100644 --- a/wrlib/raster.c +++ b/wrlib/raster.c @@ -95,21 +95,6 @@ RReleaseImage(RImage *image) } -/* Obsoleted function. Use RReleaseImage() instead. This was kept only to - * allow a smoother transition and to avoid breaking existing programs, but - * it will be removed in a future release. Right now is just an alias to - * RReleaseImage(). Do _NOT_ use RDestroyImage() anymore in your programs. - * Being an alias to RReleaseImage() this function no longer actually - * destroys the image, unless the image is no longer retained in some other - * place. - */ -void -RDestroyImage(RImage *image) -{ - RReleaseImage(image); -} - - RImage* RCloneImage(RImage *image) { diff --git a/wrlib/wraster.h b/wrlib/wraster.h index a5d8a53d..f683eb37 100644 --- a/wrlib/wraster.h +++ b/wrlib/wraster.h @@ -40,7 +40,7 @@ /* version of the header for the library: 0.21 */ -#define WRASTER_HEADER_VERSION 21 +#define WRASTER_HEADER_VERSION 22 #include @@ -87,9 +87,9 @@ extern "C" { /* std colormap usage/creation modes */ enum { RUseStdColormap, /* default. fallbacks to RIgnore.. if - there is none defined */ - RCreateStdColormap, - RIgnoreStdColormap + there is none defined */ + RCreateStdColormap, + RIgnoreStdColormap }; @@ -148,8 +148,6 @@ typedef struct RContext { unsigned int use_shared_pixmap:1; unsigned int optimize_for_speed:1; } flags; - - struct RHermesData *hermes_data; /* handle for Hermes stuff */ } RContext; @@ -327,16 +325,6 @@ RImage* RRetainImage(RImage *image); void RReleaseImage(RImage *image); -/* Obsoleted function. Use RReleaseImage() instead. This was kept only to - * allow a smoother transition and to avoid breaking existing programs, but - * it will be removed in a future release. Right now is just an alias to - * RReleaseImage(). Do _NOT_ use RDestroyImage() anymore in your programs. - * Being an alias to RReleaseImage() this function no longer actually - * destroys the image, unless the image is no longer retained in some other - * place. - */ -void RDestroyImage(RImage *image); - RImage *RGetImageFromXPMData(RContext *context, char **xpmData); /*