From de8397bc3d010bba24ec0c4d2e6249a769a86fc7 Mon Sep 17 00:00:00 2001 From: marha Date: Mon, 8 Oct 2012 08:09:46 +0200 Subject: pixman libxcb mesa xserver xkeyboard-config git update 8 oct 2012 xserver: 09f1e5b15b769e1122f0a8d7cae0820038992312 libxcb: 4ffe54f69049e6792a35a287fd9ff83abbd4fd8d mesa: 86de501f14f11f1e993c8703c0d69bdf1f6c7835 xkeyboard-config: 0a21bb5a28018902a6252fccb620d7dff7e67175 pixman: 3d81d89c292058522cce91338028d9b4c4a23c24 --- libxcb/NEWS | 13 + libxcb/configure.ac | 2 +- libxcb/src/Makefile.am | 3 +- libxcb/xcb-proto/NEWS | 6 + libxcb/xcb-proto/configure.ac | 2 +- mesalib/src/mapi/glapi/gen/gl_gentable.py | 2 +- mesalib/src/mesa/drivers/common/meta.c | 93 +- mesalib/src/mesa/drivers/dri/swrast/swrast.c | 2 +- mesalib/src/mesa/drivers/windows/gdi/wmesa.c | 2 +- mesalib/src/mesa/main/api_exec.c | 2 - mesalib/src/mesa/main/context.c | 13 +- mesalib/src/mesa/main/context.h | 6 +- mesalib/src/mesa/main/mtypes.h | 2 - mesalib/src/mesa/main/state.c | 3 +- mesalib/src/mesa/main/teximage.c | 16 +- mesalib/src/mesa/state_tracker/st_context.c | 2 +- mesalib/src/mesa/x86/gen_matypes.c | 1 - pixman/.gitignore | 4 - pixman/configure.ac | 6 - pixman/demos/radial-test.c | 2 +- pixman/pixman/Makefile.am | 8 +- pixman/pixman/Makefile.sources | 25 +- pixman/pixman/make-combine.pl | 86 - pixman/pixman/pixman-access.c | 750 ++++---- pixman/pixman/pixman-bits-image.c | 121 +- pixman/pixman/pixman-combine-float.c | 1003 ++++++++++ pixman/pixman/pixman-combine.c.template | 2437 ----------------------- pixman/pixman/pixman-combine.h.template | 226 --- pixman/pixman/pixman-combine32.c | 2460 ++++++++++++++++++++++++ pixman/pixman/pixman-combine32.h | 225 +++ pixman/pixman/pixman-conical-gradient.c | 3 +- pixman/pixman/pixman-general.c | 12 +- pixman/pixman/pixman-implementation.c | 4 +- pixman/pixman/pixman-linear-gradient.c | 3 +- pixman/pixman/pixman-noop.c | 6 +- pixman/pixman/pixman-private.h | 79 +- pixman/pixman/pixman-radial-gradient.c | 3 +- pixman/pixman/pixman-solid-fill.c | 25 +- pixman/pixman/pixman-utils.c | 198 +- pixman/test/Makefile.sources | 1 + pixman/test/blitters-test.c | 4 +- pixman/test/combiner-test.c | 151 ++ pixman/test/glyph-test.c | 7 +- pixman/test/gradient-crash-test.c | 2 +- pixman/test/pdf-op-test.c | 2 +- pixman/test/stress-test.c | 2 +- pixman/test/utils.c | 14 +- pixman/test/utils.h | 2 +- xorg-server/Xext/xf86bigfont.c | 4 +- xorg-server/Xi/exevents.c | 2 - xorg-server/Xi/xiselectev.c | 9 +- xorg-server/autogen.sh | 24 +- xorg-server/configure.ac | 7 +- xorg-server/dix/dispatch.c | 19 +- xorg-server/dix/events.c | 9 +- xorg-server/hw/kdrive/ephyr/ephyrdriext.c | 4 +- xorg-server/hw/kdrive/ephyr/ephyrglxext.c | 179 +- xorg-server/hw/kdrive/ephyr/ephyrhostglx.c | 121 +- xorg-server/hw/kdrive/ephyr/ephyrhostglx.h | 9 +- xorg-server/hw/kdrive/src/kinput.c | 2 +- xorg-server/hw/xfree86/common/xf86DGA.c | 2 +- xorg-server/hw/xfree86/common/xf86Module.h | 2 +- xorg-server/hw/xfree86/common/xf86Opt.h | 2 +- xorg-server/hw/xfree86/common/xf86Option.c | 2 +- xorg-server/hw/xfree86/common/xf86vmode.c | 6 +- xorg-server/hw/xfree86/dri/xf86dri.c | 4 +- xorg-server/hw/xfree86/dri2/dri2ext.c | 2 +- xorg-server/hw/xfree86/int10/generic.c | 3 +- xorg-server/hw/xquartz/applewm.c | 4 +- xorg-server/hw/xquartz/xpr/appledri.c | 6 +- xorg-server/hw/xwin/winwindowswm.c | 4 +- xorg-server/include/dixstruct.h | 37 +- xorg-server/include/os.h | 3 - xorg-server/include/windowstr.h | 4 +- xorg-server/mi/mipointer.c | 5 - xorg-server/os/access.c | 10 +- xorg-server/os/connection.c | 16 +- xorg-server/os/io.c | 22 +- xorg-server/os/osdep.h | 19 +- xorg-server/xkeyboard-config/rules/base.xml.in | 6 + xorg-server/xkeyboard-config/symbols/it | 43 + 81 files changed, 5024 insertions(+), 3608 deletions(-) delete mode 100644 pixman/pixman/make-combine.pl create mode 100644 pixman/pixman/pixman-combine-float.c delete mode 100644 pixman/pixman/pixman-combine.c.template delete mode 100644 pixman/pixman/pixman-combine.h.template create mode 100644 pixman/pixman/pixman-combine32.c create mode 100644 pixman/pixman/pixman-combine32.h create mode 100644 pixman/test/combiner-test.c diff --git a/libxcb/NEWS b/libxcb/NEWS index 66d6253ae..533d72b87 100644 --- a/libxcb/NEWS +++ b/libxcb/NEWS @@ -1,3 +1,16 @@ +Release 1.9 (2012-10-05) +======================== + +* Always include "config.h" at the start of all C source files. +* Add AC_USE_SYSTEM_EXTENSIONS to allow use of more system functionality +* Return connection failure if display string specifies non-existent screen +* c_client: Fix parallel-make issue creating 'man' directory +* xcb_connect: launchd: Don't fall back on tcp if $DISPLAY is a path to a launchd socket +* c_client.py: generate manpages +* Allow xcb_send_request with >MAX_IOV iovecs +* Add a .gitignore for src/man/ +* Fix a multi-thread deadlock + Release 1.8.1 (2012-03-09) ========================== - Fix a busy loop on BSD and Mac OS diff --git a/libxcb/configure.ac b/libxcb/configure.ac index 3f44b534d..736438305 100644 --- a/libxcb/configure.ac +++ b/libxcb/configure.ac @@ -4,7 +4,7 @@ # Initialize Autoconf AC_PREREQ(2.57) AC_INIT([libxcb], - 1.8.1, + 1.9, [xcb@lists.freedesktop.org]) AC_CONFIG_SRCDIR([xcb.pc.in]) # Set common system defines for POSIX extensions, such as _GNU_SOURCE diff --git a/libxcb/src/Makefile.am b/libxcb/src/Makefile.am index fed691447..6b5a2c3c4 100644 --- a/libxcb/src/Makefile.am +++ b/libxcb/src/Makefile.am @@ -227,7 +227,8 @@ noinst_HEADERS = xcbint.h STATIC_MANS = man/xcb-examples.3 man/xcb-requests.3 BUILT_MANS = man/xcb_*.3 -man_MANS = = $(STATIC_MANS) $(BUILT_MANS) +man_MANS = $(STATIC_MANS) $(BUILT_MANS) +EXTRA_DIST = $(STATIC_MANS) BUILT_SOURCES = $(EXTSOURCES) $(BUILT_MANS) CLEANFILES = $(EXTSOURCES) $(EXTHEADERS) $(BUILT_MANS) diff --git a/libxcb/xcb-proto/NEWS b/libxcb/xcb-proto/NEWS index 3e50762ab..ebe184532 100644 --- a/libxcb/xcb-proto/NEWS +++ b/libxcb/xcb-proto/NEWS @@ -1,3 +1,9 @@ +Release 1.8 (2012-10-05) +======================== +* dri2: Update to DRI2 1.4 +* XKB: Fix broken events +* xproto: add doc tags, xcbgen: handle doc tags + Release 1.7.1 (2012-03-23) ========================== * Add ge and xf86vidmode protocol descriptions diff --git a/libxcb/xcb-proto/configure.ac b/libxcb/xcb-proto/configure.ac index e20c9aa1e..ba6a90cd8 100644 --- a/libxcb/xcb-proto/configure.ac +++ b/libxcb/xcb-proto/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ(2.57) AC_INIT([XCB Proto], - 1.7.1, + 1.8, [xcb@lists.freedesktop.org]) AC_CONFIG_SRCDIR([xcb-proto.pc.in]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) diff --git a/mesalib/src/mapi/glapi/gen/gl_gentable.py b/mesalib/src/mapi/glapi/gen/gl_gentable.py index 5657e3277..edaabdbac 100644 --- a/mesalib/src/mapi/glapi/gen/gl_gentable.py +++ b/mesalib/src/mapi/glapi/gen/gl_gentable.py @@ -42,7 +42,7 @@ header = """/* GLXEXT is the define used in the xserver when the GLX extension i #endif #if (defined(GLXEXT) && defined(HAVE_BACKTRACE)) \\ - || (!defined(GLXEXT) && defined(DEBUG) && !defined(_WIN32_WCE)) + || (!defined(GLXEXT) && defined(DEBUG) && !defined(_WIN32_WCE) && !defined(__CYGWIN__)) #define USE_BACKTRACE #endif diff --git a/mesalib/src/mesa/drivers/common/meta.c b/mesalib/src/mesa/drivers/common/meta.c index d0bb5e0ae..24d8d485a 100644 --- a/mesalib/src/mesa/drivers/common/meta.c +++ b/mesalib/src/mesa/drivers/common/meta.c @@ -78,7 +78,6 @@ #include "main/glformats.h" #include "../glsl/ralloc.h" -static void *mem_ctx; /** Return offset in bytes of the field within a vertex struct */ #define OFFSET(FIELD) ((void *) offsetof(struct vertex, FIELD)) @@ -3048,7 +3047,6 @@ setup_glsl_generate_mipmap(struct gl_context *ctx, }; struct glsl_sampler *sampler; const char *vs_source; - const char *fs_template; static const char *vs_int_source = "#version 130\n" @@ -3071,49 +3069,8 @@ setup_glsl_generate_mipmap(struct gl_context *ctx, " out_color = texture(tex2d, texCoords.xy);\n" "}\n"; char *fs_source; - const char *extension_mode; GLuint vs, fs; - - if (ctx->Const.GLSLVersion < 130) { - vs_source = - "attribute vec2 position;\n" - "attribute vec3 textureCoords;\n" - "varying vec3 texCoords;\n" - "void main()\n" - "{\n" - " texCoords = textureCoords;\n" - " gl_Position = vec4(position, 0.0, 1.0);\n" - "}\n"; - fs_template = - "#extension GL_EXT_texture_array : %s\n" - "uniform %s texSampler;\n" - "varying vec3 texCoords;\n" - "void main()\n" - "{\n" - " gl_FragColor = %s(texSampler, %s);\n" - "}\n"; - } else { - vs_source = - "#version 130\n" - "in vec2 position;\n" - "in vec3 textureCoords;\n" - "out vec3 texCoords;\n" - "void main()\n" - "{\n" - " texCoords = textureCoords;\n" - " gl_Position = vec4(position, 0.0, 1.0);\n" - "}\n"; - fs_template = - "#version 130\n" - "uniform %s texSampler;\n" - "in vec3 texCoords;\n" - "out %s out_color;\n" - "\n" - "void main()\n" - "{\n" - " out_color = texture(texSampler, %s);\n" - "}\n"; - } + void *mem_ctx; /* Check if already initialized */ if (mipmap->ArrayObj == 0) { @@ -3143,18 +3100,50 @@ setup_glsl_generate_mipmap(struct gl_context *ctx, mem_ctx = ralloc_context(NULL); - if (ctx->Const.GLSLVersion < 130) { - extension_mode = ((target == GL_TEXTURE_1D_ARRAY) || - (target == GL_TEXTURE_2D_ARRAY)) ? - "require" : "disable"; + if (ctx->API == API_OPENGLES2 || ctx->Const.GLSLVersion < 130) { + vs_source = + "attribute vec2 position;\n" + "attribute vec3 textureCoords;\n" + "varying vec3 texCoords;\n" + "void main()\n" + "{\n" + " texCoords = textureCoords;\n" + " gl_Position = vec4(position, 0.0, 1.0);\n" + "}\n"; - fs_source = ralloc_asprintf(mem_ctx, fs_template, - extension_mode, sampler->type, + fs_source = ralloc_asprintf(mem_ctx, + "#extension GL_EXT_texture_array : enable\n" + "uniform %s texSampler;\n" + "varying vec3 texCoords;\n" + "void main()\n" + "{\n" + " gl_FragColor = %s(texSampler, %s);\n" + "}\n", + sampler->type, sampler->func, sampler->texcoords); } else { - fs_source = ralloc_asprintf(mem_ctx, fs_template, - sampler->type, "vec4", + vs_source = + "#version 130\n" + "in vec2 position;\n" + "in vec3 textureCoords;\n" + "out vec3 texCoords;\n" + "void main()\n" + "{\n" + " texCoords = textureCoords;\n" + " gl_Position = vec4(position, 0.0, 1.0);\n" + "}\n"; + fs_source = ralloc_asprintf(mem_ctx, + "#version 130\n" + "uniform %s texSampler;\n" + "in vec3 texCoords;\n" + "out vec4 out_color;\n" + "\n" + "void main()\n" + "{\n" + " out_color = texture(texSampler, %s);\n" + "}\n", + sampler->type, sampler->texcoords); } diff --git a/mesalib/src/mesa/drivers/dri/swrast/swrast.c b/mesalib/src/mesa/drivers/dri/swrast/swrast.c index 5ce1eb029..82dd7abf8 100644 --- a/mesalib/src/mesa/drivers/dri/swrast/swrast.c +++ b/mesalib/src/mesa/drivers/dri/swrast/swrast.c @@ -756,7 +756,7 @@ dri_create_context(gl_api api, mesaCtx = &ctx->Base; /* basic context setup */ - if (!_mesa_initialize_context(mesaCtx, api, visual, sharedCtx, &functions, (void *) cPriv)) { + if (!_mesa_initialize_context(mesaCtx, api, visual, sharedCtx, &functions)) { *error = __DRI_CTX_ERROR_NO_MEMORY; goto context_fail; } diff --git a/mesalib/src/mesa/drivers/windows/gdi/wmesa.c b/mesalib/src/mesa/drivers/windows/gdi/wmesa.c index c61020273..1580e5727 100644 --- a/mesalib/src/mesa/drivers/windows/gdi/wmesa.c +++ b/mesalib/src/mesa/drivers/windows/gdi/wmesa.c @@ -1085,7 +1085,7 @@ WMesaContext WMesaCreateContext(HDC hDC, /* initialize the Mesa context data */ ctx = &c->gl_ctx; _mesa_initialize_context(ctx, API_OPENGL, visual, - NULL, &functions, (void *)c); + NULL, &functions); /* visual no longer needed - it was copied by _mesa_initialize_context() */ _mesa_destroy_visual(visual); diff --git a/mesalib/src/mesa/main/api_exec.c b/mesalib/src/mesa/main/api_exec.c index ddf7c7fc1..f42da9438 100644 --- a/mesalib/src/mesa/main/api_exec.c +++ b/mesalib/src/mesa/main/api_exec.c @@ -335,8 +335,6 @@ _mesa_create_exec_table(struct gl_context *ctx) SET_NormalPointer(exec, _mesa_NormalPointer); SET_PrioritizeTextures(exec, _mesa_PrioritizeTextures); SET_TexCoordPointer(exec, _mesa_TexCoordPointer); - } - if (ctx->API != API_OPENGL_CORE) { SET_VertexPointer(exec, _mesa_VertexPointer); } #endif diff --git a/mesalib/src/mesa/main/context.c b/mesalib/src/mesa/main/context.c index c50504d19..d3fced946 100644 --- a/mesalib/src/mesa/main/context.c +++ b/mesalib/src/mesa/main/context.c @@ -897,20 +897,17 @@ _mesa_alloc_dispatch_table(int size) * etc with, or NULL * \param driverFunctions table of device driver functions for this context * to use - * \param driverContext pointer to driver-specific context data */ GLboolean _mesa_initialize_context(struct gl_context *ctx, gl_api api, const struct gl_config *visual, struct gl_context *share_list, - const struct dd_function_table *driverFunctions, - void *driverContext) + const struct dd_function_table *driverFunctions) { struct gl_shared_state *shared; int i; - /*ASSERT(driverContext);*/ assert(driverFunctions->NewTextureObject); assert(driverFunctions->FreeTextureImageBuffer); @@ -934,7 +931,6 @@ _mesa_initialize_context(struct gl_context *ctx, * textures. */ ctx->Driver = *driverFunctions; - ctx->DriverCtx = driverContext; if (share_list) { /* share state with another context */ @@ -1049,7 +1045,6 @@ _mesa_initialize_context(struct gl_context *ctx, * \param share_list another context to share display lists with or NULL * \param driverFunctions points to the dd_function_table into which the * driver has plugged in all its special functions. - * \param driverContext points to the device driver's private context state * * \return pointer to a new __struct gl_contextRec or NULL if error. */ @@ -1057,20 +1052,18 @@ struct gl_context * _mesa_create_context(gl_api api, const struct gl_config *visual, struct gl_context *share_list, - const struct dd_function_table *driverFunctions, - void *driverContext) + const struct dd_function_table *driverFunctions) { struct gl_context *ctx; ASSERT(visual); - /*ASSERT(driverContext);*/ ctx = calloc(1, sizeof(struct gl_context)); if (!ctx) return NULL; if (_mesa_initialize_context(ctx, api, visual, share_list, - driverFunctions, driverContext)) { + driverFunctions)) { return ctx; } else { diff --git a/mesalib/src/mesa/main/context.h b/mesalib/src/mesa/main/context.h index f0b4471b1..a5f770a6e 100644 --- a/mesalib/src/mesa/main/context.h +++ b/mesalib/src/mesa/main/context.h @@ -109,15 +109,13 @@ _mesa_initialize_context( struct gl_context *ctx, gl_api api, const struct gl_config *visual, struct gl_context *share_list, - const struct dd_function_table *driverFunctions, - void *driverContext ); + const struct dd_function_table *driverFunctions); extern struct gl_context * _mesa_create_context(gl_api api, const struct gl_config *visual, struct gl_context *share_list, - const struct dd_function_table *driverFunctions, - void *driverContext); + const struct dd_function_table *driverFunctions); extern void _mesa_free_context_data( struct gl_context *ctx ); diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index e790e18c4..40a802f52 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -3403,8 +3403,6 @@ struct gl_context */ struct dd_function_table Driver; - void *DriverCtx; /**< Points to device driver context/state */ - /** Core/Driver constants */ struct gl_constants Const; diff --git a/mesalib/src/mesa/main/state.c b/mesalib/src/mesa/main/state.c index 76946bd93..fb8b71cfe 100644 --- a/mesalib/src/mesa/main/state.c +++ b/mesalib/src/mesa/main/state.c @@ -627,7 +627,8 @@ _mesa_set_varying_vp_inputs( struct gl_context *ctx, * * It's okay to check the VP pointer here, because this is called after * _mesa_update_state in the vbo module. */ - if (ctx->VertexProgram._TnlProgram) { + if (ctx->VertexProgram._TnlProgram || + ctx->FragmentProgram._TexEnvProgram) { ctx->NewState |= _NEW_VARYING_VP_INPUTS; } /*printf("%s %x\n", __FUNCTION__, varying_inputs);*/ diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c index 019516f00..225081578 100644 --- a/mesalib/src/mesa/main/teximage.c +++ b/mesalib/src/mesa/main/teximage.c @@ -2871,13 +2871,15 @@ teximage(struct gl_context *ctx, GLboolean compressed, GLuint dims, border, internalFormat, texFormat); /* Give the texture to the driver. may be null. */ - if (compressed) { - ctx->Driver.CompressedTexImage(ctx, dims, texImage, - imageSize, pixels); - } - else { - ctx->Driver.TexImage(ctx, dims, texImage, format, - type, pixels, unpack); + if (width > 0 && height > 0 && depth > 0) { + if (compressed) { + ctx->Driver.CompressedTexImage(ctx, dims, texImage, + imageSize, pixels); + } + else { + ctx->Driver.TexImage(ctx, dims, texImage, format, + type, pixels, unpack); + } } check_gen_mipmap(ctx, target, texObj, level); diff --git a/mesalib/src/mesa/state_tracker/st_context.c b/mesalib/src/mesa/state_tracker/st_context.c index aa3534125..da361d887 100644 --- a/mesalib/src/mesa/state_tracker/st_context.c +++ b/mesalib/src/mesa/state_tracker/st_context.c @@ -225,7 +225,7 @@ struct st_context *st_create_context(gl_api api, struct pipe_context *pipe, memset(&funcs, 0, sizeof(funcs)); st_init_driver_functions(&funcs); - ctx = _mesa_create_context(api, visual, shareCtx, &funcs, NULL); + ctx = _mesa_create_context(api, visual, shareCtx, &funcs); if (!ctx) { return NULL; } diff --git a/mesalib/src/mesa/x86/gen_matypes.c b/mesalib/src/mesa/x86/gen_matypes.c index a1d8ee67d..61f181cd9 100644 --- a/mesalib/src/mesa/x86/gen_matypes.c +++ b/mesalib/src/mesa/x86/gen_matypes.c @@ -93,7 +93,6 @@ int main( int argc, char **argv ) */ OFFSET_HEADER( "struct gl_context" ); - OFFSET( "CTX_DRIVER_CTX ", struct gl_context, DriverCtx ); printf( "\n" ); OFFSET( "CTX_LIGHT_ENABLED ", struct gl_context, Light.Enabled ); OFFSET( "CTX_LIGHT_SHADE_MODEL ", struct gl_context, Light.ShadeModel ); diff --git a/pixman/.gitignore b/pixman/.gitignore index a4d9f99a7..2d089fc5e 100644 --- a/pixman/.gitignore +++ b/pixman/.gitignore @@ -39,10 +39,6 @@ demos/screen-test demos/srgb-test demos/trap-test demos/tri-test -pixman/pixman-combine32.c -pixman/pixman-combine32.h -pixman/pixman-combine64.c -pixman/pixman-combine64.h pixman/pixman-srgb.c pixman/pixman-version.h test/a1-trap-test diff --git a/pixman/configure.ac b/pixman/configure.ac index 5fda54700..c069b483c 100644 --- a/pixman/configure.ac +++ b/pixman/configure.ac @@ -182,12 +182,6 @@ AC_SUBST(LT_VERSION_INFO) PIXMAN_CHECK_CFLAG([-Wall]) PIXMAN_CHECK_CFLAG([-fno-strict-aliasing]) -AC_PATH_PROG(PERL, perl, no) -if test "x$PERL" = xno; then - AC_MSG_ERROR([Perl is required to build pixman.]) -fi -AC_SUBST(PERL) - dnl ========================================================================= dnl OpenMP for the test suite? dnl diff --git a/pixman/demos/radial-test.c b/pixman/demos/radial-test.c index 35e90d786..e64f3577f 100644 --- a/pixman/demos/radial-test.c +++ b/pixman/demos/radial-test.c @@ -133,7 +133,7 @@ main (int argc, char **argv) pixman_image_t *src_img, *dest_img; int i, j; - enable_fp_exceptions (); + enable_divbyzero_exceptions (); dest_img = pixman_image_create_bits (PIXMAN_a8r8g8b8, WIDTH, HEIGHT, diff --git a/pixman/pixman/Makefile.am b/pixman/pixman/Makefile.am index 270d65ec0..cbed0855a 100644 --- a/pixman/pixman/Makefile.am +++ b/pixman/pixman/Makefile.am @@ -12,16 +12,10 @@ noinst_LTLIBRARIES = EXTRA_DIST = \ Makefile.win32 \ - make-combine.pl \ - make-srgb.pl \ - pixman-combine.c.template \ - pixman-combine.h.template \ pixman-region.c \ solaris-hwcap.mapfile \ $(NULL) -DISTCLEANFILES = $(BUILT_SOURCES) - # mmx code if USE_X86_MMX noinst_LTLIBRARIES += libpixman-mmx.la @@ -127,5 +121,5 @@ libpixman_1_la_LDFLAGS += $(LS_LDFLAGS) libpixman_1_la_LIBADD += libpixman-loongson-mmi.la endif -.c.s : $(libpixmaninclude_HEADERS) $(BUILT_SOURCES) +.c.s : $(libpixmaninclude_HEADERS) $(CC) $(CFLAGS) $(ASM_CFLAGS_$(@:pixman-%.s=%)) $(ASM_CFLAGS_$(@:pixman-arm-%.s=arm_%)) -DHAVE_CONFIG_H -I$(srcdir) -I$(builddir) -I$(top_builddir) -S -o $@ $< diff --git a/pixman/pixman/Makefile.sources b/pixman/pixman/Makefile.sources index cf7040f33..5351fb03d 100644 --- a/pixman/pixman/Makefile.sources +++ b/pixman/pixman/Makefile.sources @@ -4,7 +4,7 @@ libpixman_sources = \ pixman-access-accessors.c \ pixman-bits-image.c \ pixman-combine32.c \ - pixman-combine64.c \ + pixman-combine-float.c \ pixman-conical-gradient.c \ pixman-x86.c \ pixman-mips.c \ @@ -25,7 +25,6 @@ libpixman_sources = \ pixman-region16.c \ pixman-region32.c \ pixman-solid-fill.c \ - pixman-srgb.c \ pixman-timer.c \ pixman-trap.c \ pixman-utils.c \ @@ -35,30 +34,8 @@ libpixman_headers = \ pixman.h \ pixman-accessor.h \ pixman-combine32.h \ - pixman-combine64.h \ pixman-compiler.h \ pixman-edge-imp.h \ pixman-inlines.h \ pixman-private.h \ $(NULL) - -BUILT_SOURCES = \ - pixman-combine32.c \ - pixman-combine32.h \ - pixman-combine64.c \ - pixman-combine64.h \ - pixman-srgb.c \ - $(NULL) - -pixman-srgb.c: make-srgb.pl - $(PERL) $< > $@ || ($(RM) $@; exit 1) - -pixman-combine32.c: pixman-combine.c.template make-combine.pl - $(PERL) $(lastword $+) 8 < $< > $@ || ($(RM) $@; exit 1) -pixman-combine32.h: pixman-combine.h.template make-combine.pl - $(PERL) $(lastword $+) 8 < $< > $@ || ($(RM) $@; exit 1) - -pixman-combine64.c: pixman-combine.c.template make-combine.pl - $(PERL) $(lastword $+) 16 < $< > $@ || ($(RM) $@; exit 1) -pixman-combine64.h: pixman-combine.h.template make-combine.pl - $(PERL) $(lastword $+) 16 < $< > $@ || ($(RM) $@; exit 1) diff --git a/pixman/pixman/make-combine.pl b/pixman/pixman/make-combine.pl deleted file mode 100644 index 417bdf085..000000000 --- a/pixman/pixman/make-combine.pl +++ /dev/null @@ -1,86 +0,0 @@ -$usage = "Usage: combine.pl { 8 | 16 } < pixman-combine.c.template"; - -$#ARGV == 0 or die $usage; - -# Get the component size. -$size = int($ARGV[0]); -$size == 8 or $size == 16 or die $usage; - -$pixel_size = $size * 4; -$half_pixel_size = $size * 2; - -sub mask { - my $str = shift; - my $suffix; - $suffix = "ULL" if $size > 8; - - return "0x" . $str . $suffix; -} - -# Generate mask strings. -$nibbles = $size / 4; -$mask = "f" x $nibbles; -$zero_mask = "0" x $nibbles; -$one_half = "8" . "0" x ($nibbles - 1); - -print "/* WARNING: This file is generated by combine.pl from combine.inc.\n"; -print " Please edit one of those files rather than this one. */\n"; -print "\n"; - -print "#line 1 \"pixman-combine.c.template\"\n"; - -$mask_ = mask($mask); -$one_half_ = mask($one_half); -$g_mask = mask($mask . $zero_mask); -$b_mask = mask($mask . $zero_mask x 2); -$a_mask = mask($mask . $zero_mask x 3); -$rb_mask = mask($mask . $zero_mask . $mask); -$ag_mask = mask($mask . $zero_mask . $mask . $zero_mask); -$rb_one_half = mask($one_half . $zero_mask . $one_half); -$rb_mask_plus_one = mask("1" . $zero_mask x 2 . "1" . $zero_mask); - -while () { - # Mask and 1/2 value for a single component. - s/#define COMPONENT_SIZE\b/$& $size/; - s/#define MASK\b/$& $mask_/; - s/#define ONE_HALF\b/$& $one_half_/; - - # Shifts and masks for green, blue, and alpha. - s/#define G_SHIFT\b/$& $size/; - s/#define R_SHIFT\b/$& $size * 2/; - s/#define A_SHIFT\b/$& $size * 3/; - s/#define G_MASK\b/$& $g_mask/; - s/#define R_MASK\b/$& $b_mask/; - s/#define A_MASK\b/$& $a_mask/; - - # Special values for dealing with red + blue at the same time. - s/#define RB_MASK\b/$& $rb_mask/; - s/#define AG_MASK\b/$& $ag_mask/; - s/#define RB_ONE_HALF\b/$& $rb_one_half/; - s/#define RB_MASK_PLUS_ONE\b/$& $rb_mask_plus_one/; - - # Add 32/64 suffix to combining function types. - s/\bCombineFunc\b/CombineFunc$pixel_size/; - s/\bFbComposeFunctions\b/FbComposeFunctions$pixel_size/; - s/combine_width/combine_$pixel_size/; - s/_pixman_setup_combiner_functions_width/_pixman_setup_combiner_functions_$pixel_size/; - s/UNc/UN$size/g; - s/ALPHA_c/ALPHA_$size/g; - s/RED_c/RED_$size/g; - s/GREEN_c/GREEN_$size/g; - s/BLUE_c/BLUE_$size/g; - - # Convert comp*_t values into the appropriate real types. - s/comp1_t/uint${size}_t/g; - s/comp2_t/uint${half_pixel_size}_t/g; - s/comp4_t/uint${pixel_size}_t/g; - - # Change the function table name for the 64-bit version. - s/pixman_composeFunctions/pixman_composeFunctions64/ if $size == 16; - - # Change the header for the 64-bit version - s/pixman-combine.h/pixman-combine64.h/ if $size == 16; - s/pixman-combine.h/pixman-combine32.h/ if $size == 8; - - print; -} diff --git a/pixman/pixman/pixman-access.c b/pixman/pixman/pixman-access.c index 9feafc49d..b5c8e4017 100644 --- a/pixman/pixman/pixman-access.c +++ b/pixman/pixman/pixman-access.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "pixman-accessor.h" #include "pixman-private.h" @@ -506,20 +507,122 @@ MAKE_ACCESSORS(a1); MAKE_ACCESSORS(g1); /********************************** Fetch ************************************/ +/* Table mapping sRGB-encoded 8 bit numbers to linearly encoded + * floating point numbers. We assume that single precision + * floating point follows the IEEE 754 format. + */ +static const uint32_t to_linear_u[256] = +{ + 0x00000000, 0x399f22b4, 0x3a1f22b4, 0x3a6eb40e, 0x3a9f22b4, 0x3ac6eb61, + 0x3aeeb40e, 0x3b0b3e5d, 0x3b1f22b4, 0x3b33070b, 0x3b46eb61, 0x3b5b518a, + 0x3b70f18a, 0x3b83e1c5, 0x3b8fe614, 0x3b9c87fb, 0x3ba9c9b5, 0x3bb7ad6d, + 0x3bc63547, 0x3bd5635f, 0x3be539bd, 0x3bf5ba70, 0x3c0373b5, 0x3c0c6152, + 0x3c15a703, 0x3c1f45bc, 0x3c293e68, 0x3c3391f4, 0x3c3e4149, 0x3c494d43, + 0x3c54b6c7, 0x3c607eb1, 0x3c6ca5df, 0x3c792d22, 0x3c830aa8, 0x3c89af9e, + 0x3c9085db, 0x3c978dc5, 0x3c9ec7c0, 0x3ca63432, 0x3cadd37d, 0x3cb5a601, + 0x3cbdac20, 0x3cc5e639, 0x3cce54ab, 0x3cd6f7d2, 0x3cdfd00e, 0x3ce8ddb9, + 0x3cf2212c, 0x3cfb9ac1, 0x3d02a569, 0x3d0798dc, 0x3d0ca7e4, 0x3d11d2ae, + 0x3d171963, 0x3d1c7c2e, 0x3d21fb3a, 0x3d2796af, 0x3d2d4ebb, 0x3d332380, + 0x3d39152b, 0x3d3f23e3, 0x3d454fd0, 0x3d4b991c, 0x3d51ffeb, 0x3d588466, + 0x3d5f26b7, 0x3d65e6fe, 0x3d6cc564, 0x3d73c210, 0x3d7add25, 0x3d810b65, + 0x3d84b793, 0x3d88732e, 0x3d8c3e48, 0x3d9018f4, 0x3d940343, 0x3d97fd48, + 0x3d9c0714, 0x3da020b9, 0x3da44a48, 0x3da883d6, 0x3daccd70, 0x3db12728, + 0x3db59110, 0x3dba0b38, 0x3dbe95b2, 0x3dc3308f, 0x3dc7dbe0, 0x3dcc97b4, + 0x3dd1641c, 0x3dd6412a, 0x3ddb2eec, 0x3de02d75, 0x3de53cd3, 0x3dea5d16, + 0x3def8e52, 0x3df4d091, 0x3dfa23e5, 0x3dff885e, 0x3e027f06, 0x3e05427f, + 0x3e080ea2, 0x3e0ae376, 0x3e0dc104, 0x3e10a752, 0x3e139669, 0x3e168e50, + 0x3e198f0e, 0x3e1c98ab, 0x3e1fab2e, 0x3e22c6a0, 0x3e25eb08, 0x3e29186a, + 0x3e2c4ed0, 0x3e2f8e42, 0x3e32d6c4, 0x3e362861, 0x3e39831e, 0x3e3ce702, + 0x3e405416, 0x3e43ca5e, 0x3e4749e4, 0x3e4ad2ae, 0x3e4e64c2, 0x3e520027, + 0x3e55a4e6, 0x3e595303, 0x3e5d0a8a, 0x3e60cb7c, 0x3e6495e0, 0x3e6869bf, + 0x3e6c4720, 0x3e702e08, 0x3e741e7f, 0x3e78188c, 0x3e7c1c34, 0x3e8014c0, + 0x3e822039, 0x3e84308b, 0x3e8645b8, 0x3e885fc3, 0x3e8a7eb0, 0x3e8ca281, + 0x3e8ecb3a, 0x3e90f8df, 0x3e932b72, 0x3e9562f6, 0x3e979f6f, 0x3e99e0e0, + 0x3e9c274e, 0x3e9e72b8, 0x3ea0c322, 0x3ea31892, 0x3ea57308, 0x3ea7d28a, + 0x3eaa3718, 0x3eaca0b7, 0x3eaf0f69, 0x3eb18332, 0x3eb3fc16, 0x3eb67a15, + 0x3eb8fd34, 0x3ebb8576, 0x3ebe12de, 0x3ec0a56e, 0x3ec33d2a, 0x3ec5da14, + 0x3ec87c30, 0x3ecb2380, 0x3ecdd008, 0x3ed081ca, 0x3ed338c9, 0x3ed5f508, + 0x3ed8b68a, 0x3edb7d52, 0x3ede4962, 0x3ee11abe, 0x3ee3f168, 0x3ee6cd64, + 0x3ee9aeb6, 0x3eec955d, 0x3eef815d, 0x3ef272ba, 0x3ef56976, 0x3ef86594, + 0x3efb6717, 0x3efe6e02, 0x3f00bd2b, 0x3f02460c, 0x3f03d1a5, 0x3f055ff8, + 0x3f06f105, 0x3f0884ce, 0x3f0a1b54, 0x3f0bb499, 0x3f0d509f, 0x3f0eef65, + 0x3f1090ef, 0x3f12353c, 0x3f13dc50, 0x3f15862a, 0x3f1732cc, 0x3f18e237, + 0x3f1a946d, 0x3f1c4970, 0x3f1e013f, 0x3f1fbbde, 0x3f21794c, 0x3f23398c, + 0x3f24fca0, 0x3f26c286, 0x3f288b42, 0x3f2a56d3, 0x3f2c253d, 0x3f2df680, + 0x3f2fca9d, 0x3f31a195, 0x3f337b6a, 0x3f35581e, 0x3f3737b1, 0x3f391a24, + 0x3f3aff7a, 0x3f3ce7b2, 0x3f3ed2d0, 0x3f40c0d2, 0x3f42b1bc, 0x3f44a58e, + 0x3f469c49, 0x3f4895ee, 0x3f4a9280, 0x3f4c91ff, 0x3f4e946c, 0x3f5099c8, + 0x3f52a216, 0x3f54ad55, 0x3f56bb88, 0x3f58ccae, 0x3f5ae0cb, 0x3f5cf7de, + 0x3f5f11ec, 0x3f612ef0, 0x3f634eef, 0x3f6571ea, 0x3f6797e1, 0x3f69c0d6, + 0x3f6beccb, 0x3f6e1bc0, 0x3f704db6, 0x3f7282af, 0x3f74baac, 0x3f76f5ae, + 0x3f7933b6, 0x3f7b74c6, 0x3f7db8de, 0x3f800000 +}; + +static const float * const to_linear = (const float *)to_linear_u; + +static uint8_t +to_srgb (float f) +{ + uint8_t low = 0; + uint8_t high = 255; + + while (high - low > 1) + { + uint8_t mid = (low + high) / 2; + + if (to_linear[mid] > f) + high = mid; + else + low = mid; + } + + if (to_linear[high] - f < f - to_linear[low]) + return high; + else + return low; +} -/* Expects a uint64_t buffer */ static void -fetch_scanline_a2r10g10b10 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * b, - const uint32_t *mask) +fetch_scanline_a8r8g8b8_sRGB_float (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * b, + const uint32_t *mask) { const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; const uint32_t *pixel = bits + x; const uint32_t *end = pixel + width; - uint64_t *buffer = (uint64_t *)b; + argb_t *buffer = (argb_t *)b; + + while (pixel < end) + { + uint32_t p = READ (image, pixel++); + argb_t *argb = buffer; + + argb->a = pixman_unorm_to_float ((p >> 24) & 0xff, 8); + + argb->r = to_linear [(p >> 16) & 0xff]; + argb->g = to_linear [(p >> 8) & 0xff]; + argb->b = to_linear [(p >> 0) & 0xff]; + + buffer++; + } +} + +/* Expects a float buffer */ +static void +fetch_scanline_a2r10g10b10_float (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * b, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint32_t *pixel = bits + x; + const uint32_t *end = pixel + width; + argb_t *buffer = (argb_t *)b; while (pixel < end) { @@ -529,62 +632,59 @@ fetch_scanline_a2r10g10b10 (pixman_image_t *image, uint64_t g = (p >> 10) & 0x3ff; uint64_t b = p & 0x3ff; - r = r << 6 | r >> 4; - g = g << 6 | g >> 4; - b = b << 6 | b >> 4; - - a <<= 14; - a |= a >> 2; - a |= a >> 4; - a |= a >> 8; + buffer->a = pixman_unorm_to_float (a, 2); + buffer->r = pixman_unorm_to_float (r, 10); + buffer->g = pixman_unorm_to_float (g, 10); + buffer->b = pixman_unorm_to_float (b, 10); - *buffer++ = a << 48 | r << 32 | g << 16 | b; + buffer++; } } -/* Expects a uint64_t buffer */ +/* Expects a float buffer */ static void -fetch_scanline_x2r10g10b10 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * b, - const uint32_t *mask) +fetch_scanline_x2r10g10b10_float (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * b, + const uint32_t *mask) { const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; const uint32_t *pixel = (uint32_t *)bits + x; const uint32_t *end = pixel + width; - uint64_t *buffer = (uint64_t *)b; - + argb_t *buffer = (argb_t *)b; + while (pixel < end) { uint32_t p = READ (image, pixel++); uint64_t r = (p >> 20) & 0x3ff; uint64_t g = (p >> 10) & 0x3ff; uint64_t b = p & 0x3ff; - - r = r << 6 | r >> 4; - g = g << 6 | g >> 4; - b = b << 6 | b >> 4; - - *buffer++ = 0xffffULL << 48 | r << 32 | g << 16 | b; + + buffer->a = 1.0; + buffer->r = pixman_unorm_to_float (r, 10); + buffer->g = pixman_unorm_to_float (g, 10); + buffer->b = pixman_unorm_to_float (b, 10); + + buffer++; } } -/* Expects a uint64_t buffer */ +/* Expects a float buffer */ static void -fetch_scanline_a2b10g10r10 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * b, - const uint32_t *mask) +fetch_scanline_a2b10g10r10_float (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * b, + const uint32_t *mask) { const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; const uint32_t *pixel = bits + x; const uint32_t *end = pixel + width; - uint64_t *buffer = (uint64_t *)b; - + argb_t *buffer = (argb_t *)b; + while (pixel < end) { uint32_t p = READ (image, pixel++); @@ -592,46 +692,43 @@ fetch_scanline_a2b10g10r10 (pixman_image_t *image, uint64_t b = (p >> 20) & 0x3ff; uint64_t g = (p >> 10) & 0x3ff; uint64_t r = p & 0x3ff; - - r = r << 6 | r >> 4; - g = g << 6 | g >> 4; - b = b << 6 | b >> 4; - - a <<= 14; - a |= a >> 2; - a |= a >> 4; - a |= a >> 8; - *buffer++ = a << 48 | r << 32 | g << 16 | b; + buffer->a = pixman_unorm_to_float (a, 2); + buffer->r = pixman_unorm_to_float (r, 10); + buffer->g = pixman_unorm_to_float (g, 10); + buffer->b = pixman_unorm_to_float (b, 10); + + buffer++; } } -/* Expects a uint64_t buffer */ +/* Expects a float buffer */ static void -fetch_scanline_x2b10g10r10 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * b, - const uint32_t *mask) +fetch_scanline_x2b10g10r10_float (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * b, + const uint32_t *mask) { const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; const uint32_t *pixel = (uint32_t *)bits + x; const uint32_t *end = pixel + width; - uint64_t *buffer = (uint64_t *)b; - + argb_t *buffer = (argb_t *)b; + while (pixel < end) { uint32_t p = READ (image, pixel++); uint64_t b = (p >> 20) & 0x3ff; uint64_t g = (p >> 10) & 0x3ff; uint64_t r = p & 0x3ff; - - r = r << 6 | r >> 4; - g = g << 6 | g >> 4; - b = b << 6 | b >> 4; - - *buffer++ = 0xffffULL << 48 | r << 32 | g << 16 | b; + + buffer->a = 1.0; + buffer->r = pixman_unorm_to_float (r, 10); + buffer->g = pixman_unorm_to_float (g, 10); + buffer->b = pixman_unorm_to_float (b, 10); + + buffer++; } } @@ -708,55 +805,51 @@ fetch_scanline_yv12 (pixman_image_t *image, /**************************** Pixel wise fetching *****************************/ -/* Despite the type, expects a uint64_t buffer */ -static uint64_t -fetch_pixel_a2r10g10b10 (bits_image_t *image, - int offset, - int line) +static argb_t +fetch_pixel_x2r10g10b10_float (bits_image_t *image, + int offset, + int line) { uint32_t *bits = image->bits + line * image->rowstride; uint32_t p = READ (image, bits + offset); - uint64_t a = p >> 30; uint64_t r = (p >> 20) & 0x3ff; uint64_t g = (p >> 10) & 0x3ff; uint64_t b = p & 0x3ff; + argb_t argb; - r = r << 6 | r >> 4; - g = g << 6 | g >> 4; - b = b << 6 | b >> 4; + argb.a = 1.0; + argb.r = pixman_unorm_to_float (r, 10); + argb.g = pixman_unorm_to_float (g, 10); + argb.b = pixman_unorm_to_float (b, 10); - a <<= 14; - a |= a >> 2; - a |= a >> 4; - a |= a >> 8; - - return a << 48 | r << 32 | g << 16 | b; + return argb; } -/* Despite the type, this function expects a uint64_t buffer */ -static uint64_t -fetch_pixel_x2r10g10b10 (bits_image_t *image, - int offset, - int line) +static argb_t +fetch_pixel_a2r10g10b10_float (bits_image_t *image, + int offset, + int line) { uint32_t *bits = image->bits + line * image->rowstride; uint32_t p = READ (image, bits + offset); + uint64_t a = p >> 30; uint64_t r = (p >> 20) & 0x3ff; uint64_t g = (p >> 10) & 0x3ff; uint64_t b = p & 0x3ff; - - r = r << 6 | r >> 4; - g = g << 6 | g >> 4; - b = b << 6 | b >> 4; - - return 0xffffULL << 48 | r << 32 | g << 16 | b; + argb_t argb; + + argb.a = pixman_unorm_to_float (a, 2); + argb.r = pixman_unorm_to_float (r, 10); + argb.g = pixman_unorm_to_float (g, 10); + argb.b = pixman_unorm_to_float (b, 10); + + return argb; } -/* Despite the type, expects a uint64_t buffer */ -static uint64_t -fetch_pixel_a2b10g10r10 (bits_image_t *image, - int offset, - int line) +static argb_t +fetch_pixel_a2b10g10r10_float (bits_image_t *image, + int offset, + int line) { uint32_t *bits = image->bits + line * image->rowstride; uint32_t p = READ (image, bits + offset); @@ -764,36 +857,52 @@ fetch_pixel_a2b10g10r10 (bits_image_t *image, uint64_t b = (p >> 20) & 0x3ff; uint64_t g = (p >> 10) & 0x3ff; uint64_t r = p & 0x3ff; - - r = r << 6 | r >> 4; - g = g << 6 | g >> 4; - b = b << 6 | b >> 4; - - a <<= 14; - a |= a >> 2; - a |= a >> 4; - a |= a >> 8; - - return a << 48 | r << 32 | g << 16 | b; + argb_t argb; + + argb.a = pixman_unorm_to_float (a, 2); + argb.r = pixman_unorm_to_float (r, 10); + argb.g = pixman_unorm_to_float (g, 10); + argb.b = pixman_unorm_to_float (b, 10); + + return argb; } -/* Despite the type, this function expects a uint64_t buffer */ -static uint64_t -fetch_pixel_x2b10g10r10 (bits_image_t *image, - int offset, - int line) +static argb_t +fetch_pixel_x2b10g10r10_float (bits_image_t *image, + int offset, + int line) { uint32_t *bits = image->bits + line * image->rowstride; uint32_t p = READ (image, bits + offset); uint64_t b = (p >> 20) & 0x3ff; uint64_t g = (p >> 10) & 0x3ff; uint64_t r = p & 0x3ff; - - r = r << 6 | r >> 4; - g = g << 6 | g >> 4; - b = b << 6 | b >> 4; - - return 0xffffULL << 48 | r << 32 | g << 16 | b; + argb_t argb; + + argb.a = 1.0; + argb.r = pixman_unorm_to_float (r, 10); + argb.g = pixman_unorm_to_float (g, 10); + argb.b = pixman_unorm_to_float (b, 10); + + return argb; +} + +static argb_t +fetch_pixel_a8r8g8b8_sRGB_float (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t p = READ (image, bits + offset); + argb_t argb; + + argb.a = pixman_unorm_to_float ((p >> 24) & 0xff, 8); + + argb.r = to_linear [(p >> 16) & 0xff]; + argb.g = to_linear [(p >> 8) & 0xff]; + argb.b = to_linear [(p >> 0) & 0xff]; + + return argb; } static uint32_t @@ -854,178 +963,174 @@ fetch_pixel_yv12 (bits_image_t *image, /*********************************** Store ************************************/ static void -store_scanline_a2r10g10b10 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *v) +store_scanline_a2r10g10b10_float (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *v) { uint32_t *bits = image->bits + image->rowstride * y; uint32_t *pixel = bits + x; - uint64_t *values = (uint64_t *)v; + argb_t *values = (argb_t *)v; int i; - + for (i = 0; i < width; ++i) { + uint16_t a, r, g, b; + + a = pixman_float_to_unorm (values[i].a, 2); + r = pixman_float_to_unorm (values[i].r, 10); + g = pixman_float_to_unorm (values[i].g, 10); + b = pixman_float_to_unorm (values[i].b, 10); + WRITE (image, pixel++, - ((values[i] >> 32) & 0xc0000000) | - ((values[i] >> 18) & 0x3ff00000) | - ((values[i] >> 12) & 0xffc00) | - ((values[i] >> 6) & 0x3ff)); + (a << 30) | (r << 20) | (g << 10) | b); } } static void -store_scanline_x2r10g10b10 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *v) +store_scanline_x2r10g10b10_float (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *v) { uint32_t *bits = image->bits + image->rowstride * y; - uint64_t *values = (uint64_t *)v; uint32_t *pixel = bits + x; + argb_t *values = (argb_t *)v; int i; - + for (i = 0; i < width; ++i) { + uint16_t r, g, b; + + r = pixman_float_to_unorm (values[i].r, 10); + g = pixman_float_to_unorm (values[i].g, 10); + b = pixman_float_to_unorm (values[i].b, 10); + WRITE (image, pixel++, - ((values[i] >> 18) & 0x3ff00000) | - ((values[i] >> 12) & 0xffc00) | - ((values[i] >> 6) & 0x3ff)); + (r << 20) | (g << 10) | b); } } static void -store_scanline_a2b10g10r10 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *v) +store_scanline_a2b10g10r10_float (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *v) { uint32_t *bits = image->bits + image->rowstride * y; uint32_t *pixel = bits + x; - uint64_t *values = (uint64_t *)v; + argb_t *values = (argb_t *)v; int i; - + for (i = 0; i < width; ++i) { + uint16_t a, r, g, b; + + a = pixman_float_to_unorm (values[i].a, 2); + r = pixman_float_to_unorm (values[i].r, 10); + g = pixman_float_to_unorm (values[i].g, 10); + b = pixman_float_to_unorm (values[i].b, 10); + WRITE (image, pixel++, - ((values[i] >> 32) & 0xc0000000) | - ((values[i] >> 38) & 0x3ff) | - ((values[i] >> 12) & 0xffc00) | - ((values[i] << 14) & 0x3ff00000)); + (a << 30) | (b << 20) | (g << 10) | r); } } static void -store_scanline_x2b10g10r10 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *v) +store_scanline_x2b10g10r10_float (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *v) { uint32_t *bits = image->bits + image->rowstride * y; - uint64_t *values = (uint64_t *)v; uint32_t *pixel = bits + x; + argb_t *values = (argb_t *)v; int i; - + + for (i = 0; i < width; ++i) + { + uint16_t r, g, b; + + r = pixman_float_to_unorm (values[i].r, 10); + g = pixman_float_to_unorm (values[i].g, 10); + b = pixman_float_to_unorm (values[i].b, 10); + + WRITE (image, pixel++, + (b << 20) | (g << 10) | r); + } +} + +static void +store_scanline_a8r8g8b8_sRGB_float (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *v) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint32_t *pixel = bits + x; + argb_t *values = (argb_t *)v; + int i; + for (i = 0; i < width; ++i) { + uint8_t a, r, g, b; + + a = pixman_float_to_unorm (values[i].a, 8); + r = to_srgb (values[i].r); + g = to_srgb (values[i].g); + b = to_srgb (values[i].b); + WRITE (image, pixel++, - ((values[i] >> 38) & 0x3ff) | - ((values[i] >> 12) & 0xffc00) | - ((values[i] << 14) & 0x3ff00000)); + (a << 24) | (r << 16) | (g << 8) | b); } } /* - * Contracts a 64bpp image to 32bpp and then stores it using a regular 32-bit - * store proc. Despite the type, this function expects a uint64_t buffer. + * Contracts a floating point image to 32bpp and then stores it using a + * regular 32-bit store proc. Despite the type, this function expects an + * argb_t buffer. */ static void -store_scanline_generic_64 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) +store_scanline_generic_float (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) { uint32_t *argb8_pixels; - + assert (image->common.type == BITS); - + argb8_pixels = pixman_malloc_ab (width, sizeof(uint32_t)); if (!argb8_pixels) return; - + /* Contract the scanline. We could do this in place if values weren't * const. */ - pixman_contract (argb8_pixels, (uint64_t *)values, width); - + pixman_contract_from_float (argb8_pixels, (argb_t *)values, width); + image->store_scanline_32 (image, x, y, width, argb8_pixels); - + free (argb8_pixels); } -/* Despite the type, this function expects both buffer - * and mask to be uint64_t - */ static void -fetch_scanline_generic_64 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) +fetch_scanline_generic_float (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) { - pixman_format_code_t format; - - /* Fetch the pixels into the first half of buffer and then expand them in - * place. - */ image->bits.fetch_scanline_32 (image, x, y, width, buffer, NULL); - format = image->bits.format; - if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR || - PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_GRAY) - { - /* Indexed formats are mapped to a8r8g8b8 with full - * precision, so when expanding we shouldn't correct - * for the width of the channels - */ - - format = PIXMAN_a8r8g8b8; - } - - pixman_expand ((uint64_t *)buffer, buffer, format, width); -} - -/* Despite the type, this function expects a uint64_t *buffer */ -static uint64_t -fetch_pixel_generic_64 (bits_image_t *image, - int offset, - int line) -{ - uint32_t pixel32 = image->fetch_pixel_32 (image, offset, line); - uint64_t result; - pixman_format_code_t format; - - format = image->format; - if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR || - PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_GRAY) - { - /* Indexed formats are mapped to a8r8g8b8 with full - * precision, so when expanding we shouldn't correct - * for the width of the channels - */ - - format = PIXMAN_a8r8g8b8; - } - - pixman_expand ((uint64_t *)&result, &pixel32, format, 1); - - return result; + pixman_expand_to_float ((argb_t *)buffer, buffer, image->bits.format, width); } /* The 32_sRGB paths should be deleted after narrow processing @@ -1046,35 +1151,20 @@ fetch_scanline_a8r8g8b8_32_sRGB (pixman_image_t *image, while (pixel < end) { - tmp = READ (image, pixel++); - *buffer++ = (tmp >> 24) << 24 - | (srgb_to_linear[(tmp >> 16) & 0xff] >> 8) << 16 - | (srgb_to_linear[(tmp >> 8) & 0xff] >> 8) << 8 - | (srgb_to_linear[(tmp >> 0) & 0xff] >> 8) << 0; - } -} + uint8_t a, r, g, b; -static void -fetch_scanline_a8r8g8b8_64_sRGB (pixman_image_t *image, - int x, - int y, - int width, - uint32_t *b, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - const uint32_t *pixel = (uint32_t *)bits + x; - const uint32_t *end = pixel + width; - uint64_t *buffer = (uint64_t *)b; - uint32_t tmp; - - while (pixel < end) - { tmp = READ (image, pixel++); - *buffer++ = (uint64_t) ((tmp >> 24) * 257) << 48 - | (uint64_t) srgb_to_linear[(tmp >> 16) & 0xff] << 32 - | (uint64_t) srgb_to_linear[(tmp >> 8) & 0xff] << 16 - | (uint64_t) srgb_to_linear[(tmp >> 0) & 0xff] << 0; + + a = (tmp >> 24) & 0xff; + r = (tmp >> 16) & 0xff; + g = (tmp >> 8) & 0xff; + b = (tmp >> 0) & 0xff; + + r = to_linear[r] * 255.0f + 0.5f; + g = to_linear[g] * 255.0f + 0.5f; + b = to_linear[b] * 255.0f + 0.5f; + + *buffer++ = (a << 24) | (r << 16) | (g << 8) | (b << 0); } } @@ -1085,23 +1175,18 @@ fetch_pixel_a8r8g8b8_32_sRGB (bits_image_t *image, { uint32_t *bits = image->bits + line * image->rowstride; uint32_t tmp = READ (image, bits + offset); - return (tmp >> 24) << 24 - | (srgb_to_linear[(tmp >> 16) & 0xff] >> 8) << 16 - | (srgb_to_linear[(tmp >> 8) & 0xff] >> 8) << 8 - | (srgb_to_linear[(tmp >> 0) & 0xff] >> 8) << 0; -} + uint8_t a, r, g, b; -static uint64_t -fetch_pixel_a8r8g8b8_64_sRGB (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint32_t tmp = READ (image, bits + offset); - return (uint64_t) ((tmp >> 24) * 257) << 48 - | (uint64_t) srgb_to_linear[(tmp >> 16) & 0xff] << 32 - | (uint64_t) srgb_to_linear[(tmp >> 8) & 0xff] << 16 - | (uint64_t) srgb_to_linear[(tmp >> 0) & 0xff] << 0; + a = (tmp >> 24) & 0xff; + r = (tmp >> 16) & 0xff; + g = (tmp >> 8) & 0xff; + b = (tmp >> 0) & 0xff; + + r = to_linear[r] * 255.0f + 0.5f; + g = to_linear[g] * 255.0f + 0.5f; + b = to_linear[b] * 255.0f + 0.5f; + + return (a << 24) | (r << 16) | (g << 8) | (b << 0); } static void @@ -1119,37 +1204,34 @@ store_scanline_a8r8g8b8_32_sRGB (bits_image_t *image, for (i = 0; i < width; ++i) { + uint8_t a, r, g, b; + tmp = values[i]; - WRITE (image, pixel++, - ((uint32_t) (tmp >> 24 ) << 24) - | (linear_to_srgb[(tmp >> 16 << 4) & 0xfff] << 16) - | (linear_to_srgb[(tmp >> 8 << 4) & 0xfff] << 8) - | (linear_to_srgb[(tmp >> 0 << 4) & 0xfff] << 0)); + + a = (tmp >> 24) & 0xff; + r = (tmp >> 16) & 0xff; + g = (tmp >> 8) & 0xff; + b = (tmp >> 0) & 0xff; + + r = to_srgb (r * (1/255.0f)); + g = to_srgb (g * (1/255.0f)); + b = to_srgb (b * (1/255.0f)); + + WRITE (image, pixel++, a | (r << 16) | (g << 8) | (b << 0)); } } -static void -store_scanline_a8r8g8b8_64_sRGB (bits_image_t *image, - int x, - int y, - int width, - const uint32_t *v) +static argb_t +fetch_pixel_generic_float (bits_image_t *image, + int offset, + int line) { - uint32_t *bits = image->bits + image->rowstride * y; - uint64_t *values = (uint64_t *)v; - uint32_t *pixel = bits + x; - uint64_t tmp; - int i; - - for (i = 0; i < width; ++i) - { - tmp = values[i]; - WRITE (image, pixel++, - ((uint32_t) (tmp >> 56) << 24) - | (linear_to_srgb[(tmp >> 36) & 0xfff] << 16) - | (linear_to_srgb[(tmp >> 20) & 0xfff] << 8) - | (linear_to_srgb[(tmp >> 4) & 0xfff] << 0)); - } + uint32_t pixel32 = image->fetch_pixel_32 (image, offset, line); + argb_t f; + + pixman_expand_to_float (&f, &pixel32, image->format, 1); + + return f; } /* @@ -1163,10 +1245,10 @@ fetch_pixel_generic_lossy_32 (bits_image_t *image, int offset, int line) { - uint64_t pixel64 = image->fetch_pixel_64 (image, offset, line); + argb_t pixel64 = image->fetch_pixel_float (image, offset, line); uint32_t result; - pixman_contract (&result, &pixel64, 1); + pixman_contract_from_float (&result, &pixel64, 1); return result; } @@ -1175,20 +1257,22 @@ typedef struct { pixman_format_code_t format; fetch_scanline_t fetch_scanline_32; - fetch_scanline_t fetch_scanline_64; + fetch_scanline_t fetch_scanline_float; fetch_pixel_32_t fetch_pixel_32; - fetch_pixel_64_t fetch_pixel_64; + fetch_pixel_float_t fetch_pixel_float; store_scanline_t store_scanline_32; - store_scanline_t store_scanline_64; + store_scanline_t store_scanline_float; } format_info_t; #define FORMAT_INFO(format) \ { \ PIXMAN_ ## format, \ fetch_scanline_ ## format, \ - fetch_scanline_generic_64, \ - fetch_pixel_ ## format, fetch_pixel_generic_64, \ - store_scanline_ ## format, store_scanline_generic_64 \ + fetch_scanline_generic_float, \ + fetch_pixel_ ## format, \ + fetch_pixel_generic_float, \ + store_scanline_ ## format, \ + store_scanline_generic_float \ } static const format_info_t accessors[] = @@ -1206,10 +1290,10 @@ static const format_info_t accessors[] = /* sRGB formats */ { PIXMAN_a8r8g8b8_sRGB, - fetch_scanline_a8r8g8b8_32_sRGB, - fetch_scanline_a8r8g8b8_64_sRGB, - fetch_pixel_a8r8g8b8_32_sRGB, fetch_pixel_a8r8g8b8_64_sRGB, - store_scanline_a8r8g8b8_32_sRGB, store_scanline_a8r8g8b8_64_sRGB }, + fetch_scanline_a8r8g8b8_32_sRGB, fetch_scanline_a8r8g8b8_sRGB_float, + fetch_pixel_a8r8g8b8_32_sRGB, fetch_pixel_a8r8g8b8_sRGB_float, + store_scanline_a8r8g8b8_32_sRGB, store_scanline_a8r8g8b8_sRGB_float, + }, /* 24bpp formats */ FORMAT_INFO (r8g8b8), @@ -1269,34 +1353,34 @@ static const format_info_t accessors[] = /* Wide formats */ { PIXMAN_a2r10g10b10, - NULL, fetch_scanline_a2r10g10b10, - fetch_pixel_generic_lossy_32, fetch_pixel_a2r10g10b10, - NULL, store_scanline_a2r10g10b10 }, - + NULL, fetch_scanline_a2r10g10b10_float, + fetch_pixel_generic_lossy_32, fetch_pixel_a2r10g10b10_float, + NULL, store_scanline_a2r10g10b10_float }, + { PIXMAN_x2r10g10b10, - NULL, fetch_scanline_x2r10g10b10, - fetch_pixel_generic_lossy_32, fetch_pixel_x2r10g10b10, - NULL, store_scanline_x2r10g10b10 }, - + NULL, fetch_scanline_x2r10g10b10_float, + fetch_pixel_generic_lossy_32, fetch_pixel_x2r10g10b10_float, + NULL, store_scanline_x2r10g10b10_float }, + { PIXMAN_a2b10g10r10, - NULL, fetch_scanline_a2b10g10r10, - fetch_pixel_generic_lossy_32, fetch_pixel_a2b10g10r10, - NULL, store_scanline_a2b10g10r10 }, - + NULL, fetch_scanline_a2b10g10r10_float, + fetch_pixel_generic_lossy_32, fetch_pixel_a2b10g10r10_float, + NULL, store_scanline_a2b10g10r10_float }, + { PIXMAN_x2b10g10r10, - NULL, fetch_scanline_x2b10g10r10, - fetch_pixel_generic_lossy_32, fetch_pixel_x2b10g10r10, - NULL, store_scanline_x2b10g10r10 }, - + NULL, fetch_scanline_x2b10g10r10_float, + fetch_pixel_generic_lossy_32, fetch_pixel_x2b10g10r10_float, + NULL, store_scanline_x2b10g10r10_float }, + /* YUV formats */ { PIXMAN_yuy2, - fetch_scanline_yuy2, fetch_scanline_generic_64, - fetch_pixel_yuy2, fetch_pixel_generic_64, + fetch_scanline_yuy2, fetch_scanline_generic_float, + fetch_pixel_yuy2, fetch_pixel_generic_float, NULL, NULL }, - + { PIXMAN_yv12, - fetch_scanline_yv12, fetch_scanline_generic_64, - fetch_pixel_yv12, fetch_pixel_generic_64, + fetch_scanline_yv12, fetch_scanline_generic_float, + fetch_pixel_yv12, fetch_pixel_generic_float, NULL, NULL }, { PIXMAN_null }, @@ -1312,11 +1396,11 @@ setup_accessors (bits_image_t *image) if (info->format == image->format) { image->fetch_scanline_32 = info->fetch_scanline_32; - image->fetch_scanline_64 = info->fetch_scanline_64; + image->fetch_scanline_float = info->fetch_scanline_float; image->fetch_pixel_32 = info->fetch_pixel_32; - image->fetch_pixel_64 = info->fetch_pixel_64; + image->fetch_pixel_float = info->fetch_pixel_float; image->store_scanline_32 = info->store_scanline_32; - image->store_scanline_64 = info->store_scanline_64; + image->store_scanline_float = info->store_scanline_float; return; } diff --git a/pixman/pixman/pixman-bits-image.c b/pixman/pixman/pixman-bits-image.c index c69e1518b..029093ddc 100644 --- a/pixman/pixman/pixman-bits-image.c +++ b/pixman/pixman/pixman-bits-image.c @@ -36,43 +36,18 @@ #include "pixman-combine32.h" #include "pixman-inlines.h" -/* - * By default, just evaluate the image at 32bpp and expand. Individual image - * types can plug in a better scanline getter if they want to. For example - * we could produce smoother gradients by evaluating them at higher color - * depth, but that's a project for the future. - */ static uint32_t * -_pixman_image_get_scanline_generic_64 (pixman_iter_t * iter, - const uint32_t *mask) +_pixman_image_get_scanline_generic_float (pixman_iter_t * iter, + const uint32_t *mask) { - int width = iter->width; - uint32_t * buffer = iter->buffer; - pixman_iter_get_scanline_t fetch_32 = iter->data; - uint32_t *mask8 = NULL; - - /* Contract the mask image, if one exists, so that the 32-bit fetch - * function can use it. - */ - if (mask) - { - mask8 = pixman_malloc_ab (width, sizeof(uint32_t)); - if (!mask8) - return buffer; - - pixman_contract (mask8, (uint64_t *)mask, width); - } - - /* Fetch the source image into the first half of buffer. */ - fetch_32 (iter, mask8); + uint32_t *buffer = iter->buffer; - /* Expand from 32bpp to 64bpp in place. */ - pixman_expand ((uint64_t *)buffer, buffer, PIXMAN_a8r8g8b8, width); + fetch_32 (iter, NULL); - free (mask8); + pixman_expand_to_float ((argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width); - return buffer; + return iter->buffer; } /* Fetch functions */ @@ -965,17 +940,17 @@ replicate_pixel_32 (bits_image_t * bits, } static void -replicate_pixel_64 (bits_image_t * bits, - int x, - int y, - int width, - uint32_t * b) +replicate_pixel_float (bits_image_t * bits, + int x, + int y, + int width, + uint32_t * b) { - uint64_t color; - uint64_t *buffer = (uint64_t *)b; - uint64_t *end; + argb_t color; + argb_t *buffer = (argb_t *)b; + argb_t *end; - color = bits->fetch_pixel_64 (bits, x, y); + color = bits->fetch_pixel_float (bits, x, y); end = buffer + width; while (buffer < end) @@ -994,7 +969,7 @@ bits_image_fetch_untransformed_repeat_none (bits_image_t *image, if (y < 0 || y >= image->height) { - memset (buffer, 0, width * (wide? 8 : 4)); + memset (buffer, 0, width * (wide? sizeof (argb_t) : 4)); return; } @@ -1002,10 +977,10 @@ bits_image_fetch_untransformed_repeat_none (bits_image_t *image, { w = MIN (width, -x); - memset (buffer, 0, w * (wide ? 8 : 4)); + memset (buffer, 0, w * (wide ? sizeof (argb_t) : 4)); width -= w; - buffer += w * (wide? 2 : 1); + buffer += w * (wide? 4 : 1); x += w; } @@ -1014,16 +989,16 @@ bits_image_fetch_untransformed_repeat_none (bits_image_t *image, w = MIN (width, image->width - x); if (wide) - image->fetch_scanline_64 ((pixman_image_t *)image, x, y, w, buffer, NULL); + image->fetch_scanline_float ((pixman_image_t *)image, x, y, w, buffer, NULL); else image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL); width -= w; - buffer += w * (wide? 2 : 1); + buffer += w * (wide? 4 : 1); x += w; } - memset (buffer, 0, width * (wide ? 8 : 4)); + memset (buffer, 0, width * (wide ? sizeof (argb_t) : 4)); } static void @@ -1045,7 +1020,7 @@ bits_image_fetch_untransformed_repeat_normal (bits_image_t *image, if (image->width == 1) { if (wide) - replicate_pixel_64 (image, 0, y, width, buffer); + replicate_pixel_float (image, 0, y, width, buffer); else replicate_pixel_32 (image, 0, y, width, buffer); @@ -1062,11 +1037,11 @@ bits_image_fetch_untransformed_repeat_normal (bits_image_t *image, w = MIN (width, image->width - x); if (wide) - image->fetch_scanline_64 ((pixman_image_t *)image, x, y, w, buffer, NULL); + image->fetch_scanline_float ((pixman_image_t *)image, x, y, w, buffer, NULL); else image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL); - buffer += w * (wide? 2 : 1); + buffer += w * (wide? 4 : 1); x += w; width -= w; } @@ -1098,9 +1073,8 @@ bits_image_fetch_untransformed_32 (pixman_iter_t * iter, } static uint32_t * -bits_image_fetch_untransformed_64 (pixman_iter_t * iter, - const uint32_t *mask) - +bits_image_fetch_untransformed_float (pixman_iter_t * iter, + const uint32_t *mask) { pixman_image_t *image = iter->image; int x = iter->x; @@ -1128,7 +1102,7 @@ typedef struct pixman_format_code_t format; uint32_t flags; pixman_iter_get_scanline_t get_scanline_32; - pixman_iter_get_scanline_t get_scanline_64; + pixman_iter_get_scanline_t get_scanline_float; } fetcher_info_t; static const fetcher_info_t fetcher_info[] = @@ -1140,7 +1114,7 @@ static const fetcher_info_t fetcher_info[] = FAST_PATH_NO_PAD_REPEAT | FAST_PATH_NO_REFLECT_REPEAT), bits_image_fetch_untransformed_32, - bits_image_fetch_untransformed_64 + bits_image_fetch_untransformed_float }, #define FAST_BILINEAR_FLAGS \ @@ -1156,13 +1130,13 @@ static const fetcher_info_t fetcher_info[] = { PIXMAN_a8r8g8b8, FAST_BILINEAR_FLAGS, bits_image_fetch_bilinear_no_repeat_8888, - _pixman_image_get_scanline_generic_64 + _pixman_image_get_scanline_generic_float }, { PIXMAN_x8r8g8b8, FAST_BILINEAR_FLAGS, bits_image_fetch_bilinear_no_repeat_8888, - _pixman_image_get_scanline_generic_64 + _pixman_image_get_scanline_generic_float }, #define GENERAL_BILINEAR_FLAGS \ @@ -1183,14 +1157,14 @@ static const fetcher_info_t fetcher_info[] = { PIXMAN_ ## format, \ GENERAL_BILINEAR_FLAGS | FAST_PATH_ ## repeat ## _REPEAT, \ bits_image_fetch_bilinear_affine_ ## name, \ - _pixman_image_get_scanline_generic_64 \ + _pixman_image_get_scanline_generic_float \ }, #define NEAREST_AFFINE_FAST_PATH(name, format, repeat) \ { PIXMAN_ ## format, \ GENERAL_NEAREST_FLAGS | FAST_PATH_ ## repeat ## _REPEAT, \ - bits_image_fetch_nearest_affine_ ## name, \ - _pixman_image_get_scanline_generic_64 \ + bits_image_fetch_nearest_affine_ ## name, \ + _pixman_image_get_scanline_generic_float \ }, #define AFFINE_FAST_PATHS(name, format, repeat) \ @@ -1218,11 +1192,15 @@ static const fetcher_info_t fetcher_info[] = { PIXMAN_any, (FAST_PATH_NO_ALPHA_MAP | FAST_PATH_HAS_TRANSFORM | FAST_PATH_AFFINE_TRANSFORM), bits_image_fetch_affine_no_alpha, - _pixman_image_get_scanline_generic_64 + _pixman_image_get_scanline_generic_float }, /* General */ - { PIXMAN_any, 0, bits_image_fetch_general, _pixman_image_get_scanline_generic_64 }, + { PIXMAN_any, + 0, + bits_image_fetch_general, + _pixman_image_get_scanline_generic_float + }, { PIXMAN_null }, }; @@ -1252,7 +1230,7 @@ _pixman_bits_image_src_iter_init (pixman_image_t *image, pixman_iter_t *iter) else { iter->data = info->get_scanline_32; - iter->get_scanline = info->get_scanline_64; + iter->get_scanline = info->get_scanline_float; } return; } @@ -1307,30 +1285,27 @@ dest_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask) int x = iter->x; int y = iter->y; int width = iter->width; - uint64_t * buffer = (uint64_t *)iter->buffer; + argb_t * buffer = (argb_t *)iter->buffer; - image->fetch_scanline_64 ( + image->fetch_scanline_float ( (pixman_image_t *)image, x, y, width, (uint32_t *)buffer, mask); if (image->common.alpha_map) { - uint64_t *alpha; + argb_t *alpha; - if ((alpha = malloc (width * sizeof (uint64_t)))) + if ((alpha = malloc (width * sizeof (argb_t)))) { int i; x -= image->common.alpha_origin_x; y -= image->common.alpha_origin_y; - image->common.alpha_map->fetch_scanline_64 ( + image->common.alpha_map->fetch_scanline_float ( (pixman_image_t *)image->common.alpha_map, x, y, width, (uint32_t *)alpha, mask); for (i = 0; i < width; ++i) - { - buffer[i] &= ~0xffff000000000000ULL; - buffer[i] |= (alpha[i] & 0xffff000000000000ULL); - } + buffer[i].a = alpha[i].a; free (alpha); } @@ -1371,14 +1346,14 @@ dest_write_back_wide (pixman_iter_t *iter) int width = iter->width; const uint32_t *buffer = iter->buffer; - image->store_scanline_64 (image, x, y, width, buffer); + image->store_scanline_float (image, x, y, width, buffer); if (image->common.alpha_map) { x -= image->common.alpha_origin_x; y -= image->common.alpha_origin_y; - image->common.alpha_map->store_scanline_64 ( + image->common.alpha_map->store_scanline_float ( image->common.alpha_map, x, y, width, buffer); } diff --git a/pixman/pixman/pixman-combine-float.c b/pixman/pixman/pixman-combine-float.c new file mode 100644 index 000000000..7bf5b5ae7 --- /dev/null +++ b/pixman/pixman/pixman-combine-float.c @@ -0,0 +1,1003 @@ +/* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */ +/* + * Copyright © 2010, 2012 Soren Sandmann Pedersen + * Copyright © 2010, 2012 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Author: Soren Sandmann Pedersen (sandmann@cs.au.dk) + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "pixman-private.h" + +typedef float (* combine_channel_t) (float sa, float s, float da, float d); + +static force_inline void +combine_inner (pixman_bool_t component, + float *dest, const float *src, const float *mask, int n_pixels, + combine_channel_t combine_a, combine_channel_t combine_c) +{ + int i; + + if (!mask) + { + for (i = 0; i < 4 * n_pixels; i += 4) + { + float sa = src[i + 0]; + float sr = src[i + 1]; + float sg = src[i + 2]; + float sb = src[i + 3]; + + float da = dest[i + 0]; + float dr = dest[i + 1]; + float dg = dest[i + 2]; + float db = dest[i + 3]; + + dest[i + 0] = combine_a (sa, sa, da, da); + dest[i + 1] = combine_c (sa, sr, da, dr); + dest[i + 2] = combine_c (sa, sg, da, dg); + dest[i + 3] = combine_c (sa, sb, da, db); + } + } + else + { + for (i = 0; i < 4 * n_pixels; i += 4) + { + float sa, sr, sg, sb; + float ma, mr, mg, mb; + float da, dr, dg, db; + + sa = src[i + 0]; + sr = src[i + 1]; + sg = src[i + 2]; + sb = src[i + 3]; + + if (component) + { + ma = mask[i + 0]; + mr = mask[i + 1]; + mg = mask[i + 2]; + mb = mask[i + 3]; + + sr *= mr; + sg *= mg; + sb *= mb; + + ma *= sa; + mr *= sa; + mg *= sa; + mb *= sa; + + sa = ma; + } + else + { + ma = mask[i + 0]; + + sa *= ma; + sr *= ma; + sg *= ma; + sb *= ma; + + ma = mr = mg = mb = sa; + } + + da = dest[i + 0]; + dr = dest[i + 1]; + dg = dest[i + 2]; + db = dest[i + 3]; + + dest[i + 0] = combine_a (ma, sa, da, da); + dest[i + 1] = combine_c (mr, sr, da, dr); + dest[i + 2] = combine_c (mg, sg, da, dg); + dest[i + 3] = combine_c (mb, sb, da, db); + } + } +} + +#define MAKE_COMBINER(name, component, combine_a, combine_c) \ + static void \ + combine_ ## name ## _float (pixman_implementation_t *imp, \ + pixman_op_t op, \ + float *dest, \ + const float *src, \ + const float *mask, \ + int n_pixels) \ + { \ + combine_inner (component, dest, src, mask, n_pixels, \ + combine_a, combine_c); \ + } + +#define MAKE_COMBINERS(name, combine_a, combine_c) \ + MAKE_COMBINER(name ## _ca, TRUE, combine_a, combine_c) \ + MAKE_COMBINER(name ## _u, FALSE, combine_a, combine_c) + + +/* + * Porter/Duff operators + */ +typedef enum +{ + ZERO, + ONE, + SRC_ALPHA, + DEST_ALPHA, + INV_SA, + INV_DA, + SA_OVER_DA, + DA_OVER_SA, + INV_SA_OVER_DA, + INV_DA_OVER_SA, + ONE_MINUS_SA_OVER_DA, + ONE_MINUS_DA_OVER_SA, + ONE_MINUS_INV_DA_OVER_SA, + ONE_MINUS_INV_SA_OVER_DA +} combine_factor_t; + +#define CLAMP(f) \ + (((f) < 0)? 0 : (((f) > 1.0) ? 1.0 : (f))) + +static force_inline float +get_factor (combine_factor_t factor, float sa, float da) +{ + float f = -1; + + switch (factor) + { + case ZERO: + f = 0.0f; + break; + + case ONE: + f = 1.0f; + break; + + case SRC_ALPHA: + f = sa; + break; + + case DEST_ALPHA: + f = da; + break; + + case INV_SA: + f = 1 - sa; + break; + + case INV_DA: + f = 1 - da; + break; + + case SA_OVER_DA: + if (da == 0.0f) + f = 1.0f; + else + f = CLAMP (sa / da); + break; + + case DA_OVER_SA: + if (sa == 0.0f) + f = 1.0f; + else + f = CLAMP (da / sa); + break; + + case INV_SA_OVER_DA: + if (da == 0.0f) + f = 1.0f; + else + f = CLAMP ((1.0f - sa) / da); + break; + + case INV_DA_OVER_SA: + if (sa == 0.0f) + f = 1.0f; + else + f = CLAMP ((1.0f - da) / sa); + break; + + case ONE_MINUS_SA_OVER_DA: + if (da == 0.0f) + f = 0.0f; + else + f = CLAMP (1.0f - sa / da); + break; + + case ONE_MINUS_DA_OVER_SA: + if (sa == 0.0f) + f = 0.0f; + else + f = CLAMP (1.0f - da / sa); + break; + + case ONE_MINUS_INV_DA_OVER_SA: + if (sa == 0.0f) + f = 0.0f; + else + f = CLAMP (1.0f - (1.0f - da) / sa); + break; + + case ONE_MINUS_INV_SA_OVER_DA: + if (da == 0.0f) + f = 0.0f; + else + f = CLAMP (1.0f - (1.0f - sa) / da); + break; + } + + return f; +} + +#define MAKE_PD_COMBINERS(name, a, b) \ + static float force_inline \ + pd_combine_ ## name (float sa, float s, float da, float d) \ + { \ + const float fa = get_factor (a, sa, da); \ + const float fb = get_factor (b, sa, da); \ + \ + return MIN (1.0f, s * fa + d * fb); \ + } \ + \ + MAKE_COMBINERS(name, pd_combine_ ## name, pd_combine_ ## name) + +MAKE_PD_COMBINERS (clear, ZERO, ZERO) +MAKE_PD_COMBINERS (src, ONE, ZERO) +MAKE_PD_COMBINERS (dst, ZERO, ONE) +MAKE_PD_COMBINERS (over, ONE, INV_SA) +MAKE_PD_COMBINERS (over_reverse, INV_DA, ONE) +MAKE_PD_COMBINERS (in, DEST_ALPHA, ZERO) +MAKE_PD_COMBINERS (in_reverse, ZERO, SRC_ALPHA) +MAKE_PD_COMBINERS (out, INV_DA, ZERO) +MAKE_PD_COMBINERS (out_reverse, ZERO, INV_SA) +MAKE_PD_COMBINERS (atop, DEST_ALPHA, INV_SA) +MAKE_PD_COMBINERS (atop_reverse, INV_DA, SRC_ALPHA) +MAKE_PD_COMBINERS (xor, INV_DA, INV_SA) +MAKE_PD_COMBINERS (add, ONE, ONE) + +MAKE_PD_COMBINERS (saturate, INV_DA_OVER_SA, ONE) + +MAKE_PD_COMBINERS (disjoint_clear, ZERO, ZERO) +MAKE_PD_COMBINERS (disjoint_src, ONE, ZERO) +MAKE_PD_COMBINERS (disjoint_dst, ZERO, ONE) +MAKE_PD_COMBINERS (disjoint_over, ONE, INV_SA_OVER_DA) +MAKE_PD_COMBINERS (disjoint_over_reverse, INV_DA_OVER_SA, ONE) +MAKE_PD_COMBINERS (disjoint_in, ONE_MINUS_INV_DA_OVER_SA, ZERO) +MAKE_PD_COMBINERS (disjoint_in_reverse, ZERO, ONE_MINUS_INV_SA_OVER_DA) +MAKE_PD_COMBINERS (disjoint_out, INV_DA_OVER_SA, ZERO) +MAKE_PD_COMBINERS (disjoint_out_reverse, ZERO, INV_SA_OVER_DA) +MAKE_PD_COMBINERS (disjoint_atop, ONE_MINUS_INV_DA_OVER_SA, INV_SA_OVER_DA) +MAKE_PD_COMBINERS (disjoint_atop_reverse, INV_DA_OVER_SA, ONE_MINUS_INV_SA_OVER_DA) +MAKE_PD_COMBINERS (disjoint_xor, INV_DA_OVER_SA, INV_SA_OVER_DA) + +MAKE_PD_COMBINERS (conjoint_clear, ZERO, ZERO) +MAKE_PD_COMBINERS (conjoint_src, ONE, ZERO) +MAKE_PD_COMBINERS (conjoint_dst, ZERO, ONE) +MAKE_PD_COMBINERS (conjoint_over, ONE, ONE_MINUS_SA_OVER_DA) +MAKE_PD_COMBINERS (conjoint_over_reverse, ONE_MINUS_DA_OVER_SA, ONE) +MAKE_PD_COMBINERS (conjoint_in, DA_OVER_SA, ZERO) +MAKE_PD_COMBINERS (conjoint_in_reverse, ZERO, SA_OVER_DA) +MAKE_PD_COMBINERS (conjoint_out, ONE_MINUS_DA_OVER_SA, ZERO) +MAKE_PD_COMBINERS (conjoint_out_reverse, ZERO, ONE_MINUS_SA_OVER_DA) +MAKE_PD_COMBINERS (conjoint_atop, DA_OVER_SA, ONE_MINUS_SA_OVER_DA) +MAKE_PD_COMBINERS (conjoint_atop_reverse, ONE_MINUS_DA_OVER_SA, SA_OVER_DA) +MAKE_PD_COMBINERS (conjoint_xor, ONE_MINUS_DA_OVER_SA, ONE_MINUS_SA_OVER_DA) + +/* + * PDF blend modes: + * + * The following blend modes have been taken from the PDF ISO 32000 + * specification, which at this point in time is available from + * http://www.adobe.com/devnet/acrobat/pdfs/PDF32000_2008.pdf + * The relevant chapters are 11.3.5 and 11.3.6. + * The formula for computing the final pixel color given in 11.3.6 is: + * αr × Cr = (1 – αs) × αb × Cb + (1 – αb) × αs × Cs + αb × αs × B(Cb, Cs) + * with B() being the blend function. + * Note that OVER is a special case of this operation, using B(Cb, Cs) = Cs + * + * These blend modes should match the SVG filter draft specification, as + * it has been designed to mirror ISO 32000. Note that at the current point + * no released draft exists that shows this, as the formulas have not been + * updated yet after the release of ISO 32000. + * + * The default implementation here uses the PDF_SEPARABLE_BLEND_MODE and + * PDF_NON_SEPARABLE_BLEND_MODE macros, which take the blend function as an + * argument. Note that this implementation operates on premultiplied colors, + * while the PDF specification does not. Therefore the code uses the formula + * ar.Cra = (1 – as) . Dca + (1 – ad) . Sca + B(Dca, ad, Sca, as) + */ + +#define MAKE_SEPARABLE_PDF_COMBINERS(name) \ + static force_inline float \ + combine_ ## name ## _a (float sa, float s, float da, float d) \ + { \ + return da + sa - da * sa; \ + } \ + \ + static force_inline float \ + combine_ ## name ## _c (float sa, float s, float da, float d) \ + { \ + float f = (1 - sa) * d + (1 - da) * s; \ + \ + return f + blend_ ## name (sa, s, da, d); \ + } \ + \ + MAKE_COMBINERS (name, combine_ ## name ## _a, combine_ ## name ## _c) + +static force_inline float +blend_multiply (float sa, float s, float da, float d) +{ + return d * s; +} + +static force_inline float +blend_screen (float sa, float s, float da, float d) +{ + return d * sa + s * da - s * d; +} + +static force_inline float +blend_overlay (float sa, float s, float da, float d) +{ + if (2 * d < da) + return 2 * s * d; + else + return sa * da - 2 * (da - d) * (sa - s); +} + +static force_inline float +blend_darken (float sa, float s, float da, float d) +{ + s = s * da; + d = d * sa; + + if (s > d) + return d; + else + return s; +} + +static force_inline float +blend_lighten (float sa, float s, float da, float d) +{ + s = s * da; + d = d * sa; + + if (s > d) + return s; + else + return d; +} + +static force_inline float +blend_color_dodge (float sa, float s, float da, float d) +{ + if (d == 0.0f) + return 0.0f; + else if (d * sa >= sa * da - s * da) + return sa * da; + else if (sa - s == 0.0f) + return sa * da; + else + return sa * sa * d / (sa - s); +} + +static force_inline float +blend_color_burn (float sa, float s, float da, float d) +{ + if (d >= da) + return sa * da; + else if (sa * (da - d) >= s * da) + return 0.0f; + else if (s == 0.0f) + return 0.0f; + else + return sa * (da - sa * (da - d) / s); +} + +static force_inline float +blend_hard_light (float sa, float s, float da, float d) +{ + if (2 * s < sa) + return 2 * s * d; + else + return sa * da - 2 * (da - d) * (sa - s); +} + +static force_inline float +blend_soft_light (float sa, float s, float da, float d) +{ + if (2 * s < sa) + { + if (da == 0.0f) + return d * sa; + else + return d * sa - d * (da - d) * (sa - 2 * s) / da; + } + else + { + if (da == 0.0f) + { + return 0.0f; + } + else + { + if (4 * d <= da) + return d * sa + (2 * s - sa) * d * ((16 * d / da - 12) * d / da + 3); + else + return d * sa + (sqrtf (d * da) - d) * (2 * s - sa); + } + } +} + +static force_inline float +blend_difference (float sa, float s, float da, float d) +{ + float dsa = d * sa; + float sda = s * da; + + if (sda < dsa) + return dsa - sda; + else + return sda - dsa; +} + +static force_inline float +blend_exclusion (float sa, float s, float da, float d) +{ + return s * da + d * sa - 2 * d * s; +} + +MAKE_SEPARABLE_PDF_COMBINERS (multiply) +MAKE_SEPARABLE_PDF_COMBINERS (screen) +MAKE_SEPARABLE_PDF_COMBINERS (overlay) +MAKE_SEPARABLE_PDF_COMBINERS (darken) +MAKE_SEPARABLE_PDF_COMBINERS (lighten) +MAKE_SEPARABLE_PDF_COMBINERS (color_dodge) +MAKE_SEPARABLE_PDF_COMBINERS (color_burn) +MAKE_SEPARABLE_PDF_COMBINERS (hard_light) +MAKE_SEPARABLE_PDF_COMBINERS (soft_light) +MAKE_SEPARABLE_PDF_COMBINERS (difference) +MAKE_SEPARABLE_PDF_COMBINERS (exclusion) + +/* + * PDF nonseperable blend modes. + * + * These are implemented using the following functions to operate in Hsl + * space, with Cmax, Cmid, Cmin referring to the max, mid and min value + * of the red, green and blue components. + * + * LUM (C) = 0.3 × Cred + 0.59 × Cgreen + 0.11 × Cblue + * + * clip_color (C): + * l = LUM (C) + * min = Cmin + * max = Cmax + * if n < 0.0 + * C = l + (((C – l) × l) ⁄ (l – min)) + * if x > 1.0 + * C = l + (((C – l) × (1 – l)) (max – l)) + * return C + * + * set_lum (C, l): + * d = l – LUM (C) + * C += d + * return clip_color (C) + * + * SAT (C) = CH_MAX (C) - CH_MIN (C) + * + * set_sat (C, s): + * if Cmax > Cmin + * Cmid = ( ( ( Cmid – Cmin ) × s ) ⁄ ( Cmax – Cmin ) ) + * Cmax = s + * else + * Cmid = Cmax = 0.0 + * Cmin = 0.0 + * return C + */ + +/* For premultiplied colors, we need to know what happens when C is + * multiplied by a real number. LUM and SAT are linear: + * + * LUM (r × C) = r × LUM (C) SAT (r × C) = r × SAT (C) + * + * If we extend clip_color with an extra argument a and change + * + * if x >= 1.0 + * + * into + * + * if x >= a + * + * then clip_color is also linear: + * + * r * clip_color (C, a) = clip_color (r_c, ra); + * + * for positive r. + * + * Similarly, we can extend set_lum with an extra argument that is just passed + * on to clip_color: + * + * r × set_lum ( C, l, a) + * + * = r × clip_color ( C + l - LUM (C), a) + * + * = clip_color ( r * C + r × l - LUM (r × C), r * a) + * + * = set_lum ( r * C, r * l, r * a) + * + * Finally, set_sat: + * + * r * set_sat (C, s) = set_sat (x * C, r * s) + * + * The above holds for all non-zero x because they x'es in the fraction for + * C_mid cancel out. Specifically, it holds for x = r: + * + * r * set_sat (C, s) = set_sat (r_c, rs) + * + * + * + * + * So, for the non-separable PDF blend modes, we have (using s, d for + * non-premultiplied colors, and S, D for premultiplied: + * + * Color: + * + * a_s * a_d * B(s, d) + * = a_s * a_d * set_lum (S/a_s, LUM (D/a_d), 1) + * = set_lum (S * a_d, a_s * LUM (D), a_s * a_d) + * + * + * Luminosity: + * + * a_s * a_d * B(s, d) + * = a_s * a_d * set_lum (D/a_d, LUM(S/a_s), 1) + * = set_lum (a_s * D, a_d * LUM(S), a_s * a_d) + * + * + * Saturation: + * + * a_s * a_d * B(s, d) + * = a_s * a_d * set_lum (set_sat (D/a_d, SAT (S/a_s)), LUM (D/a_d), 1) + * = set_lum (a_s * a_d * set_sat (D/a_d, SAT (S/a_s)), + * a_s * LUM (D), a_s * a_d) + * = set_lum (set_sat (a_s * D, a_d * SAT (S), a_s * LUM (D), a_s * a_d)) + * + * Hue: + * + * a_s * a_d * B(s, d) + * = a_s * a_d * set_lum (set_sat (S/a_s, SAT (D/a_d)), LUM (D/a_d), 1) + * = set_lum (set_sat (a_d * S, a_s * SAT (D)), a_s * LUM (D), a_s * a_d) + * + */ + +typedef struct +{ + float r; + float g; + float b; +} rgb_t; + +static force_inline float +minf (float a, float b) +{ + return a < b? a : b; +} + +static force_inline float +maxf (float a, float b) +{ + return a > b? a : b; +} + +static force_inline float +channel_min (const rgb_t *c) +{ + return minf (minf (c->r, c->g), c->b); +} + +static force_inline float +channel_max (const rgb_t *c) +{ + return maxf (maxf (c->r, c->g), c->b); +} + +static force_inline float +get_lum (const rgb_t *c) +{ + return c->r * 0.3f + c->g * 0.59f + c->b * 0.11f; +} + +static force_inline float +get_sat (const rgb_t *c) +{ + return channel_max (c) - channel_min (c); +} + +static void +clip_color (rgb_t *color, float a) +{ + float l = get_lum (color); + float n = channel_min (color); + float x = channel_max (color); + + if (n < 0.0f) + { + if ((l - n) < 4 * FLT_EPSILON) + { + color->r = 0.0f; + color->g = 0.0f; + color->b = 0.0f; + } + else + { + color->r = l + (((color->r - l) * l) / (l - n)); + color->g = l + (((color->g - l) * l) / (l - n)); + color->b = l + (((color->b - l) * l) / (l - n)); + } + } + if (x > a) + { + if ((x - l) < 4 * FLT_EPSILON) + { + color->r = a; + color->g = a; + color->b = a; + } + else + { + color->r = l + (((color->r - l) * (a - l) / (x - l))); + color->g = l + (((color->g - l) * (a - l) / (x - l))); + color->b = l + (((color->b - l) * (a - l) / (x - l))); + } + } +} + +static void +set_lum (rgb_t *color, float sa, float l) +{ + float d = l - get_lum (color); + + color->r = color->r + d; + color->g = color->g + d; + color->b = color->b + d; + + clip_color (color, sa); +} + +static void +set_sat (rgb_t *src, float sat) +{ + float *max, *mid, *min; + + if (src->r > src->g) + { + if (src->r > src->b) + { + max = &(src->r); + + if (src->g > src->b) + { + mid = &(src->g); + min = &(src->b); + } + else + { + mid = &(src->b); + min = &(src->g); + } + } + else + { + max = &(src->b); + mid = &(src->r); + min = &(src->g); + } + } + else + { + if (src->r > src->b) + { + max = &(src->g); + mid = &(src->r); + min = &(src->b); + } + else + { + min = &(src->r); + + if (src->g > src->b) + { + max = &(src->g); + mid = &(src->b); + } + else + { + max = &(src->b); + mid = &(src->g); + } + } + } + + if (*max > *min) + { + *mid = (((*mid - *min) * sat) / (*max - *min)); + *max = sat; + } + else + { + *mid = *max = 0.0f; + } + + *min = 0.0f; +} + +/* + * Hue: + * B(Cb, Cs) = set_lum (set_sat (Cs, SAT (Cb)), LUM (Cb)) + */ +static force_inline void +blend_hsl_hue (rgb_t *res, + const rgb_t *dest, float da, + const rgb_t *src, float sa) +{ + res->r = src->r * da; + res->g = src->g * da; + res->b = src->b * da; + + set_sat (res, get_sat (dest) * sa); + set_lum (res, sa * da, get_lum (dest) * sa); +} + +/* + * Saturation: + * B(Cb, Cs) = set_lum (set_sat (Cb, SAT (Cs)), LUM (Cb)) + */ +static force_inline void +blend_hsl_saturation (rgb_t *res, + const rgb_t *dest, float da, + const rgb_t *src, float sa) +{ + res->r = dest->r * sa; + res->g = dest->g * sa; + res->b = dest->b * sa; + + set_sat (res, get_sat (src) * da); + set_lum (res, sa * da, get_lum (dest) * sa); +} + +/* + * Color: + * B(Cb, Cs) = set_lum (Cs, LUM (Cb)) + */ +static force_inline void +blend_hsl_color (rgb_t *res, + const rgb_t *dest, float da, + const rgb_t *src, float sa) +{ + res->r = src->r * da; + res->g = src->g * da; + res->b = src->b * da; + + set_lum (res, sa * da, get_lum (dest) * sa); +} + +/* + * Luminosity: + * B(Cb, Cs) = set_lum (Cb, LUM (Cs)) + */ +static force_inline void +blend_hsl_luminosity (rgb_t *res, + const rgb_t *dest, float da, + const rgb_t *src, float sa) +{ + res->r = dest->r * sa; + res->g = dest->g * sa; + res->b = dest->b * sa; + + set_lum (res, sa * da, get_lum (src) * da); +} + +#define MAKE_NON_SEPARABLE_PDF_COMBINERS(name) \ + static void \ + combine_ ## name ## _u_float (pixman_implementation_t *imp, \ + pixman_op_t op, \ + float *dest, \ + const float *src, \ + const float *mask, \ + int n_pixels) \ + { \ + int i; \ + \ + for (i = 0; i < 4 * n_pixels; i += 4) \ + { \ + float sa, da; \ + rgb_t sc, dc, rc; \ + \ + sa = src[i + 0]; \ + sc.r = src[i + 1]; \ + sc.g = src[i + 2]; \ + sc.b = src[i + 3]; \ + \ + da = dest[i + 0]; \ + dc.r = dest[i + 1]; \ + dc.g = dest[i + 2]; \ + dc.b = dest[i + 3]; \ + \ + if (mask) \ + { \ + float ma = mask[i + 0]; \ + \ + /* Component alpha is not supported for HSL modes */ \ + sa *= ma; \ + sc.r *= ma; \ + sc.g *= ma; \ + sc.g *= ma; \ + } \ + \ + blend_ ## name (&rc, &dc, da, &sc, sa); \ + \ + dest[i + 0] = sa + da - sa * da; \ + dest[i + 1] = (1 - sa) * dc.r + (1 - da) * sc.r + rc.r; \ + dest[i + 2] = (1 - sa) * dc.g + (1 - da) * sc.g + rc.g; \ + dest[i + 3] = (1 - sa) * dc.b + (1 - da) * sc.b + rc.b; \ + } \ + } + +MAKE_NON_SEPARABLE_PDF_COMBINERS(hsl_hue) +MAKE_NON_SEPARABLE_PDF_COMBINERS(hsl_saturation) +MAKE_NON_SEPARABLE_PDF_COMBINERS(hsl_color) +MAKE_NON_SEPARABLE_PDF_COMBINERS(hsl_luminosity) + +void +_pixman_setup_combiner_functions_float (pixman_implementation_t *imp) +{ + /* Unified alpha */ + imp->combine_float[PIXMAN_OP_CLEAR] = combine_clear_u_float; + imp->combine_float[PIXMAN_OP_SRC] = combine_src_u_float; + imp->combine_float[PIXMAN_OP_DST] = combine_dst_u_float; + imp->combine_float[PIXMAN_OP_OVER] = combine_over_u_float; + imp->combine_float[PIXMAN_OP_OVER_REVERSE] = combine_over_reverse_u_float; + imp->combine_float[PIXMAN_OP_IN] = combine_in_u_float; + imp->combine_float[PIXMAN_OP_IN_REVERSE] = combine_in_reverse_u_float; + imp->combine_float[PIXMAN_OP_OUT] = combine_out_u_float; + imp->combine_float[PIXMAN_OP_OUT_REVERSE] = combine_out_reverse_u_float; + imp->combine_float[PIXMAN_OP_ATOP] = combine_atop_u_float; + imp->combine_float[PIXMAN_OP_ATOP_REVERSE] = combine_atop_reverse_u_float; + imp->combine_float[PIXMAN_OP_XOR] = combine_xor_u_float; + imp->combine_float[PIXMAN_OP_ADD] = combine_add_u_float; + imp->combine_float[PIXMAN_OP_SATURATE] = combine_saturate_u_float; + + /* Disjoint, unified */ + imp->combine_float[PIXMAN_OP_DISJOINT_CLEAR] = combine_disjoint_clear_u_float; + imp->combine_float[PIXMAN_OP_DISJOINT_SRC] = combine_disjoint_src_u_float; + imp->combine_float[PIXMAN_OP_DISJOINT_DST] = combine_disjoint_dst_u_float; + imp->combine_float[PIXMAN_OP_DISJOINT_OVER] = combine_disjoint_over_u_float; + imp->combine_float[PIXMAN_OP_DISJOINT_OVER_REVERSE] = combine_disjoint_over_reverse_u_float; + imp->combine_float[PIXMAN_OP_DISJOINT_IN] = combine_disjoint_in_u_float; + imp->combine_float[PIXMAN_OP_DISJOINT_IN_REVERSE] = combine_disjoint_in_reverse_u_float; + imp->combine_float[PIXMAN_OP_DISJOINT_OUT] = combine_disjoint_out_u_float; + imp->combine_float[PIXMAN_OP_DISJOINT_OUT_REVERSE] = combine_disjoint_out_reverse_u_float; + imp->combine_float[PIXMAN_OP_DISJOINT_ATOP] = combine_disjoint_atop_u_float; + imp->combine_float[PIXMAN_OP_DISJOINT_ATOP_REVERSE] = combine_disjoint_atop_reverse_u_float; + imp->combine_float[PIXMAN_OP_DISJOINT_XOR] = combine_disjoint_xor_u_float; + + /* Conjoint, unified */ + imp->combine_float[PIXMAN_OP_CONJOINT_CLEAR] = combine_conjoint_clear_u_float; + imp->combine_float[PIXMAN_OP_CONJOINT_SRC] = combine_conjoint_src_u_float; + imp->combine_float[PIXMAN_OP_CONJOINT_DST] = combine_conjoint_dst_u_float; + imp->combine_float[PIXMAN_OP_CONJOINT_OVER] = combine_conjoint_over_u_float; + imp->combine_float[PIXMAN_OP_CONJOINT_OVER_REVERSE] = combine_conjoint_over_reverse_u_float; + imp->combine_float[PIXMAN_OP_CONJOINT_IN] = combine_conjoint_in_u_float; + imp->combine_float[PIXMAN_OP_CONJOINT_IN_REVERSE] = combine_conjoint_in_reverse_u_float; + imp->combine_float[PIXMAN_OP_CONJOINT_OUT] = combine_conjoint_out_u_float; + imp->combine_float[PIXMAN_OP_CONJOINT_OUT_REVERSE] = combine_conjoint_out_reverse_u_float; + imp->combine_float[PIXMAN_OP_CONJOINT_ATOP] = combine_conjoint_atop_u_float; + imp->combine_float[PIXMAN_OP_CONJOINT_ATOP_REVERSE] = combine_conjoint_atop_reverse_u_float; + imp->combine_float[PIXMAN_OP_CONJOINT_XOR] = combine_conjoint_xor_u_float; + + /* PDF operators, unified */ + imp->combine_float[PIXMAN_OP_MULTIPLY] = combine_multiply_u_float; + imp->combine_float[PIXMAN_OP_SCREEN] = combine_screen_u_float; + imp->combine_float[PIXMAN_OP_OVERLAY] = combine_overlay_u_float; + imp->combine_float[PIXMAN_OP_DARKEN] = combine_darken_u_float; + imp->combine_float[PIXMAN_OP_LIGHTEN] = combine_lighten_u_float; + imp->combine_float[PIXMAN_OP_COLOR_DODGE] = combine_color_dodge_u_float; + imp->combine_float[PIXMAN_OP_COLOR_BURN] = combine_color_burn_u_float; + imp->combine_float[PIXMAN_OP_HARD_LIGHT] = combine_hard_light_u_float; + imp->combine_float[PIXMAN_OP_SOFT_LIGHT] = combine_soft_light_u_float; + imp->combine_float[PIXMAN_OP_DIFFERENCE] = combine_difference_u_float; + imp->combine_float[PIXMAN_OP_EXCLUSION] = combine_exclusion_u_float; + + imp->combine_float[PIXMAN_OP_HSL_HUE] = combine_hsl_hue_u_float; + imp->combine_float[PIXMAN_OP_HSL_SATURATION] = combine_hsl_saturation_u_float; + imp->combine_float[PIXMAN_OP_HSL_COLOR] = combine_hsl_color_u_float; + imp->combine_float[PIXMAN_OP_HSL_LUMINOSITY] = combine_hsl_luminosity_u_float; + + /* Component alpha combiners */ + imp->combine_float_ca[PIXMAN_OP_CLEAR] = combine_clear_ca_float; + imp->combine_float_ca[PIXMAN_OP_SRC] = combine_src_ca_float; + imp->combine_float_ca[PIXMAN_OP_DST] = combine_dst_ca_float; + imp->combine_float_ca[PIXMAN_OP_OVER] = combine_over_ca_float; + imp->combine_float_ca[PIXMAN_OP_OVER_REVERSE] = combine_over_reverse_ca_float; + imp->combine_float_ca[PIXMAN_OP_IN] = combine_in_ca_float; + imp->combine_float_ca[PIXMAN_OP_IN_REVERSE] = combine_in_reverse_ca_float; + imp->combine_float_ca[PIXMAN_OP_OUT] = combine_out_ca_float; + imp->combine_float_ca[PIXMAN_OP_OUT_REVERSE] = combine_out_reverse_ca_float; + imp->combine_float_ca[PIXMAN_OP_ATOP] = combine_atop_ca_float; + imp->combine_float_ca[PIXMAN_OP_ATOP_REVERSE] = combine_atop_reverse_ca_float; + imp->combine_float_ca[PIXMAN_OP_XOR] = combine_xor_ca_float; + imp->combine_float_ca[PIXMAN_OP_ADD] = combine_add_ca_float; + imp->combine_float_ca[PIXMAN_OP_SATURATE] = combine_saturate_ca_float; + + /* Disjoint CA */ + imp->combine_float_ca[PIXMAN_OP_DISJOINT_CLEAR] = combine_disjoint_clear_ca_float; + imp->combine_float_ca[PIXMAN_OP_DISJOINT_SRC] = combine_disjoint_src_ca_float; + imp->combine_float_ca[PIXMAN_OP_DISJOINT_DST] = combine_disjoint_dst_ca_float; + imp->combine_float_ca[PIXMAN_OP_DISJOINT_OVER] = combine_disjoint_over_ca_float; + imp->combine_float_ca[PIXMAN_OP_DISJOINT_OVER_REVERSE] = combine_disjoint_over_reverse_ca_float; + imp->combine_float_ca[PIXMAN_OP_DISJOINT_IN] = combine_disjoint_in_ca_float; + imp->combine_float_ca[PIXMAN_OP_DISJOINT_IN_REVERSE] = combine_disjoint_in_reverse_ca_float; + imp->combine_float_ca[PIXMAN_OP_DISJOINT_OUT] = combine_disjoint_out_ca_float; + imp->combine_float_ca[PIXMAN_OP_DISJOINT_OUT_REVERSE] = combine_disjoint_out_reverse_ca_float; + imp->combine_float_ca[PIXMAN_OP_DISJOINT_ATOP] = combine_disjoint_atop_ca_float; + imp->combine_float_ca[PIXMAN_OP_DISJOINT_ATOP_REVERSE] = combine_disjoint_atop_reverse_ca_float; + imp->combine_float_ca[PIXMAN_OP_DISJOINT_XOR] = combine_disjoint_xor_ca_float; + + /* Conjoint CA */ + imp->combine_float_ca[PIXMAN_OP_CONJOINT_CLEAR] = combine_conjoint_clear_ca_float; + imp->combine_float_ca[PIXMAN_OP_CONJOINT_SRC] = combine_conjoint_src_ca_float; + imp->combine_float_ca[PIXMAN_OP_CONJOINT_DST] = combine_conjoint_dst_ca_float; + imp->combine_float_ca[PIXMAN_OP_CONJOINT_OVER] = combine_conjoint_over_ca_float; + imp->combine_float_ca[PIXMAN_OP_CONJOINT_OVER_REVERSE] = combine_conjoint_over_reverse_ca_float; + imp->combine_float_ca[PIXMAN_OP_CONJOINT_IN] = combine_conjoint_in_ca_float; + imp->combine_float_ca[PIXMAN_OP_CONJOINT_IN_REVERSE] = combine_conjoint_in_reverse_ca_float; + imp->combine_float_ca[PIXMAN_OP_CONJOINT_OUT] = combine_conjoint_out_ca_float; + imp->combine_float_ca[PIXMAN_OP_CONJOINT_OUT_REVERSE] = combine_conjoint_out_reverse_ca_float; + imp->combine_float_ca[PIXMAN_OP_CONJOINT_ATOP] = combine_conjoint_atop_ca_float; + imp->combine_float_ca[PIXMAN_OP_CONJOINT_ATOP_REVERSE] = combine_conjoint_atop_reverse_ca_float; + imp->combine_float_ca[PIXMAN_OP_CONJOINT_XOR] = combine_conjoint_xor_ca_float; + + /* PDF operators CA */ + imp->combine_float_ca[PIXMAN_OP_MULTIPLY] = combine_multiply_ca_float; + imp->combine_float_ca[PIXMAN_OP_SCREEN] = combine_screen_ca_float; + imp->combine_float_ca[PIXMAN_OP_OVERLAY] = combine_overlay_ca_float; + imp->combine_float_ca[PIXMAN_OP_DARKEN] = combine_darken_ca_float; + imp->combine_float_ca[PIXMAN_OP_LIGHTEN] = combine_lighten_ca_float; + imp->combine_float_ca[PIXMAN_OP_COLOR_DODGE] = combine_color_dodge_ca_float; + imp->combine_float_ca[PIXMAN_OP_COLOR_BURN] = combine_color_burn_ca_float; + imp->combine_float_ca[PIXMAN_OP_HARD_LIGHT] = combine_hard_light_ca_float; + imp->combine_float_ca[PIXMAN_OP_SOFT_LIGHT] = combine_soft_light_ca_float; + imp->combine_float_ca[PIXMAN_OP_DIFFERENCE] = combine_difference_ca_float; + imp->combine_float_ca[PIXMAN_OP_EXCLUSION] = combine_exclusion_ca_float; + + /* It is not clear that these make sense, so make them noops for now */ + imp->combine_float_ca[PIXMAN_OP_HSL_HUE] = combine_dst_u_float; + imp->combine_float_ca[PIXMAN_OP_HSL_SATURATION] = combine_dst_u_float; + imp->combine_float_ca[PIXMAN_OP_HSL_COLOR] = combine_dst_u_float; + imp->combine_float_ca[PIXMAN_OP_HSL_LUMINOSITY] = combine_dst_u_float; +} diff --git a/pixman/pixman/pixman-combine.c.template b/pixman/pixman/pixman-combine.c.template deleted file mode 100644 index f405312d4..000000000 --- a/pixman/pixman/pixman-combine.c.template +++ /dev/null @@ -1,2437 +0,0 @@ -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include - -#include "pixman-private.h" -#include "pixman-combine.h" - -/* component alpha helper functions */ - -static void -combine_mask_ca (comp4_t *src, comp4_t *mask) -{ - comp4_t a = *mask; - - comp4_t x; - comp2_t xa; - - if (!a) - { - *(src) = 0; - return; - } - - x = *(src); - if (a == ~0) - { - x = x >> A_SHIFT; - x |= x << G_SHIFT; - x |= x << R_SHIFT; - *(mask) = x; - return; - } - - xa = x >> A_SHIFT; - UNcx4_MUL_UNcx4 (x, a); - *(src) = x; - - UNcx4_MUL_UNc (a, xa); - *(mask) = a; -} - -static void -combine_mask_value_ca (comp4_t *src, const comp4_t *mask) -{ - comp4_t a = *mask; - comp4_t x; - - if (!a) - { - *(src) = 0; - return; - } - - if (a == ~0) - return; - - x = *(src); - UNcx4_MUL_UNcx4 (x, a); - *(src) = x; -} - -static void -combine_mask_alpha_ca (const comp4_t *src, comp4_t *mask) -{ - comp4_t a = *(mask); - comp4_t x; - - if (!a) - return; - - x = *(src) >> A_SHIFT; - if (x == MASK) - return; - - if (a == ~0) - { - x |= x << G_SHIFT; - x |= x << R_SHIFT; - *(mask) = x; - return; - } - - UNcx4_MUL_UNc (a, x); - *(mask) = a; -} - -/* - * There are two ways of handling alpha -- either as a single unified value or - * a separate value for each component, hence each macro must have two - * versions. The unified alpha version has a 'u' at the end of the name, - * the component version has a 'ca'. Similarly, functions which deal with - * this difference will have two versions using the same convention. - */ - -static force_inline comp4_t -combine_mask (const comp4_t *src, const comp4_t *mask, int i) -{ - comp4_t s, m; - - if (mask) - { - m = *(mask + i) >> A_SHIFT; - - if (!m) - return 0; - } - - s = *(src + i); - - if (mask) - UNcx4_MUL_UNc (s, m); - - return s; -} - -static void -combine_clear (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - memset (dest, 0, width * sizeof(comp4_t)); -} - -static void -combine_dst (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - return; -} - -static void -combine_src_u (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - int i; - - if (!mask) - { - memcpy (dest, src, width * sizeof (comp4_t)); - } - else - { - for (i = 0; i < width; ++i) - { - comp4_t s = combine_mask (src, mask, i); - - *(dest + i) = s; - } - } -} - -static void -combine_over_u (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - int i; - - for (i = 0; i < width; ++i) - { - comp4_t s = combine_mask (src, mask, i); - comp4_t d = *(dest + i); - comp4_t ia = ALPHA_c (~s); - - UNcx4_MUL_UNc_ADD_UNcx4 (d, ia, s); - *(dest + i) = d; - } -} - -static void -combine_over_reverse_u (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - int i; - - for (i = 0; i < width; ++i) - { - comp4_t s = combine_mask (src, mask, i); - comp4_t d = *(dest + i); - comp4_t ia = ALPHA_c (~*(dest + i)); - UNcx4_MUL_UNc_ADD_UNcx4 (s, ia, d); - *(dest + i) = s; - } -} - -static void -combine_in_u (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - int i; - - for (i = 0; i < width; ++i) - { - comp4_t s = combine_mask (src, mask, i); - comp4_t a = ALPHA_c (*(dest + i)); - UNcx4_MUL_UNc (s, a); - *(dest + i) = s; - } -} - -static void -combine_in_reverse_u (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - int i; - - for (i = 0; i < width; ++i) - { - comp4_t s = combine_mask (src, mask, i); - comp4_t d = *(dest + i); - comp4_t a = ALPHA_c (s); - UNcx4_MUL_UNc (d, a); - *(dest + i) = d; - } -} - -static void -combine_out_u (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - int i; - - for (i = 0; i < width; ++i) - { - comp4_t s = combine_mask (src, mask, i); - comp4_t a = ALPHA_c (~*(dest + i)); - UNcx4_MUL_UNc (s, a); - *(dest + i) = s; - } -} - -static void -combine_out_reverse_u (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - int i; - - for (i = 0; i < width; ++i) - { - comp4_t s = combine_mask (src, mask, i); - comp4_t d = *(dest + i); - comp4_t a = ALPHA_c (~s); - UNcx4_MUL_UNc (d, a); - *(dest + i) = d; - } -} - -static void -combine_atop_u (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - int i; - - for (i = 0; i < width; ++i) - { - comp4_t s = combine_mask (src, mask, i); - comp4_t d = *(dest + i); - comp4_t dest_a = ALPHA_c (d); - comp4_t src_ia = ALPHA_c (~s); - - UNcx4_MUL_UNc_ADD_UNcx4_MUL_UNc (s, dest_a, d, src_ia); - *(dest + i) = s; - } -} - -static void -combine_atop_reverse_u (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - int i; - - for (i = 0; i < width; ++i) - { - comp4_t s = combine_mask (src, mask, i); - comp4_t d = *(dest + i); - comp4_t src_a = ALPHA_c (s); - comp4_t dest_ia = ALPHA_c (~d); - - UNcx4_MUL_UNc_ADD_UNcx4_MUL_UNc (s, dest_ia, d, src_a); - *(dest + i) = s; - } -} - -static void -combine_xor_u (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - int i; - - for (i = 0; i < width; ++i) - { - comp4_t s = combine_mask (src, mask, i); - comp4_t d = *(dest + i); - comp4_t src_ia = ALPHA_c (~s); - comp4_t dest_ia = ALPHA_c (~d); - - UNcx4_MUL_UNc_ADD_UNcx4_MUL_UNc (s, dest_ia, d, src_ia); - *(dest + i) = s; - } -} - -static void -combine_add_u (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - int i; - - for (i = 0; i < width; ++i) - { - comp4_t s = combine_mask (src, mask, i); - comp4_t d = *(dest + i); - UNcx4_ADD_UNcx4 (d, s); - *(dest + i) = d; - } -} - -static void -combine_saturate_u (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - int i; - - for (i = 0; i < width; ++i) - { - comp4_t s = combine_mask (src, mask, i); - comp4_t d = *(dest + i); - comp2_t sa, da; - - sa = s >> A_SHIFT; - da = ~d >> A_SHIFT; - if (sa > da) - { - sa = DIV_UNc (da, sa); - UNcx4_MUL_UNc (s, sa); - } - ; - UNcx4_ADD_UNcx4 (d, s); - *(dest + i) = d; - } -} - -/* - * PDF blend modes: - * The following blend modes have been taken from the PDF ISO 32000 - * specification, which at this point in time is available from - * http://www.adobe.com/devnet/acrobat/pdfs/PDF32000_2008.pdf - * The relevant chapters are 11.3.5 and 11.3.6. - * The formula for computing the final pixel color given in 11.3.6 is: - * αr × Cr = (1 – αs) × αb × Cb + (1 – αb) × αs × Cs + αb × αs × B(Cb, Cs) - * with B() being the blend function. - * Note that OVER is a special case of this operation, using B(Cb, Cs) = Cs - * - * These blend modes should match the SVG filter draft specification, as - * it has been designed to mirror ISO 32000. Note that at the current point - * no released draft exists that shows this, as the formulas have not been - * updated yet after the release of ISO 32000. - * - * The default implementation here uses the PDF_SEPARABLE_BLEND_MODE and - * PDF_NON_SEPARABLE_BLEND_MODE macros, which take the blend function as an - * argument. Note that this implementation operates on premultiplied colors, - * while the PDF specification does not. Therefore the code uses the formula - * Cra = (1 – as) . Dca + (1 – ad) . Sca + B(Dca, ad, Sca, as) - */ - -/* - * Multiply - * B(Dca, ad, Sca, as) = Dca.Sca - */ -static void -combine_multiply_u (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - int i; - - for (i = 0; i < width; ++i) - { - comp4_t s = combine_mask (src, mask, i); - comp4_t d = *(dest + i); - comp4_t ss = s; - comp4_t src_ia = ALPHA_c (~s); - comp4_t dest_ia = ALPHA_c (~d); - - UNcx4_MUL_UNc_ADD_UNcx4_MUL_UNc (ss, dest_ia, d, src_ia); - UNcx4_MUL_UNcx4 (d, s); - UNcx4_ADD_UNcx4 (d, ss); - - *(dest + i) = d; - } -} - -static void -combine_multiply_ca (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - int i; - - for (i = 0; i < width; ++i) - { - comp4_t m = *(mask + i); - comp4_t s = *(src + i); - comp4_t d = *(dest + i); - comp4_t r = d; - comp4_t dest_ia = ALPHA_c (~d); - - combine_mask_ca (&s, &m); - - UNcx4_MUL_UNcx4_ADD_UNcx4_MUL_UNc (r, ~m, s, dest_ia); - UNcx4_MUL_UNcx4 (d, s); - UNcx4_ADD_UNcx4 (r, d); - - *(dest + i) = r; - } -} - -#define PDF_SEPARABLE_BLEND_MODE(name) \ - static void \ - combine_ ## name ## _u (pixman_implementation_t *imp, \ - pixman_op_t op, \ - comp4_t * dest, \ - const comp4_t * src, \ - const comp4_t * mask, \ - int width) \ - { \ - int i; \ - for (i = 0; i < width; ++i) { \ - comp4_t s = combine_mask (src, mask, i); \ - comp4_t d = *(dest + i); \ - comp1_t sa = ALPHA_c (s); \ - comp1_t isa = ~sa; \ - comp1_t da = ALPHA_c (d); \ - comp1_t ida = ~da; \ - comp4_t result; \ - \ - result = d; \ - UNcx4_MUL_UNc_ADD_UNcx4_MUL_UNc (result, isa, s, ida); \ - \ - *(dest + i) = result + \ - (DIV_ONE_UNc (sa * (comp4_t)da) << A_SHIFT) + \ - (blend_ ## name (RED_c (d), da, RED_c (s), sa) << R_SHIFT) + \ - (blend_ ## name (GREEN_c (d), da, GREEN_c (s), sa) << G_SHIFT) + \ - (blend_ ## name (BLUE_c (d), da, BLUE_c (s), sa)); \ - } \ - } \ - \ - static void \ - combine_ ## name ## _ca (pixman_implementation_t *imp, \ - pixman_op_t op, \ - comp4_t * dest, \ - const comp4_t * src, \ - const comp4_t * mask, \ - int width) \ - { \ - int i; \ - for (i = 0; i < width; ++i) { \ - comp4_t m = *(mask + i); \ - comp4_t s = *(src + i); \ - comp4_t d = *(dest + i); \ - comp1_t da = ALPHA_c (d); \ - comp1_t ida = ~da; \ - comp4_t result; \ - \ - combine_mask_ca (&s, &m); \ - \ - result = d; \ - UNcx4_MUL_UNcx4_ADD_UNcx4_MUL_UNc (result, ~m, s, ida); \ - \ - result += \ - (DIV_ONE_UNc (ALPHA_c (m) * (comp4_t)da) << A_SHIFT) + \ - (blend_ ## name (RED_c (d), da, RED_c (s), RED_c (m)) << R_SHIFT) + \ - (blend_ ## name (GREEN_c (d), da, GREEN_c (s), GREEN_c (m)) << G_SHIFT) + \ - (blend_ ## name (BLUE_c (d), da, BLUE_c (s), BLUE_c (m))); \ - \ - *(dest + i) = result; \ - } \ - } - -/* - * Screen - * B(Dca, ad, Sca, as) = Dca.sa + Sca.da - Dca.Sca - */ -static inline comp4_t -blend_screen (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa) -{ - return DIV_ONE_UNc (sca * da + dca * sa - sca * dca); -} - -PDF_SEPARABLE_BLEND_MODE (screen) - -/* - * Overlay - * B(Dca, Da, Sca, Sa) = - * if 2.Dca < Da - * 2.Sca.Dca - * otherwise - * Sa.Da - 2.(Da - Dca).(Sa - Sca) - */ -static inline comp4_t -blend_overlay (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa) -{ - comp4_t rca; - - if (2 * dca < da) - rca = 2 * sca * dca; - else - rca = sa * da - 2 * (da - dca) * (sa - sca); - return DIV_ONE_UNc (rca); -} - -PDF_SEPARABLE_BLEND_MODE (overlay) - -/* - * Darken - * B(Dca, Da, Sca, Sa) = min (Sca.Da, Dca.Sa) - */ -static inline comp4_t -blend_darken (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa) -{ - comp4_t s, d; - - s = sca * da; - d = dca * sa; - return DIV_ONE_UNc (s > d ? d : s); -} - -PDF_SEPARABLE_BLEND_MODE (darken) - -/* - * Lighten - * B(Dca, Da, Sca, Sa) = max (Sca.Da, Dca.Sa) - */ -static inline comp4_t -blend_lighten (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa) -{ - comp4_t s, d; - - s = sca * da; - d = dca * sa; - return DIV_ONE_UNc (s > d ? s : d); -} - -PDF_SEPARABLE_BLEND_MODE (lighten) - -/* - * Color dodge - * B(Dca, Da, Sca, Sa) = - * if Dca == 0 - * 0 - * if Sca == Sa - * Sa.Da - * otherwise - * Sa.Da. min (1, Dca / Da / (1 - Sca/Sa)) - */ -static inline comp4_t -blend_color_dodge (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa) -{ - if (sca >= sa) - { - return dca == 0 ? 0 : DIV_ONE_UNc (sa * da); - } - else - { - comp4_t rca = dca * sa / (sa - sca); - return DIV_ONE_UNc (sa * MIN (rca, da)); - } -} - -PDF_SEPARABLE_BLEND_MODE (color_dodge) - -/* - * Color burn - * B(Dca, Da, Sca, Sa) = - * if Dca == Da - * Sa.Da - * if Sca == 0 - * 0 - * otherwise - * Sa.Da.(1 - min (1, (1 - Dca/Da).Sa / Sca)) - */ -static inline comp4_t -blend_color_burn (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa) -{ - if (sca == 0) - { - return dca < da ? 0 : DIV_ONE_UNc (sa * da); - } - else - { - comp4_t rca = (da - dca) * sa / sca; - return DIV_ONE_UNc (sa * (MAX (rca, da) - rca)); - } -} - -PDF_SEPARABLE_BLEND_MODE (color_burn) - -/* - * Hard light - * B(Dca, Da, Sca, Sa) = - * if 2.Sca < Sa - * 2.Sca.Dca - * otherwise - * Sa.Da - 2.(Da - Dca).(Sa - Sca) - */ -static inline comp4_t -blend_hard_light (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa) -{ - if (2 * sca < sa) - return DIV_ONE_UNc (2 * sca * dca); - else - return DIV_ONE_UNc (sa * da - 2 * (da - dca) * (sa - sca)); -} - -PDF_SEPARABLE_BLEND_MODE (hard_light) - -/* - * Soft light - * B(Dca, Da, Sca, Sa) = - * if (2.Sca <= Sa) - * Dca.(Sa - (1 - Dca/Da).(2.Sca - Sa)) - * otherwise if Dca.4 <= Da - * Dca.(Sa + (2.Sca - Sa).((16.Dca/Da - 12).Dca/Da + 3) - * otherwise - * (Dca.Sa + (SQRT (Dca/Da).Da - Dca).(2.Sca - Sa)) - */ -static inline comp4_t -blend_soft_light (comp4_t dca_org, - comp4_t da_org, - comp4_t sca_org, - comp4_t sa_org) -{ - double dca = dca_org * (1.0 / MASK); - double da = da_org * (1.0 / MASK); - double sca = sca_org * (1.0 / MASK); - double sa = sa_org * (1.0 / MASK); - double rca; - - if (2 * sca < sa) - { - if (da == 0) - rca = dca * sa; - else - rca = dca * sa - dca * (da - dca) * (sa - 2 * sca) / da; - } - else if (da == 0) - { - rca = 0; - } - else if (4 * dca <= da) - { - rca = dca * sa + - (2 * sca - sa) * dca * ((16 * dca / da - 12) * dca / da + 3); - } - else - { - rca = dca * sa + (sqrt (dca * da) - dca) * (2 * sca - sa); - } - return rca * MASK + 0.5; -} - -PDF_SEPARABLE_BLEND_MODE (soft_light) - -/* - * Difference - * B(Dca, Da, Sca, Sa) = abs (Dca.Sa - Sca.Da) - */ -static inline comp4_t -blend_difference (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa) -{ - comp4_t dcasa = dca * sa; - comp4_t scada = sca * da; - - if (scada < dcasa) - return DIV_ONE_UNc (dcasa - scada); - else - return DIV_ONE_UNc (scada - dcasa); -} - -PDF_SEPARABLE_BLEND_MODE (difference) - -/* - * Exclusion - * B(Dca, Da, Sca, Sa) = (Sca.Da + Dca.Sa - 2.Sca.Dca) - */ - -/* This can be made faster by writing it directly and not using - * PDF_SEPARABLE_BLEND_MODE, but that's a performance optimization */ - -static inline comp4_t -blend_exclusion (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa) -{ - return DIV_ONE_UNc (sca * da + dca * sa - 2 * dca * sca); -} - -PDF_SEPARABLE_BLEND_MODE (exclusion) - -#undef PDF_SEPARABLE_BLEND_MODE - -/* - * PDF nonseperable blend modes are implemented using the following functions - * to operate in Hsl space, with Cmax, Cmid, Cmin referring to the max, mid - * and min value of the red, green and blue components. - * - * LUM (C) = 0.3 × Cred + 0.59 × Cgreen + 0.11 × Cblue - * - * clip_color (C): - * l = LUM (C) - * min = Cmin - * max = Cmax - * if n < 0.0 - * C = l + ( ( ( C – l ) × l ) ⁄ ( l – min ) ) - * if x > 1.0 - * C = l + ( ( ( C – l ) × ( 1 – l ) ) ⁄ ( max – l ) ) - * return C - * - * set_lum (C, l): - * d = l – LUM (C) - * C += d - * return clip_color (C) - * - * SAT (C) = CH_MAX (C) - CH_MIN (C) - * - * set_sat (C, s): - * if Cmax > Cmin - * Cmid = ( ( ( Cmid – Cmin ) × s ) ⁄ ( Cmax – Cmin ) ) - * Cmax = s - * else - * Cmid = Cmax = 0.0 - * Cmin = 0.0 - * return C - */ - -/* For premultiplied colors, we need to know what happens when C is - * multiplied by a real number. LUM and SAT are linear: - * - * LUM (r × C) = r × LUM (C) SAT (r * C) = r * SAT (C) - * - * If we extend clip_color with an extra argument a and change - * - * if x >= 1.0 - * - * into - * - * if x >= a - * - * then clip_color is also linear: - * - * r * clip_color (C, a) = clip_color (r_c, ra); - * - * for positive r. - * - * Similarly, we can extend set_lum with an extra argument that is just passed - * on to clip_color: - * - * r * set_lum ( C, l, a) - * - * = r × clip_color ( C + l - LUM (C), a) - * - * = clip_color ( r * C + r × l - r * LUM (C), r * a) - * - * = set_lum ( r * C, r * l, r * a) - * - * Finally, set_sat: - * - * r * set_sat (C, s) = set_sat (x * C, r * s) - * - * The above holds for all non-zero x, because the x'es in the fraction for - * C_mid cancel out. Specifically, it holds for x = r: - * - * r * set_sat (C, s) = set_sat (r_c, rs) - * - */ - -/* So, for the non-separable PDF blend modes, we have (using s, d for - * non-premultiplied colors, and S, D for premultiplied: - * - * Color: - * - * a_s * a_d * B(s, d) - * = a_s * a_d * set_lum (S/a_s, LUM (D/a_d), 1) - * = set_lum (S * a_d, a_s * LUM (D), a_s * a_d) - * - * - * Luminosity: - * - * a_s * a_d * B(s, d) - * = a_s * a_d * set_lum (D/a_d, LUM(S/a_s), 1) - * = set_lum (a_s * D, a_d * LUM(S), a_s * a_d) - * - * - * Saturation: - * - * a_s * a_d * B(s, d) - * = a_s * a_d * set_lum (set_sat (D/a_d, SAT (S/a_s)), LUM (D/a_d), 1) - * = set_lum (a_s * a_d * set_sat (D/a_d, SAT (S/a_s)), - * a_s * LUM (D), a_s * a_d) - * = set_lum (set_sat (a_s * D, a_d * SAT (S), a_s * LUM (D), a_s * a_d)) - * - * Hue: - * - * a_s * a_d * B(s, d) - * = a_s * a_d * set_lum (set_sat (S/a_s, SAT (D/a_d)), LUM (D/a_d), 1) - * = set_lum (set_sat (a_d * S, a_s * SAT (D)), a_s * LUM (D), a_s * a_d) - * - */ - -#define CH_MIN(c) (c[0] < c[1] ? (c[0] < c[2] ? c[0] : c[2]) : (c[1] < c[2] ? c[1] : c[2])) -#define CH_MAX(c) (c[0] > c[1] ? (c[0] > c[2] ? c[0] : c[2]) : (c[1] > c[2] ? c[1] : c[2])) -#define LUM(c) ((c[0] * 30 + c[1] * 59 + c[2] * 11) / 100) -#define SAT(c) (CH_MAX (c) - CH_MIN (c)) - -#define PDF_NON_SEPARABLE_BLEND_MODE(name) \ - static void \ - combine_ ## name ## _u (pixman_implementation_t *imp, \ - pixman_op_t op, \ - comp4_t *dest, \ - const comp4_t *src, \ - const comp4_t *mask, \ - int width) \ - { \ - int i; \ - for (i = 0; i < width; ++i) \ - { \ - comp4_t s = combine_mask (src, mask, i); \ - comp4_t d = *(dest + i); \ - comp1_t sa = ALPHA_c (s); \ - comp1_t isa = ~sa; \ - comp1_t da = ALPHA_c (d); \ - comp1_t ida = ~da; \ - comp4_t result; \ - comp4_t sc[3], dc[3], c[3]; \ - \ - result = d; \ - UNcx4_MUL_UNc_ADD_UNcx4_MUL_UNc (result, isa, s, ida); \ - dc[0] = RED_c (d); \ - sc[0] = RED_c (s); \ - dc[1] = GREEN_c (d); \ - sc[1] = GREEN_c (s); \ - dc[2] = BLUE_c (d); \ - sc[2] = BLUE_c (s); \ - blend_ ## name (c, dc, da, sc, sa); \ - \ - *(dest + i) = result + \ - (DIV_ONE_UNc (sa * (comp4_t)da) << A_SHIFT) + \ - (DIV_ONE_UNc (c[0]) << R_SHIFT) + \ - (DIV_ONE_UNc (c[1]) << G_SHIFT) + \ - (DIV_ONE_UNc (c[2])); \ - } \ - } - -static void -set_lum (comp4_t dest[3], comp4_t src[3], comp4_t sa, comp4_t lum) -{ - double a, l, min, max; - double tmp[3]; - - a = sa * (1.0 / MASK); - - l = lum * (1.0 / MASK); - tmp[0] = src[0] * (1.0 / MASK); - tmp[1] = src[1] * (1.0 / MASK); - tmp[2] = src[2] * (1.0 / MASK); - - l = l - LUM (tmp); - tmp[0] += l; - tmp[1] += l; - tmp[2] += l; - - /* clip_color */ - l = LUM (tmp); - min = CH_MIN (tmp); - max = CH_MAX (tmp); - - if (min < 0) - { - if (l - min == 0.0) - { - tmp[0] = 0; - tmp[1] = 0; - tmp[2] = 0; - } - else - { - tmp[0] = l + (tmp[0] - l) * l / (l - min); - tmp[1] = l + (tmp[1] - l) * l / (l - min); - tmp[2] = l + (tmp[2] - l) * l / (l - min); - } - } - if (max > a) - { - if (max - l == 0.0) - { - tmp[0] = a; - tmp[1] = a; - tmp[2] = a; - } - else - { - tmp[0] = l + (tmp[0] - l) * (a - l) / (max - l); - tmp[1] = l + (tmp[1] - l) * (a - l) / (max - l); - tmp[2] = l + (tmp[2] - l) * (a - l) / (max - l); - } - } - - dest[0] = tmp[0] * MASK + 0.5; - dest[1] = tmp[1] * MASK + 0.5; - dest[2] = tmp[2] * MASK + 0.5; -} - -static void -set_sat (comp4_t dest[3], comp4_t src[3], comp4_t sat) -{ - int id[3]; - comp4_t min, max; - - if (src[0] > src[1]) - { - if (src[0] > src[2]) - { - id[0] = 0; - if (src[1] > src[2]) - { - id[1] = 1; - id[2] = 2; - } - else - { - id[1] = 2; - id[2] = 1; - } - } - else - { - id[0] = 2; - id[1] = 0; - id[2] = 1; - } - } - else - { - if (src[0] > src[2]) - { - id[0] = 1; - id[1] = 0; - id[2] = 2; - } - else - { - id[2] = 0; - if (src[1] > src[2]) - { - id[0] = 1; - id[1] = 2; - } - else - { - id[0] = 2; - id[1] = 1; - } - } - } - - max = dest[id[0]]; - min = dest[id[2]]; - if (max > min) - { - dest[id[1]] = (dest[id[1]] - min) * sat / (max - min); - dest[id[0]] = sat; - dest[id[2]] = 0; - } - else - { - dest[0] = dest[1] = dest[2] = 0; - } -} - -/* - * Hue: - * B(Cb, Cs) = set_lum (set_sat (Cs, SAT (Cb)), LUM (Cb)) - */ -static inline void -blend_hsl_hue (comp4_t c[3], - comp4_t dc[3], - comp4_t da, - comp4_t sc[3], - comp4_t sa) -{ - c[0] = sc[0] * da; - c[1] = sc[1] * da; - c[2] = sc[2] * da; - set_sat (c, c, SAT (dc) * sa); - set_lum (c, c, sa * da, LUM (dc) * sa); -} - -PDF_NON_SEPARABLE_BLEND_MODE (hsl_hue) - -/* - * Saturation: - * B(Cb, Cs) = set_lum (set_sat (Cb, SAT (Cs)), LUM (Cb)) - */ -static inline void -blend_hsl_saturation (comp4_t c[3], - comp4_t dc[3], - comp4_t da, - comp4_t sc[3], - comp4_t sa) -{ - c[0] = dc[0] * sa; - c[1] = dc[1] * sa; - c[2] = dc[2] * sa; - set_sat (c, c, SAT (sc) * da); - set_lum (c, c, sa * da, LUM (dc) * sa); -} - -PDF_NON_SEPARABLE_BLEND_MODE (hsl_saturation) - -/* - * Color: - * B(Cb, Cs) = set_lum (Cs, LUM (Cb)) - */ -static inline void -blend_hsl_color (comp4_t c[3], - comp4_t dc[3], - comp4_t da, - comp4_t sc[3], - comp4_t sa) -{ - c[0] = sc[0] * da; - c[1] = sc[1] * da; - c[2] = sc[2] * da; - set_lum (c, c, sa * da, LUM (dc) * sa); -} - -PDF_NON_SEPARABLE_BLEND_MODE (hsl_color) - -/* - * Luminosity: - * B(Cb, Cs) = set_lum (Cb, LUM (Cs)) - */ -static inline void -blend_hsl_luminosity (comp4_t c[3], - comp4_t dc[3], - comp4_t da, - comp4_t sc[3], - comp4_t sa) -{ - c[0] = dc[0] * sa; - c[1] = dc[1] * sa; - c[2] = dc[2] * sa; - set_lum (c, c, sa * da, LUM (sc) * da); -} - -PDF_NON_SEPARABLE_BLEND_MODE (hsl_luminosity) - -#undef SAT -#undef LUM -#undef CH_MAX -#undef CH_MIN -#undef PDF_NON_SEPARABLE_BLEND_MODE - -/* All of the disjoint/conjoint composing functions - * - * The four entries in the first column indicate what source contributions - * come from each of the four areas of the picture -- areas covered by neither - * A nor B, areas covered only by A, areas covered only by B and finally - * areas covered by both A and B. - * - * Disjoint Conjoint - * Fa Fb Fa Fb - * (0,0,0,0) 0 0 0 0 - * (0,A,0,A) 1 0 1 0 - * (0,0,B,B) 0 1 0 1 - * (0,A,B,A) 1 min((1-a)/b,1) 1 max(1-a/b,0) - * (0,A,B,B) min((1-b)/a,1) 1 max(1-b/a,0) 1 - * (0,0,0,A) max(1-(1-b)/a,0) 0 min(1,b/a) 0 - * (0,0,0,B) 0 max(1-(1-a)/b,0) 0 min(a/b,1) - * (0,A,0,0) min(1,(1-b)/a) 0 max(1-b/a,0) 0 - * (0,0,B,0) 0 min(1,(1-a)/b) 0 max(1-a/b,0) - * (0,0,B,A) max(1-(1-b)/a,0) min(1,(1-a)/b) min(1,b/a) max(1-a/b,0) - * (0,A,0,B) min(1,(1-b)/a) max(1-(1-a)/b,0) max(1-b/a,0) min(1,a/b) - * (0,A,B,0) min(1,(1-b)/a) min(1,(1-a)/b) max(1-b/a,0) max(1-a/b,0) - * - * See http://marc.info/?l=xfree-render&m=99792000027857&w=2 for more - * information about these operators. - */ - -#define COMBINE_A_OUT 1 -#define COMBINE_A_IN 2 -#define COMBINE_B_OUT 4 -#define COMBINE_B_IN 8 - -#define COMBINE_CLEAR 0 -#define COMBINE_A (COMBINE_A_OUT | COMBINE_A_IN) -#define COMBINE_B (COMBINE_B_OUT | COMBINE_B_IN) -#define COMBINE_A_OVER (COMBINE_A_OUT | COMBINE_B_OUT | COMBINE_A_IN) -#define COMBINE_B_OVER (COMBINE_A_OUT | COMBINE_B_OUT | COMBINE_B_IN) -#define COMBINE_A_ATOP (COMBINE_B_OUT | COMBINE_A_IN) -#define COMBINE_B_ATOP (COMBINE_A_OUT | COMBINE_B_IN) -#define COMBINE_XOR (COMBINE_A_OUT | COMBINE_B_OUT) - -/* portion covered by a but not b */ -static comp1_t -combine_disjoint_out_part (comp1_t a, comp1_t b) -{ - /* min (1, (1-b) / a) */ - - b = ~b; /* 1 - b */ - if (b >= a) /* 1 - b >= a -> (1-b)/a >= 1 */ - return MASK; /* 1 */ - return DIV_UNc (b, a); /* (1-b) / a */ -} - -/* portion covered by both a and b */ -static comp1_t -combine_disjoint_in_part (comp1_t a, comp1_t b) -{ - /* max (1-(1-b)/a,0) */ - /* = - min ((1-b)/a - 1, 0) */ - /* = 1 - min (1, (1-b)/a) */ - - b = ~b; /* 1 - b */ - if (b >= a) /* 1 - b >= a -> (1-b)/a >= 1 */ - return 0; /* 1 - 1 */ - return ~DIV_UNc(b, a); /* 1 - (1-b) / a */ -} - -/* portion covered by a but not b */ -static comp1_t -combine_conjoint_out_part (comp1_t a, comp1_t b) -{ - /* max (1-b/a,0) */ - /* = 1-min(b/a,1) */ - - /* min (1, (1-b) / a) */ - - if (b >= a) /* b >= a -> b/a >= 1 */ - return 0x00; /* 0 */ - return ~DIV_UNc(b, a); /* 1 - b/a */ -} - -/* portion covered by both a and b */ -static comp1_t -combine_conjoint_in_part (comp1_t a, comp1_t b) -{ - /* min (1,b/a) */ - - if (b >= a) /* b >= a -> b/a >= 1 */ - return MASK; /* 1 */ - return DIV_UNc (b, a); /* b/a */ -} - -#define GET_COMP(v, i) ((comp2_t) (comp1_t) ((v) >> i)) - -#define ADD(x, y, i, t) \ - ((t) = GET_COMP (x, i) + GET_COMP (y, i), \ - (comp4_t) ((comp1_t) ((t) | (0 - ((t) >> G_SHIFT)))) << (i)) - -#define GENERIC(x, y, i, ax, ay, t, u, v) \ - ((t) = (MUL_UNc (GET_COMP (y, i), ay, (u)) + \ - MUL_UNc (GET_COMP (x, i), ax, (v))), \ - (comp4_t) ((comp1_t) ((t) | \ - (0 - ((t) >> G_SHIFT)))) << (i)) - -static void -combine_disjoint_general_u (comp4_t * dest, - const comp4_t *src, - const comp4_t *mask, - int width, - comp1_t combine) -{ - int i; - - for (i = 0; i < width; ++i) - { - comp4_t s = combine_mask (src, mask, i); - comp4_t d = *(dest + i); - comp4_t m, n, o, p; - comp2_t Fa, Fb, t, u, v; - comp1_t sa = s >> A_SHIFT; - comp1_t da = d >> A_SHIFT; - - switch (combine & COMBINE_A) - { - default: - Fa = 0; - break; - - case COMBINE_A_OUT: - Fa = combine_disjoint_out_part (sa, da); - break; - - case COMBINE_A_IN: - Fa = combine_disjoint_in_part (sa, da); - break; - - case COMBINE_A: - Fa = MASK; - break; - } - - switch (combine & COMBINE_B) - { - default: - Fb = 0; - break; - - case COMBINE_B_OUT: - Fb = combine_disjoint_out_part (da, sa); - break; - - case COMBINE_B_IN: - Fb = combine_disjoint_in_part (da, sa); - break; - - case COMBINE_B: - Fb = MASK; - break; - } - m = GENERIC (s, d, 0, Fa, Fb, t, u, v); - n = GENERIC (s, d, G_SHIFT, Fa, Fb, t, u, v); - o = GENERIC (s, d, R_SHIFT, Fa, Fb, t, u, v); - p = GENERIC (s, d, A_SHIFT, Fa, Fb, t, u, v); - s = m | n | o | p; - *(dest + i) = s; - } -} - -static void -combine_disjoint_over_u (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - int i; - - for (i = 0; i < width; ++i) - { - comp4_t s = combine_mask (src, mask, i); - comp2_t a = s >> A_SHIFT; - - if (s != 0x00) - { - comp4_t d = *(dest + i); - a = combine_disjoint_out_part (d >> A_SHIFT, a); - UNcx4_MUL_UNc_ADD_UNcx4 (d, a, s); - - *(dest + i) = d; - } - } -} - -static void -combine_disjoint_in_u (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - combine_disjoint_general_u (dest, src, mask, width, COMBINE_A_IN); -} - -static void -combine_disjoint_in_reverse_u (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - combine_disjoint_general_u (dest, src, mask, width, COMBINE_B_IN); -} - -static void -combine_disjoint_out_u (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - combine_disjoint_general_u (dest, src, mask, width, COMBINE_A_OUT); -} - -static void -combine_disjoint_out_reverse_u (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - combine_disjoint_general_u (dest, src, mask, width, COMBINE_B_OUT); -} - -static void -combine_disjoint_atop_u (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - combine_disjoint_general_u (dest, src, mask, width, COMBINE_A_ATOP); -} - -static void -combine_disjoint_atop_reverse_u (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - combine_disjoint_general_u (dest, src, mask, width, COMBINE_B_ATOP); -} - -static void -combine_disjoint_xor_u (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - combine_disjoint_general_u (dest, src, mask, width, COMBINE_XOR); -} - -static void -combine_conjoint_general_u (comp4_t * dest, - const comp4_t *src, - const comp4_t *mask, - int width, - comp1_t combine) -{ - int i; - - for (i = 0; i < width; ++i) - { - comp4_t s = combine_mask (src, mask, i); - comp4_t d = *(dest + i); - comp4_t m, n, o, p; - comp2_t Fa, Fb, t, u, v; - comp1_t sa = s >> A_SHIFT; - comp1_t da = d >> A_SHIFT; - - switch (combine & COMBINE_A) - { - default: - Fa = 0; - break; - - case COMBINE_A_OUT: - Fa = combine_conjoint_out_part (sa, da); - break; - - case COMBINE_A_IN: - Fa = combine_conjoint_in_part (sa, da); - break; - - case COMBINE_A: - Fa = MASK; - break; - } - - switch (combine & COMBINE_B) - { - default: - Fb = 0; - break; - - case COMBINE_B_OUT: - Fb = combine_conjoint_out_part (da, sa); - break; - - case COMBINE_B_IN: - Fb = combine_conjoint_in_part (da, sa); - break; - - case COMBINE_B: - Fb = MASK; - break; - } - - m = GENERIC (s, d, 0, Fa, Fb, t, u, v); - n = GENERIC (s, d, G_SHIFT, Fa, Fb, t, u, v); - o = GENERIC (s, d, R_SHIFT, Fa, Fb, t, u, v); - p = GENERIC (s, d, A_SHIFT, Fa, Fb, t, u, v); - - s = m | n | o | p; - - *(dest + i) = s; - } -} - -static void -combine_conjoint_over_u (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_OVER); -} - -static void -combine_conjoint_over_reverse_u (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_OVER); -} - -static void -combine_conjoint_in_u (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_IN); -} - -static void -combine_conjoint_in_reverse_u (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_IN); -} - -static void -combine_conjoint_out_u (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_OUT); -} - -static void -combine_conjoint_out_reverse_u (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_OUT); -} - -static void -combine_conjoint_atop_u (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_ATOP); -} - -static void -combine_conjoint_atop_reverse_u (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_ATOP); -} - -static void -combine_conjoint_xor_u (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - combine_conjoint_general_u (dest, src, mask, width, COMBINE_XOR); -} - - -/* Component alpha combiners */ - -static void -combine_clear_ca (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - memset (dest, 0, width * sizeof(comp4_t)); -} - -static void -combine_src_ca (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - int i; - - for (i = 0; i < width; ++i) - { - comp4_t s = *(src + i); - comp4_t m = *(mask + i); - - combine_mask_value_ca (&s, &m); - - *(dest + i) = s; - } -} - -static void -combine_over_ca (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - int i; - - for (i = 0; i < width; ++i) - { - comp4_t s = *(src + i); - comp4_t m = *(mask + i); - comp4_t a; - - combine_mask_ca (&s, &m); - - a = ~m; - if (a) - { - comp4_t d = *(dest + i); - UNcx4_MUL_UNcx4_ADD_UNcx4 (d, a, s); - s = d; - } - - *(dest + i) = s; - } -} - -static void -combine_over_reverse_ca (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - int i; - - for (i = 0; i < width; ++i) - { - comp4_t d = *(dest + i); - comp4_t a = ~d >> A_SHIFT; - - if (a) - { - comp4_t s = *(src + i); - comp4_t m = *(mask + i); - - UNcx4_MUL_UNcx4 (s, m); - UNcx4_MUL_UNc_ADD_UNcx4 (s, a, d); - - *(dest + i) = s; - } - } -} - -static void -combine_in_ca (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - int i; - - for (i = 0; i < width; ++i) - { - comp4_t d = *(dest + i); - comp2_t a = d >> A_SHIFT; - comp4_t s = 0; - - if (a) - { - comp4_t m = *(mask + i); - - s = *(src + i); - combine_mask_value_ca (&s, &m); - - if (a != MASK) - UNcx4_MUL_UNc (s, a); - } - - *(dest + i) = s; - } -} - -static void -combine_in_reverse_ca (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - int i; - - for (i = 0; i < width; ++i) - { - comp4_t s = *(src + i); - comp4_t m = *(mask + i); - comp4_t a; - - combine_mask_alpha_ca (&s, &m); - - a = m; - if (a != ~0) - { - comp4_t d = 0; - - if (a) - { - d = *(dest + i); - UNcx4_MUL_UNcx4 (d, a); - } - - *(dest + i) = d; - } - } -} - -static void -combine_out_ca (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - int i; - - for (i = 0; i < width; ++i) - { - comp4_t d = *(dest + i); - comp2_t a = ~d >> A_SHIFT; - comp4_t s = 0; - - if (a) - { - comp4_t m = *(mask + i); - - s = *(src + i); - combine_mask_value_ca (&s, &m); - - if (a != MASK) - UNcx4_MUL_UNc (s, a); - } - - *(dest + i) = s; - } -} - -static void -combine_out_reverse_ca (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - int i; - - for (i = 0; i < width; ++i) - { - comp4_t s = *(src + i); - comp4_t m = *(mask + i); - comp4_t a; - - combine_mask_alpha_ca (&s, &m); - - a = ~m; - if (a != ~0) - { - comp4_t d = 0; - - if (a) - { - d = *(dest + i); - UNcx4_MUL_UNcx4 (d, a); - } - - *(dest + i) = d; - } - } -} - -static void -combine_atop_ca (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - int i; - - for (i = 0; i < width; ++i) - { - comp4_t d = *(dest + i); - comp4_t s = *(src + i); - comp4_t m = *(mask + i); - comp4_t ad; - comp2_t as = d >> A_SHIFT; - - combine_mask_ca (&s, &m); - - ad = ~m; - - UNcx4_MUL_UNcx4_ADD_UNcx4_MUL_UNc (d, ad, s, as); - - *(dest + i) = d; - } -} - -static void -combine_atop_reverse_ca (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - int i; - - for (i = 0; i < width; ++i) - { - comp4_t d = *(dest + i); - comp4_t s = *(src + i); - comp4_t m = *(mask + i); - comp4_t ad; - comp2_t as = ~d >> A_SHIFT; - - combine_mask_ca (&s, &m); - - ad = m; - - UNcx4_MUL_UNcx4_ADD_UNcx4_MUL_UNc (d, ad, s, as); - - *(dest + i) = d; - } -} - -static void -combine_xor_ca (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - int i; - - for (i = 0; i < width; ++i) - { - comp4_t d = *(dest + i); - comp4_t s = *(src + i); - comp4_t m = *(mask + i); - comp4_t ad; - comp2_t as = ~d >> A_SHIFT; - - combine_mask_ca (&s, &m); - - ad = ~m; - - UNcx4_MUL_UNcx4_ADD_UNcx4_MUL_UNc (d, ad, s, as); - - *(dest + i) = d; - } -} - -static void -combine_add_ca (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - int i; - - for (i = 0; i < width; ++i) - { - comp4_t s = *(src + i); - comp4_t m = *(mask + i); - comp4_t d = *(dest + i); - - combine_mask_value_ca (&s, &m); - - UNcx4_ADD_UNcx4 (d, s); - - *(dest + i) = d; - } -} - -static void -combine_saturate_ca (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - int i; - - for (i = 0; i < width; ++i) - { - comp4_t s, d; - comp2_t sa, sr, sg, sb, da; - comp2_t t, u, v; - comp4_t m, n, o, p; - - d = *(dest + i); - s = *(src + i); - m = *(mask + i); - - combine_mask_ca (&s, &m); - - sa = (m >> A_SHIFT); - sr = (m >> R_SHIFT) & MASK; - sg = (m >> G_SHIFT) & MASK; - sb = m & MASK; - da = ~d >> A_SHIFT; - - if (sb <= da) - m = ADD (s, d, 0, t); - else - m = GENERIC (s, d, 0, (da << G_SHIFT) / sb, MASK, t, u, v); - - if (sg <= da) - n = ADD (s, d, G_SHIFT, t); - else - n = GENERIC (s, d, G_SHIFT, (da << G_SHIFT) / sg, MASK, t, u, v); - - if (sr <= da) - o = ADD (s, d, R_SHIFT, t); - else - o = GENERIC (s, d, R_SHIFT, (da << G_SHIFT) / sr, MASK, t, u, v); - - if (sa <= da) - p = ADD (s, d, A_SHIFT, t); - else - p = GENERIC (s, d, A_SHIFT, (da << G_SHIFT) / sa, MASK, t, u, v); - - *(dest + i) = m | n | o | p; - } -} - -static void -combine_disjoint_general_ca (comp4_t * dest, - const comp4_t *src, - const comp4_t *mask, - int width, - comp1_t combine) -{ - int i; - - for (i = 0; i < width; ++i) - { - comp4_t s, d; - comp4_t m, n, o, p; - comp4_t Fa, Fb; - comp2_t t, u, v; - comp4_t sa; - comp1_t da; - - s = *(src + i); - m = *(mask + i); - d = *(dest + i); - da = d >> A_SHIFT; - - combine_mask_ca (&s, &m); - - sa = m; - - switch (combine & COMBINE_A) - { - default: - Fa = 0; - break; - - case COMBINE_A_OUT: - m = (comp4_t)combine_disjoint_out_part ((comp1_t) (sa >> 0), da); - n = (comp4_t)combine_disjoint_out_part ((comp1_t) (sa >> G_SHIFT), da) << G_SHIFT; - o = (comp4_t)combine_disjoint_out_part ((comp1_t) (sa >> R_SHIFT), da) << R_SHIFT; - p = (comp4_t)combine_disjoint_out_part ((comp1_t) (sa >> A_SHIFT), da) << A_SHIFT; - Fa = m | n | o | p; - break; - - case COMBINE_A_IN: - m = (comp4_t)combine_disjoint_in_part ((comp1_t) (sa >> 0), da); - n = (comp4_t)combine_disjoint_in_part ((comp1_t) (sa >> G_SHIFT), da) << G_SHIFT; - o = (comp4_t)combine_disjoint_in_part ((comp1_t) (sa >> R_SHIFT), da) << R_SHIFT; - p = (comp4_t)combine_disjoint_in_part ((comp1_t) (sa >> A_SHIFT), da) << A_SHIFT; - Fa = m | n | o | p; - break; - - case COMBINE_A: - Fa = ~0; - break; - } - - switch (combine & COMBINE_B) - { - default: - Fb = 0; - break; - - case COMBINE_B_OUT: - m = (comp4_t)combine_disjoint_out_part (da, (comp1_t) (sa >> 0)); - n = (comp4_t)combine_disjoint_out_part (da, (comp1_t) (sa >> G_SHIFT)) << G_SHIFT; - o = (comp4_t)combine_disjoint_out_part (da, (comp1_t) (sa >> R_SHIFT)) << R_SHIFT; - p = (comp4_t)combine_disjoint_out_part (da, (comp1_t) (sa >> A_SHIFT)) << A_SHIFT; - Fb = m | n | o | p; - break; - - case COMBINE_B_IN: - m = (comp4_t)combine_disjoint_in_part (da, (comp1_t) (sa >> 0)); - n = (comp4_t)combine_disjoint_in_part (da, (comp1_t) (sa >> G_SHIFT)) << G_SHIFT; - o = (comp4_t)combine_disjoint_in_part (da, (comp1_t) (sa >> R_SHIFT)) << R_SHIFT; - p = (comp4_t)combine_disjoint_in_part (da, (comp1_t) (sa >> A_SHIFT)) << A_SHIFT; - Fb = m | n | o | p; - break; - - case COMBINE_B: - Fb = ~0; - break; - } - m = GENERIC (s, d, 0, GET_COMP (Fa, 0), GET_COMP (Fb, 0), t, u, v); - n = GENERIC (s, d, G_SHIFT, GET_COMP (Fa, G_SHIFT), GET_COMP (Fb, G_SHIFT), t, u, v); - o = GENERIC (s, d, R_SHIFT, GET_COMP (Fa, R_SHIFT), GET_COMP (Fb, R_SHIFT), t, u, v); - p = GENERIC (s, d, A_SHIFT, GET_COMP (Fa, A_SHIFT), GET_COMP (Fb, A_SHIFT), t, u, v); - - s = m | n | o | p; - - *(dest + i) = s; - } -} - -static void -combine_disjoint_over_ca (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_OVER); -} - -static void -combine_disjoint_in_ca (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_IN); -} - -static void -combine_disjoint_in_reverse_ca (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - combine_disjoint_general_ca (dest, src, mask, width, COMBINE_B_IN); -} - -static void -combine_disjoint_out_ca (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_OUT); -} - -static void -combine_disjoint_out_reverse_ca (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - combine_disjoint_general_ca (dest, src, mask, width, COMBINE_B_OUT); -} - -static void -combine_disjoint_atop_ca (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_ATOP); -} - -static void -combine_disjoint_atop_reverse_ca (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - combine_disjoint_general_ca (dest, src, mask, width, COMBINE_B_ATOP); -} - -static void -combine_disjoint_xor_ca (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - combine_disjoint_general_ca (dest, src, mask, width, COMBINE_XOR); -} - -static void -combine_conjoint_general_ca (comp4_t * dest, - const comp4_t *src, - const comp4_t *mask, - int width, - comp1_t combine) -{ - int i; - - for (i = 0; i < width; ++i) - { - comp4_t s, d; - comp4_t m, n, o, p; - comp4_t Fa, Fb; - comp2_t t, u, v; - comp4_t sa; - comp1_t da; - - s = *(src + i); - m = *(mask + i); - d = *(dest + i); - da = d >> A_SHIFT; - - combine_mask_ca (&s, &m); - - sa = m; - - switch (combine & COMBINE_A) - { - default: - Fa = 0; - break; - - case COMBINE_A_OUT: - m = (comp4_t)combine_conjoint_out_part ((comp1_t) (sa >> 0), da); - n = (comp4_t)combine_conjoint_out_part ((comp1_t) (sa >> G_SHIFT), da) << G_SHIFT; - o = (comp4_t)combine_conjoint_out_part ((comp1_t) (sa >> R_SHIFT), da) << R_SHIFT; - p = (comp4_t)combine_conjoint_out_part ((comp1_t) (sa >> A_SHIFT), da) << A_SHIFT; - Fa = m | n | o | p; - break; - - case COMBINE_A_IN: - m = (comp4_t)combine_conjoint_in_part ((comp1_t) (sa >> 0), da); - n = (comp4_t)combine_conjoint_in_part ((comp1_t) (sa >> G_SHIFT), da) << G_SHIFT; - o = (comp4_t)combine_conjoint_in_part ((comp1_t) (sa >> R_SHIFT), da) << R_SHIFT; - p = (comp4_t)combine_conjoint_in_part ((comp1_t) (sa >> A_SHIFT), da) << A_SHIFT; - Fa = m | n | o | p; - break; - - case COMBINE_A: - Fa = ~0; - break; - } - - switch (combine & COMBINE_B) - { - default: - Fb = 0; - break; - - case COMBINE_B_OUT: - m = (comp4_t)combine_conjoint_out_part (da, (comp1_t) (sa >> 0)); - n = (comp4_t)combine_conjoint_out_part (da, (comp1_t) (sa >> G_SHIFT)) << G_SHIFT; - o = (comp4_t)combine_conjoint_out_part (da, (comp1_t) (sa >> R_SHIFT)) << R_SHIFT; - p = (comp4_t)combine_conjoint_out_part (da, (comp1_t) (sa >> A_SHIFT)) << A_SHIFT; - Fb = m | n | o | p; - break; - - case COMBINE_B_IN: - m = (comp4_t)combine_conjoint_in_part (da, (comp1_t) (sa >> 0)); - n = (comp4_t)combine_conjoint_in_part (da, (comp1_t) (sa >> G_SHIFT)) << G_SHIFT; - o = (comp4_t)combine_conjoint_in_part (da, (comp1_t) (sa >> R_SHIFT)) << R_SHIFT; - p = (comp4_t)combine_conjoint_in_part (da, (comp1_t) (sa >> A_SHIFT)) << A_SHIFT; - Fb = m | n | o | p; - break; - - case COMBINE_B: - Fb = ~0; - break; - } - m = GENERIC (s, d, 0, GET_COMP (Fa, 0), GET_COMP (Fb, 0), t, u, v); - n = GENERIC (s, d, G_SHIFT, GET_COMP (Fa, G_SHIFT), GET_COMP (Fb, G_SHIFT), t, u, v); - o = GENERIC (s, d, R_SHIFT, GET_COMP (Fa, R_SHIFT), GET_COMP (Fb, R_SHIFT), t, u, v); - p = GENERIC (s, d, A_SHIFT, GET_COMP (Fa, A_SHIFT), GET_COMP (Fb, A_SHIFT), t, u, v); - - s = m | n | o | p; - - *(dest + i) = s; - } -} - -static void -combine_conjoint_over_ca (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_OVER); -} - -static void -combine_conjoint_over_reverse_ca (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_OVER); -} - -static void -combine_conjoint_in_ca (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_IN); -} - -static void -combine_conjoint_in_reverse_ca (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_IN); -} - -static void -combine_conjoint_out_ca (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_OUT); -} - -static void -combine_conjoint_out_reverse_ca (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_OUT); -} - -static void -combine_conjoint_atop_ca (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_ATOP); -} - -static void -combine_conjoint_atop_reverse_ca (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_ATOP); -} - -static void -combine_conjoint_xor_ca (pixman_implementation_t *imp, - pixman_op_t op, - comp4_t * dest, - const comp4_t * src, - const comp4_t * mask, - int width) -{ - combine_conjoint_general_ca (dest, src, mask, width, COMBINE_XOR); -} - -void -_pixman_setup_combiner_functions_width (pixman_implementation_t *imp) -{ - /* Unified alpha */ - imp->combine_width[PIXMAN_OP_CLEAR] = combine_clear; - imp->combine_width[PIXMAN_OP_SRC] = combine_src_u; - imp->combine_width[PIXMAN_OP_DST] = combine_dst; - imp->combine_width[PIXMAN_OP_OVER] = combine_over_u; - imp->combine_width[PIXMAN_OP_OVER_REVERSE] = combine_over_reverse_u; - imp->combine_width[PIXMAN_OP_IN] = combine_in_u; - imp->combine_width[PIXMAN_OP_IN_REVERSE] = combine_in_reverse_u; - imp->combine_width[PIXMAN_OP_OUT] = combine_out_u; - imp->combine_width[PIXMAN_OP_OUT_REVERSE] = combine_out_reverse_u; - imp->combine_width[PIXMAN_OP_ATOP] = combine_atop_u; - imp->combine_width[PIXMAN_OP_ATOP_REVERSE] = combine_atop_reverse_u; - imp->combine_width[PIXMAN_OP_XOR] = combine_xor_u; - imp->combine_width[PIXMAN_OP_ADD] = combine_add_u; - imp->combine_width[PIXMAN_OP_SATURATE] = combine_saturate_u; - - /* Disjoint, unified */ - imp->combine_width[PIXMAN_OP_DISJOINT_CLEAR] = combine_clear; - imp->combine_width[PIXMAN_OP_DISJOINT_SRC] = combine_src_u; - imp->combine_width[PIXMAN_OP_DISJOINT_DST] = combine_dst; - imp->combine_width[PIXMAN_OP_DISJOINT_OVER] = combine_disjoint_over_u; - imp->combine_width[PIXMAN_OP_DISJOINT_OVER_REVERSE] = combine_saturate_u; - imp->combine_width[PIXMAN_OP_DISJOINT_IN] = combine_disjoint_in_u; - imp->combine_width[PIXMAN_OP_DISJOINT_IN_REVERSE] = combine_disjoint_in_reverse_u; - imp->combine_width[PIXMAN_OP_DISJOINT_OUT] = combine_disjoint_out_u; - imp->combine_width[PIXMAN_OP_DISJOINT_OUT_REVERSE] = combine_disjoint_out_reverse_u; - imp->combine_width[PIXMAN_OP_DISJOINT_ATOP] = combine_disjoint_atop_u; - imp->combine_width[PIXMAN_OP_DISJOINT_ATOP_REVERSE] = combine_disjoint_atop_reverse_u; - imp->combine_width[PIXMAN_OP_DISJOINT_XOR] = combine_disjoint_xor_u; - - /* Conjoint, unified */ - imp->combine_width[PIXMAN_OP_CONJOINT_CLEAR] = combine_clear; - imp->combine_width[PIXMAN_OP_CONJOINT_SRC] = combine_src_u; - imp->combine_width[PIXMAN_OP_CONJOINT_DST] = combine_dst; - imp->combine_width[PIXMAN_OP_CONJOINT_OVER] = combine_conjoint_over_u; - imp->combine_width[PIXMAN_OP_CONJOINT_OVER_REVERSE] = combine_conjoint_over_reverse_u; - imp->combine_width[PIXMAN_OP_CONJOINT_IN] = combine_conjoint_in_u; - imp->combine_width[PIXMAN_OP_CONJOINT_IN_REVERSE] = combine_conjoint_in_reverse_u; - imp->combine_width[PIXMAN_OP_CONJOINT_OUT] = combine_conjoint_out_u; - imp->combine_width[PIXMAN_OP_CONJOINT_OUT_REVERSE] = combine_conjoint_out_reverse_u; - imp->combine_width[PIXMAN_OP_CONJOINT_ATOP] = combine_conjoint_atop_u; - imp->combine_width[PIXMAN_OP_CONJOINT_ATOP_REVERSE] = combine_conjoint_atop_reverse_u; - imp->combine_width[PIXMAN_OP_CONJOINT_XOR] = combine_conjoint_xor_u; - - imp->combine_width[PIXMAN_OP_MULTIPLY] = combine_multiply_u; - imp->combine_width[PIXMAN_OP_SCREEN] = combine_screen_u; - imp->combine_width[PIXMAN_OP_OVERLAY] = combine_overlay_u; - imp->combine_width[PIXMAN_OP_DARKEN] = combine_darken_u; - imp->combine_width[PIXMAN_OP_LIGHTEN] = combine_lighten_u; - imp->combine_width[PIXMAN_OP_COLOR_DODGE] = combine_color_dodge_u; - imp->combine_width[PIXMAN_OP_COLOR_BURN] = combine_color_burn_u; - imp->combine_width[PIXMAN_OP_HARD_LIGHT] = combine_hard_light_u; - imp->combine_width[PIXMAN_OP_SOFT_LIGHT] = combine_soft_light_u; - imp->combine_width[PIXMAN_OP_DIFFERENCE] = combine_difference_u; - imp->combine_width[PIXMAN_OP_EXCLUSION] = combine_exclusion_u; - imp->combine_width[PIXMAN_OP_HSL_HUE] = combine_hsl_hue_u; - imp->combine_width[PIXMAN_OP_HSL_SATURATION] = combine_hsl_saturation_u; - imp->combine_width[PIXMAN_OP_HSL_COLOR] = combine_hsl_color_u; - imp->combine_width[PIXMAN_OP_HSL_LUMINOSITY] = combine_hsl_luminosity_u; - - /* Component alpha combiners */ - imp->combine_width_ca[PIXMAN_OP_CLEAR] = combine_clear_ca; - imp->combine_width_ca[PIXMAN_OP_SRC] = combine_src_ca; - /* dest */ - imp->combine_width_ca[PIXMAN_OP_OVER] = combine_over_ca; - imp->combine_width_ca[PIXMAN_OP_OVER_REVERSE] = combine_over_reverse_ca; - imp->combine_width_ca[PIXMAN_OP_IN] = combine_in_ca; - imp->combine_width_ca[PIXMAN_OP_IN_REVERSE] = combine_in_reverse_ca; - imp->combine_width_ca[PIXMAN_OP_OUT] = combine_out_ca; - imp->combine_width_ca[PIXMAN_OP_OUT_REVERSE] = combine_out_reverse_ca; - imp->combine_width_ca[PIXMAN_OP_ATOP] = combine_atop_ca; - imp->combine_width_ca[PIXMAN_OP_ATOP_REVERSE] = combine_atop_reverse_ca; - imp->combine_width_ca[PIXMAN_OP_XOR] = combine_xor_ca; - imp->combine_width_ca[PIXMAN_OP_ADD] = combine_add_ca; - imp->combine_width_ca[PIXMAN_OP_SATURATE] = combine_saturate_ca; - - /* Disjoint CA */ - imp->combine_width_ca[PIXMAN_OP_DISJOINT_CLEAR] = combine_clear_ca; - imp->combine_width_ca[PIXMAN_OP_DISJOINT_SRC] = combine_src_ca; - imp->combine_width_ca[PIXMAN_OP_DISJOINT_DST] = combine_dst; - imp->combine_width_ca[PIXMAN_OP_DISJOINT_OVER] = combine_disjoint_over_ca; - imp->combine_width_ca[PIXMAN_OP_DISJOINT_OVER_REVERSE] = combine_saturate_ca; - imp->combine_width_ca[PIXMAN_OP_DISJOINT_IN] = combine_disjoint_in_ca; - imp->combine_width_ca[PIXMAN_OP_DISJOINT_IN_REVERSE] = combine_disjoint_in_reverse_ca; - imp->combine_width_ca[PIXMAN_OP_DISJOINT_OUT] = combine_disjoint_out_ca; - imp->combine_width_ca[PIXMAN_OP_DISJOINT_OUT_REVERSE] = combine_disjoint_out_reverse_ca; - imp->combine_width_ca[PIXMAN_OP_DISJOINT_ATOP] = combine_disjoint_atop_ca; - imp->combine_width_ca[PIXMAN_OP_DISJOINT_ATOP_REVERSE] = combine_disjoint_atop_reverse_ca; - imp->combine_width_ca[PIXMAN_OP_DISJOINT_XOR] = combine_disjoint_xor_ca; - - /* Conjoint CA */ - imp->combine_width_ca[PIXMAN_OP_CONJOINT_CLEAR] = combine_clear_ca; - imp->combine_width_ca[PIXMAN_OP_CONJOINT_SRC] = combine_src_ca; - imp->combine_width_ca[PIXMAN_OP_CONJOINT_DST] = combine_dst; - imp->combine_width_ca[PIXMAN_OP_CONJOINT_OVER] = combine_conjoint_over_ca; - imp->combine_width_ca[PIXMAN_OP_CONJOINT_OVER_REVERSE] = combine_conjoint_over_reverse_ca; - imp->combine_width_ca[PIXMAN_OP_CONJOINT_IN] = combine_conjoint_in_ca; - imp->combine_width_ca[PIXMAN_OP_CONJOINT_IN_REVERSE] = combine_conjoint_in_reverse_ca; - imp->combine_width_ca[PIXMAN_OP_CONJOINT_OUT] = combine_conjoint_out_ca; - imp->combine_width_ca[PIXMAN_OP_CONJOINT_OUT_REVERSE] = combine_conjoint_out_reverse_ca; - imp->combine_width_ca[PIXMAN_OP_CONJOINT_ATOP] = combine_conjoint_atop_ca; - imp->combine_width_ca[PIXMAN_OP_CONJOINT_ATOP_REVERSE] = combine_conjoint_atop_reverse_ca; - imp->combine_width_ca[PIXMAN_OP_CONJOINT_XOR] = combine_conjoint_xor_ca; - - imp->combine_width_ca[PIXMAN_OP_MULTIPLY] = combine_multiply_ca; - imp->combine_width_ca[PIXMAN_OP_SCREEN] = combine_screen_ca; - imp->combine_width_ca[PIXMAN_OP_OVERLAY] = combine_overlay_ca; - imp->combine_width_ca[PIXMAN_OP_DARKEN] = combine_darken_ca; - imp->combine_width_ca[PIXMAN_OP_LIGHTEN] = combine_lighten_ca; - imp->combine_width_ca[PIXMAN_OP_COLOR_DODGE] = combine_color_dodge_ca; - imp->combine_width_ca[PIXMAN_OP_COLOR_BURN] = combine_color_burn_ca; - imp->combine_width_ca[PIXMAN_OP_HARD_LIGHT] = combine_hard_light_ca; - imp->combine_width_ca[PIXMAN_OP_SOFT_LIGHT] = combine_soft_light_ca; - imp->combine_width_ca[PIXMAN_OP_DIFFERENCE] = combine_difference_ca; - imp->combine_width_ca[PIXMAN_OP_EXCLUSION] = combine_exclusion_ca; - - /* It is not clear that these make sense, so make them noops for now */ - imp->combine_width_ca[PIXMAN_OP_HSL_HUE] = combine_dst; - imp->combine_width_ca[PIXMAN_OP_HSL_SATURATION] = combine_dst; - imp->combine_width_ca[PIXMAN_OP_HSL_COLOR] = combine_dst; - imp->combine_width_ca[PIXMAN_OP_HSL_LUMINOSITY] = combine_dst; -} diff --git a/pixman/pixman/pixman-combine.h.template b/pixman/pixman/pixman-combine.h.template deleted file mode 100644 index 20f784b5b..000000000 --- a/pixman/pixman/pixman-combine.h.template +++ /dev/null @@ -1,226 +0,0 @@ - -#define COMPONENT_SIZE -#define MASK -#define ONE_HALF - -#define A_SHIFT -#define R_SHIFT -#define G_SHIFT -#define A_MASK -#define R_MASK -#define G_MASK - -#define RB_MASK -#define AG_MASK -#define RB_ONE_HALF -#define RB_MASK_PLUS_ONE - -#define ALPHA_c(x) ((x) >> A_SHIFT) -#define RED_c(x) (((x) >> R_SHIFT) & MASK) -#define GREEN_c(x) (((x) >> G_SHIFT) & MASK) -#define BLUE_c(x) ((x) & MASK) - -/* - * Helper macros. - */ - -#define MUL_UNc(a, b, t) \ - ((t) = (a) * (comp2_t)(b) + ONE_HALF, ((((t) >> G_SHIFT ) + (t) ) >> G_SHIFT )) - -#define DIV_UNc(a, b) \ - (((comp2_t) (a) * MASK + ((b) / 2)) / (b)) - -#define ADD_UNc(x, y, t) \ - ((t) = (x) + (y), \ - (comp4_t) (comp1_t) ((t) | (0 - ((t) >> G_SHIFT)))) - -#define DIV_ONE_UNc(x) \ - (((x) + ONE_HALF + (((x) + ONE_HALF) >> G_SHIFT)) >> G_SHIFT) - -/* - * The methods below use some tricks to be able to do two color - * components at the same time. - */ - -/* - * x_rb = (x_rb * a) / 255 - */ -#define UNc_rb_MUL_UNc(x, a, t) \ - do \ - { \ - t = ((x) & RB_MASK) * (a); \ - t += RB_ONE_HALF; \ - x = (t + ((t >> G_SHIFT) & RB_MASK)) >> G_SHIFT; \ - x &= RB_MASK; \ - } while (0) - -/* - * x_rb = min (x_rb + y_rb, 255) - */ -#define UNc_rb_ADD_UNc_rb(x, y, t) \ - do \ - { \ - t = ((x) + (y)); \ - t |= RB_MASK_PLUS_ONE - ((t >> G_SHIFT) & RB_MASK); \ - x = (t & RB_MASK); \ - } while (0) - -/* - * x_rb = (x_rb * a_rb) / 255 - */ -#define UNc_rb_MUL_UNc_rb(x, a, t) \ - do \ - { \ - t = (x & MASK) * (a & MASK); \ - t |= (x & R_MASK) * ((a >> R_SHIFT) & MASK); \ - t += RB_ONE_HALF; \ - t = (t + ((t >> G_SHIFT) & RB_MASK)) >> G_SHIFT; \ - x = t & RB_MASK; \ - } while (0) - -/* - * x_c = (x_c * a) / 255 - */ -#define UNcx4_MUL_UNc(x, a) \ - do \ - { \ - comp4_t r1__, r2__, t__; \ - \ - r1__ = (x); \ - UNc_rb_MUL_UNc (r1__, (a), t__); \ - \ - r2__ = (x) >> G_SHIFT; \ - UNc_rb_MUL_UNc (r2__, (a), t__); \ - \ - (x) = r1__ | (r2__ << G_SHIFT); \ - } while (0) - -/* - * x_c = (x_c * a) / 255 + y_c - */ -#define UNcx4_MUL_UNc_ADD_UNcx4(x, a, y) \ - do \ - { \ - comp4_t r1__, r2__, r3__, t__; \ - \ - r1__ = (x); \ - r2__ = (y) & RB_MASK; \ - UNc_rb_MUL_UNc (r1__, (a), t__); \ - UNc_rb_ADD_UNc_rb (r1__, r2__, t__); \ - \ - r2__ = (x) >> G_SHIFT; \ - r3__ = ((y) >> G_SHIFT) & RB_MASK; \ - UNc_rb_MUL_UNc (r2__, (a), t__); \ - UNc_rb_ADD_UNc_rb (r2__, r3__, t__); \ - \ - (x) = r1__ | (r2__ << G_SHIFT); \ - } while (0) - -/* - * x_c = (x_c * a + y_c * b) / 255 - */ -#define UNcx4_MUL_UNc_ADD_UNcx4_MUL_UNc(x, a, y, b) \ - do \ - { \ - comp4_t r1__, r2__, r3__, t__; \ - \ - r1__ = (x); \ - r2__ = (y); \ - UNc_rb_MUL_UNc (r1__, (a), t__); \ - UNc_rb_MUL_UNc (r2__, (b), t__); \ - UNc_rb_ADD_UNc_rb (r1__, r2__, t__); \ - \ - r2__ = ((x) >> G_SHIFT); \ - r3__ = ((y) >> G_SHIFT); \ - UNc_rb_MUL_UNc (r2__, (a), t__); \ - UNc_rb_MUL_UNc (r3__, (b), t__); \ - UNc_rb_ADD_UNc_rb (r2__, r3__, t__); \ - \ - (x) = r1__ | (r2__ << G_SHIFT); \ - } while (0) - -/* - * x_c = (x_c * a_c) / 255 - */ -#define UNcx4_MUL_UNcx4(x, a) \ - do \ - { \ - comp4_t r1__, r2__, r3__, t__; \ - \ - r1__ = (x); \ - r2__ = (a); \ - UNc_rb_MUL_UNc_rb (r1__, r2__, t__); \ - \ - r2__ = (x) >> G_SHIFT; \ - r3__ = (a) >> G_SHIFT; \ - UNc_rb_MUL_UNc_rb (r2__, r3__, t__); \ - \ - (x) = r1__ | (r2__ << G_SHIFT); \ - } while (0) - -/* - * x_c = (x_c * a_c) / 255 + y_c - */ -#define UNcx4_MUL_UNcx4_ADD_UNcx4(x, a, y) \ - do \ - { \ - comp4_t r1__, r2__, r3__, t__; \ - \ - r1__ = (x); \ - r2__ = (a); \ - UNc_rb_MUL_UNc_rb (r1__, r2__, t__); \ - r2__ = (y) & RB_MASK; \ - UNc_rb_ADD_UNc_rb (r1__, r2__, t__); \ - \ - r2__ = ((x) >> G_SHIFT); \ - r3__ = ((a) >> G_SHIFT); \ - UNc_rb_MUL_UNc_rb (r2__, r3__, t__); \ - r3__ = ((y) >> G_SHIFT) & RB_MASK; \ - UNc_rb_ADD_UNc_rb (r2__, r3__, t__); \ - \ - (x) = r1__ | (r2__ << G_SHIFT); \ - } while (0) - -/* - * x_c = (x_c * a_c + y_c * b) / 255 - */ -#define UNcx4_MUL_UNcx4_ADD_UNcx4_MUL_UNc(x, a, y, b) \ - do \ - { \ - comp4_t r1__, r2__, r3__, t__; \ - \ - r1__ = (x); \ - r2__ = (a); \ - UNc_rb_MUL_UNc_rb (r1__, r2__, t__); \ - r2__ = (y); \ - UNc_rb_MUL_UNc (r2__, (b), t__); \ - UNc_rb_ADD_UNc_rb (r1__, r2__, t__); \ - \ - r2__ = (x) >> G_SHIFT; \ - r3__ = (a) >> G_SHIFT; \ - UNc_rb_MUL_UNc_rb (r2__, r3__, t__); \ - r3__ = (y) >> G_SHIFT; \ - UNc_rb_MUL_UNc (r3__, (b), t__); \ - UNc_rb_ADD_UNc_rb (r2__, r3__, t__); \ - \ - x = r1__ | (r2__ << G_SHIFT); \ - } while (0) - -/* - x_c = min(x_c + y_c, 255) -*/ -#define UNcx4_ADD_UNcx4(x, y) \ - do \ - { \ - comp4_t r1__, r2__, r3__, t__; \ - \ - r1__ = (x) & RB_MASK; \ - r2__ = (y) & RB_MASK; \ - UNc_rb_ADD_UNc_rb (r1__, r2__, t__); \ - \ - r2__ = ((x) >> G_SHIFT) & RB_MASK; \ - r3__ = ((y) >> G_SHIFT) & RB_MASK; \ - UNc_rb_ADD_UNc_rb (r2__, r3__, t__); \ - \ - x = r1__ | (r2__ << G_SHIFT); \ - } while (0) diff --git a/pixman/pixman/pixman-combine32.c b/pixman/pixman/pixman-combine32.c new file mode 100644 index 000000000..54cc8771b --- /dev/null +++ b/pixman/pixman/pixman-combine32.c @@ -0,0 +1,2460 @@ +/* + * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc. + * 2005 Lars Knoll & Zack Rusin, Trolltech + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "pixman-private.h" +#include "pixman-combine32.h" + +/* component alpha helper functions */ + +static void +combine_mask_ca (uint32_t *src, uint32_t *mask) +{ + uint32_t a = *mask; + + uint32_t x; + uint16_t xa; + + if (!a) + { + *(src) = 0; + return; + } + + x = *(src); + if (a == ~0) + { + x = x >> A_SHIFT; + x |= x << G_SHIFT; + x |= x << R_SHIFT; + *(mask) = x; + return; + } + + xa = x >> A_SHIFT; + UN8x4_MUL_UN8x4 (x, a); + *(src) = x; + + UN8x4_MUL_UN8 (a, xa); + *(mask) = a; +} + +static void +combine_mask_value_ca (uint32_t *src, const uint32_t *mask) +{ + uint32_t a = *mask; + uint32_t x; + + if (!a) + { + *(src) = 0; + return; + } + + if (a == ~0) + return; + + x = *(src); + UN8x4_MUL_UN8x4 (x, a); + *(src) = x; +} + +static void +combine_mask_alpha_ca (const uint32_t *src, uint32_t *mask) +{ + uint32_t a = *(mask); + uint32_t x; + + if (!a) + return; + + x = *(src) >> A_SHIFT; + if (x == MASK) + return; + + if (a == ~0) + { + x |= x << G_SHIFT; + x |= x << R_SHIFT; + *(mask) = x; + return; + } + + UN8x4_MUL_UN8 (a, x); + *(mask) = a; +} + +/* + * There are two ways of handling alpha -- either as a single unified value or + * a separate value for each component, hence each macro must have two + * versions. The unified alpha version has a 'u' at the end of the name, + * the component version has a 'ca'. Similarly, functions which deal with + * this difference will have two versions using the same convention. + */ + +static force_inline uint32_t +combine_mask (const uint32_t *src, const uint32_t *mask, int i) +{ + uint32_t s, m; + + if (mask) + { + m = *(mask + i) >> A_SHIFT; + + if (!m) + return 0; + } + + s = *(src + i); + + if (mask) + UN8x4_MUL_UN8 (s, m); + + return s; +} + +static void +combine_clear (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + memset (dest, 0, width * sizeof(uint32_t)); +} + +static void +combine_dst (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + return; +} + +static void +combine_src_u (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + int i; + + if (!mask) + { + memcpy (dest, src, width * sizeof (uint32_t)); + } + else + { + for (i = 0; i < width; ++i) + { + uint32_t s = combine_mask (src, mask, i); + + *(dest + i) = s; + } + } +} + +static void +combine_over_u (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + int i; + + for (i = 0; i < width; ++i) + { + uint32_t s = combine_mask (src, mask, i); + uint32_t d = *(dest + i); + uint32_t ia = ALPHA_8 (~s); + + UN8x4_MUL_UN8_ADD_UN8x4 (d, ia, s); + *(dest + i) = d; + } +} + +static void +combine_over_reverse_u (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + int i; + + for (i = 0; i < width; ++i) + { + uint32_t s = combine_mask (src, mask, i); + uint32_t d = *(dest + i); + uint32_t ia = ALPHA_8 (~*(dest + i)); + UN8x4_MUL_UN8_ADD_UN8x4 (s, ia, d); + *(dest + i) = s; + } +} + +static void +combine_in_u (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + int i; + + for (i = 0; i < width; ++i) + { + uint32_t s = combine_mask (src, mask, i); + uint32_t a = ALPHA_8 (*(dest + i)); + UN8x4_MUL_UN8 (s, a); + *(dest + i) = s; + } +} + +static void +combine_in_reverse_u (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + int i; + + for (i = 0; i < width; ++i) + { + uint32_t s = combine_mask (src, mask, i); + uint32_t d = *(dest + i); + uint32_t a = ALPHA_8 (s); + UN8x4_MUL_UN8 (d, a); + *(dest + i) = d; + } +} + +static void +combine_out_u (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + int i; + + for (i = 0; i < width; ++i) + { + uint32_t s = combine_mask (src, mask, i); + uint32_t a = ALPHA_8 (~*(dest + i)); + UN8x4_MUL_UN8 (s, a); + *(dest + i) = s; + } +} + +static void +combine_out_reverse_u (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + int i; + + for (i = 0; i < width; ++i) + { + uint32_t s = combine_mask (src, mask, i); + uint32_t d = *(dest + i); + uint32_t a = ALPHA_8 (~s); + UN8x4_MUL_UN8 (d, a); + *(dest + i) = d; + } +} + +static void +combine_atop_u (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + int i; + + for (i = 0; i < width; ++i) + { + uint32_t s = combine_mask (src, mask, i); + uint32_t d = *(dest + i); + uint32_t dest_a = ALPHA_8 (d); + uint32_t src_ia = ALPHA_8 (~s); + + UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (s, dest_a, d, src_ia); + *(dest + i) = s; + } +} + +static void +combine_atop_reverse_u (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + int i; + + for (i = 0; i < width; ++i) + { + uint32_t s = combine_mask (src, mask, i); + uint32_t d = *(dest + i); + uint32_t src_a = ALPHA_8 (s); + uint32_t dest_ia = ALPHA_8 (~d); + + UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (s, dest_ia, d, src_a); + *(dest + i) = s; + } +} + +static void +combine_xor_u (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + int i; + + for (i = 0; i < width; ++i) + { + uint32_t s = combine_mask (src, mask, i); + uint32_t d = *(dest + i); + uint32_t src_ia = ALPHA_8 (~s); + uint32_t dest_ia = ALPHA_8 (~d); + + UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (s, dest_ia, d, src_ia); + *(dest + i) = s; + } +} + +static void +combine_add_u (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + int i; + + for (i = 0; i < width; ++i) + { + uint32_t s = combine_mask (src, mask, i); + uint32_t d = *(dest + i); + UN8x4_ADD_UN8x4 (d, s); + *(dest + i) = d; + } +} + +static void +combine_saturate_u (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + int i; + + for (i = 0; i < width; ++i) + { + uint32_t s = combine_mask (src, mask, i); + uint32_t d = *(dest + i); + uint16_t sa, da; + + sa = s >> A_SHIFT; + da = ~d >> A_SHIFT; + if (sa > da) + { + sa = DIV_UN8 (da, sa); + UN8x4_MUL_UN8 (s, sa); + } + ; + UN8x4_ADD_UN8x4 (d, s); + *(dest + i) = d; + } +} + +/* + * PDF blend modes: + * The following blend modes have been taken from the PDF ISO 32000 + * specification, which at this point in time is available from + * http://www.adobe.com/devnet/acrobat/pdfs/PDF32000_2008.pdf + * The relevant chapters are 11.3.5 and 11.3.6. + * The formula for computing the final pixel color given in 11.3.6 is: + * αr × Cr = (1 – αs) × αb × Cb + (1 – αb) × αs × Cs + αb × αs × B(Cb, Cs) + * with B() being the blend function. + * Note that OVER is a special case of this operation, using B(Cb, Cs) = Cs + * + * These blend modes should match the SVG filter draft specification, as + * it has been designed to mirror ISO 32000. Note that at the current point + * no released draft exists that shows this, as the formulas have not been + * updated yet after the release of ISO 32000. + * + * The default implementation here uses the PDF_SEPARABLE_BLEND_MODE and + * PDF_NON_SEPARABLE_BLEND_MODE macros, which take the blend function as an + * argument. Note that this implementation operates on premultiplied colors, + * while the PDF specification does not. Therefore the code uses the formula + * Cra = (1 – as) . Dca + (1 – ad) . Sca + B(Dca, ad, Sca, as) + */ + +/* + * Multiply + * B(Dca, ad, Sca, as) = Dca.Sca + */ +static void +combine_multiply_u (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + int i; + + for (i = 0; i < width; ++i) + { + uint32_t s = combine_mask (src, mask, i); + uint32_t d = *(dest + i); + uint32_t ss = s; + uint32_t src_ia = ALPHA_8 (~s); + uint32_t dest_ia = ALPHA_8 (~d); + + UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (ss, dest_ia, d, src_ia); + UN8x4_MUL_UN8x4 (d, s); + UN8x4_ADD_UN8x4 (d, ss); + + *(dest + i) = d; + } +} + +static void +combine_multiply_ca (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + int i; + + for (i = 0; i < width; ++i) + { + uint32_t m = *(mask + i); + uint32_t s = *(src + i); + uint32_t d = *(dest + i); + uint32_t r = d; + uint32_t dest_ia = ALPHA_8 (~d); + + combine_mask_ca (&s, &m); + + UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (r, ~m, s, dest_ia); + UN8x4_MUL_UN8x4 (d, s); + UN8x4_ADD_UN8x4 (r, d); + + *(dest + i) = r; + } +} + +#define PDF_SEPARABLE_BLEND_MODE(name) \ + static void \ + combine_ ## name ## _u (pixman_implementation_t *imp, \ + pixman_op_t op, \ + uint32_t * dest, \ + const uint32_t * src, \ + const uint32_t * mask, \ + int width) \ + { \ + int i; \ + for (i = 0; i < width; ++i) { \ + uint32_t s = combine_mask (src, mask, i); \ + uint32_t d = *(dest + i); \ + uint8_t sa = ALPHA_8 (s); \ + uint8_t isa = ~sa; \ + uint8_t da = ALPHA_8 (d); \ + uint8_t ida = ~da; \ + uint32_t result; \ + \ + result = d; \ + UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (result, isa, s, ida); \ + \ + *(dest + i) = result + \ + (DIV_ONE_UN8 (sa * (uint32_t)da) << A_SHIFT) + \ + (blend_ ## name (RED_8 (d), da, RED_8 (s), sa) << R_SHIFT) + \ + (blend_ ## name (GREEN_8 (d), da, GREEN_8 (s), sa) << G_SHIFT) + \ + (blend_ ## name (BLUE_8 (d), da, BLUE_8 (s), sa)); \ + } \ + } \ + \ + static void \ + combine_ ## name ## _ca (pixman_implementation_t *imp, \ + pixman_op_t op, \ + uint32_t * dest, \ + const uint32_t * src, \ + const uint32_t * mask, \ + int width) \ + { \ + int i; \ + for (i = 0; i < width; ++i) { \ + uint32_t m = *(mask + i); \ + uint32_t s = *(src + i); \ + uint32_t d = *(dest + i); \ + uint8_t da = ALPHA_8 (d); \ + uint8_t ida = ~da; \ + uint32_t result; \ + \ + combine_mask_ca (&s, &m); \ + \ + result = d; \ + UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (result, ~m, s, ida); \ + \ + result += \ + (DIV_ONE_UN8 (ALPHA_8 (m) * (uint32_t)da) << A_SHIFT) + \ + (blend_ ## name (RED_8 (d), da, RED_8 (s), RED_8 (m)) << R_SHIFT) + \ + (blend_ ## name (GREEN_8 (d), da, GREEN_8 (s), GREEN_8 (m)) << G_SHIFT) + \ + (blend_ ## name (BLUE_8 (d), da, BLUE_8 (s), BLUE_8 (m))); \ + \ + *(dest + i) = result; \ + } \ + } + +/* + * Screen + * B(Dca, ad, Sca, as) = Dca.sa + Sca.da - Dca.Sca + */ +static inline uint32_t +blend_screen (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa) +{ + return DIV_ONE_UN8 (sca * da + dca * sa - sca * dca); +} + +PDF_SEPARABLE_BLEND_MODE (screen) + +/* + * Overlay + * B(Dca, Da, Sca, Sa) = + * if 2.Dca < Da + * 2.Sca.Dca + * otherwise + * Sa.Da - 2.(Da - Dca).(Sa - Sca) + */ +static inline uint32_t +blend_overlay (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa) +{ + uint32_t rca; + + if (2 * dca < da) + rca = 2 * sca * dca; + else + rca = sa * da - 2 * (da - dca) * (sa - sca); + return DIV_ONE_UN8 (rca); +} + +PDF_SEPARABLE_BLEND_MODE (overlay) + +/* + * Darken + * B(Dca, Da, Sca, Sa) = min (Sca.Da, Dca.Sa) + */ +static inline uint32_t +blend_darken (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa) +{ + uint32_t s, d; + + s = sca * da; + d = dca * sa; + return DIV_ONE_UN8 (s > d ? d : s); +} + +PDF_SEPARABLE_BLEND_MODE (darken) + +/* + * Lighten + * B(Dca, Da, Sca, Sa) = max (Sca.Da, Dca.Sa) + */ +static inline uint32_t +blend_lighten (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa) +{ + uint32_t s, d; + + s = sca * da; + d = dca * sa; + return DIV_ONE_UN8 (s > d ? s : d); +} + +PDF_SEPARABLE_BLEND_MODE (lighten) + +/* + * Color dodge + * B(Dca, Da, Sca, Sa) = + * if Dca == 0 + * 0 + * if Sca == Sa + * Sa.Da + * otherwise + * Sa.Da. min (1, Dca / Da / (1 - Sca/Sa)) + */ +static inline uint32_t +blend_color_dodge (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa) +{ + if (sca >= sa) + { + return dca == 0 ? 0 : DIV_ONE_UN8 (sa * da); + } + else + { + uint32_t rca = dca * sa / (sa - sca); + return DIV_ONE_UN8 (sa * MIN (rca, da)); + } +} + +PDF_SEPARABLE_BLEND_MODE (color_dodge) + +/* + * Color burn + * B(Dca, Da, Sca, Sa) = + * if Dca == Da + * Sa.Da + * if Sca == 0 + * 0 + * otherwise + * Sa.Da.(1 - min (1, (1 - Dca/Da).Sa / Sca)) + */ +static inline uint32_t +blend_color_burn (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa) +{ + if (sca == 0) + { + return dca < da ? 0 : DIV_ONE_UN8 (sa * da); + } + else + { + uint32_t rca = (da - dca) * sa / sca; + return DIV_ONE_UN8 (sa * (MAX (rca, da) - rca)); + } +} + +PDF_SEPARABLE_BLEND_MODE (color_burn) + +/* + * Hard light + * B(Dca, Da, Sca, Sa) = + * if 2.Sca < Sa + * 2.Sca.Dca + * otherwise + * Sa.Da - 2.(Da - Dca).(Sa - Sca) + */ +static inline uint32_t +blend_hard_light (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa) +{ + if (2 * sca < sa) + return DIV_ONE_UN8 (2 * sca * dca); + else + return DIV_ONE_UN8 (sa * da - 2 * (da - dca) * (sa - sca)); +} + +PDF_SEPARABLE_BLEND_MODE (hard_light) + +/* + * Soft light + * B(Dca, Da, Sca, Sa) = + * if (2.Sca <= Sa) + * Dca.(Sa - (1 - Dca/Da).(2.Sca - Sa)) + * otherwise if Dca.4 <= Da + * Dca.(Sa + (2.Sca - Sa).((16.Dca/Da - 12).Dca/Da + 3) + * otherwise + * (Dca.Sa + (SQRT (Dca/Da).Da - Dca).(2.Sca - Sa)) + */ +static inline uint32_t +blend_soft_light (uint32_t dca_org, + uint32_t da_org, + uint32_t sca_org, + uint32_t sa_org) +{ + double dca = dca_org * (1.0 / MASK); + double da = da_org * (1.0 / MASK); + double sca = sca_org * (1.0 / MASK); + double sa = sa_org * (1.0 / MASK); + double rca; + + if (2 * sca < sa) + { + if (da == 0) + rca = dca * sa; + else + rca = dca * sa - dca * (da - dca) * (sa - 2 * sca) / da; + } + else if (da == 0) + { + rca = 0; + } + else if (4 * dca <= da) + { + rca = dca * sa + + (2 * sca - sa) * dca * ((16 * dca / da - 12) * dca / da + 3); + } + else + { + rca = dca * sa + (sqrt (dca * da) - dca) * (2 * sca - sa); + } + return rca * MASK + 0.5; +} + +PDF_SEPARABLE_BLEND_MODE (soft_light) + +/* + * Difference + * B(Dca, Da, Sca, Sa) = abs (Dca.Sa - Sca.Da) + */ +static inline uint32_t +blend_difference (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa) +{ + uint32_t dcasa = dca * sa; + uint32_t scada = sca * da; + + if (scada < dcasa) + return DIV_ONE_UN8 (dcasa - scada); + else + return DIV_ONE_UN8 (scada - dcasa); +} + +PDF_SEPARABLE_BLEND_MODE (difference) + +/* + * Exclusion + * B(Dca, Da, Sca, Sa) = (Sca.Da + Dca.Sa - 2.Sca.Dca) + */ + +/* This can be made faster by writing it directly and not using + * PDF_SEPARABLE_BLEND_MODE, but that's a performance optimization */ + +static inline uint32_t +blend_exclusion (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa) +{ + return DIV_ONE_UN8 (sca * da + dca * sa - 2 * dca * sca); +} + +PDF_SEPARABLE_BLEND_MODE (exclusion) + +#undef PDF_SEPARABLE_BLEND_MODE + +/* + * PDF nonseperable blend modes are implemented using the following functions + * to operate in Hsl space, with Cmax, Cmid, Cmin referring to the max, mid + * and min value of the red, green and blue components. + * + * LUM (C) = 0.3 × Cred + 0.59 × Cgreen + 0.11 × Cblue + * + * clip_color (C): + * l = LUM (C) + * min = Cmin + * max = Cmax + * if n < 0.0 + * C = l + ( ( ( C – l ) × l ) ⁄ ( l – min ) ) + * if x > 1.0 + * C = l + ( ( ( C – l ) × ( 1 – l ) ) ⁄ ( max – l ) ) + * return C + * + * set_lum (C, l): + * d = l – LUM (C) + * C += d + * return clip_color (C) + * + * SAT (C) = CH_MAX (C) - CH_MIN (C) + * + * set_sat (C, s): + * if Cmax > Cmin + * Cmid = ( ( ( Cmid – Cmin ) × s ) ⁄ ( Cmax – Cmin ) ) + * Cmax = s + * else + * Cmid = Cmax = 0.0 + * Cmin = 0.0 + * return C + */ + +/* For premultiplied colors, we need to know what happens when C is + * multiplied by a real number. LUM and SAT are linear: + * + * LUM (r × C) = r × LUM (C) SAT (r * C) = r * SAT (C) + * + * If we extend clip_color with an extra argument a and change + * + * if x >= 1.0 + * + * into + * + * if x >= a + * + * then clip_color is also linear: + * + * r * clip_color (C, a) = clip_color (r_c, ra); + * + * for positive r. + * + * Similarly, we can extend set_lum with an extra argument that is just passed + * on to clip_color: + * + * r * set_lum ( C, l, a) + * + * = r × clip_color ( C + l - LUM (C), a) + * + * = clip_color ( r * C + r × l - r * LUM (C), r * a) + * + * = set_lum ( r * C, r * l, r * a) + * + * Finally, set_sat: + * + * r * set_sat (C, s) = set_sat (x * C, r * s) + * + * The above holds for all non-zero x, because the x'es in the fraction for + * C_mid cancel out. Specifically, it holds for x = r: + * + * r * set_sat (C, s) = set_sat (r_c, rs) + * + */ + +/* So, for the non-separable PDF blend modes, we have (using s, d for + * non-premultiplied colors, and S, D for premultiplied: + * + * Color: + * + * a_s * a_d * B(s, d) + * = a_s * a_d * set_lum (S/a_s, LUM (D/a_d), 1) + * = set_lum (S * a_d, a_s * LUM (D), a_s * a_d) + * + * + * Luminosity: + * + * a_s * a_d * B(s, d) + * = a_s * a_d * set_lum (D/a_d, LUM(S/a_s), 1) + * = set_lum (a_s * D, a_d * LUM(S), a_s * a_d) + * + * + * Saturation: + * + * a_s * a_d * B(s, d) + * = a_s * a_d * set_lum (set_sat (D/a_d, SAT (S/a_s)), LUM (D/a_d), 1) + * = set_lum (a_s * a_d * set_sat (D/a_d, SAT (S/a_s)), + * a_s * LUM (D), a_s * a_d) + * = set_lum (set_sat (a_s * D, a_d * SAT (S), a_s * LUM (D), a_s * a_d)) + * + * Hue: + * + * a_s * a_d * B(s, d) + * = a_s * a_d * set_lum (set_sat (S/a_s, SAT (D/a_d)), LUM (D/a_d), 1) + * = set_lum (set_sat (a_d * S, a_s * SAT (D)), a_s * LUM (D), a_s * a_d) + * + */ + +#define CH_MIN(c) (c[0] < c[1] ? (c[0] < c[2] ? c[0] : c[2]) : (c[1] < c[2] ? c[1] : c[2])) +#define CH_MAX(c) (c[0] > c[1] ? (c[0] > c[2] ? c[0] : c[2]) : (c[1] > c[2] ? c[1] : c[2])) +#define LUM(c) ((c[0] * 30 + c[1] * 59 + c[2] * 11) / 100) +#define SAT(c) (CH_MAX (c) - CH_MIN (c)) + +#define PDF_NON_SEPARABLE_BLEND_MODE(name) \ + static void \ + combine_ ## name ## _u (pixman_implementation_t *imp, \ + pixman_op_t op, \ + uint32_t *dest, \ + const uint32_t *src, \ + const uint32_t *mask, \ + int width) \ + { \ + int i; \ + for (i = 0; i < width; ++i) \ + { \ + uint32_t s = combine_mask (src, mask, i); \ + uint32_t d = *(dest + i); \ + uint8_t sa = ALPHA_8 (s); \ + uint8_t isa = ~sa; \ + uint8_t da = ALPHA_8 (d); \ + uint8_t ida = ~da; \ + uint32_t result; \ + uint32_t sc[3], dc[3], c[3]; \ + \ + result = d; \ + UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (result, isa, s, ida); \ + dc[0] = RED_8 (d); \ + sc[0] = RED_8 (s); \ + dc[1] = GREEN_8 (d); \ + sc[1] = GREEN_8 (s); \ + dc[2] = BLUE_8 (d); \ + sc[2] = BLUE_8 (s); \ + blend_ ## name (c, dc, da, sc, sa); \ + \ + *(dest + i) = result + \ + (DIV_ONE_UN8 (sa * (uint32_t)da) << A_SHIFT) + \ + (DIV_ONE_UN8 (c[0]) << R_SHIFT) + \ + (DIV_ONE_UN8 (c[1]) << G_SHIFT) + \ + (DIV_ONE_UN8 (c[2])); \ + } \ + } + +static void +set_lum (uint32_t dest[3], uint32_t src[3], uint32_t sa, uint32_t lum) +{ + double a, l, min, max; + double tmp[3]; + + a = sa * (1.0 / MASK); + + l = lum * (1.0 / MASK); + tmp[0] = src[0] * (1.0 / MASK); + tmp[1] = src[1] * (1.0 / MASK); + tmp[2] = src[2] * (1.0 / MASK); + + l = l - LUM (tmp); + tmp[0] += l; + tmp[1] += l; + tmp[2] += l; + + /* clip_color */ + l = LUM (tmp); + min = CH_MIN (tmp); + max = CH_MAX (tmp); + + if (min < 0) + { + if (l - min == 0.0) + { + tmp[0] = 0; + tmp[1] = 0; + tmp[2] = 0; + } + else + { + tmp[0] = l + (tmp[0] - l) * l / (l - min); + tmp[1] = l + (tmp[1] - l) * l / (l - min); + tmp[2] = l + (tmp[2] - l) * l / (l - min); + } + } + if (max > a) + { + if (max - l == 0.0) + { + tmp[0] = a; + tmp[1] = a; + tmp[2] = a; + } + else + { + tmp[0] = l + (tmp[0] - l) * (a - l) / (max - l); + tmp[1] = l + (tmp[1] - l) * (a - l) / (max - l); + tmp[2] = l + (tmp[2] - l) * (a - l) / (max - l); + } + } + + dest[0] = tmp[0] * MASK + 0.5; + dest[1] = tmp[1] * MASK + 0.5; + dest[2] = tmp[2] * MASK + 0.5; +} + +static void +set_sat (uint32_t dest[3], uint32_t src[3], uint32_t sat) +{ + int id[3]; + uint32_t min, max; + + if (src[0] > src[1]) + { + if (src[0] > src[2]) + { + id[0] = 0; + if (src[1] > src[2]) + { + id[1] = 1; + id[2] = 2; + } + else + { + id[1] = 2; + id[2] = 1; + } + } + else + { + id[0] = 2; + id[1] = 0; + id[2] = 1; + } + } + else + { + if (src[0] > src[2]) + { + id[0] = 1; + id[1] = 0; + id[2] = 2; + } + else + { + id[2] = 0; + if (src[1] > src[2]) + { + id[0] = 1; + id[1] = 2; + } + else + { + id[0] = 2; + id[1] = 1; + } + } + } + + max = dest[id[0]]; + min = dest[id[2]]; + if (max > min) + { + dest[id[1]] = (dest[id[1]] - min) * sat / (max - min); + dest[id[0]] = sat; + dest[id[2]] = 0; + } + else + { + dest[0] = dest[1] = dest[2] = 0; + } +} + +/* + * Hue: + * B(Cb, Cs) = set_lum (set_sat (Cs, SAT (Cb)), LUM (Cb)) + */ +static inline void +blend_hsl_hue (uint32_t c[3], + uint32_t dc[3], + uint32_t da, + uint32_t sc[3], + uint32_t sa) +{ + c[0] = sc[0] * da; + c[1] = sc[1] * da; + c[2] = sc[2] * da; + set_sat (c, c, SAT (dc) * sa); + set_lum (c, c, sa * da, LUM (dc) * sa); +} + +PDF_NON_SEPARABLE_BLEND_MODE (hsl_hue) + +/* + * Saturation: + * B(Cb, Cs) = set_lum (set_sat (Cb, SAT (Cs)), LUM (Cb)) + */ +static inline void +blend_hsl_saturation (uint32_t c[3], + uint32_t dc[3], + uint32_t da, + uint32_t sc[3], + uint32_t sa) +{ + c[0] = dc[0] * sa; + c[1] = dc[1] * sa; + c[2] = dc[2] * sa; + set_sat (c, c, SAT (sc) * da); + set_lum (c, c, sa * da, LUM (dc) * sa); +} + +PDF_NON_SEPARABLE_BLEND_MODE (hsl_saturation) + +/* + * Color: + * B(Cb, Cs) = set_lum (Cs, LUM (Cb)) + */ +static inline void +blend_hsl_color (uint32_t c[3], + uint32_t dc[3], + uint32_t da, + uint32_t sc[3], + uint32_t sa) +{ + c[0] = sc[0] * da; + c[1] = sc[1] * da; + c[2] = sc[2] * da; + set_lum (c, c, sa * da, LUM (dc) * sa); +} + +PDF_NON_SEPARABLE_BLEND_MODE (hsl_color) + +/* + * Luminosity: + * B(Cb, Cs) = set_lum (Cb, LUM (Cs)) + */ +static inline void +blend_hsl_luminosity (uint32_t c[3], + uint32_t dc[3], + uint32_t da, + uint32_t sc[3], + uint32_t sa) +{ + c[0] = dc[0] * sa; + c[1] = dc[1] * sa; + c[2] = dc[2] * sa; + set_lum (c, c, sa * da, LUM (sc) * da); +} + +PDF_NON_SEPARABLE_BLEND_MODE (hsl_luminosity) + +#undef SAT +#undef LUM +#undef CH_MAX +#undef CH_MIN +#undef PDF_NON_SEPARABLE_BLEND_MODE + +/* All of the disjoint/conjoint composing functions + * + * The four entries in the first column indicate what source contributions + * come from each of the four areas of the picture -- areas covered by neither + * A nor B, areas covered only by A, areas covered only by B and finally + * areas covered by both A and B. + * + * Disjoint Conjoint + * Fa Fb Fa Fb + * (0,0,0,0) 0 0 0 0 + * (0,A,0,A) 1 0 1 0 + * (0,0,B,B) 0 1 0 1 + * (0,A,B,A) 1 min((1-a)/b,1) 1 max(1-a/b,0) + * (0,A,B,B) min((1-b)/a,1) 1 max(1-b/a,0) 1 + * (0,0,0,A) max(1-(1-b)/a,0) 0 min(1,b/a) 0 + * (0,0,0,B) 0 max(1-(1-a)/b,0) 0 min(a/b,1) + * (0,A,0,0) min(1,(1-b)/a) 0 max(1-b/a,0) 0 + * (0,0,B,0) 0 min(1,(1-a)/b) 0 max(1-a/b,0) + * (0,0,B,A) max(1-(1-b)/a,0) min(1,(1-a)/b) min(1,b/a) max(1-a/b,0) + * (0,A,0,B) min(1,(1-b)/a) max(1-(1-a)/b,0) max(1-b/a,0) min(1,a/b) + * (0,A,B,0) min(1,(1-b)/a) min(1,(1-a)/b) max(1-b/a,0) max(1-a/b,0) + * + * See http://marc.info/?l=xfree-render&m=99792000027857&w=2 for more + * information about these operators. + */ + +#define COMBINE_A_OUT 1 +#define COMBINE_A_IN 2 +#define COMBINE_B_OUT 4 +#define COMBINE_B_IN 8 + +#define COMBINE_CLEAR 0 +#define COMBINE_A (COMBINE_A_OUT | COMBINE_A_IN) +#define COMBINE_B (COMBINE_B_OUT | COMBINE_B_IN) +#define COMBINE_A_OVER (COMBINE_A_OUT | COMBINE_B_OUT | COMBINE_A_IN) +#define COMBINE_B_OVER (COMBINE_A_OUT | COMBINE_B_OUT | COMBINE_B_IN) +#define COMBINE_A_ATOP (COMBINE_B_OUT | COMBINE_A_IN) +#define COMBINE_B_ATOP (COMBINE_A_OUT | COMBINE_B_IN) +#define COMBINE_XOR (COMBINE_A_OUT | COMBINE_B_OUT) + +/* portion covered by a but not b */ +static uint8_t +combine_disjoint_out_part (uint8_t a, uint8_t b) +{ + /* min (1, (1-b) / a) */ + + b = ~b; /* 1 - b */ + if (b >= a) /* 1 - b >= a -> (1-b)/a >= 1 */ + return MASK; /* 1 */ + return DIV_UN8 (b, a); /* (1-b) / a */ +} + +/* portion covered by both a and b */ +static uint8_t +combine_disjoint_in_part (uint8_t a, uint8_t b) +{ + /* max (1-(1-b)/a,0) */ + /* = - min ((1-b)/a - 1, 0) */ + /* = 1 - min (1, (1-b)/a) */ + + b = ~b; /* 1 - b */ + if (b >= a) /* 1 - b >= a -> (1-b)/a >= 1 */ + return 0; /* 1 - 1 */ + return ~DIV_UN8(b, a); /* 1 - (1-b) / a */ +} + +/* portion covered by a but not b */ +static uint8_t +combine_conjoint_out_part (uint8_t a, uint8_t b) +{ + /* max (1-b/a,0) */ + /* = 1-min(b/a,1) */ + + /* min (1, (1-b) / a) */ + + if (b >= a) /* b >= a -> b/a >= 1 */ + return 0x00; /* 0 */ + return ~DIV_UN8(b, a); /* 1 - b/a */ +} + +/* portion covered by both a and b */ +static uint8_t +combine_conjoint_in_part (uint8_t a, uint8_t b) +{ + /* min (1,b/a) */ + + if (b >= a) /* b >= a -> b/a >= 1 */ + return MASK; /* 1 */ + return DIV_UN8 (b, a); /* b/a */ +} + +#define GET_COMP(v, i) ((uint16_t) (uint8_t) ((v) >> i)) + +#define ADD(x, y, i, t) \ + ((t) = GET_COMP (x, i) + GET_COMP (y, i), \ + (uint32_t) ((uint8_t) ((t) | (0 - ((t) >> G_SHIFT)))) << (i)) + +#define GENERIC(x, y, i, ax, ay, t, u, v) \ + ((t) = (MUL_UN8 (GET_COMP (y, i), ay, (u)) + \ + MUL_UN8 (GET_COMP (x, i), ax, (v))), \ + (uint32_t) ((uint8_t) ((t) | \ + (0 - ((t) >> G_SHIFT)))) << (i)) + +static void +combine_disjoint_general_u (uint32_t * dest, + const uint32_t *src, + const uint32_t *mask, + int width, + uint8_t combine) +{ + int i; + + for (i = 0; i < width; ++i) + { + uint32_t s = combine_mask (src, mask, i); + uint32_t d = *(dest + i); + uint32_t m, n, o, p; + uint16_t Fa, Fb, t, u, v; + uint8_t sa = s >> A_SHIFT; + uint8_t da = d >> A_SHIFT; + + switch (combine & COMBINE_A) + { + default: + Fa = 0; + break; + + case COMBINE_A_OUT: + Fa = combine_disjoint_out_part (sa, da); + break; + + case COMBINE_A_IN: + Fa = combine_disjoint_in_part (sa, da); + break; + + case COMBINE_A: + Fa = MASK; + break; + } + + switch (combine & COMBINE_B) + { + default: + Fb = 0; + break; + + case COMBINE_B_OUT: + Fb = combine_disjoint_out_part (da, sa); + break; + + case COMBINE_B_IN: + Fb = combine_disjoint_in_part (da, sa); + break; + + case COMBINE_B: + Fb = MASK; + break; + } + m = GENERIC (s, d, 0, Fa, Fb, t, u, v); + n = GENERIC (s, d, G_SHIFT, Fa, Fb, t, u, v); + o = GENERIC (s, d, R_SHIFT, Fa, Fb, t, u, v); + p = GENERIC (s, d, A_SHIFT, Fa, Fb, t, u, v); + s = m | n | o | p; + *(dest + i) = s; + } +} + +static void +combine_disjoint_over_u (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + int i; + + for (i = 0; i < width; ++i) + { + uint32_t s = combine_mask (src, mask, i); + uint16_t a = s >> A_SHIFT; + + if (s != 0x00) + { + uint32_t d = *(dest + i); + a = combine_disjoint_out_part (d >> A_SHIFT, a); + UN8x4_MUL_UN8_ADD_UN8x4 (d, a, s); + + *(dest + i) = d; + } + } +} + +static void +combine_disjoint_in_u (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + combine_disjoint_general_u (dest, src, mask, width, COMBINE_A_IN); +} + +static void +combine_disjoint_in_reverse_u (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + combine_disjoint_general_u (dest, src, mask, width, COMBINE_B_IN); +} + +static void +combine_disjoint_out_u (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + combine_disjoint_general_u (dest, src, mask, width, COMBINE_A_OUT); +} + +static void +combine_disjoint_out_reverse_u (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + combine_disjoint_general_u (dest, src, mask, width, COMBINE_B_OUT); +} + +static void +combine_disjoint_atop_u (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + combine_disjoint_general_u (dest, src, mask, width, COMBINE_A_ATOP); +} + +static void +combine_disjoint_atop_reverse_u (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + combine_disjoint_general_u (dest, src, mask, width, COMBINE_B_ATOP); +} + +static void +combine_disjoint_xor_u (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + combine_disjoint_general_u (dest, src, mask, width, COMBINE_XOR); +} + +static void +combine_conjoint_general_u (uint32_t * dest, + const uint32_t *src, + const uint32_t *mask, + int width, + uint8_t combine) +{ + int i; + + for (i = 0; i < width; ++i) + { + uint32_t s = combine_mask (src, mask, i); + uint32_t d = *(dest + i); + uint32_t m, n, o, p; + uint16_t Fa, Fb, t, u, v; + uint8_t sa = s >> A_SHIFT; + uint8_t da = d >> A_SHIFT; + + switch (combine & COMBINE_A) + { + default: + Fa = 0; + break; + + case COMBINE_A_OUT: + Fa = combine_conjoint_out_part (sa, da); + break; + + case COMBINE_A_IN: + Fa = combine_conjoint_in_part (sa, da); + break; + + case COMBINE_A: + Fa = MASK; + break; + } + + switch (combine & COMBINE_B) + { + default: + Fb = 0; + break; + + case COMBINE_B_OUT: + Fb = combine_conjoint_out_part (da, sa); + break; + + case COMBINE_B_IN: + Fb = combine_conjoint_in_part (da, sa); + break; + + case COMBINE_B: + Fb = MASK; + break; + } + + m = GENERIC (s, d, 0, Fa, Fb, t, u, v); + n = GENERIC (s, d, G_SHIFT, Fa, Fb, t, u, v); + o = GENERIC (s, d, R_SHIFT, Fa, Fb, t, u, v); + p = GENERIC (s, d, A_SHIFT, Fa, Fb, t, u, v); + + s = m | n | o | p; + + *(dest + i) = s; + } +} + +static void +combine_conjoint_over_u (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_OVER); +} + +static void +combine_conjoint_over_reverse_u (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_OVER); +} + +static void +combine_conjoint_in_u (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_IN); +} + +static void +combine_conjoint_in_reverse_u (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_IN); +} + +static void +combine_conjoint_out_u (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_OUT); +} + +static void +combine_conjoint_out_reverse_u (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_OUT); +} + +static void +combine_conjoint_atop_u (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_ATOP); +} + +static void +combine_conjoint_atop_reverse_u (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_ATOP); +} + +static void +combine_conjoint_xor_u (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + combine_conjoint_general_u (dest, src, mask, width, COMBINE_XOR); +} + + +/* Component alpha combiners */ + +static void +combine_clear_ca (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + memset (dest, 0, width * sizeof(uint32_t)); +} + +static void +combine_src_ca (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + int i; + + for (i = 0; i < width; ++i) + { + uint32_t s = *(src + i); + uint32_t m = *(mask + i); + + combine_mask_value_ca (&s, &m); + + *(dest + i) = s; + } +} + +static void +combine_over_ca (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + int i; + + for (i = 0; i < width; ++i) + { + uint32_t s = *(src + i); + uint32_t m = *(mask + i); + uint32_t a; + + combine_mask_ca (&s, &m); + + a = ~m; + if (a) + { + uint32_t d = *(dest + i); + UN8x4_MUL_UN8x4_ADD_UN8x4 (d, a, s); + s = d; + } + + *(dest + i) = s; + } +} + +static void +combine_over_reverse_ca (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + int i; + + for (i = 0; i < width; ++i) + { + uint32_t d = *(dest + i); + uint32_t a = ~d >> A_SHIFT; + + if (a) + { + uint32_t s = *(src + i); + uint32_t m = *(mask + i); + + UN8x4_MUL_UN8x4 (s, m); + UN8x4_MUL_UN8_ADD_UN8x4 (s, a, d); + + *(dest + i) = s; + } + } +} + +static void +combine_in_ca (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + int i; + + for (i = 0; i < width; ++i) + { + uint32_t d = *(dest + i); + uint16_t a = d >> A_SHIFT; + uint32_t s = 0; + + if (a) + { + uint32_t m = *(mask + i); + + s = *(src + i); + combine_mask_value_ca (&s, &m); + + if (a != MASK) + UN8x4_MUL_UN8 (s, a); + } + + *(dest + i) = s; + } +} + +static void +combine_in_reverse_ca (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + int i; + + for (i = 0; i < width; ++i) + { + uint32_t s = *(src + i); + uint32_t m = *(mask + i); + uint32_t a; + + combine_mask_alpha_ca (&s, &m); + + a = m; + if (a != ~0) + { + uint32_t d = 0; + + if (a) + { + d = *(dest + i); + UN8x4_MUL_UN8x4 (d, a); + } + + *(dest + i) = d; + } + } +} + +static void +combine_out_ca (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + int i; + + for (i = 0; i < width; ++i) + { + uint32_t d = *(dest + i); + uint16_t a = ~d >> A_SHIFT; + uint32_t s = 0; + + if (a) + { + uint32_t m = *(mask + i); + + s = *(src + i); + combine_mask_value_ca (&s, &m); + + if (a != MASK) + UN8x4_MUL_UN8 (s, a); + } + + *(dest + i) = s; + } +} + +static void +combine_out_reverse_ca (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + int i; + + for (i = 0; i < width; ++i) + { + uint32_t s = *(src + i); + uint32_t m = *(mask + i); + uint32_t a; + + combine_mask_alpha_ca (&s, &m); + + a = ~m; + if (a != ~0) + { + uint32_t d = 0; + + if (a) + { + d = *(dest + i); + UN8x4_MUL_UN8x4 (d, a); + } + + *(dest + i) = d; + } + } +} + +static void +combine_atop_ca (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + int i; + + for (i = 0; i < width; ++i) + { + uint32_t d = *(dest + i); + uint32_t s = *(src + i); + uint32_t m = *(mask + i); + uint32_t ad; + uint16_t as = d >> A_SHIFT; + + combine_mask_ca (&s, &m); + + ad = ~m; + + UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (d, ad, s, as); + + *(dest + i) = d; + } +} + +static void +combine_atop_reverse_ca (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + int i; + + for (i = 0; i < width; ++i) + { + uint32_t d = *(dest + i); + uint32_t s = *(src + i); + uint32_t m = *(mask + i); + uint32_t ad; + uint16_t as = ~d >> A_SHIFT; + + combine_mask_ca (&s, &m); + + ad = m; + + UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (d, ad, s, as); + + *(dest + i) = d; + } +} + +static void +combine_xor_ca (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + int i; + + for (i = 0; i < width; ++i) + { + uint32_t d = *(dest + i); + uint32_t s = *(src + i); + uint32_t m = *(mask + i); + uint32_t ad; + uint16_t as = ~d >> A_SHIFT; + + combine_mask_ca (&s, &m); + + ad = ~m; + + UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (d, ad, s, as); + + *(dest + i) = d; + } +} + +static void +combine_add_ca (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + int i; + + for (i = 0; i < width; ++i) + { + uint32_t s = *(src + i); + uint32_t m = *(mask + i); + uint32_t d = *(dest + i); + + combine_mask_value_ca (&s, &m); + + UN8x4_ADD_UN8x4 (d, s); + + *(dest + i) = d; + } +} + +static void +combine_saturate_ca (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + int i; + + for (i = 0; i < width; ++i) + { + uint32_t s, d; + uint16_t sa, sr, sg, sb, da; + uint16_t t, u, v; + uint32_t m, n, o, p; + + d = *(dest + i); + s = *(src + i); + m = *(mask + i); + + combine_mask_ca (&s, &m); + + sa = (m >> A_SHIFT); + sr = (m >> R_SHIFT) & MASK; + sg = (m >> G_SHIFT) & MASK; + sb = m & MASK; + da = ~d >> A_SHIFT; + + if (sb <= da) + m = ADD (s, d, 0, t); + else + m = GENERIC (s, d, 0, (da << G_SHIFT) / sb, MASK, t, u, v); + + if (sg <= da) + n = ADD (s, d, G_SHIFT, t); + else + n = GENERIC (s, d, G_SHIFT, (da << G_SHIFT) / sg, MASK, t, u, v); + + if (sr <= da) + o = ADD (s, d, R_SHIFT, t); + else + o = GENERIC (s, d, R_SHIFT, (da << G_SHIFT) / sr, MASK, t, u, v); + + if (sa <= da) + p = ADD (s, d, A_SHIFT, t); + else + p = GENERIC (s, d, A_SHIFT, (da << G_SHIFT) / sa, MASK, t, u, v); + + *(dest + i) = m | n | o | p; + } +} + +static void +combine_disjoint_general_ca (uint32_t * dest, + const uint32_t *src, + const uint32_t *mask, + int width, + uint8_t combine) +{ + int i; + + for (i = 0; i < width; ++i) + { + uint32_t s, d; + uint32_t m, n, o, p; + uint32_t Fa, Fb; + uint16_t t, u, v; + uint32_t sa; + uint8_t da; + + s = *(src + i); + m = *(mask + i); + d = *(dest + i); + da = d >> A_SHIFT; + + combine_mask_ca (&s, &m); + + sa = m; + + switch (combine & COMBINE_A) + { + default: + Fa = 0; + break; + + case COMBINE_A_OUT: + m = (uint32_t)combine_disjoint_out_part ((uint8_t) (sa >> 0), da); + n = (uint32_t)combine_disjoint_out_part ((uint8_t) (sa >> G_SHIFT), da) << G_SHIFT; + o = (uint32_t)combine_disjoint_out_part ((uint8_t) (sa >> R_SHIFT), da) << R_SHIFT; + p = (uint32_t)combine_disjoint_out_part ((uint8_t) (sa >> A_SHIFT), da) << A_SHIFT; + Fa = m | n | o | p; + break; + + case COMBINE_A_IN: + m = (uint32_t)combine_disjoint_in_part ((uint8_t) (sa >> 0), da); + n = (uint32_t)combine_disjoint_in_part ((uint8_t) (sa >> G_SHIFT), da) << G_SHIFT; + o = (uint32_t)combine_disjoint_in_part ((uint8_t) (sa >> R_SHIFT), da) << R_SHIFT; + p = (uint32_t)combine_disjoint_in_part ((uint8_t) (sa >> A_SHIFT), da) << A_SHIFT; + Fa = m | n | o | p; + break; + + case COMBINE_A: + Fa = ~0; + break; + } + + switch (combine & COMBINE_B) + { + default: + Fb = 0; + break; + + case COMBINE_B_OUT: + m = (uint32_t)combine_disjoint_out_part (da, (uint8_t) (sa >> 0)); + n = (uint32_t)combine_disjoint_out_part (da, (uint8_t) (sa >> G_SHIFT)) << G_SHIFT; + o = (uint32_t)combine_disjoint_out_part (da, (uint8_t) (sa >> R_SHIFT)) << R_SHIFT; + p = (uint32_t)combine_disjoint_out_part (da, (uint8_t) (sa >> A_SHIFT)) << A_SHIFT; + Fb = m | n | o | p; + break; + + case COMBINE_B_IN: + m = (uint32_t)combine_disjoint_in_part (da, (uint8_t) (sa >> 0)); + n = (uint32_t)combine_disjoint_in_part (da, (uint8_t) (sa >> G_SHIFT)) << G_SHIFT; + o = (uint32_t)combine_disjoint_in_part (da, (uint8_t) (sa >> R_SHIFT)) << R_SHIFT; + p = (uint32_t)combine_disjoint_in_part (da, (uint8_t) (sa >> A_SHIFT)) << A_SHIFT; + Fb = m | n | o | p; + break; + + case COMBINE_B: + Fb = ~0; + break; + } + m = GENERIC (s, d, 0, GET_COMP (Fa, 0), GET_COMP (Fb, 0), t, u, v); + n = GENERIC (s, d, G_SHIFT, GET_COMP (Fa, G_SHIFT), GET_COMP (Fb, G_SHIFT), t, u, v); + o = GENERIC (s, d, R_SHIFT, GET_COMP (Fa, R_SHIFT), GET_COMP (Fb, R_SHIFT), t, u, v); + p = GENERIC (s, d, A_SHIFT, GET_COMP (Fa, A_SHIFT), GET_COMP (Fb, A_SHIFT), t, u, v); + + s = m | n | o | p; + + *(dest + i) = s; + } +} + +static void +combine_disjoint_over_ca (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_OVER); +} + +static void +combine_disjoint_in_ca (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_IN); +} + +static void +combine_disjoint_in_reverse_ca (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + combine_disjoint_general_ca (dest, src, mask, width, COMBINE_B_IN); +} + +static void +combine_disjoint_out_ca (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_OUT); +} + +static void +combine_disjoint_out_reverse_ca (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + combine_disjoint_general_ca (dest, src, mask, width, COMBINE_B_OUT); +} + +static void +combine_disjoint_atop_ca (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_ATOP); +} + +static void +combine_disjoint_atop_reverse_ca (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + combine_disjoint_general_ca (dest, src, mask, width, COMBINE_B_ATOP); +} + +static void +combine_disjoint_xor_ca (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + combine_disjoint_general_ca (dest, src, mask, width, COMBINE_XOR); +} + +static void +combine_conjoint_general_ca (uint32_t * dest, + const uint32_t *src, + const uint32_t *mask, + int width, + uint8_t combine) +{ + int i; + + for (i = 0; i < width; ++i) + { + uint32_t s, d; + uint32_t m, n, o, p; + uint32_t Fa, Fb; + uint16_t t, u, v; + uint32_t sa; + uint8_t da; + + s = *(src + i); + m = *(mask + i); + d = *(dest + i); + da = d >> A_SHIFT; + + combine_mask_ca (&s, &m); + + sa = m; + + switch (combine & COMBINE_A) + { + default: + Fa = 0; + break; + + case COMBINE_A_OUT: + m = (uint32_t)combine_conjoint_out_part ((uint8_t) (sa >> 0), da); + n = (uint32_t)combine_conjoint_out_part ((uint8_t) (sa >> G_SHIFT), da) << G_SHIFT; + o = (uint32_t)combine_conjoint_out_part ((uint8_t) (sa >> R_SHIFT), da) << R_SHIFT; + p = (uint32_t)combine_conjoint_out_part ((uint8_t) (sa >> A_SHIFT), da) << A_SHIFT; + Fa = m | n | o | p; + break; + + case COMBINE_A_IN: + m = (uint32_t)combine_conjoint_in_part ((uint8_t) (sa >> 0), da); + n = (uint32_t)combine_conjoint_in_part ((uint8_t) (sa >> G_SHIFT), da) << G_SHIFT; + o = (uint32_t)combine_conjoint_in_part ((uint8_t) (sa >> R_SHIFT), da) << R_SHIFT; + p = (uint32_t)combine_conjoint_in_part ((uint8_t) (sa >> A_SHIFT), da) << A_SHIFT; + Fa = m | n | o | p; + break; + + case COMBINE_A: + Fa = ~0; + break; + } + + switch (combine & COMBINE_B) + { + default: + Fb = 0; + break; + + case COMBINE_B_OUT: + m = (uint32_t)combine_conjoint_out_part (da, (uint8_t) (sa >> 0)); + n = (uint32_t)combine_conjoint_out_part (da, (uint8_t) (sa >> G_SHIFT)) << G_SHIFT; + o = (uint32_t)combine_conjoint_out_part (da, (uint8_t) (sa >> R_SHIFT)) << R_SHIFT; + p = (uint32_t)combine_conjoint_out_part (da, (uint8_t) (sa >> A_SHIFT)) << A_SHIFT; + Fb = m | n | o | p; + break; + + case COMBINE_B_IN: + m = (uint32_t)combine_conjoint_in_part (da, (uint8_t) (sa >> 0)); + n = (uint32_t)combine_conjoint_in_part (da, (uint8_t) (sa >> G_SHIFT)) << G_SHIFT; + o = (uint32_t)combine_conjoint_in_part (da, (uint8_t) (sa >> R_SHIFT)) << R_SHIFT; + p = (uint32_t)combine_conjoint_in_part (da, (uint8_t) (sa >> A_SHIFT)) << A_SHIFT; + Fb = m | n | o | p; + break; + + case COMBINE_B: + Fb = ~0; + break; + } + m = GENERIC (s, d, 0, GET_COMP (Fa, 0), GET_COMP (Fb, 0), t, u, v); + n = GENERIC (s, d, G_SHIFT, GET_COMP (Fa, G_SHIFT), GET_COMP (Fb, G_SHIFT), t, u, v); + o = GENERIC (s, d, R_SHIFT, GET_COMP (Fa, R_SHIFT), GET_COMP (Fb, R_SHIFT), t, u, v); + p = GENERIC (s, d, A_SHIFT, GET_COMP (Fa, A_SHIFT), GET_COMP (Fb, A_SHIFT), t, u, v); + + s = m | n | o | p; + + *(dest + i) = s; + } +} + +static void +combine_conjoint_over_ca (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_OVER); +} + +static void +combine_conjoint_over_reverse_ca (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_OVER); +} + +static void +combine_conjoint_in_ca (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_IN); +} + +static void +combine_conjoint_in_reverse_ca (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_IN); +} + +static void +combine_conjoint_out_ca (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_OUT); +} + +static void +combine_conjoint_out_reverse_ca (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_OUT); +} + +static void +combine_conjoint_atop_ca (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_ATOP); +} + +static void +combine_conjoint_atop_reverse_ca (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_ATOP); +} + +static void +combine_conjoint_xor_ca (pixman_implementation_t *imp, + pixman_op_t op, + uint32_t * dest, + const uint32_t * src, + const uint32_t * mask, + int width) +{ + combine_conjoint_general_ca (dest, src, mask, width, COMBINE_XOR); +} + +void +_pixman_setup_combiner_functions_32 (pixman_implementation_t *imp) +{ + /* Unified alpha */ + imp->combine_32[PIXMAN_OP_CLEAR] = combine_clear; + imp->combine_32[PIXMAN_OP_SRC] = combine_src_u; + imp->combine_32[PIXMAN_OP_DST] = combine_dst; + imp->combine_32[PIXMAN_OP_OVER] = combine_over_u; + imp->combine_32[PIXMAN_OP_OVER_REVERSE] = combine_over_reverse_u; + imp->combine_32[PIXMAN_OP_IN] = combine_in_u; + imp->combine_32[PIXMAN_OP_IN_REVERSE] = combine_in_reverse_u; + imp->combine_32[PIXMAN_OP_OUT] = combine_out_u; + imp->combine_32[PIXMAN_OP_OUT_REVERSE] = combine_out_reverse_u; + imp->combine_32[PIXMAN_OP_ATOP] = combine_atop_u; + imp->combine_32[PIXMAN_OP_ATOP_REVERSE] = combine_atop_reverse_u; + imp->combine_32[PIXMAN_OP_XOR] = combine_xor_u; + imp->combine_32[PIXMAN_OP_ADD] = combine_add_u; + imp->combine_32[PIXMAN_OP_SATURATE] = combine_saturate_u; + + /* Disjoint, unified */ + imp->combine_32[PIXMAN_OP_DISJOINT_CLEAR] = combine_clear; + imp->combine_32[PIXMAN_OP_DISJOINT_SRC] = combine_src_u; + imp->combine_32[PIXMAN_OP_DISJOINT_DST] = combine_dst; + imp->combine_32[PIXMAN_OP_DISJOINT_OVER] = combine_disjoint_over_u; + imp->combine_32[PIXMAN_OP_DISJOINT_OVER_REVERSE] = combine_saturate_u; + imp->combine_32[PIXMAN_OP_DISJOINT_IN] = combine_disjoint_in_u; + imp->combine_32[PIXMAN_OP_DISJOINT_IN_REVERSE] = combine_disjoint_in_reverse_u; + imp->combine_32[PIXMAN_OP_DISJOINT_OUT] = combine_disjoint_out_u; + imp->combine_32[PIXMAN_OP_DISJOINT_OUT_REVERSE] = combine_disjoint_out_reverse_u; + imp->combine_32[PIXMAN_OP_DISJOINT_ATOP] = combine_disjoint_atop_u; + imp->combine_32[PIXMAN_OP_DISJOINT_ATOP_REVERSE] = combine_disjoint_atop_reverse_u; + imp->combine_32[PIXMAN_OP_DISJOINT_XOR] = combine_disjoint_xor_u; + + /* Conjoint, unified */ + imp->combine_32[PIXMAN_OP_CONJOINT_CLEAR] = combine_clear; + imp->combine_32[PIXMAN_OP_CONJOINT_SRC] = combine_src_u; + imp->combine_32[PIXMAN_OP_CONJOINT_DST] = combine_dst; + imp->combine_32[PIXMAN_OP_CONJOINT_OVER] = combine_conjoint_over_u; + imp->combine_32[PIXMAN_OP_CONJOINT_OVER_REVERSE] = combine_conjoint_over_reverse_u; + imp->combine_32[PIXMAN_OP_CONJOINT_IN] = combine_conjoint_in_u; + imp->combine_32[PIXMAN_OP_CONJOINT_IN_REVERSE] = combine_conjoint_in_reverse_u; + imp->combine_32[PIXMAN_OP_CONJOINT_OUT] = combine_conjoint_out_u; + imp->combine_32[PIXMAN_OP_CONJOINT_OUT_REVERSE] = combine_conjoint_out_reverse_u; + imp->combine_32[PIXMAN_OP_CONJOINT_ATOP] = combine_conjoint_atop_u; + imp->combine_32[PIXMAN_OP_CONJOINT_ATOP_REVERSE] = combine_conjoint_atop_reverse_u; + imp->combine_32[PIXMAN_OP_CONJOINT_XOR] = combine_conjoint_xor_u; + + imp->combine_32[PIXMAN_OP_MULTIPLY] = combine_multiply_u; + imp->combine_32[PIXMAN_OP_SCREEN] = combine_screen_u; + imp->combine_32[PIXMAN_OP_OVERLAY] = combine_overlay_u; + imp->combine_32[PIXMAN_OP_DARKEN] = combine_darken_u; + imp->combine_32[PIXMAN_OP_LIGHTEN] = combine_lighten_u; + imp->combine_32[PIXMAN_OP_COLOR_DODGE] = combine_color_dodge_u; + imp->combine_32[PIXMAN_OP_COLOR_BURN] = combine_color_burn_u; + imp->combine_32[PIXMAN_OP_HARD_LIGHT] = combine_hard_light_u; + imp->combine_32[PIXMAN_OP_SOFT_LIGHT] = combine_soft_light_u; + imp->combine_32[PIXMAN_OP_DIFFERENCE] = combine_difference_u; + imp->combine_32[PIXMAN_OP_EXCLUSION] = combine_exclusion_u; + imp->combine_32[PIXMAN_OP_HSL_HUE] = combine_hsl_hue_u; + imp->combine_32[PIXMAN_OP_HSL_SATURATION] = combine_hsl_saturation_u; + imp->combine_32[PIXMAN_OP_HSL_COLOR] = combine_hsl_color_u; + imp->combine_32[PIXMAN_OP_HSL_LUMINOSITY] = combine_hsl_luminosity_u; + + /* Component alpha combiners */ + imp->combine_32_ca[PIXMAN_OP_CLEAR] = combine_clear_ca; + imp->combine_32_ca[PIXMAN_OP_SRC] = combine_src_ca; + /* dest */ + imp->combine_32_ca[PIXMAN_OP_OVER] = combine_over_ca; + imp->combine_32_ca[PIXMAN_OP_OVER_REVERSE] = combine_over_reverse_ca; + imp->combine_32_ca[PIXMAN_OP_IN] = combine_in_ca; + imp->combine_32_ca[PIXMAN_OP_IN_REVERSE] = combine_in_reverse_ca; + imp->combine_32_ca[PIXMAN_OP_OUT] = combine_out_ca; + imp->combine_32_ca[PIXMAN_OP_OUT_REVERSE] = combine_out_reverse_ca; + imp->combine_32_ca[PIXMAN_OP_ATOP] = combine_atop_ca; + imp->combine_32_ca[PIXMAN_OP_ATOP_REVERSE] = combine_atop_reverse_ca; + imp->combine_32_ca[PIXMAN_OP_XOR] = combine_xor_ca; + imp->combine_32_ca[PIXMAN_OP_ADD] = combine_add_ca; + imp->combine_32_ca[PIXMAN_OP_SATURATE] = combine_saturate_ca; + + /* Disjoint CA */ + imp->combine_32_ca[PIXMAN_OP_DISJOINT_CLEAR] = combine_clear_ca; + imp->combine_32_ca[PIXMAN_OP_DISJOINT_SRC] = combine_src_ca; + imp->combine_32_ca[PIXMAN_OP_DISJOINT_DST] = combine_dst; + imp->combine_32_ca[PIXMAN_OP_DISJOINT_OVER] = combine_disjoint_over_ca; + imp->combine_32_ca[PIXMAN_OP_DISJOINT_OVER_REVERSE] = combine_saturate_ca; + imp->combine_32_ca[PIXMAN_OP_DISJOINT_IN] = combine_disjoint_in_ca; + imp->combine_32_ca[PIXMAN_OP_DISJOINT_IN_REVERSE] = combine_disjoint_in_reverse_ca; + imp->combine_32_ca[PIXMAN_OP_DISJOINT_OUT] = combine_disjoint_out_ca; + imp->combine_32_ca[PIXMAN_OP_DISJOINT_OUT_REVERSE] = combine_disjoint_out_reverse_ca; + imp->combine_32_ca[PIXMAN_OP_DISJOINT_ATOP] = combine_disjoint_atop_ca; + imp->combine_32_ca[PIXMAN_OP_DISJOINT_ATOP_REVERSE] = combine_disjoint_atop_reverse_ca; + imp->combine_32_ca[PIXMAN_OP_DISJOINT_XOR] = combine_disjoint_xor_ca; + + /* Conjoint CA */ + imp->combine_32_ca[PIXMAN_OP_CONJOINT_CLEAR] = combine_clear_ca; + imp->combine_32_ca[PIXMAN_OP_CONJOINT_SRC] = combine_src_ca; + imp->combine_32_ca[PIXMAN_OP_CONJOINT_DST] = combine_dst; + imp->combine_32_ca[PIXMAN_OP_CONJOINT_OVER] = combine_conjoint_over_ca; + imp->combine_32_ca[PIXMAN_OP_CONJOINT_OVER_REVERSE] = combine_conjoint_over_reverse_ca; + imp->combine_32_ca[PIXMAN_OP_CONJOINT_IN] = combine_conjoint_in_ca; + imp->combine_32_ca[PIXMAN_OP_CONJOINT_IN_REVERSE] = combine_conjoint_in_reverse_ca; + imp->combine_32_ca[PIXMAN_OP_CONJOINT_OUT] = combine_conjoint_out_ca; + imp->combine_32_ca[PIXMAN_OP_CONJOINT_OUT_REVERSE] = combine_conjoint_out_reverse_ca; + imp->combine_32_ca[PIXMAN_OP_CONJOINT_ATOP] = combine_conjoint_atop_ca; + imp->combine_32_ca[PIXMAN_OP_CONJOINT_ATOP_REVERSE] = combine_conjoint_atop_reverse_ca; + imp->combine_32_ca[PIXMAN_OP_CONJOINT_XOR] = combine_conjoint_xor_ca; + + imp->combine_32_ca[PIXMAN_OP_MULTIPLY] = combine_multiply_ca; + imp->combine_32_ca[PIXMAN_OP_SCREEN] = combine_screen_ca; + imp->combine_32_ca[PIXMAN_OP_OVERLAY] = combine_overlay_ca; + imp->combine_32_ca[PIXMAN_OP_DARKEN] = combine_darken_ca; + imp->combine_32_ca[PIXMAN_OP_LIGHTEN] = combine_lighten_ca; + imp->combine_32_ca[PIXMAN_OP_COLOR_DODGE] = combine_color_dodge_ca; + imp->combine_32_ca[PIXMAN_OP_COLOR_BURN] = combine_color_burn_ca; + imp->combine_32_ca[PIXMAN_OP_HARD_LIGHT] = combine_hard_light_ca; + imp->combine_32_ca[PIXMAN_OP_SOFT_LIGHT] = combine_soft_light_ca; + imp->combine_32_ca[PIXMAN_OP_DIFFERENCE] = combine_difference_ca; + imp->combine_32_ca[PIXMAN_OP_EXCLUSION] = combine_exclusion_ca; + + /* It is not clear that these make sense, so make them noops for now */ + imp->combine_32_ca[PIXMAN_OP_HSL_HUE] = combine_dst; + imp->combine_32_ca[PIXMAN_OP_HSL_SATURATION] = combine_dst; + imp->combine_32_ca[PIXMAN_OP_HSL_COLOR] = combine_dst; + imp->combine_32_ca[PIXMAN_OP_HSL_LUMINOSITY] = combine_dst; +} diff --git a/pixman/pixman/pixman-combine32.h b/pixman/pixman/pixman-combine32.h new file mode 100644 index 000000000..875dde3cf --- /dev/null +++ b/pixman/pixman/pixman-combine32.h @@ -0,0 +1,225 @@ +#define COMPONENT_SIZE 8 +#define MASK 0xff +#define ONE_HALF 0x80 + +#define A_SHIFT 8 * 3 +#define R_SHIFT 8 * 2 +#define G_SHIFT 8 +#define A_MASK 0xff000000 +#define R_MASK 0xff0000 +#define G_MASK 0xff00 + +#define RB_MASK 0xff00ff +#define AG_MASK 0xff00ff00 +#define RB_ONE_HALF 0x800080 +#define RB_MASK_PLUS_ONE 0x10000100 + +#define ALPHA_8(x) ((x) >> A_SHIFT) +#define RED_8(x) (((x) >> R_SHIFT) & MASK) +#define GREEN_8(x) (((x) >> G_SHIFT) & MASK) +#define BLUE_8(x) ((x) & MASK) + +/* + * Helper macros. + */ + +#define MUL_UN8(a, b, t) \ + ((t) = (a) * (uint16_t)(b) + ONE_HALF, ((((t) >> G_SHIFT ) + (t) ) >> G_SHIFT )) + +#define DIV_UN8(a, b) \ + (((uint16_t) (a) * MASK + ((b) / 2)) / (b)) + +#define ADD_UN8(x, y, t) \ + ((t) = (x) + (y), \ + (uint32_t) (uint8_t) ((t) | (0 - ((t) >> G_SHIFT)))) + +#define DIV_ONE_UN8(x) \ + (((x) + ONE_HALF + (((x) + ONE_HALF) >> G_SHIFT)) >> G_SHIFT) + +/* + * The methods below use some tricks to be able to do two color + * components at the same time. + */ + +/* + * x_rb = (x_rb * a) / 255 + */ +#define UN8_rb_MUL_UN8(x, a, t) \ + do \ + { \ + t = ((x) & RB_MASK) * (a); \ + t += RB_ONE_HALF; \ + x = (t + ((t >> G_SHIFT) & RB_MASK)) >> G_SHIFT; \ + x &= RB_MASK; \ + } while (0) + +/* + * x_rb = min (x_rb + y_rb, 255) + */ +#define UN8_rb_ADD_UN8_rb(x, y, t) \ + do \ + { \ + t = ((x) + (y)); \ + t |= RB_MASK_PLUS_ONE - ((t >> G_SHIFT) & RB_MASK); \ + x = (t & RB_MASK); \ + } while (0) + +/* + * x_rb = (x_rb * a_rb) / 255 + */ +#define UN8_rb_MUL_UN8_rb(x, a, t) \ + do \ + { \ + t = (x & MASK) * (a & MASK); \ + t |= (x & R_MASK) * ((a >> R_SHIFT) & MASK); \ + t += RB_ONE_HALF; \ + t = (t + ((t >> G_SHIFT) & RB_MASK)) >> G_SHIFT; \ + x = t & RB_MASK; \ + } while (0) + +/* + * x_c = (x_c * a) / 255 + */ +#define UN8x4_MUL_UN8(x, a) \ + do \ + { \ + uint32_t r1__, r2__, t__; \ + \ + r1__ = (x); \ + UN8_rb_MUL_UN8 (r1__, (a), t__); \ + \ + r2__ = (x) >> G_SHIFT; \ + UN8_rb_MUL_UN8 (r2__, (a), t__); \ + \ + (x) = r1__ | (r2__ << G_SHIFT); \ + } while (0) + +/* + * x_c = (x_c * a) / 255 + y_c + */ +#define UN8x4_MUL_UN8_ADD_UN8x4(x, a, y) \ + do \ + { \ + uint32_t r1__, r2__, r3__, t__; \ + \ + r1__ = (x); \ + r2__ = (y) & RB_MASK; \ + UN8_rb_MUL_UN8 (r1__, (a), t__); \ + UN8_rb_ADD_UN8_rb (r1__, r2__, t__); \ + \ + r2__ = (x) >> G_SHIFT; \ + r3__ = ((y) >> G_SHIFT) & RB_MASK; \ + UN8_rb_MUL_UN8 (r2__, (a), t__); \ + UN8_rb_ADD_UN8_rb (r2__, r3__, t__); \ + \ + (x) = r1__ | (r2__ << G_SHIFT); \ + } while (0) + +/* + * x_c = (x_c * a + y_c * b) / 255 + */ +#define UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8(x, a, y, b) \ + do \ + { \ + uint32_t r1__, r2__, r3__, t__; \ + \ + r1__ = (x); \ + r2__ = (y); \ + UN8_rb_MUL_UN8 (r1__, (a), t__); \ + UN8_rb_MUL_UN8 (r2__, (b), t__); \ + UN8_rb_ADD_UN8_rb (r1__, r2__, t__); \ + \ + r2__ = ((x) >> G_SHIFT); \ + r3__ = ((y) >> G_SHIFT); \ + UN8_rb_MUL_UN8 (r2__, (a), t__); \ + UN8_rb_MUL_UN8 (r3__, (b), t__); \ + UN8_rb_ADD_UN8_rb (r2__, r3__, t__); \ + \ + (x) = r1__ | (r2__ << G_SHIFT); \ + } while (0) + +/* + * x_c = (x_c * a_c) / 255 + */ +#define UN8x4_MUL_UN8x4(x, a) \ + do \ + { \ + uint32_t r1__, r2__, r3__, t__; \ + \ + r1__ = (x); \ + r2__ = (a); \ + UN8_rb_MUL_UN8_rb (r1__, r2__, t__); \ + \ + r2__ = (x) >> G_SHIFT; \ + r3__ = (a) >> G_SHIFT; \ + UN8_rb_MUL_UN8_rb (r2__, r3__, t__); \ + \ + (x) = r1__ | (r2__ << G_SHIFT); \ + } while (0) + +/* + * x_c = (x_c * a_c) / 255 + y_c + */ +#define UN8x4_MUL_UN8x4_ADD_UN8x4(x, a, y) \ + do \ + { \ + uint32_t r1__, r2__, r3__, t__; \ + \ + r1__ = (x); \ + r2__ = (a); \ + UN8_rb_MUL_UN8_rb (r1__, r2__, t__); \ + r2__ = (y) & RB_MASK; \ + UN8_rb_ADD_UN8_rb (r1__, r2__, t__); \ + \ + r2__ = ((x) >> G_SHIFT); \ + r3__ = ((a) >> G_SHIFT); \ + UN8_rb_MUL_UN8_rb (r2__, r3__, t__); \ + r3__ = ((y) >> G_SHIFT) & RB_MASK; \ + UN8_rb_ADD_UN8_rb (r2__, r3__, t__); \ + \ + (x) = r1__ | (r2__ << G_SHIFT); \ + } while (0) + +/* + * x_c = (x_c * a_c + y_c * b) / 255 + */ +#define UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8(x, a, y, b) \ + do \ + { \ + uint32_t r1__, r2__, r3__, t__; \ + \ + r1__ = (x); \ + r2__ = (a); \ + UN8_rb_MUL_UN8_rb (r1__, r2__, t__); \ + r2__ = (y); \ + UN8_rb_MUL_UN8 (r2__, (b), t__); \ + UN8_rb_ADD_UN8_rb (r1__, r2__, t__); \ + \ + r2__ = (x) >> G_SHIFT; \ + r3__ = (a) >> G_SHIFT; \ + UN8_rb_MUL_UN8_rb (r2__, r3__, t__); \ + r3__ = (y) >> G_SHIFT; \ + UN8_rb_MUL_UN8 (r3__, (b), t__); \ + UN8_rb_ADD_UN8_rb (r2__, r3__, t__); \ + \ + x = r1__ | (r2__ << G_SHIFT); \ + } while (0) + +/* + x_c = min(x_c + y_c, 255) +*/ +#define UN8x4_ADD_UN8x4(x, y) \ + do \ + { \ + uint32_t r1__, r2__, r3__, t__; \ + \ + r1__ = (x) & RB_MASK; \ + r2__ = (y) & RB_MASK; \ + UN8_rb_ADD_UN8_rb (r1__, r2__, t__); \ + \ + r2__ = ((x) >> G_SHIFT) & RB_MASK; \ + r3__ = ((y) >> G_SHIFT) & RB_MASK; \ + UN8_rb_ADD_UN8_rb (r2__, r3__, t__); \ + \ + x = r1__ | (r2__ << G_SHIFT); \ + } while (0) diff --git a/pixman/pixman/pixman-conical-gradient.c b/pixman/pixman/pixman-conical-gradient.c index 05d3595b6..8bb46aecd 100644 --- a/pixman/pixman/pixman-conical-gradient.c +++ b/pixman/pixman/pixman-conical-gradient.c @@ -165,7 +165,8 @@ conical_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask) { uint32_t *buffer = conical_get_scanline_narrow (iter, NULL); - pixman_expand ((uint64_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width); + pixman_expand_to_float ( + (argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width); return buffer; } diff --git a/pixman/pixman/pixman-general.c b/pixman/pixman/pixman-general.c index 42a84a0b4..0bf91e444 100644 --- a/pixman/pixman/pixman-general.c +++ b/pixman/pixman/pixman-general.c @@ -130,7 +130,7 @@ general_composite_rect (pixman_implementation_t *imp, else { narrow = 0; - Bpp = 8; + Bpp = 16; } if (width * Bpp > SCANLINE_BUFFER_LENGTH) @@ -145,6 +145,14 @@ general_composite_rect (pixman_implementation_t *imp, mask_buffer = src_buffer + width * Bpp; dest_buffer = mask_buffer + width * Bpp; + if (!narrow) + { + /* To make sure there aren't any NANs in the buffers */ + memset (src_buffer, 0, width * Bpp); + memset (mask_buffer, 0, width * Bpp); + memset (dest_buffer, 0, width * Bpp); + } + /* src iter */ src_iter_flags = narrow | op_flags[op].src; @@ -212,7 +220,7 @@ _pixman_implementation_create_general (void) pixman_implementation_t *imp = _pixman_implementation_create (NULL, general_fast_path); _pixman_setup_combiner_functions_32 (imp); - _pixman_setup_combiner_functions_64 (imp); + _pixman_setup_combiner_functions_float (imp); imp->src_iter_init = general_src_iter_init; imp->dest_iter_init = general_dest_iter_init; diff --git a/pixman/pixman/pixman-implementation.c b/pixman/pixman/pixman-implementation.c index 5dd050199..a70892c75 100644 --- a/pixman/pixman/pixman-implementation.c +++ b/pixman/pixman/pixman-implementation.c @@ -177,11 +177,11 @@ _pixman_implementation_lookup_combiner (pixman_implementation_t *imp, switch ((narrow << 1) | component_alpha) { case 0: /* not narrow, not component alpha */ - f = (pixman_combine_32_func_t)imp->combine_64[op]; + f = (pixman_combine_32_func_t)imp->combine_float[op]; break; case 1: /* not narrow, component_alpha */ - f = (pixman_combine_32_func_t)imp->combine_64_ca[op]; + f = (pixman_combine_32_func_t)imp->combine_float_ca[op]; break; case 2: /* narrow, not component alpha */ diff --git a/pixman/pixman/pixman-linear-gradient.c b/pixman/pixman/pixman-linear-gradient.c index e51136827..40c8c9f37 100644 --- a/pixman/pixman/pixman-linear-gradient.c +++ b/pixman/pixman/pixman-linear-gradient.c @@ -227,7 +227,8 @@ linear_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask) { uint32_t *buffer = linear_get_scanline_narrow (iter, NULL); - pixman_expand ((uint64_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width); + pixman_expand_to_float ( + (argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width); return buffer; } diff --git a/pixman/pixman/pixman-noop.c b/pixman/pixman/pixman-noop.c index 7b9759ffb..850caa192 100644 --- a/pixman/pixman/pixman-noop.c +++ b/pixman/pixman/pixman-noop.c @@ -93,9 +93,9 @@ noop_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter) } else { - uint64_t color = bits->fetch_pixel_64 (bits, 0, 0); - uint64_t *buffer = (uint64_t *)iter->buffer; - uint64_t *end = buffer + iter->width; + argb_t color = bits->fetch_pixel_float (bits, 0, 0); + argb_t *buffer = (argb_t *)iter->buffer; + argb_t *end = buffer + iter->width; while (buffer < end) *(buffer++) = color; diff --git a/pixman/pixman/pixman-private.h b/pixman/pixman/pixman-private.h index b9c8319df..dd03a939b 100644 --- a/pixman/pixman/pixman-private.h +++ b/pixman/pixman/pixman-private.h @@ -45,6 +45,16 @@ typedef struct radial_gradient radial_gradient_t; typedef struct bits_image bits_image_t; typedef struct circle circle_t; +typedef struct argb_t argb_t; + +struct argb_t +{ + float a; + float r; + float g; + float b; +}; + typedef void (*fetch_scanline_t) (pixman_image_t *image, int x, int y, @@ -56,9 +66,9 @@ typedef uint32_t (*fetch_pixel_32_t) (bits_image_t *image, int x, int y); -typedef uint64_t (*fetch_pixel_64_t) (bits_image_t *image, - int x, - int y); +typedef argb_t (*fetch_pixel_float_t) (bits_image_t *image, + int x, + int y); typedef void (*store_scanline_t) (bits_image_t * image, int x, @@ -112,9 +122,9 @@ struct solid_fill { image_common_t common; pixman_color_t color; - + uint32_t color_32; - uint64_t color_64; + argb_t color_float; }; struct gradient @@ -173,9 +183,9 @@ struct bits_image fetch_pixel_32_t fetch_pixel_32; store_scanline_t store_scanline_32; - fetch_scanline_t fetch_scanline_64; - fetch_pixel_64_t fetch_pixel_64; - store_scanline_t store_scanline_64; + fetch_scanline_t fetch_scanline_float; + fetch_pixel_float_t fetch_pixel_float; + store_scanline_t store_scanline_float; /* Used for indirect access to the bits */ pixman_read_memory_func_t read_func; @@ -414,12 +424,12 @@ typedef void (*pixman_combine_32_func_t) (pixman_implementation_t *imp, const uint32_t * mask, int width); -typedef void (*pixman_combine_64_func_t) (pixman_implementation_t *imp, - pixman_op_t op, - uint64_t * dest, - const uint64_t * src, - const uint64_t * mask, - int width); +typedef void (*pixman_combine_float_func_t) (pixman_implementation_t *imp, + pixman_op_t op, + float * dest, + const float * src, + const float * mask, + int n_pixels); typedef void (*pixman_composite_func_t) (pixman_implementation_t *imp, pixman_composite_info_t *info); @@ -449,7 +459,7 @@ typedef pixman_bool_t (*pixman_iter_init_func_t) (pixman_implementation_t *imp, pixman_iter_t *iter); void _pixman_setup_combiner_functions_32 (pixman_implementation_t *imp); -void _pixman_setup_combiner_functions_64 (pixman_implementation_t *imp); +void _pixman_setup_combiner_functions_float (pixman_implementation_t *imp); typedef struct { @@ -476,8 +486,8 @@ struct pixman_implementation_t pixman_combine_32_func_t combine_32[PIXMAN_N_OPERATORS]; pixman_combine_32_func_t combine_32_ca[PIXMAN_N_OPERATORS]; - pixman_combine_64_func_t combine_64[PIXMAN_N_OPERATORS]; - pixman_combine_64_func_t combine_64_ca[PIXMAN_N_OPERATORS]; + pixman_combine_float_func_t combine_float[PIXMAN_N_OPERATORS]; + pixman_combine_float_func_t combine_float_ca[PIXMAN_N_OPERATORS]; }; uint32_t @@ -754,6 +764,12 @@ get_implementation (void) return global_implementation; } +/* This function is exported for the sake of the test suite and not part + * of the ABI. + */ +PIXMAN_EXPORT pixman_implementation_t * +_pixman_internal_only_get_implementation (void); + /* Memory allocation helpers */ void * pixman_malloc_ab (unsigned int n, unsigned int b); @@ -772,15 +788,15 @@ _pixman_addition_overflows_int (unsigned int a, unsigned int b); /* Compositing utilities */ void -pixman_expand (uint64_t * dst, - const uint32_t * src, - pixman_format_code_t format, - int width); +pixman_expand_to_float (argb_t *dst, + const uint32_t *src, + pixman_format_code_t format, + int width); void -pixman_contract (uint32_t * dst, - const uint64_t *src, - int width); +pixman_contract_from_float (uint32_t *dst, + const argb_t *src, + int width); /* Region Helpers */ pixman_bool_t @@ -941,6 +957,9 @@ unorm_to_unorm (uint32_t val, int from_bits, int to_bits) return result; } +uint16_t pixman_float_to_unorm (float f, int n_bits); +float pixman_unorm_to_float (uint16_t u, int n_bits); + /* * Various debugging code */ @@ -1089,18 +1108,6 @@ void pixman_timer_register (pixman_timer_t *timer); #endif /* PIXMAN_TIMERS */ -/* sRGB<->linear conversion tables. Linear color space is the same - * as sRGB but the components are in linear light (gamma 1.0). - * - * linear_to_srgb maps linear value from 0 to 4095 ([0.0, 1.0]) - * and returns 8-bit sRGB value. - * - * srgb_to_linear maps 8-bit sRGB value to 16-bit linear value - * with range 0 to 65535 ([0.0, 1.0]). - */ -extern const uint8_t linear_to_srgb[4096]; -extern const uint16_t srgb_to_linear[256]; - #endif /* __ASSEMBLER__ */ #endif /* PIXMAN_PRIVATE_H */ diff --git a/pixman/pixman/pixman-radial-gradient.c b/pixman/pixman/pixman-radial-gradient.c index 41bb79d73..8d562468d 100644 --- a/pixman/pixman/pixman-radial-gradient.c +++ b/pixman/pixman/pixman-radial-gradient.c @@ -405,7 +405,8 @@ radial_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask) { uint32_t *buffer = radial_get_scanline_narrow (iter, NULL); - pixman_expand ((uint64_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width); + pixman_expand_to_float ( + (argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width); return buffer; } diff --git a/pixman/pixman/pixman-solid-fill.c b/pixman/pixman/pixman-solid-fill.c index 26f85cea3..60d56d52a 100644 --- a/pixman/pixman/pixman-solid-fill.c +++ b/pixman/pixman/pixman-solid-fill.c @@ -40,9 +40,9 @@ _pixman_solid_fill_iter_init (pixman_image_t *image, pixman_iter_t *iter) } else { - uint64_t *b = (uint64_t *)iter->buffer; - uint64_t *e = b + iter->width; - uint64_t color = image->solid.color_64; + argb_t *b = (argb_t *)iter->buffer; + argb_t *e = b + iter->width; + argb_t color = image->solid.color_float; while (b < e) *(b++) = color; @@ -61,14 +61,17 @@ color_to_uint32 (const pixman_color_t *color) (color->blue >> 8); } -static uint64_t -color_to_uint64 (const pixman_color_t *color) +static argb_t +color_to_float (const pixman_color_t *color) { - return - ((uint64_t)color->alpha << 48) | - ((uint64_t)color->red << 32) | - ((uint64_t)color->green << 16) | - ((uint64_t)color->blue); + argb_t result; + + result.a = pixman_unorm_to_float (color->alpha, 16); + result.r = pixman_unorm_to_float (color->red, 16); + result.g = pixman_unorm_to_float (color->green, 16); + result.b = pixman_unorm_to_float (color->blue, 16); + + return result; } PIXMAN_EXPORT pixman_image_t * @@ -82,7 +85,7 @@ pixman_image_create_solid_fill (const pixman_color_t *color) img->type = SOLID; img->solid.color = *color; img->solid.color_32 = color_to_uint32 (color); - img->solid.color_64 = color_to_uint64 (color); + img->solid.color_float = color_to_float (color); return img; } diff --git a/pixman/pixman/pixman-utils.c b/pixman/pixman/pixman-utils.c index 5633f8f79..b1e9fb62d 100644 --- a/pixman/pixman/pixman-utils.c +++ b/pixman/pixman/pixman-utils.c @@ -71,59 +71,96 @@ pixman_malloc_abc (unsigned int a, return malloc (a * b * c); } -static void -unorm_to_unorm_params (int in_width, int out_width, uint32_t *factor, int *shift) +static force_inline uint16_t +float_to_unorm (float f, int n_bits) { - int w = 0; + uint32_t u; - *factor = 0; - while (in_width != 0 && w < out_width) - { - *factor |= 1 << w; - w += in_width; - } + if (f > 1.0) + f = 1.0; + if (f < 0.0) + f = 0.0; + + u = f * (1 << n_bits); + u -= (u >> n_bits); + + return u; +} + +static force_inline float +unorm_to_float (uint16_t u, int n_bits) +{ + uint32_t m = ((1 << n_bits) - 1); - /* Did we generate too many bits? */ - *shift = w - out_width; + return (u & m) * (1.f / (float)m); } /* - * This function expands images from ARGB8 format to ARGB16. To preserve - * precision, it needs to know the original source format. For example, if the - * source was PIXMAN_x1r5g5b5 and the red component contained bits 12345, then - * the expanded value is 12345123. To correctly expand this to 16 bits, it - * should be 1234512345123451 and not 1234512312345123. + * This function expands images from a8r8g8b8 to argb_t. To preserve + * precision, it needs to know from which source format the a8r8g8b8 pixels + * originally came. + * + * For example, if the source was PIXMAN_x1r5g5b5 and the red component + * contained bits 12345, then the 8-bit value is 12345123. To correctly + * expand this to floating point, it should be 12345 / 31.0 and not + * 12345123 / 255.0. */ void -pixman_expand (uint64_t * dst, - const uint32_t * src, - pixman_format_code_t format, - int width) +pixman_expand_to_float (argb_t *dst, + const uint32_t *src, + pixman_format_code_t format, + int width) { + static const float multipliers[16] = { + 0.0f, + 1.0f / ((1 << 1) - 1), + 1.0f / ((1 << 2) - 1), + 1.0f / ((1 << 3) - 1), + 1.0f / ((1 << 4) - 1), + 1.0f / ((1 << 5) - 1), + 1.0f / ((1 << 6) - 1), + 1.0f / ((1 << 7) - 1), + 1.0f / ((1 << 8) - 1), + 1.0f / ((1 << 9) - 1), + 1.0f / ((1 << 10) - 1), + 1.0f / ((1 << 11) - 1), + 1.0f / ((1 << 12) - 1), + 1.0f / ((1 << 13) - 1), + 1.0f / ((1 << 14) - 1), + 1.0f / ((1 << 15) - 1), + }; + int a_size, r_size, g_size, b_size; + int a_shift, r_shift, g_shift, b_shift; + float a_mul, r_mul, g_mul, b_mul; + uint32_t a_mask, r_mask, g_mask, b_mask; + int i; + + if (!PIXMAN_FORMAT_VIS (format)) + format = PIXMAN_a8r8g8b8; + /* * Determine the sizes of each component and the masks and shifts * required to extract them from the source pixel. */ - const int a_size = PIXMAN_FORMAT_A (format), - r_size = PIXMAN_FORMAT_R (format), - g_size = PIXMAN_FORMAT_G (format), - b_size = PIXMAN_FORMAT_B (format); - const int a_shift = 32 - a_size, - r_shift = 24 - r_size, - g_shift = 16 - g_size, - b_shift = 8 - b_size; - const uint8_t a_mask = ~(~0 << a_size), - r_mask = ~(~0 << r_size), - g_mask = ~(~0 << g_size), - b_mask = ~(~0 << b_size); - uint32_t au_factor, ru_factor, gu_factor, bu_factor; - int au_shift, ru_shift, gu_shift, bu_shift; - int i; - - unorm_to_unorm_params (a_size, 16, &au_factor, &au_shift); - unorm_to_unorm_params (r_size, 16, &ru_factor, &ru_shift); - unorm_to_unorm_params (g_size, 16, &gu_factor, &gu_shift); - unorm_to_unorm_params (b_size, 16, &bu_factor, &bu_shift); + a_size = PIXMAN_FORMAT_A (format); + r_size = PIXMAN_FORMAT_R (format); + g_size = PIXMAN_FORMAT_G (format); + b_size = PIXMAN_FORMAT_B (format); + + a_shift = 32 - a_size; + r_shift = 24 - r_size; + g_shift = 16 - g_size; + b_shift = 8 - b_size; + + a_mask = ((1 << a_size) - 1); + r_mask = ((1 << r_size) - 1); + g_mask = ((1 << g_size) - 1); + b_mask = ((1 << b_size) - 1); + + a_mul = multipliers[a_size]; + r_mul = multipliers[r_size]; + g_mul = multipliers[g_size]; + b_mul = multipliers[b_size]; /* Start at the end so that we can do the expansion in place * when src == dst @@ -131,59 +168,43 @@ pixman_expand (uint64_t * dst, for (i = width - 1; i >= 0; i--) { const uint32_t pixel = src[i]; - uint8_t a, r, g, b; - uint64_t a16, r16, g16, b16; - - if (a_size) - { - a = (pixel >> a_shift) & a_mask; - a16 = a * au_factor >> au_shift; - } - else - { - a16 = 0xffff; - } - - if (r_size) - { - r = (pixel >> r_shift) & r_mask; - g = (pixel >> g_shift) & g_mask; - b = (pixel >> b_shift) & b_mask; - r16 = r * ru_factor >> ru_shift; - g16 = g * gu_factor >> gu_shift; - b16 = b * bu_factor >> bu_shift; - } - else - { - r16 = g16 = b16 = 0; - } - - dst[i] = a16 << 48 | r16 << 32 | g16 << 16 | b16; + + dst[i].a = a_mask? ((pixel >> a_shift) & a_mask) * a_mul : 1.0f; + dst[i].r = ((pixel >> r_shift) & r_mask) * r_mul; + dst[i].g = ((pixel >> g_shift) & g_mask) * g_mul; + dst[i].b = ((pixel >> b_shift) & b_mask) * b_mul; } } -/* - * Contracting is easier than expanding. We just need to truncate the - * components. - */ +uint16_t +pixman_float_to_unorm (float f, int n_bits) +{ + return float_to_unorm (f, n_bits); +} + +float +pixman_unorm_to_float (uint16_t u, int n_bits) +{ + return unorm_to_float (u, n_bits); +} + void -pixman_contract (uint32_t * dst, - const uint64_t *src, - int width) +pixman_contract_from_float (uint32_t *dst, + const argb_t *src, + int width) { int i; - /* Start at the beginning so that we can do the contraction in - * place when src == dst - */ - for (i = 0; i < width; i++) + for (i = 0; i < width; ++i) { - const uint8_t a = src[i] >> 56, - r = src[i] >> 40, - g = src[i] >> 24, - b = src[i] >> 8; + uint8_t a, r, g, b; - dst[i] = a << 24 | r << 16 | g << 8 | b; + a = float_to_unorm (src[i].a, 8); + r = float_to_unorm (src[i].r, 8); + g = float_to_unorm (src[i].g, 8); + b = float_to_unorm (src[i].b, 8); + + dst[i] = (a << 24) | (r << 16) | (g << 8) | (b << 0); } } @@ -262,6 +283,15 @@ pixman_region32_copy_from_region16 (pixman_region32_t *dst, return retval; } +/* This function is exported for the sake of the test suite and not part + * of the ABI. + */ +PIXMAN_EXPORT pixman_implementation_t * +_pixman_internal_only_get_implementation (void) +{ + return get_implementation (); +} + #ifdef DEBUG void diff --git a/pixman/test/Makefile.sources b/pixman/test/Makefile.sources index 0f344116d..077897161 100644 --- a/pixman/test/Makefile.sources +++ b/pixman/test/Makefile.sources @@ -4,6 +4,7 @@ TESTPROGRAMS = \ pdf-op-test \ region-test \ region-translate-test \ + combiner-test \ fetch-test \ rotate-test \ oob-test \ diff --git a/pixman/test/blitters-test.c b/pixman/test/blitters-test.c index 8c46cef97..30d69124c 100644 --- a/pixman/test/blitters-test.c +++ b/pixman/test/blitters-test.c @@ -172,10 +172,12 @@ static pixman_format_code_t img_fmt_list[] = { PIXMAN_x14r6g6b6, PIXMAN_r8g8b8, PIXMAN_b8g8r8, +#if 0 /* These are going to use floating point in the near future */ PIXMAN_x2r10g10b10, PIXMAN_a2r10g10b10, PIXMAN_x2b10g10r10, PIXMAN_a2b10g10r10, +#endif PIXMAN_a1r5g5b5, PIXMAN_x1r5g5b5, PIXMAN_a1b5g5r5, @@ -395,6 +397,6 @@ main (int argc, const char *argv[]) } return fuzzer_test_main("blitters", 2000000, - 0x3E1DD2E8, + 0x46136E0A, test_composite, argc, argv); } diff --git a/pixman/test/combiner-test.c b/pixman/test/combiner-test.c new file mode 100644 index 000000000..c438ae62e --- /dev/null +++ b/pixman/test/combiner-test.c @@ -0,0 +1,151 @@ +#include +#include +#include "utils.h" +#include +#include "pixman-private.h" + +static const pixman_op_t op_list[] = +{ + PIXMAN_OP_SRC, + PIXMAN_OP_OVER, + PIXMAN_OP_ADD, + PIXMAN_OP_CLEAR, + PIXMAN_OP_SRC, + PIXMAN_OP_DST, + PIXMAN_OP_OVER, + PIXMAN_OP_OVER_REVERSE, + PIXMAN_OP_IN, + PIXMAN_OP_IN_REVERSE, + PIXMAN_OP_OUT, + PIXMAN_OP_OUT_REVERSE, + PIXMAN_OP_ATOP, + PIXMAN_OP_ATOP_REVERSE, + PIXMAN_OP_XOR, + PIXMAN_OP_ADD, + PIXMAN_OP_SATURATE, + PIXMAN_OP_DISJOINT_CLEAR, + PIXMAN_OP_DISJOINT_SRC, + PIXMAN_OP_DISJOINT_DST, + PIXMAN_OP_DISJOINT_OVER, + PIXMAN_OP_DISJOINT_OVER_REVERSE, + PIXMAN_OP_DISJOINT_IN, + PIXMAN_OP_DISJOINT_IN_REVERSE, + PIXMAN_OP_DISJOINT_OUT, + PIXMAN_OP_DISJOINT_OUT_REVERSE, + PIXMAN_OP_DISJOINT_ATOP, + PIXMAN_OP_DISJOINT_ATOP_REVERSE, + PIXMAN_OP_DISJOINT_XOR, + PIXMAN_OP_CONJOINT_CLEAR, + PIXMAN_OP_CONJOINT_SRC, + PIXMAN_OP_CONJOINT_DST, + PIXMAN_OP_CONJOINT_OVER, + PIXMAN_OP_CONJOINT_OVER_REVERSE, + PIXMAN_OP_CONJOINT_IN, + PIXMAN_OP_CONJOINT_IN_REVERSE, + PIXMAN_OP_CONJOINT_OUT, + PIXMAN_OP_CONJOINT_OUT_REVERSE, + PIXMAN_OP_CONJOINT_ATOP, + PIXMAN_OP_CONJOINT_ATOP_REVERSE, + PIXMAN_OP_CONJOINT_XOR, + PIXMAN_OP_MULTIPLY, + PIXMAN_OP_SCREEN, + PIXMAN_OP_OVERLAY, + PIXMAN_OP_DARKEN, + PIXMAN_OP_LIGHTEN, + PIXMAN_OP_COLOR_DODGE, + PIXMAN_OP_COLOR_BURN, + PIXMAN_OP_HARD_LIGHT, + PIXMAN_OP_DIFFERENCE, + PIXMAN_OP_EXCLUSION, + PIXMAN_OP_SOFT_LIGHT, + PIXMAN_OP_HSL_HUE, + PIXMAN_OP_HSL_SATURATION, + PIXMAN_OP_HSL_COLOR, + PIXMAN_OP_HSL_LUMINOSITY, +}; + +static float +rand_float (void) +{ + uint32_t u = lcg_rand_u32(); + + return *(float *)&u; +} + +static void +random_floats (argb_t *argb, int width) +{ + int i; + + for (i = 0; i < width; ++i) + { + argb_t *p = argb + i; + + p->a = rand_float(); + p->r = rand_float(); + p->g = rand_float(); + p->b = rand_float(); + } +} + +#define WIDTH 512 + +static pixman_combine_float_func_t +lookup_combiner (pixman_implementation_t *imp, pixman_op_t op, + pixman_bool_t component_alpha) +{ + pixman_combine_float_func_t f; + + do + { + if (component_alpha) + f = imp->combine_float_ca[op]; + else + f = imp->combine_float[op]; + + imp = imp->fallback; + } + while (!f); + + return f; +} + +int +main () +{ + pixman_implementation_t *impl; + argb_t *src_bytes = malloc (WIDTH * sizeof (argb_t)); + argb_t *mask_bytes = malloc (WIDTH * sizeof (argb_t)); + argb_t *dest_bytes = malloc (WIDTH * sizeof (argb_t)); + int i; + + enable_divbyzero_exceptions(); + + impl = _pixman_internal_only_get_implementation(); + + lcg_srand (0); + + for (i = 0; i < ARRAY_LENGTH (op_list); ++i) + { + pixman_op_t op = op_list[i]; + pixman_combine_float_func_t combiner; + int ca; + + for (ca = 0; ca < 2; ++ca) + { + combiner = lookup_combiner (impl, op, ca); + + random_floats (src_bytes, WIDTH); + random_floats (mask_bytes, WIDTH); + random_floats (dest_bytes, WIDTH); + + combiner (impl, op, + (float *)dest_bytes, + (float *)mask_bytes, + (float *)src_bytes, + WIDTH); + } + } + + return 0; +} diff --git a/pixman/test/glyph-test.c b/pixman/test/glyph-test.c index 84de5aace..9dd5b41e4 100644 --- a/pixman/test/glyph-test.c +++ b/pixman/test/glyph-test.c @@ -30,10 +30,13 @@ static const pixman_format_code_t formats[] = PIXMAN_x14r6g6b6, PIXMAN_r8g8b8, PIXMAN_b8g8r8, +#if 0 + /* These use floating point */ PIXMAN_x2r10g10b10, PIXMAN_a2r10g10b10, PIXMAN_x2b10g10r10, PIXMAN_a2b10g10r10, +#endif PIXMAN_a1r5g5b5, PIXMAN_x1r5g5b5, PIXMAN_a1b5g5r5, @@ -329,7 +332,7 @@ test_glyphs (int testnum, int verbose) int main (int argc, const char *argv[]) { - return fuzzer_test_main ("glyph", 30000, - 0x741CB2DB, + return fuzzer_test_main ("glyph", 30000, + 0x79E74996, test_glyphs, argc, argv); } diff --git a/pixman/test/gradient-crash-test.c b/pixman/test/gradient-crash-test.c index 73e5bbcd5..962d1cbe8 100644 --- a/pixman/test/gradient-crash-test.c +++ b/pixman/test/gradient-crash-test.c @@ -85,7 +85,7 @@ main (int argc, char **argv) pixman_fixed_t r_inner; pixman_fixed_t r_outer; - enable_fp_exceptions(); + enable_divbyzero_exceptions(); for (i = 0; i < WIDTH * HEIGHT; ++i) dest[i] = 0x4f00004f; /* pale blue */ diff --git a/pixman/test/pdf-op-test.c b/pixman/test/pdf-op-test.c index 99cb7dfea..dcb3a603a 100644 --- a/pixman/test/pdf-op-test.c +++ b/pixman/test/pdf-op-test.c @@ -36,7 +36,7 @@ main () { int o, s, m, d; - enable_fp_exceptions(); + enable_divbyzero_exceptions(); for (o = 0; o < ARRAY_LENGTH (pdf_ops); ++o) { diff --git a/pixman/test/stress-test.c b/pixman/test/stress-test.c index edcfe0947..059250dd4 100644 --- a/pixman/test/stress-test.c +++ b/pixman/test/stress-test.c @@ -850,7 +850,7 @@ main (int argc, char **argv) pixman_disable_out_of_bounds_workaround (); - enable_fp_exceptions(); + enable_divbyzero_exceptions(); if (getenv ("VERBOSE") != NULL) verbose = TRUE; diff --git a/pixman/test/utils.c b/pixman/test/utils.c index c922ae5d5..716bb7594 100644 --- a/pixman/test/utils.c +++ b/pixman/test/utils.c @@ -723,21 +723,11 @@ fail_after (int seconds, const char *msg) } void -enable_fp_exceptions (void) +enable_divbyzero_exceptions (void) { #ifdef HAVE_FENV_H #ifdef HAVE_FEENABLEEXCEPT - /* Note: we don't enable the FE_INEXACT trap because - * that happens quite commonly. It is possible that - * over- and underflow should similarly be considered - * okay, but for now the test suite passes with them - * enabled, and it's useful to know if they start - * occuring. - */ - feenableexcept (FE_DIVBYZERO | - FE_INVALID | - FE_OVERFLOW | - FE_UNDERFLOW); + feenableexcept (FE_DIVBYZERO); #endif #endif } diff --git a/pixman/test/utils.h b/pixman/test/utils.h index faf427f0a..f7ea34c5f 100644 --- a/pixman/test/utils.h +++ b/pixman/test/utils.h @@ -110,7 +110,7 @@ void fail_after (int seconds, const char *msg); /* If possible, enable traps for floating point exceptions */ -void enable_fp_exceptions(void); +void enable_divbyzero_exceptions(void); /* Converts a8r8g8b8 pixels to pixels that * - are not premultiplied, diff --git a/xorg-server/Xext/xf86bigfont.c b/xorg-server/Xext/xf86bigfont.c index b4ef5e460..faf81f7dc 100644 --- a/xorg-server/Xext/xf86bigfont.c +++ b/xorg-server/Xext/xf86bigfont.c @@ -288,7 +288,7 @@ ProcXF86BigfontQueryVersion(ClientPtr client) .gid = getegid(), #ifdef HAS_SHM .signature = signature, - .capabilities = (LocalClient(client) && !client->swapped) + .capabilities = (client->local && !client->swapped) ? XF86Bigfont_CAP_LocalShm : 0 #else .signature = 0, @@ -357,7 +357,7 @@ ProcXF86BigfontQueryFont(ClientPtr client) #else switch (client->req_len) { case 2: /* client with version 1.0 libX11 */ - stuff_flags = (LocalClient(client) && + stuff_flags = (client->local && !client->swapped ? XF86Bigfont_FLAGS_Shm : 0); break; case 3: /* client with version 1.1 libX11 */ diff --git a/xorg-server/Xi/exevents.c b/xorg-server/Xi/exevents.c index 494d07e20..6ed499142 100644 --- a/xorg-server/Xi/exevents.c +++ b/xorg-server/Xi/exevents.c @@ -949,8 +949,6 @@ UpdateDeviceState(DeviceIntPtr device, DeviceEvent *event) if (!(event->flags & TOUCH_POINTER_EMULATED)) return DONT_PROCESS; - if (!(event->flags & TOUCH_END)) - return DONT_PROCESS; DecreaseButtonCount(device, key, &t->buttonsDown, &t->motionMask, &t->state); diff --git a/xorg-server/Xi/xiselectev.c b/xorg-server/Xi/xiselectev.c index 0e45cb8cb..ab1b6245f 100644 --- a/xorg-server/Xi/xiselectev.c +++ b/xorg-server/Xi/xiselectev.c @@ -180,8 +180,13 @@ ProcXISelectEvents(ClientPtr client) if (CLIENT_ID(iclient->resource) == client->index) continue; - dixLookupDevice(&tmp, evmask->deviceid, serverClient, - DixReadAccess); + if (evmask->deviceid == XIAllDevices) + tmp = inputInfo.all_devices; + else if (evmask->deviceid == XIAllMasterDevices) + tmp = inputInfo.all_master_devices; + else + dixLookupDevice(&tmp, evmask->deviceid, serverClient, + DixReadAccess); if (!tmp) return BadImplementation; /* this shouldn't happen */ diff --git a/xorg-server/autogen.sh b/xorg-server/autogen.sh index 588fef395..8b6f58f69 100644 --- a/xorg-server/autogen.sh +++ b/xorg-server/autogen.sh @@ -1,12 +1,12 @@ -#! /bin/sh - -srcdir=`dirname $0` -test -z "$srcdir" && srcdir=. - -ORIGDIR=`pwd` -cd $srcdir - -autoreconf --force -v --install || exit 1 -cd $ORIGDIR || exit $? - -$srcdir/configure --enable-maintainer-mode "$@" +#! /bin/sh + +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +ORIGDIR=`pwd` +cd $srcdir + +autoreconf --force -v --install || exit 1 +cd $ORIGDIR || exit $? + +$srcdir/configure "$@" diff --git a/xorg-server/configure.ac b/xorg-server/configure.ac index ac3bf26f1..e6866140e 100644 --- a/xorg-server/configure.ac +++ b/xorg-server/configure.ac @@ -26,12 +26,11 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.60) -AC_INIT([xorg-server], 1.13.0, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server) -RELEASE_DATE="2012-09-05" -RELEASE_NAME="Iced Tea" +AC_INIT([xorg-server], 1.13.99.0, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server) +RELEASE_DATE="2012-10-04" +RELEASE_NAME="Horchata" AC_CONFIG_SRCDIR([Makefile.am]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) -AM_MAINTAINER_MODE # Require xorg-macros minimum of 1.14 for XORG_COMPILER_BRAND in XORG_DEFAULT_OPTIONS m4_ifndef([XORG_MACROS_VERSION], diff --git a/xorg-server/dix/dispatch.c b/xorg-server/dix/dispatch.c index 0ce10c2f7..2df1a6ea5 100644 --- a/xorg-server/dix/dispatch.c +++ b/xorg-server/dix/dispatch.c @@ -3499,14 +3499,16 @@ ProcInitialConnection(ClientPtr client) REQUEST(xReq); xConnClientPrefix *prefix; int whichbyte = 1; + char order; - prefix = (xConnClientPrefix *) ((char *) stuff + sz_xReq); - if ((prefix->byteOrder != 'l') && (prefix->byteOrder != 'B')) - return client->noClientException = -1; - if (((*(char *) &whichbyte) && (prefix->byteOrder == 'B')) || - (!(*(char *) &whichbyte) && (prefix->byteOrder == 'l'))) { - client->swapped = TRUE; - SwapConnClientPrefix(prefix); + prefix = (xConnClientPrefix *) ((char *)stuff + sz_xReq); + order = prefix->byteOrder; + if (order != 'l' && order != 'B' && order != 'r' && order != 'R') + return client->noClientException = -1; + if (((*(char *) &whichbyte) && (order == 'B' || order == 'R')) || + (!(*(char *) &whichbyte) && (order == 'l' || order == 'r'))) { + client->swapped = TRUE; + SwapConnClientPrefix(prefix); } stuff->reqType = 2; stuff->length += bytes_to_int32(prefix->nbytesAuthProto) + @@ -3514,6 +3516,9 @@ ProcInitialConnection(ClientPtr client) if (client->swapped) { swaps(&stuff->length); } + if (order == 'r' || order == 'R') { + client->local = FALSE; + } ResetCurrentRequest(client); return Success; } diff --git a/xorg-server/dix/events.c b/xorg-server/dix/events.c index 3b40446bc..c0e330b85 100644 --- a/xorg-server/dix/events.c +++ b/xorg-server/dix/events.c @@ -1555,11 +1555,13 @@ ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, WindowPtr oldWin; /* slave devices need to float for the duration of the grab. */ - if (grab->grabtype == XI2 && + if (grab->grabtype == XI2 && keybd->enabled && !(passive & ImplicitGrabMask) && !IsMaster(keybd)) DetachFromMaster(keybd); - if (grabinfo->grab) + if (!keybd->enabled) + oldWin = NULL; + else if (grabinfo->grab) oldWin = grabinfo->grab->window; else if (keybd->focus) oldWin = keybd->focus->win; @@ -1569,7 +1571,8 @@ ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, oldWin = keybd->focus->win; if (keybd->valuator) keybd->valuator->motionHintWindow = NullWindow; - DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab); + if (oldWin) + DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab); if (syncEvents.playingEvents) grabinfo->grabTime = syncEvents.time; else diff --git a/xorg-server/hw/kdrive/ephyr/ephyrdriext.c b/xorg-server/hw/kdrive/ephyr/ephyrdriext.c index a42be07d5..1a98a2dff 100644 --- a/xorg-server/hw/kdrive/ephyr/ephyrdriext.c +++ b/xorg-server/hw/kdrive/ephyr/ephyrdriext.c @@ -561,7 +561,7 @@ ProcXF86DRIQueryDirectRenderingCapable(register ClientPtr client) return BadValue; } - if (!LocalClient(client) || client->swapped) + if (!client->local || client->swapped) isCapable = 0; rep = (xXF86DRIQueryDirectRenderingCapableReply) { @@ -1229,7 +1229,7 @@ ProcXF86DRIDispatch(register ClientPtr client) } } - if (!LocalClient(client)) + if (!client->local) return DRIErrorBase + XF86DRIClientNotLocal; switch (stuff->data) { diff --git a/xorg-server/hw/kdrive/ephyr/ephyrglxext.c b/xorg-server/hw/kdrive/ephyr/ephyrglxext.c index df285cfcb..22d510891 100644 --- a/xorg-server/hw/kdrive/ephyr/ephyrglxext.c +++ b/xorg-server/hw/kdrive/ephyr/ephyrglxext.c @@ -61,10 +61,16 @@ int ephyrGLXGetFBConfigsSGIX(__GLXclientState * a_cl, GLbyte * a_pc); int ephyrGLXGetFBConfigsSGIXSwap(__GLXclientState * a_cl, GLbyte * a_pc); int ephyrGLXCreateContext(__GLXclientState * a_cl, GLbyte * a_pc); int ephyrGLXCreateContextSwap(__GLXclientState * a_cl, GLbyte * a_pc); +int ephyrGLXCreateNewContext(__GLXclientState * a_cl, GLbyte * a_pc); +int ephyrGLXCreateNewContextSwap(__GLXclientState * a_cl, GLbyte * a_pc); int ephyrGLXDestroyContext(__GLXclientState * a_cl, GLbyte * a_pc); int ephyrGLXDestroyContextSwap(__GLXclientState * a_cl, GLbyte * a_pc); int ephyrGLXMakeCurrent(__GLXclientState * a_cl, GLbyte * a_pc); int ephyrGLXMakeCurrentSwap(__GLXclientState * a_cl, GLbyte * a_pc); +int ephyrGLXMakeCurrentReadSGI(__GLXclientState * a_cl, GLbyte * a_pc); +int ephyrGLXMakeCurrentReadSGISwap(__GLXclientState * a_cl, GLbyte * a_pc); +int ephyrGLXMakeContextCurrent(__GLXclientState * a_cl, GLbyte * a_pc); +int ephyrGLXMakeContextCurrentSwap(__GLXclientState * a_cl, GLbyte * a_pc); int ephyrGLXGetString(__GLXclientState * a_cl, GLbyte * a_pc); int ephyrGLXGetStringSwap(__GLXclientState * a_cl, GLbyte * a_pc); int ephyrGLXGetIntegerv(__GLXclientState * a_cl, GLbyte * a_pc); @@ -108,6 +114,9 @@ ephyrHijackGLXExtension(void) dispatch_functions[X_GLXCreateContext][0] = ephyrGLXCreateContext; dispatch_functions[X_GLXCreateContext][1] = ephyrGLXCreateContextSwap; + dispatch_functions[X_GLXCreateNewContext][0] = ephyrGLXCreateNewContext; + dispatch_functions[X_GLXCreateNewContext][1] = ephyrGLXCreateNewContextSwap; + dispatch_functions[X_GLXDestroyContext][0] = ephyrGLXDestroyContext; dispatch_functions[X_GLXDestroyContext][1] = ephyrGLXDestroyContextSwap; @@ -123,14 +132,24 @@ ephyrHijackGLXExtension(void) dispatch_functions[61][0] = ephyrGLXGetIntegerv; dispatch_functions[61][1] = ephyrGLXGetIntegervSwap; + dispatch_functions[X_GLXMakeContextCurrent][0] = + ephyrGLXMakeContextCurrent; + dispatch_functions[X_GLXMakeContextCurrent][1] = + ephyrGLXMakeContextCurrentSwap; + /* * hijack some vendor priv entry point dispatch functions */ dispatch_functions = VendorPriv_dispatch_info.dispatch_functions; dispatch_functions[92][0] = ephyrGLXGetFBConfigsSGIX; dispatch_functions[92][1] = ephyrGLXGetFBConfigsSGIXSwap; + + dispatch_functions[89][0] = ephyrGLXMakeCurrentReadSGI; + dispatch_functions[89][1] = ephyrGLXMakeCurrentReadSGISwap; + EPHYR_LOG("hijacked glx entry points to forward requests to host X\n"); + return TRUE; } @@ -445,7 +464,8 @@ ephyrGLXCreateContextReal(xGLXCreateContextReq * a_req, Bool a_do_swap) if (!ephyrHostGLXCreateContext(a_req->screen, host_w_attrs.visualid, a_req->context, - a_req->shareList, a_req->isDirect)) { + a_req->shareList, 0, + a_req->isDirect, X_GLXCreateContext)) { EPHYR_LOG_ERROR("ephyrHostGLXCreateContext() failed\n"); goto out; } @@ -455,6 +475,45 @@ ephyrGLXCreateContextReal(xGLXCreateContextReq * a_req, Bool a_do_swap) return res; } +static int +ephyrGLXCreateNewContextReal(xGLXCreateNewContextReq * a_req, Bool a_do_swap) +{ + int res = BadImplementation; + + __GLX_DECLARE_SWAP_VARIABLES; + + EPHYR_RETURN_VAL_IF_FAIL(a_req, BadValue); + EPHYR_LOG("enter\n"); + + if (a_do_swap) { + __GLX_SWAP_SHORT(&a_req->length); + __GLX_SWAP_INT(&a_req->context); + __GLX_SWAP_INT(&a_req->fbconfig); + __GLX_SWAP_INT(&a_req->screen); + __GLX_SWAP_INT(&a_req->renderType); + __GLX_SWAP_INT(&a_req->shareList); + } + + EPHYR_LOG("context creation requested. localid:%d, " + "screen:%d, fbconfig:%d, renderType:%d, direct:%d\n", + (int) a_req->context, (int) a_req->screen, + (int) a_req->fbconfig, (int) a_req->renderType, + (int) a_req->isDirect); + + if (!ephyrHostGLXCreateContext(a_req->screen, + a_req->fbconfig, + a_req->context, + a_req->shareList, a_req->renderType, + a_req->isDirect, X_GLXCreateNewContext)) { + EPHYR_LOG_ERROR("ephyrHostGLXCreateNewContext() failed\n"); + goto out; + } + res = Success; + out: + EPHYR_LOG("leave\n"); + return res; +} + int ephyrGLXCreateContext(__GLXclientState * cl, GLbyte * pc) { @@ -471,6 +530,22 @@ ephyrGLXCreateContextSwap(__GLXclientState * cl, GLbyte * pc) return ephyrGLXCreateContextReal(req, TRUE); } +int +ephyrGLXCreateNewContext(__GLXclientState * cl, GLbyte * pc) +{ + xGLXCreateNewContextReq *req = (xGLXCreateNewContextReq *) pc; + + return ephyrGLXCreateNewContextReal(req, FALSE); +} + +int +ephyrGLXCreateNewContextSwap(__GLXclientState * cl, GLbyte * pc) +{ + xGLXCreateNewContextReq *req = (xGLXCreateNewContextReq *) pc; + + return ephyrGLXCreateNewContextReal(req, TRUE); +} + static int ephyrGLXDestroyContextReal(__GLXclientState * a_cl, GLbyte * a_pc, Bool a_do_swap) @@ -505,26 +580,34 @@ ephyrGLXDestroyContextSwap(__GLXclientState * a_cl, GLbyte * a_pc) } static int -ephyrGLXMakeCurrentReal(__GLXclientState * a_cl, GLbyte * a_pc, Bool a_do_swap) +ephyrGLXMakeCurrentReal(__GLXclientState * a_cl, GLXDrawable write, + GLXDrawable read, GLXContextTag ctx, + GLXContextTag old_ctx, Bool a_do_swap) { int res = BadImplementation; - xGLXMakeCurrentReq *req = (xGLXMakeCurrentReq *) a_pc; xGLXMakeCurrentReply reply; - DrawablePtr drawable = NULL; - GLXContextTag contextTag = 0; - int rc = 0; + DrawablePtr drawableR = NULL, drawableW = NULL; + GLXContextTag new_ctx = 0; EPHYR_LOG("enter\n"); - rc = dixLookupDrawable(&drawable, - req->drawable, a_cl->client, 0, DixReadAccess); - EPHYR_RETURN_VAL_IF_FAIL(drawable, BadValue); - EPHYR_RETURN_VAL_IF_FAIL(drawable->pScreen, BadValue); - EPHYR_LOG("screen nummber requested:%d\n", drawable->pScreen->myNum); - - if (!ephyrHostGLXMakeCurrent(hostx_get_window(drawable->pScreen->myNum), - req->context, - req->oldContextTag, - (int *) &contextTag)) { + res = dixLookupDrawable(&drawableW, write, a_cl->client, 0, DixReadAccess); + EPHYR_RETURN_VAL_IF_FAIL(drawableW, BadValue); + EPHYR_RETURN_VAL_IF_FAIL(drawableW->pScreen, BadValue); + EPHYR_LOG("screen nummber requested:%d\n", drawableW->pScreen->myNum); + + if (read != write) { + res = dixLookupDrawable(&drawableR, read, a_cl->client, 0, + DixReadAccess); + EPHYR_RETURN_VAL_IF_FAIL(drawableR, BadValue); + EPHYR_RETURN_VAL_IF_FAIL(drawableR->pScreen, BadValue); + } + else { + drawableR = drawableW; + } + + if (!ephyrHostGLXMakeCurrent(hostx_get_window(drawableW->pScreen->myNum), + hostx_get_window(drawableR->pScreen->myNum), + ctx, old_ctx, (int *) &new_ctx)) { EPHYR_LOG_ERROR("ephyrHostGLXMakeCurrent() failed\n"); goto out; } @@ -532,7 +615,7 @@ ephyrGLXMakeCurrentReal(__GLXclientState * a_cl, GLbyte * a_pc, Bool a_do_swap) .type = X_Reply, .sequenceNumber = a_cl->client->sequence, .length = 0, - .contextTag = contextTag + .contextTag = new_ctx }; if (a_do_swap) { __GLX_DECLARE_SWAP_VARIABLES; @@ -551,13 +634,71 @@ ephyrGLXMakeCurrentReal(__GLXclientState * a_cl, GLbyte * a_pc, Bool a_do_swap) int ephyrGLXMakeCurrent(__GLXclientState * a_cl, GLbyte * a_pc) { - return ephyrGLXMakeCurrentReal(a_cl, a_pc, FALSE); + xGLXMakeCurrentReq *req = (xGLXMakeCurrentReq *) a_pc; + return ephyrGLXMakeCurrentReal(a_cl, req->drawable, req->drawable, + req->context, req->oldContextTag, FALSE); } int ephyrGLXMakeCurrentSwap(__GLXclientState * a_cl, GLbyte * a_pc) { - return ephyrGLXMakeCurrentReal(a_cl, a_pc, TRUE); + xGLXMakeCurrentReq *req = (xGLXMakeCurrentReq *) a_pc; + __GLX_DECLARE_SWAP_VARIABLES; + + __GLX_SWAP_INT(&req->drawable); + __GLX_SWAP_INT(&req->context); + __GLX_SWAP_INT(&req->oldContextTag); + + return ephyrGLXMakeCurrentReal(a_cl, req->drawable, req->drawable, + req->context, req->oldContextTag, TRUE); +} + +int +ephyrGLXMakeCurrentReadSGI(__GLXclientState * a_cl, GLbyte * a_pc) +{ + xGLXMakeCurrentReadSGIReq *req = (xGLXMakeCurrentReadSGIReq *) a_pc; + + return ephyrGLXMakeCurrentReal(a_cl, req->drawable, req->readable, + req->context, req->oldContextTag, FALSE); +} + +int +ephyrGLXMakeCurrentReadSGISwap(__GLXclientState * a_cl, GLbyte * a_pc) +{ + xGLXMakeCurrentReadSGIReq *req = (xGLXMakeCurrentReadSGIReq *) a_pc; + __GLX_DECLARE_SWAP_VARIABLES; + + __GLX_SWAP_INT(&req->drawable); + __GLX_SWAP_INT(&req->readable); + __GLX_SWAP_INT(&req->context); + __GLX_SWAP_INT(&req->oldContextTag); + + return ephyrGLXMakeCurrentReal(a_cl, req->drawable, req->readable, + req->context, req->oldContextTag, TRUE); +} + +int +ephyrGLXMakeContextCurrent(__GLXclientState * a_cl, GLbyte * a_pc) +{ + xGLXMakeContextCurrentReq *req = (xGLXMakeContextCurrentReq *) a_pc; + + return ephyrGLXMakeCurrentReal(a_cl, req->drawable, req->readdrawable, + req->context, req->oldContextTag, FALSE); +} + +int +ephyrGLXMakeContextCurrentSwap(__GLXclientState * a_cl, GLbyte * a_pc) +{ + xGLXMakeContextCurrentReq *req = (xGLXMakeContextCurrentReq *) a_pc; + __GLX_DECLARE_SWAP_VARIABLES; + + __GLX_SWAP_INT(&req->drawable); + __GLX_SWAP_INT(&req->readdrawable); + __GLX_SWAP_INT(&req->context); + __GLX_SWAP_INT(&req->oldContextTag); + + return ephyrGLXMakeCurrentReal(a_cl, req->drawable, req->readdrawable, + req->context, req->oldContextTag, TRUE); } static int diff --git a/xorg-server/hw/kdrive/ephyr/ephyrhostglx.c b/xorg-server/hw/kdrive/ephyr/ephyrhostglx.c index 6b9da6fb1..392489a00 100644 --- a/xorg-server/hw/kdrive/ephyr/ephyrhostglx.c +++ b/xorg-server/hw/kdrive/ephyr/ephyrhostglx.c @@ -52,6 +52,8 @@ #include "ephyrlog.h" #include "hostx.h" +static int glx_major, glx_minor; + enum VisualConfRequestType { EPHYR_GET_FB_CONFIG, EPHYR_VENDOR_PRIV_GET_FB_CONFIG_SGIX, @@ -99,6 +101,12 @@ ephyrHostGLXQueryVersion(int *a_major, int *a_minor) EPHYR_RETURN_VAL_IF_FAIL(a_major && a_minor, FALSE); EPHYR_LOG("enter\n"); + if (glx_major) { + *a_major = glx_major; + *a_minor = glx_minor; + return TRUE; + } + if (!ephyrHostGLXGetMajorOpcode(&major_opcode)) { EPHYR_LOG_ERROR("failed to get major opcode\n"); goto out; @@ -117,8 +125,8 @@ ephyrHostGLXQueryVersion(int *a_major, int *a_minor) UnlockDisplay(dpy); SyncHandle(); - *a_major = reply.majorVersion; - *a_minor = reply.minorVersion; + *a_major = glx_major = reply.majorVersion; + *a_minor = glx_minor = reply.minorVersion; EPHYR_LOG("major:%d, minor:%d\n", *a_major, *a_minor); @@ -431,17 +439,20 @@ ephyrHostGLXSendClientInfo(int32_t a_major, int32_t a_minor, Bool ephyrHostGLXCreateContext(int a_screen, - int a_visual_id, + int a_generic_id, int a_context_id, - int a_share_list_ctxt_id, Bool a_direct) + int a_share_list_ctxt_id, + int a_render_type, + Bool a_direct, + int code) { Bool is_ok = FALSE; Display *dpy = hostx_get_display(); int major_opcode = 0, remote_context_id = 0; - xGLXCreateContextReq *req; - EPHYR_LOG("enter. screen:%d, visual:%d, contextid:%d, direct:%d\n", - a_screen, a_visual_id, a_context_id, a_direct); + EPHYR_LOG("enter. screen:%d, generic_id:%d, contextid:%d, rendertype:%d, " + "direct:%d\n", a_screen, a_generic_id, a_context_id, + a_render_type, a_direct); if (!hostx_allocate_resource_id_peer(a_context_id, &remote_context_id)) { EPHYR_LOG_ERROR("failed to peer the context id %d host X", @@ -456,15 +467,38 @@ ephyrHostGLXCreateContext(int a_screen, LockDisplay(dpy); - /* Send the glXCreateContext request */ - GetReq(GLXCreateContext, req); - req->reqType = major_opcode; - req->glxCode = X_GLXCreateContext; - req->context = remote_context_id; - req->visual = a_visual_id; - req->screen = DefaultScreen(dpy); - req->shareList = a_share_list_ctxt_id; - req->isDirect = a_direct; + switch (code) { + case X_GLXCreateContext: { + /* Send the glXCreateContext request */ + xGLXCreateContextReq *req; + GetReq(GLXCreateContext, req); + req->reqType = major_opcode; + req->glxCode = X_GLXCreateContext; + req->context = remote_context_id; + req->visual = a_generic_id; + req->screen = DefaultScreen(dpy); + req->shareList = a_share_list_ctxt_id; + req->isDirect = a_direct; + } + + case X_GLXCreateNewContext: { + /* Send the glXCreateNewContext request */ + xGLXCreateNewContextReq *req; + GetReq(GLXCreateNewContext, req); + req->reqType = major_opcode; + req->glxCode = X_GLXCreateNewContext; + req->context = remote_context_id; + req->fbconfig = a_generic_id; + req->screen = DefaultScreen(dpy); + req->renderType = a_render_type; + req->shareList = a_share_list_ctxt_id; + req->isDirect = a_direct; + } + + default: + /* This should never be reached !*/ + EPHYR_LOG("Internal error! Invalid CreateContext code!\n"); + } UnlockDisplay(dpy); SyncHandle(); @@ -512,20 +546,19 @@ ephyrHostDestroyContext(int a_ctxt_id) } Bool -ephyrHostGLXMakeCurrent(int a_drawable, +ephyrHostGLXMakeCurrent(int a_drawable, int a_readable, int a_glx_ctxt_id, int a_old_ctxt_tag, int *a_ctxt_tag) { Bool is_ok = FALSE; Display *dpy = hostx_get_display(); int32_t major_opcode = 0; int remote_glx_ctxt_id = 0; - xGLXMakeCurrentReq *req; xGLXMakeCurrentReply reply; EPHYR_RETURN_VAL_IF_FAIL(a_ctxt_tag, FALSE); - EPHYR_LOG("enter. drawable:%d, context:%d, oldtag:%d\n", - a_drawable, a_glx_ctxt_id, a_old_ctxt_tag); + EPHYR_LOG("enter. drawable:%d, read:%d, context:%d, oldtag:%d\n", + a_drawable, a_readable, a_glx_ctxt_id, a_old_ctxt_tag); if (!ephyrHostGLXGetMajorOpcode(&major_opcode)) { EPHYR_LOG_ERROR("failed to get major opcode\n"); @@ -538,12 +571,48 @@ ephyrHostGLXMakeCurrent(int a_drawable, LockDisplay(dpy); - GetReq(GLXMakeCurrent, req); - req->reqType = major_opcode; - req->glxCode = X_GLXMakeCurrent; - req->drawable = a_drawable; - req->context = remote_glx_ctxt_id; - req->oldContextTag = a_old_ctxt_tag; + /* If both drawables are the same, use the old MakeCurrent request. + * Otherwise, if we have GLX 1.3 or higher, use the MakeContextCurrent + * request which supports separate read and draw targets. Failing that, + * try the SGI MakeCurrentRead extension. Logic cribbed from Mesa. */ + if (a_drawable == a_readable) { + xGLXMakeCurrentReq *req; + + GetReq(GLXMakeCurrent, req); + req->reqType = major_opcode; + req->glxCode = X_GLXMakeCurrent; + req->drawable = a_drawable; + req->context = remote_glx_ctxt_id; + req->oldContextTag = a_old_ctxt_tag; + } + else if (glx_major > 1 || glx_minor >= 3) { + xGLXMakeContextCurrentReq *req; + + GetReq(GLXMakeContextCurrent, req); + req->reqType = major_opcode; + req->glxCode = X_GLXMakeContextCurrent; + req->drawable = a_drawable; + req->readdrawable = a_readable; + req->context = remote_glx_ctxt_id; + req->oldContextTag = a_old_ctxt_tag; + } + else { + xGLXVendorPrivateWithReplyReq *vpreq; + xGLXMakeCurrentReadSGIReq *req; + + GetReqExtra(GLXVendorPrivateWithReply, + (sz_xGLXMakeCurrentReadSGIReq - + sz_xGLXVendorPrivateWithReplyReq), + vpreq); + req = (xGLXMakeCurrentReadSGIReq *) vpreq; + req->reqType = major_opcode; + req->glxCode = X_GLXVendorPrivateWithReply; + req->vendorCode = X_GLXvop_MakeCurrentReadSGI; + req->drawable = a_drawable; + req->readable = a_readable; + req->context = remote_glx_ctxt_id; + req->oldContextTag = a_old_ctxt_tag; + } memset(&reply, 0, sizeof(reply)); if (!_XReply(dpy, (xReply *) & reply, 0, False)) { diff --git a/xorg-server/hw/kdrive/ephyr/ephyrhostglx.h b/xorg-server/hw/kdrive/ephyr/ephyrhostglx.h index 9c6012070..7ff515dc2 100644 --- a/xorg-server/hw/kdrive/ephyr/ephyrhostglx.h +++ b/xorg-server/hw/kdrive/ephyr/ephyrhostglx.h @@ -55,13 +55,16 @@ Bool ephyrHostGLXGetMajorOpcode(int32_t * a_opcode); Bool ephyrHostGLXSendClientInfo(int32_t a_major, int32_t a_minor, const char *a_extension_list); Bool ephyrHostGLXCreateContext(int a_screen, - int a_visual_id, + int a_generic_id, int a_context_id, - int a_shared_list_ctx_id, Bool a_direct); + int a_share_list_ctxt_id, + int a_render_type, + Bool a_direct, + int code); Bool ephyrHostDestroyContext(int a_ctxt_id); -Bool ephyrHostGLXMakeCurrent(int a_drawable, int a_glx_ctxt_id, +Bool ephyrHostGLXMakeCurrent(int a_drawable, int a_readable, int a_glx_ctxt_id, int a_olg_ctxt_tag, int *a_ctxt_tag); Bool ephyrHostGetIntegerValue(int a_current_context_tag, int a_int, int *a_val); diff --git a/xorg-server/hw/kdrive/src/kinput.c b/xorg-server/hw/kdrive/src/kinput.c index d35dcf848..b1068bbee 100644 --- a/xorg-server/hw/kdrive/src/kinput.c +++ b/xorg-server/hw/kdrive/src/kinput.c @@ -1034,7 +1034,7 @@ KdGetOptions(InputOption **options, char *string) if (strchr(string, '=')) { tam_key = (strchr(string, '=') - string); - key = strndup(string, tam_key + 1); + key = strndup(string, tam_key); if (!key) goto out; diff --git a/xorg-server/hw/xfree86/common/xf86DGA.c b/xorg-server/hw/xfree86/common/xf86DGA.c index a441dee99..c25a2747b 100644 --- a/xorg-server/hw/xfree86/common/xf86DGA.c +++ b/xorg-server/hw/xfree86/common/xf86DGA.c @@ -2095,7 +2095,7 @@ ProcXDGADispatch(ClientPtr client) { REQUEST(xReq); - if (!LocalClient(client)) + if (!client->local) return DGAErrorBase + XF86DGAClientNotLocal; #ifdef DGA_REQ_DEBUG diff --git a/xorg-server/hw/xfree86/common/xf86Module.h b/xorg-server/hw/xfree86/common/xf86Module.h index 83f9790d2..fd90aac54 100644 --- a/xorg-server/hw/xfree86/common/xf86Module.h +++ b/xorg-server/hw/xfree86/common/xf86Module.h @@ -80,7 +80,7 @@ typedef enum { * mask is 0xFFFF0000. */ #define ABI_ANSIC_VERSION SET_ABI_VERSION(0, 4) -#define ABI_VIDEODRV_VERSION SET_ABI_VERSION(13, 0) +#define ABI_VIDEODRV_VERSION SET_ABI_VERSION(14, 0) #define ABI_XINPUT_VERSION SET_ABI_VERSION(18, 0) #define ABI_EXTENSION_VERSION SET_ABI_VERSION(7, 0) #define ABI_FONT_VERSION SET_ABI_VERSION(0, 6) diff --git a/xorg-server/hw/xfree86/common/xf86Opt.h b/xorg-server/hw/xfree86/common/xf86Opt.h index 0d808de14..c3ba2d75c 100644 --- a/xorg-server/hw/xfree86/common/xf86Opt.h +++ b/xorg-server/hw/xfree86/common/xf86Opt.h @@ -85,7 +85,7 @@ extern _X_EXPORT int xf86CheckIntOption(XF86OptionPtr optlist, const char *name, extern _X_EXPORT double xf86CheckRealOption(XF86OptionPtr optlist, const char *name, double deflt); extern _X_EXPORT char *xf86CheckStrOption(XF86OptionPtr optlist, - const char *name, char *deflt); + const char *name, const char *deflt); extern _X_EXPORT int xf86CheckBoolOption(XF86OptionPtr list, const char *name, int deflt); extern _X_EXPORT double xf86CheckPercentOption(XF86OptionPtr list, diff --git a/xorg-server/hw/xfree86/common/xf86Option.c b/xorg-server/hw/xfree86/common/xf86Option.c index 7cc744029..c2ec79a53 100644 --- a/xorg-server/hw/xfree86/common/xf86Option.c +++ b/xorg-server/hw/xfree86/common/xf86Option.c @@ -276,7 +276,7 @@ xf86CheckRealOption(XF86OptionPtr optlist, const char *name, double deflt) } char * -xf86CheckStrOption(XF86OptionPtr optlist, const char *name, char *deflt) +xf86CheckStrOption(XF86OptionPtr optlist, const char *name, const char *deflt) { return LookupStrOption(optlist, name, deflt, FALSE); } diff --git a/xorg-server/hw/xfree86/common/xf86vmode.c b/xorg-server/hw/xfree86/common/xf86vmode.c index 7cd2eedb3..cad0e6a21 100644 --- a/xorg-server/hw/xfree86/common/xf86vmode.c +++ b/xorg-server/hw/xfree86/common/xf86vmode.c @@ -1590,7 +1590,7 @@ ProcXF86VidModeGetPermissions(ClientPtr client) return BadValue; if (xf86GetVidModeEnabled() && - (xf86GetVidModeAllowNonLocal() || LocalClient(client))) { + (xf86GetVidModeAllowNonLocal() || client->local)) { rep.permissions |= XF86VM_WRITE_PERMISSION; } if (client->swapped) { @@ -1659,7 +1659,7 @@ ProcXF86VidModeDispatch(ClientPtr client) default: if (!xf86GetVidModeEnabled()) return VidModeErrorBase + XF86VidModeExtensionDisabled; - if (xf86GetVidModeAllowNonLocal() || LocalClient(client)) { + if (xf86GetVidModeAllowNonLocal() || client->local) { switch (stuff->data) { case X_XF86VidModeAddModeLine: return ProcXF86VidModeAddModeLine(client); @@ -2083,7 +2083,7 @@ SProcXF86VidModeDispatch(ClientPtr client) default: if (!xf86GetVidModeEnabled()) return VidModeErrorBase + XF86VidModeExtensionDisabled; - if (xf86GetVidModeAllowNonLocal() || LocalClient(client)) { + if (xf86GetVidModeAllowNonLocal() || client->local) { switch (stuff->data) { case X_XF86VidModeAddModeLine: return SProcXF86VidModeAddModeLine(client); diff --git a/xorg-server/hw/xfree86/dri/xf86dri.c b/xorg-server/hw/xfree86/dri/xf86dri.c index ba74bb04f..0b2e8fa1b 100644 --- a/xorg-server/hw/xfree86/dri/xf86dri.c +++ b/xorg-server/hw/xfree86/dri/xf86dri.c @@ -118,7 +118,7 @@ ProcXF86DRIQueryDirectRenderingCapable(register ClientPtr client) return BadValue; } - if (!LocalClient(client) || client->swapped) + if (!client->local || client->swapped) isCapable = 0; rep = (xXF86DRIQueryDirectRenderingCapableReply) { @@ -528,7 +528,7 @@ ProcXF86DRIDispatch(register ClientPtr client) return ProcXF86DRIQueryDirectRenderingCapable(client); } - if (!LocalClient(client)) + if (!client->local) return DRIErrorBase + XF86DRIClientNotLocal; switch (stuff->data) { diff --git a/xorg-server/hw/xfree86/dri2/dri2ext.c b/xorg-server/hw/xfree86/dri2/dri2ext.c index ee610c0ec..e1decec9e 100644 --- a/xorg-server/hw/xfree86/dri2/dri2ext.c +++ b/xorg-server/hw/xfree86/dri2/dri2ext.c @@ -588,7 +588,7 @@ ProcDRI2Dispatch(ClientPtr client) return ProcDRI2QueryVersion(client); } - if (!LocalClient(client)) + if (!client->local) return BadRequest; switch (stuff->data) { diff --git a/xorg-server/hw/xfree86/int10/generic.c b/xorg-server/hw/xfree86/int10/generic.c index 4633120fd..d7594def2 100644 --- a/xorg-server/hw/xfree86/int10/generic.c +++ b/xorg-server/hw/xfree86/int10/generic.c @@ -178,7 +178,8 @@ xf86ExtendedInitInt10(int entityIndex, int Flags) */ vbiosMem = (char *) base + V_BIOS; memset(vbiosMem, 0, 2 * V_BIOS_SIZE); - if (pci_device_read_rom(pInt->dev, vbiosMem) < V_BIOS_SIZE) { + if (pci_device_read_rom(pInt->dev, vbiosMem) != 0 + || pInt->dev->rom_size < V_BIOS_SIZE) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Unable to retrieve all of segment 0x0C0000.\n"); } diff --git a/xorg-server/hw/xquartz/applewm.c b/xorg-server/hw/xquartz/applewm.c index d41a81db3..aea0a45f2 100644 --- a/xorg-server/hw/xquartz/applewm.c +++ b/xorg-server/hw/xquartz/applewm.c @@ -612,7 +612,7 @@ ProcAppleWMDispatch(register ClientPtr client) return ProcAppleWMQueryVersion(client); } - if (!LocalClient(client)) + if (!client->local) return WMErrorBase + AppleWMClientNotLocal; switch (stuff->data) { @@ -684,7 +684,7 @@ SProcAppleWMDispatch(register ClientPtr client) REQUEST(xReq); /* It is bound to be non-local when there is byte swapping */ - if (!LocalClient(client)) + if (!client->local) return WMErrorBase + AppleWMClientNotLocal; /* only local clients are allowed WM access */ diff --git a/xorg-server/hw/xquartz/xpr/appledri.c b/xorg-server/hw/xquartz/xpr/appledri.c index f77848f13..9aac07240 100644 --- a/xorg-server/hw/xquartz/xpr/appledri.c +++ b/xorg-server/hw/xquartz/xpr/appledri.c @@ -129,7 +129,7 @@ ProcAppleDRIQueryDirectRenderingCapable(register ClientPtr client) } rep.isCapable = isCapable; - if (!LocalClient(client)) + if (!client->local) rep.isCapable = 0; if (client->swapped) { @@ -354,7 +354,7 @@ ProcAppleDRIDispatch(register ClientPtr client) return ProcAppleDRIQueryDirectRenderingCapable(client); } - if (!LocalClient(client)) + if (!client->local) return DRIErrorBase + AppleDRIClientNotLocal; switch (stuff->data) { @@ -469,7 +469,7 @@ SProcAppleDRIDispatch(register ClientPtr client) return SProcAppleDRIQueryDirectRenderingCapable(client); } - if (!LocalClient(client)) + if (!client->local) return DRIErrorBase + AppleDRIClientNotLocal; switch (stuff->data) { diff --git a/xorg-server/hw/xwin/winwindowswm.c b/xorg-server/hw/xwin/winwindowswm.c index 5d513a893..88c375733 100644 --- a/xorg-server/hw/xwin/winwindowswm.c +++ b/xorg-server/hw/xwin/winwindowswm.c @@ -525,7 +525,7 @@ ProcWindowsWMDispatch(ClientPtr client) return ProcWindowsWMQueryVersion(client); } - if (!LocalClient(client)) + if (!client->local) return WMErrorBase + WindowsWMClientNotLocal; switch (stuff->data) { @@ -575,7 +575,7 @@ SProcWindowsWMDispatch(ClientPtr client) REQUEST(xReq); /* It is bound to be non-local when there is byte swapping */ - if (!LocalClient(client)) + if (!client->local) return WMErrorBase + WindowsWMClientNotLocal; /* only local clients are allowed WM access */ diff --git a/xorg-server/include/dixstruct.h b/xorg-server/include/dixstruct.h index b2a168aa8..c1236f5c9 100644 --- a/xorg-server/include/dixstruct.h +++ b/xorg-server/include/dixstruct.h @@ -56,8 +56,7 @@ ReplyNotSwappd(ClientPtr /* pClient */ , void * /* pbuf */ ) _X_NORETURN; typedef enum { ClientStateInitial, - /* 1 is unused now, was ClientStateAuthenticating */ - ClientStateRunning = 2, + ClientStateRunning, ClientStateRetained, ClientStateGone } ClientState; @@ -86,26 +85,29 @@ typedef struct _Window *SaveSetElt; #endif typedef struct _Client { - int index; - Mask clientAsMask; pointer requestBuffer; pointer osPrivate; /* for OS layer, including scheduler */ - Bool swapped; + Mask clientAsMask; + short index; + unsigned char majorOp, minorOp; + int swapped:1; + int local:1; + int big_requests:1; /* supports large requests */ + int clientGone:1; + int closeDownMode:2; + int clientState:2; + char smart_priority; + short noClientException; /* this client died or needs to be killed */ + int priority; ReplySwapPtr pSwapReplyFunc; XID errorValue; int sequence; - int closeDownMode; - int clientGone; - int noClientException; /* this client died or needs to be - * killed */ int ignoreCount; /* count for Attend/IgnoreClient */ - SaveSetElt *saveSet; int numSaved; + SaveSetElt *saveSet; int (**requestVector) (ClientPtr /* pClient */ ); CARD32 req_len; /* length of current request */ - Bool big_requests; /* supports large requests */ - int priority; - ClientState clientState; + unsigned int replyBytesRemaining; PrivateRec *devPrivates; unsigned short xkbClientFlags; unsigned short mapNotifyMask; @@ -113,15 +115,12 @@ typedef struct _Client { unsigned short vMajor, vMinor; KeyCode minKC, maxKC; - unsigned long replyBytesRemaining; - int smart_priority; - long smart_start_tick; - long smart_stop_tick; - long smart_check_tick; + int smart_start_tick; + int smart_stop_tick; + int smart_check_tick; DeviceIntPtr clientPtr; ClientIdPtr clientIds; - unsigned short majorOp, minorOp; } ClientRec; /* diff --git a/xorg-server/include/os.h b/xorg-server/include/os.h index 9e323f331..e32421610 100644 --- a/xorg-server/include/os.h +++ b/xorg-server/include/os.h @@ -406,9 +406,6 @@ typedef struct sockaddr *sockaddrPtr; extern _X_EXPORT int InvalidHost(sockaddrPtr /*saddr */ , int /*len */ , ClientPtr client); -extern _X_EXPORT int -LocalClient(ClientPtr /* client */ ); - extern _X_EXPORT int LocalClientCred(ClientPtr, int *, int *); diff --git a/xorg-server/include/windowstr.h b/xorg-server/include/windowstr.h index 9caafba41..a1e608f09 100644 --- a/xorg-server/include/windowstr.h +++ b/xorg-server/include/windowstr.h @@ -86,8 +86,8 @@ typedef struct _WindowOpt { struct _OtherClients *otherClients; /* default: NULL */ struct _GrabRec *passiveGrabs; /* default: NULL */ PropertyPtr userProps; /* default: NULL */ - unsigned long backingBitPlanes; /* default: ~0L */ - unsigned long backingPixel; /* default: 0 */ + CARD32 backingBitPlanes; /* default: ~0L */ + CARD32 backingPixel; /* default: 0 */ RegionPtr boundingShape; /* default: NULL */ RegionPtr clipShape; /* default: NULL */ RegionPtr inputShape; /* default: NULL */ diff --git a/xorg-server/mi/mipointer.c b/xorg-server/mi/mipointer.c index 4defaf5ec..f34506326 100644 --- a/xorg-server/mi/mipointer.c +++ b/xorg-server/mi/mipointer.c @@ -575,13 +575,8 @@ miPointerSetPosition(DeviceIntPtr pDev, int mode, double *screenx, miPointerPtr pPointer; - if (!pDev) - return NULL; - pPointer = MIPOINTER(pDev); pScreen = pPointer->pScreen; - if (!pScreen) - return NULL; /* called before ready */ x = trunc(*screenx); y = trunc(*screeny); diff --git a/xorg-server/os/access.c b/xorg-server/os/access.c index 550f2ed8c..104b6a713 100644 --- a/xorg-server/os/access.c +++ b/xorg-server/os/access.c @@ -1007,14 +1007,6 @@ ComputeLocalClient(ClientPtr client) return FALSE; } -Bool -LocalClient(ClientPtr client) -{ - if (!client->osPrivate) - return FALSE; - return ((OsCommPtr) client->osPrivate)->local_client; -} - /* * Return the uid and gid of a connected local client * @@ -1176,7 +1168,7 @@ AuthorizedClient(ClientPtr client) if (rc != Success) return rc; - return LocalClient(client) ? Success : BadAccess; + return client->local ? Success : BadAccess; } /* Add a host to the access control list. This is the external interface diff --git a/xorg-server/os/connection.c b/xorg-server/os/connection.c index 721ad65b3..6cd8bcf43 100644 --- a/xorg-server/os/connection.c +++ b/xorg-server/os/connection.c @@ -764,7 +764,7 @@ AllocNewConnection(XtransConnInfo trans_conn, int fd, CARD32 conn_time) free(oc); return NullClient; } - oc->local_client = ComputeLocalClient(client); + client->local = ComputeLocalClient(client); #if !defined(WIN32) ConnectionTranslation[fd] = client->index; #else @@ -894,7 +894,7 @@ ErrorConnMax(XtransConnInfo trans_conn) xConnSetupPrefix csp; char pad[3] = { 0, 0, 0 }; struct iovec iov[3]; - char byteOrder = 0; + char order = 0; int whichbyte = 1; struct timeval waittime; fd_set mask; @@ -907,15 +907,15 @@ ErrorConnMax(XtransConnInfo trans_conn) FD_SET(fd, &mask); (void) Select(fd + 1, &mask, NULL, NULL, &waittime); /* try to read the byte-order of the connection */ - (void) _XSERVTransRead(trans_conn, &byteOrder, 1); - if ((byteOrder == 'l') || (byteOrder == 'B')) { + (void) _XSERVTransRead(trans_conn, &order, 1); + if (order == 'l' || order == 'B' || order == 'r' || order == 'R') { csp.success = xFalse; csp.lengthReason = sizeof(NOROOM) - 1; csp.length = (sizeof(NOROOM) + 2) >> 2; csp.majorVersion = X_PROTOCOL; csp.minorVersion = X_PROTOCOL_REVISION; - if (((*(char *) &whichbyte) && (byteOrder == 'B')) || - (!(*(char *) &whichbyte) && (byteOrder == 'l'))) { + if (((*(char *) &whichbyte) && (order == 'B' || order == 'R')) || + (!(*(char *) &whichbyte) && (order == 'l' || order == 'r'))) { swaps(&csp.majorVersion); swaps(&csp.minorVersion); swaps(&csp.length); @@ -1038,8 +1038,8 @@ CloseDownConnection(ClientPtr client) if (FlushCallback) CallCallbacks(&FlushCallback, NULL); - if (oc->output && oc->output->count) - FlushClient(client, oc, (char *) NULL, 0); + if (oc->output) + FlushClient(client, oc, (char *) NULL, 0); #ifdef XDMCP XdmcpCloseDisplay(oc->fd); #endif diff --git a/xorg-server/os/io.c b/xorg-server/os/io.c index e44db3933..2f091c417 100644 --- a/xorg-server/os/io.c +++ b/xorg-server/os/io.c @@ -82,6 +82,23 @@ SOFTWARE. CallbackListPtr ReplyCallback; CallbackListPtr FlushCallback; +typedef struct _connectionInput { + struct _connectionInput *next; + char *buffer; /* contains current client input */ + char *bufptr; /* pointer to current start of data */ + int bufcnt; /* count of bytes in buffer */ + int lenLastReq; + int size; + unsigned int ignoreBytes; /* bytes to ignore before the next request */ +} ConnectionInput; + +typedef struct _connectionOutput { + struct _connectionOutput *next; + unsigned char *buf; + int size; + int count; +} ConnectionOutput; + static ConnectionInputPtr AllocateInputBuffer(void); static ConnectionOutputPtr AllocateOutputBuffer(void); @@ -846,10 +863,13 @@ FlushClient(ClientPtr who, OsCommPtr oc, const void *__extraBuf, int extraCount) long todo; if (!oco) - return 0; + return 0; written = 0; padsize = padding_for_int32(extraCount); notWritten = oco->count + extraCount + padsize; + if (!notWritten) + return 0; + todo = notWritten; while (notWritten) { long before = written; /* amount of whole thing written */ diff --git a/xorg-server/os/osdep.h b/xorg-server/os/osdep.h index fff088701..0ccdb62ef 100644 --- a/xorg-server/os/osdep.h +++ b/xorg-server/os/osdep.h @@ -107,22 +107,8 @@ typedef Bool (*AddAuthorFunc) (unsigned name_length, const char *name, unsigned data_length, char *data); #endif -typedef struct _connectionInput { - struct _connectionInput *next; - char *buffer; /* contains current client input */ - char *bufptr; /* pointer to current start of data */ - int bufcnt; /* count of bytes in buffer */ - int lenLastReq; - int size; - unsigned int ignoreBytes; /* bytes to ignore before the next request */ -} ConnectionInput, *ConnectionInputPtr; - -typedef struct _connectionOutput { - struct _connectionOutput *next; - int size; - unsigned char *buf; - int count; -} ConnectionOutput, *ConnectionOutputPtr; +typedef struct _connectionInput *ConnectionInputPtr; +typedef struct _connectionOutput *ConnectionOutputPtr; struct _osComm; @@ -162,7 +148,6 @@ typedef struct _osComm { XID auth_id; /* authorization id */ CARD32 conn_time; /* timestamp if not established, else 0 */ struct _XtransConnInfo *trans_conn; /* transport connection object */ - Bool local_client; } OsCommRec, *OsCommPtr; extern int FlushClient(ClientPtr /*who */ , diff --git a/xorg-server/xkeyboard-config/rules/base.xml.in b/xorg-server/xkeyboard-config/rules/base.xml.in index 87943048e..712ddabf6 100644 --- a/xorg-server/xkeyboard-config/rules/base.xml.in +++ b/xorg-server/xkeyboard-config/rules/base.xml.in @@ -3433,6 +3433,12 @@ + + + ibm + <_description>Italian (IBM 142) + + diff --git a/xorg-server/xkeyboard-config/symbols/it b/xorg-server/xkeyboard-config/symbols/it index 1d26a044b..d70e49755 100644 --- a/xorg-server/xkeyboard-config/symbols/it +++ b/xorg-server/xkeyboard-config/symbols/it @@ -255,3 +255,46 @@ xkb_symbols "htcdream" { include "level3(alt_switch)" }; + +partial alphanumeric_keys +xkb_symbols "ibm" { + + // Modifies the basic italian layout to match IBM 142 variant + + include "us" + + name[Group1]="Italian (IBM 142)"; + + key { [ backslash, bar ] }; + + key { [ 2, quotedbl ] }; + key { [ 3, sterling, numbersign ] }; + key { [ 6, ampersand ] }; + key { [ 7, slash, braceleft ] }; + key { [ 8, parenleft, bracketleft ] }; + key { [ 9, parenright, bracketright ] }; + key { [ 0, equal, braceright ] }; + key { [apostrophe, question ] }; + key { [ igrave, asciicircum ] }; + + key { [ q, Q, at ] }; + key { [ e, E, EuroSign ] }; + key { [ egrave, eacute ] }; + key { [ plus, asterisk, asciitilde ] }; + + key { [ ograve, ccedilla ] }; + key { [ agrave, degree ] }; + + key { [ comma, semicolon ] }; + key { [ period, colon ] }; + key { [ minus, underscore ] }; + + key { [ ugrave, section, grave ] }; + + key { [ less, greater ] }; + + include "level3(ralt_switch)" + include "kpdl(comma)" + +}; + -- cgit v1.2.3