summaryrefslogtreecommitdiff
path: root/lib/mesa/src/util
diff options
context:
space:
mode:
Diffstat (limited to 'lib/mesa/src/util')
-rw-r--r--lib/mesa/src/util/Makefile.sources14
-rw-r--r--lib/mesa/src/util/SConscript7
-rw-r--r--lib/mesa/src/util/bitscan.c80
-rw-r--r--lib/mesa/src/util/bitscan.h234
-rw-r--r--lib/mesa/src/util/bitset.h2
-rw-r--r--lib/mesa/src/util/format_r11g11b10f.h227
-rw-r--r--lib/mesa/src/util/format_rgb9e5.h120
-rw-r--r--lib/mesa/src/util/hash_table.c2
-rw-r--r--lib/mesa/src/util/hash_table.h13
-rw-r--r--lib/mesa/src/util/list.h36
-rw-r--r--lib/mesa/src/util/macros.h25
-rw-r--r--lib/mesa/src/util/mesa-sha1.c20
-rw-r--r--lib/mesa/src/util/mesa-sha1.h4
-rw-r--r--lib/mesa/src/util/ralloc.c21
-rw-r--r--lib/mesa/src/util/rounding.h7
-rw-r--r--lib/mesa/src/util/slab.c316
-rw-r--r--lib/mesa/src/util/slab.h94
-rw-r--r--lib/mesa/src/util/string_to_uint_map.cpp42
-rw-r--r--lib/mesa/src/util/string_to_uint_map.h177
-rw-r--r--lib/mesa/src/util/u_endian.h69
-rw-r--r--lib/mesa/src/util/u_vector.c98
-rw-r--r--lib/mesa/src/util/u_vector.h92
-rw-r--r--lib/mesa/src/util/vk_alloc.h75
23 files changed, 1741 insertions, 34 deletions
diff --git a/lib/mesa/src/util/Makefile.sources b/lib/mesa/src/util/Makefile.sources
index a87114601..c5531c82d 100644
--- a/lib/mesa/src/util/Makefile.sources
+++ b/lib/mesa/src/util/Makefile.sources
@@ -1,7 +1,11 @@
MESA_UTIL_FILES := \
+ bitscan.c \
+ bitscan.h \
bitset.h \
debug.c \
debug.h \
+ format_r11g11b10f.h \
+ format_rgb9e5.h \
format_srgb.h \
half_float.c \
half_float.h \
@@ -21,12 +25,20 @@ MESA_UTIL_FILES := \
set.c \
set.h \
simple_list.h \
+ slab.c \
+ slab.h \
+ string_to_uint_map.h \
+ string_to_uint_map.cpp \
strndup.c \
strndup.h \
strtod.c \
strtod.h \
texcompress_rgtc_tmp.h \
- u_atomic.h
+ u_atomic.h \
+ u_endian.h \
+ u_vector.c \
+ u_vector.h \
+ vk_alloc.h
MESA_UTIL_GENERATED_FILES = \
format_srgb.c
diff --git a/lib/mesa/src/util/SConscript b/lib/mesa/src/util/SConscript
index 5f3ecc1cd..73f343039 100644
--- a/lib/mesa/src/util/SConscript
+++ b/lib/mesa/src/util/SConscript
@@ -47,17 +47,14 @@ env.Alias('mesautil', mesautil)
Export('mesautil')
-# http://www.scons.org/wiki/UnitTests
u_atomic_test = env.Program(
target = 'u_atomic_test',
source = ['u_atomic_test.c'],
)
-alias = env.Alias("u_atomic_test", u_atomic_test, u_atomic_test[0].abspath)
-AlwaysBuild(alias)
+env.UnitTest("u_atomic_test", u_atomic_test)
roundeven_test = env.Program(
target = 'roundeven_test',
source = ['roundeven_test.c'],
)
-alias = env.Alias("roundeven_test", roundeven_test, roundeven_test[0].abspath)
-AlwaysBuild(alias)
+env.UnitTest("roundeven_test", roundeven_test)
diff --git a/lib/mesa/src/util/bitscan.c b/lib/mesa/src/util/bitscan.c
new file mode 100644
index 000000000..ceca59eba
--- /dev/null
+++ b/lib/mesa/src/util/bitscan.c
@@ -0,0 +1,80 @@
+/**************************************************************************
+ *
+ * Copyright 2008 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS 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.
+ *
+ **************************************************************************/
+
+
+#include "bitscan.h"
+
+#ifdef HAVE___BUILTIN_FFS
+#elif defined(_MSC_VER) && (_M_IX86 || _M_ARM || _M_AMD64 || _M_IA64)
+#else
+int
+ffs(unsigned i)
+{
+ int bit = 0;
+ if (!i)
+ return bit;
+ if (!(i & 0xffff)) {
+ bit += 16;
+ i >>= 16;
+ }
+ if (!(i & 0xff)) {
+ bit += 8;
+ i >>= 8;
+ }
+ if (!(i & 0xf)) {
+ bit += 4;
+ i >>= 4;
+ }
+ if (!(i & 0x3)) {
+ bit += 2;
+ i >>= 2;
+ }
+ if (!(i & 0x1))
+ bit += 1;
+ return bit + 1;
+}
+#endif
+
+#ifdef HAVE___BUILTIN_FFSLL
+#elif defined(_MSC_VER) && (_M_AMD64 || _M_ARM || _M_IA64)
+#else
+int
+ffsll(uint64_t val)
+{
+ int bit;
+
+ bit = ffs((unsigned) (val & 0xffffffff));
+ if (bit != 0)
+ return bit;
+
+ bit = ffs((unsigned) (val >> 32));
+ if (bit != 0)
+ return 32 + bit;
+
+ return 0;
+}
+#endif
diff --git a/lib/mesa/src/util/bitscan.h b/lib/mesa/src/util/bitscan.h
new file mode 100644
index 000000000..a5dfa1f9e
--- /dev/null
+++ b/lib/mesa/src/util/bitscan.h
@@ -0,0 +1,234 @@
+/**************************************************************************
+ *
+ * Copyright 2008 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS 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.
+ *
+ **************************************************************************/
+
+
+#ifndef BITSCAN_H
+#define BITSCAN_H
+
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+
+#if defined(_MSC_VER)
+#include <intrin.h>
+#endif
+
+#include "c99_compat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * Find first bit set in word. Least significant bit is 1.
+ * Return 0 if no bits set.
+ */
+#ifdef HAVE___BUILTIN_FFS
+#define ffs __builtin_ffs
+#elif defined(_MSC_VER) && (_M_IX86 || _M_ARM || _M_AMD64 || _M_IA64)
+static inline
+int ffs(unsigned i)
+{
+ unsigned long index;
+ if (_BitScanForward(&index, i))
+ return index + 1;
+ else
+ return 0;
+}
+#else
+extern
+int ffs(unsigned i);
+#endif
+
+#ifdef HAVE___BUILTIN_FFSLL
+#define ffsll __builtin_ffsll
+#elif defined(_MSC_VER) && (_M_AMD64 || _M_ARM || _M_IA64)
+static inline int
+ffsll(uint64_t i)
+{
+ unsigned long index;
+ if (_BitScanForward64(&index, i))
+ return index + 1;
+ else
+ return 0;
+}
+#else
+extern int
+ffsll(uint64_t val);
+#endif
+
+
+/* Destructively loop over all of the bits in a mask as in:
+ *
+ * while (mymask) {
+ * int i = u_bit_scan(&mymask);
+ * ... process element i
+ * }
+ *
+ */
+static inline int
+u_bit_scan(unsigned *mask)
+{
+ const int i = ffs(*mask) - 1;
+ *mask ^= (1u << i);
+ return i;
+}
+
+static inline int
+u_bit_scan64(uint64_t *mask)
+{
+ const int i = ffsll(*mask) - 1;
+ *mask ^= (((uint64_t)1) << i);
+ return i;
+}
+
+/* For looping over a bitmask when you want to loop over consecutive bits
+ * manually, for example:
+ *
+ * while (mask) {
+ * int start, count, i;
+ *
+ * u_bit_scan_consecutive_range(&mask, &start, &count);
+ *
+ * for (i = 0; i < count; i++)
+ * ... process element (start+i)
+ * }
+ */
+static inline void
+u_bit_scan_consecutive_range(unsigned *mask, int *start, int *count)
+{
+ if (*mask == 0xffffffff) {
+ *start = 0;
+ *count = 32;
+ *mask = 0;
+ return;
+ }
+ *start = ffs(*mask) - 1;
+ *count = ffs(~(*mask >> *start)) - 1;
+ *mask &= ~(((1u << *count) - 1) << *start);
+}
+
+static inline void
+u_bit_scan_consecutive_range64(uint64_t *mask, int *start, int *count)
+{
+ if (*mask == ~0llu) {
+ *start = 0;
+ *count = 64;
+ *mask = 0;
+ return;
+ }
+ *start = ffsll(*mask) - 1;
+ *count = ffsll(~(*mask >> *start)) - 1;
+ *mask &= ~(((((uint64_t)1) << *count) - 1) << *start);
+}
+
+
+/**
+ * Find last bit set in a word. The least significant bit is 1.
+ * Return 0 if no bits are set.
+ * Essentially ffs() in the reverse direction.
+ */
+static inline unsigned
+util_last_bit(unsigned u)
+{
+#if defined(HAVE___BUILTIN_CLZ)
+ return u == 0 ? 0 : 32 - __builtin_clz(u);
+#elif defined(_MSC_VER) && (_M_IX86 || _M_ARM || _M_AMD64 || _M_IA64)
+ unsigned long index;
+ if (_BitScanReverse(&index, u))
+ return index + 1;
+ else
+ return 0;
+#else
+ unsigned r = 0;
+ while (u) {
+ r++;
+ u >>= 1;
+ }
+ return r;
+#endif
+}
+
+/**
+ * Find last bit set in a word. The least significant bit is 1.
+ * Return 0 if no bits are set.
+ * Essentially ffsll() in the reverse direction.
+ */
+static inline unsigned
+util_last_bit64(uint64_t u)
+{
+#if defined(HAVE___BUILTIN_CLZLL)
+ return u == 0 ? 0 : 64 - __builtin_clzll(u);
+#elif defined(_MSC_VER) && (_M_AMD64 || _M_ARM || _M_IA64)
+ unsigned long index;
+ if (_BitScanReverse64(&index, u))
+ return index + 1;
+ else
+ return 0;
+#else
+ unsigned r = 0;
+ while (u) {
+ r++;
+ u >>= 1;
+ }
+ return r;
+#endif
+}
+
+/**
+ * Find last bit in a word that does not match the sign bit. The least
+ * significant bit is 1.
+ * Return 0 if no bits are set.
+ */
+static inline unsigned
+util_last_bit_signed(int i)
+{
+ if (i >= 0)
+ return util_last_bit(i);
+ else
+ return util_last_bit(~(unsigned)i);
+}
+
+/* Returns a bitfield in which the first count bits starting at start are
+ * set.
+ */
+static inline unsigned
+u_bit_consecutive(unsigned start, unsigned count)
+{
+ assert(start + count <= 32);
+ if (count == 32)
+ return ~0;
+ return ((1u << count) - 1) << start;
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BITSCAN_H */
diff --git a/lib/mesa/src/util/bitset.h b/lib/mesa/src/util/bitset.h
index c45281941..2404ce7f6 100644
--- a/lib/mesa/src/util/bitset.h
+++ b/lib/mesa/src/util/bitset.h
@@ -98,7 +98,7 @@ __bitset_ffs(const BITSET_WORD *x, int n)
static inline unsigned
__bitset_next_set(unsigned i, BITSET_WORD *tmp,
- BITSET_WORD *set, unsigned size)
+ const BITSET_WORD *set, unsigned size)
{
unsigned bit, word;
diff --git a/lib/mesa/src/util/format_r11g11b10f.h b/lib/mesa/src/util/format_r11g11b10f.h
new file mode 100644
index 000000000..f6cd4ac69
--- /dev/null
+++ b/lib/mesa/src/util/format_r11g11b10f.h
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2011 Marek Olšák <maraeo@gmail.com>
+ *
+ * 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.
+ */
+
+/* Based on code from The OpenGL Programming Guide / 7th Edition, Appendix J.
+ * Available here: http://www.opengl-redbook.com/appendices/
+ * The algorithm in the book contains a bug though, which is fixed in the code
+ * below.
+ */
+
+#include <stdint.h>
+
+#define UF11(e, m) ((e << 6) | (m))
+#define UF11_EXPONENT_BIAS 15
+#define UF11_EXPONENT_BITS 0x1F
+#define UF11_EXPONENT_SHIFT 6
+#define UF11_MANTISSA_BITS 0x3F
+#define UF11_MANTISSA_SHIFT (23 - UF11_EXPONENT_SHIFT)
+#define UF11_MAX_EXPONENT (UF11_EXPONENT_BITS << UF11_EXPONENT_SHIFT)
+
+#define UF10(e, m) ((e << 5) | (m))
+#define UF10_EXPONENT_BIAS 15
+#define UF10_EXPONENT_BITS 0x1F
+#define UF10_EXPONENT_SHIFT 5
+#define UF10_MANTISSA_BITS 0x1F
+#define UF10_MANTISSA_SHIFT (23 - UF10_EXPONENT_SHIFT)
+#define UF10_MAX_EXPONENT (UF10_EXPONENT_BITS << UF10_EXPONENT_SHIFT)
+
+#define F32_INFINITY 0x7f800000
+
+static inline uint32_t f32_to_uf11(float val)
+{
+ union {
+ float f;
+ uint32_t ui;
+ } f32 = {val};
+
+ uint16_t uf11 = 0;
+
+ /* Decode little-endian 32-bit floating-point value */
+ int sign = (f32.ui >> 16) & 0x8000;
+ /* Map exponent to the range [-127,128] */
+ int exponent = ((f32.ui >> 23) & 0xff) - 127;
+ int mantissa = f32.ui & 0x007fffff;
+
+ if (exponent == 128) { /* Infinity or NaN */
+ /* From the GL_EXT_packed_float spec:
+ *
+ * "Additionally: negative infinity is converted to zero; positive
+ * infinity is converted to positive infinity; and both positive and
+ * negative NaN are converted to positive NaN."
+ */
+ uf11 = UF11_MAX_EXPONENT;
+ if (mantissa) {
+ uf11 |= 1; /* NaN */
+ } else {
+ if (sign)
+ uf11 = 0; /* 0.0 */
+ }
+ } else if (sign) {
+ return 0;
+ } else if (val > 65024.0f) {
+ /* From the GL_EXT_packed_float spec:
+ *
+ * "Likewise, finite positive values greater than 65024 (the maximum
+ * finite representable unsigned 11-bit floating-point value) are
+ * converted to 65024."
+ */
+ uf11 = UF11(30, 63);
+ } else if (exponent > -15) { /* Representable value */
+ exponent += UF11_EXPONENT_BIAS;
+ mantissa >>= UF11_MANTISSA_SHIFT;
+ uf11 = exponent << UF11_EXPONENT_SHIFT | mantissa;
+ }
+
+ return uf11;
+}
+
+static inline float uf11_to_f32(uint16_t val)
+{
+ union {
+ float f;
+ uint32_t ui;
+ } f32;
+
+ int exponent = (val & 0x07c0) >> UF11_EXPONENT_SHIFT;
+ int mantissa = (val & 0x003f);
+
+ f32.f = 0.0;
+
+ if (exponent == 0) {
+ if (mantissa != 0) {
+ const float scale = 1.0 / (1 << 20);
+ f32.f = scale * mantissa;
+ }
+ } else if (exponent == 31) {
+ f32.ui = F32_INFINITY | mantissa;
+ } else {
+ float scale, decimal;
+ exponent -= 15;
+ if (exponent < 0) {
+ scale = 1.0f / (1 << -exponent);
+ } else {
+ scale = (float) (1 << exponent);
+ }
+ decimal = 1.0f + (float) mantissa / 64;
+ f32.f = scale * decimal;
+ }
+
+ return f32.f;
+}
+
+static inline uint32_t f32_to_uf10(float val)
+{
+ union {
+ float f;
+ uint32_t ui;
+ } f32 = {val};
+
+ uint16_t uf10 = 0;
+
+ /* Decode little-endian 32-bit floating-point value */
+ int sign = (f32.ui >> 16) & 0x8000;
+ /* Map exponent to the range [-127,128] */
+ int exponent = ((f32.ui >> 23) & 0xff) - 127;
+ int mantissa = f32.ui & 0x007fffff;
+
+ if (exponent == 128) {
+ /* From the GL_EXT_packed_float spec:
+ *
+ * "Additionally: negative infinity is converted to zero; positive
+ * infinity is converted to positive infinity; and both positive and
+ * negative NaN are converted to positive NaN."
+ */
+ uf10 = UF10_MAX_EXPONENT;
+ if (mantissa) {
+ uf10 |= 1; /* NaN */
+ } else {
+ if (sign)
+ uf10 = 0; /* 0.0 */
+ }
+ } else if (sign) {
+ return 0;
+ } else if (val > 64512.0f) {
+ /* From the GL_EXT_packed_float spec:
+ *
+ * "Likewise, finite positive values greater than 64512 (the maximum
+ * finite representable unsigned 10-bit floating-point value) are
+ * converted to 64512."
+ */
+ uf10 = UF10(30, 31);
+ } else if (exponent > -15) { /* Representable value */
+ exponent += UF10_EXPONENT_BIAS;
+ mantissa >>= UF10_MANTISSA_SHIFT;
+ uf10 = exponent << UF10_EXPONENT_SHIFT | mantissa;
+ }
+
+ return uf10;
+}
+
+static inline float uf10_to_f32(uint16_t val)
+{
+ union {
+ float f;
+ uint32_t ui;
+ } f32;
+
+ int exponent = (val & 0x03e0) >> UF10_EXPONENT_SHIFT;
+ int mantissa = (val & 0x001f);
+
+ f32.f = 0.0;
+
+ if (exponent == 0) {
+ if (mantissa != 0) {
+ const float scale = 1.0 / (1 << 19);
+ f32.f = scale * mantissa;
+ }
+ } else if (exponent == 31) {
+ f32.ui = F32_INFINITY | mantissa;
+ } else {
+ float scale, decimal;
+ exponent -= 15;
+ if (exponent < 0) {
+ scale = 1.0f / (1 << -exponent);
+ }
+ else {
+ scale = (float) (1 << exponent);
+ }
+ decimal = 1.0f + (float) mantissa / 32;
+ f32.f = scale * decimal;
+ }
+
+ return f32.f;
+}
+
+static inline uint32_t float3_to_r11g11b10f(const float rgb[3])
+{
+ return ( f32_to_uf11(rgb[0]) & 0x7ff) |
+ ((f32_to_uf11(rgb[1]) & 0x7ff) << 11) |
+ ((f32_to_uf10(rgb[2]) & 0x3ff) << 22);
+}
+
+static inline void r11g11b10f_to_float3(uint32_t rgb, float retval[3])
+{
+ retval[0] = uf11_to_f32( rgb & 0x7ff);
+ retval[1] = uf11_to_f32((rgb >> 11) & 0x7ff);
+ retval[2] = uf10_to_f32((rgb >> 22) & 0x3ff);
+}
diff --git a/lib/mesa/src/util/format_rgb9e5.h b/lib/mesa/src/util/format_rgb9e5.h
new file mode 100644
index 000000000..70ad04fde
--- /dev/null
+++ b/lib/mesa/src/util/format_rgb9e5.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2011 Marek Olšák <maraeo@gmail.com>
+ *
+ * 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.
+ */
+
+/* Copied from EXT_texture_shared_exponent and edited, getting rid of
+ * expensive float math bits too. */
+
+#ifndef RGB9E5_H
+#define RGB9E5_H
+
+#include <assert.h>
+#include <stdint.h>
+
+#include "c99_math.h"
+
+#define RGB9E5_EXPONENT_BITS 5
+#define RGB9E5_MANTISSA_BITS 9
+#define RGB9E5_EXP_BIAS 15
+#define RGB9E5_MAX_VALID_BIASED_EXP 31
+
+#define MAX_RGB9E5_EXP (RGB9E5_MAX_VALID_BIASED_EXP - RGB9E5_EXP_BIAS)
+#define RGB9E5_MANTISSA_VALUES (1<<RGB9E5_MANTISSA_BITS)
+#define MAX_RGB9E5_MANTISSA (RGB9E5_MANTISSA_VALUES-1)
+#define MAX_RGB9E5 (((float)MAX_RGB9E5_MANTISSA)/RGB9E5_MANTISSA_VALUES * (1<<MAX_RGB9E5_EXP))
+
+static inline int rgb9e5_ClampRange(float x)
+{
+ union { float f; uint32_t u; } f, max;
+ f.f = x;
+ max.f = MAX_RGB9E5;
+
+ if (f.u > 0x7f800000)
+ /* catches neg, NaNs */
+ return 0;
+ else if (f.u >= max.u)
+ return max.u;
+ else
+ return f.u;
+}
+
+static inline uint32_t float3_to_rgb9e5(const float rgb[3])
+{
+ int rm, gm, bm, exp_shared;
+ uint32_t revdenom_biasedexp;
+ union { float f; uint32_t u; } rc, bc, gc, maxrgb, revdenom;
+
+ rc.u = rgb9e5_ClampRange(rgb[0]);
+ gc.u = rgb9e5_ClampRange(rgb[1]);
+ bc.u = rgb9e5_ClampRange(rgb[2]);
+ maxrgb.u = MAX3(rc.u, gc.u, bc.u);
+
+ /*
+ * Compared to what the spec suggests, instead of conditionally adjusting
+ * the exponent after the fact do it here by doing the equivalent of +0.5 -
+ * the int add will spill over into the exponent in this case.
+ */
+ maxrgb.u += maxrgb.u & (1 << (23-9));
+ exp_shared = MAX2((maxrgb.u >> 23), -RGB9E5_EXP_BIAS - 1 + 127) +
+ 1 + RGB9E5_EXP_BIAS - 127;
+ revdenom_biasedexp = 127 - (exp_shared - RGB9E5_EXP_BIAS -
+ RGB9E5_MANTISSA_BITS) + 1;
+ revdenom.u = revdenom_biasedexp << 23;
+ assert(exp_shared <= RGB9E5_MAX_VALID_BIASED_EXP);
+
+ /*
+ * The spec uses strict round-up behavior (d3d10 disagrees, but in any case
+ * must match what is done above for figuring out exponent).
+ * We avoid the doubles ((int) rc * revdenom + 0.5) by doing the rounding
+ * ourselves (revdenom was adjusted by +1, above).
+ */
+ rm = (int) (rc.f * revdenom.f);
+ gm = (int) (gc.f * revdenom.f);
+ bm = (int) (bc.f * revdenom.f);
+ rm = (rm & 1) + (rm >> 1);
+ gm = (gm & 1) + (gm >> 1);
+ bm = (bm & 1) + (bm >> 1);
+
+ assert(rm <= MAX_RGB9E5_MANTISSA);
+ assert(gm <= MAX_RGB9E5_MANTISSA);
+ assert(bm <= MAX_RGB9E5_MANTISSA);
+ assert(rm >= 0);
+ assert(gm >= 0);
+ assert(bm >= 0);
+
+ return (exp_shared << 27) | (bm << 18) | (gm << 9) | rm;
+}
+
+static inline void rgb9e5_to_float3(uint32_t rgb, float retval[3])
+{
+ int exponent;
+ union { float f; uint32_t u; } scale;
+
+ exponent = (rgb >> 27) - RGB9E5_EXP_BIAS - RGB9E5_MANTISSA_BITS;
+ scale.u = (exponent + 127) << 23;
+
+ retval[0] = ( rgb & 0x1ff) * scale.f;
+ retval[1] = ((rgb >> 9) & 0x1ff) * scale.f;
+ retval[2] = ((rgb >> 18) & 0x1ff) * scale.f;
+}
+
+#endif
diff --git a/lib/mesa/src/util/hash_table.c b/lib/mesa/src/util/hash_table.c
index 4cfe3d932..9e643af8b 100644
--- a/lib/mesa/src/util/hash_table.c
+++ b/lib/mesa/src/util/hash_table.c
@@ -295,6 +295,8 @@ hash_table_insert(struct hash_table *ht, uint32_t hash,
uint32_t start_hash_address, hash_address;
struct hash_entry *available_entry = NULL;
+ assert(key != NULL);
+
if (ht->entries >= ht->max_entries) {
_mesa_hash_table_rehash(ht, ht->size_index + 1);
} else if (ht->deleted_entries + ht->entries >= ht->max_entries) {
diff --git a/lib/mesa/src/util/hash_table.h b/lib/mesa/src/util/hash_table.h
index c69abfa3e..b35ee871b 100644
--- a/lib/mesa/src/util/hash_table.h
+++ b/lib/mesa/src/util/hash_table.h
@@ -139,6 +139,19 @@ _mesa_fnv32_1a_accumulate_block(uint32_t hash, const void *data, size_t size)
entry != NULL; \
entry = _mesa_hash_table_next_entry(ht, entry))
+static inline void
+hash_table_call_foreach(struct hash_table *ht,
+ void (*callback)(const void *key,
+ void *data,
+ void *closure),
+ void *closure)
+{
+ struct hash_entry *entry;
+
+ hash_table_foreach(ht, entry)
+ callback(entry->key, entry->data, closure);
+}
+
#ifdef __cplusplus
} /* extern C */
#endif
diff --git a/lib/mesa/src/util/list.h b/lib/mesa/src/util/list.h
index 066f9b8df..e8a99ac8e 100644
--- a/lib/mesa/src/util/list.h
+++ b/lib/mesa/src/util/list.h
@@ -71,12 +71,18 @@ static inline void list_addtail(struct list_head *item, struct list_head *list)
list->prev = item;
}
+static inline bool list_empty(struct list_head *list);
+
static inline void list_replace(struct list_head *from, struct list_head *to)
{
- to->prev = from->prev;
- to->next = from->next;
- from->next->prev = to;
- from->prev->next = to;
+ if (list_empty(from)) {
+ list_inithead(to);
+ } else {
+ to->prev = from->prev;
+ to->next = from->next;
+ from->next->prev = to;
+ from->prev->next = to;
+ }
}
static inline void list_del(struct list_head *item)
@@ -116,6 +122,28 @@ static inline unsigned list_length(struct list_head *list)
return length;
}
+static inline void list_splice(struct list_head *src, struct list_head *dst)
+{
+ if (list_empty(src))
+ return;
+
+ src->next->prev = dst;
+ src->prev->next = dst->next;
+ dst->next->prev = src->prev;
+ dst->next = src->next;
+}
+
+static inline void list_splicetail(struct list_head *src, struct list_head *dst)
+{
+ if (list_empty(src))
+ return;
+
+ src->prev->next = dst;
+ src->next->prev = dst->prev;
+ dst->prev->next = src->next;
+ dst->prev = src->prev;
+}
+
static inline void list_validate(struct list_head *list)
{
struct list_head *node;
diff --git a/lib/mesa/src/util/macros.h b/lib/mesa/src/util/macros.h
index 71bb15744..27d1b6292 100644
--- a/lib/mesa/src/util/macros.h
+++ b/lib/mesa/src/util/macros.h
@@ -26,6 +26,8 @@
#include <assert.h>
+#include "c99_compat.h"
+
/* Compute the size of an array */
#ifndef ARRAY_SIZE
# define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
@@ -152,6 +154,12 @@ do { \
#define ATTRIBUTE_PURE
#endif
+#ifdef HAVE_FUNC_ATTRIBUTE_RETURNS_NONNULL
+#define ATTRIBUTE_RETURNS_NONNULL __attribute__((__returns_nonnull__))
+#else
+#define ATTRIBUTE_RETURNS_NONNULL
+#endif
+
#ifdef __cplusplus
/**
* Macro function that evaluates to true if T is a trivially
@@ -204,13 +212,15 @@ do { \
#define UNUSED
#endif
+#define MAYBE_UNUSED UNUSED
+
#ifdef HAVE_FUNC_ATTRIBUTE_WARN_UNUSED_RESULT
#define MUST_CHECK __attribute__((warn_unused_result))
#else
#define MUST_CHECK
#endif
-#if defined(__GNUC__) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590))
+#if defined(__GNUC__)
#define ATTRIBUTE_NOINLINE __attribute__((noinline))
#else
#define ATTRIBUTE_NOINLINE
@@ -219,4 +229,17 @@ do { \
/** Compute ceiling of integer quotient of A divided by B. */
#define DIV_ROUND_UP( A, B ) ( (A) % (B) == 0 ? (A)/(B) : (A)/(B)+1 )
+/** Clamp X to [MIN,MAX] */
+#define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) )
+
+/** Minimum of two values: */
+#define MIN2( A, B ) ( (A)<(B) ? (A) : (B) )
+
+/** Maximum of two values: */
+#define MAX2( A, B ) ( (A)>(B) ? (A) : (B) )
+
+/** Minimum and maximum of three values: */
+#define MIN3( A, B, C ) ((A) < (B) ? MIN2(A, C) : MIN2(B, C))
+#define MAX3( A, B, C ) ((A) > (B) ? MAX2(A, C) : MAX2(B, C))
+
#endif /* UTIL_MACROS_H */
diff --git a/lib/mesa/src/util/mesa-sha1.c b/lib/mesa/src/util/mesa-sha1.c
index faa1c871b..b6a192f4d 100644
--- a/lib/mesa/src/util/mesa-sha1.c
+++ b/lib/mesa/src/util/mesa-sha1.c
@@ -175,21 +175,25 @@ _mesa_sha1_final(struct mesa_sha1 *ctx, unsigned char result[20])
#elif defined(HAVE_SHA1_IN_LIBGCRYPT) /* Use libgcrypt for SHA1 */
#include <gcrypt.h>
+#include "c11/threads.h"
+
+static void _mesa_libgcrypt_init(void)
+{
+ if (!gcry_check_version(NULL))
+ return;
+
+ gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
+ gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
+}
struct mesa_sha1 *
_mesa_sha1_init(void)
{
- static int init;
+ static once_flag flag = ONCE_FLAG_INIT;
gcry_md_hd_t h;
gcry_error_t err;
- if (!init) {
- if (!gcry_check_version(NULL))
- return NULL;
- gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
- gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
- init = 1;
- }
+ call_once(&flag, _mesa_libgcrypt_init);
err = gcry_md_open(&h, GCRY_MD_SHA1, 0);
if (err)
diff --git a/lib/mesa/src/util/mesa-sha1.h b/lib/mesa/src/util/mesa-sha1.h
index 1599405cd..0be5485f3 100644
--- a/lib/mesa/src/util/mesa-sha1.h
+++ b/lib/mesa/src/util/mesa-sha1.h
@@ -23,12 +23,12 @@
#ifndef SHA1_H
#define SHA1_H
+#include <stdlib.h>
+
#ifdef __cplusplus
extern "C" {
#endif
-#include <stdlib.h>
-
struct mesa_sha1;
struct mesa_sha1 *
diff --git a/lib/mesa/src/util/ralloc.c b/lib/mesa/src/util/ralloc.c
index 6d4032bd4..9526011b8 100644
--- a/lib/mesa/src/util/ralloc.c
+++ b/lib/mesa/src/util/ralloc.c
@@ -110,6 +110,18 @@ ralloc_context(const void *ctx)
void *
ralloc_size(const void *ctx, size_t size)
{
+ /* ralloc_size was originally implemented using calloc, which meant some
+ * code accidentally relied on its zero filling behavior.
+ *
+ * TODO: Make ralloc_size not zero fill memory, and cleanup any code that
+ * should instead be using rzalloc.
+ */
+ return rzalloc_size(ctx, size);
+}
+
+void *
+rzalloc_size(const void *ctx, size_t size)
+{
void *block = calloc(1, size + sizeof(ralloc_header));
ralloc_header *info;
ralloc_header *parent;
@@ -128,15 +140,6 @@ ralloc_size(const void *ctx, size_t size)
return PTR_FROM_HEADER(info);
}
-void *
-rzalloc_size(const void *ctx, size_t size)
-{
- void *ptr = ralloc_size(ctx, size);
- if (likely(ptr != NULL))
- memset(ptr, 0, size);
- return ptr;
-}
-
/* helper function - assumes ptr != NULL */
static void *
resize(void *ptr, size_t size)
diff --git a/lib/mesa/src/util/rounding.h b/lib/mesa/src/util/rounding.h
index afb38fbdb..dfc691eaf 100644
--- a/lib/mesa/src/util/rounding.h
+++ b/lib/mesa/src/util/rounding.h
@@ -29,7 +29,8 @@
#include <limits.h>
#include <stdint.h>
-#ifdef __x86_64__
+#if defined(__SSE__) || defined(_MSC_VER)
+/* MSVC always has SSE nowadays */
#include <xmmintrin.h>
#include <emmintrin.h>
#endif
@@ -95,7 +96,7 @@ _mesa_roundeven(double x)
static inline long
_mesa_lroundevenf(float x)
{
-#ifdef __x86_64__
+#if defined(__SSE__) || defined(_MSC_VER)
#if LONG_MAX == INT64_MAX
return _mm_cvtss_si64(_mm_load_ss(&x));
#elif LONG_MAX == INT32_MAX
@@ -115,7 +116,7 @@ _mesa_lroundevenf(float x)
static inline long
_mesa_lroundeven(double x)
{
-#ifdef __x86_64__
+#if defined(__SSE__) || defined(_MSC_VER)
#if LONG_MAX == INT64_MAX
return _mm_cvtsd_si64(_mm_load_sd(&x));
#elif LONG_MAX == INT32_MAX
diff --git a/lib/mesa/src/util/slab.c b/lib/mesa/src/util/slab.c
new file mode 100644
index 000000000..4264814ca
--- /dev/null
+++ b/lib/mesa/src/util/slab.c
@@ -0,0 +1,316 @@
+/*
+ * Copyright 2010 Marek Olšák <maraeo@gmail.com>
+ * Copyright 2016 Advanced Micro Devices, 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
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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. */
+
+#include "slab.h"
+#include "macros.h"
+#include "u_atomic.h"
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+
+#define ALIGN(value, align) (((value) + (align) - 1) & ~((align) - 1))
+
+#define SLAB_MAGIC_ALLOCATED 0xcafe4321
+#define SLAB_MAGIC_FREE 0x7ee01234
+
+#ifdef DEBUG
+#define SET_MAGIC(element, value) (element)->magic = (value)
+#define CHECK_MAGIC(element, value) assert((element)->magic == (value))
+#else
+#define SET_MAGIC(element, value)
+#define CHECK_MAGIC(element, value)
+#endif
+
+/* One array element within a big buffer. */
+struct slab_element_header {
+ /* The next element in the free or migrated list. */
+ struct slab_element_header *next;
+
+ /* This is either
+ * - a pointer to the child pool to which this element belongs, or
+ * - a pointer to the orphaned page of the element, with the least
+ * significant bit set to 1.
+ */
+ intptr_t owner;
+
+#ifdef DEBUG
+ intptr_t magic;
+#endif
+};
+
+/* The page is an array of allocations in one block. */
+struct slab_page_header {
+ union {
+ /* Next page in the same child pool. */
+ struct slab_page_header *next;
+
+ /* Number of remaining, non-freed elements (for orphaned pages). */
+ unsigned num_remaining;
+ } u;
+ /* Memory after the last member is dedicated to the page itself.
+ * The allocated size is always larger than this structure.
+ */
+};
+
+
+static struct slab_element_header *
+slab_get_element(struct slab_parent_pool *parent,
+ struct slab_page_header *page, unsigned index)
+{
+ return (struct slab_element_header*)
+ ((uint8_t*)&page[1] + (parent->element_size * index));
+}
+
+/* The given object/element belongs to an orphaned page (i.e. the owning child
+ * pool has been destroyed). Mark the element as freed and free the whole page
+ * when no elements are left in it.
+ */
+static void
+slab_free_orphaned(struct slab_element_header *elt)
+{
+ struct slab_page_header *page;
+
+ assert(elt->owner & 1);
+
+ page = (struct slab_page_header *)(elt->owner & ~(intptr_t)1);
+ if (!p_atomic_dec_return(&page->u.num_remaining))
+ free(page);
+}
+
+/**
+ * Create a parent pool for the allocation of same-sized objects.
+ *
+ * \param item_size Size of one object.
+ * \param num_items Number of objects to allocate at once.
+ */
+void
+slab_create_parent(struct slab_parent_pool *parent,
+ unsigned item_size,
+ unsigned num_items)
+{
+ mtx_init(&parent->mutex, mtx_plain);
+ parent->element_size = ALIGN(sizeof(struct slab_element_header) + item_size,
+ sizeof(intptr_t));
+ parent->num_elements = num_items;
+}
+
+void
+slab_destroy_parent(struct slab_parent_pool *parent)
+{
+ mtx_destroy(&parent->mutex);
+}
+
+/**
+ * Create a child pool linked to the given parent.
+ */
+void slab_create_child(struct slab_child_pool *pool,
+ struct slab_parent_pool *parent)
+{
+ pool->parent = parent;
+ pool->pages = NULL;
+ pool->free = NULL;
+ pool->migrated = NULL;
+}
+
+/**
+ * Destroy the child pool.
+ *
+ * Pages associated to the pool will be orphaned. They are eventually freed
+ * when all objects in them are freed.
+ */
+void slab_destroy_child(struct slab_child_pool *pool)
+{
+ mtx_lock(&pool->parent->mutex);
+
+ while (pool->pages) {
+ struct slab_page_header *page = pool->pages;
+ pool->pages = page->u.next;
+ p_atomic_set(&page->u.num_remaining, pool->parent->num_elements);
+
+ for (unsigned i = 0; i < pool->parent->num_elements; ++i) {
+ struct slab_element_header *elt = slab_get_element(pool->parent, page, i);
+ p_atomic_set(&elt->owner, (intptr_t)page | 1);
+ }
+ }
+
+ while (pool->migrated) {
+ struct slab_element_header *elt = pool->migrated;
+ pool->migrated = elt->next;
+ slab_free_orphaned(elt);
+ }
+
+ mtx_unlock(&pool->parent->mutex);
+
+ while (pool->free) {
+ struct slab_element_header *elt = pool->free;
+ pool->free = elt->next;
+ slab_free_orphaned(elt);
+ }
+
+ /* Guard against use-after-free. */
+ pool->parent = NULL;
+}
+
+static bool
+slab_add_new_page(struct slab_child_pool *pool)
+{
+ struct slab_page_header *page = malloc(sizeof(struct slab_page_header) +
+ pool->parent->num_elements * pool->parent->element_size);
+
+ if (!page)
+ return false;
+
+ for (unsigned i = 0; i < pool->parent->num_elements; ++i) {
+ struct slab_element_header *elt = slab_get_element(pool->parent, page, i);
+ elt->owner = (intptr_t)pool;
+ assert(!(elt->owner & 1));
+
+ elt->next = pool->free;
+ pool->free = elt;
+ SET_MAGIC(elt, SLAB_MAGIC_FREE);
+ }
+
+ page->u.next = pool->pages;
+ pool->pages = page;
+
+ return true;
+}
+
+/**
+ * Allocate an object from the child pool. Single-threaded (i.e. the caller
+ * must ensure that no operation happens on the same child pool in another
+ * thread).
+ */
+void *
+slab_alloc(struct slab_child_pool *pool)
+{
+ struct slab_element_header *elt;
+
+ if (!pool->free) {
+ /* First, collect elements that belong to us but were freed from a
+ * different child pool.
+ */
+ mtx_lock(&pool->parent->mutex);
+ pool->free = pool->migrated;
+ pool->migrated = NULL;
+ mtx_unlock(&pool->parent->mutex);
+
+ /* Now allocate a new page. */
+ if (!pool->free && !slab_add_new_page(pool))
+ return NULL;
+ }
+
+ elt = pool->free;
+ pool->free = elt->next;
+
+ CHECK_MAGIC(elt, SLAB_MAGIC_FREE);
+ SET_MAGIC(elt, SLAB_MAGIC_ALLOCATED);
+
+ return &elt[1];
+}
+
+/**
+ * Free an object allocated from the slab. Single-threaded (i.e. the caller
+ * must ensure that no operation happens on the same child pool in another
+ * thread).
+ *
+ * Freeing an object in a different child pool from the one where it was
+ * allocated is allowed, as long the pool belong to the same parent. No
+ * additional locking is required in this case.
+ */
+void slab_free(struct slab_child_pool *pool, void *ptr)
+{
+ struct slab_element_header *elt = ((struct slab_element_header*)ptr - 1);
+ intptr_t owner_int;
+
+ CHECK_MAGIC(elt, SLAB_MAGIC_ALLOCATED);
+ SET_MAGIC(elt, SLAB_MAGIC_FREE);
+
+ if (p_atomic_read(&elt->owner) == (intptr_t)pool) {
+ /* This is the simple case: The caller guarantees that we can safely
+ * access the free list.
+ */
+ elt->next = pool->free;
+ pool->free = elt;
+ return;
+ }
+
+ /* The slow case: migration or an orphaned page. */
+ mtx_lock(&pool->parent->mutex);
+
+ /* Note: we _must_ re-read elt->owner here because the owning child pool
+ * may have been destroyed by another thread in the meantime.
+ */
+ owner_int = p_atomic_read(&elt->owner);
+
+ if (!(owner_int & 1)) {
+ struct slab_child_pool *owner = (struct slab_child_pool *)owner_int;
+ elt->next = owner->migrated;
+ owner->migrated = elt;
+ mtx_unlock(&pool->parent->mutex);
+ } else {
+ mtx_unlock(&pool->parent->mutex);
+
+ slab_free_orphaned(elt);
+ }
+}
+
+/**
+ * Allocate an object from the slab. Single-threaded (no mutex).
+ */
+void *
+slab_alloc_st(struct slab_mempool *pool)
+{
+ return slab_alloc(&pool->child);
+}
+
+/**
+ * Free an object allocated from the slab. Single-threaded (no mutex).
+ */
+void
+slab_free_st(struct slab_mempool *pool, void *ptr)
+{
+ slab_free(&pool->child, ptr);
+}
+
+void
+slab_destroy(struct slab_mempool *pool)
+{
+ slab_destroy_child(&pool->child);
+ slab_destroy_parent(&pool->parent);
+}
+
+/**
+ * Create an allocator for same-sized objects.
+ *
+ * \param item_size Size of one object.
+ * \param num_items Number of objects to allocate at once.
+ */
+void
+slab_create(struct slab_mempool *pool,
+ unsigned item_size,
+ unsigned num_items)
+{
+ slab_create_parent(&pool->parent, item_size, num_items);
+ slab_create_child(&pool->child, &pool->parent);
+}
diff --git a/lib/mesa/src/util/slab.h b/lib/mesa/src/util/slab.h
new file mode 100644
index 000000000..e83f8ec1a
--- /dev/null
+++ b/lib/mesa/src/util/slab.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2010 Marek Olšák <maraeo@gmail.com>
+ * Copyright 2016 Advanced Micro Devices, 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
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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. */
+
+/**
+ * Slab allocator for equally sized memory allocations.
+ *
+ * Objects are allocated from "child" pools that are connected to a "parent"
+ * pool.
+ *
+ * Calls to slab_alloc/slab_free for the same child pool must not occur from
+ * multiple threads simultaneously.
+ *
+ * Allocations obtained from one child pool should usually be freed in the
+ * same child pool. Freeing an allocation in a different child pool associated
+ * to the same parent is allowed (and requires no locking by the caller), but
+ * it is discouraged because it implies a performance penalty.
+ *
+ * For convenience and to ease the transition, there is also a set of wrapper
+ * functions around a single parent-child pair.
+ */
+
+#ifndef SLAB_H
+#define SLAB_H
+
+#include "c11/threads.h"
+
+struct slab_element_header;
+struct slab_page_header;
+
+struct slab_parent_pool {
+ mtx_t mutex;
+ unsigned element_size;
+ unsigned num_elements;
+};
+
+struct slab_child_pool {
+ struct slab_parent_pool *parent;
+
+ struct slab_page_header *pages;
+
+ /* Free elements. */
+ struct slab_element_header *free;
+
+ /* Elements that are owned by this pool but were freed with a different
+ * pool as the argument to slab_free.
+ *
+ * This list is protected by the parent mutex.
+ */
+ struct slab_element_header *migrated;
+};
+
+void slab_create_parent(struct slab_parent_pool *parent,
+ unsigned item_size,
+ unsigned num_items);
+void slab_destroy_parent(struct slab_parent_pool *parent);
+void slab_create_child(struct slab_child_pool *pool,
+ struct slab_parent_pool *parent);
+void slab_destroy_child(struct slab_child_pool *pool);
+void *slab_alloc(struct slab_child_pool *pool);
+void slab_free(struct slab_child_pool *pool, void *ptr);
+
+struct slab_mempool {
+ struct slab_parent_pool parent;
+ struct slab_child_pool child;
+};
+
+void slab_create(struct slab_mempool *pool,
+ unsigned item_size,
+ unsigned num_items);
+void slab_destroy(struct slab_mempool *pool);
+void *slab_alloc_st(struct slab_mempool *pool);
+void slab_free_st(struct slab_mempool *pool, void *ptr);
+
+#endif
diff --git a/lib/mesa/src/util/string_to_uint_map.cpp b/lib/mesa/src/util/string_to_uint_map.cpp
new file mode 100644
index 000000000..35fb76bf7
--- /dev/null
+++ b/lib/mesa/src/util/string_to_uint_map.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file string_to_uint_map.cpp
+ * \brief Dumb wrapprs so that C code can create and destroy maps.
+ *
+ * \author Ian Romanick <ian.d.romanick@intel.com>
+ */
+#include "string_to_uint_map.h"
+
+extern "C" struct string_to_uint_map *
+string_to_uint_map_ctor()
+{
+ return new string_to_uint_map;
+}
+
+extern "C" void
+string_to_uint_map_dtor(struct string_to_uint_map *map)
+{
+ delete map;
+}
diff --git a/lib/mesa/src/util/string_to_uint_map.h b/lib/mesa/src/util/string_to_uint_map.h
new file mode 100644
index 000000000..e0533ec6e
--- /dev/null
+++ b/lib/mesa/src/util/string_to_uint_map.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ *
+ * 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.
+ *
+ */
+
+#ifndef STRING_TO_UINT_MAP_H
+#define STRING_TO_UINT_MAP_H
+
+#include <string.h>
+#include <limits.h>
+#include "util/hash_table.h"
+
+struct string_to_uint_map;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct string_to_uint_map *
+string_to_uint_map_ctor();
+
+void
+string_to_uint_map_dtor(struct string_to_uint_map *);
+
+
+#ifdef __cplusplus
+}
+
+struct string_map_iterate_wrapper_closure {
+ void (*callback)(const char *key, unsigned value, void *closure);
+ void *closure;
+};
+
+/**
+ * Map from a string (name) to an unsigned integer value
+ *
+ * \note
+ * Because of the way this class interacts with the \c hash_table
+ * implementation, values of \c UINT_MAX cannot be stored in the map.
+ */
+struct string_to_uint_map {
+public:
+ string_to_uint_map()
+ {
+ this->ht = _mesa_hash_table_create(NULL, _mesa_key_hash_string,
+ _mesa_key_string_equal);
+ }
+
+ ~string_to_uint_map()
+ {
+ hash_table_call_foreach(this->ht, delete_key, NULL);
+ _mesa_hash_table_destroy(this->ht, NULL);
+ }
+
+ /**
+ * Remove all mappings from this map.
+ */
+ void clear()
+ {
+ hash_table_call_foreach(this->ht, delete_key, NULL);
+ _mesa_hash_table_clear(this->ht, NULL);
+ }
+
+ /**
+ * Runs a passed callback for the hash
+ */
+ void iterate(void (*func)(const char *, unsigned, void *), void *closure)
+ {
+ struct string_map_iterate_wrapper_closure *wrapper;
+
+ wrapper = (struct string_map_iterate_wrapper_closure *)
+ malloc(sizeof(struct string_map_iterate_wrapper_closure));
+ if (wrapper == NULL)
+ return;
+
+ wrapper->callback = func;
+ wrapper->closure = closure;
+
+ hash_table_call_foreach(this->ht, subtract_one_wrapper, wrapper);
+ free(wrapper);
+ }
+
+ /**
+ * Get the value associated with a particular key
+ *
+ * \return
+ * If \c key is found in the map, \c true is returned. Otherwise \c false
+ * is returned.
+ *
+ * \note
+ * If \c key is not found in the table, \c value is not modified.
+ */
+ bool get(unsigned &value, const char *key)
+ {
+ hash_entry *entry = _mesa_hash_table_search(this->ht,
+ (const void *) key);
+
+ if (!entry)
+ return false;
+
+ const intptr_t v = (intptr_t) entry->data;
+ value = (unsigned)(v - 1);
+ return true;
+ }
+
+ void put(unsigned value, const char *key)
+ {
+ /* The low-level hash table structure returns NULL if key is not in the
+ * hash table. However, users of this map might want to store zero as a
+ * valid value in the table. Bias the value by +1 so that a
+ * user-specified zero is stored as 1. This enables ::get to tell the
+ * difference between a user-specified zero (returned as 1 by
+ * _mesa_hash_table_search) and the key not in the table (returned as 0 by
+ * _mesa_hash_table_search).
+ *
+ * The net effect is that we can't store UINT_MAX in the table. This is
+ * because UINT_MAX+1 = 0.
+ */
+ assert(value != UINT_MAX);
+ char *dup_key = strdup(key);
+
+ struct hash_entry *entry = _mesa_hash_table_search(this->ht, dup_key);
+ if (entry) {
+ entry->data = (void *) (intptr_t) (value + 1);
+ } else {
+ _mesa_hash_table_insert(this->ht, dup_key,
+ (void *) (intptr_t) (value + 1));
+ }
+
+ if (entry)
+ free(dup_key);
+ }
+
+private:
+ static void delete_key(const void *key, void *data, void *closure)
+ {
+ (void) data;
+ (void) closure;
+
+ free((char *)key);
+ }
+
+ static void subtract_one_wrapper(const void *key, void *data, void *closure)
+ {
+ struct string_map_iterate_wrapper_closure *wrapper =
+ (struct string_map_iterate_wrapper_closure *) closure;
+ unsigned value = (intptr_t) data;
+
+ value -= 1;
+
+ wrapper->callback((const char *) key, value, wrapper->closure);
+ }
+
+ struct hash_table *ht;
+};
+
+#endif /* __cplusplus */
+#endif /* STRING_TO_UINT_MAP_H */
diff --git a/lib/mesa/src/util/u_endian.h b/lib/mesa/src/util/u_endian.h
new file mode 100644
index 000000000..b9d563dd4
--- /dev/null
+++ b/lib/mesa/src/util/u_endian.h
@@ -0,0 +1,69 @@
+/**************************************************************************
+ *
+ * Copyright 2007-2008 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS 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.
+ *
+ **************************************************************************/
+#ifndef U_ENDIAN_H
+#define U_ENDIAN_H
+
+#if defined(__GLIBC__) || defined(ANDROID)
+#include <endian.h>
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# define PIPE_ARCH_LITTLE_ENDIAN
+#elif __BYTE_ORDER == __BIG_ENDIAN
+# define PIPE_ARCH_BIG_ENDIAN
+#endif
+
+#elif defined(__APPLE__)
+#include <machine/endian.h>
+
+#if __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN
+# define PIPE_ARCH_LITTLE_ENDIAN
+#elif __DARWIN_BYTE_ORDER == __DARWIN_BIG_ENDIAN
+# define PIPE_ARCH_BIG_ENDIAN
+#endif
+
+#elif defined(__sun)
+#include <sys/isa_defs.h>
+
+#if defined(_LITTLE_ENDIAN)
+# define PIPE_ARCH_LITTLE_ENDIAN
+#elif defined(_BIG_ENDIAN)
+# define PIPE_ARCH_BIG_ENDIAN
+#endif
+
+#elif defined(__OpenBSD__) || defined(__NetBSD__)
+#include <sys/types.h>
+#include <machine/endian.h>
+
+#if _BYTE_ORDER == _LITTLE_ENDIAN
+# define PIPE_ARCH_LITTLE_ENDIAN
+#elif _BYTE_ORDER == _BIG_ENDIAN
+# define PIPE_ARCH_BIG_ENDIAN
+#endif
+
+#endif
+
+#endif
diff --git a/lib/mesa/src/util/u_vector.c b/lib/mesa/src/util/u_vector.c
new file mode 100644
index 000000000..37c4245eb
--- /dev/null
+++ b/lib/mesa/src/util/u_vector.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright © 2015 Intel Corporation
+ *
+ * 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.
+ */
+#include "util/u_vector.h"
+
+int
+u_vector_init(struct u_vector *vector, uint32_t element_size, uint32_t size)
+{
+ assert(util_is_power_of_two(size));
+ assert(element_size < size && util_is_power_of_two(element_size));
+
+ vector->head = 0;
+ vector->tail = 0;
+ vector->element_size = element_size;
+ vector->size = size;
+ vector->data = malloc(size);
+
+ return vector->data != NULL;
+}
+
+void *
+u_vector_add(struct u_vector *vector)
+{
+ uint32_t offset, size, split, src_tail, dst_tail;
+ void *data;
+
+ if (vector->head - vector->tail == vector->size) {
+ size = vector->size * 2;
+ data = malloc(size);
+ if (data == NULL)
+ return NULL;
+ src_tail = vector->tail & (vector->size - 1);
+ dst_tail = vector->tail & (size - 1);
+ if (src_tail == 0) {
+ /* Since we know that the vector is full, this means that it's
+ * linear from start to end so we can do one copy.
+ */
+ memcpy((char *)data + dst_tail, vector->data, vector->size);
+ } else {
+ /* In this case, the vector is split into two pieces and we have
+ * to do two copies. We have to be careful to make sure each
+ * piece goes to the right locations. Thanks to the change in
+ * size, it may or may not still wrap around.
+ */
+ split = u_align_u32(vector->tail, vector->size);
+ assert(vector->tail <= split && split < vector->head);
+ memcpy((char *)data + dst_tail, (char *)vector->data + src_tail,
+ split - vector->tail);
+ memcpy((char *)data + (split & (size - 1)), vector->data,
+ vector->head - split);
+ }
+ free(vector->data);
+ vector->data = data;
+ vector->size = size;
+ }
+
+ assert(vector->head - vector->tail < vector->size);
+
+ offset = vector->head & (vector->size - 1);
+ vector->head += vector->element_size;
+
+ return (char *)vector->data + offset;
+}
+
+void *
+u_vector_remove(struct u_vector *vector)
+{
+ uint32_t offset;
+
+ if (vector->head == vector->tail)
+ return NULL;
+
+ assert(vector->head - vector->tail <= vector->size);
+
+ offset = vector->tail & (vector->size - 1);
+ vector->tail += vector->element_size;
+
+ return (char *)vector->data + offset;
+}
diff --git a/lib/mesa/src/util/u_vector.h b/lib/mesa/src/util/u_vector.h
new file mode 100644
index 000000000..8fa4ec483
--- /dev/null
+++ b/lib/mesa/src/util/u_vector.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright © 2015 Intel Corporation
+ *
+ * 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.
+ */
+
+/*
+ * u_vector is a vector based queue for storing arbitrary
+ * sized arrays of objects without using a linked list.
+ */
+
+#ifndef U_VECTOR_H
+#define U_VECTOR_H
+
+#include <stdint.h>
+#include <stdlib.h>
+#include "util/u_math.h"
+#include "util/macros.h"
+
+/* TODO - move to u_math.h - name it better etc */
+static inline uint32_t
+u_align_u32(uint32_t v, uint32_t a)
+{
+ assert(a != 0 && a == (a & -a));
+ return (v + a - 1) & ~(a - 1);
+}
+
+struct u_vector {
+ uint32_t head;
+ uint32_t tail;
+ uint32_t element_size;
+ uint32_t size;
+ void *data;
+};
+
+int u_vector_init(struct u_vector *queue, uint32_t element_size, uint32_t size);
+void *u_vector_add(struct u_vector *queue);
+void *u_vector_remove(struct u_vector *queue);
+
+static inline int
+u_vector_length(struct u_vector *queue)
+{
+ return (queue->head - queue->tail) / queue->element_size;
+}
+
+static inline void *
+u_vector_head(struct u_vector *vector)
+{
+ assert(vector->tail < vector->head);
+ return (void *)((char *)vector->data +
+ ((vector->head - vector->element_size) &
+ (vector->size - 1)));
+}
+
+static inline void *
+u_vector_tail(struct u_vector *vector)
+{
+ return (void *)((char *)vector->data + (vector->tail & (vector->size - 1)));
+}
+
+static inline void
+u_vector_finish(struct u_vector *queue)
+{
+ free(queue->data);
+}
+
+#define u_vector_foreach(elem, queue) \
+ static_assert(__builtin_types_compatible_p(__typeof__(queue), struct u_vector *), ""); \
+ for (uint32_t __u_vector_offset = (queue)->tail; \
+ elem = (queue)->data + (__u_vector_offset & ((queue)->size - 1)), __u_vector_offset < (queue)->head; \
+ __u_vector_offset += (queue)->element_size)
+
+
+#endif
+
diff --git a/lib/mesa/src/util/vk_alloc.h b/lib/mesa/src/util/vk_alloc.h
new file mode 100644
index 000000000..a8e21cade
--- /dev/null
+++ b/lib/mesa/src/util/vk_alloc.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright © 2015 Intel Corporation
+ *
+ * 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.
+ */
+#ifndef VK_ALLOC_H
+#define VK_ALLOC_H
+
+/* common allocation inlines for vulkan drivers */
+
+#include <vulkan/vulkan.h>
+
+static inline void *
+vk_alloc(const VkAllocationCallbacks *alloc,
+ size_t size, size_t align,
+ VkSystemAllocationScope scope)
+{
+ return alloc->pfnAllocation(alloc->pUserData, size, align, scope);
+}
+
+static inline void *
+vk_realloc(const VkAllocationCallbacks *alloc,
+ void *ptr, size_t size, size_t align,
+ VkSystemAllocationScope scope)
+{
+ return alloc->pfnReallocation(alloc->pUserData, ptr, size, align, scope);
+}
+
+static inline void
+vk_free(const VkAllocationCallbacks *alloc, void *data)
+{
+ alloc->pfnFree(alloc->pUserData, data);
+}
+
+static inline void *
+vk_alloc2(const VkAllocationCallbacks *parent_alloc,
+ const VkAllocationCallbacks *alloc,
+ size_t size, size_t align,
+ VkSystemAllocationScope scope)
+{
+ if (alloc)
+ return vk_alloc(alloc, size, align, scope);
+ else
+ return vk_alloc(parent_alloc, size, align, scope);
+}
+
+static inline void
+vk_free2(const VkAllocationCallbacks *parent_alloc,
+ const VkAllocationCallbacks *alloc,
+ void *data)
+{
+ if (alloc)
+ vk_free(alloc, data);
+ else
+ vk_free(parent_alloc, data);
+}
+
+#endif