README.xspice | 8 configure.ac | 4 debian/changelog | 14 debian/control | 2 debian/copyright | 3 debian/patches/series | 1 debian/patches/translate-the-access-region.diff | 48 - debian/source/options | 2 examples/spiceqxl.xorg.conf.example | 37 - scripts/Makefile.am | 4 scripts/Xspice | 128 +++ scripts/xspice | 125 --- src/Makefile.am | 10 src/lookup3.c | 769 ------------------------ src/lookup3.h | 26 src/murmurhash3.c | 357 +++++++++++ src/murmurhash3.h | 39 + src/qxl.h | 33 - src/qxl_driver.c | 178 ++++- src/qxl_image.c | 155 ++-- src/qxl_option_helpers.c | 37 + src/qxl_option_helpers.h | 14 src/qxl_ring.c | 3 src/qxl_surface.c | 249 +------ src/spiceqxl_inputs.c | 9 src/spiceqxl_io_port.c | 3 src/spiceqxl_spice_server.c | 35 - src/spiceqxl_spice_server.h | 1 src/uxa/uxa-unaccel.c | 11 src/uxa/uxa.c | 33 - 30 files changed, 939 insertions(+), 1399 deletions(-)
New commits: commit 1fe2148c3ebdc643f742f6fc0e5910eebef5cd3c Author: Liang Guo <bluestonech...@gmail.com> Date: Sat Mar 17 15:05:18 2012 +0800 Refresh debian/changelog diff --git a/debian/changelog b/debian/changelog index 26cbe51..b539a0f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,8 +1,18 @@ -xserver-xorg-video-qxl (0.0.16-3) UNRELEASED; urgency=low +xserver-xorg-video-qxl (0.0.17-1) unstable; urgency=low + [ Liang Guo ] + * New upstream release. + * debian/copyright: + - Remove src/lookup3.c, removed upstream. + - Add src/murmurhash3.{c,h}, new file. + * debian/source/options: + - Ignore ChangeLog, included in upstream tarbar, but not in git. + * Remove translate-the-access-region.patch, applied upstream. + * Bump Standards-Version to 3.9.3, no changes needed. + [ Cyril Brulebois ] * Fix typo in the debug package's description. - -- Cyril Brulebois <k...@debian.org> Thu, 02 Feb 2012 17:49:19 +0100 + -- Liang Guo <bluestonech...@gmail.com> Fri, 16 Mar 2012 16:13:52 +0800 xserver-xorg-video-qxl (0.0.16-2) unstable; urgency=low commit a4626e4113ea00a0b32a359a313e25143ec4095d Author: Liang Guo <bluestonech...@gmail.com> Date: Sat Mar 17 15:05:03 2012 +0800 Bump Standards-Version to 3.9.3 diff --git a/debian/control b/debian/control index d9937c4..bbfbfb0 100644 --- a/debian/control +++ b/debian/control @@ -21,7 +21,7 @@ Build-Depends: xutils-dev (>= 1:7.5), quilt (>= 0.46-7~), libspice-protocol-dev (>= 0.8.1~) -Standards-Version: 3.9.2 +Standards-Version: 3.9.3 Homepage: http://spice-space.org/ Vcs-Git: git://git.debian.org/git/pkg-xorg/driver/xserver-xorg-video-qxl Vcs-Browser: http://git.debian.org/?p=pkg-xorg/driver/xserver-xorg-video-qxl.git commit 53b390765f2790c795f7576b5b735415d202355f Author: Liang Guo <bluestonech...@gmail.com> Date: Sat Mar 17 15:04:28 2012 +0800 Add src/murmurhash3.{c,h}, remove src/lookup3.c in debian/copyright diff --git a/debian/copyright b/debian/copyright index b85f608..73c2756 100644 --- a/debian/copyright +++ b/debian/copyright @@ -21,4 +21,5 @@ THE AUTHORS 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. -src/lookup3.c is public domain software by Bob Jenkins, May 2006. +src/murmurhash3.c, src/murmurhash3.h is public domain software, and +written by Austin Appleby. commit 893e395c8135127e1a4541b4a40518223f13098d Author: Liang Guo <bluestonech...@gmail.com> Date: Sat Mar 17 15:01:41 2012 +0800 Ignore ChangeLog, included in upstream tarbar, but not in git diff --git a/debian/source/options b/debian/source/options index 8ad9e57..fc938a6 100644 --- a/debian/source/options +++ b/debian/source/options @@ -1 +1 @@ -diff-ignore = autogen.sh|.git|TODO.xspice +diff-ignore = autogen.sh|.git|TODO.xspice|ChangeLog commit 467be4b6c0864023d708fd479f8bc3b86058f5e7 Author: Liang Guo <bluestonech...@gmail.com> Date: Sat Mar 17 15:01:09 2012 +0800 Remove translate-the-access-region.patch, applied upstream diff --git a/debian/patches/series b/debian/patches/series deleted file mode 100644 index 07222c6..0000000 --- a/debian/patches/series +++ /dev/null @@ -1 +0,0 @@ -translate-the-access-region.diff diff --git a/debian/patches/translate-the-access-region.diff b/debian/patches/translate-the-access-region.diff deleted file mode 100644 index 7c2800a..0000000 --- a/debian/patches/translate-the-access-region.diff +++ /dev/null @@ -1,48 +0,0 @@ -commit c77ba9f217093f946a4c6bf6edf9f34b24844d8d -Author: Søren Sandmann <s...@redhat.com> -Date: Fri Oct 28 12:56:30 2011 -0400 - - Translate the access region according to the drawable offset. - - The driver code expects to be given coordinates relative to the - offscreen pixmap. - -diff --git a/src/uxa/uxa.c b/src/uxa/uxa.c -index 83e06cc..9d02e34 100644 ---- a/src/uxa/uxa.c -+++ b/src/uxa/uxa.c -@@ -143,19 +143,19 @@ Bool uxa_prepare_access(DrawablePtr pDrawable, RegionPtr region, uxa_access_t ac - { - ScreenPtr pScreen = pDrawable->pScreen; - uxa_screen_t *uxa_screen = uxa_get_screen(pScreen); -- PixmapPtr pPixmap = uxa_get_drawable_pixmap(pDrawable); -- Bool offscreen = uxa_pixmap_is_offscreen(pPixmap); -+ int xoff, yoff; -+ PixmapPtr pPixmap = uxa_get_offscreen_pixmap(pDrawable, &xoff, &yoff); - BoxRec box; - RegionRec region_rec; - Bool result; - -- if (!offscreen) -+ if (!pPixmap) - return TRUE; - - box.x1 = 0; - box.y1 = 0; -- box.x2 = pPixmap->drawable.width; -- box.y2 = pPixmap->drawable.height; -+ box.x2 = pDrawable->width; -+ box.y2 = pDrawable->height; - - REGION_INIT (pScreen, ®ion_rec, &box, 1); - if (!region) -@@ -168,7 +168,8 @@ Bool uxa_prepare_access(DrawablePtr pDrawable, RegionPtr region, uxa_access_t ac - */ - REGION_INTERSECT (pScreen, region, region, ®ion_rec); - #endif -- -+ REGION_TRANSLATE (pScreen, region, xoff, yoff); -+ - result = TRUE; - - if (uxa_screen->info->prepare_access) commit b75eed01fa7514c15f4379092a93ecf8478f0b48 Author: Søren Sandmann Pedersen <s...@redhat.com> Date: Thu Mar 15 13:49:52 2012 -0400 Version bump to 0.0.17 diff --git a/configure.ac b/configure.ac index 22b2e3d..f34624f 100644 --- a/configure.ac +++ b/configure.ac @@ -23,7 +23,7 @@ # Initialize Autoconf AC_PREREQ([2.60]) AC_INIT([xf86-video-qxl], - [0.0.16], + [0.0.17], [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], [xf86-video-qxl]) AC_CONFIG_SRCDIR([Makefile.am]) commit c358c7f199bfeb519e08b0903438e43b1afd02c1 Author: Søren Sandmann Pedersen <s...@redhat.com> Date: Thu Mar 15 13:49:42 2012 -0400 Add qxl_option_helper.h to Makefile.am diff --git a/src/Makefile.am b/src/Makefile.am index 6350ade..c3ba074 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -61,7 +61,8 @@ spiceqxl_drv_la_LIBADD = uxa/libuxa.la spiceqxl_drv_la_SOURCES = \ qxl.h \ - qxl_option_helpers.c \ + qxl_option_helpers.c \ + qxl_option_helpers.h \ spiceqxl_spice_server.c \ spiceqxl_spice_server.h \ spiceqxl_io_port.c \ commit 81bee3d3491ab6b31b0d69207729280e86138d50 Author: Søren Sandmann Pedersen <s...@redhat.com> Date: Thu Mar 15 13:42:04 2012 -0400 In qxl_prepare_access(), don't modify the width/height of the pixmap The width and height were not properly restored, which caused GetDrawableInfo() to return bogus results, which caused GNOME shell crashes. Signed-off-by: Soren Sandmann <s...@redhat.com> diff --git a/src/qxl_surface.c b/src/qxl_surface.c index e39fde7..7f68e5b 100644 --- a/src/qxl_surface.c +++ b/src/qxl_surface.c @@ -885,12 +885,8 @@ qxl_surface_prepare_access (qxl_surface_t *surface, pScreen->ModifyPixmapHeader( pixmap, -#if 0 pixmap->drawable.width, pixmap->drawable.height, -#endif - pixman_image_get_width (surface->host_image), - pixman_image_get_height (surface->host_image), -1, -1, -1, pixman_image_get_data (surface->host_image)); commit 773fbda754de2dd91f8b6bfe754d1aa59368072b Author: Søren Sandmann Pedersen <s...@redhat.com> Date: Wed Mar 14 12:38:03 2012 -0400 qxl_surface.c: Remove #if 0'd debug spew diff --git a/src/qxl_surface.c b/src/qxl_surface.c index 06bee09..e39fde7 100644 --- a/src/qxl_surface.c +++ b/src/qxl_surface.c @@ -192,21 +192,6 @@ qxl_surface_cache_sanity_check (surface_cache_t *qxl) #endif } -#if 0 -void -qxl_surface_free_all (qxl_screen_t *qxl) -{ - for (i = 0; i < qxl->rom->n_surfaces; ++i) - { - qxl_surface_t *surface = &(all_surfaces[i]); - if (surface->in_use) - { - - } - } -} -#endif - static void print_cache_info (surface_cache_t *cache) { @@ -264,11 +249,6 @@ surface_get_from_cache (surface_cache_t *cache, int width, int height, int bpp) { int i; -#if 0 - ErrorF ("Before getting from cache\n"); - print_cache_info (cache); -#endif - for (i = 0; i < N_CACHED_SURFACES; ++i) { qxl_surface_t *s = cache->cached_surfaces[i]; @@ -282,32 +262,11 @@ surface_get_from_cache (surface_cache_t *cache, int width, int height, int bpp) { cache->cached_surfaces[i] = NULL; -#if 0 - ErrorF ("Got %d from cache\n", s->id); - print_cache_info (cache); -#endif return s; } } -#if 0 - else - { - if (s) - ErrorF ("!%d (%d %d %d, %d); ", s->id, - pixman_image_get_width (s->host_image), - pixman_image_get_height (s->host_image), - bpp, - s->bpp); - else - ErrorF ("[null]; "); - } -#endif } -#if 0 - ErrorF ("Nothing in cache for %d %d %d\n", width, height, bpp); -#endif - return NULL; } @@ -318,25 +277,9 @@ qxl_surface_recycle (surface_cache_t *cache, uint32_t id) { qxl_surface_t *surface = cache->all_surfaces + id; -#if 0 - ErrorF ("recycle %d\n", id); -#endif - -#if 0 - ErrorF ("freeing %p\n", surface->address); -#endif - n_live--; qxl_free (cache->qxl->surf_mem, surface->address); -#if 0 - ErrorF ("%d live\n", n_live); -#endif - -#if 0 - ErrorF (" Adding %d to free list\n", surface->id); -#endif - surface->next = cache->free_surfaces; cache->free_surfaces = surface; } @@ -397,10 +340,6 @@ qxl_surface_cache_create_primary (surface_cache_t *cache, surface->bpp = mode->bits; surface->next = NULL; surface->prev = NULL; - -#if 0 - ErrorF ("primary %p\n", surface->address); -#endif REGION_INIT (NULL, &(surface->access_region), (BoxPtr)NULL, 0); surface->access_type = UXA_ACCESS_RO; @@ -569,9 +508,6 @@ surface_get_from_free_list (surface_cache_t *cache) static int align (int x) { -#if 0 - return (x + 255) & ~255; -#endif return x; } @@ -657,10 +593,6 @@ retry: physical_address (qxl, surface->address, qxl->vram_mem_slot); push_surface_cmd (cache, cmd); - -#if 0 - ErrorF ("Allocated %d (%d %d %d)\n", surface->id, width, height, surface->bpp); -#endif dev_addr = (uint32_t *)((uint8_t *)surface->address + stride * (height - 1)); @@ -737,10 +669,6 @@ qxl_surface_set_pixmap (qxl_surface_t *surface, PixmapPtr pixmap) surface->pixmap = pixmap; assert (get_surface (pixmap) == surface); - -#if 0 - ErrorF ("setting pixmap %p on surface %p\n", pixmap, surface); -#endif } static void @@ -844,10 +772,6 @@ surface_add_to_cache (qxl_surface_t *surface) */ if (destroy_surface) qxl_surface_unref (destroy_surface->cache, destroy_surface->id); - -#if 0 - ErrorF ("Done\n"); -#endif } void @@ -858,12 +782,7 @@ qxl_surface_unref (surface_cache_t *cache, uint32_t id) qxl_surface_t *surface = cache->all_surfaces + id; if (--surface->ref_count == 0) - { -#if 0 - ErrorF ("destroying %d\n", id); -#endif send_destroy (surface); - } } } @@ -872,34 +791,14 @@ qxl_surface_kill (qxl_surface_t *surface) { unlink_surface (surface); -#if 0 - ErrorF ("killed %d (%d %d %d)\n", surface->id, - pixman_image_get_width (surface->host_image), - pixman_image_get_height (surface->host_image), - surface->bpp); -#endif - if (surface->id != 0 && pixman_image_get_width (surface->host_image) >= 128 && pixman_image_get_height (surface->host_image) >= 128) { -#if 0 - ErrorF ("Adding %d to cache\n", surface->id); -#endif surface_add_to_cache (surface); } -#if 0 - ErrorF ("After adding %d to cache\n", surface->id); - print_cache_info (surface->cache); -#endif - qxl_surface_unref (surface->cache, surface->id); - -#if 0 - ErrorF ("After unreffing %d\n", surface->id); - print_cache_info (surface->cache); -#endif } /* send anything pending to the other side */ @@ -922,10 +821,6 @@ download_box (qxl_surface_t *surface, int x1, int y1, int x2, int y2) ram_header->update_surface = surface->id; -#if 0 - ErrorF ("Issuing update command for %d\n", surface->id); -#endif - qxl_update_area(surface->cache->qxl); pixman_image_composite (PIXMAN_OP_SRC, @@ -962,19 +857,9 @@ qxl_surface_prepare_access (qxl_surface_t *surface, n_boxes = REGION_NUM_RECTS (region); boxes = REGION_RECTS (region); -#if 0 - ErrorF ("Preparing access to %d boxes\n", n_boxes); -#endif - stride = pixman_image_get_stride (surface->dev_image); height = pixman_image_get_height (surface->dev_image); -#if 0 - ErrorF ("Flattening %p -> %p (allocated end %p)\n", - surface->address, - surface->address + stride * height, surface->end); -#endif - if (n_boxes < 25) { while (n_boxes--) @@ -986,11 +871,9 @@ qxl_surface_prepare_access (qxl_surface_t *surface, } else { -#if 0 - ErrorF ("Downloading extents (%d > %d)\n", n_boxes, 25); -#endif - - download_box (surface, new.extents.x1, new.extents.y1, new.extents.x2, new.extents.y2); + download_box ( + surface, + new.extents.x1, new.extents.y1, new.extents.x2, new.extents.y2); } REGION_UNION (pScreen, @@ -1012,11 +895,6 @@ qxl_surface_prepare_access (qxl_surface_t *surface, pixman_image_get_data (surface->host_image)); pixmap->devKind = pixman_image_get_stride (surface->host_image); - -#if 0 - ErrorF ("stride %d\n", pixmap->devKind); - ErrorF ("height %d\n", pixmap->drawable.height); -#endif return TRUE; } @@ -1137,9 +1015,6 @@ qxl_surface_cache_evacuate_all (surface_cache_t *cache) qxl_surface_t *s; int i; -#if 0 - ErrorF ("Before evacucate\n"); -#endif for (i = 0; i < N_CACHED_SURFACES; ++i) { if (cache->cached_surfaces[i]) @@ -1149,10 +1024,6 @@ qxl_surface_cache_evacuate_all (surface_cache_t *cache) } } -#if 0 - ErrorF ("Evacuating all\n"); -#endif - s = cache->live_surfaces; while (s != NULL) { @@ -1170,10 +1041,6 @@ qxl_surface_cache_evacuate_all (surface_cache_t *cache) assert (get_surface (evacuated->pixmap) == s); -#if 0 - ErrorF ("Evacuated %d => %p\n", s->id, evacuated->pixmap); -#endif - evacuated->bpp = s->bpp; s->host_image = NULL; @@ -1199,12 +1066,6 @@ qxl_surface_cache_replace_all (surface_cache_t *cache, void *data) { evacuated_surface_t *ev; -#if 0 - ErrorF ("Before replace\n"); -#endif -#if 0 - ErrorF ("Replacing all\n"); -#endif if (!surface_cache_init (cache, cache->qxl)) { /* FIXME: report the error */ @@ -1220,10 +1081,6 @@ qxl_surface_cache_replace_all (surface_cache_t *cache, void *data) qxl_surface_t *surface; surface = qxl_surface_create (cache, width, height, ev->bpp); -#if 0 - ErrorF ("recreated %d\n", surface->id); - ErrorF ("%d => %p\n", surface->id, ev->pixmap); -#endif assert (surface->host_image); assert (surface->dev_image); @@ -1306,12 +1163,7 @@ qxl_surface_solid (qxl_surface_t *destination, qrect.left = x1; qrect.right = x2; -#if 0 - if (destination->u.solid_pixel == 0x0000) - p = 0xffccffcc; - else -#endif - p = destination->u.solid_pixel; + p = destination->u.solid_pixel; submit_fill (qxl, destination->id, &qrect, p); } @@ -1347,10 +1199,6 @@ qxl_surface_copy (qxl_surface_t *dest, print_region (" copy dest", &(dest->access_region)); #endif -#if 0 - ErrorF ("copy from %d to %d\n", dest->u.copy_src->id, dest->id); -#endif - qrect.top = dest_y1; qrect.bottom = dest_y1 + height; qrect.left = dest_x1; @@ -1377,13 +1225,6 @@ qxl_surface_copy (qxl_surface_t *dest, drawable = make_drawable (qxl, dest->id, QXL_DRAW_COPY, &qrect); -#if 0 - ErrorF ("Drawing %d to %d [area %d %d %d %d] (command is %p)\n", - dest->u.copy_src->id, dest->id, - qrect.left, qrect.top, qrect.right, qrect.bottom, - drawable); -#endif - drawable->u.copy.src_bitmap = physical_address (qxl, image, qxl->main_mem_slot); drawable->u.copy.src_area.left = src_x1; drawable->u.copy.src_area.top = src_y1; @@ -1399,12 +1240,6 @@ qxl_surface_copy (qxl_surface_t *dest, drawable->surfaces_dest[0] = dest->u.copy_src->id; drawable->surfaces_rects[0] = drawable->u.copy.src_area; -#if 0 - submit_fill (qxl, dest->id, &qrect, 0xffff00ff); - - usleep (70000); -#endif - assert (src_x1 >= 0); assert (src_y1 >= 0); commit 4724bb7922e1bb193117f13ffbd69fa4f97a29fb Author: Søren Sandmann Pedersen <s...@redhat.com> Date: Fri Mar 9 12:09:17 2012 -0500 options: Turn surfaces and caching on by default diff --git a/src/qxl_driver.c b/src/qxl_driver.c index ed4bb13..ad82d50 100644 --- a/src/qxl_driver.c +++ b/src/qxl_driver.c @@ -1441,11 +1441,11 @@ qxl_pre_init(ScrnInfoPtr pScrn, int flags) xf86ProcessOptions(scrnIndex, pScrn->options, qxl->options); qxl->enable_image_cache = - xf86ReturnOptValBool (qxl->options, OPTION_ENABLE_IMAGE_CACHE, FALSE); + xf86ReturnOptValBool (qxl->options, OPTION_ENABLE_IMAGE_CACHE, TRUE); qxl->enable_fallback_cache = - xf86ReturnOptValBool (qxl->options, OPTION_ENABLE_FALLBACK_CACHE, FALSE); + xf86ReturnOptValBool (qxl->options, OPTION_ENABLE_FALLBACK_CACHE, TRUE); qxl->enable_surfaces = - xf86ReturnOptValBool (qxl->options, OPTION_ENABLE_SURFACES, FALSE); + xf86ReturnOptValBool (qxl->options, OPTION_ENABLE_SURFACES, TRUE); xf86DrvMsg(scrnIndex, X_INFO, "Offscreen Surfaces: %s\n", qxl->enable_surfaces? "Enabled" : "Disabled"); commit babe13196137f339b6f55c6382f7bd1c11100ec2 Author: Alon Levy <al...@redhat.com> Date: Thu Feb 16 15:55:21 2012 +0200 missed when added qxl_option_helpers.c diff --git a/src/qxl_option_helpers.h b/src/qxl_option_helpers.h new file mode 100644 index 0000000..12a14ff --- /dev/null +++ b/src/qxl_option_helpers.h @@ -0,0 +1,14 @@ +#ifndef OPTION_HELPERS_H +#define OPTION_HELPERS_H + + +int get_int_option(OptionInfoPtr options, int option_index, + const char *env_name); + +const char *get_str_option(OptionInfoPtr options, int option_index, + const char *env_name); + +int get_bool_option(OptionInfoPtr options, int option_index, + const char *env_name); + +#endif // OPTION_HELPERS_H commit 70d0d49b7c7d115f297dae710b9bb62b97fa22d5 Author: Alon Levy <al...@redhat.com> Date: Sun Jan 22 19:26:11 2012 +0200 replace lookup3 with MurmurHash3 See http://code.google.com/p/smhasher/wiki/MurmurHash3 Performance quotes from there are 2.5 times what lookup3 can do, for 32 bit variant, which is what we use: Lookup3_x86_32 - 1234 mb/sec Lookup3_x64_32 - 1265 mb/sec MurmurHash3_x86_32 - 3105 mb/sec New files are released to the public domain, keeping them that way. My own comparison shows the added hash to be ~45% faster then the existing one, see the tests at https://gitorious.org/hash_tests/hash_tests diff --git a/src/Makefile.am b/src/Makefile.am index 9e249dc..6350ade 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -45,8 +45,8 @@ qxl_drv_la_SOURCES = \ qxl_mem.c \ mspace.c \ mspace.h \ - lookup3.c \ - lookup3.h \ + murmurhash3.c \ + murmurhash3.h \ qxl_cursor.c endif @@ -81,7 +81,7 @@ spiceqxl_drv_la_SOURCES = \ qxl_mem.c \ mspace.c \ mspace.h \ - lookup3.c \ - lookup3.h \ + murmurhash3.c \ + murmurhash3.h \ qxl_cursor.c endif diff --git a/src/lookup3.c b/src/lookup3.c deleted file mode 100644 index b37ca51..0000000 --- a/src/lookup3.c +++ /dev/null @@ -1,769 +0,0 @@ -/* -------------------------------------------------------------------------------- -lookup3.c, by Bob Jenkins, May 2006, Public Domain. - -These are functions for producing 32-bit hashes for hash table lookup. -hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final() -are externally useful functions. Routines to test the hash are included -if SELF_TEST is defined. You can use this free for any purpose. It's in -the public domain. It has no warranty. - -You probably want to use hashlittle(). hashlittle() and hashbig() -hash byte arrays. hashlittle() is is faster than hashbig() on -little-endian machines. Intel and AMD are little-endian machines. -On second thought, you probably want hashlittle2(), which is identical to -hashlittle() except it returns two 32-bit hashes for the price of one. -You could implement hashbig2() if you wanted but I haven't bothered here. - -If you want to find a hash of, say, exactly 7 integers, do - a = i1; b = i2; c = i3; - mix(a,b,c); - a += i4; b += i5; c += i6; - mix(a,b,c); - a += i7; - final(a,b,c); -then use c as the hash value. If you have a variable length array of -4-byte integers to hash, use hashword(). If you have a byte array (like -a character string), use hashlittle(). If you have several byte arrays, or -a mix of things, see the comments above hashlittle(). - -Why is this so big? I read 12 bytes at a time into 3 4-byte integers, -then mix those integers. This is fast (you can do a lot more thorough -mixing with 12*3 instructions on 3 integers than you can with 3 instructions -on 1 byte), but shoehorning those bytes into integers efficiently is messy. -------------------------------------------------------------------------------- -*/ - -#include <stdio.h> /* defines printf for tests */ -#include <time.h> /* defines time_t for timings in the test */ -#include "lookup3.h" -#ifdef linux -# include <endian.h> /* attempt to define endianness */ -#endif - -/* - * My best guess at if you are big-endian or little-endian. This may - * need adjustment. - */ -#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \ - __BYTE_ORDER == __LITTLE_ENDIAN) || \ - (defined(i386) || defined(__i386__) || defined(__i486__) || \ - defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL)) -# define HASH_LITTLE_ENDIAN 1 -# define HASH_BIG_ENDIAN 0 -#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \ - __BYTE_ORDER == __BIG_ENDIAN) || \ - (defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel)) -# define HASH_LITTLE_ENDIAN 0 -# define HASH_BIG_ENDIAN 1 -#else -# define HASH_LITTLE_ENDIAN 0 -# define HASH_BIG_ENDIAN 0 -#endif - -#define hashsize(n) ((uint32_t)1<<(n)) -#define hashmask(n) (hashsize(n)-1) -#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) - -/* -------------------------------------------------------------------------------- -mix -- mix 3 32-bit values reversibly. - -This is reversible, so any information in (a,b,c) before mix() is -still in (a,b,c) after mix(). - -If four pairs of (a,b,c) inputs are run through mix(), or through -mix() in reverse, there are at least 32 bits of the output that -are sometimes the same for one pair and different for another pair. -This was tested for: -* pairs that differed by one bit, by two bits, in any combination - of top bits of (a,b,c), or in any combination of bottom bits of - (a,b,c). -* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed - the output delta to a Gray code (a^(a>>1)) so a string of 1's (as - is commonly produced by subtraction) look like a single 1-bit - difference. -* the base values were pseudorandom, all zero but one bit set, or - all zero plus a counter that starts at zero. - -Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that -satisfy this are - 4 6 8 16 19 4 - 9 15 3 18 27 15 - 14 9 3 7 17 3 -Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing -for "differ" defined as + with a one-bit base and a two-bit delta. I -used http://burtleburtle.net/bob/hash/avalanche.html to choose -the operations, constants, and arrangements of the variables. - -This does not achieve avalanche. There are input bits of (a,b,c) -that fail to affect some output bits of (a,b,c), especially of a. The -most thoroughly mixed value is c, but it doesn't really even achieve -avalanche in c. - -This allows some parallelism. Read-after-writes are good at doubling -the number of bits affected, so the goal of mixing pulls in the opposite -direction as the goal of parallelism. I did what I could. Rotates -seem to cost as much as shifts on every machine I could lay my hands -on, and rotates are much kinder to the top and bottom bits, so I used -rotates. -------------------------------------------------------------------------------- -*/ -#define mix(a,b,c) \ -{ \ - a -= c; a ^= rot(c, 4); c += b; \ - b -= a; b ^= rot(a, 6); a += c; \ - c -= b; c ^= rot(b, 8); b += a; \ - a -= c; a ^= rot(c,16); c += b; \ - b -= a; b ^= rot(a,19); a += c; \ - c -= b; c ^= rot(b, 4); b += a; \ -} - -/* -------------------------------------------------------------------------------- -final -- final mixing of 3 32-bit values (a,b,c) into c - -Pairs of (a,b,c) values differing in only a few bits will usually -produce values of c that look totally different. This was tested for -* pairs that differed by one bit, by two bits, in any combination - of top bits of (a,b,c), or in any combination of bottom bits of - (a,b,c). -* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed - the output delta to a Gray code (a^(a>>1)) so a string of 1's (as - is commonly produced by subtraction) look like a single 1-bit - difference. -* the base values were pseudorandom, all zero but one bit set, or - all zero plus a counter that starts at zero. - -These constants passed: - 14 11 25 16 4 14 24 - 12 14 25 16 4 14 24 -and these came close: - 4 8 15 26 3 22 24 - 10 8 15 26 3 22 24 - 11 8 15 26 3 22 24 -------------------------------------------------------------------------------- -*/ -#define final(a,b,c) \ -{ \ - c ^= b; c -= rot(b,14); \ - a ^= c; a -= rot(c,11); \ - b ^= a; b -= rot(a,25); \ - c ^= b; c -= rot(b,16); \ - a ^= c; a -= rot(c,4); \ - b ^= a; b -= rot(a,14); \ - c ^= b; c -= rot(b,24); \ -} - -/* --------------------------------------------------------------------- - This works on all machines. To be useful, it requires - -- that the key be an array of uint32_t's, and - -- that the length be the number of uint32_t's in the key - - The function hashword() is identical to hashlittle() on little-endian - machines, and identical to hashbig() on big-endian machines, - except that the length has to be measured in uint32_ts rather than in - bytes. hashlittle() is more complicated than hashword() only because - hashlittle() has to dance around fitting the key bytes into registers. --------------------------------------------------------------------- -*/ -uint32_t hashword( - const uint32_t *k, /* the key, an array of uint32_t values */ - size_t length, /* the length of the key, in uint32_ts */ - uint32_t initval) /* the previous hash, or an arbitrary value */ -{ - uint32_t a,b,c; - - /* Set up the internal state */ - a = b = c = 0xdeadbeef + (((uint32_t)length)<<2) + initval; - - /*------------------------------------------------- handle most of the key */ - while (length > 3) - { - a += k[0]; - b += k[1]; - c += k[2]; - mix(a,b,c); - length -= 3; - k += 3; - } - - /*------------------------------------------- handle the last 3 uint32_t's */ - switch(length) /* all the case statements fall through */ - { - case 3 : c+=k[2]; - case 2 : b+=k[1]; - case 1 : a+=k[0]; - final(a,b,c); - case 0: /* case 0: nothing left to add */ - break; - } - /*------------------------------------------------------ report the result */ - return c; -} - - -/* --------------------------------------------------------------------- -hashword2() -- same as hashword(), but take two seeds and return two -32-bit values. pc and pb must both be nonnull, and *pc and *pb must -both be initialized with seeds. If you pass in (*pb)==0, the output -(*pc) will be the same as the return value from hashword(). --------------------------------------------------------------------- -*/ -void hashword2 ( -const uint32_t *k, /* the key, an array of uint32_t values */ -size_t length, /* the length of the key, in uint32_ts */ -uint32_t *pc, /* IN: seed OUT: primary hash value */ -uint32_t *pb) /* IN: more seed OUT: secondary hash value */ -{ - uint32_t a,b,c; - - /* Set up the internal state */ - a = b = c = 0xdeadbeef + ((uint32_t)(length<<2)) + *pc; - c += *pb; - - /*------------------------------------------------- handle most of the key */ - while (length > 3) - { - a += k[0]; - b += k[1]; - c += k[2]; - mix(a,b,c); - length -= 3; - k += 3; - } - - /*------------------------------------------- handle the last 3 uint32_t's */ - switch(length) /* all the case statements fall through */ - { - case 3 : c+=k[2]; - case 2 : b+=k[1]; - case 1 : a+=k[0]; - final(a,b,c); - case 0: /* case 0: nothing left to add */ - break; - } - /*------------------------------------------------------ report the result */ - *pc=c; *pb=b; -} - - -/* -------------------------------------------------------------------------------- -hashlittle() -- hash a variable-length key into a 32-bit value - k : the key (the unaligned variable-length array of bytes) - length : the length of the key, counting by bytes - initval : can be any 4-byte value -Returns a 32-bit value. Every bit of the key affects every bit of -the return value. Two keys differing by one or two bits will have -totally different hash values. - -The best hash table sizes are powers of 2. There is no need to do -mod a prime (mod is sooo slow!). If you need less than 32 bits, -use a bitmask. For example, if you need only 10 bits, do - h = (h & hashmask(10)); -- To UNSUBSCRIBE, email to debian-x-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org Archive: http://lists.debian.org/e1s8nsv-0003ps...@vasks.debian.org