summaryrefslogtreecommitdiff
path: root/src/gallium/include/pipe
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/include/pipe')
-rw-r--r--src/gallium/include/pipe/internal/p_winsys_screen.h8
-rw-r--r--src/gallium/include/pipe/p_atomic.h382
-rw-r--r--src/gallium/include/pipe/p_config.h8
-rw-r--r--src/gallium/include/pipe/p_context.h1
-rw-r--r--src/gallium/include/pipe/p_debug.h361
-rw-r--r--src/gallium/include/pipe/p_defines.h12
-rw-r--r--src/gallium/include/pipe/p_format.h3
-rw-r--r--src/gallium/include/pipe/p_inlines.h175
-rw-r--r--src/gallium/include/pipe/p_refcnt.h88
-rw-r--r--src/gallium/include/pipe/p_screen.h60
-rw-r--r--src/gallium/include/pipe/p_shader_tokens.h6
-rw-r--r--src/gallium/include/pipe/p_state.h85
-rw-r--r--src/gallium/include/pipe/p_thread.h32
13 files changed, 699 insertions, 522 deletions
diff --git a/src/gallium/include/pipe/internal/p_winsys_screen.h b/src/gallium/include/pipe/internal/p_winsys_screen.h
index ee835578b2..f4a29e63c7 100644
--- a/src/gallium/include/pipe/internal/p_winsys_screen.h
+++ b/src/gallium/include/pipe/internal/p_winsys_screen.h
@@ -68,6 +68,11 @@ struct pipe_winsys
const char *(*get_name)( struct pipe_winsys *ws );
/**
+ * Do any special operations to ensure buffer size is correct
+ */
+ void (*update_buffer)( struct pipe_winsys *ws,
+ void *context_private );
+ /**
* Do any special operations to ensure frontbuffer contents are
* displayed, eg copy fake frontbuffer.
*/
@@ -149,8 +154,7 @@ struct pipe_winsys
void (*buffer_unmap)( struct pipe_winsys *ws,
struct pipe_buffer *buf );
- void (*buffer_destroy)( struct pipe_winsys *ws,
- struct pipe_buffer *buf );
+ void (*buffer_destroy)( struct pipe_buffer *buf );
/** Set ptr = fence, with reference counting */
diff --git a/src/gallium/include/pipe/p_atomic.h b/src/gallium/include/pipe/p_atomic.h
new file mode 100644
index 0000000000..f2fe083efa
--- /dev/null
+++ b/src/gallium/include/pipe/p_atomic.h
@@ -0,0 +1,382 @@
+/**
+ * Many similar implementations exist. See for example libwsbm
+ * or the linux kernel include/atomic.h
+ *
+ * No copyright claimed on this file.
+ *
+ */
+
+#ifndef P_ATOMIC_H
+#define P_ATOMIC_H
+
+#include "p_compiler.h"
+#include "p_defines.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Favor OS-provided implementations.
+ */
+#define PIPE_ATOMIC_OS_UNLOCKED \
+ (defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) || \
+ defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT))
+
+#define PIPE_ATOMIC_OS_MS_INTERLOCK \
+ (!defined(PIPE_CC_GCC) && \
+ !PIPE_ATOMIC_OS_UNLOCKED && \
+ defined(PIPE_SUBSYSTEM_WINDOWS_USER))
+
+#define PIPE_ATOMIC_OS_PROVIDED \
+ (PIPE_ATOMIC_OS_UNLOCKED || \
+ PIPE_ATOMIC_OS_MS_INTERLOCK)
+
+/* Where no OS-provided implementation is available, fall back to
+ * either locally coded assembly or ultimately a mutex-based
+ * implementation:
+ */
+#define PIPE_ATOMIC_ASM_GCC_X86 \
+ (!PIPE_ATOMIC_OS_PROVIDED && \
+ defined(PIPE_CC_GCC) && \
+ defined(PIPE_ARCH_X86))
+
+/* KW: this was originally used when x86 asm wasn't available.
+ * Maintain that logic here.
+ */
+#define PIPE_ATOMIC_GCC_INTRINISIC \
+ (!PIPE_ATOMIC_OS_PROVIDED && \
+ !PIPE_ATOMIC_ASM_GCC_X86 && \
+ defined(PIPE_CC_GCC))
+
+#define PIPE_ATOMIC_ASM_MSVC_X86 \
+ (!PIPE_ATOMIC_OS_PROVIDED && \
+ defined(PIPE_CC_MSVC) && \
+ defined(PIPE_ARCH_X86))
+
+#define PIPE_ATOMIC_ASM \
+ (PIPE_ATOMIC_ASM_GCC_X86 || \
+ PIPE_ATOMIC_ASM_GCC_INTRINSIC || \
+ PIPE_ATOMIC_ASM_MSVC_X86)
+
+
+/* Where no OS-provided or locally-coded assembly implemenation is
+ * available, use pipe_mutex:
+ */
+#define PIPE_ATOMIC_MUTEX \
+ (!PIPE_ATOMIC_OS_PROVIDED && \
+ !PIPE_ATOMIC_ASM)
+
+
+
+#if (PIPE_ATOMIC_ASM_GCC_X86)
+
+#define PIPE_ATOMIC "GCC x86 assembly"
+
+struct pipe_atomic {
+ int32_t count;
+};
+
+#define p_atomic_set(_v, _i) ((_v)->count = (_i))
+#define p_atomic_read(_v) ((_v)->count)
+
+
+static INLINE boolean
+p_atomic_dec_zero(struct pipe_atomic *v)
+{
+ unsigned char c;
+
+ __asm__ __volatile__("lock; decl %0; sete %1":"+m"(v->count), "=qm"(c)
+ ::"memory");
+
+ return c != 0;
+}
+
+static INLINE void
+p_atomic_inc(struct pipe_atomic *v)
+{
+ __asm__ __volatile__("lock; incl %0":"+m"(v->count));
+}
+
+static INLINE void
+p_atomic_dec(struct pipe_atomic *v)
+{
+ __asm__ __volatile__("lock; decl %0":"+m"(v->count));
+}
+
+static INLINE int32_t
+p_atomic_cmpxchg(struct pipe_atomic *v, int32_t old, int32_t _new)
+{
+ return __sync_val_compare_and_swap(&v->count, old, _new);
+}
+#endif
+
+
+
+/* Implementation using GCC-provided synchronization intrinsics
+ */
+#if (PIPE_ATOMIC_ASM_GCC_INTRINSIC)
+
+#define PIPE_ATOMIC "GCC Sync Intrinsics"
+
+struct pipe_atomic {
+ int32_t count;
+};
+
+#define p_atomic_set(_v, _i) ((_v)->count = (_i))
+#define p_atomic_read(_v) ((_v)->count)
+
+
+static INLINE boolean
+p_atomic_dec_zero(struct pipe_atomic *v)
+{
+ return (__sync_sub_and_fetch(&v->count, 1) == 0);
+}
+
+static INLINE void
+p_atomic_inc(struct pipe_atomic *v)
+{
+ (void) __sync_add_and_fetch(&v->count, 1);
+}
+
+static INLINE void
+p_atomic_dec(struct pipe_atomic *v)
+{
+ (void) __sync_sub_and_fetch(&v->count, 1);
+}
+
+static INLINE int32_t
+p_atomic_cmpxchg(struct pipe_atomic *v, int32_t old, int32_t _new)
+{
+ return __sync_val_compare_and_swap(&v->count, old, _new);
+}
+#endif
+
+
+
+/* Unlocked version for single threaded environments, such as some
+ * windows kernel modules.
+ */
+#if (PIPE_ATOMIC_OS_UNLOCKED)
+
+#define PIPE_ATOMIC "Unlocked"
+
+struct pipe_atomic
+{
+ int32_t count;
+};
+
+#define p_atomic_set(_v, _i) ((_v)->count = (_i))
+#define p_atomic_read(_v) ((_v)->count)
+#define p_atomic_dec_zero(_v) ((boolean) --(_v)->count)
+#define p_atomic_inc(_v) ((void) (_v)->count++)
+#define p_atomic_dec(_v) ((void) (_v)->count--)
+#define p_atomic_cmpxchg(_v, old, _new) ((_v)->count == old ? (_v)->count = (_new) : (_v)->count)
+
+#endif
+
+
+/* Locally coded assembly for MSVC on x86:
+ */
+#if (PIPE_ATOMIC_ASM_MSVC_X86)
+
+#define PIPE_ATOMIC "MSVC x86 assembly"
+
+struct pipe_atomic
+{
+ int32_t count;
+};
+
+#define p_atomic_set(_v, _i) ((_v)->count = (_i))
+#define p_atomic_read(_v) ((_v)->count)
+
+static INLINE boolean
+p_atomic_dec_zero(struct pipe_atomic *v)
+{
+ int32_t *pcount = &v->count;
+ unsigned char c;
+
+ __asm {
+ mov eax, [pcount]
+ lock dec dword ptr [eax]
+ sete byte ptr [c]
+ }
+
+ return c != 0;
+}
+
+static INLINE void
+p_atomic_inc(struct pipe_atomic *v)
+{
+ int32_t *pcount = &v->count;
+
+ __asm {
+ mov eax, [pcount]
+ lock inc dword ptr [eax]
+ }
+}
+
+static INLINE void
+p_atomic_dec(struct pipe_atomic *v)
+{
+ int32_t *pcount = &v->count;
+
+ __asm {
+ mov eax, [pcount]
+ lock dec dword ptr [eax]
+ }
+}
+
+static INLINE int32_t
+p_atomic_cmpxchg(struct pipe_atomic *v, int32_t old, int32_t _new)
+{
+ int32_t *pcount = &v->count;
+ int32_t orig;
+
+ __asm {
+ mov ecx, [pcount]
+ mov eax, [old]
+ mov edx, [_new]
+ lock cmpxchg [ecx], edx
+ mov [orig], eax
+ }
+
+ return orig;
+}
+#endif
+
+
+#if (PIPE_ATOMIC_OS_MS_INTERLOCK)
+
+#define PIPE_ATOMIC "MS userspace interlocks"
+
+#include <windows.h>
+
+struct pipe_atomic
+{
+ long count;
+};
+
+#define p_atomic_set(_v, _i) ((_v)->count = (_i))
+#define p_atomic_read(_v) ((_v)->count)
+
+static INLINE boolean
+p_atomic_dec_zero(struct pipe_atomic *v)
+{
+ return InterlockedDecrement(&v->count);
+}
+
+static INLINE void
+p_atomic_inc(struct pipe_atomic *v)
+{
+ InterlockedIncrement(&v->count);
+}
+
+static INLINE void
+p_atomic_dec(struct pipe_atomic *v)
+{
+ InterlockedDecrement(&v->count);
+}
+
+static INLINE int32_t
+p_atomic_cmpxchg(struct pipe_atomic *v, int32_t old, int32_t _new)
+{
+ return InterlockedCompareExchange(&v->count, _new, old);
+}
+
+#endif
+
+
+
+#if (PIPE_ATOMIC_MUTEX)
+
+#define PIPE_ATOMIC "mutex-based fallback"
+
+#include "pipe/p_thread.h"
+
+/**
+ * This implementation should really not be used.
+ * Add an assembly port instead. It may abort and
+ * doesn't destroy used mutexes.
+ */
+
+struct pipe_atomic {
+ pipe_mutex mutex;
+ int32_t count;
+};
+
+static INLINE void
+p_atomic_set(struct pipe_atomic *v, int32_t i)
+{
+ pipe_mutex_init(v->mutex);
+ pipe_mutex_lock(v->mutex);
+ v->count = i;
+ pipe_mutex_unlock(v->mutex);
+}
+
+static INLINE int32_t
+p_atomic_read(struct pipe_atomic *v)
+{
+ int32_t ret;
+
+ pipe_mutex_lock(v->mutex);
+ ret = v->count;
+ pipe_mutex_unlock(v->mutex);
+ return ret;
+}
+
+static INLINE void
+p_atomic_inc(struct pipe_atomic *v)
+{
+ pipe_mutex_lock(v->mutex);
+ ++v->count;
+ pipe_mutex_unlock(v->mutex);
+}
+
+static INLINE void
+p_atomic_dec(struct pipe_atomic *v)
+{
+ pipe_mutex_lock(v->mutex);
+ --v->count;
+ pipe_mutex_unlock(v->mutex);
+}
+
+static INLINE boolean
+p_atomic_dec_zero(struct pipe_atomic *v)
+{
+ boolean ret;
+
+ pipe_mutex_lock(v->mutex);
+ ret = (--v->count == 0);
+ pipe_mutex_unlock(v->mutex);
+ return ret;
+}
+
+static INLINE int32_t
+p_atomic_cmpxchg(struct pipe_atomic *v, int32_t old, int32_t _new)
+{
+ int32_t ret;
+
+ pipe_mutex_lock(v->mutex);
+ ret = v->count;
+ if (ret == old)
+ v->count = _new;
+ pipe_mutex_unlock(v->mutex);
+
+ return ret;
+}
+
+#endif
+
+
+#ifndef PIPE_ATOMIC
+#error "No pipe_atomic implementation selected"
+#endif
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* P_ATOMIC_H */
diff --git a/src/gallium/include/pipe/p_config.h b/src/gallium/include/pipe/p_config.h
index 05cbd2fc4d..7f7657031d 100644
--- a/src/gallium/include/pipe/p_config.h
+++ b/src/gallium/include/pipe/p_config.h
@@ -111,6 +111,10 @@
#define PIPE_OS_LINUX
#endif
+#if defined(__FreeBSD__)
+#define PIPE_OS_BSD
+#endif
+
#if defined(_WIN32) || defined(WIN32)
#define PIPE_OS_WINDOWS
#endif
@@ -122,9 +126,9 @@
* NOTE: There is no way to auto-detect most of these.
*/
-#if defined(PIPE_OS_LINUX)
+#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD)
#define PIPE_SUBSYSTEM_DRI
-#endif /* PIPE_OS_LINUX */
+#endif /* PIPE_OS_LINUX || PIPE_OS_BSD */
#if defined(PIPE_OS_WINDOWS)
#if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h
index 9454cc87db..2452bf3522 100644
--- a/src/gallium/include/pipe/p_context.h
+++ b/src/gallium/include/pipe/p_context.h
@@ -193,7 +193,6 @@ struct pipe_context {
*/
/*@{*/
void (*surface_copy)(struct pipe_context *pipe,
- boolean do_flip,/**< flip surface contents vertically */
struct pipe_surface *dest,
unsigned destx, unsigned desty,
struct pipe_surface *src, /* don't make this const -
diff --git a/src/gallium/include/pipe/p_debug.h b/src/gallium/include/pipe/p_debug.h
deleted file mode 100644
index e9c95982dd..0000000000
--- a/src/gallium/include/pipe/p_debug.h
+++ /dev/null
@@ -1,361 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
- * 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 TUNGSTEN GRAPHICS 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.
- *
- **************************************************************************/
-
-/**
- * @file
- * Cross-platform debugging helpers.
- *
- * For now it just has assert and printf replacements, but it might be extended
- * with stack trace reports and more advanced logging in the near future.
- *
- * @author Jose Fonseca <jrfonseca@tungstengraphics.com>
- */
-
-#ifndef P_DEBUG_H_
-#define P_DEBUG_H_
-
-
-#include <stdarg.h>
-
-#include "p_compiler.h"
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-#if defined(DBG) || defined(DEBUG)
-#ifndef DEBUG
-#define DEBUG 1
-#endif
-#else
-#ifndef NDEBUG
-#define NDEBUG 1
-#endif
-#endif
-
-
-/* MSVC bebore VC7 does not have the __FUNCTION__ macro */
-#if defined(_MSC_VER) && _MSC_VER < 1300
-#define __FUNCTION__ "???"
-#endif
-
-
-void _debug_vprintf(const char *format, va_list ap);
-
-
-static INLINE void
-_debug_printf(const char *format, ...)
-{
- va_list ap;
- va_start(ap, format);
- _debug_vprintf(format, ap);
- va_end(ap);
-}
-
-
-/**
- * Print debug messages.
- *
- * The actual channel used to output debug message is platform specific. To
- * avoid misformating or truncation, follow these rules of thumb:
- * - output whole lines
- * - avoid outputing large strings (512 bytes is the current maximum length
- * that is guaranteed to be printed in all platforms)
- */
-static INLINE void
-debug_printf(const char *format, ...)
-{
-#ifdef DEBUG
- va_list ap;
- va_start(ap, format);
- _debug_vprintf(format, ap);
- va_end(ap);
-#else
- (void) format; /* silence warning */
-#endif
-}
-
-
-#ifdef DEBUG
-#define debug_vprintf(_format, _ap) _debug_vprintf(_format, _ap)
-#else
-#define debug_vprintf(_format, _ap) ((void)0)
-#endif
-
-
-#ifdef DEBUG
-/**
- * Dump a blob in hex to the same place that debug_printf sends its
- * messages.
- */
-void debug_print_blob( const char *name, const void *blob, unsigned size );
-
-/* Print a message along with a prettified format string
- */
-void debug_print_format(const char *msg, unsigned fmt );
-#else
-#define debug_print_blob(_name, _blob, _size) ((void)0)
-#define debug_print_format(_msg, _fmt) ((void)0)
-#endif
-
-
-void _debug_break(void);
-
-
-/**
- * Hard-coded breakpoint.
- */
-#ifdef DEBUG
-#if defined(PIPE_ARCH_X86) && defined(PIPE_CC_GCC)
-#define debug_break() __asm("int3")
-#elif defined(PIPE_ARCH_X86) && defined(PIPE_CC_MSVC)
-#define debug_break() do { _asm {int 3} } while(0)
-#else
-#define debug_break() _debug_break()
-#endif
-#else /* !DEBUG */
-#define debug_break() ((void)0)
-#endif /* !DEBUG */
-
-
-long
-debug_get_num_option(const char *name, long dfault);
-
-void _debug_assert_fail(const char *expr,
- const char *file,
- unsigned line,
- const char *function);
-
-
-/**
- * Assert macro
- *
- * Do not expect that the assert call terminates -- errors must be handled
- * regardless of assert behavior.
- */
-#ifdef DEBUG
-#define debug_assert(expr) ((expr) ? (void)0 : _debug_assert_fail(#expr, __FILE__, __LINE__, __FUNCTION__))
-#else
-#define debug_assert(expr) ((void)0)
-#endif
-
-
-/** Override standard assert macro */
-#ifdef assert
-#undef assert
-#endif
-#define assert(expr) debug_assert(expr)
-
-
-/**
- * Output the current function name.
- */
-#ifdef DEBUG
-#define debug_checkpoint() \
- _debug_printf("%s\n", __FUNCTION__)
-#else
-#define debug_checkpoint() \
- ((void)0)
-#endif
-
-
-/**
- * Output the full source code position.
- */
-#ifdef DEBUG
-#define debug_checkpoint_full() \
- _debug_printf("%s:%u:%s", __FILE__, __LINE__, __FUNCTION__)
-#else
-#define debug_checkpoint_full() \
- ((void)0)
-#endif
-
-
-/**
- * Output a warning message. Muted on release version.
- */
-#ifdef DEBUG
-#define debug_warning(__msg) \
- _debug_printf("%s:%u:%s: warning: %s\n", __FILE__, __LINE__, __FUNCTION__, __msg)
-#else
-#define debug_warning(__msg) \
- ((void)0)
-#endif
-
-
-/**
- * Output an error message. Not muted on release version.
- */
-#ifdef DEBUG
-#define debug_error(__msg) \
- _debug_printf("%s:%u:%s: error: %s\n", __FILE__, __LINE__, __FUNCTION__, __msg)
-#else
-#define debug_error(__msg) \
- _debug_printf("error: %s\n", __msg)
-#endif
-
-
-/**
- * Used by debug_dump_enum and debug_dump_flags to describe symbols.
- */
-struct debug_named_value
-{
- const char *name;
- unsigned long value;
-};
-
-
-/**
- * Some C pre-processor magic to simplify creating named values.
- *
- * Example:
- * @code
- * static const debug_named_value my_names[] = {
- * DEBUG_NAMED_VALUE(MY_ENUM_VALUE_X),
- * DEBUG_NAMED_VALUE(MY_ENUM_VALUE_Y),
- * DEBUG_NAMED_VALUE(MY_ENUM_VALUE_Z),
- * DEBUG_NAMED_VALUE_END
- * };
- *
- * ...
- * debug_printf("%s = %s\n",
- * name,
- * debug_dump_enum(my_names, my_value));
- * ...
- * @endcode
- */
-#define DEBUG_NAMED_VALUE(__symbol) {#__symbol, (unsigned long)__symbol}
-#define DEBUG_NAMED_VALUE_END {NULL, 0}
-
-
-/**
- * Convert a enum value to a string.
- */
-const char *
-debug_dump_enum(const struct debug_named_value *names,
- unsigned long value);
-
-const char *
-debug_dump_enum_noprefix(const struct debug_named_value *names,
- const char *prefix,
- unsigned long value);
-
-
-/**
- * Convert binary flags value to a string.
- */
-const char *
-debug_dump_flags(const struct debug_named_value *names,
- unsigned long value);
-
-
-/**
- * Get option.
- *
- * It is an alias for getenv on Linux.
- *
- * On Windows it reads C:\gallium.cfg, which is a text file with CR+LF line
- * endings with one option per line as
- *
- * NAME=value
- *
- * This file must be terminated with an extra empty line.
- */
-const char *
-debug_get_option(const char *name, const char *dfault);
-
-boolean
-debug_get_bool_option(const char *name, boolean dfault);
-
-long
-debug_get_num_option(const char *name, long dfault);
-
-unsigned long
-debug_get_flags_option(const char *name,
- const struct debug_named_value *flags,
- unsigned long dfault);
-
-
-void *
-debug_malloc(const char *file, unsigned line, const char *function,
- size_t size);
-
-void
-debug_free(const char *file, unsigned line, const char *function,
- void *ptr);
-
-void *
-debug_calloc(const char *file, unsigned line, const char *function,
- size_t count, size_t size );
-
-void *
-debug_realloc(const char *file, unsigned line, const char *function,
- void *old_ptr, size_t old_size, size_t new_size );
-
-unsigned long
-debug_memory_begin(void);
-
-void
-debug_memory_end(unsigned long beginning);
-
-
-#if defined(PROFILE) && defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
-
-void
-debug_profile_start(void);
-
-void
-debug_profile_stop(void);
-
-#endif
-
-
-#ifdef DEBUG
-struct pipe_surface;
-void debug_dump_image(const char *prefix,
- unsigned format, unsigned cpp,
- unsigned width, unsigned height,
- unsigned stride,
- const void *data);
-void debug_dump_surface(const char *prefix,
- struct pipe_surface *surface);
-void debug_dump_surface_bmp(const char *filename,
- struct pipe_surface *surface);
-#else
-#define debug_dump_image(prefix, format, cpp, width, height, stride, data) ((void)0)
-#define debug_dump_surface(prefix, surface) ((void)0)
-#define debug_dump_surface_bmp(filename, surface) ((void)0)
-#endif
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* P_DEBUG_H_ */
diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h
index 4f0b301f31..52d443970b 100644
--- a/src/gallium/include/pipe/p_defines.h
+++ b/src/gallium/include/pipe/p_defines.h
@@ -194,6 +194,16 @@ enum pipe_texture_target {
/**
+ * Transfer object usage flags
+ */
+enum pipe_transfer_usage {
+ PIPE_TRANSFER_READ,
+ PIPE_TRANSFER_WRITE,
+ PIPE_TRANSFER_READ_WRITE //< Read/modify/write
+};
+
+
+/**
* Buffer usage flags
*/
#define PIPE_BUFFER_USAGE_CPU_READ (1 << 0)
@@ -205,6 +215,7 @@ enum pipe_texture_target {
#define PIPE_BUFFER_USAGE_INDEX (1 << 6)
#define PIPE_BUFFER_USAGE_CONSTANT (1 << 7)
#define PIPE_BUFFER_USAGE_DISCARD (1 << 8)
+#define PIPE_BUFFER_USAGE_DONTBLOCK (1 << 9)
/** Pipe driver custom usage flags should be greater or equal to this value */
#define PIPE_BUFFER_USAGE_CUSTOM (1 << 16)
@@ -247,6 +258,7 @@ enum pipe_texture_target {
#define PIPE_PRIM_QUADS 7
#define PIPE_PRIM_QUAD_STRIP 8
#define PIPE_PRIM_POLYGON 9
+#define PIPE_PRIM_MAX 10
/**
diff --git a/src/gallium/include/pipe/p_format.h b/src/gallium/include/pipe/p_format.h
index b42f98ceba..3f65a60436 100644
--- a/src/gallium/include/pipe/p_format.h
+++ b/src/gallium/include/pipe/p_format.h
@@ -30,8 +30,9 @@
#define PIPE_FORMAT_H
#include "p_compiler.h"
-#include "p_debug.h"
+/* FIXME: remove these header dependencies */
+#include "util/u_debug.h"
#include "util/u_string.h"
#ifdef __cplusplus
diff --git a/src/gallium/include/pipe/p_inlines.h b/src/gallium/include/pipe/p_inlines.h
index 1219c817b4..1232c87968 100644
--- a/src/gallium/include/pipe/p_inlines.h
+++ b/src/gallium/include/pipe/p_inlines.h
@@ -38,95 +38,6 @@ extern "C" {
#endif
-/* XXX: these are a kludge. will fix when all surfaces are views into
- * textures, and free-floating winsys surfaces go away.
- */
-static INLINE void *
-pipe_surface_map( struct pipe_surface *surf, unsigned flags )
-{
- struct pipe_screen *screen;
- assert(surf->texture);
- screen = surf->texture->screen;
- return screen->surface_map( screen, surf, flags );
-}
-
-static INLINE void
-pipe_surface_unmap( struct pipe_surface *surf )
-{
- struct pipe_screen *screen;
- assert(surf->texture);
- screen = surf->texture->screen;
- screen->surface_unmap( screen, surf );
-}
-
-
-
-/**
- * Set 'ptr' to point to 'surf' and update reference counting.
- * The old thing pointed to, if any, will be unreferenced first.
- * 'surf' may be NULL.
- */
-static INLINE void
-pipe_surface_reference(struct pipe_surface **ptr, struct pipe_surface *surf)
-{
- /* bump the refcount first */
- if (surf) {
- assert(surf->refcount);
- surf->refcount++;
- }
-
- if (*ptr) {
- struct pipe_screen *screen;
- assert((*ptr)->refcount);
- assert((*ptr)->texture);
- screen = (*ptr)->texture->screen;
- screen->tex_surface_release( screen, ptr );
- assert(!*ptr);
- }
-
- *ptr = surf;
-}
-
-
-/**
- * \sa pipe_surface_reference
- */
-static INLINE void
-pipe_texture_reference(struct pipe_texture **ptr,
- struct pipe_texture *pt)
-{
- assert(ptr);
-
- if (pt) {
- assert(pt->refcount);
- pt->refcount++;
- }
-
- if (*ptr) {
- struct pipe_screen *screen = (*ptr)->screen;
- assert(screen);
- assert((*ptr)->refcount);
- screen->texture_release(screen, ptr);
-
- assert(!*ptr);
- }
-
- *ptr = pt;
-}
-
-
-static INLINE void
-pipe_texture_release(struct pipe_texture **ptr)
-{
- struct pipe_screen *screen;
- assert(ptr);
- screen = (*ptr)->screen;
- assert((*ptr)->refcount);
- screen->texture_release(screen, ptr);
- *ptr = NULL;
-}
-
-
/**
* Convenience wrappers for screen buffer functions.
*/
@@ -149,7 +60,13 @@ pipe_buffer_map(struct pipe_screen *screen,
struct pipe_buffer *buf,
unsigned usage)
{
- return screen->buffer_map(screen, buf, usage);
+ if(screen->buffer_map_range) {
+ unsigned offset = 0;
+ unsigned length = buf->size;
+ return screen->buffer_map_range(screen, buf, offset, length, usage);
+ }
+ else
+ return screen->buffer_map(screen, buf, usage);
}
static INLINE void
@@ -159,26 +76,74 @@ pipe_buffer_unmap(struct pipe_screen *screen,
screen->buffer_unmap(screen, buf);
}
-/* XXX: thread safety issues!
- */
+static INLINE void *
+pipe_buffer_map_range(struct pipe_screen *screen,
+ struct pipe_buffer *buf,
+ unsigned offset,
+ unsigned length,
+ unsigned usage)
+{
+ assert(offset < buf->size);
+ assert(offset + length <= buf->size);
+ assert(length);
+ if(screen->buffer_map_range)
+ return screen->buffer_map_range(screen, buf, offset, length, usage);
+ else
+ return screen->buffer_map(screen, buf, usage);
+}
+
static INLINE void
-pipe_buffer_reference(struct pipe_screen *screen,
- struct pipe_buffer **ptr,
- struct pipe_buffer *buf)
+pipe_buffer_flush_mapped_range(struct pipe_screen *screen,
+ struct pipe_buffer *buf,
+ unsigned offset,
+ unsigned length)
{
- if (buf) {
- assert(buf->refcount);
- buf->refcount++;
- }
+ assert(offset < buf->size);
+ assert(offset + length <= buf->size);
+ assert(length);
+ if(screen->buffer_flush_mapped_range)
+ screen->buffer_flush_mapped_range(screen, buf, offset, length);
+}
- if (*ptr) {
- assert((*ptr)->refcount);
- if(--(*ptr)->refcount == 0) {
- screen->buffer_destroy( screen, *ptr );
- }
+static INLINE void
+pipe_buffer_write(struct pipe_screen *screen,
+ struct pipe_buffer *buf,
+ unsigned offset, unsigned size,
+ const void *data)
+{
+ uint8_t *map;
+
+ assert(offset < buf->size);
+ assert(offset + size <= buf->size);
+ assert(size);
+
+ map = pipe_buffer_map_range(screen, buf, offset, size, PIPE_BUFFER_USAGE_CPU_WRITE);
+ assert(map);
+ if(map) {
+ memcpy(map + offset, data, size);
+ pipe_buffer_flush_mapped_range(screen, buf, offset, size);
+ pipe_buffer_unmap(screen, buf);
}
+}
- *ptr = buf;
+static INLINE void
+pipe_buffer_read(struct pipe_screen *screen,
+ struct pipe_buffer *buf,
+ unsigned offset, unsigned size,
+ void *data)
+{
+ uint8_t *map;
+
+ assert(offset < buf->size);
+ assert(offset + size <= buf->size);
+ assert(size);
+
+ map = pipe_buffer_map_range(screen, buf, offset, size, PIPE_BUFFER_USAGE_CPU_READ);
+ assert(map);
+ if(map) {
+ memcpy(data, map + offset, size);
+ pipe_buffer_unmap(screen, buf);
+ }
}
diff --git a/src/gallium/include/pipe/p_refcnt.h b/src/gallium/include/pipe/p_refcnt.h
new file mode 100644
index 0000000000..60844e40a5
--- /dev/null
+++ b/src/gallium/include/pipe/p_refcnt.h
@@ -0,0 +1,88 @@
+/**************************************************************************
+ *
+ * Copyright 2009 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 TUNGSTEN GRAPHICS 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 P_REFCNT_H
+#define P_REFCNT_H
+
+
+#include "p_defines.h"
+#include "p_atomic.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+struct pipe_reference
+{
+ struct pipe_atomic count;
+};
+
+
+static INLINE void
+pipe_reference_init(struct pipe_reference *reference, unsigned count)
+{
+ p_atomic_set(&reference->count, count);
+}
+
+
+/**
+ * Set 'ptr' to point to 'reference' and update reference counting.
+ * The old thing pointed to, if any, will be unreferenced first.
+ * 'reference' may be NULL.
+ *
+ * XXX: thread safety issues!
+ */
+static INLINE bool
+pipe_reference(struct pipe_reference **ptr, struct pipe_reference *reference)
+{
+ bool destroy = FALSE;
+
+ /* bump the reference.count first */
+ if (reference) {
+ assert(p_atomic_read(&reference->count) != 0);
+ p_atomic_inc(&reference->count);
+ }
+
+ if (*ptr) {
+ assert(p_atomic_read(&(*ptr)->count) != 0);
+ if (p_atomic_dec_zero(&(*ptr)->count)) {
+ destroy = TRUE;
+ }
+ }
+
+ *ptr = reference;
+
+ return destroy;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* P_REFCNT_H */
diff --git a/src/gallium/include/pipe/p_screen.h b/src/gallium/include/pipe/p_screen.h
index 17d1548253..ed3a026023 100644
--- a/src/gallium/include/pipe/p_screen.h
+++ b/src/gallium/include/pipe/p_screen.h
@@ -55,6 +55,7 @@ struct pipe_winsys;
struct pipe_buffer;
+
/**
* Gallium screen/adapter context. Basically everything
* hardware-specific that doesn't actually require a rendering
@@ -112,8 +113,7 @@ struct pipe_screen {
const unsigned *stride,
struct pipe_buffer *buffer);
- void (*texture_release)(struct pipe_screen *,
- struct pipe_texture **pt);
+ void (*texture_destroy)(struct pipe_texture *pt);
/** Get a surface which is a "view" into a texture */
struct pipe_surface *(*get_tex_surface)(struct pipe_screen *,
@@ -122,18 +122,25 @@ struct pipe_screen {
unsigned zslice,
unsigned usage );
- /* Surfaces allocated by the above must be released here:
- */
- void (*tex_surface_release)( struct pipe_screen *,
- struct pipe_surface ** );
+ void (*tex_surface_destroy)(struct pipe_surface *);
- void *(*surface_map)( struct pipe_screen *,
- struct pipe_surface *surface,
- unsigned flags );
+ /** Get a transfer object for transferring data to/from a texture */
+ struct pipe_transfer *(*get_tex_transfer)(struct pipe_screen *,
+ struct pipe_texture *texture,
+ unsigned face, unsigned level,
+ unsigned zslice,
+ enum pipe_transfer_usage usage,
+ unsigned x, unsigned y,
+ unsigned w, unsigned h);
+
+ void (*tex_transfer_destroy)(struct pipe_transfer *);
+
+ void *(*transfer_map)( struct pipe_screen *,
+ struct pipe_transfer *transfer );
- void (*surface_unmap)( struct pipe_screen *,
- struct pipe_surface *surface );
+ void (*transfer_unmap)( struct pipe_screen *,
+ struct pipe_transfer *transfer );
/**
@@ -195,12 +202,37 @@ struct pipe_screen {
void *(*buffer_map)( struct pipe_screen *screen,
struct pipe_buffer *buf,
unsigned usage );
+ /**
+ * Map a subrange of the buffer data store into the client's address space.
+ *
+ * The returned pointer is always relative to buffer start, regardless of
+ * the specified range. This is different from the ARB_map_buffer_range
+ * semantics because we don't forbid multiple mappings of the same buffer
+ * (yet).
+ */
+ void *(*buffer_map_range)( struct pipe_screen *screen,
+ struct pipe_buffer *buf,
+ unsigned offset,
+ unsigned length,
+ unsigned usage);
+
+ /**
+ * Notify a range that was actually written into.
+ *
+ * The range is relative to the buffer start, regardless of the range
+ * specified to buffer_map_range. This is different from the
+ * ARB_map_buffer_range semantics because we don't forbid multiple mappings
+ * of the same buffer (yet).
+ */
+ void (*buffer_flush_mapped_range)( struct pipe_screen *screen,
+ struct pipe_buffer *buf,
+ unsigned offset,
+ unsigned length);
void (*buffer_unmap)( struct pipe_screen *screen,
- struct pipe_buffer *buf );
+ struct pipe_buffer *buf );
- void (*buffer_destroy)( struct pipe_screen *screen,
- struct pipe_buffer *buf );
+ void (*buffer_destroy)( struct pipe_buffer *buf );
/**
diff --git a/src/gallium/include/pipe/p_shader_tokens.h b/src/gallium/include/pipe/p_shader_tokens.h
index 35df70e7b7..4dafdd6f0a 100644
--- a/src/gallium/include/pipe/p_shader_tokens.h
+++ b/src/gallium/include/pipe/p_shader_tokens.h
@@ -191,8 +191,8 @@ struct tgsi_immediate_float32
/*
* GL_EXT_vertex_shader
*/
-#define TGSI_OPCODE_INDEX 22
-#define TGSI_OPCODE_NEGATE 23
+#define TGSI_OPCODE_INDEX 22 /* considered for removal */
+#define TGSI_OPCODE_NEGATE 23 /* considered for removal */
#define TGSI_OPCODE_MADD TGSI_OPCODE_MAD
#define TGSI_OPCODE_FRAC 24
#define TGSI_OPCODE_SETGE TGSI_OPCODE_SGE
@@ -206,7 +206,7 @@ struct tgsi_immediate_float32
#define TGSI_OPCODE_RECIP TGSI_OPCODE_RCP
#define TGSI_OPCODE_RECIPSQRT TGSI_OPCODE_RSQ
#define TGSI_OPCODE_CROSSPRODUCT 31
-#define TGSI_OPCODE_MULTIPLYMATRIX 32
+#define TGSI_OPCODE_MULTIPLYMATRIX 32 /* considered for removal */
/*
* GL_NV_vertex_program1_1
diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h
index 9dc541630c..aad41fab11 100644
--- a/src/gallium/include/pipe/p_state.h
+++ b/src/gallium/include/pipe/p_state.h
@@ -43,6 +43,8 @@
#include "p_compiler.h"
#include "p_defines.h"
#include "p_format.h"
+#include "p_refcnt.h"
+#include "p_screen.h"
#ifdef __cplusplus
@@ -64,23 +66,20 @@ extern "C" {
/* fwd decls */
-struct pipe_screen;
struct pipe_surface;
-
/**
* The driver will certainly subclass this to include actual memory
* management information.
*/
struct pipe_buffer
{
+ struct pipe_reference reference;
+ struct pipe_screen *screen;
unsigned alignment;
unsigned usage;
unsigned size;
-
- /** Reference count */
- unsigned refcount;
};
@@ -109,9 +108,15 @@ struct pipe_rasterizer_state
unsigned line_stipple_factor:8; /**< [1..256] actually */
unsigned line_stipple_pattern:16;
unsigned line_last_pixel:1;
- unsigned bypass_clipping:1;
- unsigned bypass_vs:1; /**< Skip the vertex shader. Note that the shader is
- still needed though, to indicate inputs/outputs */
+
+ /**
+ * Vertex coordinates are pre-transformed to screen space. Skip
+ * the vertex shader, clipping and viewport processing. Note that
+ * a vertex shader is still needed though, to indicate the mapping
+ * from vertex elements to fragment shader input semantics.
+ */
+ unsigned bypass_vs_clip_and_viewport:1;
+
unsigned origin_lower_left:1; /**< Is (0,0) the lower-left corner? */
unsigned flatshade_first:1; /**< take color attribute from the first vertex of a primitive */
unsigned gl_rasterization_rules:1; /**< enable tweaks for GL rasterization? */
@@ -275,18 +280,14 @@ struct pipe_sampler_state
*/
struct pipe_surface
{
+ struct pipe_reference reference;
enum pipe_format format; /**< PIPE_FORMAT_x */
unsigned status; /**< PIPE_SURFACE_STATUS_x */
unsigned clear_value; /**< XXX may be temporary */
unsigned width; /**< logical width in pixels */
unsigned height; /**< logical height in pixels */
- struct pipe_format_block block;
- unsigned nblocksx; /**< allocated width in blocks */
- unsigned nblocksy; /**< allocated height in blocks */
- unsigned stride; /**< stride in bytes between rows of blocks */
unsigned layout; /**< PIPE_SURFACE_LAYOUT_x */
unsigned offset; /**< offset from start of buffer, in bytes */
- unsigned refcount;
unsigned usage; /**< PIPE_BUFFER_USAGE_* */
struct pipe_texture *texture; /**< texture into which this is a view */
@@ -297,10 +298,35 @@ struct pipe_surface
/**
+ * Transfer object. For data transfer to/from a texture.
+ */
+struct pipe_transfer
+{
+ enum pipe_format format; /**< PIPE_FORMAT_x */
+ unsigned x; /**< x offset from start of texture image */
+ unsigned y; /**< y offset from start of texture image */
+ unsigned width; /**< logical width in pixels */
+ unsigned height; /**< logical height in pixels */
+ struct pipe_format_block block;
+ unsigned nblocksx; /**< allocated width in blocks */
+ unsigned nblocksy; /**< allocated height in blocks */
+ unsigned stride; /**< stride in bytes between rows of blocks */
+ unsigned usage; /**< PIPE_TRANSFER_* */
+
+ struct pipe_texture *texture; /**< texture to transfer to/from */
+ unsigned face;
+ unsigned level;
+ unsigned zslice;
+};
+
+
+/**
* Texture object.
*/
struct pipe_texture
{
+ struct pipe_reference reference;
+
enum pipe_texture_target target; /**< PIPE_TEXTURE_x */
enum pipe_format format; /**< PIPE_FORMAT_x */
@@ -319,10 +345,6 @@ struct pipe_texture
unsigned tex_usage; /* PIPE_TEXTURE_USAGE_* */
- /* These are also refcounted:
- */
- unsigned refcount;
-
struct pipe_screen *screen; /**< screen that this texture belongs to */
};
@@ -359,6 +381,35 @@ struct pipe_vertex_element
};
+/* Reference counting helper functions */
+static INLINE void
+pipe_buffer_reference(struct pipe_buffer **ptr, struct pipe_buffer *buf)
+{
+ struct pipe_buffer *old_buf = *ptr;
+
+ if (pipe_reference((struct pipe_reference **)ptr, &buf->reference))
+ old_buf->screen->buffer_destroy(old_buf);
+}
+
+static INLINE void
+pipe_surface_reference(struct pipe_surface **ptr, struct pipe_surface *surf)
+{
+ struct pipe_surface *old_surf = *ptr;
+
+ if (pipe_reference((struct pipe_reference **)ptr, &surf->reference))
+ old_surf->texture->screen->tex_surface_destroy(old_surf);
+}
+
+static INLINE void
+pipe_texture_reference(struct pipe_texture **ptr, struct pipe_texture *tex)
+{
+ struct pipe_texture *old_tex = *ptr;
+
+ if (pipe_reference((struct pipe_reference **)ptr, &tex->reference))
+ old_tex->screen->texture_destroy(old_tex);
+}
+
+
#ifdef __cplusplus
}
#endif
diff --git a/src/gallium/include/pipe/p_thread.h b/src/gallium/include/pipe/p_thread.h
index 8af3cd958b..a9cd77541d 100644
--- a/src/gallium/include/pipe/p_thread.h
+++ b/src/gallium/include/pipe/p_thread.h
@@ -38,7 +38,7 @@
#include "pipe/p_compiler.h"
-#if defined(PIPE_OS_LINUX)
+#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD)
#include <pthread.h> /* POSIX threads headers */
#include <stdio.h> /* for perror() */
@@ -73,7 +73,7 @@ typedef pthread_cond_t pipe_condvar;
static pipe_mutex mutex = PTHREAD_MUTEX_INITIALIZER
#define pipe_mutex_init(mutex) \
- pthread_mutex_init(&(mutex), NULL)
+ (void) pthread_mutex_init(&(mutex), NULL)
#define pipe_mutex_destroy(mutex) \
pthread_mutex_destroy(&(mutex))
@@ -134,20 +134,20 @@ static INLINE int pipe_thread_destroy( pipe_thread thread )
typedef CRITICAL_SECTION pipe_mutex;
-#define pipe_static_mutex(name) \
- /*static*/ pipe_mutex name = {0,0,0,0,0,0}
+#define pipe_static_mutex(mutex) \
+ /*static*/ pipe_mutex mutex = {0,0,0,0,0,0}
-#define pipe_mutex_init(name) \
- InitializeCriticalSection(&name)
+#define pipe_mutex_init(mutex) \
+ InitializeCriticalSection(&mutex)
-#define pipe_mutex_destroy(name) \
- DeleteCriticalSection(&name)
+#define pipe_mutex_destroy(mutex) \
+ DeleteCriticalSection(&mutex)
-#define pipe_mutex_lock(name) \
- EnterCriticalSection(&name)
+#define pipe_mutex_lock(mutex) \
+ EnterCriticalSection(&mutex)
-#define pipe_mutex_unlock(name) \
- LeaveCriticalSection(&name)
+#define pipe_mutex_unlock(mutex) \
+ LeaveCriticalSection(&mutex)
/* XXX: dummy definitions, make it compile */
@@ -210,7 +210,7 @@ typedef unsigned pipe_condvar;
*/
typedef struct {
-#if defined(PIPE_OS_LINUX)
+#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD)
pthread_key_t key;
#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
DWORD key;
@@ -225,7 +225,7 @@ typedef struct {
static INLINE void
pipe_tsd_init(pipe_tsd *tsd)
{
-#if defined(PIPE_OS_LINUX)
+#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD)
if (pthread_key_create(&tsd->key, NULL/*free*/) != 0) {
perror("pthread_key_create(): failed to allocate key for thread specific data");
exit(-1);
@@ -242,7 +242,7 @@ pipe_tsd_get(pipe_tsd *tsd)
if (tsd->initMagic != (int) PIPE_TSD_INIT_MAGIC) {
pipe_tsd_init(tsd);
}
-#if defined(PIPE_OS_LINUX)
+#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD)
return pthread_getspecific(tsd->key);
#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
assert(0);
@@ -259,7 +259,7 @@ pipe_tsd_set(pipe_tsd *tsd, void *value)
if (tsd->initMagic != (int) PIPE_TSD_INIT_MAGIC) {
pipe_tsd_init(tsd);
}
-#if defined(PIPE_OS_LINUX)
+#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD)
if (pthread_setspecific(tsd->key, value) != 0) {
perror("pthread_set_specific() failed");
exit(-1);