commit
a3a2c64cd6
@ -0,0 +1,28 @@ |
||||
# Copyright © 2013 Red Hat
|
||||
#
|
||||
# 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.
|
||||
|
||||
SUBDIRS = src
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = virglrenderer.pc
|
||||
|
||||
EXTRA_DIST = \
|
||||
virglrenderer.pc.in
|
@ -0,0 +1,14 @@ |
||||
#! /bin/sh |
||||
|
||||
srcdir=`dirname "$0"` |
||||
test -z "$srcdir" && srcdir=. |
||||
|
||||
ORIGDIR=`pwd` |
||||
cd "$srcdir" |
||||
|
||||
autoreconf -v --install || exit 1 |
||||
cd $ORIGDIR || exit $? |
||||
|
||||
if test -z "$NOCONFIGURE"; then |
||||
"$srcdir"/configure "$@" |
||||
fi |
@ -0,0 +1,48 @@ |
||||
dnl Process this file with autoconf to create configure. |
||||
|
||||
AC_PREREQ([2.60]) |
||||
|
||||
AC_INIT([virglrenderer], [0.0.1], |
||||
[]) |
||||
AC_CONFIG_SRCDIR([Makefile.am]) |
||||
AC_CONFIG_HEADERS([config.h]) |
||||
AM_INIT_AUTOMAKE([foreign dist-bzip2]) |
||||
|
||||
# Support silent build rules, requires at least automake-1.11. Disable |
||||
# by either passing --disable-silent-rules to configure or passing V=1 |
||||
# to make |
||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])], |
||||
[AC_SUBST([AM_DEFAULT_VERBOSITY], [1])]) |
||||
|
||||
m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) |
||||
|
||||
AC_DISABLE_STATIC |
||||
AC_PROG_LIBTOOL |
||||
AC_SYS_LARGEFILE |
||||
|
||||
XORG_MACROS_VERSION(1.8) |
||||
XORG_DEFAULT_OPTIONS |
||||
|
||||
LIBDRM_REQUIRED=2.4.50 |
||||
|
||||
dnl Add flags for gcc |
||||
if test "x$GCC" = xyes; then |
||||
CFLAGS="$CFLAGS -Wall -std=c99" |
||||
fi |
||||
|
||||
DEFINES="-D_GNU_SOURCE" |
||||
AC_SUBST([DEFINES]) |
||||
PKG_CHECK_MODULES([LIBDRM], [libdrm >= $LIBDRM_REQUIRED], |
||||
[have_libdrm=yes], [have_libdrm=no]) |
||||
|
||||
PKG_CHECK_MODULES([EPOXY], [epoxy], |
||||
[have_epoxy=yes], [have_epoxy=no]) |
||||
|
||||
AC_CONFIG_FILES([ |
||||
virglrenderer.pc |
||||
Makefile |
||||
src/Makefile |
||||
src/gallium/auxiliary/Makefile |
||||
]) |
||||
AC_OUTPUT |
||||
|
@ -0,0 +1,50 @@ |
||||
SUBDIRS := gallium/auxiliary
|
||||
AM_LDFLAGS = gallium/auxiliary/libgallium.la $(EPOXY_LIBS) $(GL_LIBS) -lgbm -lm -ldl -I./gallium/include
|
||||
|
||||
AM_CFLAGS = \
|
||||
-I$(top_srcdir)/src/gallium/drivers/virgl \
|
||||
-I$(top_srcdir)/src/gallium/include \
|
||||
-I$(top_srcdir)/src/gallium/auxiliary \
|
||||
-I$(top_srcdir)/src/gallium/drivers \
|
||||
-I$(top_srcdir)/include \
|
||||
$(DEFINES) \
|
||||
$(PIC_FLAGS) \
|
||||
$(LIBDRM_CFLAGS) \
|
||||
$(EPOXY_CFLAGS) \
|
||||
$(VISIBILITY_CFLAGS)
|
||||
|
||||
#graw_renderer_SOURCES = \
|
||||
# graw_pipe_renderer.c \
|
||||
# graw_renderer_glx.c
|
||||
|
||||
#graw_shm_renderer_SOURCES = \
|
||||
# graw_shm_renderer.c \
|
||||
# graw_renderer_glx.c \
|
||||
# send_scm.c
|
||||
|
||||
#graw_renderer_LDADD = libgrend.la -lX11
|
||||
#graw_shm_renderer_LDADD = libgrend.la -lrt -lX11
|
||||
|
||||
libgrend_la_SOURCES = \
|
||||
graw_renderer.c \
|
||||
graw_shader.c \
|
||||
vrend_object.c \
|
||||
graw_decode.c \
|
||||
graw_cursor.c \
|
||||
graw_formats.c \
|
||||
iov.c \
|
||||
graw_renderer_helper.c \
|
||||
virgl_egl_context.c
|
||||
|
||||
lib_LTLIBRARIES = libvirglrenderer.la
|
||||
noinst_LTLIBRARIES = libgrend.la
|
||||
|
||||
GM_LDFLAGS = -Wl,-Bsymbolic -version-number 0:1 -no-undefined
|
||||
|
||||
libvirglrenderer_la_SOURCES = graw_virtio_lib_renderer.c
|
||||
libvirglrenderer_ladir = $(libdir)
|
||||
libvirglrenderer_la_LIBADD = libgrend.la
|
||||
libvirglrenderer_la_LDFLAGS = $(GM_LDFLAGS) $(EPOXY_LDFLAGS)
|
||||
|
||||
libvirglrendererincludedir = ${includedir}
|
||||
libvirglrendererinclude_HEADERS = virglrenderer.h virgl_helper.h
|
@ -0,0 +1,18 @@ |
||||
AUTOMAKE_OPTIONS = subdir-objects
|
||||
|
||||
include Makefile.sources |
||||
include $(top_srcdir)/src/gallium/Automake.inc |
||||
|
||||
noinst_LTLIBRARIES = libgallium.la
|
||||
|
||||
AM_CFLAGS = \
|
||||
-I$(top_srcdir)/src/gallium/auxiliary/util \
|
||||
$(GALLIUM_CFLAGS) \
|
||||
$(VISIBILITY_CFLAGS)
|
||||
|
||||
AM_CXXFLAGS = $(VISIBILITY_CXXFLAGS)
|
||||
|
||||
libgallium_la_SOURCES = \
|
||||
$(C_SOURCES) \
|
||||
$(GENERATED_SOURCES)
|
||||
|
@ -0,0 +1,20 @@ |
||||
C_SOURCES := \
|
||||
os/os_misc.c \
|
||||
os/os_process.c \
|
||||
os/os_time.c \
|
||||
tgsi/tgsi_build.c \
|
||||
tgsi/tgsi_dump.c \
|
||||
tgsi/tgsi_exec.c \
|
||||
tgsi/tgsi_info.c \
|
||||
tgsi/tgsi_iterate.c \
|
||||
tgsi/tgsi_parse.c \
|
||||
tgsi/tgsi_scan.c \
|
||||
tgsi/tgsi_strings.c \
|
||||
tgsi/tgsi_text.c \
|
||||
tgsi/tgsi_transform.c \
|
||||
tgsi/tgsi_ureg.c \
|
||||
tgsi/tgsi_util.c \
|
||||
util/u_format_srgb.c \
|
||||
util/u_format_table.c
|
||||
|
||||
|
@ -0,0 +1,80 @@ |
||||
/**************************************************************************
|
||||
* |
||||
* Copyright 2010 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. |
||||
* |
||||
**************************************************************************/ |
||||
|
||||
|
||||
/*
|
||||
* OS memory management abstractions |
||||
*/ |
||||
|
||||
|
||||
#ifndef _OS_MEMORY_H_ |
||||
#define _OS_MEMORY_H_ |
||||
|
||||
|
||||
#include "pipe/p_config.h" |
||||
#include "pipe/p_compiler.h" |
||||
|
||||
|
||||
#if defined(PIPE_SUBSYSTEM_EMBEDDED) |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
void * |
||||
os_malloc(size_t size); |
||||
|
||||
void * |
||||
os_calloc(size_t count, size_t size); |
||||
|
||||
void |
||||
os_free(void *ptr); |
||||
|
||||
void * |
||||
os_realloc(void *ptr, size_t old_size, size_t new_size); |
||||
|
||||
void * |
||||
os_malloc_aligned(size_t size, size_t alignment); |
||||
|
||||
void |
||||
os_free_aligned(void *ptr); |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#elif defined(PIPE_OS_WINDOWS) && defined(DEBUG) && !defined(DEBUG_MEMORY_IMPLEMENTATION) |
||||
|
||||
# include "os_memory_debug.h" |
||||
|
||||
#else |
||||
|
||||
# include "os_memory_stdc.h" |
||||
|
||||
#endif |
||||
|
||||
#endif /* _OS_MEMORY_H_ */ |
@ -0,0 +1,72 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008-2010 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. |
||||
*
|
||||
**************************************************************************/ |
||||
|
||||
|
||||
/*
|
||||
* Memory alignment wrappers. |
||||
*/ |
||||
|
||||
|
||||
#ifndef _OS_MEMORY_H_ |
||||
#error "Must not be included directly. Include os_memory.h instead" |
||||
#endif |
||||
|
||||
|
||||
#include "pipe/p_compiler.h" |
||||
|
||||
|
||||
/**
|
||||
* Return memory on given byte alignment |
||||
*/ |
||||
static INLINE void * |
||||
os_malloc_aligned(size_t size, size_t alignment) |
||||
{ |
||||
char *ptr, *buf; |
||||
|
||||
ptr = (char *) os_malloc(size + alignment + sizeof(void *)); |
||||
if (!ptr) |
||||
return NULL; |
||||
|
||||
buf = (char *)(((uintptr_t)ptr + sizeof(void *) + alignment - 1) & ~((uintptr_t)(alignment - 1))); |
||||
*(char **)(buf - sizeof(void *)) = ptr; |
||||
|
||||
return buf; |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Free memory returned by align_malloc(). |
||||
*/ |
||||
static INLINE void |
||||
os_free_aligned(void *ptr) |
||||
{ |
||||
if (ptr) { |
||||
void **cubbyHole = (void **) ((char *) ptr - sizeof(void *)); |
||||
void *realAddr = *cubbyHole; |
||||
os_free(realAddr); |
||||
} |
||||
} |
@ -0,0 +1,92 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008-2010 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. |
||||
*
|
||||
**************************************************************************/ |
||||
|
||||
|
||||
/*
|
||||
* Debugging wrappers for OS memory management abstractions. |
||||
*/ |
||||
|
||||
|
||||
#ifndef _OS_MEMORY_H_ |
||||
#error "Must not be included directly. Include os_memory.h instead" |
||||
#endif |
||||
|
||||
|
||||
#include "pipe/p_compiler.h" |
||||
|
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
|
||||
void * |
||||
debug_malloc(const char *file, unsigned line, const char *function, |
||||
size_t size); |
||||
|
||||
void * |
||||
debug_calloc(const char *file, unsigned line, const char *function, |
||||
size_t count, size_t size ); |
||||
|
||||
void |
||||
debug_free(const char *file, unsigned line, const char *function, |
||||
void *ptr); |
||||
|
||||
void * |
||||
debug_realloc(const char *file, unsigned line, const char *function, |
||||
void *old_ptr, size_t old_size, size_t new_size ); |
||||
|
||||
void |
||||
debug_memory_tag(void *ptr, unsigned tag); |
||||
|
||||
void |
||||
debug_memory_check_block(void *ptr); |
||||
|
||||
void
|
||||
debug_memory_check(void); |
||||
|
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
|
||||
#ifndef DEBUG_MEMORY_IMPLEMENTATION |
||||
|
||||
#define os_malloc( _size ) \ |
||||
debug_malloc( __FILE__, __LINE__, __FUNCTION__, _size ) |
||||
#define os_calloc( _count, _size ) \ |
||||
debug_calloc(__FILE__, __LINE__, __FUNCTION__, _count, _size ) |
||||
#define os_free( _ptr ) \ |
||||
debug_free( __FILE__, __LINE__, __FUNCTION__, _ptr ) |
||||
#define os_realloc( _ptr, _old_size, _new_size ) \ |
||||
debug_realloc( __FILE__, __LINE__, __FUNCTION__, _ptr, _old_size, _new_size ) |
||||
|
||||
/* TODO: wrap os_malloc_aligned() and os_free_aligned() too */ |
||||
#include "os_memory_aligned.h" |
||||
|
||||
#endif /* !DEBUG_MEMORY_IMPLEMENTATION */ |
@ -0,0 +1,76 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008-2010 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. |
||||
*
|
||||
**************************************************************************/ |
||||
|
||||
|
||||
/*
|
||||
* OS memory management abstractions for the standard C library. |
||||
*/ |
||||
|
||||
|
||||
#ifndef _OS_MEMORY_H_ |
||||
#error "Must not be included directly. Include os_memory.h instead" |
||||
#endif |
||||
|
||||
#include <stdlib.h> |
||||
|
||||
#include "pipe/p_compiler.h" |
||||
|
||||
|
||||
#define os_malloc(_size) malloc(_size) |
||||
#define os_calloc(_count, _size ) calloc(_count, _size ) |
||||
#define os_free(_ptr) free(_ptr) |
||||
|
||||
#define os_realloc( _old_ptr, _old_size, _new_size) \ |
||||
realloc(_old_ptr, _new_size + 0*(_old_size)) |
||||
|
||||
|
||||
#if defined(HAVE_POSIX_MEMALIGN) |
||||
|
||||
static INLINE void * |
||||
os_malloc_aligned(size_t size, size_t alignment) |
||||
{ |
||||
void *ptr; |
||||
alignment = (alignment + sizeof(void*) - 1) & ~(sizeof(void*) - 1); |
||||
if(posix_memalign(&ptr, alignment, size) != 0) |
||||
return NULL; |
||||
return ptr; |
||||
} |
||||
|
||||
#define os_free_aligned(_ptr) free(_ptr) |
||||
|
||||
#elif defined(PIPE_OS_WINDOWS) |
||||
|
||||
#include <malloc.h> |
||||
|
||||
#define os_malloc_aligned(_size, _align) _aligned_malloc(_size, _align) |
||||
#define os_free_aligned(_ptr) _aligned_free(_ptr) |
||||
|
||||
#else |
||||
|
||||
#include "os_memory_aligned.h" |
||||
|
||||
#endif |
@ -0,0 +1,91 @@ |
||||
/**************************************************************************
|
||||
* |
||||
* Copyright 2008-2010 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 "os_misc.h" |
||||
|
||||
#include <stdarg.h> |
||||
|
||||
|
||||
#if defined(PIPE_SUBSYSTEM_WINDOWS_USER) |
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN |
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
#endif |
||||
#include <windows.h> |
||||
#include <stdio.h> |
||||
|
||||
#else |
||||
|
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
|
||||
#endif |
||||
|
||||
|
||||
void |
||||
os_log_message(const char *message) |
||||
{ |
||||
/* If the GALLIUM_LOG_FILE environment variable is set to a valid filename,
|
||||
* write all messages to that file. |
||||
*/ |
||||
static FILE *fout = NULL; |
||||
|
||||
if (!fout) { |
||||
/* one-time init */ |
||||
const char *filename = os_get_option("GALLIUM_LOG_FILE"); |
||||
if (filename) |
||||
fout = fopen(filename, "w"); |
||||
if (!fout) |
||||
fout = stderr; |
||||
} |
||||
|
||||
#if defined(PIPE_SUBSYSTEM_WINDOWS_USER) |
||||
OutputDebugStringA(message); |
||||
if(GetConsoleWindow() && !IsDebuggerPresent()) { |
||||
fflush(stdout); |
||||
fputs(message, fout); |
||||
fflush(fout); |
||||
} |
||||
else if (fout != stderr) { |
||||
fputs(message, fout); |
||||
fflush(fout); |
||||
} |
||||
#else /* !PIPE_SUBSYSTEM_WINDOWS */ |
||||
fflush(stdout); |
||||
fputs(message, fout); |
||||
fflush(fout); |
||||
#endif |
||||
} |
||||
|
||||
|
||||
const char * |
||||
os_get_option(const char *name) |
||||
{ |
||||
return getenv(name); |
||||
} |
||||
|
@ -0,0 +1,95 @@ |
||||
/**************************************************************************
|
||||
* |
||||
* Copyright 2010 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. |
||||
* |
||||
**************************************************************************/ |
||||
|
||||
|
||||
/*
|
||||
* Miscellaneous OS services. |
||||
*/ |
||||
|
||||
|
||||
#ifndef _OS_MISC_H_ |
||||
#define _OS_MISC_H_ |
||||
|
||||
|
||||
#include "pipe/p_compiler.h" |
||||
|
||||
|
||||
#if defined(PIPE_OS_UNIX) |
||||
# include <signal.h> /* for kill() */ |
||||
# include <unistd.h> /* getpid() */ |
||||
#endif |
||||
|
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
|
||||
/*
|
||||
* Trap into the debugger. |
||||
*/ |
||||
#if (defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)) && defined(PIPE_CC_GCC) |
||||
# define os_break() __asm("int3") |
||||
#elif defined(PIPE_CC_MSVC) |
||||
# define os_break() __debugbreak() |
||||
#elif defined(PIPE_OS_UNIX) |
||||
# define os_break() kill(getpid(), SIGTRAP) |
||||
#else |
||||
# define os_break() abort() |
||||
#endif |
||||
|
||||
|
||||
/*
|
||||
* Abort the program. |
||||
*/ |
||||
#if defined(DEBUG) |
||||
# define os_abort() os_break() |
||||
#else |
||||
# define os_abort() abort() |
||||
#endif |
||||
|
||||
|
||||
/*
|
||||
* Output a message. Message should preferably end in a newline. |
||||
*/ |
||||
void |
||||
os_log_message(const char *message); |
||||
|
||||
|
||||
/*
|
||||
* Get an option. Should return NULL if specified option is not set. |
||||
*/ |
||||
const char * |
||||
os_get_option(const char *name); |
||||
|
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
|
||||
#endif /* _OS_MISC_H_ */ |
@ -0,0 +1,87 @@ |
||||
/**************************************************************************
|
||||
* |
||||
* Copyright 2011 LunarG, 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. |
||||
* |
||||
**************************************************************************/ |
||||
|
||||
/**
|
||||
* @file |
||||
* OS independent memory mapping (with large file support). |
||||
* |
||||
* @author Chia-I Wu <olvaffe@gmail.com> |
||||
*/ |
||||
|
||||
#ifndef _OS_MMAN_H_ |
||||
#define _OS_MMAN_H_ |
||||
|
||||
|
||||
#include "pipe/p_config.h" |
||||
#include "pipe/p_compiler.h" |
||||
|
||||
#if defined(PIPE_OS_UNIX) |
||||
# ifndef _FILE_OFFSET_BITS |
||||
# error _FILE_OFFSET_BITS must be defined to 64 |
||||
# endif |
||||
# include <sys/mman.h> |
||||
#else |
||||
# error Unsupported OS |
||||
#endif |
||||
|
||||
#if defined(PIPE_OS_ANDROID) |
||||
# include <errno.h> /* for EINVAL */ |
||||
#endif |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
|
||||
#if defined(PIPE_OS_ANDROID) |
||||
|
||||
extern void *__mmap2(void *, size_t, int, int, int, size_t); |
||||
|
||||
static INLINE void *os_mmap(void *addr, size_t length, int prot, int flags, int fd, loff_t offset) |
||||
{ |
||||
/* offset must be aligned to 4096 (not necessarily the page size) */ |
||||
if (unlikely(offset & 4095)) { |
||||
errno = EINVAL; |
||||
return MAP_FAILED; |
||||
} |
||||
|
||||
return __mmap2(addr, length, prot, flags, fd, (size_t) (offset >> 12)); |
||||
} |
||||
|
||||
#else |
||||
/* assume large file support exists */ |
||||
# define os_mmap(addr, length, prot, flags, fd, offset) mmap(addr, length, prot, flags, fd, offset) |
||||
#endif |
||||
|
||||
#define os_munmap(addr, length) munmap(addr, length) |
||||
|
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* _OS_MMAN_H_ */ |
@ -0,0 +1,92 @@ |
||||
/**************************************************************************
|
||||
* |
||||
* Copyright 2013 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 THE AUTHORS 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 "pipe/p_config.h" |
||||
#include "os/os_process.h" |
||||
#include "util/u_memory.h" |
||||
|
||||
#if defined(PIPE_SUBSYSTEM_WINDOWS_USER) |
||||
# include <windows.h> |
||||
#elif defined(__GLIBC__) |
||||
# include <errno.h> |
||||
#elif defined(PIPE_OS_BSD) || defined(PIPE_OS_APPLE) |
||||
# include <stdlib.h> |
||||
#else |
||||
#warning unexpected platform in os_process.c |
||||
#endif |
||||
|
||||
|
||||
/**
|
||||
* Return the name of the current process. |
||||
* \param procname returns the process name |
||||
* \param size size of the procname buffer |
||||
* \return TRUE or FALSE for success, failure |
||||
*/ |
||||
boolean |
||||
os_get_process_name(char *procname, size_t size) |
||||
{ |
||||
const char *name; |
||||
#if defined(PIPE_SUBSYSTEM_WINDOWS_USER) |
||||
char szProcessPath[MAX_PATH]; |
||||
char *lpProcessName; |
||||
char *lpProcessExt; |
||||
|
||||
GetModuleFileNameA(NULL, szProcessPath, Elements(szProcessPath)); |
||||
|
||||
lpProcessName = strrchr(szProcessPath, '\\'); |
||||
lpProcessName = lpProcessName ? lpProcessName + 1 : szProcessPath; |
||||
|
||||
lpProcessExt = strrchr(lpProcessName, '.'); |
||||
if (lpProcessExt) { |
||||
*lpProcessExt = '\0'; |
||||
} |
||||
|
||||
name = lpProcessName; |
||||
|
||||
#elif defined(__GLIBC__) |
||||
name = program_invocation_short_name; |
||||
#elif defined(PIPE_OS_BSD) || defined(PIPE_OS_APPLE) |
||||
/* *BSD and OS X */ |
||||
name = getprogname(); |
||||
#else |
||||
#warning unexpected platform in os_process.c |
||||
return FALSE; |
||||
#endif |
||||
|
||||
assert(size > 0); |
||||
assert(procname); |
||||
|
||||
if (name && procname && size > 0) { |
||||
strncpy(procname, name, size); |
||||
procname[size - 1] = '\0'; |
||||
return TRUE; |
||||
} |
||||
else { |
||||
return FALSE; |
||||
} |
||||
} |
@ -0,0 +1,40 @@ |
||||
/**************************************************************************
|
||||
* |
||||
* Copyright 2013 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 THE AUTHORS 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 OS_PROCESS_H |
||||
#define OS_PROCESS_H |
||||
|
||||
|
||||
#include "pipe/p_compiler.h" |
||||
|
||||
|
||||
extern boolean |
||||
os_get_process_name(char *str, size_t size); |
||||
|
||||
|
||||
#endif /* OS_PROCESS_H */ |
@ -0,0 +1,300 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 1999-2006 Brian Paul |
||||
* 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, 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 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 |
||||
*
|
||||
* Thread, mutex, condition variable, barrier, semaphore and |
||||
* thread-specific data functions. |
||||
*/ |
||||
|
||||
|
||||
#ifndef OS_THREAD_H_ |
||||
#define OS_THREAD_H_ |
||||
|
||||
|
||||
#include "pipe/p_compiler.h" |
||||
#include "util/u_debug.h" /* for assert */ |
||||
|
||||
#include "c11/threads.h" |
||||
|
||||
#ifdef HAVE_PTHREAD |
||||
#include <signal.h> |
||||
#endif |
||||
|
||||
|
||||
/* pipe_thread
|
||||
*/ |
||||
typedef thrd_t pipe_thread; |
||||
|
||||
#define PIPE_THREAD_ROUTINE( name, param ) \ |
||||
int name( void *param ) |
||||
|
||||
static INLINE pipe_thread pipe_thread_create( PIPE_THREAD_ROUTINE((*routine), ), void *param ) |
||||
{ |
||||
pipe_thread thread; |
||||
#ifdef HAVE_PTHREAD |
||||
sigset_t saved_set, new_set; |
||||
int ret; |
||||
|
||||
sigfillset(&new_set); |
||||
pthread_sigmask(SIG_SETMASK, &new_set, &saved_set); |
||||
ret = thrd_create( &thread, routine, param ); |
||||
pthread_sigmask(SIG_SETMASK, &saved_set, NULL); |
||||
#else |
||||
int ret; |
||||
ret = thrd_create( &thread, routine, param ); |
||||
#endif |
||||
if (ret) |
||||
return 0; |
||||
|
||||
return thread; |
||||
} |
||||
|
||||
static INLINE int pipe_thread_wait( pipe_thread thread ) |
||||
{ |
||||
return thrd_join( thread, NULL ); |
||||
} |
||||
|
||||
static INLINE int pipe_thread_destroy( pipe_thread thread ) |
||||
{ |
||||
return thrd_detach( thread ); |
||||
} |
||||
|
||||
|
||||
/* pipe_mutex
|
||||
*/ |
||||
typedef mtx_t pipe_mutex; |
||||
|
||||
#define pipe_static_mutex(mutex) \ |
||||
static pipe_mutex mutex = _MTX_INITIALIZER_NP |
||||
|
||||
#define pipe_mutex_init(mutex) \ |
||||
(void) mtx_init(&(mutex), mtx_plain) |
||||
|
||||
#define pipe_mutex_destroy(mutex) \ |
||||
mtx_destroy(&(mutex)) |
||||
|
||||
#define pipe_mutex_lock(mutex) \ |
||||
(void) mtx_lock(&(mutex)) |
||||
|
||||
#define pipe_mutex_unlock(mutex) \ |
||||
(void) mtx_unlock(&(mutex)) |
||||
|
||||
|
||||
/* pipe_condvar
|
||||
*/ |
||||
typedef cnd_t pipe_condvar; |
||||
|
||||
#define pipe_condvar_init(cond) \ |
||||
cnd_init(&(cond)) |
||||
|
||||
#define pipe_condvar_destroy(cond) \ |
||||
cnd_destroy(&(cond)) |
||||
|
||||
#define pipe_condvar_wait(cond, mutex) \ |
||||
cnd_wait(&(cond), &(mutex)) |
||||
|
||||
#define pipe_condvar_signal(cond) \ |
||||
cnd_signal(&(cond)) |
||||
|
||||
#define pipe_condvar_broadcast(cond) \ |
||||
cnd_broadcast(&(cond)) |
||||
|
||||
|
||||
/*
|
||||
* pipe_barrier |
||||
*/ |
||||
|
||||
#if (defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_HURD)) && !defined(PIPE_OS_ANDROID) |
||||
|
||||
typedef pthread_barrier_t pipe_barrier; |
||||
|
||||
static INLINE void pipe_barrier_init(pipe_barrier *barrier, unsigned count) |
||||
{ |
||||
pthread_barrier_init(barrier, NULL, count); |
||||
} |
||||
|
||||
static INLINE void pipe_barrier_destroy(pipe_barrier *barrier) |
||||
{ |
||||
pthread_barrier_destroy(barrier); |
||||
} |
||||
|
||||
static INLINE void pipe_barrier_wait(pipe_barrier *barrier) |
||||
{ |
||||
pthread_barrier_wait(barrier); |
||||
} |
||||
|
||||
|
||||
#else /* If the OS doesn't have its own, implement barriers using a mutex and a condvar */ |
||||
|
||||
typedef struct { |
||||
unsigned count; |
||||
unsigned waiters; |
||||
uint64_t sequence; |
||||
pipe_mutex mutex; |
||||
pipe_condvar condvar; |
||||
} pipe_barrier; |
||||
|
||||
static INLINE void pipe_barrier_init(pipe_barrier *barrier, unsigned count) |
||||
{ |
||||
barrier->count = count; |
||||
barrier->waiters = 0; |
||||
barrier->sequence = 0; |
||||
pipe_mutex_init(barrier->mutex); |
||||
pipe_condvar_init(barrier->condvar); |
||||
} |
||||
|
||||
static INLINE void pipe_barrier_destroy(pipe_barrier *barrier) |
||||
{ |
||||
assert(barrier->waiters == 0); |
||||
pipe_mutex_destroy(barrier->mutex); |
||||
pipe_condvar_destroy(barrier->condvar); |
||||
} |
||||
|
||||
static INLINE void pipe_barrier_wait(pipe_barrier *barrier) |
||||
{ |
||||
pipe_mutex_lock(barrier->mutex); |
||||
|
||||
assert(barrier->waiters < barrier->count); |
||||
barrier->waiters++; |
||||
|
||||
if (barrier->waiters < barrier->count) { |
||||
uint64_t sequence = barrier->sequence; |
||||
|
||||
do { |
||||
pipe_condvar_wait(barrier->condvar, barrier->mutex); |
||||
} while (sequence == barrier->sequence); |
||||
} else { |
||||
barrier->waiters = 0; |
||||
barrier->sequence++; |
||||
pipe_condvar_broadcast(barrier->condvar); |
||||
} |
||||
|
||||
pipe_mutex_unlock(barrier->mutex); |
||||
} |
||||
|
||||
|
||||
#endif |
||||
|
||||
|
||||
/*
|
||||
* Semaphores |
||||
*/ |
||||
|
||||
typedef struct |
||||
{ |
||||
pipe_mutex mutex; |
||||
pipe_condvar cond; |
||||
int counter; |
||||
} pipe_semaphore; |
||||
|
||||
|
||||
static INLINE void |
||||
pipe_semaphore_init(pipe_semaphore *sema, int init_val) |
||||
{ |
||||
pipe_mutex_init(sema->mutex); |
||||
pipe_condvar_init(sema->cond); |
||||
sema->counter = init_val; |
||||
} |
||||
|
||||
static INLINE void |
||||
pipe_semaphore_destroy(pipe_semaphore *sema) |
||||
{ |
||||
pipe_mutex_destroy(sema->mutex); |
||||
pipe_condvar_destroy(sema->cond); |
||||
} |
||||
|
||||
/** Signal/increment semaphore counter */ |
||||
static INLINE void |
||||
pipe_semaphore_signal(pipe_semaphore *sema) |
||||
{ |
||||
pipe_mutex_lock(sema->mutex); |
||||
sema->counter++; |
||||
pipe_condvar_signal(sema->cond); |
||||
pipe_mutex_unlock(sema->mutex); |
||||
} |
||||
|
||||
/** Wait for semaphore counter to be greater than zero */ |
||||
static INLINE void |
||||
pipe_semaphore_wait(pipe_semaphore *sema) |
||||
{ |
||||
pipe_mutex_lock(sema->mutex); |
||||
while (sema->counter <= 0) { |
||||
pipe_condvar_wait(sema->cond, sema->mutex); |
||||
} |
||||
sema->counter--; |
||||
pipe_mutex_unlock(sema->mutex); |
||||
} |
||||
|
||||
|
||||
|
||||
/*
|
||||
* Thread-specific data. |
||||
*/ |
||||
|
||||
typedef struct { |
||||
tss_t key; |
||||
int initMagic; |
||||
} pipe_tsd; |
||||
|
||||
|
||||
#define PIPE_TSD_INIT_MAGIC 0xff8adc98 |
||||
|
||||
|
||||
static INLINE void |
||||
pipe_tsd_init(pipe_tsd *tsd) |
||||
{ |
||||
if (tss_create(&tsd->key, NULL/*free*/) != 0) { |
||||
exit(-1); |
||||
} |
||||
tsd->initMagic = PIPE_TSD_INIT_MAGIC; |
||||
} |
||||
|
||||
static INLINE void * |
||||
pipe_tsd_get(pipe_tsd *tsd) |
||||
{ |
||||
if (tsd->initMagic != (int) PIPE_TSD_INIT_MAGIC) { |
||||
pipe_tsd_init(tsd); |
||||
} |
||||
return tss_get(tsd->key); |
||||
} |
||||
|
||||
static INLINE void |
||||
pipe_tsd_set(pipe_tsd *tsd, void *value) |
||||
{ |
||||
if (tsd->initMagic != (int) PIPE_TSD_INIT_MAGIC) { |
||||
pipe_tsd_init(tsd); |
||||
} |
||||
if (tss_set(tsd->key, value) != 0) { |
||||
exit(-1); |
||||
} |
||||
} |
||||
|
||||
|
||||
|
||||
#endif /* OS_THREAD_H_ */ |
@ -0,0 +1,94 @@ |
||||
/**************************************************************************
|
||||
* |
||||
* Copyright 2008-2010 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. |
||||
* |
||||
**************************************************************************/ |
||||
|
||||
/**
|
||||
* @file |
||||
* OS independent time-manipulation functions. |
||||
*
|
||||
* @author Jose Fonseca <jfonseca@vmware.com> |
||||
*/ |
||||
|
||||
|
||||
#include "pipe/p_config.h" |
||||
|
||||
#if defined(PIPE_OS_UNIX) |
||||
# include <time.h> /* timeval */ |
||||
# include <sys/time.h> /* timeval */ |
||||
#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) |
||||
# include <windows.h> |
||||
#else |
||||
# error Unsupported OS |
||||
#endif |
||||
|
||||
#include "os_time.h" |
||||
|
||||
|
||||
int64_t |
||||
os_time_get_nano(void) |
||||
{ |
||||
#if defined(PIPE_OS_LINUX) |
||||
|
||||
struct timespec tv; |
||||
clock_gettime(CLOCK_MONOTONIC, &tv); |
||||
return tv.tv_nsec + tv.tv_sec*INT64_C(1000000000); |
||||
|
||||
#elif defined(PIPE_OS_UNIX) |
||||
|
||||
struct timeval tv; |
||||
gettimeofday(&tv, NULL); |
||||
return tv.tv_usec*INT64_C(1000) + tv.tv_sec*INT64_C(1000000000); |
||||
|
||||
#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) |
||||
|
||||
static LARGE_INTEGER frequency; |
||||
LARGE_INTEGER counter; |
||||
if(!frequency.QuadPart) |
||||
QueryPerformanceFrequency(&frequency); |
||||
QueryPerformanceCounter(&counter); |
||||
return counter.QuadPart*INT64_C(1000000000)/frequency.QuadPart; |
||||
|
||||
#else |
||||
|
||||
#error Unsupported OS |
||||
|
||||
#endif |
||||
} |
||||
|
||||
|
||||
#if defined(PIPE_SUBSYSTEM_WINDOWS_USER) |
||||
|
||||
void |
||||
os_time_sleep(int64_t usecs) |
||||
{ |
||||
DWORD dwMilliseconds = (DWORD) ((usecs + 999) / 1000); |
||||
/* Avoid Sleep(O) as that would cause to sleep for an undetermined duration */ |
||||
if (dwMilliseconds) { |
||||
Sleep(dwMilliseconds); |
||||
} |
||||
} |
||||
|
||||
#endif |
@ -0,0 +1,101 @@ |
||||
/**************************************************************************
|
||||
* |
||||
* Copyright 2008-2010 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. |
||||
* |
||||
**************************************************************************/ |
||||
|
||||
/**
|
||||
* @file |
||||
* OS independent time-manipulation functions. |
||||
*
|
||||
* @author Jose Fonseca <jfonseca@vmware.com> |
||||
*/ |
||||
|
||||
#ifndef _OS_TIME_H_ |
||||
#define _OS_TIME_H_ |
||||
|
||||
|
||||
#include "pipe/p_config.h" |
||||
|
||||
#if defined(PIPE_OS_UNIX) |
||||
# include <unistd.h> /* usleep */ |
||||
#endif |
||||
|
||||
#include "pipe/p_compiler.h" |
||||
|
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
|
||||
/*
|
||||
* Get the current time in nanoseconds from an unknown base. |
||||
*/ |
||||
int64_t |
||||
os_time_get_nano(void); |
||||
|
||||
|
||||
/*
|
||||
* Get the current time in microseconds from an unknown base. |
||||
*/ |
||||
static INLINE int64_t |
||||
os_time_get(void) { |
||||
return os_time_get_nano() / 1000; |
||||
} |
||||
|
||||
|
||||
/*
|
||||
* Sleep. |
||||
*/ |
||||
#if defined(PIPE_OS_UNIX) |
||||
#define os_time_sleep(_usecs) usleep(_usecs) |
||||
#else |
||||
void |
||||
os_time_sleep(int64_t usecs); |
||||
#endif |
||||
|
||||
|
||||
/*
|
||||
* Helper function for detecting time outs, taking in account overflow. |
||||
* |
||||
* Returns true if the current time has elapsed beyond the specified interval. |
||||
*/ |
||||
static INLINE boolean |
||||
os_time_timeout(int64_t start, |
||||
int64_t end, |
||||
int64_t curr) |
||||
{ |
||||
if(start <= end) |
||||
return !(start <= curr && curr < end); |
||||
else |
||||
return !((start <= curr) || (curr < end)); |
||||
} |
||||
|
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* _OS_TIME_H_ */ |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,118 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 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 TGSI_BUILD_H |
||||
#define TGSI_BUILD_H |
||||
|
||||
|
||||
struct tgsi_token; |
||||
|
||||
|
||||
#if defined __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
|
||||
/*
|
||||
* header |
||||
*/ |
||||
|
||||
struct tgsi_header |
||||
tgsi_build_header( void ); |
||||
|
||||
struct tgsi_processor |
||||
tgsi_build_processor( |
||||
unsigned processor, |
||||
struct tgsi_header *header ); |
||||
|
||||
/*
|
||||
* declaration |
||||
*/ |
||||
|
||||
struct tgsi_full_declaration |
||||
tgsi_default_full_declaration( void ); |
||||
|
||||
unsigned |
||||
tgsi_build_full_declaration( |
||||
const struct tgsi_full_declaration *full_decl, |
||||
struct tgsi_token *tokens, |
||||
struct tgsi_header *header, |
||||
unsigned maxsize ); |
||||
|
||||
/*
|
||||
* immediate |
||||
*/ |
||||
|
||||
struct tgsi_full_immediate |
||||
tgsi_default_full_immediate( void ); |
||||
|
||||
unsigned |
||||
tgsi_build_full_immediate( |
||||
const struct tgsi_full_immediate *full_imm, |
||||
struct tgsi_token *tokens, |
||||
struct tgsi_header *header, |
||||
unsigned maxsize ); |
||||
|
||||
/*
|
||||
* properties |
||||
*/ |
||||
|
||||
struct tgsi_full_property |
||||
tgsi_default_full_property( void ); |
||||
|
||||
unsigned |
||||
tgsi_build_full_property( |
||||
const struct tgsi_full_property *full_prop, |
||||
struct tgsi_token *tokens, |
||||
struct tgsi_header *header, |
||||
unsigned maxsize ); |
||||
|
||||
/*
|
||||
* instruction |
||||
*/ |
||||
|
||||
struct tgsi_instruction |
||||
tgsi_default_instruction( void ); |
||||
|
||||
struct tgsi_full_instruction |
||||
tgsi_default_full_instruction( void ); |
||||
|
||||
unsigned |
||||
tgsi_build_full_instruction( |
||||
const struct tgsi_full_instruction *full_inst, |
||||
struct tgsi_token *tokens, |
||||
struct tgsi_header *header, |
||||
unsigned maxsize ); |
||||
|
||||
struct tgsi_instruction_predicate |
||||
tgsi_default_instruction_predicate(void); |
||||
|
||||
#if defined __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* TGSI_BUILD_H */ |
@ -0,0 +1,763 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* 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. |
||||
*
|
||||
**************************************************************************/ |
||||
|
||||
#include "util/u_debug.h" |
||||
#include "util/u_string.h" |
||||
#include "util/u_math.h" |
||||
#include "util/u_memory.h" |
||||
#include "util/u_math.h" |
||||
#include "tgsi_dump.h" |
||||
#include "tgsi_info.h" |
||||
#include "tgsi_iterate.h" |
||||
#include "tgsi_strings.h" |
||||
|
||||
|
||||
/** Number of spaces to indent for IF/LOOP/etc */ |
||||
static const int indent_spaces = 3; |
||||
|
||||
|
||||
struct dump_ctx |
||||
{ |
||||
struct tgsi_iterate_context iter; |
||||
|
||||
boolean dump_float_as_hex; |
||||
|
||||
uint instno; |
||||
uint immno; |
||||
int indent; |
||||
|
||||
uint indentation; |
||||
|
||||
void (*dump_printf)(struct dump_ctx *ctx, const char *format, ...); |
||||
}; |
||||
|
||||
static void
|
||||
dump_ctx_printf(struct dump_ctx *ctx, const char *format, ...) |
||||
{ |
||||
va_list ap; |
||||
(void)ctx; |
||||
va_start(ap, format); |
||||
_debug_vprintf(format, ap); |
||||
va_end(ap); |
||||
} |
||||
|
||||
static void |
||||
dump_enum( |
||||
struct dump_ctx *ctx, |
||||
uint e, |
||||
const char **enums, |
||||
uint enum_count ) |
||||
{ |
||||
if (e >= enum_count) |
||||
ctx->dump_printf( ctx, "%u", e ); |
||||
else |
||||
ctx->dump_printf( ctx, "%s", enums[e] ); |
||||
} |
||||
|
||||
#define EOL() ctx->dump_printf( ctx, "\n" ) |
||||
#define TXT(S) ctx->dump_printf( ctx, "%s", S ) |
||||
#define CHR(C) ctx->dump_printf( ctx, "%c", C ) |
||||
#define UIX(I) ctx->dump_printf( ctx, "0x%x", I ) |
||||
#define UID(I) ctx->dump_printf( ctx, "%u", I ) |
||||
#define INSTID(I) ctx->dump_printf( ctx, "% 3u", I ) |
||||
#define SID(I) ctx->dump_printf( ctx, "%d", I ) |
||||
#define FLT(F) ctx->dump_printf( ctx, "%10.8f", F ) |
||||
#define HFLT(F) ctx->dump_printf( ctx, "0x%08x", fui((F)) ) |
||||
#define ENM(E,ENUMS) dump_enum( ctx, E, ENUMS, sizeof( ENUMS ) / sizeof( *ENUMS ) ) |
||||
|
||||
const char * |
||||
tgsi_swizzle_names[4] = |
||||
{ |
||||
"x", |
||||
"y", |
||||
"z", |
||||
"w" |
||||
}; |
||||
|
||||
static void |
||||
_dump_register_src( |
||||
struct dump_ctx *ctx, |
||||
const struct tgsi_full_src_register *src ) |
||||
{ |
||||
TXT(tgsi_file_name(src->Register.File)); |
||||
if (src->Register.Dimension) { |
||||
if (src->Dimension.Indirect) { |
||||
CHR( '[' ); |
||||
TXT(tgsi_file_name(src->DimIndirect.File)); |
||||
CHR( '[' ); |
||||
SID( src->DimIndirect.Index ); |
||||
TXT( "]." ); |
||||
ENM( src->DimIndirect.Swizzle, tgsi_swizzle_names ); |
||||
if (src->Dimension.Index != 0) { |
||||
if (src->Dimension.Index > 0) |
||||
CHR( '+' ); |
||||
SID( src->Dimension.Index ); |
||||
} |
||||
CHR( ']' ); |
||||
if (src->DimIndirect.ArrayID) { |
||||
CHR( '(' ); |
||||
SID( src->DimIndirect.ArrayID ); |
||||
CHR( ')' ); |
||||
} |
||||
} else { |
||||
CHR('['); |
||||
SID(src->Dimension.Index); |
||||
CHR(']'); |
||||
} |
||||
} |
||||
if (src->Register.Indirect) { |
||||
CHR( '[' ); |
||||
TXT(tgsi_file_name(src->Indirect.File)); |
||||
CHR( '[' ); |
||||
SID( src->Indirect.Index ); |
||||
TXT( "]." ); |
||||
ENM( src->Indirect.Swizzle, tgsi_swizzle_names ); |
||||
if (src->Register.Index != 0) { |
||||
if (src->Register.Index > 0) |
||||
CHR( '+' ); |
||||
SID( src->Register.Index ); |
||||
} |
||||
CHR( ']' ); |
||||
if (src->Indirect.ArrayID) { |
||||
CHR( '(' ); |
||||
SID( src->Indirect.ArrayID ); |
||||
CHR( ')' ); |
||||
} |
||||
} else { |
||||
CHR( '[' ); |
||||
SID( src->Register.Index ); |
||||
CHR( ']' ); |
||||
} |
||||
} |
||||
|
||||
|
||||
static void |
||||
_dump_register_dst( |
||||
struct dump_ctx *ctx, |
||||
const struct tgsi_full_dst_register *dst ) |
||||
{ |
||||
TXT(tgsi_file_name(dst->Register.File)); |
||||
if (dst->Register.Dimension) { |
||||
if (dst->Dimension.Indirect) { |
||||
CHR( '[' ); |
||||
TXT(tgsi_file_name(dst->DimIndirect.File)); |
||||
CHR( '[' ); |
||||
SID( dst->DimIndirect.Index ); |
||||
TXT( "]." ); |
||||
ENM( dst->DimIndirect.Swizzle, tgsi_swizzle_names ); |
||||
if (dst->Dimension.Index != 0) { |
||||
if (dst->Dimension.Index > 0) |
||||
CHR( '+' ); |
||||
SID( dst->Dimension.Index ); |
||||
} |
||||
CHR( ']' ); |
||||
if (dst->DimIndirect.ArrayID) { |
||||
CHR( '(' ); |
||||
SID( dst->DimIndirect.ArrayID ); |
||||
CHR( ')' ); |
||||
} |
||||
} else { |
||||
CHR('['); |
||||
SID(dst->Dimension.Index); |
||||
CHR(']'); |
||||
} |
||||
} |
||||
if (dst->Register.Indirect) { |
||||
CHR( '[' ); |
||||
TXT(tgsi_file_name(dst->Indirect.File)); |
||||
CHR( '[' ); |
||||
SID( dst->Indirect.Index ); |
||||
TXT( "]." ); |
||||
ENM( dst->Indirect.Swizzle, tgsi_swizzle_names ); |
||||
if (dst->Register.Index != 0) { |
||||
if (dst->Register.Index > 0) |
||||
CHR( '+' ); |
||||
SID( dst->Register.Index ); |
||||
} |
||||
CHR( ']' ); |
||||
if (dst->Indirect.ArrayID) { |
||||
CHR( '(' ); |
||||
SID( dst->Indirect.ArrayID ); |
||||
CHR( ')' ); |
||||
} |
||||
} else { |
||||
CHR( '[' ); |
||||
SID( dst->Register.Index ); |
||||
CHR( ']' ); |
||||
} |
||||
} |
||||
static void |
||||
_dump_writemask( |
||||
struct dump_ctx *ctx, |
||||
uint writemask ) |
||||
{ |
||||
if (writemask != TGSI_WRITEMASK_XYZW) { |
||||
CHR( '.' ); |
||||
if (writemask & TGSI_WRITEMASK_X) |
||||
CHR( 'x' ); |
||||
if (writemask & TGSI_WRITEMASK_Y) |
||||
CHR( 'y' ); |
||||
if (writemask & TGSI_WRITEMASK_Z) |
||||
CHR( 'z' ); |
||||
if (writemask & TGSI_WRITEMASK_W) |
||||
CHR( 'w' ); |
||||
} |
||||
} |
||||
|
||||
static void |
||||
dump_imm_data(struct tgsi_iterate_context *iter, |
||||
union tgsi_immediate_data *data, |
||||
unsigned num_tokens, |
||||
unsigned data_type) |
||||
{ |
||||
struct dump_ctx *ctx = (struct dump_ctx *)iter; |
||||
unsigned i ; |
||||
|
||||
TXT( " {" ); |
||||
|
||||
assert( num_tokens <= 4 ); |
||||
for (i = 0; i < num_tokens; i++) { |
||||
switch (data_type) { |
||||
case TGSI_IMM_FLOAT32: |
||||
if (ctx->dump_float_as_hex) |
||||
HFLT( data[i].Float ); |
||||
else |
||||
FLT( data[i].Float ); |
||||
break; |
||||
case TGSI_IMM_UINT32: |
||||
UID(data[i].Uint); |
||||
break; |
||||
case TGSI_IMM_INT32: |
||||
SID(data[i].Int); |
||||
break; |
||||
default: |
||||
assert( 0 ); |
||||
} |
||||
|
||||
if (i < num_tokens - 1) |
||||
TXT( ", " ); |
||||
} |
||||
TXT( "}" ); |
||||
} |
||||
|
||||
static boolean |
||||
iter_declaration( |
||||
struct tgsi_iterate_context *iter, |
||||
struct tgsi_full_declaration *decl ) |
||||
{ |
||||
struct dump_ctx *ctx = (struct dump_ctx *)iter; |
||||
|
||||
TXT( "DCL " ); |
||||
|
||||
TXT(tgsi_file_name(decl->Declaration.File)); |
||||
|
||||
/* all geometry shader inputs are two dimensional */ |
||||
if (decl->Declaration.File == TGSI_FILE_INPUT && |
||||
iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY) { |
||||
TXT("[]"); |
||||
} |
||||
|
||||
if (decl->Declaration.Dimension) { |
||||
CHR('['); |
||||
SID(decl->Dim.Index2D); |
||||
CHR(']'); |
||||
} |
||||
|
||||
CHR('['); |
||||
SID(decl->Range.First); |
||||
if (decl->Range.First != decl->Range.Last) { |
||||
TXT(".."); |
||||
SID(decl->Range.Last); |
||||
} |
||||
CHR(']'); |
||||
|
||||
_dump_writemask( |
||||
ctx, |
||||
decl->Declaration.UsageMask ); |
||||
|
||||
if (decl->Declaration.Array) { |
||||
TXT( ", ARRAY(" ); |
||||
SID(decl->Array.ArrayID); |
||||
CHR(')'); |
||||
} |
||||
|
||||
if (decl->Declaration.Local) |
||||
TXT( ", LOCAL" ); |
||||
|
||||
if (decl->Declaration.Semantic) { |
||||
TXT( ", " ); |
||||
ENM( decl->Semantic.Name, tgsi_semantic_names ); |
||||
if (decl->Semantic.Index != 0 || |
||||
decl->Semantic.Name == TGSI_SEMANTIC_TEXCOORD || |
||||
decl->Semantic.Name == TGSI_SEMANTIC_GENERIC) { |
||||
CHR( '[' ); |
||||
UID( decl->Semantic.Index ); |
||||
CHR( ']' ); |
||||
} |
||||
} |
||||
|
||||
if (decl->Declaration.File == TGSI_FILE_RESOURCE) { |
||||
TXT(", "); |
||||
ENM(decl->Resource.Resource, tgsi_texture_names); |
||||
if (decl->Resource.Writable) |
||||
TXT(", WR"); |
||||
if (decl->Resource.Raw) |
||||
TXT(", RAW"); |
||||
} |
||||
|
||||
if (decl->Declaration.File == TGSI_FILE_SAMPLER_VIEW) { |
||||
TXT(", "); |
||||
ENM(decl->SamplerView.Resource, tgsi_texture_names); |
||||
TXT(", "); |
||||
if ((decl->SamplerView.ReturnTypeX == decl->SamplerView.ReturnTypeY) && |
||||
(decl->SamplerView.ReturnTypeX == decl->SamplerView.ReturnTypeZ) && |
||||
(decl->SamplerView.ReturnTypeX == decl->SamplerView.ReturnTypeW)) { |
||||
ENM(decl->SamplerView.ReturnTypeX, tgsi_type_names); |
||||
} else { |
||||
ENM(decl->SamplerView.ReturnTypeX, tgsi_type_names); |
||||
TXT(", "); |
||||
ENM(decl->SamplerView.ReturnTypeY, tgsi_type_names); |
||||
TXT(", "); |
||||
ENM(decl->SamplerView.ReturnTypeZ, tgsi_type_names); |
||||
TXT(", "); |
||||
ENM(decl->SamplerView.ReturnTypeW, tgsi_type_names); |
||||
} |
||||
} |
||||
|
||||
if (decl->Declaration.Interpolate) { |
||||
if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT && |
||||
decl->Declaration.File == TGSI_FILE_INPUT) |
||||
{ |
||||
TXT( ", " ); |
||||
ENM( decl->Interp.Interpolate, tgsi_interpolate_names ); |
||||
} |
||||
|
||||
if (decl->Interp.Centroid) { |
||||
TXT( ", CENTROID" ); |
||||
} |
||||
|
||||
if (decl->Interp.CylindricalWrap) { |
||||
TXT(", CYLWRAP_"); |
||||
if (decl->Interp.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_X) { |
||||
CHR('X'); |
||||
} |
||||
if (decl->Interp.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_Y) { |
||||
CHR('Y'); |
||||
} |
||||
if (decl->Interp.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_Z) { |
||||
CHR('Z'); |
||||
} |
||||
if (decl->Interp.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_W) { |
||||
CHR('W'); |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (decl->Declaration.Invariant) { |
||||
TXT( ", INVARIANT" ); |
||||
} |
||||
|
||||
EOL(); |
||||
|
||||
return TRUE; |
||||
} |
||||
|
||||
void |
||||
tgsi_dump_declaration( |
||||
const struct tgsi_full_declaration *decl ) |
||||
{ |
||||
struct dump_ctx ctx; |
||||
|
||||
ctx.dump_printf = dump_ctx_printf; |
||||
|
||||
iter_declaration( &ctx.iter, (struct tgsi_full_declaration *)decl ); |
||||
} |
||||
|
||||
static boolean |
||||
iter_property( |
||||
struct tgsi_iterate_context *iter, |
||||
struct tgsi_full_property *prop ) |
||||
{ |
||||
unsigned i; |
||||
struct dump_ctx *ctx = (struct dump_ctx *)iter; |
||||
|
||||
TXT( "PROPERTY " ); |
||||
ENM(prop->Property.PropertyName, tgsi_property_names); |
||||
|
||||
if (prop->Property.NrTokens > 1) |
||||
TXT(" "); |
||||
|
||||
for (i = 0; i < prop->Property.NrTokens - 1; ++i) { |
||||
switch (prop->Property.PropertyName) { |
||||
case TGSI_PROPERTY_GS_INPUT_PRIM: |
||||
case TGSI_PROPERTY_GS_OUTPUT_PRIM: |
||||
ENM(prop->u[i].Data, tgsi_primitive_names); |
||||
break; |
||||
case TGSI_PROPERTY_FS_COORD_ORIGIN: |
||||
ENM(prop->u[i].Data, tgsi_fs_coord_origin_names); |
||||
break; |
||||
case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER: |
||||
ENM(prop->u[i].Data, tgsi_fs_coord_pixel_center_names); |
||||
break; |
||||
default: |
||||
SID( prop->u[i].Data ); |
||||
break; |
||||
} |
||||
if (i < prop->Property.NrTokens - 2) |
||||
TXT( ", " ); |
||||
} |
||||
EOL(); |
||||
|
||||
return TRUE; |
||||
} |
||||
|
||||
void tgsi_dump_property( |
||||
const struct tgsi_full_property *prop ) |
||||
{ |
||||
struct dump_ctx ctx; |
||||
|
||||
ctx.dump_printf = dump_ctx_printf; |
||||
|
||||
iter_property( &ctx.iter, (struct tgsi_full_property *)prop ); |
||||
} |
||||
|
||||
static boolean |
||||
iter_immediate( |
||||
struct tgsi_iterate_context *iter, |
||||
struct tgsi_full_immediate *imm ) |
||||
{ |
||||
struct dump_ctx *ctx = (struct dump_ctx *) iter; |
||||
|
||||
TXT( "IMM[" ); |
||||
SID( ctx->immno++ ); |
||||
TXT( "] " ); |
||||
ENM( imm->Immediate.DataType, tgsi_immediate_type_names ); |
||||
|
||||
dump_imm_data(iter, imm->u, imm->Immediate.NrTokens - 1, |
||||
imm->Immediate.DataType); |
||||
|
||||
EOL(); |
||||
|
||||
return TRUE; |
||||
} |
||||
|
||||
void |
||||
tgsi_dump_immediate( |
||||
const struct tgsi_full_immediate *imm ) |
||||
{ |
||||
struct dump_ctx ctx; |
||||
|
||||
ctx.dump_printf = dump_ctx_printf; |
||||
|
||||
iter_immediate( &ctx.iter, (struct tgsi_full_immediate *)imm ); |
||||
} |
||||
|
||||
static boolean |
||||
iter_instruction( |
||||
struct tgsi_iterate_context *iter, |
||||
struct tgsi_full_instruction *inst ) |
||||
{ |
||||
struct dump_ctx *ctx = (struct dump_ctx *) iter; |
||||
uint instno = ctx->instno++; |
||||
const struct tgsi_opcode_info *info = tgsi_get_opcode_info( inst->Instruction.Opcode ); |
||||
uint i; |
||||
boolean first_reg = TRUE; |
||||
|
||||
INSTID( instno ); |
||||
TXT( ": " ); |
||||
|
||||
ctx->indent -= info->pre_dedent; |
||||
for(i = 0; (int)i < ctx->indent; ++i) |
||||
TXT( " " ); |
||||
ctx->indent += info->post_indent; |
||||
|
||||
if (inst->Instruction.Predicate) { |
||||
CHR( '(' ); |
||||
|
||||
if (inst->Predicate.Negate) |
||||
CHR( '!' ); |
||||
|
||||
TXT( "PRED[" ); |
||||
SID( inst->Predicate.Index ); |
||||
CHR( ']' ); |
||||
|
||||
if (inst->Predicate.SwizzleX != TGSI_SWIZZLE_X || |
||||
inst->Predicate.SwizzleY != TGSI_SWIZZLE_Y || |
||||
inst->Predicate.SwizzleZ != TGSI_SWIZZLE_Z || |
||||
inst->Predicate.SwizzleW != TGSI_SWIZZLE_W) { |
||||
CHR( '.' ); |
||||
ENM( inst->Predicate.SwizzleX, tgsi_swizzle_names ); |
||||
ENM( inst->Predicate.SwizzleY, tgsi_swizzle_names ); |
||||
ENM( inst->Predicate.SwizzleZ, tgsi_swizzle_names ); |
||||
ENM( inst->Predicate.SwizzleW, tgsi_swizzle_names ); |
||||
} |
||||
|
||||
TXT( ") " ); |
||||
} |
||||
|
||||
TXT( info->mnemonic ); |
||||
|
||||
switch (inst->Instruction.Saturate) { |
||||
case TGSI_SAT_NONE: |
||||
break; |
||||
case TGSI_SAT_ZERO_ONE: |
||||
TXT( "_SAT" ); |
||||
break; |
||||
case TGSI_SAT_MINUS_PLUS_ONE: |
||||
TXT( "_SATNV" ); |
||||
break; |
||||
default: |
||||
assert( 0 ); |
||||
} |
||||
|
||||
for (i = 0; i < inst->Instruction.NumDstRegs; i++) { |
||||
const struct tgsi_full_dst_register *dst = &inst->Dst[i]; |
||||
|
||||
if (!first_reg) |
||||
CHR( ',' ); |
||||
CHR( ' ' ); |
||||
|
||||
_dump_register_dst( ctx, dst ); |
||||
_dump_writemask( ctx, dst->Register.WriteMask ); |
||||
|
||||
first_reg = FALSE; |
||||
} |
||||
|
||||
for (i = 0; i < inst->Instruction.NumSrcRegs; i++) { |
||||
const struct tgsi_full_src_register *src = &inst->Src[i]; |
||||
|
||||
if (!first_reg) |
||||
CHR( ',' ); |
||||
CHR( ' ' ); |
||||
|
||||
if (src->Register.Negate) |
||||
CHR( '-' ); |
||||
if (src->Register.Absolute) |
||||
CHR( '|' ); |
||||
|
||||
_dump_register_src(ctx, src); |
||||
|
||||
if (src->Register.SwizzleX != TGSI_SWIZZLE_X || |
||||
src->Register.SwizzleY != TGSI_SWIZZLE_Y || |
||||
src->Register.SwizzleZ != TGSI_SWIZZLE_Z || |
||||
src->Register.SwizzleW != TGSI_SWIZZLE_W) { |
||||
CHR( '.' ); |
||||
ENM( src->Register.SwizzleX, tgsi_swizzle_names ); |
||||
ENM( src->Register.SwizzleY, tgsi_swizzle_names ); |
||||
ENM( src->Register.SwizzleZ, tgsi_swizzle_names ); |
||||
ENM( src->Register.SwizzleW, tgsi_swizzle_names ); |
||||
} |
||||
|
||||
if (src->Register.Absolute) |
||||
CHR( '|' ); |
||||
|
||||
first_reg = FALSE; |
||||
} |
||||
|
||||
if (inst->Instruction.Texture) { |
||||
TXT( ", " ); |
||||
ENM( inst->Texture.Texture, tgsi_texture_names ); |
||||
for (i = 0; i < inst->Texture.NumOffsets; i++) { |
||||
TXT( ", " ); |
||||
TXT(tgsi_file_name(inst->TexOffsets[i].File)); |
||||
CHR( '[' ); |
||||
SID( inst->TexOffsets[i].Index ); |
||||
CHR( ']' ); |
||||
CHR( '.' ); |
||||
ENM( inst->TexOffsets[i].SwizzleX, tgsi_swizzle_names); |
||||
ENM( inst->TexOffsets[i].SwizzleY, tgsi_swizzle_names); |
||||
ENM( inst->TexOffsets[i].SwizzleZ, tgsi_swizzle_names); |
||||
} |
||||
} |
||||
|
||||
switch (inst->Instruction.Opcode) { |
||||
case TGSI_OPCODE_IF: |
||||
case TGSI_OPCODE_UIF: |
||||
case TGSI_OPCODE_ELSE: |
||||
case TGSI_OPCODE_BGNLOOP: |
||||
case TGSI_OPCODE_ENDLOOP: |
||||
case TGSI_OPCODE_CAL: |
||||
TXT( " :" ); |
||||
UID( inst->Label.Label ); |
||||
break; |
||||
} |
||||
|
||||
/* update indentation */ |
||||
if (inst->Instruction.Opcode == TGSI_OPCODE_IF || |
||||
inst->Instruction.Opcode == TGSI_OPCODE_UIF || |
||||
inst->Instruction.Opcode == TGSI_OPCODE_ELSE || |
||||
inst->Instruction.Opcode == TGSI_OPCODE_BGNLOOP) { |
||||
ctx->indentation += indent_spaces; |
||||
} |
||||
|
||||
EOL(); |
||||
|
||||
return TRUE; |
||||
} |
||||
|
||||
void |
||||
tgsi_dump_instruction( |
||||
const struct tgsi_full_instruction *inst, |
||||
uint instno ) |
||||
{ |
||||
struct dump_ctx ctx; |
||||
|
||||
ctx.instno = instno; |
||||
ctx.immno = instno; |
||||
ctx.indent = 0; |
||||
ctx.dump_printf = dump_ctx_printf; |
||||
ctx.indentation = 0; |
||||
|
||||
iter_instruction( &ctx.iter, (struct tgsi_full_instruction *)inst ); |
||||
} |
||||
|
||||
static boolean |
||||
prolog( |
||||
struct tgsi_iterate_context *iter ) |
||||
{ |
||||
struct dump_ctx *ctx = (struct dump_ctx *) iter; |
||||
ENM( iter->processor.Processor, tgsi_processor_type_names ); |
||||
EOL(); |
||||
return TRUE; |
||||
} |
||||
|
||||
void |
||||
tgsi_dump( |
||||
const struct tgsi_token *tokens, |
||||
uint flags ) |
||||
{ |
||||
struct dump_ctx ctx; |
||||
|
||||
ctx.iter.prolog = prolog; |
||||
ctx.iter.iterate_instruction = iter_instruction; |
||||
ctx.iter.iterate_declaration = iter_declaration; |
||||
ctx.iter.iterate_immediate = iter_immediate; |
||||
ctx.iter.iterate_property = iter_property; |
||||
ctx.iter.epilog = NULL; |
||||
|
||||
ctx.instno = 0; |
||||
ctx.immno = 0; |
||||
ctx.indent = 0; |
||||
ctx.dump_printf = dump_ctx_printf; |
||||
ctx.indentation = 0; |
||||
|
||||
if (flags & TGSI_DUMP_FLOAT_AS_HEX) |
||||
ctx.dump_float_as_hex = TRUE; |
||||
else |
||||
ctx.dump_float_as_hex = FALSE; |
||||
|
||||
tgsi_iterate_shader( tokens, &ctx.iter ); |
||||
} |
||||
|
||||
struct str_dump_ctx |
||||
{ |
||||
struct dump_ctx base; |
||||
char *str; |
||||
char *ptr; |
||||
int left; |
||||
}; |
||||
|
||||
static void |
||||
str_dump_ctx_printf(struct dump_ctx *ctx, const char *format, ...) |
||||
{ |
||||
struct str_dump_ctx *sctx = (struct str_dump_ctx *)ctx; |
||||
|
||||
if(sctx->left > 1) { |
||||
int written; |
||||
va_list ap; |
||||
va_start(ap, format); |
||||
written = util_vsnprintf(sctx->ptr, sctx->left, format, ap); |
||||
va_end(ap); |
||||
|
||||
/* Some complicated logic needed to handle the return value of
|
||||
* vsnprintf: |
||||
*/ |
||||
if (written > 0) { |
||||
written = MIN2(sctx->left, written); |
||||
sctx->ptr += written; |
||||
sctx->left -= written; |
||||
} |
||||
} |
||||
} |
||||
|
||||
void |
||||
tgsi_dump_str( |
||||
const struct tgsi_token *tokens, |
||||
uint flags, |
||||
char *str, |
||||
size_t size) |
||||
{ |
||||
struct str_dump_ctx ctx; |
||||
|
||||
ctx.base.iter.prolog = prolog; |
||||
ctx.base.iter.iterate_instruction = iter_instruction; |
||||
ctx.base.iter.iterate_declaration = iter_declaration; |
||||
ctx.base.iter.iterate_immediate = iter_immediate; |
||||
ctx.base.iter.iterate_property = iter_property; |
||||
ctx.base.iter.epilog = NULL; |
||||
|
||||
ctx.base.instno = 0; |
||||
ctx.base.immno = 0; |
||||
ctx.base.indent = 0; |
||||
ctx.base.dump_printf = &str_dump_ctx_printf; |
||||
ctx.base.indentation = 0; |
||||
|
||||
ctx.str = str; |
||||
ctx.str[0] = 0; |
||||
ctx.ptr = str; |
||||
ctx.left = (int)size; |
||||
|
||||
if (flags & TGSI_DUMP_FLOAT_AS_HEX) |
||||
ctx.base.dump_float_as_hex = TRUE; |
||||
else |
||||
ctx.base.dump_float_as_hex = FALSE; |
||||
|
||||
tgsi_iterate_shader( tokens, &ctx.base.iter ); |
||||
} |
||||
|
||||
void |
||||
tgsi_dump_instruction_str( |
||||
const struct tgsi_full_instruction *inst, |
||||
uint instno, |
||||
char *str, |
||||
size_t size) |
||||
{ |
||||
struct str_dump_ctx ctx; |
||||
|
||||
ctx.base.instno = instno; |
||||
ctx.base.immno = instno; |
||||
ctx.base.indent = 0; |
||||
ctx.base.dump_printf = &str_dump_ctx_printf; |
||||
ctx.base.indentation = 0; |
||||
|
||||
ctx.str = str; |
||||
ctx.str[0] = 0; |
||||
ctx.ptr = str; |
||||
ctx.left = (int)size; |
||||
|
||||
iter_instruction( &ctx.base.iter, (struct tgsi_full_instruction *)inst ); |
||||
} |
@ -0,0 +1,86 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* 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 TGSI_DUMP_H |
||||
#define TGSI_DUMP_H |
||||
|
||||
#include "pipe/p_compiler.h" |
||||
#include "pipe/p_defines.h" |
||||
#include "pipe/p_shader_tokens.h" |
||||
|
||||
#if defined __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
#define TGSI_DUMP_FLOAT_AS_HEX (1 << 0) |
||||
|
||||
void |
||||
tgsi_dump_str( |
||||
const struct tgsi_token *tokens, |
||||
uint flags, |
||||
char *str, |
||||
size_t size); |
||||
|
||||
void |
||||
tgsi_dump( |
||||
const struct tgsi_token *tokens, |
||||
uint flags ); |
||||
|
||||
struct tgsi_full_immediate; |
||||
struct tgsi_full_instruction; |
||||
struct tgsi_full_declaration; |
||||
struct tgsi_full_property; |
||||
|
||||
void |
||||
tgsi_dump_immediate( |
||||
const struct tgsi_full_immediate *imm ); |
||||
|
||||
void |
||||
tgsi_dump_instruction_str( |
||||
const struct tgsi_full_instruction *inst, |
||||
uint instno, |
||||
char *str, |
||||
size_t size); |
||||
|
||||
void |
||||
tgsi_dump_instruction( |
||||
const struct tgsi_full_instruction *inst, |
||||
uint instno ); |
||||
|
||||
void |
||||
tgsi_dump_declaration( |
||||
const struct tgsi_full_declaration *decl ); |
||||
|
||||
void |
||||
tgsi_dump_property( |
||||
const struct tgsi_full_property *prop ); |
||||
|
||||
#if defined __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* TGSI_DUMP_H */ |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,463 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007-2008 VMware, Inc. |
||||
* All Rights Reserved. |
||||
* Copyright 2009-2010 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 TGSI_EXEC_H |
||||
#define TGSI_EXEC_H |
||||
|
||||
#include "pipe/p_compiler.h" |
||||
#include "pipe/p_state.h" |
||||
#include "pipe/p_shader_tokens.h" |
||||
|
||||
#if defined __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
#define TGSI_CHAN_X 0 |
||||
#define TGSI_CHAN_Y 1 |
||||
#define TGSI_CHAN_Z 2 |
||||
#define TGSI_CHAN_W 3 |
||||
|
||||
#define TGSI_NUM_CHANNELS 4 /* R,G,B,A */ |
||||
#define TGSI_QUAD_SIZE 4 /* 4 pixel/quad */ |
||||
|
||||
#define TGSI_FOR_EACH_CHANNEL( CHAN )\ |
||||
for (CHAN = 0; CHAN < TGSI_NUM_CHANNELS; CHAN++) |
||||
|
||||
#define TGSI_IS_DST0_CHANNEL_ENABLED( INST, CHAN )\ |
||||
((INST)->Dst[0].Register.WriteMask & (1 << (CHAN))) |
||||
|
||||
#define TGSI_IF_IS_DST0_CHANNEL_ENABLED( INST, CHAN )\ |
||||
if (TGSI_IS_DST0_CHANNEL_ENABLED( INST, CHAN )) |
||||
|
||||
#define TGSI_FOR_EACH_DST0_ENABLED_CHANNEL( INST, CHAN )\ |
||||
TGSI_FOR_EACH_CHANNEL( CHAN )\
|
||||
TGSI_IF_IS_DST0_CHANNEL_ENABLED( INST, CHAN ) |
||||
|
||||
|
||||
/**
|
||||
* Registers may be treated as float, signed int or unsigned int. |
||||
*/ |
||||
union tgsi_exec_channel |
||||
{ |
||||
float f[TGSI_QUAD_SIZE]; |
||||
int i[TGSI_QUAD_SIZE]; |
||||
unsigned u[TGSI_QUAD_SIZE]; |
||||
}; |
||||
|
||||
/**
|
||||
* A vector[RGBA] of channels[4 pixels] |
||||
*/ |
||||
struct tgsi_exec_vector |
||||
{ |
||||
union tgsi_exec_channel xyzw[TGSI_NUM_CHANNELS]; |
||||
}; |
||||
|
||||
/**
|
||||
* For fragment programs, information for computing fragment input |
||||
* values from plane equation of the triangle/line. |
||||
*/ |
||||
struct tgsi_interp_coef |
||||
{ |
||||
float a0[TGSI_NUM_CHANNELS]; /* in an xyzw layout */ |
||||
float dadx[TGSI_NUM_CHANNELS]; |
||||
float dady[TGSI_NUM_CHANNELS]; |
||||
}; |
||||
|
||||
enum tgsi_sampler_control { |
||||
tgsi_sampler_lod_none, |
||||
tgsi_sampler_lod_bias, |
||||
tgsi_sampler_lod_explicit, |
||||
tgsi_sampler_lod_zero, |
||||
tgsi_sampler_derivs_explicit |
||||
}; |
||||
|
||||
/**
|
||||
* Information for sampling textures, which must be implemented |
||||
* by code outside the TGSI executor. |
||||
*/ |
||||
struct tgsi_sampler |
||||
{ |
||||
/** Get samples for four fragments in a quad */ |
||||
/* this interface contains 5 sets of channels that vary
|
||||
* depending on the sampler. |
||||
* s - the first texture coordinate for sampling. |
||||
* t - the second texture coordinate for sampling - unused for 1D, |
||||
layer for 1D arrays. |
||||
* r - the third coordinate for sampling for 3D, cube, cube arrays, |
||||
* layer for 2D arrays. Compare value for 1D/2D shadows. |
||||
* c0 - Compare value for shadow cube and shadow 2d arrays, |
||||
* layer for cube arrays. |
||||
* derivs - explicit derivatives. |
||||
* offset - texel offsets |
||||
* lod - lod value, except for shadow cube arrays (compare value there). |
||||
*/ |
||||
void (*get_samples)(struct tgsi_sampler *sampler, |
||||
const unsigned sview_index, |
||||
const unsigned sampler_index, |
||||
const float s[TGSI_QUAD_SIZE], |
||||
const float t[TGSI_QUAD_SIZE], |
||||
const float r[TGSI_QUAD_SIZE], |
||||
const float c0[TGSI_QUAD_SIZE], |
||||
const float c1[TGSI_QUAD_SIZE], |
||||
float derivs[3][2][TGSI_QUAD_SIZE], |
||||
const int8_t offset[3], |
||||
enum tgsi_sampler_control control, |
||||
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]); |
||||
void (*get_dims)(struct tgsi_sampler *sampler, |
||||
const unsigned sview_index, |
||||
int level, int dims[4]); |
||||
void (*get_texel)(struct tgsi_sampler *sampler, |
||||
const unsigned sview_index, |
||||
const int i[TGSI_QUAD_SIZE], |
||||
const int j[TGSI_QUAD_SIZE], const int k[TGSI_QUAD_SIZE], |
||||
const int lod[TGSI_QUAD_SIZE], const int8_t offset[3], |
||||
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]); |
||||
}; |
||||
|
||||
#define TGSI_EXEC_NUM_TEMPS 4096 |
||||
#define TGSI_EXEC_NUM_IMMEDIATES 256 |
||||
|
||||
/*
|
||||
* Locations of various utility registers (_I = Index, _C = Channel) |
||||
*/ |
||||
#define TGSI_EXEC_TEMP_00000000_I (TGSI_EXEC_NUM_TEMPS + 0) |
||||
#define TGSI_EXEC_TEMP_00000000_C 0 |
||||
|
||||
#define TGSI_EXEC_TEMP_7FFFFFFF_I (TGSI_EXEC_NUM_TEMPS + 0) |
||||
#define TGSI_EXEC_TEMP_7FFFFFFF_C 1 |
||||
|
||||
#define TGSI_EXEC_TEMP_80000000_I (TGSI_EXEC_NUM_TEMPS + 0) |
||||
#define TGSI_EXEC_TEMP_80000000_C 2 |
||||
|
||||
#define TGSI_EXEC_TEMP_FFFFFFFF_I (TGSI_EXEC_NUM_TEMPS + 0) |
||||
#define TGSI_EXEC_TEMP_FFFFFFFF_C 3 |
||||
|
||||
#define TGSI_EXEC_TEMP_ONE_I (TGSI_EXEC_NUM_TEMPS + 1) |
||||
#define TGSI_EXEC_TEMP_ONE_C 0 |
||||
|
||||
#define TGSI_EXEC_TEMP_TWO_I (TGSI_EXEC_NUM_TEMPS + 1) |
||||
#define TGSI_EXEC_TEMP_TWO_C 1 |
||||
|
||||
#define TGSI_EXEC_TEMP_128_I (TGSI_EXEC_NUM_TEMPS + 1) |
||||
#define TGSI_EXEC_TEMP_128_C 2 |
||||
|
||||
#define TGSI_EXEC_TEMP_MINUS_128_I (TGSI_EXEC_NUM_TEMPS + 1) |
||||
#define TGSI_EXEC_TEMP_MINUS_128_C 3 |
||||
|
||||
#define TGSI_EXEC_TEMP_KILMASK_I (TGSI_EXEC_NUM_TEMPS + 2) |
||||
#define TGSI_EXEC_TEMP_KILMASK_C 0 |
||||
|
||||
#define TGSI_EXEC_TEMP_OUTPUT_I (TGSI_EXEC_NUM_TEMPS + 2) |
||||
#define TGSI_EXEC_TEMP_OUTPUT_C 1 |
||||
|
||||
#define TGSI_EXEC_TEMP_PRIMITIVE_I (TGSI_EXEC_NUM_TEMPS + 2) |
||||
#define TGSI_EXEC_TEMP_PRIMITIVE_C 2 |
||||
|
||||
#define TGSI_EXEC_TEMP_THREE_I (TGSI_EXEC_NUM_TEMPS + 2) |
||||
#define TGSI_EXEC_TEMP_THREE_C 3 |
||||
|
||||
#define TGSI_EXEC_TEMP_HALF_I (TGSI_EXEC_NUM_TEMPS + 3) |
||||
#define TGSI_EXEC_TEMP_HALF_C 0 |
||||
|
||||
/* execution mask, each value is either 0 or ~0 */ |
||||
#define TGSI_EXEC_MASK_I (TGSI_EXEC_NUM_TEMPS + 3) |
||||
#define TGSI_EXEC_MASK_C 1 |
||||
|
||||
/* 4 register buffer for various purposes */ |
||||
#define TGSI_EXEC_TEMP_R0 (TGSI_EXEC_NUM_TEMPS + 4) |
||||
#define TGSI_EXEC_NUM_TEMP_R 4 |
||||
|
||||
#define TGSI_EXEC_TEMP_ADDR (TGSI_EXEC_NUM_TEMPS + 8) |
||||
#define TGSI_EXEC_NUM_ADDRS 1 |
||||
|
||||
/* predicate register */ |
||||
#define TGSI_EXEC_TEMP_P0 (TGSI_EXEC_NUM_TEMPS + 9) |
||||
#define TGSI_EXEC_NUM_PREDS 1 |
||||
|
||||
#define TGSI_EXEC_NUM_TEMP_EXTRAS 10 |
||||
|
||||
|
||||
|
||||
#define TGSI_EXEC_MAX_NESTING 32 |
||||
#define TGSI_EXEC_MAX_COND_NESTING TGSI_EXEC_MAX_NESTING |
||||
#define TGSI_EXEC_MAX_LOOP_NESTING TGSI_EXEC_MAX_NESTING |
||||
#define TGSI_EXEC_MAX_SWITCH_NESTING TGSI_EXEC_MAX_NESTING |
||||
#define TGSI_EXEC_MAX_CALL_NESTING TGSI_EXEC_MAX_NESTING |
||||
|
||||
/* The maximum number of input attributes per vertex. For 2D
|
||||
* input register files, this is the stride between two 1D |
||||
* arrays. |
||||
*/ |
||||
#define TGSI_EXEC_MAX_INPUT_ATTRIBS 17 |
||||
|
||||
/* The maximum number of constant vectors per constant buffer.
|
||||
*/ |
||||
#define TGSI_EXEC_MAX_CONST_BUFFER 4096 |
||||
|
||||
/* The maximum number of vertices per primitive */ |
||||
#define TGSI_MAX_PRIM_VERTICES 6 |
||||
|
||||
/* The maximum number of primitives to be generated */ |
||||
#define TGSI_MAX_PRIMITIVES 64 |
||||
|
||||
/* The maximum total number of vertices */ |
||||
#define TGSI_MAX_TOTAL_VERTICES (TGSI_MAX_PRIM_VERTICES * TGSI_MAX_PRIMITIVES * PIPE_MAX_ATTRIBS) |
||||
|
||||
#define TGSI_MAX_MISC_INPUTS 8 |
||||
|
||||
/** function call/activation record */ |
||||
struct tgsi_call_record |
||||
{ |
||||
uint CondStackTop; |
||||
uint LoopStackTop; |
||||
uint ContStackTop; |
||||
int SwitchStackTop; |
||||
int BreakStackTop; |
||||
uint ReturnAddr; |
||||
}; |
||||
|
||||
|
||||
/* Switch-case block state. */ |
||||
struct tgsi_switch_record { |
||||
uint mask; /**< execution mask */ |
||||
union tgsi_exec_channel selector; /**< a value case statements are compared to */ |
||||
uint defaultMask; /**< non-execute mask for default case */ |
||||
}; |
||||
|
||||
|
||||
enum tgsi_break_type { |
||||
TGSI_EXEC_BREAK_INSIDE_LOOP, |
||||
TGSI_EXEC_BREAK_INSIDE_SWITCH |
||||
}; |
||||
|
||||
|
||||
#define TGSI_EXEC_MAX_BREAK_STACK (TGSI_EXEC_MAX_LOOP_NESTING + TGSI_EXEC_MAX_SWITCH_NESTING) |
||||
|
||||
|
||||
/**
|
||||
* Run-time virtual machine state for executing TGSI shader. |
||||
*/ |
||||
struct tgsi_exec_machine |
||||
{ |
||||
/* Total = program temporaries + internal temporaries
|
||||
*/ |
||||
struct tgsi_exec_vector Temps[TGSI_EXEC_NUM_TEMPS + |
||||
TGSI_EXEC_NUM_TEMP_EXTRAS]; |
||||
|
||||
float Imms[TGSI_EXEC_NUM_IMMEDIATES][4]; |
||||
|
||||
float ImmArray[TGSI_EXEC_NUM_IMMEDIATES][4]; |
||||
|
||||
struct tgsi_exec_vector *Inputs; |
||||
struct tgsi_exec_vector *Outputs; |
||||
|
||||
/* System values */ |
||||
unsigned SysSemanticToIndex[TGSI_SEMANTIC_COUNT]; |
||||
union tgsi_exec_channel SystemValue[TGSI_MAX_MISC_INPUTS]; |
||||
|
||||
struct tgsi_exec_vector *Addrs; |
||||
struct tgsi_exec_vector *Predicates; |
||||
|
||||
struct tgsi_sampler *Sampler; |
||||
|
||||
unsigned ImmLimit; |
||||
|
||||
const void *Consts[PIPE_MAX_CONSTANT_BUFFERS]; |
||||
unsigned ConstsSize[PIPE_MAX_CONSTANT_BUFFERS]; |
||||
|
||||
const struct tgsi_token *Tokens; /**< Declarations, instructions */ |
||||
unsigned Processor; /**< TGSI_PROCESSOR_x */ |
||||
|
||||
/* GEOMETRY processor only. */ |
||||
unsigned *Primitives; |
||||
unsigned NumOutputs; |
||||
unsigned MaxGeometryShaderOutputs; |
||||
|
||||
/* FRAGMENT processor only. */ |
||||
const struct tgsi_interp_coef *InterpCoefs; |
||||
struct tgsi_exec_vector QuadPos; |
||||
float Face; /**< +1 if front facing, -1 if back facing */ |
||||
bool flatshade_color; |
||||
/* Conditional execution masks */ |
||||
uint CondMask; /**< For IF/ELSE/ENDIF */ |
||||
uint LoopMask; /**< For BGNLOOP/ENDLOOP */ |
||||
uint ContMask; /**< For loop CONT statements */ |
||||
uint FuncMask; /**< For function calls */ |
||||
uint ExecMask; /**< = CondMask & LoopMask */ |
||||
|
||||
/* Current switch-case state. */ |
||||
struct tgsi_switch_record Switch; |
||||
|
||||
/* Current break type. */ |
||||
enum tgsi_break_type BreakType; |
||||
|
||||
/** Condition mask stack (for nested conditionals) */ |
||||
uint CondStack[TGSI_EXEC_MAX_COND_NESTING]; |
||||
int CondStackTop; |
||||
|
||||
/** Loop mask stack (for nested loops) */ |
||||
uint LoopStack[TGSI_EXEC_MAX_LOOP_NESTING]; |
||||
int LoopStackTop; |
||||
|
||||
/** Loop label stack */ |
||||
uint LoopLabelStack[TGSI_EXEC_MAX_LOOP_NESTING]; |
||||
int LoopLabelStackTop; |
||||
|
||||
/** Loop continue mask stack (see comments in tgsi_exec.c) */ |
||||
uint ContStack[TGSI_EXEC_MAX_LOOP_NESTING]; |
||||
int ContStackTop; |
||||
|
||||
/** Switch case stack */ |
||||
struct tgsi_switch_record SwitchStack[TGSI_EXEC_MAX_SWITCH_NESTING]; |
||||
int SwitchStackTop; |
||||
|
||||
enum tgsi_break_type BreakStack[TGSI_EXEC_MAX_BREAK_STACK]; |
||||
int BreakStackTop; |
||||
|
||||
/** Function execution mask stack (for executing subroutine code) */ |
||||
uint FuncStack[TGSI_EXEC_MAX_CALL_NESTING]; |
||||
int FuncStackTop; |
||||
|
||||
/** Function call stack for saving/restoring the program counter */ |
||||
struct tgsi_call_record CallStack[TGSI_EXEC_MAX_CALL_NESTING]; |
||||
int CallStackTop; |
||||
|
||||
struct tgsi_full_instruction *Instructions; |
||||
uint NumInstructions; |
||||
|
||||
struct tgsi_full_declaration *Declarations; |
||||
uint NumDeclarations; |
||||
|
||||
struct tgsi_declaration_sampler_view |
||||
SamplerViews[PIPE_MAX_SHADER_SAMPLER_VIEWS]; |
||||
|
||||
boolean UsedGeometryShader; |
||||
}; |
||||
|
||||
struct tgsi_exec_machine * |
||||
tgsi_exec_machine_create( void ); |
||||
|
||||
void |
||||
tgsi_exec_machine_destroy(struct tgsi_exec_machine *mach); |
||||
|
||||
|
||||
void
|
||||
tgsi_exec_machine_bind_shader( |
||||
struct tgsi_exec_machine *mach, |
||||
const struct tgsi_token *tokens, |
||||
struct tgsi_sampler *sampler); |
||||
|
||||
uint |
||||
tgsi_exec_machine_run( |
||||
struct tgsi_exec_machine *mach ); |
||||
|
||||
|
||||
void |
||||
tgsi_exec_machine_free_data(struct tgsi_exec_machine *mach); |
||||
|
||||
|
||||
boolean |
||||
tgsi_check_soa_dependencies(const struct tgsi_full_instruction *inst); |
||||
|
||||
|
||||
static INLINE void |
||||
tgsi_set_kill_mask(struct tgsi_exec_machine *mach, unsigned mask) |
||||
{ |
||||
mach->Temps[TGSI_EXEC_TEMP_KILMASK_I].xyzw[TGSI_EXEC_TEMP_KILMASK_C].u[0] = |
||||
mask; |
||||
} |
||||
|
||||
|
||||
/** Set execution mask values prior to executing the shader */ |
||||
static INLINE void |
||||
tgsi_set_exec_mask(struct tgsi_exec_machine *mach, |
||||
boolean ch0, boolean ch1, boolean ch2, boolean ch3) |
||||
{ |
||||
int *mask = mach->Temps[TGSI_EXEC_MASK_I].xyzw[TGSI_EXEC_MASK_C].i; |
||||
mask[0] = ch0 ? ~0 : 0; |
||||
mask[1] = ch1 ? ~0 : 0; |
||||
mask[2] = ch2 ? ~0 : 0; |
||||
mask[3] = ch3 ? ~0 : 0; |
||||
} |
||||
|
||||
|
||||
extern void |
||||
tgsi_exec_set_constant_buffers(struct tgsi_exec_machine *mach, |
||||
unsigned num_bufs, |
||||
const void **bufs, |
||||
const unsigned *buf_sizes); |
||||
|
||||
|
||||
static INLINE int |
||||
tgsi_exec_get_shader_param(enum pipe_shader_cap param) |
||||
{ |
||||
switch(param) { |
||||
case PIPE_SHADER_CAP_MAX_INSTRUCTIONS: |
||||
case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS: |
||||
case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS: |
||||
case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS: |
||||
return INT_MAX; |
||||
case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH: |
||||
return TGSI_EXEC_MAX_NESTING; |
||||
case PIPE_SHADER_CAP_MAX_INPUTS: |
||||
return TGSI_EXEC_MAX_INPUT_ATTRIBS; |
||||
case PIPE_SHADER_CAP_MAX_CONSTS: |
||||
return TGSI_EXEC_MAX_CONST_BUFFER; |
||||
case PIPE_SHADER_CAP_MAX_CONST_BUFFERS: |
||||
return PIPE_MAX_CONSTANT_BUFFERS; |
||||
case PIPE_SHADER_CAP_MAX_TEMPS: |
||||
return TGSI_EXEC_NUM_TEMPS; |
||||
case PIPE_SHADER_CAP_MAX_ADDRS: |
||||
return TGSI_EXEC_NUM_ADDRS; |
||||
case PIPE_SHADER_CAP_MAX_PREDS: |
||||
return TGSI_EXEC_NUM_PREDS; |
||||
case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED: |
||||
return 1; |
||||
case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR: |
||||
case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR: |
||||
case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR: |
||||
case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR: |
||||
return 1; |
||||
case PIPE_SHADER_CAP_SUBROUTINES: |
||||
return 1; |
||||
case PIPE_SHADER_CAP_INTEGERS: |
||||
return 1; |
||||
case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS: |
||||
return PIPE_MAX_SAMPLERS; |
||||
case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED: |
||||
return 1; |
||||
default: |
||||
return 0; |
||||
} |
||||
} |
||||
|
||||
#if defined __cplusplus |
||||
} /* extern "C" */ |
||||
#endif |
||||
|
||||
#endif /* TGSI_EXEC_H */ |
@ -0,0 +1,375 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* 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 "util/u_debug.h" |
||||
#include "util/u_memory.h" |
||||
#include "tgsi_info.h" |
||||
|
||||
#define NONE TGSI_OUTPUT_NONE |
||||
#define COMP TGSI_OUTPUT_COMPONENTWISE |
||||
#define REPL TGSI_OUTPUT_REPLICATE |
||||
#define CHAN TGSI_OUTPUT_CHAN_DEPENDENT |
||||
#define OTHR TGSI_OUTPUT_OTHER |
||||
|
||||
static const struct tgsi_opcode_info opcode_info[TGSI_OPCODE_LAST] = |
||||
{ |
||||
{ 1, 1, 0, 0, 0, 0, COMP, "ARL", TGSI_OPCODE_ARL }, |
||||
{ 1, 1, 0, 0, 0, 0, COMP, "MOV", TGSI_OPCODE_MOV }, |
||||
{ 1, 1, 0, 0, 0, 0, CHAN, "LIT", TGSI_OPCODE_LIT }, |
||||
{ 1, 1, 0, 0, 0, 0, REPL, "RCP", TGSI_OPCODE_RCP }, |
||||
{ 1, 1, 0, 0, 0, 0, REPL, "RSQ", TGSI_OPCODE_RSQ }, |
||||
{ 1, 1, 0, 0, 0, 0, CHAN, "EXP", TGSI_OPCODE_EXP }, |
||||
{ 1, 1, 0, 0, 0, 0, CHAN, "LOG", TGSI_OPCODE_LOG }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "MUL", TGSI_OPCODE_MUL }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "ADD", TGSI_OPCODE_ADD }, |
||||
{ 1, 2, 0, 0, 0, 0, REPL, "DP3", TGSI_OPCODE_DP3 }, |
||||
{ 1, 2, 0, 0, 0, 0, REPL, "DP4", TGSI_OPCODE_DP4 }, |
||||
{ 1, 2, 0, 0, 0, 0, CHAN, "DST", TGSI_OPCODE_DST }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "MIN", TGSI_OPCODE_MIN }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "MAX", TGSI_OPCODE_MAX }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "SLT", TGSI_OPCODE_SLT }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "SGE", TGSI_OPCODE_SGE }, |
||||
{ 1, 3, 0, 0, 0, 0, COMP, "MAD", TGSI_OPCODE_MAD }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "SUB", TGSI_OPCODE_SUB }, |
||||
{ 1, 3, 0, 0, 0, 0, COMP, "LRP", TGSI_OPCODE_LRP }, |
||||
{ 1, 3, 0, 0, 0, 0, COMP, "CND", TGSI_OPCODE_CND }, |
||||
{ 1, 1, 0, 0, 0, 0, REPL, "SQRT", TGSI_OPCODE_SQRT }, |
||||
{ 1, 3, 0, 0, 0, 0, REPL, "DP2A", TGSI_OPCODE_DP2A }, |
||||
{ 0, 0, 0, 0, 0, 0, NONE, "", 22 }, /* removed */ |
||||
{ 0, 0, 0, 0, 0, 0, NONE, "", 23 }, /* removed */ |
||||
{ 1, 1, 0, 0, 0, 0, COMP, "FRC", TGSI_OPCODE_FRC }, |
||||
{ 1, 3, 0, 0, 0, 0, COMP, "CLAMP", TGSI_OPCODE_CLAMP }, |
||||
{ 1, 1, 0, 0, 0, 0, COMP, "FLR", TGSI_OPCODE_FLR }, |
||||
{ 1, 1, 0, 0, 0, 0, COMP, "ROUND", TGSI_OPCODE_ROUND }, |
||||
{ 1, 1, 0, 0, 0, 0, REPL, "EX2", TGSI_OPCODE_EX2 }, |
||||
{ 1, 1, 0, 0, 0, 0, REPL, "LG2", TGSI_OPCODE_LG2 }, |
||||
{ 1, 2, 0, 0, 0, 0, REPL, "POW", TGSI_OPCODE_POW }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "XPD", TGSI_OPCODE_XPD }, |
||||
{ 0, 0, 0, 0, 0, 0, NONE, "", 32 }, /* removed */ |
||||
{ 1, 1, 0, 0, 0, 0, COMP, "ABS", TGSI_OPCODE_ABS }, |
||||
{ 1, 1, 0, 0, 0, 0, REPL, "RCC", TGSI_OPCODE_RCC }, |
||||
{ 1, 2, 0, 0, 0, 0, REPL, "DPH", TGSI_OPCODE_DPH }, |
||||
{ 1, 1, 0, 0, 0, 0, REPL, "COS", TGSI_OPCODE_COS }, |
||||
{ 1, 1, 0, 0, 0, 0, COMP, "DDX", TGSI_OPCODE_DDX }, |
||||
{ 1, 1, 0, 0, 0, 0, COMP, "DDY", TGSI_OPCODE_DDY }, |
||||
{ 0, 0, 0, 0, 0, 0, NONE, "KILL", TGSI_OPCODE_KILL }, |
||||
{ 1, 1, 0, 0, 0, 0, COMP, "PK2H", TGSI_OPCODE_PK2H }, |
||||
{ 1, 1, 0, 0, 0, 0, COMP, "PK2US", TGSI_OPCODE_PK2US }, |
||||
{ 1, 1, 0, 0, 0, 0, COMP, "PK4B", TGSI_OPCODE_PK4B }, |
||||
{ 1, 1, 0, 0, 0, 0, COMP, "PK4UB", TGSI_OPCODE_PK4UB }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "RFL", TGSI_OPCODE_RFL }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "SEQ", TGSI_OPCODE_SEQ }, |
||||
{ 1, 2, 0, 0, 0, 0, REPL, "SFL", TGSI_OPCODE_SFL }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "SGT", TGSI_OPCODE_SGT }, |
||||
{ 1, 1, 0, 0, 0, 0, REPL, "SIN", TGSI_OPCODE_SIN }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "SLE", TGSI_OPCODE_SLE }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "SNE", TGSI_OPCODE_SNE }, |
||||
{ 1, 2, 0, 0, 0, 0, REPL, "STR", TGSI_OPCODE_STR }, |
||||
{ 1, 2, 1, 0, 0, 0, OTHR, "TEX", TGSI_OPCODE_TEX }, |
||||
{ 1, 4, 1, 0, 0, 0, OTHR, "TXD", TGSI_OPCODE_TXD }, |
||||
{ 1, 2, 1, 0, 0, 0, OTHR, "TXP", TGSI_OPCODE_TXP }, |
||||
{ 1, 1, 0, 0, 0, 0, COMP, "UP2H", TGSI_OPCODE_UP2H }, |
||||
{ 1, 1, 0, 0, 0, 0, COMP, "UP2US", TGSI_OPCODE_UP2US }, |
||||
{ 1, 1, 0, 0, 0, 0, COMP, "UP4B", TGSI_OPCODE_UP4B }, |
||||
{ 1, 1, 0, 0, 0, 0, COMP, "UP4UB", TGSI_OPCODE_UP4UB }, |
||||
{ 1, 3, 0, 0, 0, 0, COMP, "X2D", TGSI_OPCODE_X2D }, |
||||
{ 1, 1, 0, 0, 0, 0, COMP, "ARA", TGSI_OPCODE_ARA }, |
||||
{ 1, 1, 0, 0, 0, 0, COMP, "ARR", TGSI_OPCODE_ARR }, |
||||
{ 0, 1, 0, 0, 0, 0, NONE, "BRA", TGSI_OPCODE_BRA }, |
||||
{ 0, 0, 0, 1, 0, 0, NONE, "CAL", TGSI_OPCODE_CAL }, |
||||
{ 0, 0, 0, 0, 0, 0, NONE, "RET", TGSI_OPCODE_RET }, |
||||
{ 1, 1, 0, 0, 0, 0, COMP, "SSG", TGSI_OPCODE_SSG }, |
||||
{ 1, 3, 0, 0, 0, 0, COMP, "CMP", TGSI_OPCODE_CMP }, |
||||
{ 1, 1, 0, 0, 0, 0, CHAN, "SCS", TGSI_OPCODE_SCS }, |
||||
{ 1, 2, 1, 0, 0, 0, OTHR, "TXB", TGSI_OPCODE_TXB }, |
||||
{ 1, 1, 0, 0, 0, 0, COMP, "NRM", TGSI_OPCODE_NRM }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "DIV", TGSI_OPCODE_DIV }, |
||||
{ 1, 2, 0, 0, 0, 0, REPL, "DP2", TGSI_OPCODE_DP2 }, |
||||
{ 1, 2, 1, 0, 0, 0, OTHR, "TXL", TGSI_OPCODE_TXL }, |
||||
{ 0, 0, 0, 0, 0, 0, NONE, "BRK", TGSI_OPCODE_BRK }, |
||||
{ 0, 1, 0, 1, 0, 1, NONE, "IF", TGSI_OPCODE_IF }, |
||||
{ 0, 1, 0, 1, 0, 1, NONE, "UIF", TGSI_OPCODE_UIF }, |
||||
{ 0, 1, 0, 0, 0, 1, NONE, "", 76 }, /* removed */ |
||||
{ 0, 0, 0, 1, 1, 1, NONE, "ELSE", TGSI_OPCODE_ELSE }, |
||||
{ 0, 0, 0, 0, 1, 0, NONE, "ENDIF", TGSI_OPCODE_ENDIF }, |
||||
{ 1, 0, 0, 0, 1, 0, NONE, "", 79 }, /* removed */ |
||||
{ 0, 0, 0, 0, 1, 0, NONE, "", 80 }, /* removed */ |
||||
{ 0, 1, 0, 0, 0, 0, NONE, "PUSHA", TGSI_OPCODE_PUSHA }, |
||||
{ 1, 0, 0, 0, 0, 0, NONE, "POPA", TGSI_OPCODE_POPA }, |
||||
{ 1, 1, 0, 0, 0, 0, COMP, "CEIL", TGSI_OPCODE_CEIL }, |
||||
{ 1, 1, 0, 0, 0, 0, COMP, "I2F", TGSI_OPCODE_I2F }, |
||||
{ 1, 1, 0, 0, 0, 0, COMP, "NOT", TGSI_OPCODE_NOT }, |
||||
{ 1, 1, 0, 0, 0, 0, COMP, "TRUNC", TGSI_OPCODE_TRUNC }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "SHL", TGSI_OPCODE_SHL }, |
||||
{ 0, 0, 0, 0, 0, 0, NONE, "", 88 }, /* removed */ |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "AND", TGSI_OPCODE_AND }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "OR", TGSI_OPCODE_OR }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "MOD", TGSI_OPCODE_MOD }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "XOR", TGSI_OPCODE_XOR }, |
||||
{ 1, 3, 0, 0, 0, 0, COMP, "SAD", TGSI_OPCODE_SAD }, |
||||
{ 1, 2, 1, 0, 0, 0, OTHR, "TXF", TGSI_OPCODE_TXF }, |
||||
{ 1, 2, 1, 0, 0, 0, OTHR, "TXQ", TGSI_OPCODE_TXQ }, |
||||
{ 0, 0, 0, 0, 0, 0, NONE, "CONT", TGSI_OPCODE_CONT }, |
||||
{ 0, 0, 0, 0, 0, 0, NONE, "EMIT", TGSI_OPCODE_EMIT }, |
||||
{ 0, 0, 0, 0, 0, 0, NONE, "ENDPRIM", TGSI_OPCODE_ENDPRIM }, |
||||
{ 0, 0, 0, 1, 0, 1, NONE, "BGNLOOP", TGSI_OPCODE_BGNLOOP }, |
||||
{ 0, 0, 0, 0, 0, 1, NONE, "BGNSUB", TGSI_OPCODE_BGNSUB }, |
||||
{ 0, 0, 0, 1, 1, 0, NONE, "ENDLOOP", TGSI_OPCODE_ENDLOOP }, |
||||
{ 0, 0, 0, 0, 1, 0, NONE, "ENDSUB", TGSI_OPCODE_ENDSUB }, |
||||
{ 1, 1, 1, 0, 0, 0, OTHR, "TXQ_LZ", TGSI_OPCODE_TXQ_LZ }, |
||||
{ 0, 0, 0, 0, 0, 0, NONE, "", 104 }, /* removed */ |
||||
{ 0, 0, 0, 0, 0, 0, NONE, "", 105 }, /* removed */ |
||||
{ 0, 0, 0, 0, 0, 0, NONE, "", 106 }, /* removed */ |
||||
{ 0, 0, 0, 0, 0, 0, NONE, "NOP", TGSI_OPCODE_NOP }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "FSEQ", TGSI_OPCODE_FSEQ }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "FSGE", TGSI_OPCODE_FSGE }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "FSLT", TGSI_OPCODE_FSLT }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "FSNE", TGSI_OPCODE_FSNE }, |
||||
{ 1, 1, 0, 0, 0, 0, REPL, "NRM4", TGSI_OPCODE_NRM4 }, |
||||
{ 0, 1, 0, 0, 0, 0, NONE, "CALLNZ", TGSI_OPCODE_CALLNZ }, |
||||
{ 0, 1, 0, 0, 0, 0, NONE, "", 114 }, /* removed */ |
||||
{ 0, 1, 0, 0, 0, 0, NONE, "BREAKC", TGSI_OPCODE_BREAKC }, |
||||
{ 0, 1, 0, 0, 0, 0, NONE, "KILL_IF", TGSI_OPCODE_KILL_IF }, |
||||
{ 0, 0, 0, 0, 0, 0, NONE, "END", TGSI_OPCODE_END }, |
||||
{ 0, 0, 0, 0, 0, 0, NONE, "", 118 }, /* removed */ |
||||
{ 1, 1, 0, 0, 0, 0, COMP, "F2I", TGSI_OPCODE_F2I }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "IDIV", TGSI_OPCODE_IDIV }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "IMAX", TGSI_OPCODE_IMAX }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "IMIN", TGSI_OPCODE_IMIN }, |
||||
{ 1, 1, 0, 0, 0, 0, COMP, "INEG", TGSI_OPCODE_INEG }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "ISGE", TGSI_OPCODE_ISGE }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "ISHR", TGSI_OPCODE_ISHR }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "ISLT", TGSI_OPCODE_ISLT }, |
||||
{ 1, 1, 0, 0, 0, 0, COMP, "F2U", TGSI_OPCODE_F2U }, |
||||
{ 1, 1, 0, 0, 0, 0, COMP, "U2F", TGSI_OPCODE_U2F }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "UADD", TGSI_OPCODE_UADD }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "UDIV", TGSI_OPCODE_UDIV }, |
||||
{ 1, 3, 0, 0, 0, 0, COMP, "UMAD", TGSI_OPCODE_UMAD }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "UMAX", TGSI_OPCODE_UMAX }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "UMIN", TGSI_OPCODE_UMIN }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "UMOD", TGSI_OPCODE_UMOD }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "UMUL", TGSI_OPCODE_UMUL }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "USEQ", TGSI_OPCODE_USEQ }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "USGE", TGSI_OPCODE_USGE }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "USHR", TGSI_OPCODE_USHR }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "USLT", TGSI_OPCODE_USLT }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "USNE", TGSI_OPCODE_USNE }, |
||||
{ 0, 1, 0, 0, 0, 0, NONE, "SWITCH", TGSI_OPCODE_SWITCH }, |
||||
{ 0, 1, 0, 0, 0, 0, NONE, "CASE", TGSI_OPCODE_CASE }, |
||||
{ 0, 0, 0, 0, 0, 0, NONE, "DEFAULT", TGSI_OPCODE_DEFAULT }, |
||||
{ 0, 0, 0, 0, 0, 0, NONE, "ENDSWITCH", TGSI_OPCODE_ENDSWITCH }, |
||||
|
||||
{ 1, 3, 0, 0, 0, 0, OTHR, "SAMPLE", TGSI_OPCODE_SAMPLE }, |
||||
{ 1, 2, 0, 0, 0, 0, OTHR, "SAMPLE_I", TGSI_OPCODE_SAMPLE_I }, |
||||
{ 1, 3, 0, 0, 0, 0, OTHR, "SAMPLE_I_MS", TGSI_OPCODE_SAMPLE_I_MS }, |
||||
{ 1, 4, 0, 0, 0, 0, OTHR, "SAMPLE_B", TGSI_OPCODE_SAMPLE_B }, |
||||
{ 1, 4, 0, 0, 0, 0, OTHR, "SAMPLE_C", TGSI_OPCODE_SAMPLE_C }, |
||||
{ 1, 4, 0, 0, 0, 0, OTHR, "SAMPLE_C_LZ", TGSI_OPCODE_SAMPLE_C_LZ }, |
||||
{ 1, 5, 0, 0, 0, 0, OTHR, "SAMPLE_D", TGSI_OPCODE_SAMPLE_D }, |
||||
{ 1, 4, 0, 0, 0, 0, OTHR, "SAMPLE_L", TGSI_OPCODE_SAMPLE_L }, |
||||
{ 1, 3, 0, 0, 0, 0, OTHR, "GATHER4", TGSI_OPCODE_GATHER4 }, |
||||
{ 1, 2, 0, 0, 0, 0, OTHR, "SVIEWINFO", TGSI_OPCODE_SVIEWINFO }, |
||||
{ 1, 2, 0, 0, 0, 0, OTHR, "SAMPLE_POS", TGSI_OPCODE_SAMPLE_POS }, |
||||
{ 1, 2, 0, 0, 0, 0, OTHR, "SAMPLE_INFO", TGSI_OPCODE_SAMPLE_INFO }, |
||||
{ 1, 1, 0, 0, 0, 0, COMP, "UARL", TGSI_OPCODE_UARL }, |
||||
{ 1, 3, 0, 0, 0, 0, COMP, "UCMP", TGSI_OPCODE_UCMP }, |
||||
{ 1, 1, 0, 0, 0, 0, COMP, "IABS", TGSI_OPCODE_IABS }, |
||||
{ 1, 1, 0, 0, 0, 0, COMP, "ISSG", TGSI_OPCODE_ISSG }, |
||||
{ 1, 2, 0, 0, 0, 0, OTHR, "LOAD", TGSI_OPCODE_LOAD }, |
||||
{ 1, 2, 0, 0, 0, 0, OTHR, "STORE", TGSI_OPCODE_STORE }, |
||||
{ 1, 0, 0, 0, 0, 0, OTHR, "MFENCE", TGSI_OPCODE_MFENCE }, |
||||
{ 1, 0, 0, 0, 0, 0, OTHR, "LFENCE", TGSI_OPCODE_LFENCE }, |
||||
{ 1, 0, 0, 0, 0, 0, OTHR, "SFENCE", TGSI_OPCODE_SFENCE }, |
||||
{ 0, 0, 0, 0, 0, 0, OTHR, "BARRIER", TGSI_OPCODE_BARRIER }, |
||||
|
||||
{ 1, 3, 0, 0, 0, 0, OTHR, "ATOMUADD", TGSI_OPCODE_ATOMUADD }, |
||||
{ 1, 3, 0, 0, 0, 0, OTHR, "ATOMXCHG", TGSI_OPCODE_ATOMXCHG }, |
||||
{ 1, 4, 0, 0, 0, 0, OTHR, "ATOMCAS", TGSI_OPCODE_ATOMCAS }, |
||||
{ 1, 3, 0, 0, 0, 0, OTHR, "ATOMAND", TGSI_OPCODE_ATOMAND }, |
||||
{ 1, 3, 0, 0, 0, 0, OTHR, "ATOMOR", TGSI_OPCODE_ATOMOR }, |
||||
{ 1, 3, 0, 0, 0, 0, OTHR, "ATOMXOR", TGSI_OPCODE_ATOMXOR }, |
||||
{ 1, 3, 0, 0, 0, 0, OTHR, "ATOMUMIN", TGSI_OPCODE_ATOMUMIN }, |
||||
{ 1, 3, 0, 0, 0, 0, OTHR, "ATOMUMAX", TGSI_OPCODE_ATOMUMAX }, |
||||
{ 1, 3, 0, 0, 0, 0, OTHR, "ATOMIMIN", TGSI_OPCODE_ATOMIMIN }, |
||||
{ 1, 3, 0, 0, 0, 0, OTHR, "ATOMIMAX", TGSI_OPCODE_ATOMIMAX }, |
||||
{ 1, 3, 1, 0, 0, 0, OTHR, "TEX2", TGSI_OPCODE_TEX2 }, |
||||
{ 1, 3, 1, 0, 0, 0, OTHR, "TXB2", TGSI_OPCODE_TXB2 }, |
||||
{ 1, 3, 1, 0, 0, 0, OTHR, "TXL2", TGSI_OPCODE_TXL2 }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "IMUL_HI", TGSI_OPCODE_IMUL_HI }, |
||||
{ 1, 2, 0, 0, 0, 0, COMP, "UMUL_HI", TGSI_OPCODE_UMUL_HI }, |
||||
{ 1, 3, 1, 0, 0, 0, OTHR, "TG4", TGSI_OPCODE_TG4 }, |
||||
}; |
||||
|
||||
const struct tgsi_opcode_info * |
||||
tgsi_get_opcode_info( uint opcode ) |
||||
{ |
||||
static boolean firsttime = 1; |
||||
|
||||
if (firsttime) { |
||||
unsigned i; |
||||
firsttime = 0; |
||||
for (i = 0; i < Elements(opcode_info); i++) |
||||
assert(opcode_info[i].opcode == i); |
||||
} |
||||
|
||||
if (opcode < TGSI_OPCODE_LAST) |
||||
return &opcode_info[opcode]; |
||||
|
||||
assert( 0 ); |
||||
return NULL; |
||||
} |
||||
|
||||
|
||||
const char * |
||||
tgsi_get_opcode_name( uint opcode ) |
||||
{ |
||||
const struct tgsi_opcode_info *info = tgsi_get_opcode_info(opcode); |
||||
return info->mnemonic; |
||||
} |
||||
|
||||
|
||||
const char * |
||||
tgsi_get_processor_name( uint processor ) |
||||
{ |
||||
switch (processor) { |
||||
case TGSI_PROCESSOR_VERTEX: |
||||
return "vertex shader"; |
||||
case TGSI_PROCESSOR_FRAGMENT: |
||||
return "fragment shader"; |
||||
case TGSI_PROCESSOR_GEOMETRY: |
||||
return "geometry shader"; |
||||
default: |
||||
return "unknown shader type!"; |
||||
} |
||||
} |
||||
|
||||
/**
|
||||
* Infer the type (of the dst) of the opcode. |
||||
* |
||||
* MOV and UCMP is special so return VOID |
||||
*/ |
||||
static INLINE enum tgsi_opcode_type |
||||
tgsi_opcode_infer_type( uint opcode ) |
||||
{ |
||||
switch (opcode) { |
||||
case TGSI_OPCODE_MOV: |
||||
case TGSI_OPCODE_UCMP: |
||||
return TGSI_TYPE_UNTYPED; |
||||
case TGSI_OPCODE_NOT: |
||||
case TGSI_OPCODE_SHL: |
||||
case TGSI_OPCODE_AND: |
||||
case TGSI_OPCODE_OR: |
||||
case TGSI_OPCODE_XOR: |
||||
case TGSI_OPCODE_SAD: /* XXX some src args may be signed for SAD ? */ |
||||
case TGSI_OPCODE_TXQ: |
||||
case TGSI_OPCODE_TXQ_LZ: |
||||
case TGSI_OPCODE_F2U: |
||||
case TGSI_OPCODE_UDIV: |
||||
case TGSI_OPCODE_UMAD: |
||||
case TGSI_OPCODE_UMAX: |
||||
case TGSI_OPCODE_UMIN: |
||||
case TGSI_OPCODE_UMOD: |
||||
case TGSI_OPCODE_UMUL: |
||||
case TGSI_OPCODE_USEQ: |
||||
case TGSI_OPCODE_USGE: |
||||
case TGSI_OPCODE_USHR: |
||||
case TGSI_OPCODE_USLT: |
||||
case TGSI_OPCODE_USNE: |
||||
case TGSI_OPCODE_SVIEWINFO: |
||||
case TGSI_OPCODE_UMUL_HI: |
||||
return TGSI_TYPE_UNSIGNED; |
||||
case TGSI_OPCODE_ARL: |
||||
case TGSI_OPCODE_ARR: |
||||
case TGSI_OPCODE_MOD: |
||||
case TGSI_OPCODE_F2I: |
||||
case TGSI_OPCODE_FSEQ: |
||||
case TGSI_OPCODE_FSGE: |
||||
case TGSI_OPCODE_FSLT: |
||||
case TGSI_OPCODE_FSNE: |
||||
case TGSI_OPCODE_IDIV: |
||||
case TGSI_OPCODE_IMAX: |
||||
case TGSI_OPCODE_IMIN: |
||||
case TGSI_OPCODE_INEG: |
||||
case TGSI_OPCODE_ISGE: |
||||
case TGSI_OPCODE_ISHR: |
||||
case TGSI_OPCODE_ISLT: |
||||
case TGSI_OPCODE_UADD: |
||||
case TGSI_OPCODE_UARL: |
||||
case TGSI_OPCODE_IABS: |
||||
case TGSI_OPCODE_ISSG: |
||||
case TGSI_OPCODE_IMUL_HI: |
||||
return TGSI_TYPE_SIGNED; |
||||
default: |
||||
return TGSI_TYPE_FLOAT; |
||||
} |
||||
} |
||||
|
||||
/*
|
||||
* infer the source type of a TGSI opcode. |
||||
*/ |
||||
enum tgsi_opcode_type |
||||
tgsi_opcode_infer_src_type( uint opcode ) |
||||
{ |
||||
switch (opcode) { |
||||
case TGSI_OPCODE_UIF: |
||||
case TGSI_OPCODE_TXF: |
||||
case TGSI_OPCODE_BREAKC: |
||||
case TGSI_OPCODE_U2F: |
||||
case TGSI_OPCODE_UADD: |
||||
case TGSI_OPCODE_SWITCH: |
||||
case TGSI_OPCODE_CASE: |
||||
case TGSI_OPCODE_SAMPLE_I: |
||||
case TGSI_OPCODE_SAMPLE_I_MS: |
||||
case TGSI_OPCODE_UMUL_HI: |
||||
return TGSI_TYPE_UNSIGNED; |
||||
case TGSI_OPCODE_IMUL_HI: |
||||
case TGSI_OPCODE_I2F: |
||||
return TGSI_TYPE_SIGNED; |
||||
case TGSI_OPCODE_ARL: |
||||
case TGSI_OPCODE_ARR: |
||||
case TGSI_OPCODE_TXQ_LZ: |
||||
case TGSI_OPCODE_F2I: |
||||
case TGSI_OPCODE_F2U: |
||||
case TGSI_OPCODE_FSEQ: |
||||
case TGSI_OPCODE_FSGE: |
||||
case TGSI_OPCODE_FSLT: |
||||
case TGSI_OPCODE_FSNE: |
||||
case TGSI_OPCODE_UCMP: |
||||
return TGSI_TYPE_FLOAT; |
||||
default: |
||||
return tgsi_opcode_infer_type(opcode); |
||||
} |
||||
} |
||||
|
||||
/*
|
||||
* infer the destination type of a TGSI opcode. |
||||
*/ |
||||
enum tgsi_opcode_type |
||||
tgsi_opcode_infer_dst_type( uint opcode ) |
||||
{ |
||||
return tgsi_opcode_infer_type(opcode); |
||||
} |
@ -0,0 +1,113 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* 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 TGSI_INFO_H |
||||
#define TGSI_INFO_H |
||||
|
||||
#include "pipe/p_compiler.h" |
||||
#include "pipe/p_shader_tokens.h" |
||||
#include "util/u_format.h" |
||||
|
||||
#if defined __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/* This enum describes how an opcode calculates its result. */ |
||||
enum tgsi_output_mode { |
||||
/** The opcode produces no result. */ |
||||
TGSI_OUTPUT_NONE = 0, |
||||
|
||||
/** When this opcode writes to a channel of the destination register,
|
||||
* it takes as arguments values from the same channel of the source |
||||
* register(s). |
||||
* |
||||
* Example: TGSI_OPCODE_ADD |
||||
*/ |
||||
TGSI_OUTPUT_COMPONENTWISE = 1, |
||||
|
||||
/** This opcode writes the same value to all enabled channels of the
|
||||
* destination register. |
||||
* |
||||
* Example: TGSI_OPCODE_RSQ |
||||
*/ |
||||
TGSI_OUTPUT_REPLICATE = 2, |
||||
|
||||
/** The operation performed by this opcode is dependent on which channel
|
||||
* of the destination register is being written. |
||||
* |
||||
* Example: TGSI_OPCODE_LOG |
||||
*/ |
||||
TGSI_OUTPUT_CHAN_DEPENDENT = 3, |
||||
|
||||
/**
|
||||
* Example: TGSI_OPCODE_TEX |
||||
*/ |
||||
TGSI_OUTPUT_OTHER = 4 |
||||
}; |
||||
|
||||
struct tgsi_opcode_info |
||||
{ |
||||
unsigned num_dst:3; |
||||
unsigned num_src:3; |
||||
unsigned is_tex:1; |
||||
unsigned is_branch:1; |
||||
int pre_dedent:2; |
||||
int post_indent:2; |
||||
enum tgsi_output_mode output_mode:3; |
||||
const char *mnemonic; |
||||
uint opcode; |
||||
}; |
||||
|
||||
const struct tgsi_opcode_info * |
||||
tgsi_get_opcode_info( uint opcode ); |
||||
|
||||
const char * |
||||
tgsi_get_opcode_name( uint opcode ); |
||||
|
||||
const char * |
||||
tgsi_get_processor_name( uint processor ); |
||||
|
||||
enum tgsi_opcode_type { |
||||
TGSI_TYPE_UNTYPED, /* for MOV */ |
||||
TGSI_TYPE_VOID, |
||||
TGSI_TYPE_UNSIGNED, |
||||
TGSI_TYPE_SIGNED, |
||||
TGSI_TYPE_FLOAT, |
||||
TGSI_TYPE_DOUBLE |
||||
}; |
||||
|
||||
enum tgsi_opcode_type |
||||
tgsi_opcode_infer_src_type( uint opcode ); |
||||
|
||||
enum tgsi_opcode_type |
||||
tgsi_opcode_infer_dst_type( uint opcode ); |
||||
|
||||
#if defined __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* TGSI_INFO_H */ |
@ -0,0 +1,90 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* 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 "util/u_debug.h" |
||||
#include "tgsi_iterate.h" |
||||
|
||||
boolean |
||||
tgsi_iterate_shader( |
||||
const struct tgsi_token *tokens, |
||||
struct tgsi_iterate_context *ctx ) |
||||
{ |
||||
struct tgsi_parse_context parse; |
||||
|
||||
if (tgsi_parse_init( &parse, tokens ) != TGSI_PARSE_OK) |
||||
return FALSE; |
||||
|
||||
ctx->processor = parse.FullHeader.Processor; |
||||
|
||||
if (ctx->prolog) |
||||
if (!ctx->prolog( ctx )) |
||||
goto fail; |
||||
|
||||
while (!tgsi_parse_end_of_tokens( &parse )) { |
||||
tgsi_parse_token( &parse ); |
||||
|
||||
switch (parse.FullToken.Token.Type) { |
||||
case TGSI_TOKEN_TYPE_INSTRUCTION: |
||||
if (ctx->iterate_instruction) |
||||
if (!ctx->iterate_instruction( ctx, &parse.FullToken.FullInstruction )) |
||||
goto fail; |
||||
break; |
||||
|
||||
case TGSI_TOKEN_TYPE_DECLARATION: |
||||
if (ctx->iterate_declaration) |
||||
if (!ctx->iterate_declaration( ctx, &parse.FullToken.FullDeclaration )) |
||||
goto fail; |
||||
break; |
||||
|
||||
case TGSI_TOKEN_TYPE_IMMEDIATE: |
||||
if (ctx->iterate_immediate) |
||||
if (!ctx->iterate_immediate( ctx, &parse.FullToken.FullImmediate )) |
||||
goto fail; |
||||
break; |
||||
|
||||
case TGSI_TOKEN_TYPE_PROPERTY: |
||||
if (ctx->iterate_property) |
||||
if (!ctx->iterate_property( ctx, &parse.FullToken.FullProperty )) |
||||
goto fail; |
||||
break; |
||||
|
||||
default: |
||||
assert( 0 ); |
||||
} |
||||
} |
||||
|
||||
if (ctx->epilog) |
||||
if (!ctx->epilog( ctx )) |
||||
goto fail; |
||||
|
||||
tgsi_parse_free( &parse ); |
||||
return TRUE; |
||||
|
||||
fail: |
||||
tgsi_parse_free( &parse ); |
||||
return FALSE; |
||||
} |
@ -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. |
||||
*
|
||||
**************************************************************************/ |
||||
|
||||
#ifndef TGSI_ITERATE_H |
||||
#define TGSI_ITERATE_H |
||||
|
||||
#include "pipe/p_shader_tokens.h" |
||||
#include "tgsi/tgsi_parse.h" |
||||
|
||||
#if defined __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
struct tgsi_iterate_context |
||||
{ |
||||
boolean |
||||
(* prolog)( |
||||
struct tgsi_iterate_context *ctx ); |
||||
|
||||
boolean |
||||
(* iterate_instruction)( |
||||
struct tgsi_iterate_context *ctx, |
||||
struct tgsi_full_instruction *inst ); |
||||
|
||||
boolean |
||||
(* iterate_declaration)( |
||||
struct tgsi_iterate_context *ctx, |
||||
struct tgsi_full_declaration *decl ); |
||||
|
||||
boolean |
||||
(* iterate_immediate)( |
||||
struct tgsi_iterate_context *ctx, |
||||
struct tgsi_full_immediate *imm ); |
||||
|
||||
boolean |
||||
(* iterate_property)( |
||||
struct tgsi_iterate_context *ctx, |
||||
struct tgsi_full_property *prop ); |
||||
|
||||
boolean |
||||
(* epilog)( |
||||
struct tgsi_iterate_context *ctx ); |
||||
|
||||
struct tgsi_processor processor; |
||||
}; |
||||
|
||||
boolean |
||||
tgsi_iterate_shader( |
||||
const struct tgsi_token *tokens, |
||||
struct tgsi_iterate_context *ctx ); |
||||
|
||||
#if defined __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* TGSI_ITERATE_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 OP12_TEX |
||||
#define OP12_TEX(a) OP12(a) |
||||
#endif |
||||
|
||||
#ifndef OP14_TEX |
||||
#define OP14_TEX(a) OP14(a) |
||||
#endif |
||||
|
||||
#ifndef OP12_SAMPLE |
||||
#define OP12_SAMPLE(a) OP12(a) |
||||
#endif |
||||
|
||||
#ifndef OP13_SAMPLE |
||||
#define OP13_SAMPLE(a) OP13(a) |
||||
#endif |
||||
|
||||
#ifndef OP14_SAMPLE |
||||
#define OP14_SAMPLE(a) OP14(a) |
||||
#endif |
||||
|
||||
#ifndef OP15_SAMPLE |
||||
#define OP15_SAMPLE(a) OP15(a) |
||||
#endif |
||||
|
||||
#ifndef OP00_LBL |
||||
#define OP00_LBL(a) OP00(a) |
||||
#endif |
||||
|
||||
#ifndef OP01_LBL |
||||
#define OP01_LBL(a) OP01(a) |
||||
#endif |
||||
|
||||
OP11(ARL) |
||||
OP11(MOV) |
||||
OP11(LIT) |
||||
OP11(RCP) |
||||
OP11(RSQ) |
||||
OP11(EXP) |
||||
OP11(LOG) |
||||
OP12(MUL) |
||||
OP12(ADD) |
||||
OP12(DP3) |
||||
OP12(DP4) |
||||
OP12(DST) |
||||
OP12(MIN) |
||||
OP12(MAX) |
||||
OP12(SLT) |
||||
OP12(SGE) |
||||
OP13(MAD) |
||||
OP12(SUB) |
||||
OP13(LRP) |
||||
OP13(CND) |
||||
OP11(SQRT) |
||||
OP13(DP2A) |
||||
OP11(FRC) |
||||
OP13(CLAMP) |
||||
OP11(FLR) |
||||
OP11(ROUND) |
||||
OP11(EX2) |
||||
OP11(LG2) |
||||
OP12(POW) |
||||
OP12(XPD) |
||||
OP11(ABS) |
||||
OP11(RCC) |
||||
OP12(DPH) |
||||
OP11(COS) |
||||
OP11(DDX) |
||||
OP11(DDY) |
||||
OP00(KILL) |
||||
OP11(PK2H) |
||||
OP11(PK2US) |
||||
OP11(PK4B) |
||||
OP11(PK4UB) |
||||
OP12(RFL) |
||||
OP12(SEQ) |
||||
OP12(SFL) |
||||
OP12(SGT) |
||||
OP11(SIN) |
||||
OP12(SLE) |
||||
OP12(SNE) |
||||
OP12(STR) |
||||
OP12_TEX(TEX) |
||||
OP14_TEX(TXD) |
||||
OP12_TEX(TXP) |
||||
OP11(UP2H) |
||||
OP11(UP2US) |
||||
OP11(UP4B) |
||||
OP11(UP4UB) |
||||
OP13(X2D) |
||||
OP11(ARA) |
||||
OP11(ARR) |
||||
OP01(BRA) |
||||
OP00_LBL(CAL) |
||||
OP00(RET) |
||||
OP11(SSG) |
||||
OP13(CMP) |
||||
OP11(SCS) |
||||
OP12_TEX(TXB) |
||||
OP11(NRM) |
||||
OP12(DIV) |
||||
OP12(DP2) |
||||
OP12_TEX(TXL) |
||||
OP00(BRK) |
||||
OP01_LBL(IF) |
||||
OP01_LBL(UIF) |
||||
OP00_LBL(ELSE) |
||||
OP00(ENDIF) |
||||
OP01(PUSHA) |
||||
OP10(POPA) |
||||
OP11(CEIL) |
||||
OP11(I2F) |
||||
OP11(NOT) |
||||
OP11(TRUNC) |
||||
OP12(SHL) |
||||
OP12(AND) |
||||
OP12(OR) |
||||
OP12(MOD) |
||||
OP12(XOR) |
||||
OP13(SAD) |
||||
OP12_TEX(TXF) |
||||
OP12_TEX(TXQ) |
||||
OP00(CONT) |
||||
OP00(EMIT) |
||||
OP00(ENDPRIM) |
||||
OP00_LBL(BGNLOOP) |
||||
OP00(BGNSUB) |
||||
OP00_LBL(ENDLOOP) |
||||
OP00(ENDSUB) |
||||
OP00(NOP) |
||||
OP11(NRM4) |
||||
OP01(CALLNZ) |
||||
OP01(BREAKC) |
||||
OP01(KILL_IF) |
||||
OP00(END) |
||||
OP11(F2I) |
||||
OP12(FSEQ) |
||||
OP12(FSGE) |
||||
OP12(FSLT) |
||||
OP12(FSNE) |
||||
OP12(IDIV) |
||||
OP12(IMAX) |
||||
OP12(IMIN) |
||||
OP11(INEG) |
||||
OP12(ISGE) |
||||
OP12(ISHR) |
||||
OP12(ISLT) |
||||
OP11(F2U) |
||||
OP11(U2F) |
||||
OP12(UADD) |
||||
OP12(UDIV) |
||||
OP13(UMAD) |
||||
OP12(UMAX) |
||||
OP12(UMIN) |
||||
OP12(UMOD) |
||||
OP12(UMUL) |
||||
OP12(USEQ) |
||||
OP12(USGE) |
||||
OP12(USHR) |
||||
OP12(USLT) |
||||
OP12(USNE) |
||||
OP01(SWITCH) |
||||
OP01(CASE) |
||||
OP00(DEFAULT) |
||||
OP00(ENDSWITCH) |
||||
|
||||
OP13_SAMPLE(SAMPLE) |
||||
OP12_SAMPLE(SAMPLE_I) |
||||
OP13_SAMPLE(SAMPLE_I_MS) |
||||
OP14_SAMPLE(SAMPLE_B) |
||||
OP14_SAMPLE(SAMPLE_C) |
||||
OP14_SAMPLE(SAMPLE_C_LZ) |
||||
OP15_SAMPLE(SAMPLE_D) |
||||
OP14_SAMPLE(SAMPLE_L) |
||||
OP13_SAMPLE(GATHER4) |
||||
OP12(SVIEWINFO) |
||||
OP13(SAMPLE_POS) |
||||
OP12(SAMPLE_INFO) |
||||
|
||||
OP13(UCMP) |
||||
|
||||
OP12(IMUL_HI) |
||||
OP12(UMUL_HI) |
||||
|
||||
#undef OP00 |
||||
#undef OP01 |
||||
#undef OP10 |
||||
#undef OP11 |
||||
#undef OP12 |
||||
#undef OP13 |
||||
|
||||
#ifdef OP14 |
||||
#undef OP14 |
||||
#endif |
||||
|
||||
#ifdef OP15 |
||||
#undef OP15 |
||||
#endif |
||||
|
||||
#undef OP00_LBL |
||||
#undef OP01_LBL |
||||
|
||||
#undef OP12_TEX |
||||
#undef OP14_TEX |
||||
|
||||
#undef OP12_SAMPLE |
||||
#undef OP13_SAMPLE |
||||
#undef OP14_SAMPLE |
||||
#undef OP15_SAMPLE |
@ -0,0 +1,307 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 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 "util/u_debug.h" |
||||
#include "pipe/p_shader_tokens.h" |
||||
#include "tgsi_parse.h" |
||||
#include "util/u_memory.h" |
||||
|
||||
unsigned |
||||
tgsi_parse_init( |
||||
struct tgsi_parse_context *ctx, |
||||
const struct tgsi_token *tokens ) |
||||
{ |
||||
ctx->FullHeader.Header = *(struct tgsi_header *) &tokens[0]; |
||||
if( ctx->FullHeader.Header.HeaderSize >= 2 ) { |
||||
ctx->FullHeader.Processor = *(struct tgsi_processor *) &tokens[1]; |
||||
} |
||||
else { |
||||
return TGSI_PARSE_ERROR; |
||||
} |
||||
|
||||
ctx->Tokens = tokens; |
||||
ctx->Position = ctx->FullHeader.Header.HeaderSize; |
||||
|
||||
return TGSI_PARSE_OK; |
||||
} |
||||
|
||||
void |
||||
tgsi_parse_free( |
||||
struct tgsi_parse_context *ctx ) |
||||
{ |
||||
} |
||||
|
||||
boolean |
||||
tgsi_parse_end_of_tokens( |
||||
struct tgsi_parse_context *ctx ) |
||||
{ |
||||
return ctx->Position >= |
||||
ctx->FullHeader.Header.HeaderSize + ctx->FullHeader.Header.BodySize; |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* This function is used to avoid and work-around type punning/aliasing |
||||
* warnings. The warnings seem harmless on x86 but on PPC they cause |
||||
* real failures. |
||||
*/ |
||||
static INLINE void |
||||
copy_token(void *dst, const void *src) |
||||
{ |
||||
memcpy(dst, src, 4); |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Get next 4-byte token, return it at address specified by 'token' |
||||
*/ |
||||
static void |
||||
next_token( |
||||
struct tgsi_parse_context *ctx, |
||||
void *token ) |
||||
{ |
||||
assert( !tgsi_parse_end_of_tokens( ctx ) ); |
||||
copy_token(token, &ctx->Tokens[ctx->Position]); |
||||
ctx->Position++; |
||||
} |
||||
|
||||
|
||||
void |
||||
tgsi_parse_token( |
||||
struct tgsi_parse_context *ctx ) |
||||
{ |
||||
struct tgsi_token token; |
||||
unsigned i; |
||||
|
||||
next_token( ctx, &token ); |
||||
|
||||
switch( token.Type ) { |
||||
case TGSI_TOKEN_TYPE_DECLARATION: |
||||
{ |
||||
struct tgsi_full_declaration *decl = &ctx->FullToken.FullDeclaration; |
||||
|
||||
memset(decl, 0, sizeof *decl); |
||||
copy_token(&decl->Declaration, &token); |
||||
|
||||
next_token( ctx, &decl->Range ); |
||||
|
||||
if (decl->Declaration.Dimension) { |
||||
next_token(ctx, &decl->Dim); |
||||
} |
||||
|
||||
if( decl->Declaration.Interpolate ) { |
||||
next_token( ctx, &decl->Interp ); |
||||
} |
||||
|
||||
if( decl->Declaration.Semantic ) { |
||||
next_token( ctx, &decl->Semantic ); |
||||
} |
||||
|
||||
if (decl->Declaration.File == TGSI_FILE_RESOURCE) { |
||||
next_token(ctx, &decl->Resource); |
||||
} |
||||
|
||||
if (decl->Declaration.File == TGSI_FILE_SAMPLER_VIEW) { |
||||
next_token(ctx, &decl->SamplerView); |
||||
} |
||||
|
||||
if( decl->Declaration.Array ) { |
||||
next_token(ctx, &decl->Array); |
||||
} |
||||
|
||||
break; |
||||
} |
||||
|
||||
case TGSI_TOKEN_TYPE_IMMEDIATE: |
||||
{ |
||||
struct tgsi_full_immediate *imm = &ctx->FullToken.FullImmediate; |
||||
uint imm_count; |
||||
|
||||
memset(imm, 0, sizeof *imm); |
||||
copy_token(&imm->Immediate, &token); |
||||
|
||||
imm_count = imm->Immediate.NrTokens - 1; |
||||
|
||||
switch (imm->Immediate.DataType) { |
||||
case TGSI_IMM_FLOAT32: |
||||
for (i = 0; i < imm_count; i++) { |
||||
next_token(ctx, &imm->u[i].Float); |
||||
} |
||||
break; |
||||
|
||||
case TGSI_IMM_UINT32: |
||||
for (i = 0; i < imm_count; i++) { |
||||
next_token(ctx, &imm->u[i].Uint); |
||||
} |
||||
break; |
||||
|
||||
case TGSI_IMM_INT32: |
||||
for (i = 0; i < imm_count; i++) { |
||||
next_token(ctx, &imm->u[i].Int); |
||||
} |
||||
break; |
||||
|
||||
default: |
||||
assert( 0 ); |
||||
} |
||||
|
||||
break; |
||||
} |
||||
|
||||
case TGSI_TOKEN_TYPE_INSTRUCTION: |
||||
{ |
||||
struct tgsi_full_instruction *inst = &ctx->FullToken.FullInstruction; |
||||
|
||||
memset(inst, 0, sizeof *inst); |
||||
copy_token(&inst->Instruction, &token); |
||||
|
||||
if (inst->Instruction.Predicate) { |
||||
next_token(ctx, &inst->Predicate); |
||||
} |
||||
|
||||
if (inst->Instruction.Label) { |
||||
next_token( ctx, &inst->Label); |
||||
} |
||||
|
||||
if (inst->Instruction.Texture) { |
||||
next_token( ctx, &inst->Texture); |
||||
for( i = 0; i < inst->Texture.NumOffsets; i++ ) { |
||||
next_token( ctx, &inst->TexOffsets[i] ); |
||||
} |
||||
} |
||||
|
||||
assert( inst->Instruction.NumDstRegs <= TGSI_FULL_MAX_DST_REGISTERS ); |
||||
|
||||
for( i = 0; i < inst->Instruction.NumDstRegs; i++ ) { |
||||
|
||||
next_token( ctx, &inst->Dst[i].Register ); |
||||
|
||||
if( inst->Dst[i].Register.Indirect ) |
||||
next_token( ctx, &inst->Dst[i].Indirect ); |
||||
|
||||
if( inst->Dst[i].Register.Dimension ) { |
||||
next_token( ctx, &inst->Dst[i].Dimension ); |
||||
|
||||
/*
|
||||
* No support for multi-dimensional addressing. |
||||
*/ |
||||
assert( !inst->Dst[i].Dimension.Dimension ); |
||||
|
||||
if( inst->Dst[i].Dimension.Indirect ) |
||||
next_token( ctx, &inst->Dst[i].DimIndirect ); |
||||
} |
||||
} |
||||
|
||||
assert( inst->Instruction.NumSrcRegs <= TGSI_FULL_MAX_SRC_REGISTERS ); |
||||
|
||||
for( i = 0; i < inst->Instruction.NumSrcRegs; i++ ) { |
||||
|
||||
next_token( ctx, &inst->Src[i].Register ); |
||||
|
||||
if( inst->Src[i].Register.Indirect ) |
||||
next_token( ctx, &inst->Src[i].Indirect ); |
||||
|
||||
if( inst->Src[i].Register.Dimension ) { |
||||
next_token( ctx, &inst->Src[i].Dimension ); |
||||
|
||||
/*
|
||||
* No support for multi-dimensional addressing. |
||||
*/ |
||||
assert( !inst->Src[i].Dimension.Dimension ); |
||||
|
||||
if( inst->Src[i].Dimension.Indirect ) |
||||
next_token( ctx, &inst->Src[i].DimIndirect ); |
||||
} |
||||
} |
||||
|
||||
break; |
||||
} |
||||
|
||||
case TGSI_TOKEN_TYPE_PROPERTY: |
||||
{ |
||||
struct tgsi_full_property *prop = &ctx->FullToken.FullProperty; |
||||
uint prop_count; |
||||
|
||||
memset(prop, 0, sizeof *prop); |
||||
copy_token(&prop->Property, &token); |
||||
|
||||
prop_count = prop->Property.NrTokens - 1; |
||||
for (i = 0; i < prop_count; i++) { |
||||
next_token(ctx, &prop->u[i]); |
||||
} |
||||
|
||||
break; |
||||
} |
||||
|
||||
default: |
||||
assert( 0 ); |
||||
} |
||||
} |
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Make a new copy of a token array. |
||||
*/ |
||||
struct tgsi_token * |
||||
tgsi_dup_tokens(const struct tgsi_token *tokens) |
||||
{ |
||||
unsigned n = tgsi_num_tokens(tokens); |
||||
unsigned bytes = n * sizeof(struct tgsi_token); |
||||
struct tgsi_token *new_tokens = (struct tgsi_token *) MALLOC(bytes); |
||||
if (new_tokens) |
||||
memcpy(new_tokens, tokens, bytes); |
||||
return new_tokens; |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Allocate memory for num_tokens tokens. |
||||
*/ |
||||
struct tgsi_token * |
||||
tgsi_alloc_tokens(unsigned num_tokens) |
||||
{ |
||||
unsigned bytes = num_tokens * sizeof(struct tgsi_token); |
||||
return (struct tgsi_token *) MALLOC(bytes); |
||||
} |
||||
|
||||
|
||||
void |
||||
tgsi_dump_tokens(const struct tgsi_token *tokens) |
||||
{ |
||||
const unsigned *dwords = (const unsigned *)tokens; |
||||
int nr = tgsi_num_tokens(tokens); |
||||
int i; |
||||
|
||||
assert(sizeof(*tokens) == sizeof(unsigned)); |
||||
|
||||
debug_printf("const unsigned tokens[%d] = {\n", nr); |
||||
for (i = 0; i < nr; i++) |
||||
debug_printf("0x%08x,\n", dwords[i]); |
||||
debug_printf("};\n"); |
||||
} |
@ -0,0 +1,159 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 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 TGSI_PARSE_H |
||||
#define TGSI_PARSE_H |
||||
|
||||
#include "pipe/p_compiler.h" |
||||
#include "pipe/p_shader_tokens.h" |
||||
|
||||
#if defined __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
struct tgsi_full_header |
||||
{ |
||||
struct tgsi_header Header; |
||||
struct tgsi_processor Processor; |
||||
}; |
||||
|
||||
struct tgsi_full_dst_register |
||||
{ |
||||
struct tgsi_dst_register Register; |
||||
struct tgsi_ind_register Indirect; |
||||
struct tgsi_dimension Dimension; |
||||
struct tgsi_ind_register DimIndirect; |
||||
}; |
||||
|
||||
struct tgsi_full_src_register |
||||
{ |
||||
struct tgsi_src_register Register; |
||||
struct tgsi_ind_register Indirect; |
||||
struct tgsi_dimension Dimension; |
||||
struct tgsi_ind_register DimIndirect; |
||||
}; |
||||
|
||||
struct tgsi_full_declaration |
||||
{ |
||||
struct tgsi_declaration Declaration; |
||||
struct tgsi_declaration_range Range; |
||||
struct tgsi_declaration_dimension Dim; |
||||
struct tgsi_declaration_interp Interp; |
||||
struct tgsi_declaration_semantic Semantic; |
||||
struct tgsi_declaration_resource Resource; |
||||
struct tgsi_declaration_sampler_view SamplerView; |
||||
struct tgsi_declaration_array Array; |
||||
}; |
||||
|
||||
struct tgsi_full_immediate |
||||
{ |
||||
struct tgsi_immediate Immediate; |
||||
union tgsi_immediate_data u[4]; |
||||
}; |
||||
|
||||
struct tgsi_full_property |
||||
{ |
||||
struct tgsi_property Property; |
||||
struct tgsi_property_data u[8]; |
||||
}; |
||||
|
||||
#define TGSI_FULL_MAX_DST_REGISTERS 2 |
||||
#define TGSI_FULL_MAX_SRC_REGISTERS 5 /* SAMPLE_D has 5 */ |
||||
#define TGSI_FULL_MAX_TEX_OFFSETS 4 |
||||
|
||||
struct tgsi_full_instruction |
||||
{ |
||||
struct tgsi_instruction Instruction; |
||||
struct tgsi_instruction_predicate Predicate; |
||||
struct tgsi_instruction_label Label; |
||||
struct tgsi_instruction_texture Texture; |
||||
struct tgsi_full_dst_register Dst[TGSI_FULL_MAX_DST_REGISTERS]; |
||||
struct tgsi_full_src_register Src[TGSI_FULL_MAX_SRC_REGISTERS]; |
||||
struct tgsi_texture_offset TexOffsets[TGSI_FULL_MAX_TEX_OFFSETS]; |
||||
}; |
||||
|
||||
union tgsi_full_token |
||||
{ |
||||
struct tgsi_token Token; |
||||
struct tgsi_full_declaration FullDeclaration; |
||||
struct tgsi_full_immediate FullImmediate; |
||||
struct tgsi_full_instruction FullInstruction; |
||||
struct tgsi_full_property FullProperty; |
||||
}; |
||||
|
||||
struct tgsi_parse_context |
||||
{ |
||||
const struct tgsi_token *Tokens; |
||||
unsigned Position; |
||||
struct tgsi_full_header FullHeader; |
||||
union tgsi_full_token FullToken; |
||||
}; |
||||
|
||||
#define TGSI_PARSE_OK 0 |
||||
#define TGSI_PARSE_ERROR 1 |
||||
|
||||
unsigned |
||||
tgsi_parse_init( |
||||
struct tgsi_parse_context *ctx, |
||||
const struct tgsi_token *tokens ); |
||||
|
||||
void |
||||
tgsi_parse_free( |
||||
struct tgsi_parse_context *ctx ); |
||||
|
||||
boolean |
||||
tgsi_parse_end_of_tokens( |
||||
struct tgsi_parse_context *ctx ); |
||||
|
||||
void |
||||
tgsi_parse_token( |
||||
struct tgsi_parse_context *ctx ); |
||||
|
||||
static INLINE unsigned |
||||
tgsi_num_tokens(const struct tgsi_token *tokens) |
||||
{ |
||||
struct tgsi_header header; |
||||
memcpy(&header, tokens, sizeof(header)); |
||||
return header.HeaderSize + header.BodySize; |
||||
} |
||||
|
||||
void |
||||
tgsi_dump_tokens(const struct tgsi_token *tokens); |
||||
|
||||
struct tgsi_token * |
||||
tgsi_dup_tokens(const struct tgsi_token *tokens); |
||||
|
||||
struct tgsi_token * |
||||
tgsi_alloc_tokens(unsigned num_tokens); |
||||
|
||||
|
||||
#if defined __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* TGSI_PARSE_H */ |
||||
|
@ -0,0 +1,52 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* 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 TGSI_SANITY_H |
||||
#define TGSI_SANITY_H |
||||
|
||||
#if defined __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
#include "pipe/p_compiler.h" |
||||
|
||||
struct tgsi_token; |
||||
|
||||
/* Check the given token stream for errors and common mistakes.
|
||||
* Diagnostic messages are printed out to the debug output, and is |
||||
* controlled by the debug option TGSI_PRINT_SANITY (default false). |
||||
* Returns TRUE if there are no errors, even though there could be some warnings. |
||||
*/ |
||||
boolean |
||||
tgsi_sanity_check( |
||||
const struct tgsi_token *tokens ); |
||||
|
||||
#if defined __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* TGSI_SANITY_H */ |
@ -0,0 +1,409 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 VMware, Inc. |
||||
* All Rights Reserved. |
||||
* 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. |
||||
*
|
||||
**************************************************************************/ |
||||
|
||||
/**
|
||||
* TGSI program scan utility. |
||||
* Used to determine which registers and instructions are used by a shader. |
||||
* |
||||
* Authors: Brian Paul |
||||
*/ |
||||
|
||||
|
||||
#include "util/u_debug.h" |
||||
#include "util/u_math.h" |
||||
#include "util/u_memory.h" |
||||
#include "util/u_prim.h" |
||||
#include "tgsi/tgsi_parse.h" |
||||
#include "tgsi/tgsi_util.h" |
||||
#include "tgsi/tgsi_scan.h" |
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Scan the given TGSI shader to collect information such as number of |
||||
* registers used, special instructions used, etc. |
||||
* \return info the result of the scan |
||||
*/ |
||||
void |
||||
tgsi_scan_shader(const struct tgsi_token *tokens, |
||||
struct tgsi_shader_info *info) |
||||
{ |
||||
uint procType, i; |
||||
struct tgsi_parse_context parse; |
||||
|
||||
memset(info, 0, sizeof(*info)); |
||||
for (i = 0; i < TGSI_FILE_COUNT; i++) |
||||
info->file_max[i] = -1; |
||||
for (i = 0; i < Elements(info->const_file_max); i++) |
||||
info->const_file_max[i] = -1; |
||||
|
||||
/**
|
||||
** Setup to begin parsing input shader |
||||
**/ |
||||
if (tgsi_parse_init( &parse, tokens ) != TGSI_PARSE_OK) { |
||||
debug_printf("tgsi_parse_init() failed in tgsi_scan_shader()!\n"); |
||||
return; |
||||
} |
||||
procType = parse.FullHeader.Processor.Processor; |
||||
assert(procType == TGSI_PROCESSOR_FRAGMENT || |
||||
procType == TGSI_PROCESSOR_VERTEX || |
||||
procType == TGSI_PROCESSOR_GEOMETRY || |
||||
procType == TGSI_PROCESSOR_COMPUTE); |
||||
info->processor = procType; |
||||
|
||||
|
||||
/**
|
||||
** Loop over incoming program tokens/instructions |
||||
*/ |
||||
while( !tgsi_parse_end_of_tokens( &parse ) ) { |
||||
|
||||
info->num_tokens++; |
||||
|
||||
tgsi_parse_token( &parse ); |
||||
|
||||
switch( parse.FullToken.Token.Type ) { |
||||
case TGSI_TOKEN_TYPE_INSTRUCTION: |
||||
{ |
||||
const struct tgsi_full_instruction *fullinst |
||||
= &parse.FullToken.FullInstruction; |
||||
uint i; |
||||
|
||||
assert(fullinst->Instruction.Opcode < TGSI_OPCODE_LAST); |
||||
info->opcode_count[fullinst->Instruction.Opcode]++; |
||||
|
||||
for (i = 0; i < fullinst->Instruction.NumSrcRegs; i++) { |
||||
const struct tgsi_full_src_register *src = |
||||
&fullinst->Src[i]; |
||||
int ind = src->Register.Index; |
||||
|
||||
/* Mark which inputs are effectively used */ |
||||
if (src->Register.File == TGSI_FILE_INPUT) { |
||||
unsigned usage_mask; |
||||
usage_mask = tgsi_util_get_inst_usage_mask(fullinst, i); |
||||
if (src->Register.Indirect) { |
||||
for (ind = 0; ind < info->num_inputs; ++ind) { |
||||
info->input_usage_mask[ind] |= usage_mask; |
||||
} |
||||
} else { |
||||
assert(ind >= 0); |
||||
assert(ind < PIPE_MAX_SHADER_INPUTS); |
||||
info->input_usage_mask[ind] |= usage_mask; |
||||
} |
||||
|
||||
if (procType == TGSI_PROCESSOR_FRAGMENT && |
||||
info->reads_position && |
||||
src->Register.Index == 0 && |
||||
(src->Register.SwizzleX == TGSI_SWIZZLE_Z || |
||||
src->Register.SwizzleY == TGSI_SWIZZLE_Z || |
||||
src->Register.SwizzleZ == TGSI_SWIZZLE_Z || |
||||
src->Register.SwizzleW == TGSI_SWIZZLE_Z)) { |
||||
info->reads_z = TRUE; |
||||
} |
||||
} |
||||
|
||||
/* check for indirect register reads */ |
||||
if (src->Register.Indirect) { |
||||
info->indirect_files |= (1 << src->Register.File); |
||||
} |
||||
|
||||
/* MSAA samplers */ |
||||
if (src->Register.File == TGSI_FILE_SAMPLER) { |
||||
assert(fullinst->Instruction.Texture); |
||||
assert(src->Register.Index < Elements(info->is_msaa_sampler)); |
||||
|
||||
if (fullinst->Instruction.Texture && |
||||
(fullinst->Texture.Texture == TGSI_TEXTURE_2D_MSAA || |
||||
fullinst->Texture.Texture == TGSI_TEXTURE_2D_ARRAY_MSAA)) { |
||||
info->is_msaa_sampler[src->Register.Index] = TRUE; |
||||
} |
||||
} |
||||
} |
||||
|
||||
/* check for indirect register writes */ |
||||
for (i = 0; i < fullinst->Instruction.NumDstRegs; i++) { |
||||
const struct tgsi_full_dst_register *dst = &fullinst->Dst[i]; |
||||
if (dst->Register.Indirect) { |
||||
info->indirect_files |= (1 << dst->Register.File); |
||||
} |
||||
} |
||||
|
||||
info->num_instructions++; |
||||
} |
||||
break; |
||||
|
||||
case TGSI_TOKEN_TYPE_DECLARATION: |
||||
{ |
||||
const struct tgsi_full_declaration *fulldecl |
||||
= &parse.FullToken.FullDeclaration; |
||||
const uint file = fulldecl->Declaration.File; |
||||
uint reg; |
||||
for (reg = fulldecl->Range.First; |
||||
reg <= fulldecl->Range.Last; |
||||
reg++) { |
||||
unsigned semName = fulldecl->Semantic.Name; |
||||
unsigned semIndex = fulldecl->Semantic.Index; |
||||
|
||||
/* only first 32 regs will appear in this bitfield */ |
||||
info->file_mask[file] |= (1 << reg); |
||||
info->file_count[file]++; |
||||
info->file_max[file] = MAX2(info->file_max[file], (int)reg); |
||||
|
||||
if (file == TGSI_FILE_CONSTANT) { |
||||
int buffer = 0; |
||||
|
||||
if (fulldecl->Declaration.Dimension) |
||||
buffer = fulldecl->Dim.Index2D; |
||||
|
||||
info->const_file_max[buffer] = |
||||
MAX2(info->const_file_max[buffer], (int)reg); |
||||
} |
||||
else if (file == TGSI_FILE_INPUT) { |
||||
info->input_semantic_name[reg] = (ubyte) semName; |
||||
info->input_semantic_index[reg] = (ubyte) semIndex; |
||||
info->input_interpolate[reg] = (ubyte)fulldecl->Interp.Interpolate; |
||||
info->input_centroid[reg] = (ubyte)fulldecl->Interp.Centroid; |
||||
info->input_cylindrical_wrap[reg] = (ubyte)fulldecl->Interp.CylindricalWrap; |
||||
info->num_inputs++; |
||||
|
||||
if (procType == TGSI_PROCESSOR_FRAGMENT) { |
||||
if (semName == TGSI_SEMANTIC_POSITION) |
||||
info->reads_position = TRUE; |
||||
else if (semName == TGSI_SEMANTIC_PRIMID) |
||||
info->uses_primid = TRUE; |
||||
else if (semName == TGSI_SEMANTIC_FACE) |
||||
info->uses_frontface = TRUE; |
||||
} |
||||
} |
||||
else if (file == TGSI_FILE_SYSTEM_VALUE) { |
||||
unsigned index = fulldecl->Range.First; |
||||
|
||||
info->system_value_semantic_name[index] = semName; |
||||
info->num_system_values = MAX2(info->num_system_values, |
||||
index + 1); |
||||
|
||||
if (semName == TGSI_SEMANTIC_INSTANCEID) { |
||||
info->uses_instanceid = TRUE; |
||||
} |
||||
else if (semName == TGSI_SEMANTIC_VERTEXID) { |
||||
info->uses_vertexid = TRUE; |
||||
} |
||||
else if (semName == TGSI_SEMANTIC_PRIMID) { |
||||
info->uses_primid = TRUE; |
||||
} |
||||
} |
||||
else if (file == TGSI_FILE_OUTPUT) { |
||||
info->output_semantic_name[reg] = (ubyte) semName; |
||||
info->output_semantic_index[reg] = (ubyte) semIndex; |
||||
info->num_outputs++; |
||||
|
||||
if (procType == TGSI_PROCESSOR_VERTEX || |
||||
procType == TGSI_PROCESSOR_GEOMETRY) { |
||||
if (semName == TGSI_SEMANTIC_CLIPDIST) { |
||||
info->num_written_clipdistance += |
||||
util_bitcount(fulldecl->Declaration.UsageMask); |
||||
} |
||||
else if (semName == TGSI_SEMANTIC_CULLDIST) { |
||||
info->num_written_culldistance += |
||||
util_bitcount(fulldecl->Declaration.UsageMask); |
||||
} |
||||
} |
||||
|
||||
if (procType == TGSI_PROCESSOR_FRAGMENT) { |
||||
if (semName == TGSI_SEMANTIC_POSITION) { |
||||
info->writes_z = TRUE; |
||||
} |
||||
else if (semName == TGSI_SEMANTIC_STENCIL) { |
||||
info->writes_stencil = TRUE; |
||||
} |
||||
} |
||||
|
||||
if (procType == TGSI_PROCESSOR_VERTEX) { |
||||
if (semName == TGSI_SEMANTIC_EDGEFLAG) { |
||||
info->writes_edgeflag = TRUE; |
||||
} |
||||
} |
||||
|
||||
if (procType == TGSI_PROCESSOR_GEOMETRY) { |
||||
if (semName == TGSI_SEMANTIC_VIEWPORT_INDEX) { |
||||
info->writes_viewport_index = TRUE; |
||||
} |
||||
else if (semName == TGSI_SEMANTIC_LAYER) { |
||||
info->writes_layer = TRUE; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
break; |
||||
|
||||
case TGSI_TOKEN_TYPE_IMMEDIATE: |
||||
{ |
||||
uint reg = info->immediate_count++; |
||||
uint file = TGSI_FILE_IMMEDIATE; |
||||
|
||||
info->file_mask[file] |= (1 << reg); |
||||
info->file_count[file]++; |
||||
info->file_max[file] = MAX2(info->file_max[file], (int)reg); |
||||
} |
||||
break; |
||||
|
||||
case TGSI_TOKEN_TYPE_PROPERTY: |
||||
{ |
||||
const struct tgsi_full_property *fullprop |
||||
= &parse.FullToken.FullProperty; |
||||
|
||||
info->properties[info->num_properties].name = |
||||
fullprop->Property.PropertyName; |
||||
memcpy(info->properties[info->num_properties].data, |
||||
fullprop->u, 8 * sizeof(unsigned));; |
||||
|
||||
++info->num_properties; |
||||
} |
||||
break; |
||||
|
||||
default: |
||||
assert( 0 ); |
||||
} |
||||
} |
||||
|
||||
info->uses_kill = (info->opcode_count[TGSI_OPCODE_KILL_IF] || |
||||
info->opcode_count[TGSI_OPCODE_KILL]); |
||||
|
||||
/* extract simple properties */ |
||||
for (i = 0; i < info->num_properties; ++i) { |
||||
switch (info->properties[i].name) { |
||||
case TGSI_PROPERTY_FS_COORD_ORIGIN: |
||||
info->origin_lower_left = info->properties[i].data[0]; |
||||
break; |
||||
case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER: |
||||
info->pixel_center_integer = info->properties[i].data[0]; |
||||
break; |
||||
case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS: |
||||
info->color0_writes_all_cbufs = info->properties[i].data[0]; |
||||
break; |
||||
case TGSI_PROPERTY_GS_INPUT_PRIM: |
||||
/* The dimensions of the IN decleration in geometry shader have
|
||||
* to be deduced from the type of the input primitive. |
||||
*/ |
||||
if (procType == TGSI_PROCESSOR_GEOMETRY) { |
||||
unsigned input_primitive = info->properties[i].data[0]; |
||||
int num_verts = u_vertices_per_prim(input_primitive); |
||||
int j; |
||||
info->file_count[TGSI_FILE_INPUT] = num_verts; |
||||
info->file_max[TGSI_FILE_INPUT] = |
||||
MAX2(info->file_max[TGSI_FILE_INPUT], num_verts - 1); |
||||
for (j = 0; j < num_verts; ++j) { |
||||
info->file_mask[TGSI_FILE_INPUT] |= (1 << j); |
||||
} |
||||
} |
||||
break; |
||||
default: |
||||
; |
||||
} |
||||
} |
||||
|
||||
tgsi_parse_free (&parse); |
||||
} |
||||
|
||||
|
||||
|
||||
/**
|
||||
* Check if the given shader is a "passthrough" shader consisting of only |
||||
* MOV instructions of the form: MOV OUT[n], IN[n] |
||||
*
|
||||
*/ |
||||
boolean |
||||
tgsi_is_passthrough_shader(const struct tgsi_token *tokens) |
||||
{ |
||||
struct tgsi_parse_context parse; |
||||
|
||||
/**
|
||||
** Setup to begin parsing input shader |
||||
**/ |
||||
if (tgsi_parse_init(&parse, tokens) != TGSI_PARSE_OK) { |
||||
debug_printf("tgsi_parse_init() failed in tgsi_is_passthrough_shader()!\n"); |
||||
return FALSE; |
||||
} |
||||
|
||||
/**
|
||||
** Loop over incoming program tokens/instructions |
||||
*/ |
||||
while (!tgsi_parse_end_of_tokens(&parse)) { |
||||
|
||||
tgsi_parse_token(&parse); |
||||
|
||||
switch (parse.FullToken.Token.Type) { |
||||
case TGSI_TOKEN_TYPE_INSTRUCTION: |
||||
{ |
||||
struct tgsi_full_instruction *fullinst = |
||||
&parse.FullToken.FullInstruction; |
||||
const struct tgsi_full_src_register *src = |
||||
&fullinst->Src[0]; |
||||
const struct tgsi_full_dst_register *dst = |
||||
&fullinst->Dst[0]; |
||||
|
||||
/* Do a whole bunch of checks for a simple move */ |
||||
if (fullinst->Instruction.Opcode != TGSI_OPCODE_MOV || |
||||
(src->Register.File != TGSI_FILE_INPUT && |
||||
src->Register.File != TGSI_FILE_SYSTEM_VALUE) || |
||||
dst->Register.File != TGSI_FILE_OUTPUT || |
||||
src->Register.Index != dst->Register.Index || |
||||
|
||||
src->Register.Negate || |
||||
src->Register.Absolute || |
||||
|
||||
src->Register.SwizzleX != TGSI_SWIZZLE_X || |
||||
src->Register.SwizzleY != TGSI_SWIZZLE_Y || |
||||
src->Register.SwizzleZ != TGSI_SWIZZLE_Z || |
||||
src->Register.SwizzleW != TGSI_SWIZZLE_W || |
||||
|
||||
dst->Register.WriteMask != TGSI_WRITEMASK_XYZW) |
||||
{ |
||||
tgsi_parse_free(&parse); |
||||
return FALSE; |
||||
} |
||||
} |
||||
break; |
||||
|
||||
case TGSI_TOKEN_TYPE_DECLARATION: |
||||
/* fall-through */ |
||||
case TGSI_TOKEN_TYPE_IMMEDIATE: |
||||
/* fall-through */ |
||||
case TGSI_TOKEN_TYPE_PROPERTY: |
||||
/* fall-through */ |
||||
default: |
||||
; /* no-op */ |
||||
} |
||||
} |
||||
|
||||
tgsi_parse_free(&parse); |
||||
|
||||
/* if we get here, it's a pass-through shader */ |
||||
return TRUE; |
||||
} |
@ -0,0 +1,110 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* 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 TGSI_SCAN_H |
||||
#define TGSI_SCAN_H |
||||
|
||||
|
||||
#include "pipe/p_compiler.h" |
||||
#include "pipe/p_state.h" |
||||
#include "pipe/p_shader_tokens.h" |
||||
|
||||
/**
|
||||
* Shader summary info |
||||
*/ |
||||
struct tgsi_shader_info |
||||
{ |
||||
uint num_tokens; |
||||
|
||||
ubyte num_inputs; |
||||
ubyte num_outputs; |
||||
ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS]; /**< TGSI_SEMANTIC_x */ |
||||
ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS]; |
||||
ubyte input_interpolate[PIPE_MAX_SHADER_INPUTS]; |
||||
ubyte input_centroid[PIPE_MAX_SHADER_INPUTS]; |
||||
ubyte input_usage_mask[PIPE_MAX_SHADER_INPUTS]; |
||||
ubyte input_cylindrical_wrap[PIPE_MAX_SHADER_INPUTS]; |
||||
ubyte output_semantic_name[PIPE_MAX_SHADER_OUTPUTS]; /**< TGSI_SEMANTIC_x */ |
||||
ubyte output_semantic_index[PIPE_MAX_SHADER_OUTPUTS]; |
||||
|
||||
ubyte num_system_values; |
||||
ubyte system_value_semantic_name[PIPE_MAX_SHADER_INPUTS]; |
||||
|
||||
ubyte processor; |
||||
|
||||
uint file_mask[TGSI_FILE_COUNT]; /**< bitmask of declared registers */ |
||||
uint file_count[TGSI_FILE_COUNT]; /**< number of declared registers */ |
||||
int file_max[TGSI_FILE_COUNT]; /**< highest index of declared registers */ |
||||
int const_file_max[PIPE_MAX_CONSTANT_BUFFERS]; |
||||
|
||||
uint immediate_count; /**< number of immediates declared */ |
||||
uint num_instructions; |
||||
|
||||
uint opcode_count[TGSI_OPCODE_LAST]; /**< opcode histogram */ |
||||
|
||||
boolean reads_position; /**< does fragment shader read position? */ |
||||
boolean reads_z; /**< does fragment shader read depth? */ |
||||
boolean writes_z; /**< does fragment shader write Z value? */ |
||||
boolean writes_stencil; /**< does fragment shader write stencil value? */ |
||||
boolean writes_edgeflag; /**< vertex shader outputs edgeflag */ |
||||
boolean uses_kill; /**< KILL or KILL_IF instruction used? */ |
||||
boolean uses_instanceid; |
||||
boolean uses_vertexid; |
||||
boolean uses_primid; |
||||
boolean uses_frontface; |
||||
boolean origin_lower_left; |
||||
boolean pixel_center_integer; |
||||
boolean color0_writes_all_cbufs; |
||||
boolean writes_viewport_index; |
||||
boolean writes_layer; |
||||
boolean is_msaa_sampler[PIPE_MAX_SAMPLERS]; |
||||
|
||||
unsigned num_written_culldistance; |
||||
unsigned num_written_clipdistance; |
||||
/**
|
||||
* Bitmask indicating which register files are accessed with |
||||
* indirect addressing. The bits are (1 << TGSI_FILE_x), etc. |
||||
*/ |
||||
unsigned indirect_files; |
||||
|
||||
struct { |
||||
unsigned name; |
||||
unsigned data[8]; |
||||
} properties[TGSI_PROPERTY_COUNT]; |
||||
uint num_properties; |
||||
}; |
||||
|
||||
extern void |
||||
tgsi_scan_shader(const struct tgsi_token *tokens, |
||||
struct tgsi_shader_info *info); |
||||
|
||||
|
||||
extern boolean |
||||
tgsi_is_passthrough_shader(const struct tgsi_token *tokens); |
||||
|
||||
|
||||
#endif /* TGSI_SCAN_H */ |
@ -0,0 +1,201 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007-2008 VMware, Inc. |
||||
* Copyright 2012 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 THE AUTHORS 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 "pipe/p_compiler.h" |
||||
#include "util/u_memory.h" |
||||
#include "tgsi_strings.h" |
||||
|
||||
|
||||
const char *tgsi_processor_type_names[4] = |
||||
{ |
||||
"FRAG", |
||||
"VERT", |
||||
"GEOM", |
||||
"COMP" |
||||
}; |
||||
|
||||
static const char *tgsi_file_names[] = |
||||
{ |
||||
"NULL", |
||||
"CONST", |
||||
"IN", |
||||
"OUT", |
||||
"TEMP", |
||||
"SAMP", |
||||
"ADDR", |
||||
"IMM", |
||||
"PRED", |
||||
"SV", |
||||
"RES", |
||||
"SVIEW" |
||||
}; |
||||
|
||||
const char *tgsi_semantic_names[TGSI_SEMANTIC_COUNT] = |
||||
{ |
||||
"POSITION", |
||||
"COLOR", |
||||
"BCOLOR", |
||||
"FOG", |
||||
"PSIZE", |
||||
"GENERIC", |
||||
"NORMAL", |
||||
"FACE", |
||||
"EDGEFLAG", |
||||
"PRIM_ID", |
||||
"INSTANCEID", |
||||
"VERTEXID", |
||||
"STENCIL", |
||||
"CLIPDIST", |
||||
"CLIPVERTEX", |
||||
"GRID_SIZE", |
||||
"BLOCK_ID", |
||||
"BLOCK_SIZE", |
||||
"THREAD_ID", |
||||
"TEXCOORD", |
||||
"PCOORD", |
||||
"VIEWPORT_INDEX", |
||||
"LAYER", |
||||
"CULLDIST" |
||||
}; |
||||
|
||||
const char *tgsi_texture_names[TGSI_TEXTURE_COUNT] = |
||||
{ |
||||
"BUFFER", |
||||
"1D", |
||||
"2D", |
||||
"3D", |
||||
"CUBE", |
||||
"RECT", |
||||
"SHADOW1D", |
||||
"SHADOW2D", |
||||
"SHADOWRECT", |
||||
"1D_ARRAY", |
||||
"2D_ARRAY", |
||||
"SHADOW1D_ARRAY", |
||||
"SHADOW2D_ARRAY", |
||||
"SHADOWCUBE", |
||||
"2D_MSAA", |
||||
"2D_ARRAY_MSAA", |
||||
"CUBEARRAY", |
||||
"SHADOWCUBEARRAY", |
||||
"UNKNOWN", |
||||
}; |
||||
|
||||
const char *tgsi_property_names[TGSI_PROPERTY_COUNT] = |
||||
{ |
||||
"GS_INPUT_PRIMITIVE", |
||||
"GS_OUTPUT_PRIMITIVE", |
||||
"GS_MAX_OUTPUT_VERTICES", |
||||
"FS_COORD_ORIGIN", |
||||
"FS_COORD_PIXEL_CENTER", |
||||
"FS_COLOR0_WRITES_ALL_CBUFS", |
||||
"FS_DEPTH_LAYOUT", |
||||
"VS_PROHIBIT_UCPS" |
||||
}; |
||||
|
||||
const char *tgsi_type_names[5] = |
||||
{ |
||||
"UNORM", |
||||
"SNORM", |
||||
"SINT", |
||||
"UINT", |
||||
"FLOAT" |
||||
}; |
||||
|
||||
const char *tgsi_interpolate_names[TGSI_INTERPOLATE_COUNT] = |
||||
{ |
||||
"CONSTANT", |
||||
"LINEAR", |
||||
"PERSPECTIVE", |
||||
"COLOR" |
||||
}; |
||||
|
||||
const char *tgsi_primitive_names[PIPE_PRIM_MAX] = |
||||
{ |
||||
"POINTS", |
||||
"LINES", |
||||
"LINE_LOOP", |
||||
"LINE_STRIP", |
||||
"TRIANGLES", |
||||
"TRIANGLE_STRIP", |
||||
"TRIANGLE_FAN", |
||||
"QUADS", |
||||
"QUAD_STRIP", |
||||
"POLYGON", |
||||
"LINES_ADJACENCY", |
||||
"LINE_STRIP_ADJACENCY", |
||||
"TRIANGLES_ADJACENCY", |
||||
"TRIANGLE_STRIP_ADJACENCY" |
||||
}; |
||||
|
||||
const char *tgsi_fs_coord_origin_names[2] = |
||||
{ |
||||
"UPPER_LEFT", |
||||
"LOWER_LEFT" |
||||
}; |
||||
|
||||
const char *tgsi_fs_coord_pixel_center_names[2] = |
||||
{ |
||||
"HALF_INTEGER", |
||||
"INTEGER" |
||||
}; |
||||
|
||||
const char *tgsi_immediate_type_names[3] = |
||||
{ |
||||
"FLT32", |
||||
"UINT32", |
||||
"INT32" |
||||
}; |
||||
|
||||
|
||||
static INLINE void |
||||
tgsi_strings_check(void) |
||||
{ |
||||
STATIC_ASSERT(Elements(tgsi_semantic_names) == TGSI_SEMANTIC_COUNT); |
||||
STATIC_ASSERT(Elements(tgsi_texture_names) == TGSI_TEXTURE_COUNT); |
||||
STATIC_ASSERT(Elements(tgsi_property_names) == TGSI_PROPERTY_COUNT); |
||||
STATIC_ASSERT(Elements(tgsi_primitive_names) == PIPE_PRIM_MAX); |
||||
STATIC_ASSERT(Elements(tgsi_interpolate_names) == TGSI_INTERPOLATE_COUNT); |
||||
(void) tgsi_processor_type_names; |
||||
(void) tgsi_type_names; |
||||
(void) tgsi_immediate_type_names; |
||||
(void) tgsi_fs_coord_origin_names; |
||||
(void) tgsi_fs_coord_pixel_center_names; |
||||
} |
||||
|
||||
|
||||
const char * |
||||
tgsi_file_name(unsigned file) |
||||
{ |
||||
STATIC_ASSERT(Elements(tgsi_file_names) == TGSI_FILE_COUNT); |
||||
if (file < Elements(tgsi_file_names)) |
||||
return tgsi_file_names[file]; |
||||
else |
||||
return "invalid file"; |
||||
} |
@ -0,0 +1,71 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007-2008 VMware, Inc. |
||||
* Copyright 2012 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 THE AUTHORS 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 TGSI_STRINGS_H |
||||
#define TGSI_STRINGS_H |
||||
|
||||
#include "pipe/p_shader_tokens.h" |
||||
#include "pipe/p_state.h" |
||||
|
||||
|
||||
#if defined __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
|
||||
extern const char *tgsi_processor_type_names[4]; |
||||
|
||||
extern const char *tgsi_semantic_names[TGSI_SEMANTIC_COUNT]; |
||||
|
||||
extern const char *tgsi_texture_names[TGSI_TEXTURE_COUNT]; |
||||
|
||||
extern const char *tgsi_property_names[TGSI_PROPERTY_COUNT]; |
||||
|
||||
extern const char *tgsi_type_names[5]; |
||||
|
||||
extern const char *tgsi_interpolate_names[TGSI_INTERPOLATE_COUNT]; |
||||
|
||||
extern const char *tgsi_primitive_names[PIPE_PRIM_MAX]; |
||||
|
||||
extern const char *tgsi_fs_coord_origin_names[2]; |
||||
|
||||
extern const char *tgsi_fs_coord_pixel_center_names[2]; |
||||
|
||||
extern const char *tgsi_immediate_type_names[3]; |
||||
|
||||
|
||||
const char * |
||||
tgsi_file_name(unsigned file); |
||||
|
||||
|
||||
#if defined __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
|
||||
#endif /* TGSI_STRINGS_H */ |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,49 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* 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 TGSI_TEXT_H |
||||
#define TGSI_TEXT_H |
||||
|
||||
#if defined __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
#include "pipe/p_compiler.h" |
||||
|
||||
struct tgsi_token; |
||||
|
||||
boolean |
||||
tgsi_text_translate( |
||||
const char *text, |
||||
struct tgsi_token *tokens, |
||||
uint num_tokens ); |
||||
|
||||
#if defined __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* TGSI_TEXT_H */ |
@ -0,0 +1,250 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* 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. |
||||
*
|
||||
**************************************************************************/ |
||||
|
||||
/**
|
||||
* TGSI program transformation utility. |
||||
* |
||||
* Authors: Brian Paul |
||||
*/ |
||||
|
||||
#include "util/u_debug.h" |
||||
|
||||
#include "tgsi_transform.h" |
||||
|
||||
|
||||
|
||||
static void |
||||
emit_instruction(struct tgsi_transform_context *ctx, |
||||
const struct tgsi_full_instruction *inst) |
||||
{ |
||||
uint ti = ctx->ti; |
||||
|
||||
ti += tgsi_build_full_instruction(inst, |
||||
ctx->tokens_out + ti, |
||||
ctx->header, |
||||
ctx->max_tokens_out - ti); |
||||
ctx->ti = ti; |
||||
} |
||||
|
||||
|
||||
static void |
||||
emit_declaration(struct tgsi_transform_context *ctx, |
||||
const struct tgsi_full_declaration *decl) |
||||
{ |
||||
uint ti = ctx->ti; |
||||
|
||||
ti += tgsi_build_full_declaration(decl, |
||||
ctx->tokens_out + ti, |
||||
ctx->header, |
||||
ctx->max_tokens_out - ti); |
||||
ctx->ti = ti; |
||||
} |
||||
|
||||
|
||||
static void |
||||
emit_immediate(struct tgsi_transform_context *ctx, |
||||
const struct tgsi_full_immediate *imm) |
||||
{ |
||||
uint ti = ctx->ti; |
||||
|
||||
ti += tgsi_build_full_immediate(imm, |
||||
ctx->tokens_out + ti, |
||||
ctx->header, |
||||
ctx->max_tokens_out - ti); |
||||
ctx->ti = ti; |
||||
} |
||||
|
||||
|
||||
static void |
||||
emit_property(struct tgsi_transform_context *ctx, |
||||
const struct tgsi_full_property *prop) |
||||
{ |
||||
uint ti = ctx->ti; |
||||
|
||||
ti += tgsi_build_full_property(prop, |
||||
ctx->tokens_out + ti, |
||||
ctx->header, |
||||
ctx->max_tokens_out - ti); |
||||
ctx->ti = ti; |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Apply user-defined transformations to the input shader to produce |
||||
* the output shader. |
||||
* For example, a register search-and-replace operation could be applied |
||||
* by defining a transform_instruction() callback that examined and changed |
||||
* the instruction src/dest regs. |
||||
* |
||||
* \return number of tokens emitted |
||||
*/ |
||||
int |
||||
tgsi_transform_shader(const struct tgsi_token *tokens_in, |
||||
struct tgsi_token *tokens_out, |
||||
uint max_tokens_out, |
||||
struct tgsi_transform_context *ctx) |
||||
{ |
||||
uint procType; |
||||
|
||||
/* input shader */ |
||||
struct tgsi_parse_context parse; |
||||
|
||||
/* output shader */ |
||||
struct tgsi_processor *processor; |
||||
|
||||
|
||||
/**
|
||||
** callback context init |
||||
**/ |
||||
ctx->emit_instruction = emit_instruction; |
||||
ctx->emit_declaration = emit_declaration; |
||||
ctx->emit_immediate = emit_immediate; |
||||
ctx->emit_property = emit_property; |
||||
ctx->tokens_out = tokens_out; |
||||
ctx->max_tokens_out = max_tokens_out; |
||||
|
||||
|
||||
/**
|
||||
** Setup to begin parsing input shader |
||||
**/ |
||||
if (tgsi_parse_init( &parse, tokens_in ) != TGSI_PARSE_OK) { |
||||
debug_printf("tgsi_parse_init() failed in tgsi_transform_shader()!\n"); |
||||
return -1; |
||||
} |
||||
procType = parse.FullHeader.Processor.Processor; |
||||
assert(procType == TGSI_PROCESSOR_FRAGMENT || |
||||
procType == TGSI_PROCESSOR_VERTEX || |
||||
procType == TGSI_PROCESSOR_GEOMETRY); |
||||
|
||||
|
||||
/**
|
||||
** Setup output shader |
||||
**/ |
||||
ctx->header = (struct tgsi_header *)tokens_out; |
||||
*ctx->header = tgsi_build_header(); |
||||
|
||||
processor = (struct tgsi_processor *) (tokens_out + 1); |
||||
*processor = tgsi_build_processor( procType, ctx->header ); |
||||
|
||||
ctx->ti = 2; |
||||
|
||||
|
||||
/**
|
||||
** Loop over incoming program tokens/instructions |
||||
*/ |
||||
while( !tgsi_parse_end_of_tokens( &parse ) ) { |
||||
|
||||
tgsi_parse_token( &parse ); |
||||
|
||||
switch( parse.FullToken.Token.Type ) { |
||||
case TGSI_TOKEN_TYPE_INSTRUCTION: |
||||
{ |
||||
struct tgsi_full_instruction *fullinst |
||||
= &parse.FullToken.FullInstruction; |
||||
|
||||
if (ctx->transform_instruction) |
||||
ctx->transform_instruction(ctx, fullinst); |
||||
else |
||||
ctx->emit_instruction(ctx, fullinst); |
||||
} |
||||
break; |
||||
|
||||
case TGSI_TOKEN_TYPE_DECLARATION: |
||||
{ |
||||
struct tgsi_full_declaration *fulldecl |
||||
= &parse.FullToken.FullDeclaration; |
||||
|
||||
if (ctx->transform_declaration) |
||||
ctx->transform_declaration(ctx, fulldecl); |
||||
else |
||||
ctx->emit_declaration(ctx, fulldecl); |
||||
} |
||||
break; |
||||
|
||||
case TGSI_TOKEN_TYPE_IMMEDIATE: |
||||
{ |
||||
struct tgsi_full_immediate *fullimm |
||||
= &parse.FullToken.FullImmediate; |
||||
|
||||
if (ctx->transform_immediate) |
||||
ctx->transform_immediate(ctx, fullimm); |
||||
else |
||||
ctx->emit_immediate(ctx, fullimm); |
||||
} |
||||
break; |
||||
case TGSI_TOKEN_TYPE_PROPERTY: |
||||
{ |
||||
struct tgsi_full_property *fullprop |
||||
= &parse.FullToken.FullProperty; |
||||
|
||||
if (ctx->transform_property) |
||||
ctx->transform_property(ctx, fullprop); |
||||
else |
||||
ctx->emit_property(ctx, fullprop); |
||||
} |
||||
break; |
||||
|
||||
default: |
||||
assert( 0 ); |
||||
} |
||||
} |
||||
|
||||
if (ctx->epilog) { |
||||
ctx->epilog(ctx); |
||||
} |
||||
|
||||
tgsi_parse_free (&parse); |
||||
|
||||
return ctx->ti; |
||||
} |
||||
|
||||
|
||||
#include "tgsi_text.h" |
||||
|
||||
extern int tgsi_transform_foo( struct tgsi_token *tokens_out, |
||||
uint max_tokens_out ); |
||||
|
||||
/* This function exists only so that tgsi_text_translate() doesn't get
|
||||
* magic-ed out of the libtgsi.a archive by the build system. Don't |
||||
* remove unless you know this has been fixed - check on mingw/scons |
||||
* builds as well. |
||||
*/ |
||||
int |
||||
tgsi_transform_foo( struct tgsi_token *tokens_out, |
||||
uint max_tokens_out ) |
||||
{ |
||||
const char *text =
|
||||
"FRAG\n" |
||||
"DCL IN[0], COLOR, CONSTANT\n" |
||||
"DCL OUT[0], COLOR\n" |
||||
" 0: MOV OUT[0], IN[0]\n" |
||||
" 1: END"; |
||||
|
||||
return tgsi_text_translate( text, |
||||
tokens_out, |
||||
max_tokens_out ); |
||||
} |
@ -0,0 +1,96 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* 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 TGSI_TRANSFORM_H |
||||
#define TGSI_TRANSFORM_H |
||||
|
||||
|
||||
#include "pipe/p_shader_tokens.h" |
||||
#include "tgsi/tgsi_parse.h" |
||||
#include "tgsi/tgsi_build.h" |
||||
|
||||
|
||||
|
||||
/**
|
||||
* Subclass this to add caller-specific data |
||||
*/ |
||||
struct tgsi_transform_context |
||||
{ |
||||
/**** PUBLIC ***/ |
||||
|
||||
/**
|
||||
* User-defined callbacks invoked per instruction. |
||||
*/ |
||||
void (*transform_instruction)(struct tgsi_transform_context *ctx, |
||||
struct tgsi_full_instruction *inst); |
||||
|
||||
void (*transform_declaration)(struct tgsi_transform_context *ctx, |
||||
struct tgsi_full_declaration *decl); |
||||
|
||||
void (*transform_immediate)(struct tgsi_transform_context *ctx, |
||||
struct tgsi_full_immediate *imm); |
||||
void (*transform_property)(struct tgsi_transform_context *ctx, |
||||
struct tgsi_full_property *prop); |
||||
|
||||
/**
|
||||
* Called at end of input program to allow caller to append extra |
||||
* instructions. Return number of tokens emitted. |
||||
*/ |
||||
void (*epilog)(struct tgsi_transform_context *ctx); |
||||
|
||||
|
||||
/*** PRIVATE ***/ |
||||
|
||||
/**
|
||||
* These are setup by tgsi_transform_shader() and cannot be overridden. |
||||
* Meant to be called from in the above user callback functions. |
||||
*/ |
||||
void (*emit_instruction)(struct tgsi_transform_context *ctx, |
||||
const struct tgsi_full_instruction *inst); |
||||
void (*emit_declaration)(struct tgsi_transform_context *ctx, |
||||
const struct tgsi_full_declaration *decl); |
||||
void (*emit_immediate)(struct tgsi_transform_context *ctx, |
||||
const struct tgsi_full_immediate *imm); |
||||
void (*emit_property)(struct tgsi_transform_context *ctx, |
||||
const struct tgsi_full_property *prop); |
||||
|
||||
struct tgsi_header *header; |
||||
uint max_tokens_out; |
||||
struct tgsi_token *tokens_out; |
||||
uint ti; |
||||
}; |
||||
|
||||
|
||||
|
||||
extern int |
||||
tgsi_transform_shader(const struct tgsi_token *tokens_in, |
||||
struct tgsi_token *tokens_out, |
||||
uint max_tokens_out, |
||||
struct tgsi_transform_context *ctx); |
||||
|
||||
|
||||
#endif /* TGSI_TRANSFORM_H */ |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,463 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 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 "util/u_debug.h" |
||||
#include "pipe/p_shader_tokens.h" |
||||
#include "tgsi_parse.h" |
||||
#include "tgsi_util.h" |
||||
|
||||
union pointer_hack |
||||
{ |
||||
void *pointer; |
||||
uint64_t uint64; |
||||
}; |
||||
|
||||
void * |
||||
tgsi_align_128bit( |
||||
void *unaligned ) |
||||
{ |
||||
union pointer_hack ph; |
||||
|
||||
ph.uint64 = 0; |
||||
ph.pointer = unaligned; |
||||
ph.uint64 = (ph.uint64 + 15) & ~15; |
||||
return ph.pointer; |
||||
} |
||||
|
||||
unsigned |
||||
tgsi_util_get_src_register_swizzle( |
||||
const struct tgsi_src_register *reg, |
||||
unsigned component ) |
||||
{ |
||||
switch( component ) { |
||||
case 0: |
||||
return reg->SwizzleX; |
||||
case 1: |
||||
return reg->SwizzleY; |
||||
case 2: |
||||
return reg->SwizzleZ; |
||||
case 3: |
||||
return reg->SwizzleW; |
||||
default: |
||||
assert( 0 ); |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
|
||||
unsigned |
||||
tgsi_util_get_full_src_register_swizzle( |
||||
const struct tgsi_full_src_register *reg, |
||||
unsigned component ) |
||||
{ |
||||
return tgsi_util_get_src_register_swizzle( |
||||
®->Register, |
||||
component ); |
||||
} |
||||
|
||||
void |
||||
tgsi_util_set_src_register_swizzle( |
||||
struct tgsi_src_register *reg, |
||||
unsigned swizzle, |
||||
unsigned component ) |
||||
{ |
||||
switch( component ) { |
||||
case 0: |
||||
reg->SwizzleX = swizzle; |
||||
break; |
||||
case 1: |
||||
reg->SwizzleY = swizzle; |
||||
break; |
||||
case 2: |
||||
reg->SwizzleZ = swizzle; |
||||
break; |
||||
case 3: |
||||
reg->SwizzleW = swizzle; |
||||
break; |
||||
default: |
||||
assert( 0 ); |
||||
} |
||||
} |
||||
|
||||
unsigned |
||||
tgsi_util_get_full_src_register_sign_mode( |
||||
const struct tgsi_full_src_register *reg, |
||||
unsigned component ) |
||||
{ |
||||
unsigned sign_mode; |
||||
|
||||
if( reg->Register.Absolute ) { |
||||
/* Consider only the post-abs negation. */ |
||||
|
||||
if( reg->Register.Negate ) { |
||||
sign_mode = TGSI_UTIL_SIGN_SET; |
||||
} |
||||
else { |
||||
sign_mode = TGSI_UTIL_SIGN_CLEAR; |
||||
} |
||||
} |
||||
else { |
||||
if( reg->Register.Negate ) { |
||||
sign_mode = TGSI_UTIL_SIGN_TOGGLE; |
||||
} |
||||
else { |
||||
sign_mode = TGSI_UTIL_SIGN_KEEP; |
||||
} |
||||
} |
||||
|
||||
return sign_mode; |
||||
} |
||||
|
||||
void |
||||
tgsi_util_set_full_src_register_sign_mode( |
||||
struct tgsi_full_src_register *reg, |
||||
unsigned sign_mode ) |
||||
{ |
||||
switch (sign_mode) |
||||
{ |
||||
case TGSI_UTIL_SIGN_CLEAR: |
||||
reg->Register.Negate = 0; |
||||
reg->Register.Absolute = 1; |
||||
break; |
||||
|
||||
case TGSI_UTIL_SIGN_SET: |
||||
reg->Register.Absolute = 1; |
||||
reg->Register.Negate = 1; |
||||
break; |
||||
|
||||
case TGSI_UTIL_SIGN_TOGGLE: |
||||
reg->Register.Negate = 1; |
||||
reg->Register.Absolute = 0; |
||||
break; |
||||
|
||||
case TGSI_UTIL_SIGN_KEEP: |
||||
reg->Register.Negate = 0; |
||||
reg->Register.Absolute = 0; |
||||
break; |
||||
|
||||
default: |
||||
assert( 0 ); |
||||
} |
||||
} |
||||
|
||||
/**
|
||||
* Determine which channels of the specificed src register are effectively |
||||
* used by this instruction. |
||||
*/ |
||||
unsigned |
||||
tgsi_util_get_inst_usage_mask(const struct tgsi_full_instruction *inst, |
||||
unsigned src_idx) |
||||
{ |
||||
const struct tgsi_full_src_register *src = &inst->Src[src_idx]; |
||||
unsigned write_mask = inst->Dst[0].Register.WriteMask; |
||||
unsigned read_mask; |
||||
unsigned usage_mask; |
||||
unsigned chan; |
||||
|
||||
switch (inst->Instruction.Opcode) { |
||||
case TGSI_OPCODE_MOV: |
||||
case TGSI_OPCODE_ARL: |
||||
case TGSI_OPCODE_ARR: |
||||
case TGSI_OPCODE_RCP: |
||||
case TGSI_OPCODE_MUL: |
||||
case TGSI_OPCODE_DIV: |
||||
case TGSI_OPCODE_ADD: |
||||
case TGSI_OPCODE_MIN: |
||||
case TGSI_OPCODE_MAX: |
||||
case TGSI_OPCODE_SLT: |
||||
case TGSI_OPCODE_SGE: |
||||
case TGSI_OPCODE_MAD: |
||||
case TGSI_OPCODE_SUB: |
||||
case TGSI_OPCODE_LRP: |
||||
case TGSI_OPCODE_CND: |
||||
case TGSI_OPCODE_FRC: |
||||
case TGSI_OPCODE_CEIL: |
||||
case TGSI_OPCODE_CLAMP: |
||||
case TGSI_OPCODE_FLR: |
||||
case TGSI_OPCODE_ROUND: |
||||
case TGSI_OPCODE_POW: |
||||
case TGSI_OPCODE_ABS: |
||||
case TGSI_OPCODE_COS: |
||||
case TGSI_OPCODE_SIN: |
||||
case TGSI_OPCODE_DDX: |
||||
case TGSI_OPCODE_DDY: |
||||
case TGSI_OPCODE_SEQ: |
||||
case TGSI_OPCODE_SGT: |
||||
case TGSI_OPCODE_SLE: |
||||
case TGSI_OPCODE_SNE: |
||||
case TGSI_OPCODE_SSG: |
||||
case TGSI_OPCODE_CMP: |
||||
case TGSI_OPCODE_TRUNC: |
||||
case TGSI_OPCODE_NOT: |
||||
case TGSI_OPCODE_AND: |
||||
case TGSI_OPCODE_OR: |
||||
case TGSI_OPCODE_XOR: |
||||
case TGSI_OPCODE_SAD: |
||||
case TGSI_OPCODE_FSEQ: |
||||
case TGSI_OPCODE_FSGE: |
||||
case TGSI_OPCODE_FSLT: |
||||
case TGSI_OPCODE_FSNE: |
||||
case TGSI_OPCODE_F2I: |
||||
case TGSI_OPCODE_IDIV: |
||||
case TGSI_OPCODE_IMAX: |
||||
case TGSI_OPCODE_IMIN: |
||||
case TGSI_OPCODE_INEG: |
||||
case TGSI_OPCODE_ISGE: |
||||
case TGSI_OPCODE_ISHR: |
||||
case TGSI_OPCODE_ISLT: |
||||
case TGSI_OPCODE_F2U: |
||||
case TGSI_OPCODE_U2F: |
||||
case TGSI_OPCODE_UADD: |
||||
case TGSI_OPCODE_UDIV: |
||||
case TGSI_OPCODE_UMAD: |
||||
case TGSI_OPCODE_UMAX: |
||||
case TGSI_OPCODE_UMIN: |
||||
case TGSI_OPCODE_UMOD: |
||||
case TGSI_OPCODE_UMUL: |
||||
case TGSI_OPCODE_USEQ: |
||||
case TGSI_OPCODE_USGE: |
||||
case TGSI_OPCODE_USHR: |
||||
case TGSI_OPCODE_USLT: |
||||
case TGSI_OPCODE_USNE: |
||||
case TGSI_OPCODE_IMUL_HI: |
||||
case TGSI_OPCODE_UMUL_HI: |
||||
/* Channel-wise operations */ |
||||
read_mask = write_mask; |
||||
break; |
||||
|
||||
case TGSI_OPCODE_EX2: |
||||
case TGSI_OPCODE_LG2: |
||||
case TGSI_OPCODE_RCC: |
||||
read_mask = TGSI_WRITEMASK_X; |
||||
break; |
||||
|
||||
case TGSI_OPCODE_SCS: |
||||
read_mask = write_mask & TGSI_WRITEMASK_XY ? TGSI_WRITEMASK_X : 0; |
||||
break; |
||||
|
||||
case TGSI_OPCODE_EXP: |
||||
case TGSI_OPCODE_LOG: |
||||
read_mask = write_mask & TGSI_WRITEMASK_XYZ ? TGSI_WRITEMASK_X : 0; |
||||
break; |
||||
|
||||
case TGSI_OPCODE_DP2A: |
||||
read_mask = src_idx == 2 ? TGSI_WRITEMASK_X : TGSI_WRITEMASK_XY; |
||||
break; |
||||
|
||||
case TGSI_OPCODE_DP2: |
||||
read_mask = TGSI_WRITEMASK_XY; |
||||
break; |
||||
|
||||
case TGSI_OPCODE_DP3: |
||||
read_mask = TGSI_WRITEMASK_XYZ; |
||||
break; |
||||
|
||||
case TGSI_OPCODE_DP4: |
||||
read_mask = TGSI_WRITEMASK_XYZW; |
||||
break; |
||||
|
||||
case TGSI_OPCODE_DPH: |
||||
read_mask = src_idx == 0 ? TGSI_WRITEMASK_XYZ : TGSI_WRITEMASK_XYZW; |
||||
break; |
||||
|
||||
case TGSI_OPCODE_TEX: |
||||
case TGSI_OPCODE_TXD: |
||||
case TGSI_OPCODE_TXB: |
||||
case TGSI_OPCODE_TXL: |
||||
case TGSI_OPCODE_TXP: |
||||
if (src_idx == 0) { |
||||
/* Note that the SHADOW variants use the Z component too */ |
||||
switch (inst->Texture.Texture) { |
||||
case TGSI_TEXTURE_1D: |
||||
read_mask = TGSI_WRITEMASK_X; |
||||
break; |
||||
case TGSI_TEXTURE_SHADOW1D: |
||||
read_mask = TGSI_WRITEMASK_XZ; |
||||
break; |
||||
case TGSI_TEXTURE_1D_ARRAY: |
||||
case TGSI_TEXTURE_2D: |
||||
case TGSI_TEXTURE_RECT: |
||||
read_mask = TGSI_WRITEMASK_XY; |
||||
break; |
||||
case TGSI_TEXTURE_SHADOW1D_ARRAY: |
||||
case TGSI_TEXTURE_SHADOW2D: |
||||
case TGSI_TEXTURE_SHADOWRECT: |
||||
case TGSI_TEXTURE_2D_ARRAY: |
||||
case TGSI_TEXTURE_3D: |
||||
case TGSI_TEXTURE_CUBE: |
||||
case TGSI_TEXTURE_2D_MSAA: |
||||
read_mask = TGSI_WRITEMASK_XYZ; |
||||
break; |
||||
case TGSI_TEXTURE_SHADOW2D_ARRAY: |
||||
case TGSI_TEXTURE_CUBE_ARRAY: |
||||
case TGSI_TEXTURE_SHADOWCUBE: |
||||
case TGSI_TEXTURE_2D_ARRAY_MSAA: |
||||
case TGSI_TEXTURE_SHADOWCUBE_ARRAY: |
||||
read_mask = TGSI_WRITEMASK_XYZW; |
||||
break; |
||||
default: |
||||
assert(0); |
||||
read_mask = 0; |
||||
} |
||||
|
||||
if (inst->Instruction.Opcode != TGSI_OPCODE_TEX) { |
||||
read_mask |= TGSI_WRITEMASK_W; |
||||
} |
||||
} else { |
||||
/* A safe approximation */ |
||||
read_mask = TGSI_WRITEMASK_XYZW; |
||||
} |
||||
break; |
||||
|
||||
default: |
||||
/* Assume all channels are read */ |
||||
read_mask = TGSI_WRITEMASK_XYZW; |
||||
break; |
||||
} |
||||
|
||||
usage_mask = 0; |
||||
for (chan = 0; chan < 4; ++chan) { |
||||
if (read_mask & (1 << chan)) { |
||||
usage_mask |= 1 << tgsi_util_get_full_src_register_swizzle(src, chan); |
||||
} |
||||
} |
||||
|
||||
return usage_mask; |
||||
} |
||||
|
||||
/**
|
||||
* Convert a tgsi_ind_register into a tgsi_src_register |
||||
*/ |
||||
struct tgsi_src_register |
||||
tgsi_util_get_src_from_ind(const struct tgsi_ind_register *reg) |
||||
{ |
||||
struct tgsi_src_register src = { 0 }; |
||||
|
||||
src.File = reg->File; |
||||
src.Index = reg->Index; |
||||
src.SwizzleX = reg->Swizzle; |
||||
src.SwizzleY = reg->Swizzle; |
||||
src.SwizzleZ = reg->Swizzle; |
||||
src.SwizzleW = reg->Swizzle; |
||||
|
||||
return src; |
||||
} |
||||
|
||||
/**
|
||||
* Return the dimension of the texture coordinates (layer included for array |
||||
* textures), as well as the location of the shadow reference value or the |
||||
* sample index. |
||||
*/ |
||||
int |
||||
tgsi_util_get_texture_coord_dim(int tgsi_tex, int *shadow_or_sample) |
||||
{ |
||||
int dim; |
||||
|
||||
/*
|
||||
* Depending on the texture target, (src0.xyzw, src1.x) is interpreted |
||||
* differently: |
||||
* |
||||
* (s, X, X, X, X), for BUFFER |
||||
* (s, X, X, X, X), for 1D |
||||
* (s, t, X, X, X), for 2D, RECT |
||||
* (s, t, r, X, X), for 3D, CUBE |
||||
* |
||||
* (s, layer, X, X, X), for 1D_ARRAY |
||||
* (s, t, layer, X, X), for 2D_ARRAY |
||||
* (s, t, r, layer, X), for CUBE_ARRAY |
||||
* |
||||
* (s, X, shadow, X, X), for SHADOW1D |
||||
* (s, t, shadow, X, X), for SHADOW2D, SHADOWRECT |
||||
* (s, t, r, shadow, X), for SHADOWCUBE |
||||
* |
||||
* (s, layer, shadow, X, X), for SHADOW1D_ARRAY |
||||
* (s, t, layer, shadow, X), for SHADOW2D_ARRAY |
||||
* (s, t, r, layer, shadow), for SHADOWCUBE_ARRAY |
||||
* |
||||
* (s, t, sample, X, X), for 2D_MSAA |
||||
* (s, t, layer, sample, X), for 2D_ARRAY_MSAA |
||||
*/ |
||||
switch (tgsi_tex) { |
||||
case TGSI_TEXTURE_BUFFER: |
||||
case TGSI_TEXTURE_1D: |
||||
case TGSI_TEXTURE_SHADOW1D: |
||||
dim = 1; |
||||
break; |
||||
case TGSI_TEXTURE_2D: |
||||
case TGSI_TEXTURE_RECT: |
||||
case TGSI_TEXTURE_1D_ARRAY: |
||||
case TGSI_TEXTURE_SHADOW2D: |
||||
case TGSI_TEXTURE_SHADOWRECT: |
||||
case TGSI_TEXTURE_SHADOW1D_ARRAY: |
||||
case TGSI_TEXTURE_2D_MSAA: |
||||
dim = 2; |
||||
break; |
||||
case TGSI_TEXTURE_3D: |
||||
case TGSI_TEXTURE_CUBE: |
||||
case TGSI_TEXTURE_2D_ARRAY: |
||||
case TGSI_TEXTURE_SHADOWCUBE: |
||||
case TGSI_TEXTURE_SHADOW2D_ARRAY: |
||||
case TGSI_TEXTURE_2D_ARRAY_MSAA: |
||||
dim = 3; |
||||
break; |
||||
case TGSI_TEXTURE_CUBE_ARRAY: |
||||
case TGSI_TEXTURE_SHADOWCUBE_ARRAY: |
||||
dim = 4; |
||||
break; |
||||
default: |
||||
assert(!"unknown texture target"); |
||||
dim = 0; |
||||
break; |
||||
} |
||||
|
||||
if (shadow_or_sample) { |
||||
switch (tgsi_tex) { |
||||
case TGSI_TEXTURE_SHADOW1D: |
||||
/* there is a gap */ |
||||
*shadow_or_sample = 2; |
||||
break; |
||||
case TGSI_TEXTURE_SHADOW2D: |
||||
case TGSI_TEXTURE_SHADOWRECT: |
||||
case TGSI_TEXTURE_SHADOWCUBE: |
||||
case TGSI_TEXTURE_SHADOW1D_ARRAY: |
||||
case TGSI_TEXTURE_SHADOW2D_ARRAY: |
||||
case TGSI_TEXTURE_SHADOWCUBE_ARRAY: |
||||
*shadow_or_sample = dim; |
||||
break; |
||||
case TGSI_TEXTURE_2D_MSAA: |
||||
case TGSI_TEXTURE_2D_ARRAY_MSAA: |
||||
*shadow_or_sample = 3; |
||||
break; |
||||
default: |
||||
/* no shadow nor sample */ |
||||
*shadow_or_sample = -1; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return dim; |
||||
} |
@ -0,0 +1,89 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 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 TGSI_UTIL_H |
||||
#define TGSI_UTIL_H |
||||
|
||||
#if defined __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
struct tgsi_src_register; |
||||
struct tgsi_full_src_register; |
||||
struct tgsi_full_instruction; |
||||
|
||||
void * |
||||
tgsi_align_128bit( |
||||
void *unaligned ); |
||||
|
||||
unsigned |
||||
tgsi_util_get_src_register_swizzle( |
||||
const struct tgsi_src_register *reg, |
||||
unsigned component ); |
||||
|
||||
|
||||
unsigned |
||||
tgsi_util_get_full_src_register_swizzle( |
||||
const struct tgsi_full_src_register *reg, |
||||
unsigned component ); |
||||
|
||||
void |
||||
tgsi_util_set_src_register_swizzle( |
||||
struct tgsi_src_register *reg, |
||||
unsigned swizzle, |
||||
unsigned component ); |
||||
|
||||
#define TGSI_UTIL_SIGN_CLEAR 0 /* Force positive */ |
||||
#define TGSI_UTIL_SIGN_SET 1 /* Force negative */ |
||||
#define TGSI_UTIL_SIGN_TOGGLE 2 /* Negate */ |
||||
#define TGSI_UTIL_SIGN_KEEP 3 /* No change */ |
||||
|
||||
unsigned |
||||
tgsi_util_get_full_src_register_sign_mode( |
||||
const struct tgsi_full_src_register *reg, |
||||
unsigned component ); |
||||
|
||||
void |
||||
tgsi_util_set_full_src_register_sign_mode( |
||||
struct tgsi_full_src_register *reg, |
||||
unsigned sign_mode ); |
||||
|
||||
unsigned |
||||
tgsi_util_get_inst_usage_mask(const struct tgsi_full_instruction *inst, |
||||
unsigned src_idx); |
||||
|
||||
struct tgsi_src_register |
||||
tgsi_util_get_src_from_ind(const struct tgsi_ind_register *reg); |
||||
|
||||
int |
||||
tgsi_util_get_texture_coord_dim(int tgsi_tex, int *shadow_or_sample); |
||||
|
||||
#if defined __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* TGSI_UTIL_H */ |
@ -0,0 +1,349 @@ |
||||
/**
|
||||
* Many similar implementations exist. See for example libwsbm |
||||
* or the linux kernel include/atomic.h |
||||
* |
||||
* No copyright claimed on this file. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef U_ATOMIC_H |
||||
#define U_ATOMIC_H |
||||
|
||||
#include "pipe/p_compiler.h" |
||||
#include "pipe/p_defines.h" |
||||
|
||||
/* Favor OS-provided implementations.
|
||||
* |
||||
* Where no OS-provided implementation is available, fall back to |
||||
* locally coded assembly, compiler intrinsic or ultimately a |
||||
* mutex-based implementation. |
||||
*/ |
||||
#if defined(PIPE_OS_SOLARIS) |
||||
#define PIPE_ATOMIC_OS_SOLARIS |
||||
#elif defined(PIPE_CC_MSVC) |
||||
#define PIPE_ATOMIC_MSVC_INTRINSIC |
||||
#elif (defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86)) |
||||
#define PIPE_ATOMIC_ASM_MSVC_X86 |
||||
#elif (defined(PIPE_CC_GCC) && defined(PIPE_ARCH_X86)) |
||||
#define PIPE_ATOMIC_ASM_GCC_X86 |
||||
#elif (defined(PIPE_CC_GCC) && defined(PIPE_ARCH_X86_64)) |
||||
#define PIPE_ATOMIC_ASM_GCC_X86_64 |
||||
#elif defined(PIPE_CC_GCC) && (PIPE_CC_GCC_VERSION >= 401) |
||||
#define PIPE_ATOMIC_GCC_INTRINSIC |
||||
#else |
||||
#error "Unsupported platform" |
||||
#endif |
||||
|
||||
|
||||
#if defined(PIPE_ATOMIC_ASM_GCC_X86_64) |
||||
#define PIPE_ATOMIC "GCC x86_64 assembly" |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
#define p_atomic_set(_v, _i) (*(_v) = (_i)) |
||||
#define p_atomic_read(_v) (*(_v)) |
||||
|
||||
static INLINE boolean |
||||
p_atomic_dec_zero(int32_t *v) |
||||
{ |
||||
unsigned char c; |
||||
|
||||
__asm__ __volatile__("lock; decl %0; sete %1":"+m"(*v), "=qm"(c) |
||||
::"memory"); |
||||
|
||||
return c != 0; |
||||
} |
||||
|
||||
static INLINE void |
||||
p_atomic_inc(int32_t *v) |
||||
{ |
||||
__asm__ __volatile__("lock; incl %0":"+m"(*v)); |
||||
} |
||||
|
||||
static INLINE void |
||||
p_atomic_dec(int32_t *v) |
||||
{ |
||||
__asm__ __volatile__("lock; decl %0":"+m"(*v)); |
||||
} |
||||
|
||||
static INLINE int32_t |
||||
p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new) |
||||
{ |
||||
return __sync_val_compare_and_swap(v, old, _new); |
||||
} |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* PIPE_ATOMIC_ASM_GCC_X86_64 */ |
||||
|
||||
|
||||
#if defined(PIPE_ATOMIC_ASM_GCC_X86) |
||||
|
||||
#define PIPE_ATOMIC "GCC x86 assembly" |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
#define p_atomic_set(_v, _i) (*(_v) = (_i)) |
||||
#define p_atomic_read(_v) (*(_v)) |
||||
|
||||
static INLINE boolean |
||||
p_atomic_dec_zero(int32_t *v) |
||||
{ |
||||
unsigned char c; |
||||
|
||||
__asm__ __volatile__("lock; decl %0; sete %1":"+m"(*v), "=qm"(c) |
||||
::"memory"); |
||||
|
||||
return c != 0; |
||||
} |
||||
|
||||
static INLINE void |
||||
p_atomic_inc(int32_t *v) |
||||
{ |
||||
__asm__ __volatile__("lock; incl %0":"+m"(*v)); |
||||
} |
||||
|
||||
static INLINE void |
||||
p_atomic_dec(int32_t *v) |
||||
{ |
||||
__asm__ __volatile__("lock; decl %0":"+m"(*v)); |
||||
} |
||||
|
||||
static INLINE int32_t |
||||
p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new) |
||||
{ |
||||
return __sync_val_compare_and_swap(v, old, _new); |
||||
} |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif |
||||
|
||||
|
||||
|
||||
/* Implementation using GCC-provided synchronization intrinsics
|
||||
*/ |
||||
#if defined(PIPE_ATOMIC_GCC_INTRINSIC) |
||||
|
||||
#define PIPE_ATOMIC "GCC Sync Intrinsics" |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
#define p_atomic_set(_v, _i) (*(_v) = (_i)) |
||||
#define p_atomic_read(_v) (*(_v)) |
||||
|
||||
static INLINE boolean |
||||
p_atomic_dec_zero(int32_t *v) |
||||
{ |
||||
return (__sync_sub_and_fetch(v, 1) == 0); |
||||
} |
||||
|
||||
static INLINE void |
||||
p_atomic_inc(int32_t *v) |
||||
{ |
||||
(void) __sync_add_and_fetch(v, 1); |
||||
} |
||||
|
||||
static INLINE void |
||||
p_atomic_dec(int32_t *v) |
||||
{ |
||||
(void) __sync_sub_and_fetch(v, 1); |
||||
} |
||||
|
||||
static INLINE int32_t |
||||
p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new) |
||||
{ |
||||
return __sync_val_compare_and_swap(v, old, _new); |
||||
} |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif |
||||
|
||||
|
||||
|
||||
/* Unlocked version for single threaded environments, such as some
|
||||
* windows kernel modules. |
||||
*/ |
||||
#if defined(PIPE_ATOMIC_OS_UNLOCKED) |
||||
|
||||
#define PIPE_ATOMIC "Unlocked" |
||||
|
||||
#define p_atomic_set(_v, _i) (*(_v) = (_i)) |
||||
#define p_atomic_read(_v) (*(_v)) |
||||
#define p_atomic_dec_zero(_v) ((boolean) --(*(_v))) |
||||
#define p_atomic_inc(_v) ((void) (*(_v))++) |
||||
#define p_atomic_dec(_v) ((void) (*(_v))--) |
||||
#define p_atomic_cmpxchg(_v, old, _new) (*(_v) == old ? *(_v) = (_new) : *(_v)) |
||||
|
||||
#endif |
||||
|
||||
|
||||
/* Locally coded assembly for MSVC on x86:
|
||||
*/ |
||||
#if defined(PIPE_ATOMIC_ASM_MSVC_X86) |
||||
|
||||
#define PIPE_ATOMIC "MSVC x86 assembly" |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
#define p_atomic_set(_v, _i) (*(_v) = (_i)) |
||||
#define p_atomic_read(_v) (*(_v)) |
||||
|
||||
static INLINE boolean |
||||
p_atomic_dec_zero(int32_t *v) |
||||
{ |
||||
unsigned char c; |
||||
|
||||
__asm { |
||||
mov eax, [v] |
||||
lock dec dword ptr [eax] |
||||
sete byte ptr [c] |
||||
} |
||||
|
||||
return c != 0; |
||||
} |
||||
|
||||
static INLINE void |
||||
p_atomic_inc(int32_t *v) |
||||
{ |
||||
__asm { |
||||
mov eax, [v] |
||||
lock inc dword ptr [eax] |
||||
} |
||||
} |
||||
|
||||
static INLINE void |
||||
p_atomic_dec(int32_t *v) |
||||
{ |
||||
__asm { |
||||
mov eax, [v] |
||||
lock dec dword ptr [eax] |
||||
} |
||||
} |
||||
|
||||
static INLINE int32_t |
||||
p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new) |
||||
{ |
||||
int32_t orig; |
||||
|
||||
__asm { |
||||
mov ecx, [v] |
||||
mov eax, [old] |
||||
mov edx, [_new] |
||||
lock cmpxchg [ecx], edx |
||||
mov [orig], eax |
||||
} |
||||
|
||||
return orig; |
||||
} |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif |
||||
|
||||
|
||||
#if defined(PIPE_ATOMIC_MSVC_INTRINSIC) |
||||
|
||||
#define PIPE_ATOMIC "MSVC Intrinsics" |
||||
|
||||
#include <intrin.h> |
||||
|
||||
#pragma intrinsic(_InterlockedIncrement) |
||||
#pragma intrinsic(_InterlockedDecrement) |
||||
#pragma intrinsic(_InterlockedCompareExchange) |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
#define p_atomic_set(_v, _i) (*(_v) = (_i)) |
||||
#define p_atomic_read(_v) (*(_v)) |
||||
|
||||
static INLINE boolean |
||||
p_atomic_dec_zero(int32_t *v) |
||||
{ |
||||
return _InterlockedDecrement((long *)v) == 0; |
||||
} |
||||
|
||||
static INLINE void |
||||
p_atomic_inc(int32_t *v) |
||||
{ |
||||
_InterlockedIncrement((long *)v); |
||||
} |
||||
|
||||
static INLINE void |
||||
p_atomic_dec(int32_t *v) |
||||
{ |
||||
_InterlockedDecrement((long *)v); |
||||
} |
||||
|
||||
static INLINE int32_t |
||||
p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new) |
||||
{ |
||||
return _InterlockedCompareExchange((long *)v, _new, old); |
||||
} |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif |
||||
|
||||
#if defined(PIPE_ATOMIC_OS_SOLARIS) |
||||
|
||||
#define PIPE_ATOMIC "Solaris OS atomic functions" |
||||
|
||||
#include <atomic.h> |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
#define p_atomic_set(_v, _i) (*(_v) = (_i)) |
||||
#define p_atomic_read(_v) (*(_v)) |
||||
|
||||
static INLINE boolean |
||||
p_atomic_dec_zero(int32_t *v) |
||||
{ |
||||
uint32_t n = atomic_dec_32_nv((uint32_t *) v); |
||||
|
||||
return n != 0; |
||||
} |
||||
|
||||
#define p_atomic_inc(_v) atomic_inc_32((uint32_t *) _v) |
||||
#define p_atomic_dec(_v) atomic_dec_32((uint32_t *) _v) |
||||
|
||||
#define p_atomic_cmpxchg(_v, _old, _new) \ |
||||
atomic_cas_32( (uint32_t *) _v, (uint32_t) _old, (uint32_t) _new) |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif |
||||
|
||||
|
||||
#ifndef PIPE_ATOMIC |
||||
#error "No pipe_atomic implementation selected" |
||||
#endif |
||||
|
||||
|
||||
|
||||
#endif /* U_ATOMIC_H */ |
@ -0,0 +1,117 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* 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 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. |
||||
*
|
||||
**************************************************************************/ |
||||
|
||||
/**
|
||||
* @file |
||||
* Generic bitmask. |
||||
*
|
||||
* @author Jose Fonseca <jfonseca@vmware.com> |
||||
*/ |
||||
|
||||
#ifndef U_HANDLE_BITMASK_H_ |
||||
#define U_HANDLE_BITMASK_H_ |
||||
|
||||
|
||||
#include "pipe/p_compiler.h" |
||||
|
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
|
||||
#define UTIL_BITMASK_INVALID_INDEX (~0U) |
||||
|
||||
|
||||
/**
|
||||
* Abstract data type to represent arbitrary set of bits. |
||||
*/ |
||||
struct util_bitmask; |
||||
|
||||
|
||||
struct util_bitmask * |
||||
util_bitmask_create(void); |
||||
|
||||
|
||||
/**
|
||||
* Search a cleared bit and set it. |
||||
*
|
||||
* It searches for the first cleared bit. |
||||
*
|
||||
* Returns the bit index on success, or UTIL_BITMASK_INVALID_INDEX on out of
|
||||
* memory growing the bitmask. |
||||
*/ |
||||
unsigned |
||||
util_bitmask_add(struct util_bitmask *bm); |
||||
|
||||
/**
|
||||
* Set a bit. |
||||
*
|
||||
* Returns the input index on success, or UTIL_BITMASK_INVALID_INDEX on out of
|
||||
* memory growing the bitmask. |
||||
*/ |
||||
unsigned |
||||
util_bitmask_set(struct util_bitmask *bm,
|
||||
unsigned index); |
||||
|
||||
void |
||||
util_bitmask_clear(struct util_bitmask *bm,
|
||||
unsigned index); |
||||
|
||||
boolean |
||||
util_bitmask_get(struct util_bitmask *bm,
|
||||
unsigned index); |
||||
|
||||
|
||||
void |
||||
util_bitmask_destroy(struct util_bitmask *bm); |
||||
|
||||
|
||||
/**
|
||||
* Search for the first set bit. |
||||
*
|
||||
* Returns UTIL_BITMASK_INVALID_INDEX if a set bit cannot be found.
|
||||
*/ |
||||
unsigned |
||||
util_bitmask_get_first_index(struct util_bitmask *bm); |
||||
|
||||
|
||||
/**
|
||||
* Search for the first set bit, starting from the giving index. |
||||
*
|
||||
* Returns UTIL_BITMASK_INVALID_INDEX if a set bit cannot be found.
|
||||
*/ |
||||
unsigned |
||||
util_bitmask_get_next_index(struct util_bitmask *bm, |
||||
unsigned index); |
||||
|
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* U_HANDLE_BITMASK_H_ */ |
@ -0,0 +1,80 @@ |
||||
#ifndef UTIL_BOX_INLINES_H |
||||
#define UTIL_BOX_INLINES_H |
||||
|
||||
#include "pipe/p_state.h" |
||||
|
||||
static INLINE |
||||
void u_box_1d( unsigned x, |
||||
unsigned w, |
||||
struct pipe_box *box ) |
||||
{ |
||||
box->x = x; |
||||
box->y = 0; |
||||
box->z = 0; |
||||
box->width = w; |
||||
box->height = 1; |
||||
box->depth = 1; |
||||
} |
||||
|
||||
static INLINE |
||||
void u_box_2d( unsigned x, |
||||
unsigned y, |
||||
unsigned w, |
||||
unsigned h, |
||||
struct pipe_box *box ) |
||||
{ |
||||
box->x = x; |
||||
box->y = y; |
||||
box->z = 0; |
||||
box->width = w; |
||||
box->height = h; |
||||
box->depth = 1; |
||||
} |
||||
|
||||
static INLINE |
||||
void u_box_origin_2d( unsigned w, |
||||
unsigned h, |
||||
struct pipe_box *box ) |
||||
{ |
||||
box->x = 0; |
||||
box->y = 0; |
||||
box->z = 0; |
||||
box->width = w; |
||||
box->height = h; |
||||
box->depth = 1; |
||||
} |
||||
|
||||
static INLINE |
||||
void u_box_2d_zslice( unsigned x, |
||||
unsigned y, |
||||
unsigned z, |
||||
unsigned w, |
||||
unsigned h, |
||||
struct pipe_box *box ) |
||||
{ |
||||
box->x = x; |
||||
box->y = y; |
||||
box->z = z; |
||||
box->width = w; |
||||
box->height = h; |
||||
box->depth = 1; |
||||
} |
||||
|
||||
static INLINE |
||||
void u_box_3d( unsigned x, |
||||
unsigned y, |
||||
unsigned z, |
||||
unsigned w, |
||||
unsigned h, |
||||
unsigned d, |
||||
struct pipe_box *box ) |
||||
{ |
||||
box->x = x; |
||||
box->y = y; |
||||
box->z = z; |
||||
box->width = w; |
||||
box->height = h; |
||||
box->depth = d; |
||||
} |
||||
|
||||
#endif |
@ -0,0 +1,730 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 VMware, Inc. |
||||
* Copyright (c) 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 "pipe/p_config.h" |
||||
|
||||
#include "pipe/p_compiler.h" |
||||
#include "util/u_debug.h" |
||||
#include "pipe/p_format.h" |
||||
#include "pipe/p_state.h" |
||||
#include "util/u_inlines.h" |
||||
#include "util/u_format.h" |
||||
#include "util/u_memory.h" |
||||
#include "util/u_string.h" |
||||
#include "util/u_math.h" |
||||
#include "util/u_tile.h" |
||||
#include "util/u_prim.h" |
||||
#include "util/u_surface.h" |
||||
|
||||
#include <stdio.h> |
||||
#include <limits.h> /* CHAR_BIT */ |
||||
#include <ctype.h> /* isalnum */ |
||||
|
||||
void _debug_vprintf(const char *format, va_list ap) |
||||
{ |
||||
static char buf[4096] = {'\0'}; |
||||
#if defined(PIPE_OS_WINDOWS) || defined(PIPE_SUBSYSTEM_EMBEDDED) |
||||
/* We buffer until we find a newline. */ |
||||
size_t len = strlen(buf); |
||||
int ret = util_vsnprintf(buf + len, sizeof(buf) - len, format, ap); |
||||
if(ret > (int)(sizeof(buf) - len - 1) || util_strchr(buf + len, '\n')) { |
||||
os_log_message(buf); |
||||
buf[0] = '\0'; |
||||
} |
||||
#else |
||||
util_vsnprintf(buf, sizeof(buf), format, ap); |
||||
os_log_message(buf); |
||||
#endif |
||||
} |
||||
|
||||
|
||||
#ifdef DEBUG |
||||
void debug_print_blob( const char *name, |
||||
const void *blob, |
||||
unsigned size ) |
||||
{ |
||||
const unsigned *ublob = (const unsigned *)blob; |
||||
unsigned i; |
||||
|
||||
debug_printf("%s (%d dwords%s)\n", name, size/4, |
||||
size%4 ? "... plus a few bytes" : ""); |
||||
|
||||
for (i = 0; i < size/4; i++) { |
||||
debug_printf("%d:\t%08x\n", i, ublob[i]); |
||||
} |
||||
} |
||||
#endif |
||||
|
||||
|
||||
static boolean |
||||
debug_get_option_should_print(void) |
||||
{ |
||||
static boolean first = TRUE; |
||||
static boolean value = FALSE; |
||||
|
||||
if (!first) |
||||
return value; |
||||
|
||||
/* Oh hey this will call into this function,
|
||||
* but its cool since we set first to false |
||||
*/ |
||||
first = FALSE; |
||||
value = debug_get_bool_option("GALLIUM_PRINT_OPTIONS", FALSE); |
||||
/* XXX should we print this option? Currently it wont */ |
||||
return value; |
||||
} |
||||
|
||||
const char * |
||||
debug_get_option(const char *name, const char *dfault) |
||||
{ |
||||
const char *result; |
||||
|
||||
result = os_get_option(name); |
||||
if(!result) |
||||
result = dfault; |
||||
|
||||
if (debug_get_option_should_print()) |
||||
debug_printf("%s: %s = %s\n", __FUNCTION__, name, result ? result : "(null)"); |
||||
|
||||
return result; |
||||
} |
||||
|
||||
boolean |
||||
debug_get_bool_option(const char *name, boolean dfault) |
||||
{ |
||||
const char *str = os_get_option(name); |
||||
boolean result; |
||||
|
||||
if(str == NULL) |
||||
result = dfault; |
||||
else if(!util_strcmp(str, "n")) |
||||
result = FALSE; |
||||
else if(!util_strcmp(str, "no")) |
||||
result = FALSE; |
||||
else if(!util_strcmp(str, "0")) |
||||
result = FALSE; |
||||
else if(!util_strcmp(str, "f")) |
||||
result = FALSE; |
||||
else if(!util_strcmp(str, "F")) |
||||
result = FALSE; |
||||
else if(!util_strcmp(str, "false")) |
||||
result = FALSE; |
||||
else if(!util_strcmp(str, "FALSE")) |
||||
result = FALSE; |
||||
else |
||||
result = TRUE; |
||||
|
||||
if (debug_get_option_should_print()) |
||||
debug_printf("%s: %s = %s\n", __FUNCTION__, name, result ? "TRUE" : "FALSE"); |
||||
|
||||
return result; |
||||
} |
||||
|
||||
|
||||
long |
||||
debug_get_num_option(const char *name, long dfault) |
||||
{ |
||||
long result; |
||||
const char *str; |
||||
|
||||
str = os_get_option(name); |
||||
if(!str) |
||||
result = dfault; |
||||
else { |
||||
long sign; |
||||
char c; |
||||
c = *str++; |
||||
if(c == '-') { |
||||
sign = -1; |
||||
c = *str++; |
||||
}
|
||||
else { |
||||
sign = 1; |
||||
} |
||||
result = 0; |
||||
while('0' <= c && c <= '9') { |
||||
result = result*10 + (c - '0'); |
||||
c = *str++; |
||||
} |
||||
result *= sign; |
||||
} |
||||
|
||||
if (debug_get_option_should_print()) |
||||
debug_printf("%s: %s = %li\n", __FUNCTION__, name, result); |
||||
|
||||
return result; |
||||
} |
||||
|
||||
static boolean str_has_option(const char *str, const char *name) |
||||
{ |
||||
/* Empty string. */ |
||||
if (!*str) { |
||||
return FALSE; |
||||
} |
||||
|
||||
/* OPTION=all */ |
||||
if (!util_strcmp(str, "all")) { |
||||
return TRUE; |
||||
} |
||||
|
||||
/* Find 'name' in 'str' surrounded by non-alphanumeric characters. */ |
||||
{ |
||||
const char *start = str; |
||||
unsigned name_len = strlen(name); |
||||
|
||||
/* 'start' is the beginning of the currently-parsed word,
|
||||
* we increment 'str' each iteration. |
||||
* if we find either the end of string or a non-alphanumeric character, |
||||
* we compare 'start' up to 'str-1' with 'name'. */ |
||||
|
||||
while (1) { |
||||
if (!*str || !(isalnum(*str) || *str == '_')) { |
||||
if (str-start == name_len && |
||||
!memcmp(start, name, name_len)) { |
||||
return TRUE; |
||||
} |
||||
|
||||
if (!*str) { |
||||
return FALSE; |
||||
} |
||||
|
||||
start = str+1; |
||||
} |
||||
|
||||
str++; |
||||
} |
||||
} |
||||
|
||||
return FALSE; |
||||
} |
||||
|
||||
unsigned long |
||||
debug_get_flags_option(const char *name,
|
||||
const struct debug_named_value *flags, |
||||
unsigned long dfault) |
||||
{ |
||||
unsigned long result; |
||||
const char *str; |
||||
const struct debug_named_value *orig = flags; |
||||
unsigned namealign = 0; |
||||
|
||||
str = os_get_option(name); |
||||
if(!str) |
||||
result = dfault; |
||||
else if (!util_strcmp(str, "help")) { |
||||
result = dfault; |
||||
_debug_printf("%s: help for %s:\n", __FUNCTION__, name); |
||||
for (; flags->name; ++flags) |
||||
namealign = MAX2(namealign, strlen(flags->name)); |
||||
for (flags = orig; flags->name; ++flags) |
||||
_debug_printf("| %*s [0x%0*lx]%s%s\n", namealign, flags->name, |
||||
(int)sizeof(unsigned long)*CHAR_BIT/4, flags->value, |
||||
flags->desc ? " " : "", flags->desc ? flags->desc : ""); |
||||
} |
||||
else { |
||||
result = 0; |
||||
while( flags->name ) { |
||||
if (str_has_option(str, flags->name)) |
||||
result |= flags->value; |
||||
++flags; |
||||
} |
||||
} |
||||
|
||||
if (debug_get_option_should_print()) { |
||||
if (str) { |
||||
debug_printf("%s: %s = 0x%lx (%s)\n", __FUNCTION__, name, result, str); |
||||
} else { |
||||
debug_printf("%s: %s = 0x%lx\n", __FUNCTION__, name, result); |
||||
} |
||||
} |
||||
|
||||
return result; |
||||
} |
||||
|
||||
|
||||
void _debug_assert_fail(const char *expr,
|
||||
const char *file,
|
||||
unsigned line,
|
||||
const char *function)
|
||||
{ |
||||
_debug_printf("%s:%u:%s: Assertion `%s' failed.\n", file, line, function, expr); |
||||
if (debug_get_bool_option("GALLIUM_ABORT_ON_ASSERT", TRUE)) |
||||
os_abort(); |
||||
else |
||||
_debug_printf("continuing...\n"); |
||||
} |
||||
|
||||
|
||||
const char * |
||||
debug_dump_enum(const struct debug_named_value *names,
|
||||
unsigned long value) |
||||
{ |
||||
static char rest[64]; |
||||
|
||||
while(names->name) { |
||||
if(names->value == value) |
||||
return names->name; |
||||
++names; |
||||
} |
||||
|
||||
util_snprintf(rest, sizeof(rest), "0x%08lx", value); |
||||
return rest; |
||||
} |
||||
|
||||
|
||||
const char * |
||||
debug_dump_enum_noprefix(const struct debug_named_value *names,
|
||||
const char *prefix, |
||||
unsigned long value) |
||||
{ |
||||
static char rest[64]; |
||||
|
||||
while(names->name) { |
||||
if(names->value == value) { |
||||
const char *name = names->name; |
||||
while (*name == *prefix) { |
||||
name++; |
||||
prefix++; |
||||
} |
||||
return name; |
||||
} |
||||
++names; |
||||
} |
||||
|
||||
|
||||
|
||||
util_snprintf(rest, sizeof(rest), "0x%08lx", value); |
||||
return rest; |
||||
} |
||||
|
||||
|
||||
const char * |
||||
debug_dump_flags(const struct debug_named_value *names,
|
||||
unsigned long value) |
||||
{ |
||||
static char output[4096]; |
||||
static char rest[256]; |
||||
int first = 1; |
||||
|
||||
output[0] = '\0'; |
||||
|
||||
while(names->name) { |
||||
if((names->value & value) == names->value) { |
||||
if (!first) |
||||
util_strncat(output, "|", sizeof(output)); |
||||
else |
||||
first = 0; |
||||
util_strncat(output, names->name, sizeof(output) - 1); |
||||
output[sizeof(output) - 1] = '\0'; |
||||
value &= ~names->value; |
||||
} |
||||
++names; |
||||
} |
||||
|
||||
if (value) { |
||||
if (!first) |
||||
util_strncat(output, "|", sizeof(output)); |
||||
else |
||||
first = 0; |
||||
|
||||
util_snprintf(rest, sizeof(rest), "0x%08lx", value); |
||||
util_strncat(output, rest, sizeof(output) - 1); |
||||
output[sizeof(output) - 1] = '\0'; |
||||
} |
||||
|
||||
if(first) |
||||
return "0"; |
||||
|
||||
return output; |
||||
} |
||||
|
||||
|
||||
#ifdef DEBUG |
||||
void debug_print_format(const char *msg, unsigned fmt ) |
||||
{ |
||||
debug_printf("%s: %s\n", msg, util_format_name(fmt)); |
||||
} |
||||
#endif |
||||
|
||||
|
||||
|
||||
static const struct debug_named_value pipe_prim_names[] = { |
||||
#ifdef DEBUG |
||||
DEBUG_NAMED_VALUE(PIPE_PRIM_POINTS), |
||||
DEBUG_NAMED_VALUE(PIPE_PRIM_LINES), |
||||
DEBUG_NAMED_VALUE(PIPE_PRIM_LINE_LOOP), |
||||
DEBUG_NAMED_VALUE(PIPE_PRIM_LINE_STRIP), |
||||
DEBUG_NAMED_VALUE(PIPE_PRIM_TRIANGLES), |
||||
DEBUG_NAMED_VALUE(PIPE_PRIM_TRIANGLE_STRIP), |
||||
DEBUG_NAMED_VALUE(PIPE_PRIM_TRIANGLE_FAN), |
||||
DEBUG_NAMED_VALUE(PIPE_PRIM_QUADS), |
||||
DEBUG_NAMED_VALUE(PIPE_PRIM_QUAD_STRIP), |
||||
DEBUG_NAMED_VALUE(PIPE_PRIM_POLYGON), |
||||
DEBUG_NAMED_VALUE(PIPE_PRIM_LINES_ADJACENCY), |
||||
DEBUG_NAMED_VALUE(PIPE_PRIM_LINE_STRIP_ADJACENCY), |
||||
DEBUG_NAMED_VALUE(PIPE_PRIM_TRIANGLES_ADJACENCY), |
||||
DEBUG_NAMED_VALUE(PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY), |
||||
#endif |
||||
DEBUG_NAMED_VALUE_END |
||||
}; |
||||
|
||||
|
||||
const char *u_prim_name( unsigned prim ) |
||||
{ |
||||
return debug_dump_enum(pipe_prim_names, prim); |
||||
} |
||||
|
||||
|
||||
|
||||
#ifdef DEBUG |
||||
int fl_indent = 0; |
||||
const char* fl_function[1024]; |
||||
|
||||
int debug_funclog_enter(const char* f, const int line, const char* file) |
||||
{ |
||||
int i; |
||||
|
||||
for (i = 0; i < fl_indent; i++) |
||||
debug_printf(" "); |
||||
debug_printf("%s\n", f); |
||||
|
||||
assert(fl_indent < 1023); |
||||
fl_function[fl_indent++] = f; |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
void debug_funclog_exit(const char* f, const int line, const char* file) |
||||
{ |
||||
--fl_indent; |
||||
assert(fl_indent >= 0); |
||||
assert(fl_function[fl_indent] == f); |
||||
} |
||||
|
||||
void debug_funclog_enter_exit(const char* f, const int line, const char* file) |
||||
{ |
||||
int i; |
||||
for (i = 0; i < fl_indent; i++) |
||||
debug_printf(" "); |
||||
debug_printf("%s\n", f); |
||||
} |
||||
#endif |
||||
|
||||
|
||||
|
||||
#ifdef DEBUG |
||||
/**
|
||||
* Dump an image to .ppm file. |
||||
* \param format PIPE_FORMAT_x |
||||
* \param cpp bytes per pixel |
||||
* \param width width in pixels |
||||
* \param height height in pixels |
||||
* \param stride row stride in bytes |
||||
*/ |
||||
void debug_dump_image(const char *prefix, |
||||
enum pipe_format format, unsigned cpp, |
||||
unsigned width, unsigned height, |
||||
unsigned stride, |
||||
const void *data)
|
||||
{ |
||||
/* write a ppm file */ |
||||
char filename[256]; |
||||
unsigned char *rgb8; |
||||
FILE *f; |
||||
|
||||
util_snprintf(filename, sizeof(filename), "%s.ppm", prefix); |
||||
|
||||
rgb8 = MALLOC(height * width * 3); |
||||
if (!rgb8) { |
||||
return; |
||||
} |
||||
|
||||
util_format_translate( |
||||
PIPE_FORMAT_R8G8B8_UNORM, |
||||
rgb8, width * 3, |
||||
0, 0, |
||||
format, |
||||
data, stride, |
||||
0, 0, width, height); |
||||
|
||||
/* Must be opened in binary mode or DOS line ending causes data
|
||||
* to be read with one byte offset. |
||||
*/ |
||||
f = fopen(filename, "wb"); |
||||
if (f) { |
||||
fprintf(f, "P6\n"); |
||||
fprintf(f, "# ppm-file created by gallium\n"); |
||||
fprintf(f, "%i %i\n", width, height); |
||||
fprintf(f, "255\n"); |
||||
fwrite(rgb8, 1, height * width * 3, f); |
||||
fclose(f); |
||||
} |
||||
else { |
||||
fprintf(stderr, "Can't open %s for writing\n", filename); |
||||
} |
||||
|
||||
FREE(rgb8); |
||||
} |
||||
|
||||
/* FIXME: dump resources, not surfaces... */ |
||||
void debug_dump_surface(struct pipe_context *pipe, |
||||
const char *prefix, |
||||
struct pipe_surface *surface) |
||||
{ |
||||
struct pipe_resource *texture; |
||||
struct pipe_transfer *transfer; |
||||
void *data; |
||||
|
||||
if (!surface) |
||||
return; |
||||
|
||||
/* XXX: this doesn't necessarily work, as the driver may be using
|
||||
* temporary storage for the surface which hasn't been propagated |
||||
* back into the texture. Need to nail down the semantics of views |
||||
* and transfers a bit better before we can say if extra work needs |
||||
* to be done here: |
||||
*/ |
||||
texture = surface->texture; |
||||
|
||||
data = pipe_transfer_map(pipe, texture, surface->u.tex.level, |
||||
surface->u.tex.first_layer, |
||||
PIPE_TRANSFER_READ, |
||||
0, 0, surface->width, surface->height, &transfer); |
||||
if(!data) |
||||
return; |
||||
|
||||
debug_dump_image(prefix, |
||||
texture->format, |
||||
util_format_get_blocksize(texture->format), |
||||
util_format_get_nblocksx(texture->format, surface->width), |
||||
util_format_get_nblocksy(texture->format, surface->height), |
||||
transfer->stride, |
||||
data); |
||||
|
||||
pipe->transfer_unmap(pipe, transfer); |
||||
} |
||||
|
||||
|
||||
void debug_dump_texture(struct pipe_context *pipe, |
||||
const char *prefix, |
||||
struct pipe_resource *texture) |
||||
{ |
||||
struct pipe_surface *surface, surf_tmpl; |
||||
|
||||
if (!texture) |
||||
return; |
||||
|
||||
/* XXX for now, just dump image for layer=0, level=0 */ |
||||
u_surface_default_template(&surf_tmpl, texture); |
||||
surface = pipe->create_surface(pipe, texture, &surf_tmpl); |
||||
if (surface) { |
||||
debug_dump_surface(pipe, prefix, surface); |
||||
pipe->surface_destroy(pipe, surface); |
||||
} |
||||
} |
||||
|
||||
|
||||
#pragma pack(push,2) |
||||
struct bmp_file_header { |
||||
uint16_t bfType; |
||||
uint32_t bfSize; |
||||
uint16_t bfReserved1; |
||||
uint16_t bfReserved2; |
||||
uint32_t bfOffBits; |
||||
}; |
||||
#pragma pack(pop) |
||||
|
||||
struct bmp_info_header { |
||||
uint32_t biSize; |
||||
int32_t biWidth; |
||||
int32_t biHeight; |
||||
uint16_t biPlanes; |
||||
uint16_t biBitCount; |
||||
uint32_t biCompression; |
||||
uint32_t biSizeImage; |
||||
int32_t biXPelsPerMeter; |
||||
int32_t biYPelsPerMeter; |
||||
uint32_t biClrUsed; |
||||
uint32_t biClrImportant; |
||||
}; |
||||
|
||||
struct bmp_rgb_quad { |
||||
uint8_t rgbBlue; |
||||
uint8_t rgbGreen; |
||||
uint8_t rgbRed; |
||||
uint8_t rgbAlpha; |
||||
}; |
||||
|
||||
void |
||||
debug_dump_surface_bmp(struct pipe_context *pipe, |
||||
const char *filename, |
||||
struct pipe_surface *surface) |
||||
{ |
||||
struct pipe_transfer *transfer; |
||||
struct pipe_resource *texture = surface->texture; |
||||
void *ptr; |
||||
|
||||
ptr = pipe_transfer_map(pipe, texture, surface->u.tex.level, |
||||
surface->u.tex.first_layer, PIPE_TRANSFER_READ, |
||||
0, 0, surface->width, surface->height, &transfer); |
||||
|
||||
debug_dump_transfer_bmp(pipe, filename, transfer, ptr); |
||||
|
||||
pipe->transfer_unmap(pipe, transfer); |
||||
} |
||||
|
||||
void |
||||
debug_dump_transfer_bmp(struct pipe_context *pipe, |
||||
const char *filename, |
||||
struct pipe_transfer *transfer, void *ptr) |
||||
{ |
||||
float *rgba; |
||||
|
||||
if (!transfer) |
||||
goto error1; |
||||
|
||||
rgba = MALLOC(transfer->box.width * |
||||
transfer->box.height * |
||||
transfer->box.depth * |
||||
4*sizeof(float)); |
||||
if(!rgba) |
||||
goto error1; |
||||
|
||||
pipe_get_tile_rgba(transfer, ptr, 0, 0, |
||||
transfer->box.width, transfer->box.height, |
||||
rgba); |
||||
|
||||
debug_dump_float_rgba_bmp(filename, |
||||
transfer->box.width, transfer->box.height, |
||||
rgba, transfer->box.width); |
||||
|
||||
FREE(rgba); |
||||
error1: |
||||
; |
||||
} |
||||
|
||||
void |
||||
debug_dump_float_rgba_bmp(const char *filename, |
||||
unsigned width, unsigned height, |
||||
float *rgba, unsigned stride) |
||||
{ |
||||
FILE *stream; |
||||
struct bmp_file_header bmfh; |
||||
struct bmp_info_header bmih; |
||||
unsigned x, y; |
||||
|
||||
if(!rgba) |
||||
goto error1; |
||||
|
||||
bmfh.bfType = 0x4d42; |
||||
bmfh.bfSize = 14 + 40 + height*width*4; |
||||
bmfh.bfReserved1 = 0; |
||||
bmfh.bfReserved2 = 0; |
||||
bmfh.bfOffBits = 14 + 40; |
||||
|
||||
bmih.biSize = 40; |
||||
bmih.biWidth = width; |
||||
bmih.biHeight = height; |
||||
bmih.biPlanes = 1; |
||||
bmih.biBitCount = 32; |
||||
bmih.biCompression = 0; |
||||
bmih.biSizeImage = height*width*4; |
||||
bmih.biXPelsPerMeter = 0; |
||||
bmih.biYPelsPerMeter = 0; |
||||
bmih.biClrUsed = 0; |
||||
bmih.biClrImportant = 0; |
||||
|
||||
stream = fopen(filename, "wb"); |
||||
if(!stream) |
||||
goto error1; |
||||
|
||||
fwrite(&bmfh, 14, 1, stream); |
||||
fwrite(&bmih, 40, 1, stream); |
||||
|
||||
y = height; |
||||
while(y--) { |
||||
float *ptr = rgba + (stride * y * 4); |
||||
for(x = 0; x < width; ++x) |
||||
{ |
||||
struct bmp_rgb_quad pixel; |
||||
pixel.rgbRed = float_to_ubyte(ptr[x*4 + 0]); |
||||
pixel.rgbGreen = float_to_ubyte(ptr[x*4 + 1]); |
||||
pixel.rgbBlue = float_to_ubyte(ptr[x*4 + 2]); |
||||
pixel.rgbAlpha = float_to_ubyte(ptr[x*4 + 3]); |
||||
fwrite(&pixel, 1, 4, stream); |
||||
} |
||||
} |
||||
|
||||
fclose(stream); |
||||
error1: |
||||
; |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Print PIPE_TRANSFER_x flags with a message. |
||||
*/ |
||||
void |
||||
debug_print_transfer_flags(const char *msg, unsigned usage) |
||||
{ |
||||
#define FLAG(x) { x, #x } |
||||
static const struct { |
||||
unsigned bit; |
||||
const char *name; |
||||
} flags[] = { |
||||
FLAG(PIPE_TRANSFER_READ), |
||||
FLAG(PIPE_TRANSFER_WRITE), |
||||
FLAG(PIPE_TRANSFER_MAP_DIRECTLY), |
||||
FLAG(PIPE_TRANSFER_DISCARD_RANGE), |
||||
FLAG(PIPE_TRANSFER_DONTBLOCK), |
||||
FLAG(PIPE_TRANSFER_UNSYNCHRONIZED), |
||||
FLAG(PIPE_TRANSFER_FLUSH_EXPLICIT), |
||||
FLAG(PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) |
||||
}; |
||||
unsigned i; |
||||
|
||||
debug_printf("%s ", msg); |
||||
|
||||
for (i = 0; i < Elements(flags); i++) { |
||||
if (usage & flags[i].bit) { |
||||
debug_printf("%s", flags[i].name); |
||||
usage &= ~flags[i].bit; |
||||
if (usage) { |
||||
debug_printf(" | "); |
||||
} |
||||
} |
||||
} |
||||
|
||||
debug_printf("\n"); |
||||
#undef FLAG |
||||
} |
||||
|
||||
|
||||
|
||||
#endif |
@ -0,0 +1,459 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* 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. |
||||
*
|
||||
**************************************************************************/ |
||||
|
||||
/**
|
||||
* @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 <jfonseca@vmware.com> |
||||
*/ |
||||
|
||||
#ifndef U_DEBUG_H_ |
||||
#define U_DEBUG_H_ |
||||
|
||||
|
||||
#include "os/os_misc.h" |
||||
|
||||
#include "pipe/p_format.h" |
||||
|
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
|
||||
#if defined(__GNUC__) |
||||
#define _util_printf_format(fmt, list) __attribute__ ((format (printf, fmt, list))) |
||||
#else |
||||
#define _util_printf_format(fmt, list) |
||||
#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) |
||||
*/ |
||||
#if !defined(PIPE_OS_HAIKU) |
||||
static INLINE void |
||||
debug_printf(const char *format, ...) _util_printf_format(1,2); |
||||
|
||||
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 |
||||
} |
||||
#else /* is Haiku */ |
||||
/* Haiku provides debug_printf in libroot with OS.h */ |
||||
#include <OS.h> |
||||
#endif |
||||
|
||||
|
||||
/*
|
||||
* ... isn't portable so we need to pass arguments in parentheses. |
||||
* |
||||
* usage: |
||||
* debug_printf_once(("answer: %i\n", 42)); |
||||
*/ |
||||
#define debug_printf_once(args) \ |
||||
do { \
|
||||
static boolean once = TRUE; \
|
||||
if (once) { \
|
||||
once = FALSE; \
|
||||
debug_printf args; \
|
||||
} \
|
||||
} while (0) |
||||
|
||||
|
||||
#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 |
||||
|
||||
|
||||
/**
|
||||
* Hard-coded breakpoint. |
||||
*/ |
||||
#ifdef DEBUG |
||||
#define debug_break() os_break() |
||||
#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. |
||||
* |
||||
* For non debug builds the assert macro will expand to a no-op, so do not |
||||
* call functions with side effects in the assert expression. |
||||
*/ |
||||
#ifdef DEBUG |
||||
#define debug_assert(expr) ((expr) ? (void)0 : _debug_assert_fail(#expr, __FILE__, __LINE__, __FUNCTION__)) |
||||
#else |
||||
#define debug_assert(expr) do { } while (0 && (expr)) |
||||
#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\n", __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 |
||||
|
||||
|
||||
/**
|
||||
* Emit a warning message, but only once. |
||||
*/ |
||||
#ifdef DEBUG |
||||
#define debug_warn_once(__msg) \ |
||||
do { \
|
||||
static bool warned = FALSE; \
|
||||
if (!warned) { \
|
||||
_debug_printf("%s:%u:%s: one time warning: %s\n", \
|
||||
__FILE__, __LINE__, __FUNCTION__, __msg); \
|
||||
warned = TRUE; \
|
||||
} \
|
||||
} while (0) |
||||
#else |
||||
#define debug_warn_once(__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; |
||||
const char *desc; |
||||
}; |
||||
|
||||
|
||||
/**
|
||||
* 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, NULL} |
||||
#define DEBUG_NAMED_VALUE_WITH_DESCRIPTION(__symbol, __desc) {#__symbol, (unsigned long)__symbol, __desc} |
||||
#define DEBUG_NAMED_VALUE_END {NULL, 0, NULL} |
||||
|
||||
|
||||
/**
|
||||
* 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); |
||||
|
||||
|
||||
/**
|
||||
* Function enter exit loggers |
||||
*/ |
||||
#ifdef DEBUG |
||||
int debug_funclog_enter(const char* f, const int line, const char* file); |
||||
void debug_funclog_exit(const char* f, const int line, const char* file); |
||||
void debug_funclog_enter_exit(const char* f, const int line, const char* file); |
||||
|
||||
#define DEBUG_FUNCLOG_ENTER() \ |
||||
int __debug_decleration_work_around = \
|
||||
debug_funclog_enter(__FUNCTION__, __LINE__, __FILE__) |
||||
#define DEBUG_FUNCLOG_EXIT() \ |
||||
do { \
|
||||
(void)__debug_decleration_work_around; \
|
||||
debug_funclog_exit(__FUNCTION__, __LINE__, __FILE__); \
|
||||
return; \
|
||||
} while(0) |
||||
#define DEBUG_FUNCLOG_EXIT_RET(ret) \ |
||||
do { \
|
||||
(void)__debug_decleration_work_around; \
|
||||
debug_funclog_exit(__FUNCTION__, __LINE__, __FILE__); \
|
||||
return ret; \
|
||||
} while(0) |
||||
#define DEBUG_FUNCLOG_ENTER_EXIT() \ |
||||
debug_funclog_enter_exit(__FUNCTION__, __LINE__, __FILE__) |
||||
|
||||
#else |
||||
#define DEBUG_FUNCLOG_ENTER() \ |
||||
int __debug_decleration_work_around |
||||
#define DEBUG_FUNCLOG_EXIT() \ |
||||
do { (void)__debug_decleration_work_around; return; } while(0) |
||||
#define DEBUG_FUNCLOG_EXIT_RET(ret) \ |
||||
do { (void)__debug_decleration_work_around; return ret; } while(0) |
||||
#define DEBUG_FUNCLOG_ENTER_EXIT() |
||||
#endif |
||||
|
||||
|
||||
/**
|
||||
* 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); |
||||
|
||||
#define DEBUG_GET_ONCE_BOOL_OPTION(sufix, name, dfault) \ |
||||
static boolean \
|
||||
debug_get_option_ ## sufix (void) \
|
||||
{ \
|
||||
static boolean first = TRUE; \
|
||||
static boolean value; \
|
||||
if (first) { \
|
||||
first = FALSE; \
|
||||
value = debug_get_bool_option(name, dfault); \
|
||||
} \
|
||||
return value; \
|
||||
} |
||||
|
||||
#define DEBUG_GET_ONCE_NUM_OPTION(sufix, name, dfault) \ |
||||
static long \
|
||||
debug_get_option_ ## sufix (void) \
|
||||
{ \
|
||||
static boolean first = TRUE; \
|
||||
static long value; \
|
||||
if (first) { \
|
||||
first = FALSE; \
|
||||
value = debug_get_num_option(name, dfault); \
|
||||
} \
|
||||
return value; \
|
||||
} |
||||
|
||||
#define DEBUG_GET_ONCE_FLAGS_OPTION(sufix, name, flags, dfault) \ |
||||
static unsigned long \
|
||||
debug_get_option_ ## sufix (void) \
|
||||
{ \
|
||||
static boolean first = TRUE; \
|
||||
static unsigned long value; \
|
||||
if (first) { \
|
||||
first = FALSE; \
|
||||
value = debug_get_flags_option(name, flags, dfault); \
|
||||
} \
|
||||
return value; \
|
||||
} |
||||
|
||||
|
||||
unsigned long |
||||
debug_memory_begin(void); |
||||
|
||||
void
|
||||
debug_memory_end(unsigned long beginning); |
||||
|
||||
|
||||
#ifdef DEBUG |
||||
struct pipe_context; |
||||
struct pipe_surface; |
||||
struct pipe_transfer; |
||||
struct pipe_resource; |
||||
|
||||
void debug_dump_image(const char *prefix, |
||||
enum pipe_format format, unsigned cpp, |
||||
unsigned width, unsigned height, |
||||
unsigned stride, |
||||
const void *data); |
||||
void debug_dump_surface(struct pipe_context *pipe, |
||||
const char *prefix, |
||||
struct pipe_surface *surface);
|
||||
void debug_dump_texture(struct pipe_context *pipe, |
||||
const char *prefix, |
||||
struct pipe_resource *texture); |
||||
void debug_dump_surface_bmp(struct pipe_context *pipe, |
||||
const char *filename, |
||||
struct pipe_surface *surface); |
||||
void debug_dump_transfer_bmp(struct pipe_context *pipe, |
||||
const char *filename, |
||||
struct pipe_transfer *transfer, void *ptr); |
||||
void debug_dump_float_rgba_bmp(const char *filename, |
||||
unsigned width, unsigned height, |
||||
float *rgba, unsigned stride); |
||||
#else |
||||
#define debug_dump_image(prefix, format, cpp, width, height, stride, data) ((void)0) |
||||
#define debug_dump_surface(pipe, prefix, surface) ((void)0) |
||||
#define debug_dump_surface_bmp(pipe, filename, surface) ((void)0) |
||||
#define debug_dump_transfer_bmp(filename, transfer, ptr) ((void)0) |
||||
#define debug_dump_float_rgba_bmp(filename, width, height, rgba, stride) ((void)0) |
||||
#endif |
||||
|
||||
|
||||
void |
||||
debug_print_transfer_flags(const char *msg, unsigned usage); |
||||
|
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* U_DEBUG_H_ */ |
@ -0,0 +1,91 @@ |
||||
/**************************************************************************
|
||||
* |
||||
* Copyright 2010 Luca Barbieri |
||||
* |
||||
* 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 COPYRIGHT OWNER(S) 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 "pipe/p_state.h" |
||||
#include "util/u_format.h" |
||||
#include "util/u_debug_describe.h" |
||||
#include "util/u_string.h" |
||||
|
||||
void |
||||
debug_describe_reference(char* buf, const struct pipe_reference*ptr) |
||||
{ |
||||
strcpy(buf, "pipe_object"); |
||||
} |
||||
|
||||
void |
||||
debug_describe_resource(char* buf, const struct pipe_resource *ptr) |
||||
{ |
||||
switch(ptr->target) |
||||
{ |
||||
case PIPE_BUFFER: |
||||
util_sprintf(buf, "pipe_buffer<%u>", (unsigned)util_format_get_stride(ptr->format, ptr->width0)); |
||||
break; |
||||
case PIPE_TEXTURE_1D: |
||||
util_sprintf(buf, "pipe_texture1d<%u,%s,%u>", ptr->width0, util_format_short_name(ptr->format), ptr->last_level); |
||||
break; |
||||
case PIPE_TEXTURE_2D: |
||||
util_sprintf(buf, "pipe_texture2d<%u,%u,%s,%u>", ptr->width0, ptr->height0, util_format_short_name(ptr->format), ptr->last_level); |
||||
break; |
||||
case PIPE_TEXTURE_RECT: |
||||
util_sprintf(buf, "pipe_texture_rect<%u,%u,%s>", ptr->width0, ptr->height0, util_format_short_name(ptr->format)); |
||||
break; |
||||
case PIPE_TEXTURE_CUBE: |
||||
util_sprintf(buf, "pipe_texture_cube<%u,%u,%s,%u>", ptr->width0, ptr->height0, util_format_short_name(ptr->format), ptr->last_level); |
||||
break; |
||||
case PIPE_TEXTURE_3D: |
||||
util_sprintf(buf, "pipe_texture3d<%u,%u,%u,%s,%u>", ptr->width0, ptr->height0, ptr->depth0, util_format_short_name(ptr->format), ptr->last_level); |
||||
break; |
||||
default: |
||||
util_sprintf(buf, "pipe_martian_resource<%u>", ptr->target); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
void |
||||
debug_describe_surface(char* buf, const struct pipe_surface *ptr) |
||||
{ |
||||
char res[128]; |
||||
debug_describe_resource(res, ptr->texture); |
||||
util_sprintf(buf, "pipe_surface<%s,%u,%u,%u>", res, ptr->u.tex.level, ptr->u.tex.first_layer, ptr->u.tex.last_layer); |
||||
} |
||||
|
||||
void |
||||
debug_describe_sampler_view(char* buf, const struct pipe_sampler_view *ptr) |
||||
{ |
||||
char res[128]; |
||||
debug_describe_resource(res, ptr->texture); |
||||
util_sprintf(buf, "pipe_sampler_view<%s,%s>", res, util_format_short_name(ptr->format)); |
||||
} |
||||
|
||||
void |
||||
debug_describe_so_target(char* buf, |
||||
const struct pipe_stream_output_target *ptr) |
||||
{ |
||||
char res[128]; |
||||
debug_describe_resource(res, ptr->buffer); |
||||
util_sprintf(buf, "pipe_stream_output_target<%s,%u,%u>", res, |
||||
ptr->buffer_offset, ptr->buffer_size); |
||||
} |
@ -0,0 +1,51 @@ |
||||
/**************************************************************************
|
||||
* |
||||
* Copyright 2010 Luca Barbieri |
||||
* |
||||
* 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 COPYRIGHT OWNER(S) 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_DEBUG_DESCRIBE_H_ |
||||
#define U_DEBUG_DESCRIBE_H_ |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
struct pipe_reference; |
||||
struct pipe_resource; |
||||
struct pipe_surface; |
||||
struct pipe_sampler_view; |
||||
|
||||
/* a 256-byte buffer is necessary and sufficient */ |
||||
void debug_describe_reference(char* buf, const struct pipe_reference*ptr); |
||||
void debug_describe_resource(char* buf, const struct pipe_resource *ptr); |
||||
void debug_describe_surface(char* buf, const struct pipe_surface *ptr); |
||||
void debug_describe_sampler_view(char* buf, const struct pipe_sampler_view *ptr); |
||||
void debug_describe_so_target(char* buf, |
||||
const struct pipe_stream_output_target *ptr); |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* U_DEBUG_DESCRIBE_H_ */ |
@ -0,0 +1,63 @@ |
||||
/**************************************************************************
|
||||
* |
||||
* Copyright 2010 Luca Barbieri |
||||
* |
||||
* 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 COPYRIGHT OWNER(S) 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_DEBUG_REFCNT_H_ |
||||
#define U_DEBUG_REFCNT_H_ |
||||
|
||||
#include "pipe/p_config.h" |
||||
#include "pipe/p_state.h" |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
typedef void (*debug_reference_descriptor)(char*, const struct pipe_reference*); |
||||
|
||||
#if defined(DEBUG) && (!defined(PIPE_OS_WINDOWS) || defined(PIPE_SUBSYSTEM_WINDOWS_USER)) |
||||
|
||||
extern int debug_refcnt_state; |
||||
|
||||
void debug_reference_slowpath(const struct pipe_reference* p, debug_reference_descriptor get_desc, int change); |
||||
|
||||
static INLINE void debug_reference(const struct pipe_reference* p, debug_reference_descriptor get_desc, int change) |
||||
{ |
||||
if (debug_refcnt_state >= 0) |
||||
debug_reference_slowpath(p, get_desc, change); |
||||
} |
||||
|
||||
#else |
||||
|
||||
static INLINE void debug_reference(const struct pipe_reference* p, debug_reference_descriptor get_desc, int change) |
||||
{ |
||||
} |
||||
|
||||
#endif |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* U_DEBUG_REFCNT_H_ */ |
@ -0,0 +1,147 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2006 VMware, Inc., Bismarck, ND. USA. |
||||
* 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 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 COPYRIGHT HOLDERS, AUTHORS 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. |
||||
* |
||||
* The above copyright notice and this permission notice (including the |
||||
* next paragraph) shall be included in all copies or substantial portions |
||||
* of the Software. |
||||
*
|
||||
**************************************************************************/ |
||||
|
||||
/**
|
||||
* \file |
||||
* List macros heavily inspired by the Linux kernel |
||||
* list handling. No list looping yet. |
||||
*
|
||||
* Is not threadsafe, so common operations need to |
||||
* be protected using an external mutex. |
||||
*/ |
||||
|
||||
#ifndef _U_DOUBLE_LIST_H_ |
||||
#define _U_DOUBLE_LIST_H_ |
||||
|
||||
|
||||
#include <stddef.h> |
||||
#include "pipe/p_compiler.h" |
||||
|
||||
|
||||
struct list_head |
||||
{ |
||||
struct list_head *prev; |
||||
struct list_head *next; |
||||
}; |
||||
|
||||
static INLINE void list_inithead(struct list_head *item) |
||||
{ |
||||
item->prev = item; |
||||
item->next = item; |
||||
} |
||||
|
||||
static INLINE void list_add(struct list_head *item, struct list_head *list) |
||||
{ |
||||
item->prev = list; |
||||
item->next = list->next; |
||||
list->next->prev = item; |
||||
list->next = item; |
||||
} |
||||
|
||||
static INLINE void list_addtail(struct list_head *item, struct list_head *list) |
||||
{ |
||||
item->next = list; |
||||
item->prev = list->prev; |
||||
list->prev->next = item; |
||||
list->prev = item; |
||||
} |
||||
|
||||
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; |
||||
} |
||||
|
||||
static INLINE void list_del(struct list_head *item) |
||||
{ |
||||
item->prev->next = item->next; |
||||
item->next->prev = item->prev; |
||||
item->prev = item->next = NULL; |
||||
} |
||||
|
||||
static INLINE void list_delinit(struct list_head *item) |
||||
{ |
||||
item->prev->next = item->next; |
||||
item->next->prev = item->prev; |
||||
item->next = item; |
||||
item->prev = item; |
||||
} |
||||
|
||||
#define LIST_INITHEAD(__item) list_inithead(__item) |
||||
#define LIST_ADD(__item, __list) list_add(__item, __list) |
||||
#define LIST_ADDTAIL(__item, __list) list_addtail(__item, __list) |
||||
#define LIST_REPLACE(__from, __to) list_replace(__from, __to) |
||||
#define LIST_DEL(__item) list_del(__item) |
||||
#define LIST_DELINIT(__item) list_delinit(__item) |
||||
|
||||
#define LIST_ENTRY(__type, __item, __field) \ |
||||
((__type *)(((char *)(__item)) - offsetof(__type, __field))) |
||||
|
||||
#define LIST_IS_EMPTY(__list) \ |
||||
((__list)->next == (__list)) |
||||
|
||||
/**
|
||||
* Cast from a pointer to a member of a struct back to the containing struct. |
||||
* |
||||
* 'sample' MUST be initialized, or else the result is undefined! |
||||
*/ |
||||
#ifndef container_of |
||||
#define container_of(ptr, sample, member) \ |
||||
(void *)((char *)(ptr) \
|
||||
- ((char *)&(sample)->member - (char *)(sample))) |
||||
#endif |
||||
|
||||
#define LIST_FOR_EACH_ENTRY(pos, head, member) \ |
||||
for (pos = NULL, pos = container_of((head)->next, pos, member); \
|
||||
&pos->member != (head); \
|
||||
pos = container_of(pos->member.next, pos, member)) |
||||
|
||||
#define LIST_FOR_EACH_ENTRY_SAFE(pos, storage, head, member) \ |
||||
for (pos = NULL, pos = container_of((head)->next, pos, member), \
|
||||
storage = container_of(pos->member.next, pos, member); \
|
||||
&pos->member != (head); \
|
||||
pos = storage, storage = container_of(storage->member.next, storage, member)) |
||||
|
||||
#define LIST_FOR_EACH_ENTRY_SAFE_REV(pos, storage, head, member) \ |
||||
for (pos = NULL, pos = container_of((head)->prev, pos, member), \
|
||||
storage = container_of(pos->member.prev, pos, member); \
|
||||
&pos->member != (head); \
|
||||
pos = storage, storage = container_of(storage->member.prev, storage, member)) |
||||
|
||||
#define LIST_FOR_EACH_ENTRY_FROM(pos, start, head, member) \ |
||||
for (pos = NULL, pos = container_of((start), pos, member); \
|
||||
&pos->member != (head); \
|
||||
pos = container_of(pos->member.next, pos, member)) |
||||
|
||||
#define LIST_FOR_EACH_ENTRY_FROM_REV(pos, start, head, member) \ |
||||
for (pos = NULL, pos = container_of((start), pos, member); \
|
||||
&pos->member != (head); \
|
||||
pos = container_of(pos->member.prev, pos, member)) |
||||
|
||||
#endif /*_U_DOUBLE_LIST_H_*/ |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,46 @@ |
||||
/**************************************************************************
|
||||
* |
||||
* Copyright 2011 LunarG, 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 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 COPYRIGHT HOLDERS, AUTHORS 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. |
||||
* |
||||
* The above copyright notice and this permission notice (including the |
||||
* next paragraph) shall be included in all copies or substantial portions |
||||
* of the Software. |
||||
* |
||||
**************************************************************************/ |
||||
|
||||
#ifndef U_FORMAT_ETC1_H_ |
||||
#define U_FORMAT_ETC1_H_ |
||||
|
||||
void |
||||
util_format_etc1_rgb8_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_etc1_rgb8_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_etc1_rgb8_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_etc1_rgb8_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_etc1_rgb8_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j); |
||||
|
||||
#endif /* U_FORMAT_ETC1_H_ */ |
@ -0,0 +1,108 @@ |
||||
/**************************************************************************
|
||||
* |
||||
* Copyright 2011 Red Hat 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 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 COPYRIGHT HOLDERS, AUTHORS 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. |
||||
* |
||||
* The above copyright notice and this permission notice (including the |
||||
* next paragraph) shall be included in all copies or substantial portions |
||||
* of the Software. |
||||
* |
||||
**************************************************************************/ |
||||
|
||||
#ifndef U_FORMAT_LATC_H_ |
||||
#define U_FORMAT_LATC_H_ |
||||
|
||||
void |
||||
util_format_latc1_unorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j); |
||||
|
||||
void |
||||
util_format_latc1_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_latc1_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_latc1_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_latc1_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_latc1_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j); |
||||
|
||||
|
||||
|
||||
void |
||||
util_format_latc1_snorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j); |
||||
|
||||
void |
||||
util_format_latc1_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_latc1_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_latc1_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_latc1_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_latc1_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j); |
||||
|
||||
|
||||
void |
||||
util_format_latc2_unorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j); |
||||
|
||||
void |
||||
util_format_latc2_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_latc2_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_latc2_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_latc2_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_latc2_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j); |
||||
|
||||
|
||||
void |
||||
util_format_latc2_snorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j); |
||||
|
||||
void |
||||
util_format_latc2_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_latc2_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_latc2_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_latc2_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_latc2_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j); |
||||
|
||||
|
||||
#endif |
@ -0,0 +1,134 @@ |
||||
/**************************************************************************
|
||||
* |
||||
* Copyright 2010 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 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 COPYRIGHT HOLDERS, AUTHORS 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. |
||||
* |
||||
* The above copyright notice and this permission notice (including the |
||||
* next paragraph) shall be included in all copies or substantial portions |
||||
* of the Software. |
||||
* |
||||
**************************************************************************/ |
||||
|
||||
|
||||
#ifndef U_FORMAT_OTHER_H_ |
||||
#define U_FORMAT_OTHER_H_ |
||||
|
||||
|
||||
#include "pipe/p_compiler.h" |
||||
|
||||
|
||||
void |
||||
util_format_r9g9b9e5_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_r9g9b9e5_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, |
||||
const float *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_r9g9b9e5_float_fetch_rgba_float(float *dst, const uint8_t *src, |
||||
unsigned i, unsigned j); |
||||
|
||||
void |
||||
util_format_r9g9b9e5_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_r9g9b9e5_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_r11g11b10_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_r11g11b10_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, |
||||
const float *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_r11g11b10_float_fetch_rgba_float(float *dst, const uint8_t *src, |
||||
unsigned i, unsigned j); |
||||
|
||||
void |
||||
util_format_r11g11b10_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_r11g11b10_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_r1_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_r1_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, |
||||
const float *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_r1_unorm_fetch_rgba_float(float *dst, const uint8_t *src, |
||||
unsigned i, unsigned j); |
||||
|
||||
void |
||||
util_format_r1_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_r1_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_r8g8bx_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_r8g8bx_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, |
||||
const float *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_r8g8bx_snorm_fetch_rgba_float(float *dst, const uint8_t *src, |
||||
unsigned i, unsigned j); |
||||
|
||||
void |
||||
util_format_r8g8bx_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_r8g8bx_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
#endif /* U_FORMAT_OTHER_H_ */ |
@ -0,0 +1,114 @@ |
||||
/**************************************************************************
|
||||
* |
||||
* Copyright 2011 Red Hat 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 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 COPYRIGHT HOLDERS, AUTHORS 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. |
||||
* |
||||
* The above copyright notice and this permission notice (including the |
||||
* next paragraph) shall be included in all copies or substantial portions |
||||
* of the Software. |
||||
* |
||||
**************************************************************************/ |
||||
|
||||
#ifndef U_FORMAT_RGTC_H_ |
||||
#define U_FORMAT_RGTC_H_ |
||||
|
||||
void |
||||
util_format_rgtc1_unorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j); |
||||
|
||||
void |
||||
util_format_rgtc1_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_rgtc1_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_rgtc1_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_rgtc1_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_rgtc1_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j); |
||||
|
||||
|
||||
|
||||
void |
||||
util_format_rgtc1_snorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j); |
||||
|
||||
void |
||||
util_format_rgtc1_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_rgtc1_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_rgtc1_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_rgtc1_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_rgtc1_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j); |
||||
|
||||
|
||||
void |
||||
util_format_rgtc2_unorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j); |
||||
|
||||
void |
||||
util_format_rgtc2_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_rgtc2_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_rxtc2_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height, unsigned chan2off); |
||||
|
||||
void |
||||
util_format_rgtc2_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_rgtc2_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_rgtc2_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j); |
||||
|
||||
|
||||
void |
||||
util_format_rgtc2_snorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j); |
||||
|
||||
void |
||||
util_format_rgtc2_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_rgtc2_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_rgtc2_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_rxtc2_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height, unsigned chan2off); |
||||
|
||||
void |
||||
util_format_rgtc2_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_rgtc2_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j); |
||||
|
||||
|
||||
#endif |
@ -0,0 +1,218 @@ |
||||
/**************************************************************************
|
||||
* |
||||
* Copyright 2010 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 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 COPYRIGHT HOLDERS, AUTHORS 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. |
||||
* |
||||
* The above copyright notice and this permission notice (including the |
||||
* next paragraph) shall be included in all copies or substantial portions |
||||
* of the Software. |
||||
* |
||||
**************************************************************************/ |
||||
|
||||
|
||||
#ifndef U_FORMAT_S3TC_H_ |
||||
#define U_FORMAT_S3TC_H_ |
||||
|
||||
|
||||
#include "pipe/p_compiler.h" |
||||
|
||||
|
||||
enum util_format_dxtn { |
||||
UTIL_FORMAT_DXT1_RGB = 0x83F0, |
||||
UTIL_FORMAT_DXT1_RGBA = 0x83F1, |
||||
UTIL_FORMAT_DXT3_RGBA = 0x83F2, |
||||
UTIL_FORMAT_DXT5_RGBA = 0x83F3 |
||||
}; |
||||
|
||||
|
||||
typedef void |
||||
(*util_format_dxtn_fetch_t)( int src_stride, |
||||
const uint8_t *src, |
||||
int col, int row, |
||||
uint8_t *dst ); |
||||
|
||||
typedef void |
||||
(*util_format_dxtn_pack_t)( int src_comps, |
||||
int width, int height, |
||||
const uint8_t *src, |
||||
enum util_format_dxtn dst_format, |
||||
uint8_t *dst, |
||||
int dst_stride); |
||||
|
||||
extern boolean util_format_s3tc_enabled; |
||||
|
||||
extern util_format_dxtn_fetch_t util_format_dxt1_rgb_fetch; |
||||
extern util_format_dxtn_fetch_t util_format_dxt1_rgba_fetch; |
||||
extern util_format_dxtn_fetch_t util_format_dxt3_rgba_fetch; |
||||
extern util_format_dxtn_fetch_t util_format_dxt5_rgba_fetch; |
||||
|
||||
extern util_format_dxtn_pack_t util_format_dxtn_pack; |
||||
|
||||
|
||||
void |
||||
util_format_s3tc_init(void); |
||||
|
||||
|
||||
void |
||||
util_format_dxt1_rgb_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_dxt1_rgb_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_dxt1_rgb_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j); |
||||
|
||||
void |
||||
util_format_dxt1_rgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_dxt1_rgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_dxt1_rgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j); |
||||
|
||||
void |
||||
util_format_dxt3_rgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_dxt3_rgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_dxt3_rgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j); |
||||
|
||||
void |
||||
util_format_dxt5_rgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_dxt5_rgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_dxt5_rgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j); |
||||
|
||||
void |
||||
util_format_dxt1_srgb_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_dxt1_srgb_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_dxt1_srgb_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j); |
||||
|
||||
void |
||||
util_format_dxt1_srgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_dxt1_srgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_dxt1_srgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j); |
||||
|
||||
void |
||||
util_format_dxt3_srgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_dxt3_srgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_dxt3_srgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j); |
||||
|
||||
void |
||||
util_format_dxt5_srgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_dxt5_srgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_dxt5_srgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j); |
||||
|
||||
|
||||
void |
||||
util_format_dxt1_rgb_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_dxt1_rgb_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_dxt1_rgb_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j); |
||||
|
||||
void |
||||
util_format_dxt1_rgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_dxt1_rgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_dxt1_rgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j); |
||||
|
||||
void |
||||
util_format_dxt3_rgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_dxt3_rgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_dxt3_rgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j); |
||||
|
||||
void |
||||
util_format_dxt5_rgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_dxt5_rgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_dxt5_rgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j); |
||||
|
||||
void |
||||
util_format_dxt1_srgb_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_dxt1_srgb_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_dxt1_srgb_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j); |
||||
|
||||
void |
||||
util_format_dxt1_srgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_dxt1_srgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_dxt1_srgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j); |
||||
|
||||
void |
||||
util_format_dxt3_srgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_dxt3_srgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_dxt3_srgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j); |
||||
|
||||
void |
||||
util_format_dxt5_srgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_dxt5_srgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_dxt5_srgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j); |
||||
|
||||
|
||||
#endif /* U_FORMAT_S3TC_H_ */ |
@ -0,0 +1,178 @@ |
||||
/* This file is autogenerated by u_format_srgb.py. Do not edit directly. */ |
||||
|
||||
/**************************************************************************
|
||||
* |
||||
* Copyright 2010 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. |
||||
* |
||||
**************************************************************************/ |
||||
|
||||
/**
|
||||
* @file |
||||
* SRGB translation. |
||||
* |
||||
* @author Brian Paul <brianp@vmware.com> |
||||
* @author Michal Krol <michal@vmware.com> |
||||
* @author Jose Fonseca <jfonseca@vmware.com> |
||||
*/ |
||||
|
||||
#include "u_format_srgb.h" |
||||
|
||||
const float |
||||
util_format_srgb_8unorm_to_linear_float_table[256] = { |
||||
0.0000000e+00, 3.0352698e-04, 6.0705397e-04, 9.1058095e-04, |
||||
1.2141079e-03, 1.5176349e-03, 1.8211619e-03, 2.1246889e-03, |
||||
2.4282159e-03, 2.7317429e-03, 3.0352698e-03, 3.3465358e-03, |
||||
3.6765073e-03, 4.0247170e-03, 4.3914420e-03, 4.7769535e-03, |
||||
5.1815167e-03, 5.6053916e-03, 6.0488330e-03, 6.5120908e-03, |
||||
6.9954102e-03, 7.4990320e-03, 8.0231930e-03, 8.5681256e-03, |
||||
9.1340587e-03, 9.7212173e-03, 1.0329823e-02, 1.0960094e-02, |
||||
1.1612245e-02, 1.2286488e-02, 1.2983032e-02, 1.3702083e-02, |
||||
1.4443844e-02, 1.5208514e-02, 1.5996293e-02, 1.6807376e-02, |
||||
1.7641954e-02, 1.8500220e-02, 1.9382361e-02, 2.0288563e-02, |
||||
2.1219010e-02, 2.2173885e-02, 2.3153366e-02, 2.4157632e-02, |
||||
2.5186860e-02, 2.6241222e-02, 2.7320892e-02, 2.8426040e-02, |
||||
2.9556834e-02, 3.0713444e-02, 3.1896033e-02, 3.3104767e-02, |
||||
3.4339807e-02, 3.5601315e-02, 3.6889450e-02, 3.8204372e-02, |
||||
3.9546235e-02, 4.0915197e-02, 4.2311411e-02, 4.3735029e-02, |
||||
4.5186204e-02, 4.6665086e-02, 4.8171824e-02, 4.9706566e-02, |
||||
5.1269458e-02, 5.2860647e-02, 5.4480276e-02, 5.6128490e-02, |
||||
5.7805430e-02, 5.9511238e-02, 6.1246054e-02, 6.3010018e-02, |
||||
6.4803267e-02, 6.6625939e-02, 6.8478170e-02, 7.0360096e-02, |
||||
7.2271851e-02, 7.4213568e-02, 7.6185381e-02, 7.8187422e-02, |
||||
8.0219820e-02, 8.2282707e-02, 8.4376212e-02, 8.6500462e-02, |
||||
8.8655586e-02, 9.0841711e-02, 9.3058963e-02, 9.5307467e-02, |
||||
9.7587347e-02, 9.9898728e-02, 1.0224173e-01, 1.0461648e-01, |
||||
1.0702310e-01, 1.0946171e-01, 1.1193243e-01, 1.1443537e-01, |
||||
1.1697067e-01, 1.1953843e-01, 1.2213877e-01, 1.2477182e-01, |
||||
1.2743768e-01, 1.3013648e-01, 1.3286832e-01, 1.3563333e-01, |
||||
1.3843162e-01, 1.4126329e-01, 1.4412847e-01, 1.4702727e-01, |
||||
1.4995979e-01, 1.5292615e-01, 1.5592646e-01, 1.5896084e-01, |
||||
1.6202938e-01, 1.6513219e-01, 1.6826940e-01, 1.7144110e-01, |
||||
1.7464740e-01, 1.7788842e-01, 1.8116424e-01, 1.8447499e-01, |
||||
1.8782077e-01, 1.9120168e-01, 1.9461783e-01, 1.9806932e-01, |
||||
2.0155625e-01, 2.0507874e-01, 2.0863687e-01, 2.1223076e-01, |
||||
2.1586050e-01, 2.1952620e-01, 2.2322796e-01, 2.2696587e-01, |
||||
2.3074005e-01, 2.3455058e-01, 2.3839757e-01, 2.4228112e-01, |
||||
2.4620133e-01, 2.5015828e-01, 2.5415209e-01, 2.5818285e-01, |
||||
2.6225066e-01, 2.6635560e-01, 2.7049779e-01, 2.7467731e-01, |
||||
2.7889426e-01, 2.8314874e-01, 2.8744084e-01, 2.9177065e-01, |
||||
2.9613827e-01, 3.0054379e-01, 3.0498731e-01, 3.0946892e-01, |
||||
3.1398871e-01, 3.1854678e-01, 3.2314321e-01, 3.2777810e-01, |
||||
3.3245154e-01, 3.3716362e-01, 3.4191442e-01, 3.4670406e-01, |
||||
3.5153260e-01, 3.5640014e-01, 3.6130678e-01, 3.6625260e-01, |
||||
3.7123768e-01, 3.7626212e-01, 3.8132601e-01, 3.8642943e-01, |
||||
3.9157248e-01, 3.9675523e-01, 4.0197778e-01, 4.0724021e-01, |
||||
4.1254261e-01, 4.1788507e-01, 4.2326767e-01, 4.2869050e-01, |
||||
4.3415364e-01, 4.3965717e-01, 4.4520119e-01, 4.5078578e-01, |
||||
4.5641102e-01, 4.6207700e-01, 4.6778380e-01, 4.7353150e-01, |
||||
4.7932018e-01, 4.8514994e-01, 4.9102085e-01, 4.9693300e-01, |
||||
5.0288646e-01, 5.0888132e-01, 5.1491767e-01, 5.2099557e-01, |
||||
5.2711513e-01, 5.3327640e-01, 5.3947949e-01, 5.4572446e-01, |
||||
5.5201140e-01, 5.5834039e-01, 5.6471151e-01, 5.7112483e-01, |
||||
5.7758044e-01, 5.8407842e-01, 5.9061884e-01, 5.9720179e-01, |
||||
6.0382734e-01, 6.1049557e-01, 6.1720656e-01, 6.2396039e-01, |
||||
6.3075714e-01, 6.3759687e-01, 6.4447968e-01, 6.5140564e-01, |
||||
6.5837482e-01, 6.6538730e-01, 6.7244316e-01, 6.7954247e-01, |
||||
6.8668531e-01, 6.9387176e-01, 7.0110189e-01, 7.0837578e-01, |
||||
7.1569350e-01, 7.2305513e-01, 7.3046074e-01, 7.3791041e-01, |
||||
7.4540421e-01, 7.5294222e-01, 7.6052450e-01, 7.6815115e-01, |
||||
7.7582222e-01, 7.8353779e-01, 7.9129794e-01, 7.9910274e-01, |
||||
8.0695226e-01, 8.1484657e-01, 8.2278575e-01, 8.3076988e-01, |
||||
8.3879901e-01, 8.4687323e-01, 8.5499261e-01, 8.6315721e-01, |
||||
8.7136712e-01, 8.7962240e-01, 8.8792312e-01, 8.9626935e-01, |
||||
9.0466117e-01, 9.1309865e-01, 9.2158186e-01, 9.3011086e-01, |
||||
9.3868573e-01, 9.4730654e-01, 9.5597335e-01, 9.6468625e-01, |
||||
9.7344529e-01, 9.8225055e-01, 9.9110210e-01, 1.0000000e+00, |
||||
}; |
||||
|
||||
const uint8_t |
||||
util_format_srgb_to_linear_8unorm_table[256] = { |
||||
0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
||||
1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, |
||||
4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, |
||||
8, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 12, 12, 12, 13, |
||||
13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 17, 18, 18, 19, 19, 20, |
||||
20, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 27, 27, 28, 29, 29, |
||||
30, 30, 31, 32, 32, 33, 34, 35, 35, 36, 37, 37, 38, 39, 40, 41, |
||||
41, 42, 43, 44, 45, 45, 46, 47, 48, 49, 50, 51, 51, 52, 53, 54, |
||||
55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, |
||||
71, 72, 73, 74, 76, 77, 78, 79, 80, 81, 82, 84, 85, 86, 87, 88, |
||||
90, 91, 92, 93, 95, 96, 97, 99, 100, 101, 103, 104, 105, 107, 108, 109, |
||||
111, 112, 114, 115, 116, 118, 119, 121, 122, 124, 125, 127, 128, 130, 131, 133, |
||||
134, 136, 138, 139, 141, 142, 144, 146, 147, 149, 151, 152, 154, 156, 157, 159, |
||||
161, 163, 164, 166, 168, 170, 171, 173, 175, 177, 179, 181, 183, 184, 186, 188, |
||||
190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, |
||||
222, 224, 226, 229, 231, 233, 235, 237, 239, 242, 244, 246, 248, 250, 253, 255, |
||||
}; |
||||
|
||||
const uint8_t |
||||
util_format_linear_to_srgb_8unorm_table[256] = { |
||||
0, 13, 22, 28, 34, 38, 42, 46, 50, 53, 56, 59, 61, 64, 66, 69, |
||||
71, 73, 75, 77, 79, 81, 83, 85, 86, 88, 90, 92, 93, 95, 96, 98, |
||||
99, 101, 102, 104, 105, 106, 108, 109, 110, 112, 113, 114, 115, 117, 118, 119, |
||||
120, 121, 122, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, |
||||
137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 148, 149, 150, 151, |
||||
152, 153, 154, 155, 155, 156, 157, 158, 159, 159, 160, 161, 162, 163, 163, 164, |
||||
165, 166, 167, 167, 168, 169, 170, 170, 171, 172, 173, 173, 174, 175, 175, 176, |
||||
177, 178, 178, 179, 180, 180, 181, 182, 182, 183, 184, 185, 185, 186, 187, 187, |
||||
188, 189, 189, 190, 190, 191, 192, 192, 193, 194, 194, 195, 196, 196, 197, 197, |
||||
198, 199, 199, 200, 200, 201, 202, 202, 203, 203, 204, 205, 205, 206, 206, 207, |
||||
208, 208, 209, 209, 210, 210, 211, 212, 212, 213, 213, 214, 214, 215, 215, 216, |
||||
216, 217, 218, 218, 219, 219, 220, 220, 221, 221, 222, 222, 223, 223, 224, 224, |
||||
225, 226, 226, 227, 227, 228, 228, 229, 229, 230, 230, 231, 231, 232, 232, 233, |
||||
233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238, 238, 239, 239, 240, 240, |
||||
241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, 246, 246, 247, 247, 248, |
||||
248, 249, 249, 250, 250, 251, 251, 251, 252, 252, 253, 253, 254, 254, 255, 255, |
||||
}; |
||||
|
||||
const unsigned |
||||
util_format_linear_to_srgb_helper_table[104] = { |
||||
0x0073000d, 0x007a000d, 0x0080000d, 0x0087000d, |
||||
0x008d000d, 0x0094000d, 0x009a000d, 0x00a1000d, |
||||
0x00a7001a, 0x00b4001a, 0x00c1001a, 0x00ce001a, |
||||
0x00da001a, 0x00e7001a, 0x00f4001a, 0x0101001a, |
||||
0x010e0033, 0x01280033, 0x01410033, 0x015b0033, |
||||
0x01750033, 0x018f0033, 0x01a80033, 0x01c20033, |
||||
0x01dc0067, 0x020f0067, 0x02430067, 0x02760067, |
||||
0x02aa0067, 0x02dd0067, 0x03110067, 0x03440067, |
||||
0x037800ce, 0x03df00ce, 0x044600ce, 0x04ad00ce, |
||||
0x051400ce, 0x057b00c5, 0x05dd00bc, 0x063b00b5, |
||||
0x06970158, 0x07420142, 0x07e30130, 0x087b0120, |
||||
0x090b0112, 0x09940106, 0x0a1700fc, 0x0a9500f2, |
||||
0x0b0f01cb, 0x0bf401ae, 0x0ccb0195, 0x0d950180, |
||||
0x0e56016e, 0x0f0d015e, 0x0fbc0150, 0x10630143, |
||||
0x11070264, 0x1238023e, 0x1357021d, 0x14660201, |
||||
0x156601e9, 0x165a01d3, 0x174401c0, 0x182401af, |
||||
0x18fe0331, 0x1a9602fe, 0x1c1502d2, 0x1d7e02ad, |
||||
0x1ed4028d, 0x201a0270, 0x21520256, 0x227d0240, |
||||
0x239f0443, 0x25c003fe, 0x27bf03c4, 0x29a10392, |
||||
0x2b6a0367, 0x2d1d0341, 0x2ebe031f, 0x304d0300, |
||||
0x31d105b0, 0x34a80555, 0x37520507, 0x39d504c5, |
||||
0x3c37048b, 0x3e7c0458, 0x40a8042a, 0x42bd0401, |
||||
0x44c20798, 0x488e071e, 0x4c1c06b6, 0x4f76065d, |
||||
0x52a50610, 0x55ac05cc, 0x5892058f, 0x5b590559, |
||||
0x5e0c0a23, 0x631c0980, 0x67db08f6, 0x6c55087f, |
||||
0x70940818, 0x74a007bd, 0x787d076c, 0x7c330723, |
||||
}; |
||||
|
@ -0,0 +1,147 @@ |
||||
/**************************************************************************
|
||||
* |
||||
* Copyright 2010 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 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 COPYRIGHT HOLDERS, AUTHORS 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. |
||||
* |
||||
* The above copyright notice and this permission notice (including the |
||||
* next paragraph) shall be included in all copies or substantial portions |
||||
* of the Software. |
||||
* |
||||
**************************************************************************/ |
||||
|
||||
/**
|
||||
* @file |
||||
* SRGB translation. |
||||
* |
||||
* @author Brian Paul <brianp@vmware.com> |
||||
* @author Michal Krol <michal@vmware.com> |
||||
* @author Jose Fonseca <jfonseca@vmware.com> |
||||
*/ |
||||
|
||||
#ifndef U_FORMAT_SRGB_H_ |
||||
#define U_FORMAT_SRGB_H_ |
||||
|
||||
|
||||
#include "pipe/p_compiler.h" |
||||
#include "u_pack_color.h" |
||||
#include "u_math.h" |
||||
|
||||
|
||||
extern const float |
||||
util_format_srgb_8unorm_to_linear_float_table[256]; |
||||
|
||||
extern const uint8_t |
||||
util_format_srgb_to_linear_8unorm_table[256]; |
||||
|
||||
extern const uint8_t |
||||
util_format_linear_to_srgb_8unorm_table[256]; |
||||
|
||||
extern const unsigned |
||||
util_format_linear_to_srgb_helper_table[104]; |
||||
|
||||
|
||||
/**
|
||||
* Convert a unclamped linear float to srgb value in the [0,255]. |
||||
*/ |
||||
static INLINE uint8_t |
||||
util_format_linear_float_to_srgb_8unorm(float x) |
||||
{ |
||||
/* this would be exact but (probably much) slower */ |
||||
if (0) { |
||||
if (x >= 1.0f) |
||||
return 255; |
||||
else if (x >= 0.0031308f) |
||||
return float_to_ubyte(1.055f * powf(x, 0.41666666f) - 0.055f); |
||||
else if (x > 0.0f) |
||||
return float_to_ubyte(12.92f * x); |
||||
else |
||||
return 0; |
||||
} |
||||
else { |
||||
/*
|
||||
* This is taken from https://gist.github.com/rygorous/2203834
|
||||
* Use LUT and do linear interpolation. |
||||
*/ |
||||
union fi almostone, minval, f; |
||||
unsigned tab, bias, scale, t; |
||||
|
||||
almostone.ui = 0x3f7fffff; |
||||
minval.ui = (127-13) << 23; |
||||
|
||||
/*
|
||||
* Clamp to [2^(-13), 1-eps]; these two values map to 0 and 1, respectively. |
||||
* The tests are carefully written so that NaNs map to 0, same as in the |
||||
* reference implementation. |
||||
*/ |
||||
if (!(x > minval.f)) |
||||
x = minval.f; |
||||
if (x > almostone.f) |
||||
x = almostone.f; |
||||
|
||||
/* Do the table lookup and unpack bias, scale */ |
||||
f.f = x; |
||||
tab = util_format_linear_to_srgb_helper_table[(f.ui - minval.ui) >> 20]; |
||||
bias = (tab >> 16) << 9; |
||||
scale = tab & 0xffff; |
||||
|
||||
/* Grab next-highest mantissa bits and perform linear interpolation */ |
||||
t = (f.ui >> 12) & 0xff; |
||||
return (uint8_t) ((bias + scale*t) >> 16); |
||||
} |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Convert an 8-bit sRGB value from non-linear space to a |
||||
* linear RGB value in [0, 1]. |
||||
* Implemented with a 256-entry lookup table. |
||||
*/ |
||||
static INLINE float |
||||
util_format_srgb_8unorm_to_linear_float(uint8_t x) |
||||
{ |
||||
return util_format_srgb_8unorm_to_linear_float_table[x]; |
||||
} |
||||
|
||||
|
||||
/*
|
||||
* XXX These 2 functions probably don't make a lot of sense (but lots |
||||
* of potential callers which most likely all don't make sense neither) |
||||
*/ |
||||
|
||||
/**
|
||||
* Convert a 8bit normalized value from linear to srgb. |
||||
*/ |
||||
static INLINE uint8_t |
||||
util_format_linear_to_srgb_8unorm(uint8_t x) |
||||
{ |
||||
return util_format_linear_to_srgb_8unorm_table[x]; |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Convert a 8bit normalized value from srgb to linear. |
||||
*/ |
||||
static INLINE uint8_t |
||||
util_format_srgb_to_linear_8unorm(uint8_t x) |
||||
{ |
||||
return util_format_srgb_to_linear_8unorm_table[x]; |
||||
} |
||||
|
||||
|
||||
#endif /* U_FORMAT_SRGB_H_ */ |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,364 @@ |
||||
/**************************************************************************
|
||||
* |
||||
* Copyright 2010 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 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 COPYRIGHT HOLDERS, AUTHORS 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. |
||||
* |
||||
* The above copyright notice and this permission notice (including the |
||||
* next paragraph) shall be included in all copies or substantial portions |
||||
* of the Software. |
||||
* |
||||
**************************************************************************/ |
||||
|
||||
|
||||
/**
|
||||
* @file |
||||
* YUV colorspace conversion. |
||||
* |
||||
* @author Brian Paul <brianp@vmware.com> |
||||
* @author Michal Krol <michal@vmware.com> |
||||
* @author Jose Fonseca <jfonseca@vmware.com> |
||||
* |
||||
* See also: |
||||
* - http://www.fourcc.org/fccyvrgb.php
|
||||
* - http://msdn.microsoft.com/en-us/library/ms893078
|
||||
* - http://en.wikipedia.org/wiki/YUV
|
||||
*/ |
||||
|
||||
|
||||
#ifndef U_FORMAT_YUV_H_ |
||||
#define U_FORMAT_YUV_H_ |
||||
|
||||
|
||||
#include "pipe/p_compiler.h" |
||||
#include "u_math.h" |
||||
|
||||
|
||||
/*
|
||||
* TODO: Ensure we use consistent and right floating formulas, with enough |
||||
* precision in the coefficients. |
||||
*/ |
||||
|
||||
static INLINE void |
||||
util_format_rgb_float_to_yuv(float r, float g, float b, |
||||
uint8_t *y, uint8_t *u, uint8_t *v) |
||||
{ |
||||
const float _r = CLAMP(r, 0.0f, 1.0f); |
||||
const float _g = CLAMP(g, 0.0f, 1.0f); |
||||
const float _b = CLAMP(b, 0.0f, 1.0f); |
||||
|
||||
const float scale = 255.0f; |
||||
|
||||
const int _y = scale * ( (0.257f * _r) + (0.504f * _g) + (0.098f * _b)); |
||||
const int _u = scale * (-(0.148f * _r) - (0.291f * _g) + (0.439f * _b)); |
||||
const int _v = scale * ( (0.439f * _r) - (0.368f * _g) - (0.071f * _b)); |
||||
|
||||
*y = _y + 16;
|
||||
*u = _u + 128;
|
||||
*v = _v + 128;
|
||||
} |
||||
|
||||
|
||||
static INLINE void |
||||
util_format_yuv_to_rgb_float(uint8_t y, uint8_t u, uint8_t v, |
||||
float *r, float *g, float *b) |
||||
{ |
||||
const int _y = y - 16; |
||||
const int _u = u - 128; |
||||
const int _v = v - 128; |
||||
|
||||
const float y_factor = 255.0f / 219.0f; |
||||
|
||||
const float scale = 1.0f / 255.0f; |
||||
|
||||
*r = scale * (y_factor * _y + 1.596f * _v); |
||||
*g = scale * (y_factor * _y - 0.391f * _u - 0.813f * _v); |
||||
*b = scale * (y_factor * _y + 2.018f * _u ); |
||||
} |
||||
|
||||
|
||||
static INLINE void |
||||
util_format_rgb_8unorm_to_yuv(uint8_t r, uint8_t g, uint8_t b, |
||||
uint8_t *y, uint8_t *u, uint8_t *v) |
||||
{ |
||||
*y = (( 66 * r + 129 * g + 25 * b + 128) >> 8) + 16; |
||||
*u = (( -38 * r - 74 * g + 112 * b + 128) >> 8) + 128; |
||||
*v = (( 112 * r - 94 * g - 18 * b + 128) >> 8) + 128; |
||||
} |
||||
|
||||
|
||||
static INLINE void |
||||
util_format_yuv_to_rgb_8unorm(uint8_t y, uint8_t u, uint8_t v, |
||||
uint8_t *r, uint8_t *g, uint8_t *b) |
||||
{ |
||||
const int _y = y - 16; |
||||
const int _u = u - 128; |
||||
const int _v = v - 128; |
||||
|
||||
const int _r = (298 * _y + 409 * _v + 128) >> 8; |
||||
const int _g = (298 * _y - 100 * _u - 208 * _v + 128) >> 8; |
||||
const int _b = (298 * _y + 516 * _u + 128) >> 8; |
||||
|
||||
*r = CLAMP(_r, 0, 255); |
||||
*g = CLAMP(_g, 0, 255); |
||||
*b = CLAMP(_b, 0, 255); |
||||
} |
||||
|
||||
|
||||
|
||||
void |
||||
util_format_uyvy_unpack_rgba_float(float *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_uyvy_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_uyvy_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, |
||||
const float *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_uyvy_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_uyvy_fetch_rgba_float(float *dst, const uint8_t *src, |
||||
unsigned i, unsigned j); |
||||
|
||||
void |
||||
util_format_yuyv_unpack_rgba_float(float *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_yuyv_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_yuyv_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, |
||||
const float *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_yuyv_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_yuyv_fetch_rgba_float(float *dst, const uint8_t *src, |
||||
unsigned i, unsigned j); |
||||
|
||||
/* XXX: Stubbed for now */ |
||||
void |
||||
util_format_yv12_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
void |
||||
util_format_yv12_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
void |
||||
util_format_yv12_unpack_rgba_float(float *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
void |
||||
util_format_yv12_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, |
||||
const float *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
void |
||||
util_format_yv12_fetch_rgba_float(float *dst, const uint8_t *src, |
||||
unsigned i, unsigned j); |
||||
void |
||||
util_format_yv16_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
void |
||||
util_format_yv16_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
void |
||||
util_format_yv16_unpack_rgba_float(float *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
void |
||||
util_format_yv16_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, |
||||
const float *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
void |
||||
util_format_yv16_fetch_rgba_float(float *dst, const uint8_t *src, |
||||
unsigned i, unsigned j); |
||||
void |
||||
util_format_iyuv_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
void |
||||
util_format_iyuv_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
void |
||||
util_format_iyuv_unpack_rgba_float(float *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
void |
||||
util_format_iyuv_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, |
||||
const float *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
void |
||||
util_format_iyuv_fetch_rgba_float(float *dst, const uint8_t *src, |
||||
unsigned i, unsigned j); |
||||
void |
||||
util_format_nv12_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
void |
||||
util_format_nv12_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
void |
||||
util_format_nv12_unpack_rgba_float(float *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
void |
||||
util_format_nv12_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, |
||||
const float *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
void |
||||
util_format_nv12_fetch_rgba_float(float *dst, const uint8_t *src, |
||||
unsigned i, unsigned j); |
||||
void |
||||
util_format_nv21_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
void |
||||
util_format_nv21_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
void |
||||
util_format_nv21_unpack_rgba_float(float *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
void |
||||
util_format_nv21_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, |
||||
const float *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
void |
||||
util_format_nv21_fetch_rgba_float(float *dst, const uint8_t *src, |
||||
unsigned i, unsigned j); |
||||
void |
||||
util_format_r8g8_b8g8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_r8g8_b8g8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_r8g8_b8g8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, |
||||
const float *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_r8g8_b8g8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_r8g8_b8g8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, |
||||
unsigned i, unsigned j); |
||||
|
||||
void |
||||
util_format_g8r8_g8b8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_g8r8_g8b8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_g8r8_g8b8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, |
||||
const float *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_g8r8_g8b8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_g8r8_g8b8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, |
||||
unsigned i, unsigned j); |
||||
|
||||
void |
||||
util_format_r8g8_r8b8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_r8g8_r8b8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_r8g8_r8b8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, |
||||
const float *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_r8g8_r8b8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_r8g8_r8b8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, |
||||
unsigned i, unsigned j); |
||||
|
||||
void |
||||
util_format_g8r8_b8r8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_g8r8_b8r8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_g8r8_b8r8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, |
||||
const float *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_g8r8_b8r8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, |
||||
const uint8_t *src_row, unsigned src_stride, |
||||
unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_g8r8_b8r8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, |
||||
unsigned i, unsigned j); |
||||
|
||||
#endif /* U_FORMAT_YUV_H_ */ |
@ -0,0 +1,212 @@ |
||||
/**************************************************************************
|
||||
* |
||||
* Copyright 2010 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 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 COPYRIGHT HOLDERS, AUTHORS 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. |
||||
* |
||||
* The above copyright notice and this permission notice (including the |
||||
* next paragraph) shall be included in all copies or substantial portions |
||||
* of the Software. |
||||
* |
||||
**************************************************************************/ |
||||
|
||||
|
||||
#ifndef U_FORMAT_ZS_H_ |
||||
#define U_FORMAT_ZS_H_ |
||||
|
||||
|
||||
#include "pipe/p_compiler.h" |
||||
|
||||
|
||||
void |
||||
util_format_s8_uint_unpack_s_8uint(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_s8_uint_pack_s_8uint(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_z16_unorm_unpack_z_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_z16_unorm_pack_z_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_z16_unorm_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_z16_unorm_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, const uint32_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_z32_unorm_unpack_z_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_z32_unorm_pack_z_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_z32_unorm_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_z32_unorm_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, const uint32_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_z32_float_unpack_z_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_z32_float_pack_z_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_z32_float_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_z32_float_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, const uint32_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_z24_unorm_s8_uint_unpack_z_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_z24_unorm_s8_uint_pack_z_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_z24_unorm_s8_uint_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_z24_unorm_s8_uint_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, const uint32_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_z24_unorm_s8_uint_unpack_s_8uint(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_z24_unorm_s8_uint_pack_s_8uint(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_s8_uint_z24_unorm_unpack_z_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_s8_uint_z24_unorm_pack_z_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_s8_uint_z24_unorm_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_s8_uint_z24_unorm_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, const uint32_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_s8_uint_z24_unorm_unpack_s_8uint(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_s8_uint_z24_unorm_pack_s_8uint(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_z24x8_unorm_unpack_z_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_z24x8_unorm_pack_z_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_z24x8_unorm_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_z24x8_unorm_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, const uint32_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_x8z24_unorm_unpack_z_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_x8z24_unorm_pack_z_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_x8z24_unorm_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_x8z24_unorm_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, const uint32_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_z32_float_s8x24_uint_unpack_z_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_z32_float_s8x24_uint_pack_z_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_z32_float_s8x24_uint_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_z32_float_s8x24_uint_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, const uint32_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_z32_float_s8x24_uint_unpack_s_8uint(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
|
||||
void |
||||
util_format_z32_float_s8x24_uint_pack_s_8uint(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_x24s8_uint_unpack_s_8uint(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_x24s8_uint_pack_s_8uint(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_s8x24_uint_unpack_s_8uint(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_s8x24_uint_pack_s_8uint(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_x32_s8x24_uint_unpack_s_8uint(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
|
||||
void |
||||
util_format_x32_s8x24_uint_pack_s_8uint(uint8_t *dst_row, unsigned dst_sride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); |
||||
#endif /* U_FORMAT_ZS_H_ */ |
@ -0,0 +1,131 @@ |
||||
/**************************************************************************
|
||||
* |
||||
* Copyright 2010 Luca Barbieri |
||||
* |
||||
* 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 COPYRIGHT OWNER(S) 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_HALF_H |
||||
#define U_HALF_H |
||||
|
||||
#include "pipe/p_compiler.h" |
||||
#include "util/u_math.h" |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/*
|
||||
* References for float <-> half conversions |
||||
* |
||||
* http://fgiesen.wordpress.com/2012/03/28/half-to-float-done-quic/
|
||||
* https://gist.github.com/2156668
|
||||
* https://gist.github.com/2144712
|
||||
*/ |
||||
|
||||
static INLINE uint16_t |
||||
util_float_to_half(float f) |
||||
{ |
||||
uint32_t sign_mask = 0x80000000; |
||||
uint32_t round_mask = ~0xfff; |
||||
uint32_t f32inf = 0xff << 23; |
||||
uint32_t f16inf = 0x1f << 23; |
||||
uint32_t sign; |
||||
union fi magic; |
||||
union fi f32; |
||||
uint16_t f16; |
||||
|
||||
magic.ui = 0xf << 23; |
||||
|
||||
f32.f = f; |
||||
|
||||
/* Sign */ |
||||
sign = f32.ui & sign_mask; |
||||
f32.ui ^= sign; |
||||
|
||||
if (f32.ui == f32inf) { |
||||
/* Inf */ |
||||
f16 = 0x7c00; |
||||
} else if (f32.ui > f32inf) { |
||||
/* NaN */ |
||||
f16 = 0x7e00; |
||||
} else { |
||||
/* Number */ |
||||
f32.ui &= round_mask; |
||||
f32.f *= magic.f; |
||||
f32.ui -= round_mask; |
||||
|
||||
/*
|
||||
* Clamp to max finite value if overflowed. |
||||
* OpenGL has completely undefined rounding behavior for float to |
||||
* half-float conversions, and this matches what is mandated for float |
||||
* to fp11/fp10, which recommend round-to-nearest-finite too. |
||||
* (d3d10 is deeply unhappy about flushing such values to infinity, and |
||||
* while it also mandates round-to-zero it doesn't care nearly as much |
||||
* about that.) |
||||
*/ |
||||
if (f32.ui > f16inf) |
||||
f32.ui = f16inf - 1; |
||||
|
||||
f16 = f32.ui >> 13; |
||||
} |
||||
|
||||
/* Sign */ |
||||
f16 |= sign >> 16; |
||||
|
||||
return f16; |
||||
} |
||||
|
||||
static INLINE float |
||||
util_half_to_float(uint16_t f16) |
||||
{ |
||||
union fi infnan; |
||||
union fi magic; |
||||
union fi f32; |
||||
|
||||
infnan.ui = 0x8f << 23; |
||||
infnan.f = 65536.0f; |
||||
magic.ui = 0xef << 23; |
||||
|
||||
/* Exponent / Mantissa */ |
||||
f32.ui = (f16 & 0x7fff) << 13; |
||||
|
||||
/* Adjust */ |
||||
f32.f *= magic.f; |
||||
|
||||
/* Inf / NaN */ |
||||
if (f32.f >= infnan.f) |
||||
f32.ui |= 0xff << 23; |
||||
|
||||
/* Sign */ |
||||
f32.ui |= (f16 & 0x8000) << 16; |
||||
|
||||
return f32.f; |
||||
} |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* U_HALF_H */ |
||||
|
@ -0,0 +1,96 @@ |
||||
/**************************************************************************
|
||||
* |
||||
* 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. |
||||
* |
||||
**************************************************************************/ |
||||
|
||||
/**
|
||||
* General purpose hash table. |
||||
*
|
||||
* @author José Fonseca <jfonseca@vmware.com> |
||||
*/ |
||||
|
||||
#ifndef U_HASH_TABLE_H_ |
||||
#define U_HASH_TABLE_H_ |
||||
|
||||
|
||||
#include "pipe/p_defines.h" |
||||
|
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
|
||||
/**
|
||||
* Generic purpose hash table. |
||||
*/ |
||||
struct util_hash_table; |
||||
|
||||
|
||||
/**
|
||||
* Create an hash table. |
||||
*
|
||||
* @param hash hash function |
||||
* @param compare should return 0 for two equal keys. |
||||
*/ |
||||
struct util_hash_table * |
||||
util_hash_table_create(unsigned (*hash)(void *key), |
||||
int (*compare)(void *key1, void *key2)); |
||||
|
||||
|
||||
enum pipe_error |
||||
util_hash_table_set(struct util_hash_table *ht, |
||||
void *key, |
||||
void *value); |
||||
|
||||
void * |
||||
util_hash_table_get(struct util_hash_table *ht, |
||||
void *key); |
||||
|
||||
|
||||
void |
||||
util_hash_table_remove(struct util_hash_table *ht, |
||||
void *key); |
||||
|
||||
|
||||
void |
||||
util_hash_table_clear(struct util_hash_table *ht); |
||||
|
||||
|
||||
enum pipe_error |
||||
util_hash_table_foreach(struct util_hash_table *ht, |
||||
enum pipe_error (*callback) |
||||
(void *key, void *value, void *data), |
||||
void *data); |
||||
|
||||
void |
||||
util_hash_table_destroy(struct util_hash_table *ht); |
||||
|
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* U_HASH_TABLE_H_ */ |
@ -0,0 +1,644 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 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_INLINES_H |
||||
#define U_INLINES_H |
||||
|
||||
#include "pipe/p_context.h" |
||||
#include "pipe/p_defines.h" |
||||
#include "pipe/p_shader_tokens.h" |
||||
#include "pipe/p_state.h" |
||||
#include "pipe/p_screen.h" |
||||
#include "util/u_debug.h" |
||||
#include "util/u_debug_describe.h" |
||||
#include "util/u_debug_refcnt.h" |
||||
#include "util/u_atomic.h" |
||||
#include "util/u_box.h" |
||||
#include "util/u_math.h" |
||||
|
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
|
||||
/*
|
||||
* Reference counting helper functions. |
||||
*/ |
||||
|
||||
|
||||
static INLINE void |
||||
pipe_reference_init(struct pipe_reference *reference, unsigned count) |
||||
{ |
||||
p_atomic_set(&reference->count, count); |
||||
} |
||||
|
||||
static INLINE boolean |
||||
pipe_is_referenced(struct pipe_reference *reference) |
||||
{ |
||||
return p_atomic_read(&reference->count) != 0; |
||||
} |
||||
|
||||
/**
|
||||
* Update reference counting. |
||||
* The old thing pointed to, if any, will be unreferenced. |
||||
* Both 'ptr' and 'reference' may be NULL. |
||||
* \return TRUE if the object's refcount hits zero and should be destroyed. |
||||
*/ |
||||
static INLINE boolean |
||||
pipe_reference_described(struct pipe_reference *ptr,
|
||||
struct pipe_reference *reference,
|
||||
debug_reference_descriptor get_desc) |
||||
{ |
||||
boolean destroy = FALSE; |
||||
|
||||
if(ptr != reference) { |
||||
/* bump the reference.count first */ |
||||
if (reference) { |
||||
assert(pipe_is_referenced(reference)); |
||||
p_atomic_inc(&reference->count); |
||||
debug_reference(reference, get_desc, 1); |
||||
} |
||||
|
||||
if (ptr) { |
||||
assert(pipe_is_referenced(ptr)); |
||||
if (p_atomic_dec_zero(&ptr->count)) { |
||||
destroy = TRUE; |
||||
} |
||||
debug_reference(ptr, get_desc, -1); |
||||
} |
||||
} |
||||
|
||||
return destroy; |
||||
} |
||||
|
||||
static INLINE boolean |
||||
pipe_reference(struct pipe_reference *ptr, struct pipe_reference *reference) |
||||
{ |
||||
return pipe_reference_described(ptr, reference,
|
||||
(debug_reference_descriptor)debug_describe_reference); |
||||
} |
||||
|
||||
static INLINE void |
||||
pipe_surface_reference(struct pipe_surface **ptr, struct pipe_surface *surf) |
||||
{ |
||||
struct pipe_surface *old_surf = *ptr; |
||||
|
||||
if (pipe_reference_described(&(*ptr)->reference, &surf->reference,
|
||||
(debug_reference_descriptor)debug_describe_surface)) |
||||
old_surf->context->surface_destroy(old_surf->context, old_surf); |
||||
*ptr = surf; |
||||
} |
||||
|
||||
/**
|
||||
* Similar to pipe_surface_reference() but always set the pointer to NULL |
||||
* and pass in an explicit context. The explicit context avoids the problem |
||||
* of using a deleted context's surface_destroy() method when freeing a surface |
||||
* that's shared by multiple contexts. |
||||
*/ |
||||
static INLINE void |
||||
pipe_surface_release(struct pipe_context *pipe, struct pipe_surface **ptr) |
||||
{ |
||||
if (pipe_reference_described(&(*ptr)->reference, NULL, |
||||
(debug_reference_descriptor)debug_describe_surface)) |
||||
pipe->surface_destroy(pipe, *ptr); |
||||
*ptr = NULL; |
||||
} |
||||
|
||||
|
||||
static INLINE void |
||||
pipe_resource_reference(struct pipe_resource **ptr, struct pipe_resource *tex) |
||||
{ |
||||
struct pipe_resource *old_tex = *ptr; |
||||
|
||||
if (pipe_reference_described(&(*ptr)->reference, &tex->reference,
|
||||
(debug_reference_descriptor)debug_describe_resource)) |
||||
old_tex->screen->resource_destroy(old_tex->screen, old_tex); |
||||
*ptr = tex; |
||||
} |
||||
|
||||
static INLINE void |
||||
pipe_sampler_view_reference(struct pipe_sampler_view **ptr, struct pipe_sampler_view *view) |
||||
{ |
||||
struct pipe_sampler_view *old_view = *ptr; |
||||
|
||||
if (pipe_reference_described(&(*ptr)->reference, &view->reference, |
||||
(debug_reference_descriptor)debug_describe_sampler_view)) |
||||
old_view->context->sampler_view_destroy(old_view->context, old_view); |
||||
*ptr = view; |
||||
} |
||||
|
||||
/**
|
||||
* Similar to pipe_sampler_view_reference() but always set the pointer to |
||||
* NULL and pass in an explicit context. Passing an explicit context is a |
||||
* work-around for fixing a dangling context pointer problem when textures |
||||
* are shared by multiple contexts. XXX fix this someday. |
||||
*/ |
||||
static INLINE void |
||||
pipe_sampler_view_release(struct pipe_context *ctx, |
||||
struct pipe_sampler_view **ptr) |
||||
{ |
||||
struct pipe_sampler_view *old_view = *ptr; |
||||
if (*ptr && (*ptr)->context != ctx) { |
||||
debug_printf_once(("context mis-match in pipe_sampler_view_release()\n")); |
||||
} |
||||
if (pipe_reference_described(&(*ptr)->reference, NULL, |
||||
(debug_reference_descriptor)debug_describe_sampler_view)) { |
||||
ctx->sampler_view_destroy(ctx, old_view); |
||||
} |
||||
*ptr = NULL; |
||||
} |
||||
|
||||
|
||||
static INLINE void |
||||
pipe_so_target_reference(struct pipe_stream_output_target **ptr, |
||||
struct pipe_stream_output_target *target) |
||||
{ |
||||
struct pipe_stream_output_target *old = *ptr; |
||||
|
||||
if (pipe_reference_described(&(*ptr)->reference, &target->reference, |
||||
(debug_reference_descriptor)debug_describe_so_target)) |
||||
old->context->stream_output_target_destroy(old->context, old); |
||||
*ptr = target; |
||||
} |
||||
|
||||
static INLINE void |
||||
pipe_surface_reset(struct pipe_context *ctx, struct pipe_surface* ps, |
||||
struct pipe_resource *pt, unsigned level, unsigned layer) |
||||
{ |
||||
pipe_resource_reference(&ps->texture, pt); |
||||
ps->format = pt->format; |
||||
ps->width = u_minify(pt->width0, level); |
||||
ps->height = u_minify(pt->height0, level); |
||||
ps->u.tex.level = level; |
||||
ps->u.tex.first_layer = ps->u.tex.last_layer = layer; |
||||
ps->context = ctx; |
||||
} |
||||
|
||||
static INLINE void |
||||
pipe_surface_init(struct pipe_context *ctx, struct pipe_surface* ps, |
||||
struct pipe_resource *pt, unsigned level, unsigned layer) |
||||
{ |
||||
ps->texture = 0; |
||||
pipe_reference_init(&ps->reference, 1); |
||||
pipe_surface_reset(ctx, ps, pt, level, layer); |
||||
} |
||||
|
||||
/* Return true if the surfaces are equal. */ |
||||
static INLINE boolean |
||||
pipe_surface_equal(struct pipe_surface *s1, struct pipe_surface *s2) |
||||
{ |
||||
return s1->texture == s2->texture && |
||||
s1->format == s2->format && |
||||
(s1->texture->target != PIPE_BUFFER || |
||||
(s1->u.buf.first_element == s2->u.buf.first_element && |
||||
s1->u.buf.last_element == s2->u.buf.last_element)) && |
||||
(s1->texture->target == PIPE_BUFFER || |
||||
(s1->u.tex.level == s2->u.tex.level && |
||||
s1->u.tex.first_layer == s2->u.tex.first_layer && |
||||
s1->u.tex.last_layer == s2->u.tex.last_layer)); |
||||
} |
||||
|
||||
/*
|
||||
* Convenience wrappers for screen buffer functions. |
||||
*/ |
||||
|
||||
|
||||
/**
|
||||
* Create a new resource. |
||||
* \param bind bitmask of PIPE_BIND_x flags |
||||
* \param usage bitmask of PIPE_USAGE_x flags |
||||
*/ |
||||
static INLINE struct pipe_resource * |
||||
pipe_buffer_create( struct pipe_screen *screen, |
||||
unsigned bind, |
||||
unsigned usage, |
||||
unsigned size ) |
||||
{ |
||||
struct pipe_resource buffer; |
||||
memset(&buffer, 0, sizeof buffer); |
||||
buffer.target = PIPE_BUFFER; |
||||
buffer.format = PIPE_FORMAT_R8_UNORM; /* want TYPELESS or similar */ |
||||
buffer.bind = bind; |
||||
buffer.usage = usage; |
||||
buffer.flags = 0; |
||||
buffer.width0 = size; |
||||
buffer.height0 = 1; |
||||
buffer.depth0 = 1; |
||||
buffer.array_size = 1; |
||||
return screen->resource_create(screen, &buffer); |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Map a range of a resource. |
||||
* \param offset start of region, in bytes
|
||||
* \param length size of region, in bytes
|
||||
* \param access bitmask of PIPE_TRANSFER_x flags |
||||
* \param transfer returns a transfer object |
||||
*/ |
||||
static INLINE void * |
||||
pipe_buffer_map_range(struct pipe_context *pipe, |
||||
struct pipe_resource *buffer, |
||||
unsigned offset, |
||||
unsigned length, |
||||
unsigned access, |
||||
struct pipe_transfer **transfer) |
||||
{ |
||||
struct pipe_box box; |
||||
void *map; |
||||
|
||||
assert(offset < buffer->width0); |
||||
assert(offset + length <= buffer->width0); |
||||
assert(length); |
||||
|
||||
u_box_1d(offset, length, &box); |
||||
|
||||
map = pipe->transfer_map(pipe, buffer, 0, access, &box, transfer); |
||||
if (map == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
return map; |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Map whole resource. |
||||
* \param access bitmask of PIPE_TRANSFER_x flags |
||||
* \param transfer returns a transfer object |
||||
*/ |
||||
static INLINE void * |
||||
pipe_buffer_map(struct pipe_context *pipe, |
||||
struct pipe_resource *buffer, |
||||
unsigned access, |
||||
struct pipe_transfer **transfer) |
||||
{ |
||||
return pipe_buffer_map_range(pipe, buffer, 0, buffer->width0, access, transfer); |
||||
} |
||||
|
||||
|
||||
static INLINE void |
||||
pipe_buffer_unmap(struct pipe_context *pipe, |
||||
struct pipe_transfer *transfer) |
||||
{ |
||||
pipe->transfer_unmap(pipe, transfer); |
||||
} |
||||
|
||||
static INLINE void |
||||
pipe_buffer_flush_mapped_range(struct pipe_context *pipe, |
||||
struct pipe_transfer *transfer, |
||||
unsigned offset, |
||||
unsigned length) |
||||
{ |
||||
struct pipe_box box; |
||||
int transfer_offset; |
||||
|
||||
assert(length); |
||||
assert(transfer->box.x <= (int) offset); |
||||
assert((int) (offset + length) <= transfer->box.x + transfer->box.width); |
||||
|
||||
/* Match old screen->buffer_flush_mapped_range() behaviour, where
|
||||
* offset parameter is relative to the start of the buffer, not the |
||||
* mapped range. |
||||
*/ |
||||
transfer_offset = offset - transfer->box.x; |
||||
|
||||
u_box_1d(transfer_offset, length, &box); |
||||
|
||||
pipe->transfer_flush_region(pipe, transfer, &box); |
||||
} |
||||
|
||||
static INLINE void |
||||
pipe_buffer_write(struct pipe_context *pipe, |
||||
struct pipe_resource *buf, |
||||
unsigned offset, |
||||
unsigned size, |
||||
const void *data) |
||||
{ |
||||
struct pipe_box box; |
||||
unsigned access = PIPE_TRANSFER_WRITE; |
||||
|
||||
if (offset == 0 && size == buf->width0) { |
||||
access |= PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE; |
||||
} else { |
||||
access |= PIPE_TRANSFER_DISCARD_RANGE; |
||||
} |
||||
|
||||
u_box_1d(offset, size, &box); |
||||
|
||||
pipe->transfer_inline_write( pipe, |
||||
buf, |
||||
0, |
||||
access, |
||||
&box, |
||||
data, |
||||
size, |
||||
0); |
||||
} |
||||
|
||||
/**
|
||||
* Special case for writing non-overlapping ranges. |
||||
* |
||||
* We can avoid GPU/CPU synchronization when writing range that has never |
||||
* been written before. |
||||
*/ |
||||
static INLINE void |
||||
pipe_buffer_write_nooverlap(struct pipe_context *pipe, |
||||
struct pipe_resource *buf, |
||||
unsigned offset, unsigned size, |
||||
const void *data) |
||||
{ |
||||
struct pipe_box box; |
||||
|
||||
u_box_1d(offset, size, &box); |
||||
|
||||
pipe->transfer_inline_write(pipe, |
||||
buf, |
||||
0, |
||||
(PIPE_TRANSFER_WRITE | |
||||
PIPE_TRANSFER_UNSYNCHRONIZED), |
||||
&box, |
||||
data, |
||||
0, 0); |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Create a new resource and immediately put data into it |
||||
* \param bind bitmask of PIPE_BIND_x flags |
||||
* \param usage bitmask of PIPE_USAGE_x flags |
||||
*/ |
||||
static INLINE struct pipe_resource * |
||||
pipe_buffer_create_with_data(struct pipe_context *pipe, |
||||
unsigned bind, |
||||
unsigned usage, |
||||
unsigned size, |
||||
const void *ptr) |
||||
{ |
||||
struct pipe_resource *res = pipe_buffer_create(pipe->screen, |
||||
bind, usage, size); |
||||
pipe_buffer_write_nooverlap(pipe, res, 0, size, ptr); |
||||
return res; |
||||
} |
||||
|
||||
static INLINE void |
||||
pipe_buffer_read(struct pipe_context *pipe, |
||||
struct pipe_resource *buf, |
||||
unsigned offset, |
||||
unsigned size, |
||||
void *data) |
||||
{ |
||||
struct pipe_transfer *src_transfer; |
||||
ubyte *map; |
||||
|
||||
map = (ubyte *) pipe_buffer_map_range(pipe, |
||||
buf, |
||||
offset, size, |
||||
PIPE_TRANSFER_READ, |
||||
&src_transfer); |
||||
if (!map) |
||||
return; |
||||
|
||||
memcpy(data, map, size); |
||||
pipe_buffer_unmap(pipe, src_transfer); |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Map a resource for reading/writing. |
||||
* \param access bitmask of PIPE_TRANSFER_x flags |
||||
*/ |
||||
static INLINE void * |
||||
pipe_transfer_map(struct pipe_context *context, |
||||
struct pipe_resource *resource, |
||||
unsigned level, unsigned layer, |
||||
unsigned access, |
||||
unsigned x, unsigned y, |
||||
unsigned w, unsigned h, |
||||
struct pipe_transfer **transfer) |
||||
{ |
||||
struct pipe_box box; |
||||
u_box_2d_zslice(x, y, layer, w, h, &box); |
||||
return context->transfer_map(context, |
||||
resource, |
||||
level, |
||||
access, |
||||
&box, transfer); |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Map a 3D (texture) resource for reading/writing. |
||||
* \param access bitmask of PIPE_TRANSFER_x flags |
||||
*/ |
||||
static INLINE void * |
||||
pipe_transfer_map_3d(struct pipe_context *context, |
||||
struct pipe_resource *resource, |
||||
unsigned level, |
||||
unsigned access, |
||||
unsigned x, unsigned y, unsigned z, |
||||
unsigned w, unsigned h, unsigned d, |
||||
struct pipe_transfer **transfer) |
||||
{ |
||||
struct pipe_box box; |
||||
u_box_3d(x, y, z, w, h, d, &box); |
||||
return context->transfer_map(context, |
||||
resource, |
||||
level, |
||||
access, |
||||
&box, transfer); |
||||
} |
||||
|
||||
static INLINE void |
||||
pipe_transfer_unmap( struct pipe_context *context, |
||||
struct pipe_transfer *transfer ) |
||||
{ |
||||
context->transfer_unmap( context, transfer ); |
||||
} |
||||
|
||||
static INLINE void |
||||
pipe_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, |
||||
struct pipe_resource *buf) |
||||
{ |
||||
if (buf) { |
||||
struct pipe_constant_buffer cb; |
||||
cb.buffer = buf; |
||||
cb.buffer_offset = 0; |
||||
cb.buffer_size = buf->width0; |
||||
cb.user_buffer = NULL; |
||||
pipe->set_constant_buffer(pipe, shader, index, &cb); |
||||
} else { |
||||
pipe->set_constant_buffer(pipe, shader, index, NULL); |
||||
} |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Get the polygon offset enable/disable flag for the given polygon fill mode. |
||||
* \param fill_mode one of PIPE_POLYGON_MODE_POINT/LINE/FILL |
||||
*/ |
||||
static INLINE boolean |
||||
util_get_offset(const struct pipe_rasterizer_state *templ, |
||||
unsigned fill_mode) |
||||
{ |
||||
switch(fill_mode) { |
||||
case PIPE_POLYGON_MODE_POINT: |
||||
return templ->offset_point; |
||||
case PIPE_POLYGON_MODE_LINE: |
||||
return templ->offset_line; |
||||
case PIPE_POLYGON_MODE_FILL: |
||||
return templ->offset_tri; |
||||
default: |
||||
assert(0); |
||||
return FALSE; |
||||
} |
||||
} |
||||
|
||||
static INLINE float |
||||
util_get_min_point_size(const struct pipe_rasterizer_state *state) |
||||
{ |
||||
/* The point size should be clamped to this value at the rasterizer stage.
|
||||
*/ |
||||
return !state->point_quad_rasterization && |
||||
!state->point_smooth && |
||||
!state->multisample ? 1.0f : 0.0f; |
||||
} |
||||
|
||||
static INLINE void |
||||
util_query_clear_result(union pipe_query_result *result, unsigned type) |
||||
{ |
||||
switch (type) { |
||||
case PIPE_QUERY_OCCLUSION_PREDICATE: |
||||
case PIPE_QUERY_SO_OVERFLOW_PREDICATE: |
||||
case PIPE_QUERY_GPU_FINISHED: |
||||
result->b = FALSE; |
||||
break; |
||||
case PIPE_QUERY_OCCLUSION_COUNTER: |
||||
case PIPE_QUERY_TIMESTAMP: |
||||
case PIPE_QUERY_TIME_ELAPSED: |
||||
case PIPE_QUERY_PRIMITIVES_GENERATED: |
||||
case PIPE_QUERY_PRIMITIVES_EMITTED: |
||||
result->u64 = 0; |
||||
break; |
||||
case PIPE_QUERY_SO_STATISTICS: |
||||
memset(&result->so_statistics, 0, sizeof(result->so_statistics)); |
||||
break; |
||||
case PIPE_QUERY_TIMESTAMP_DISJOINT: |
||||
memset(&result->timestamp_disjoint, 0, sizeof(result->timestamp_disjoint)); |
||||
break; |
||||
case PIPE_QUERY_PIPELINE_STATISTICS: |
||||
memset(&result->pipeline_statistics, 0, sizeof(result->pipeline_statistics)); |
||||
break; |
||||
default: |
||||
memset(result, 0, sizeof(*result)); |
||||
} |
||||
} |
||||
|
||||
/** Convert PIPE_TEXTURE_x to TGSI_TEXTURE_x */ |
||||
static INLINE unsigned |
||||
util_pipe_tex_to_tgsi_tex(enum pipe_texture_target pipe_tex_target, |
||||
unsigned nr_samples) |
||||
{ |
||||
switch (pipe_tex_target) { |
||||
case PIPE_TEXTURE_1D: |
||||
assert(nr_samples <= 1); |
||||
return TGSI_TEXTURE_1D; |
||||
|
||||
case PIPE_TEXTURE_2D: |
||||
return nr_samples > 1 ? TGSI_TEXTURE_2D_MSAA : TGSI_TEXTURE_2D; |
||||
|
||||
case PIPE_TEXTURE_RECT: |
||||
assert(nr_samples <= 1); |
||||
return TGSI_TEXTURE_RECT; |
||||
|
||||
case PIPE_TEXTURE_3D: |
||||
assert(nr_samples <= 1); |
||||
return TGSI_TEXTURE_3D; |
||||
|
||||
case PIPE_TEXTURE_CUBE: |
||||
assert(nr_samples <= 1); |
||||
return TGSI_TEXTURE_CUBE; |
||||
|
||||
case PIPE_TEXTURE_1D_ARRAY: |
||||
assert(nr_samples <= 1); |
||||
return TGSI_TEXTURE_1D_ARRAY; |
||||
|
||||
case PIPE_TEXTURE_2D_ARRAY: |
||||
return nr_samples > 1 ? TGSI_TEXTURE_2D_ARRAY_MSAA : |
||||
TGSI_TEXTURE_2D_ARRAY; |
||||
|
||||
case PIPE_TEXTURE_CUBE_ARRAY: |
||||
return TGSI_TEXTURE_CUBE_ARRAY; |
||||
|
||||
default: |
||||
assert(0 && "unexpected texture target"); |
||||
return TGSI_TEXTURE_UNKNOWN; |
||||
} |
||||
} |
||||
|
||||
|
||||
static INLINE void |
||||
util_copy_constant_buffer(struct pipe_constant_buffer *dst, |
||||
const struct pipe_constant_buffer *src) |
||||
{ |
||||
if (src) { |
||||
pipe_resource_reference(&dst->buffer, src->buffer); |
||||
dst->buffer_offset = src->buffer_offset; |
||||
dst->buffer_size = src->buffer_size; |
||||
dst->user_buffer = src->user_buffer; |
||||
} |
||||
else { |
||||
pipe_resource_reference(&dst->buffer, NULL); |
||||
dst->buffer_offset = 0; |
||||
dst->buffer_size = 0; |
||||
dst->user_buffer = NULL; |
||||
} |
||||
} |
||||
|
||||
static INLINE unsigned |
||||
util_max_layer(const struct pipe_resource *r, unsigned level) |
||||
{ |
||||
switch (r->target) { |
||||
case PIPE_TEXTURE_CUBE: |
||||
return 6 - 1; |
||||
case PIPE_TEXTURE_3D: |
||||
return u_minify(r->depth0, level) - 1; |
||||
case PIPE_TEXTURE_1D_ARRAY: |
||||
case PIPE_TEXTURE_2D_ARRAY: |
||||
case PIPE_TEXTURE_CUBE_ARRAY: |
||||
return r->array_size - 1; |
||||
default: |
||||
return 0; |
||||
} |
||||
} |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* U_INLINES_H */ |
@ -0,0 +1,868 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* 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. |
||||
*
|
||||
**************************************************************************/ |
||||
|
||||
|
||||
/**
|
||||
* Math utilities and approximations for common math functions. |
||||
* Reduced precision is usually acceptable in shaders... |
||||
* |
||||
* "fast" is used in the names of functions which are low-precision, |
||||
* or at least lower-precision than the normal C lib functions. |
||||
*/ |
||||
|
||||
|
||||
#ifndef U_MATH_H |
||||
#define U_MATH_H |
||||
|
||||
|
||||
#include "pipe/p_compiler.h" |
||||
|
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
|
||||
#include <math.h> |
||||
#include <float.h> |
||||
#include <stdarg.h> |
||||
|
||||
#ifdef PIPE_OS_UNIX |
||||
#include <strings.h> /* for ffs */ |
||||
#endif |
||||
|
||||
|
||||
#ifndef M_SQRT2 |
||||
#define M_SQRT2 1.41421356237309504880 |
||||
#endif |
||||
|
||||
|
||||
#if defined(_MSC_VER) |
||||
|
||||
#if _MSC_VER < 1400 && !defined(__cplusplus) |
||||
|
||||
static INLINE float cosf( float f )
|
||||
{ |
||||
return (float) cos( (double) f ); |
||||
} |
||||
|
||||
static INLINE float sinf( float f )
|
||||
{ |
||||
return (float) sin( (double) f ); |
||||
} |
||||
|
||||
static INLINE float ceilf( float f )
|
||||
{ |
||||
return (float) ceil( (double) f ); |
||||
} |
||||
|
||||
static INLINE float floorf( float f )
|
||||
{ |
||||
return (float) floor( (double) f ); |
||||
} |
||||
|
||||
static INLINE float powf( float f, float g )
|
||||
{ |
||||
return (float) pow( (double) f, (double) g ); |
||||
} |
||||
|
||||
static INLINE float sqrtf( float f )
|
||||
{ |
||||
return (float) sqrt( (double) f ); |
||||
} |
||||
|
||||
static INLINE float fabsf( float f )
|
||||
{ |
||||
return (float) fabs( (double) f ); |
||||
} |
||||
|
||||
static INLINE float logf( float f )
|
||||
{ |
||||
return (float) log( (double) f ); |
||||
} |
||||
|
||||
#else |
||||
/* Work-around an extra semi-colon in VS 2005 logf definition */ |
||||
#ifdef logf |
||||
#undef logf |
||||
#define logf(x) ((float)log((double)(x))) |
||||
#endif /* logf */ |
||||
|
||||
#define isfinite(x) _finite((double)(x)) |
||||
#define isnan(x) _isnan((double)(x)) |
||||
#endif /* _MSC_VER < 1400 && !defined(__cplusplus) */ |
||||
|
||||
static INLINE double log2( double x ) |
||||
{ |
||||
const double invln2 = 1.442695041; |
||||
return log( x ) * invln2; |
||||
} |
||||
|
||||
static INLINE double |
||||
round(double x) |
||||
{ |
||||
return x >= 0.0 ? floor(x + 0.5) : ceil(x - 0.5); |
||||
} |
||||
|
||||
static INLINE float |
||||
roundf(float x) |
||||
{ |
||||
return x >= 0.0f ? floorf(x + 0.5f) : ceilf(x - 0.5f); |
||||
} |
||||
|
||||
#define INFINITY (DBL_MAX + DBL_MAX) |
||||
#define NAN (INFINITY - INFINITY) |
||||
|
||||
#endif /* _MSC_VER */ |
||||
|
||||
|
||||
#ifdef PIPE_OS_ANDROID |
||||
|
||||
static INLINE |
||||
double log2(double d) |
||||
{ |
||||
return log(d) * (1.0 / M_LN2); |
||||
} |
||||
|
||||
/* workaround a conflict with main/imports.h */ |
||||
#ifdef log2f |
||||
#undef log2f |
||||
#endif |
||||
|
||||
static INLINE |
||||
float log2f(float f) |
||||
{ |
||||
return logf(f) * (float) (1.0 / M_LN2); |
||||
} |
||||
|
||||
#endif |
||||
|
||||
|
||||
#if __STDC_VERSION__ < 199901L && (!defined(__cplusplus) || defined(_MSC_VER)) |
||||
static INLINE long int |
||||
lrint(double d) |
||||
{ |
||||
long int rounded = (long int)(d + 0.5); |
||||
|
||||
if (d - floor(d) == 0.5) { |
||||
if (rounded % 2 != 0) |
||||
rounded += (d > 0) ? -1 : 1; |
||||
} |
||||
|
||||
return rounded; |
||||
} |
||||
|
||||
static INLINE long int |
||||
lrintf(float f) |
||||
{ |
||||
long int rounded = (long int)(f + 0.5f); |
||||
|
||||
if (f - floorf(f) == 0.5f) { |
||||
if (rounded % 2 != 0) |
||||
rounded += (f > 0) ? -1 : 1; |
||||
} |
||||
|
||||
return rounded; |
||||
} |
||||
|
||||
static INLINE long long int |
||||
llrint(double d) |
||||
{ |
||||
long long int rounded = (long long int)(d + 0.5); |
||||
|
||||
if (d - floor(d) == 0.5) { |
||||
if (rounded % 2 != 0) |
||||
rounded += (d > 0) ? -1 : 1; |
||||
} |
||||
|
||||
return rounded; |
||||
} |
||||
|
||||
static INLINE long long int |
||||
llrintf(float f) |
||||
{ |
||||
long long int rounded = (long long int)(f + 0.5f); |
||||
|
||||
if (f - floorf(f) == 0.5f) { |
||||
if (rounded % 2 != 0) |
||||
rounded += (f > 0) ? -1 : 1; |
||||
} |
||||
|
||||
return rounded; |
||||
} |
||||
#endif /* C99 */ |
||||
|
||||
#define POW2_TABLE_SIZE_LOG2 9 |
||||
#define POW2_TABLE_SIZE (1 << POW2_TABLE_SIZE_LOG2) |
||||
#define POW2_TABLE_OFFSET (POW2_TABLE_SIZE/2) |
||||
#define POW2_TABLE_SCALE ((float)(POW2_TABLE_SIZE/2)) |
||||
extern float pow2_table[POW2_TABLE_SIZE]; |
||||
|
||||
|
||||
/**
|
||||
* Initialize math module. This should be called before using any |
||||
* other functions in this module. |
||||
*/ |
||||
extern void |
||||
util_init_math(void); |
||||
|
||||
|
||||
union fi { |
||||
float f; |
||||
int32_t i; |
||||
uint32_t ui; |
||||
}; |
||||
|
||||
|
||||
union di { |
||||
double d; |
||||
int64_t i; |
||||
uint64_t ui; |
||||
}; |
||||
|
||||
|
||||
/**
|
||||
* Extract the IEEE float32 exponent. |
||||
*/ |
||||
static INLINE signed |
||||
util_get_float32_exponent(float x) { |
||||
union fi f; |
||||
|
||||
f.f = x; |
||||
|
||||
return ((f.ui >> 23) & 0xff) - 127; |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Fast version of 2^x |
||||
* Identity: exp2(a + b) = exp2(a) * exp2(b) |
||||
* Let ipart = int(x) |
||||
* Let fpart = x - ipart; |
||||
* So, exp2(x) = exp2(ipart) * exp2(fpart) |
||||
* Compute exp2(ipart) with i << ipart |
||||
* Compute exp2(fpart) with lookup table. |
||||
*/ |
||||
static INLINE float |
||||
util_fast_exp2(float x) |
||||
{ |
||||
int32_t ipart; |
||||
float fpart, mpart; |
||||
union fi epart; |
||||
|
||||
if(x > 129.00000f) |
||||
return 3.402823466e+38f; |
||||
|
||||
if (x < -126.99999f) |
||||
return 0.0f; |
||||
|
||||
ipart = (int32_t) x; |
||||
fpart = x - (float) ipart; |
||||
|
||||
/* same as
|
||||
* epart.f = (float) (1 << ipart) |
||||
* but faster and without integer overflow for ipart > 31 |
||||
*/ |
||||
epart.i = (ipart + 127 ) << 23; |
||||
|
||||
mpart = pow2_table[POW2_TABLE_OFFSET + (int)(fpart * POW2_TABLE_SCALE)]; |
||||
|
||||
return epart.f * mpart; |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Fast approximation to exp(x). |
||||
*/ |
||||
static INLINE float |
||||
util_fast_exp(float x) |
||||
{ |
||||
const float k = 1.44269f; /* = log2(e) */ |
||||
return util_fast_exp2(k * x); |
||||
} |
||||
|
||||
|
||||
#define LOG2_TABLE_SIZE_LOG2 16 |
||||
#define LOG2_TABLE_SCALE (1 << LOG2_TABLE_SIZE_LOG2) |
||||
#define LOG2_TABLE_SIZE (LOG2_TABLE_SCALE + 1) |
||||
extern float log2_table[LOG2_TABLE_SIZE]; |
||||
|
||||
|
||||
/**
|
||||
* Fast approximation to log2(x). |
||||
*/ |
||||
static INLINE float |
||||
util_fast_log2(float x) |
||||
{ |
||||
union fi num; |
||||
float epart, mpart; |
||||
num.f = x; |
||||
epart = (float)(((num.i & 0x7f800000) >> 23) - 127); |
||||
/* mpart = log2_table[mantissa*LOG2_TABLE_SCALE + 0.5] */ |
||||
mpart = log2_table[((num.i & 0x007fffff) + (1 << (22 - LOG2_TABLE_SIZE_LOG2))) >> (23 - LOG2_TABLE_SIZE_LOG2)]; |
||||
return epart + mpart; |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Fast approximation to x^y. |
||||
*/ |
||||
static INLINE float |
||||
util_fast_pow(float x, float y) |
||||
{ |
||||
return util_fast_exp2(util_fast_log2(x) * y); |
||||
} |
||||
|
||||
/* Note that this counts zero as a power of two.
|
||||
*/ |
||||
static INLINE boolean |
||||
util_is_power_of_two( unsigned v ) |
||||
{ |
||||
return (v & (v-1)) == 0; |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Floor(x), returned as int. |
||||
*/ |
||||
static INLINE int |
||||
util_ifloor(float f) |
||||
{ |
||||
int ai, bi; |
||||
double af, bf; |
||||
union fi u; |
||||
af = (3 << 22) + 0.5 + (double) f; |
||||
bf = (3 << 22) + 0.5 - (double) f; |
||||
u.f = (float) af; ai = u.i; |
||||
u.f = (float) bf; bi = u.i; |
||||
return (ai - bi) >> 1; |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Round float to nearest int. |
||||
*/ |
||||
static INLINE int |
||||
util_iround(float f) |
||||
{ |
||||
#if defined(PIPE_CC_GCC) && defined(PIPE_ARCH_X86) |
||||
int r; |
||||
__asm__ ("fistpl %0" : "=m" (r) : "t" (f) : "st"); |
||||
return r; |
||||
#elif defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86) |
||||
int r; |
||||
_asm { |
||||
fld f |
||||
fistp r |
||||
} |
||||
return r; |
||||
#else |
||||
if (f >= 0.0f) |
||||
return (int) (f + 0.5f); |
||||
else |
||||
return (int) (f - 0.5f); |
||||
#endif |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Approximate floating point comparison |
||||
*/ |
||||
static INLINE boolean |
||||
util_is_approx(float a, float b, float tol) |
||||
{ |
||||
return fabs(b - a) <= tol; |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* util_is_X_inf_or_nan = test if x is NaN or +/- Inf |
||||
* util_is_X_nan = test if x is NaN |
||||
* util_X_inf_sign = return +1 for +Inf, -1 for -Inf, or 0 for not Inf |
||||
* |
||||
* NaN can be checked with x != x, however this fails with the fast math flag |
||||
**/ |
||||
|
||||
|
||||
/**
|
||||
* Single-float |
||||
*/ |
||||
static INLINE boolean |
||||
util_is_inf_or_nan(float x) |
||||
{ |
||||
union fi tmp; |
||||
tmp.f = x; |
||||
return (tmp.ui & 0x7f800000) == 0x7f800000; |
||||
} |
||||
|
||||
|
||||
static INLINE boolean |
||||
util_is_nan(float x) |
||||
{ |
||||
union fi tmp; |
||||
tmp.f = x; |
||||
return (tmp.ui & 0x7fffffff) > 0x7f800000; |
||||
} |
||||
|
||||
|
||||
static INLINE int |
||||
util_inf_sign(float x) |
||||
{ |
||||
union fi tmp; |
||||
tmp.f = x; |
||||
if ((tmp.ui & 0x7fffffff) != 0x7f800000) { |
||||
return 0; |
||||
} |
||||
|
||||
return (x < 0) ? -1 : 1; |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Double-float |
||||
*/ |
||||
static INLINE boolean |
||||
util_is_double_inf_or_nan(double x) |
||||
{ |
||||
union di tmp; |
||||
tmp.d = x; |
||||
return (tmp.ui & 0x7ff0000000000000ULL) == 0x7ff0000000000000ULL; |
||||
} |
||||
|
||||
|
||||
static INLINE boolean |
||||
util_is_double_nan(double x) |
||||
{ |
||||
union di tmp; |
||||
tmp.d = x; |
||||
return (tmp.ui & 0x7fffffffffffffffULL) > 0x7ff0000000000000ULL; |
||||
} |
||||
|
||||
|
||||
static INLINE int |
||||
util_double_inf_sign(double x) |
||||
{ |
||||
union di tmp; |
||||
tmp.d = x; |
||||
if ((tmp.ui & 0x7fffffffffffffffULL) != 0x7ff0000000000000ULL) { |
||||
return 0; |
||||
} |
||||
|
||||
return (x < 0) ? -1 : 1; |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Half-float |
||||
*/ |
||||
static INLINE boolean |
||||
util_is_half_inf_or_nan(int16_t x) |
||||
{ |
||||
return (x & 0x7c00) == 0x7c00; |
||||
} |
||||
|
||||
|
||||
static INLINE boolean |
||||
util_is_half_nan(int16_t x) |
||||
{ |
||||
return (x & 0x7fff) > 0x7c00; |
||||
} |
||||
|
||||
|
||||
static INLINE int |
||||
util_half_inf_sign(int16_t x) |
||||
{ |
||||
if ((x & 0x7fff) != 0x7c00) { |
||||
return 0; |
||||
} |
||||
|
||||
return (x < 0) ? -1 : 1; |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Find first bit set in word. Least significant bit is 1. |
||||
* Return 0 if no bits set. |
||||
*/ |
||||
#ifndef FFS_DEFINED |
||||
#define FFS_DEFINED 1 |
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1300 && (_M_IX86 || _M_AMD64 || _M_IA64) |
||||
unsigned char _BitScanForward(unsigned long* Index, unsigned long Mask); |
||||
#pragma intrinsic(_BitScanForward) |
||||
static INLINE |
||||
unsigned long ffs( unsigned long u ) |
||||
{ |
||||
unsigned long i; |
||||
if (_BitScanForward(&i, u)) |
||||
return i + 1; |
||||
else |
||||
return 0; |
||||
} |
||||
#elif defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86) |
||||
static INLINE |
||||
unsigned ffs( unsigned u ) |
||||
{ |
||||
unsigned i; |
||||
|
||||
if (u == 0) { |
||||
return 0; |
||||
} |
||||
|
||||
__asm bsf eax, [u] |
||||
__asm inc eax |
||||
__asm mov [i], eax |
||||
|
||||
return i; |
||||
} |
||||
#elif defined(__MINGW32__) || defined(PIPE_OS_ANDROID) |
||||
#define ffs __builtin_ffs |
||||
#endif |
||||
|
||||
#endif /* FFS_DEFINED */ |
||||
|
||||
/**
|
||||
* Find last bit set in a word. The least significant bit is 1. |
||||
* Return 0 if no bits are set. |
||||
*/ |
||||
static INLINE unsigned util_last_bit(unsigned u) |
||||
{ |
||||
#if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) |
||||
return u == 0 ? 0 : 32 - __builtin_clz(u); |
||||
#else |
||||
unsigned r = 0; |
||||
while (u) { |
||||
r++; |
||||
u >>= 1; |
||||
} |
||||
return r; |
||||
#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) |
||||
{ |
||||
int i = ffs(*mask) - 1; |
||||
*mask &= ~(1 << i); |
||||
return i; |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Return float bits. |
||||
*/ |
||||
static INLINE unsigned |
||||
fui( float f ) |
||||
{ |
||||
union fi fi; |
||||
fi.f = f; |
||||
return fi.ui; |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Convert ubyte to float in [0, 1]. |
||||
* XXX a 256-entry lookup table would be slightly faster. |
||||
*/ |
||||
static INLINE float |
||||
ubyte_to_float(ubyte ub) |
||||
{ |
||||
return (float) ub * (1.0f / 255.0f); |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Convert float in [0,1] to ubyte in [0,255] with clamping. |
||||
*/ |
||||
static INLINE ubyte |
||||
float_to_ubyte(float f) |
||||
{ |
||||
union fi tmp; |
||||
|
||||
tmp.f = f; |
||||
if (tmp.i < 0) { |
||||
return (ubyte) 0; |
||||
} |
||||
else if (tmp.i >= 0x3f800000 /* 1.0f */) { |
||||
return (ubyte) 255; |
||||
} |
||||
else { |
||||
tmp.f = tmp.f * (255.0f/256.0f) + 32768.0f; |
||||
return (ubyte) tmp.i; |
||||
} |
||||
} |
||||
|
||||
static INLINE float |
||||
byte_to_float_tex(int8_t b) |
||||
{ |
||||
return (b == -128) ? -1.0F : b * 1.0F / 127.0F; |
||||
} |
||||
|
||||
static INLINE int8_t |
||||
float_to_byte_tex(float f) |
||||
{ |
||||
return (int8_t) (127.0F * f); |
||||
} |
||||
|
||||
/**
|
||||
* Calc log base 2 |
||||
*/ |
||||
static INLINE unsigned |
||||
util_logbase2(unsigned n) |
||||
{ |
||||
#if defined(PIPE_CC_GCC) && (PIPE_CC_GCC_VERSION >= 304) |
||||
return ((sizeof(unsigned) * 8 - 1) - __builtin_clz(n | 1)); |
||||
#else |
||||
unsigned pos = 0; |
||||
if (n >= 1<<16) { n >>= 16; pos += 16; } |
||||
if (n >= 1<< 8) { n >>= 8; pos += 8; } |
||||
if (n >= 1<< 4) { n >>= 4; pos += 4; } |
||||
if (n >= 1<< 2) { n >>= 2; pos += 2; } |
||||
if (n >= 1<< 1) { pos += 1; } |
||||
return pos; |
||||
#endif |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Returns the smallest power of two >= x |
||||
*/ |
||||
static INLINE unsigned |
||||
util_next_power_of_two(unsigned x) |
||||
{ |
||||
#if defined(PIPE_CC_GCC) && (PIPE_CC_GCC_VERSION >= 304) |
||||
if (x <= 1) |
||||
return 1; |
||||
|
||||
return (1 << ((sizeof(unsigned) * 8) - __builtin_clz(x - 1))); |
||||
#else |
||||
unsigned val = x; |
||||
|
||||
if (x <= 1) |
||||
return 1; |
||||
|
||||
if (util_is_power_of_two(x)) |
||||
return x; |
||||
|
||||
val--; |
||||
val = (val >> 1) | val; |
||||
val = (val >> 2) | val; |
||||
val = (val >> 4) | val; |
||||
val = (val >> 8) | val; |
||||
val = (val >> 16) | val; |
||||
val++; |
||||
return val; |
||||
#endif |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Return number of bits set in n. |
||||
*/ |
||||
static INLINE unsigned |
||||
util_bitcount(unsigned n) |
||||
{ |
||||
#if defined(PIPE_CC_GCC) && (PIPE_CC_GCC_VERSION >= 304) |
||||
return __builtin_popcount(n); |
||||
#else |
||||
/* K&R classic bitcount.
|
||||
* |
||||
* For each iteration, clear the LSB from the bitfield. |
||||
* Requires only one iteration per set bit, instead of |
||||
* one iteration per bit less than highest set bit. |
||||
*/ |
||||
unsigned bits = 0; |
||||
for (bits; n; bits++) { |
||||
n &= n - 1; |
||||
} |
||||
return bits; |
||||
#endif |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Convert from little endian to CPU byte order. |
||||
*/ |
||||
|
||||
#ifdef PIPE_ARCH_BIG_ENDIAN |
||||
#define util_le64_to_cpu(x) util_bswap64(x) |
||||
#define util_le32_to_cpu(x) util_bswap32(x) |
||||
#define util_le16_to_cpu(x) util_bswap16(x) |
||||
#else |
||||
#define util_le64_to_cpu(x) (x) |
||||
#define util_le32_to_cpu(x) (x) |
||||
#define util_le16_to_cpu(x) (x) |
||||
#endif |
||||
|
||||
#define util_cpu_to_le64(x) util_le64_to_cpu(x) |
||||
#define util_cpu_to_le32(x) util_le32_to_cpu(x) |
||||
#define util_cpu_to_le16(x) util_le16_to_cpu(x) |
||||
|
||||
/**
|
||||
* Reverse byte order of a 32 bit word. |
||||
*/ |
||||
static INLINE uint32_t |
||||
util_bswap32(uint32_t n) |
||||
{ |
||||
/* We need the gcc version checks for non-autoconf build system */ |
||||
#if defined(HAVE___BUILTIN_BSWAP32) || (defined(PIPE_CC_GCC) && (PIPE_CC_GCC_VERSION >= 403)) |
||||
return __builtin_bswap32(n); |
||||
#else |
||||
return (n >> 24) | |
||||
((n >> 8) & 0x0000ff00) | |
||||
((n << 8) & 0x00ff0000) | |
||||
(n << 24); |
||||
#endif |
||||
} |
||||
|
||||
/**
|
||||
* Reverse byte order of a 64bit word. |
||||
*/ |
||||
static INLINE uint64_t |
||||
util_bswap64(uint64_t n) |
||||
{ |
||||
#if defined(HAVE___BUILTIN_BSWAP64) |
||||
return __builtin_bswap64(n); |
||||
#else |
||||
return ((uint64_t)util_bswap32(n) << 32) | |
||||
util_bswap32((n >> 32)); |
||||
#endif |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Reverse byte order of a 16 bit word. |
||||
*/ |
||||
static INLINE uint16_t |
||||
util_bswap16(uint16_t n) |
||||
{ |
||||
return (n >> 8) | |
||||
(n << 8); |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Clamp X to [MIN, MAX]. |
||||
* This is a macro to allow float, int, uint, etc. types. |
||||
*/ |
||||
#define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) ) |
||||
|
||||
#define MIN2( A, B ) ( (A)<(B) ? (A) : (B) ) |
||||
#define MAX2( A, B ) ( (A)>(B) ? (A) : (B) ) |
||||
|
||||
#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)) |
||||
|
||||
#define MIN4( A, B, C, D ) ((A) < (B) ? MIN3(A, C, D) : MIN3(B, C, D)) |
||||
#define MAX4( A, B, C, D ) ((A) > (B) ? MAX3(A, C, D) : MAX3(B, C, D)) |
||||
|
||||
|
||||
/**
|
||||
* Align a value, only works pot alignemnts. |
||||
*/ |
||||
static INLINE int |
||||
align(int value, int alignment) |
||||
{ |
||||
return (value + alignment - 1) & ~(alignment - 1); |
||||
} |
||||
|
||||
/**
|
||||
* Works like align but on npot alignments. |
||||
*/ |
||||
static INLINE size_t |
||||
util_align_npot(size_t value, size_t alignment) |
||||
{ |
||||
if (value % alignment) |
||||
return value + (alignment - (value % alignment)); |
||||
return value; |
||||
} |
||||
|
||||
static INLINE unsigned |
||||
u_minify(unsigned value, unsigned levels) |
||||
{ |
||||
return MAX2(1, value >> levels); |
||||
} |
||||
|
||||
#ifndef COPY_4V |
||||
#define COPY_4V( DST, SRC ) \ |
||||
do { \
|
||||
(DST)[0] = (SRC)[0]; \
|
||||
(DST)[1] = (SRC)[1]; \
|
||||
(DST)[2] = (SRC)[2]; \
|
||||
(DST)[3] = (SRC)[3]; \
|
||||
} while (0) |
||||
#endif |
||||
|
||||
|
||||
#ifndef COPY_4FV |
||||
#define COPY_4FV( DST, SRC ) COPY_4V(DST, SRC) |
||||
#endif |
||||
|
||||
|
||||
#ifndef ASSIGN_4V |
||||
#define ASSIGN_4V( DST, V0, V1, V2, V3 ) \ |
||||
do { \
|
||||
(DST)[0] = (V0); \
|
||||
(DST)[1] = (V1); \
|
||||
(DST)[2] = (V2); \
|
||||
(DST)[3] = (V3); \
|
||||
} while (0) |
||||
#endif |
||||
|
||||
|
||||
static INLINE uint32_t util_unsigned_fixed(float value, unsigned frac_bits) |
||||
{ |
||||
return value < 0 ? 0 : (uint32_t)(value * (1<<frac_bits)); |
||||
} |
||||
|
||||
static INLINE int32_t util_signed_fixed(float value, unsigned frac_bits) |
||||
{ |
||||
return (int32_t)(value * (1<<frac_bits)); |
||||
} |
||||
|
||||
unsigned |
||||
util_fpstate_get(void); |
||||
unsigned |
||||
util_fpstate_set_denorms_to_zero(unsigned current_fpstate); |
||||
void |
||||
util_fpstate_set(unsigned fpstate); |
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* U_MATH_H */ |
@ -0,0 +1,100 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* 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. |
||||
*
|
||||
**************************************************************************/ |
||||
|
||||
|
||||
/*
|
||||
* Memory functions |
||||
*/ |
||||
|
||||
|
||||
#ifndef U_MEMORY_H |
||||
#define U_MEMORY_H |
||||
|
||||
|
||||
#include "util/u_pointer.h" |
||||
#include "util/u_debug.h" |
||||
#include "os/os_memory.h" |
||||
|
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
|
||||
#define MALLOC(_size) os_malloc(_size) |
||||
|
||||
#define CALLOC(_count, _size) os_calloc(_count, _size) |
||||
|
||||
#define FREE(_ptr ) os_free(_ptr) |
||||
|
||||
#define REALLOC(_ptr, _old_size, _size) os_realloc(_ptr, _old_size, _size) |
||||
|
||||
#define MALLOC_STRUCT(T) (struct T *) MALLOC(sizeof(struct T)) |
||||
|
||||
#define CALLOC_STRUCT(T) (struct T *) CALLOC(1, sizeof(struct T)) |
||||
|
||||
#define CALLOC_VARIANT_LENGTH_STRUCT(T,more_size) ((struct T *) CALLOC(1, sizeof(struct T) + more_size)) |
||||
|
||||
|
||||
#define align_malloc(_size, _alignment) os_malloc_aligned(_size, _alignment) |
||||
#define align_free(_ptr) os_free_aligned(_ptr) |
||||
|
||||
|
||||
/**
|
||||
* Duplicate a block of memory. |
||||
*/ |
||||
static INLINE void * |
||||
mem_dup(const void *src, uint size) |
||||
{ |
||||
void *dup = MALLOC(size); |
||||
if (dup) |
||||
memcpy(dup, src, size); |
||||
return dup; |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Number of elements in an array. |
||||
*/ |
||||
#ifndef Elements |
||||
#define Elements(x) (sizeof(x)/sizeof((x)[0])) |
||||
#endif |
||||
|
||||
|
||||
/**
|
||||
* Offset of a field in a struct, in bytes. |
||||
*/ |
||||
#define Offset(TYPE, MEMBER) ((uintptr_t)&(((TYPE *)NULL)->MEMBER)) |
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
|
||||
#endif /* U_MEMORY_H */ |
@ -0,0 +1,651 @@ |
||||
/**************************************************************************
|
||||
* |
||||
* 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. |
||||
* |
||||
**************************************************************************/ |
||||
|
||||
/**
|
||||
* @file |
||||
* Functions to produce packed colors/Z from floats. |
||||
*/ |
||||
|
||||
|
||||
#ifndef U_PACK_COLOR_H |
||||
#define U_PACK_COLOR_H |
||||
|
||||
|
||||
#include "pipe/p_compiler.h" |
||||
#include "pipe/p_format.h" |
||||
#include "util/u_debug.h" |
||||
#include "util/u_format.h" |
||||
#include "util/u_math.h" |
||||
|
||||
|
||||
/**
|
||||
* Helper union for packing pixel values. |
||||
* Will often contain values in formats which are too complex to be described |
||||
* in simple terms, hence might just effectively contain a number of bytes. |
||||
* Must be big enough to hold data for all formats (currently 256 bits). |
||||
*/ |
||||
union util_color { |
||||
ubyte ub; |
||||
ushort us; |
||||
uint ui; |
||||
ushort h[4]; /* half float */ |
||||
float f[4]; |
||||
double d[4]; |
||||
}; |
||||
|
||||
/**
|
||||
* Pack ubyte R,G,B,A into dest pixel. |
||||
*/ |
||||
static INLINE void |
||||
util_pack_color_ub(ubyte r, ubyte g, ubyte b, ubyte a, |
||||
enum pipe_format format, union util_color *uc) |
||||
{ |
||||
switch (format) { |
||||
case PIPE_FORMAT_ABGR8888_UNORM: |
||||
{ |
||||
uc->ui = (r << 24) | (g << 16) | (b << 8) | a; |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_XBGR8888_UNORM: |
||||
{ |
||||
uc->ui = (r << 24) | (g << 16) | (b << 8) | 0xff; |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_BGRA8888_UNORM: |
||||
{ |
||||
uc->ui = (a << 24) | (r << 16) | (g << 8) | b; |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_BGRX8888_UNORM: |
||||
{ |
||||
uc->ui = (0xff << 24) | (r << 16) | (g << 8) | b; |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_ARGB8888_UNORM: |
||||
{ |
||||
uc->ui = (b << 24) | (g << 16) | (r << 8) | a; |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_XRGB8888_UNORM: |
||||
{ |
||||
uc->ui = (b << 24) | (g << 16) | (r << 8) | 0xff; |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_B5G6R5_UNORM: |
||||
{ |
||||
uc->us = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3); |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_B5G5R5X1_UNORM: |
||||
{ |
||||
uc->us = ((0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_B5G5R5A1_UNORM: |
||||
{ |
||||
uc->us = ((a & 0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_B4G4R4A4_UNORM: |
||||
{ |
||||
uc->us = ((a & 0xf0) << 8) | ((r & 0xf0) << 4) | ((g & 0xf0) << 0) | (b >> 4); |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_A8_UNORM: |
||||
{ |
||||
uc->ub = a; |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_L8_UNORM: |
||||
case PIPE_FORMAT_I8_UNORM: |
||||
{ |
||||
uc->ub = r; |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_R32G32B32A32_FLOAT: |
||||
{ |
||||
uc->f[0] = (float)r / 255.0f; |
||||
uc->f[1] = (float)g / 255.0f; |
||||
uc->f[2] = (float)b / 255.0f; |
||||
uc->f[3] = (float)a / 255.0f; |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_R32G32B32_FLOAT: |
||||
{ |
||||
uc->f[0] = (float)r / 255.0f; |
||||
uc->f[1] = (float)g / 255.0f; |
||||
uc->f[2] = (float)b / 255.0f; |
||||
} |
||||
return; |
||||
|
||||
/* Handle other cases with a generic function.
|
||||
*/ |
||||
default: |
||||
{ |
||||
ubyte src[4]; |
||||
|
||||
src[0] = r; |
||||
src[1] = g; |
||||
src[2] = b; |
||||
src[3] = a; |
||||
util_format_write_4ub(format, src, 0, uc, 0, 0, 0, 1, 1); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Unpack RGBA from a packed pixel, returning values as ubytes in [0,255]. |
||||
*/ |
||||
static INLINE void |
||||
util_unpack_color_ub(enum pipe_format format, union util_color *uc, |
||||
ubyte *r, ubyte *g, ubyte *b, ubyte *a) |
||||
{ |
||||
switch (format) { |
||||
case PIPE_FORMAT_ABGR8888_UNORM: |
||||
{ |
||||
uint p = uc->ui; |
||||
*r = (ubyte) ((p >> 24) & 0xff); |
||||
*g = (ubyte) ((p >> 16) & 0xff); |
||||
*b = (ubyte) ((p >> 8) & 0xff); |
||||
*a = (ubyte) ((p >> 0) & 0xff); |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_XBGR8888_UNORM: |
||||
{ |
||||
uint p = uc->ui; |
||||
*r = (ubyte) ((p >> 24) & 0xff); |
||||
*g = (ubyte) ((p >> 16) & 0xff); |
||||
*b = (ubyte) ((p >> 8) & 0xff); |
||||
*a = (ubyte) 0xff; |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_BGRA8888_UNORM: |
||||
{ |
||||
uint p = uc->ui; |
||||
*r = (ubyte) ((p >> 16) & 0xff); |
||||
*g = (ubyte) ((p >> 8) & 0xff); |
||||
*b = (ubyte) ((p >> 0) & 0xff); |
||||
*a = (ubyte) ((p >> 24) & 0xff); |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_BGRX8888_UNORM: |
||||
{ |
||||
uint p = uc->ui; |
||||
*r = (ubyte) ((p >> 16) & 0xff); |
||||
*g = (ubyte) ((p >> 8) & 0xff); |
||||
*b = (ubyte) ((p >> 0) & 0xff); |
||||
*a = (ubyte) 0xff; |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_ARGB8888_UNORM: |
||||
{ |
||||
uint p = uc->ui; |
||||
*r = (ubyte) ((p >> 8) & 0xff); |
||||
*g = (ubyte) ((p >> 16) & 0xff); |
||||
*b = (ubyte) ((p >> 24) & 0xff); |
||||
*a = (ubyte) ((p >> 0) & 0xff); |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_XRGB8888_UNORM: |
||||
{ |
||||
uint p = uc->ui; |
||||
*r = (ubyte) ((p >> 8) & 0xff); |
||||
*g = (ubyte) ((p >> 16) & 0xff); |
||||
*b = (ubyte) ((p >> 24) & 0xff); |
||||
*a = (ubyte) 0xff; |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_B5G6R5_UNORM: |
||||
{ |
||||
ushort p = uc->us; |
||||
*r = (ubyte) (((p >> 8) & 0xf8) | ((p >> 13) & 0x7)); |
||||
*g = (ubyte) (((p >> 3) & 0xfc) | ((p >> 9) & 0x3)); |
||||
*b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7)); |
||||
*a = (ubyte) 0xff; |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_B5G5R5X1_UNORM: |
||||
{ |
||||
ushort p = uc->us; |
||||
*r = (ubyte) (((p >> 7) & 0xf8) | ((p >> 12) & 0x7)); |
||||
*g = (ubyte) (((p >> 2) & 0xf8) | ((p >> 7) & 0x7)); |
||||
*b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7)); |
||||
*a = (ubyte) 0xff; |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_B5G5R5A1_UNORM: |
||||
{ |
||||
ushort p = uc->us; |
||||
*r = (ubyte) (((p >> 7) & 0xf8) | ((p >> 12) & 0x7)); |
||||
*g = (ubyte) (((p >> 2) & 0xf8) | ((p >> 7) & 0x7)); |
||||
*b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7)); |
||||
*a = (ubyte) (0xff * (p >> 15)); |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_B4G4R4A4_UNORM: |
||||
{ |
||||
ushort p = uc->us; |
||||
*r = (ubyte) (((p >> 4) & 0xf0) | ((p >> 8) & 0xf)); |
||||
*g = (ubyte) (((p >> 0) & 0xf0) | ((p >> 4) & 0xf)); |
||||
*b = (ubyte) (((p << 4) & 0xf0) | ((p >> 0) & 0xf)); |
||||
*a = (ubyte) (((p >> 8) & 0xf0) | ((p >> 12) & 0xf)); |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_A8_UNORM: |
||||
{ |
||||
ubyte p = uc->ub; |
||||
*r = *g = *b = (ubyte) 0xff; |
||||
*a = p; |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_L8_UNORM: |
||||
{ |
||||
ubyte p = uc->ub; |
||||
*r = *g = *b = p; |
||||
*a = (ubyte) 0xff; |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_I8_UNORM: |
||||
{ |
||||
ubyte p = uc->ub; |
||||
*r = *g = *b = *a = p; |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_R32G32B32A32_FLOAT: |
||||
{ |
||||
const float *p = &uc->f[0]; |
||||
*r = float_to_ubyte(p[0]); |
||||
*g = float_to_ubyte(p[1]); |
||||
*b = float_to_ubyte(p[2]); |
||||
*a = float_to_ubyte(p[3]); |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_R32G32B32_FLOAT: |
||||
{ |
||||
const float *p = &uc->f[0]; |
||||
*r = float_to_ubyte(p[0]); |
||||
*g = float_to_ubyte(p[1]); |
||||
*b = float_to_ubyte(p[2]); |
||||
*a = (ubyte) 0xff; |
||||
} |
||||
return; |
||||
|
||||
case PIPE_FORMAT_R32G32_FLOAT: |
||||
{ |
||||
const float *p = &uc->f[0]; |
||||
*r = float_to_ubyte(p[0]); |
||||
*g = float_to_ubyte(p[1]); |
||||
*b = *a = (ubyte) 0xff; |
||||
} |
||||
return; |
||||
|
||||
case PIPE_FORMAT_R32_FLOAT: |
||||
{ |
||||
const float *p = &uc->f[0]; |
||||
*r = float_to_ubyte(p[0]); |
||||
*g = *b = *a = (ubyte) 0xff; |
||||
} |
||||
return; |
||||
|
||||
/* Handle other cases with a generic function.
|
||||
*/ |
||||
default: |
||||
{ |
||||
ubyte dst[4]; |
||||
|
||||
util_format_read_4ub(format, dst, 0, uc, 0, 0, 0, 1, 1); |
||||
*r = dst[0]; |
||||
*g = dst[1]; |
||||
*b = dst[2]; |
||||
*a = dst[3]; |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Note rgba outside [0,1] will be clamped for int pixel formats. |
||||
* This will not work (and might not really be useful with float input) |
||||
* for pure integer formats (which lack the pack_rgba_float function). |
||||
*/ |
||||
static INLINE void |
||||
util_pack_color(const float rgba[4], enum pipe_format format, union util_color *uc) |
||||
{ |
||||
ubyte r = 0; |
||||
ubyte g = 0; |
||||
ubyte b = 0; |
||||
ubyte a = 0; |
||||
|
||||
if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 0) <= 8) { |
||||
/* format uses 8-bit components or less */ |
||||
r = float_to_ubyte(rgba[0]); |
||||
g = float_to_ubyte(rgba[1]); |
||||
b = float_to_ubyte(rgba[2]); |
||||
a = float_to_ubyte(rgba[3]); |
||||
} |
||||
|
||||
switch (format) { |
||||
case PIPE_FORMAT_ABGR8888_UNORM: |
||||
{ |
||||
uc->ui = (r << 24) | (g << 16) | (b << 8) | a; |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_XBGR8888_UNORM: |
||||
{ |
||||
uc->ui = (r << 24) | (g << 16) | (b << 8) | 0xff; |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_BGRA8888_UNORM: |
||||
{ |
||||
uc->ui = (a << 24) | (r << 16) | (g << 8) | b; |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_BGRX8888_UNORM: |
||||
{ |
||||
uc->ui = (0xff << 24) | (r << 16) | (g << 8) | b; |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_ARGB8888_UNORM: |
||||
{ |
||||
uc->ui = (b << 24) | (g << 16) | (r << 8) | a; |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_XRGB8888_UNORM: |
||||
{ |
||||
uc->ui = (b << 24) | (g << 16) | (r << 8) | 0xff; |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_B5G6R5_UNORM: |
||||
{ |
||||
uc->us = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3); |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_B5G5R5X1_UNORM: |
||||
{ |
||||
uc->us = ((0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_B5G5R5A1_UNORM: |
||||
{ |
||||
uc->us = ((a & 0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_B4G4R4A4_UNORM: |
||||
{ |
||||
uc->us = ((a & 0xf0) << 8) | ((r & 0xf0) << 4) | ((g & 0xf0) << 0) | (b >> 4); |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_A8_UNORM: |
||||
{ |
||||
uc->ub = a; |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_L8_UNORM: |
||||
case PIPE_FORMAT_I8_UNORM: |
||||
{ |
||||
uc->ub = r; |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_R32G32B32A32_FLOAT: |
||||
{ |
||||
uc->f[0] = rgba[0]; |
||||
uc->f[1] = rgba[1]; |
||||
uc->f[2] = rgba[2]; |
||||
uc->f[3] = rgba[3]; |
||||
} |
||||
return; |
||||
case PIPE_FORMAT_R32G32B32_FLOAT: |
||||
{ |
||||
uc->f[0] = rgba[0]; |
||||
uc->f[1] = rgba[1]; |
||||
uc->f[2] = rgba[2]; |
||||
} |
||||
return; |
||||
|
||||
/* Handle other cases with a generic function.
|
||||
*/ |
||||
default: |
||||
util_format_write_4f(format, rgba, 0, uc, 0, 0, 0, 1, 1); |
||||
} |
||||
} |
||||
|
||||
/* Integer versions of util_pack_z and util_pack_z_stencil - useful for
|
||||
* constructing clear masks. |
||||
*/ |
||||
static INLINE uint32_t |
||||
util_pack_mask_z(enum pipe_format format, uint32_t z) |
||||
{ |
||||
switch (format) { |
||||
case PIPE_FORMAT_Z16_UNORM: |
||||
return z & 0xffff; |
||||
case PIPE_FORMAT_Z32_UNORM: |
||||
case PIPE_FORMAT_Z32_FLOAT: |
||||
return z; |
||||
case PIPE_FORMAT_Z24_UNORM_S8_UINT: |
||||
case PIPE_FORMAT_Z24X8_UNORM: |
||||
return z & 0xffffff; |
||||
case PIPE_FORMAT_S8_UINT_Z24_UNORM: |
||||
case PIPE_FORMAT_X8Z24_UNORM: |
||||
return (z & 0xffffff) << 8; |
||||
case PIPE_FORMAT_S8_UINT: |
||||
return 0; |
||||
default: |
||||
debug_print_format("gallium: unhandled format in util_pack_mask_z()", format); |
||||
assert(0); |
||||
return 0; |
||||
} |
||||
} |
||||
|
||||
|
||||
static INLINE uint64_t |
||||
util_pack64_mask_z(enum pipe_format format, uint32_t z) |
||||
{ |
||||
switch (format) { |
||||
case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: |
||||
return z; |
||||
default: |
||||
return util_pack_mask_z(format, z); |
||||
} |
||||
} |
||||
|
||||
|
||||
static INLINE uint32_t |
||||
util_pack_mask_z_stencil(enum pipe_format format, uint32_t z, uint8_t s) |
||||
{ |
||||
uint32_t packed = util_pack_mask_z(format, z); |
||||
|
||||
switch (format) { |
||||
case PIPE_FORMAT_Z24_UNORM_S8_UINT: |
||||
packed |= (uint32_t)s << 24; |
||||
break; |
||||
case PIPE_FORMAT_S8_UINT_Z24_UNORM: |
||||
packed |= s; |
||||
break; |
||||
case PIPE_FORMAT_S8_UINT: |
||||
packed |= s; |
||||
break; |
||||
default: |
||||
break; |
||||
} |
||||
|
||||
return packed; |
||||
} |
||||
|
||||
|
||||
static INLINE uint64_t |
||||
util_pack64_mask_z_stencil(enum pipe_format format, uint32_t z, uint8_t s) |
||||
{ |
||||
uint64_t packed; |
||||
|
||||
switch (format) { |
||||
case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: |
||||
packed = util_pack64_mask_z(format, z); |
||||
packed |= (uint64_t)s << 32ull; |
||||
return packed; |
||||
default: |
||||
return util_pack_mask_z_stencil(format, z, s); |
||||
} |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Note: it's assumed that z is in [0,1] |
||||
*/ |
||||
static INLINE uint32_t |
||||
util_pack_z(enum pipe_format format, double z) |
||||
{ |
||||
union fi fui; |
||||
|
||||
if (z == 0.0) |
||||
return 0; |
||||
|
||||
switch (format) { |
||||
case PIPE_FORMAT_Z16_UNORM: |
||||
if (z == 1.0) |
||||
return 0xffff; |
||||
return (uint32_t) lrint(z * 0xffff); |
||||
case PIPE_FORMAT_Z32_UNORM: |
||||
/* special-case to avoid overflow */ |
||||
if (z == 1.0) |
||||
return 0xffffffff; |
||||
return (uint32_t) llrint(z * 0xffffffff); |
||||
case PIPE_FORMAT_Z32_FLOAT: |
||||
fui.f = (float)z; |
||||
return fui.ui; |
||||
case PIPE_FORMAT_Z24_UNORM_S8_UINT: |
||||
case PIPE_FORMAT_Z24X8_UNORM: |
||||
if (z == 1.0) |
||||
return 0xffffff; |
||||
return (uint32_t) lrint(z * 0xffffff); |
||||
case PIPE_FORMAT_S8_UINT_Z24_UNORM: |
||||
case PIPE_FORMAT_X8Z24_UNORM: |
||||
if (z == 1.0) |
||||
return 0xffffff00; |
||||
return ((uint32_t) lrint(z * 0xffffff)) << 8; |
||||
case PIPE_FORMAT_S8_UINT: |
||||
/* this case can get it via util_pack_z_stencil() */ |
||||
return 0; |
||||
default: |
||||
debug_print_format("gallium: unhandled format in util_pack_z()", format); |
||||
assert(0); |
||||
return 0; |
||||
} |
||||
} |
||||
|
||||
|
||||
static INLINE uint64_t |
||||
util_pack64_z(enum pipe_format format, double z) |
||||
{ |
||||
union fi fui; |
||||
|
||||
if (z == 0) |
||||
return 0; |
||||
|
||||
switch (format) { |
||||
case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: |
||||
fui.f = (float)z; |
||||
return fui.ui; |
||||
default: |
||||
return util_pack_z(format, z); |
||||
} |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Pack Z and/or stencil values into a 32-bit value described by format. |
||||
* Note: it's assumed that z is in [0,1] and s in [0,255] |
||||
*/ |
||||
static INLINE uint32_t |
||||
util_pack_z_stencil(enum pipe_format format, double z, uint8_t s) |
||||
{ |
||||
uint32_t packed = util_pack_z(format, z); |
||||
|
||||
switch (format) { |
||||
case PIPE_FORMAT_Z24_UNORM_S8_UINT: |
||||
packed |= (uint32_t)s << 24; |
||||
break; |
||||
case PIPE_FORMAT_S8_UINT_Z24_UNORM: |
||||
packed |= s; |
||||
break; |
||||
case PIPE_FORMAT_S8_UINT: |
||||
packed |= s; |
||||
break; |
||||
default: |
||||
break; |
||||
} |
||||
|
||||
return packed; |
||||
} |
||||
|
||||
|
||||
static INLINE uint64_t |
||||
util_pack64_z_stencil(enum pipe_format format, double z, uint8_t s) |
||||
{ |
||||
uint64_t packed; |
||||
|
||||
switch (format) { |
||||
case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: |
||||
packed = util_pack64_z(format, z); |
||||
packed |= (uint64_t)s << 32ull; |
||||
break; |
||||
default: |
||||
return util_pack_z_stencil(format, z, s); |
||||
} |
||||
|
||||
return packed; |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Pack 4 ubytes into a 4-byte word |
||||
*/ |
||||
static INLINE unsigned |
||||
pack_ub4(ubyte b0, ubyte b1, ubyte b2, ubyte b3) |
||||
{ |
||||
return ((((unsigned int)b0) << 0) | |
||||
(((unsigned int)b1) << 8) | |
||||
(((unsigned int)b2) << 16) | |
||||
(((unsigned int)b3) << 24)); |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Pack/convert 4 floats into one 4-byte word. |
||||
*/ |
||||
static INLINE unsigned |
||||
pack_ui32_float4(float a, float b, float c, float d) |
||||
{ |
||||
return pack_ub4( float_to_ubyte(a), |
||||
float_to_ubyte(b), |
||||
float_to_ubyte(c), |
||||
float_to_ubyte(d) ); |
||||
} |
||||
|
||||
|
||||
|
||||
#endif /* U_PACK_COLOR_H */ |
@ -0,0 +1,130 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* 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_POINTER_H |
||||
#define U_POINTER_H |
||||
|
||||
#include "pipe/p_compiler.h" |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
static INLINE intptr_t |
||||
pointer_to_intptr( const void *p ) |
||||
{ |
||||
union { |
||||
const void *p; |
||||
intptr_t i; |
||||
} pi; |
||||
pi.p = p; |
||||
return pi.i; |
||||
} |
||||
|
||||
static INLINE void * |
||||
intptr_to_pointer( intptr_t i ) |
||||
{ |
||||
union { |
||||
void *p; |
||||
intptr_t i; |
||||
} pi; |
||||
pi.i = i; |
||||
return pi.p; |
||||
} |
||||
|
||||
static INLINE uintptr_t |
||||
pointer_to_uintptr( const void *ptr ) |
||||
{ |
||||
union { |
||||
const void *p; |
||||
uintptr_t u; |
||||
} pu; |
||||
pu.p = ptr; |
||||
return pu.u; |
||||
} |
||||
|
||||
static INLINE void * |
||||
uintptr_to_pointer( uintptr_t u ) |
||||
{ |
||||
union { |
||||
void *p; |
||||
uintptr_t u; |
||||
} pu; |
||||
pu.u = u; |
||||
return pu.p; |
||||
} |
||||
|
||||
/**
|
||||
* Return a pointer aligned to next multiple of N bytes. |
||||
*/ |
||||
static INLINE void * |
||||
align_pointer( const void *unaligned, uintptr_t alignment ) |
||||
{ |
||||
uintptr_t aligned = (pointer_to_uintptr( unaligned ) + alignment - 1) & ~(alignment - 1); |
||||
return uintptr_to_pointer( aligned ); |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Return a pointer aligned to next multiple of 16 bytes. |
||||
*/ |
||||
static INLINE void * |
||||
align16( void *unaligned ) |
||||
{ |
||||
return align_pointer( unaligned, 16 ); |
||||
} |
||||
|
||||
typedef void (*func_pointer)(void); |
||||
|
||||
static INLINE func_pointer |
||||
pointer_to_func( void *p ) |
||||
{ |
||||
union { |
||||
void *p; |
||||
func_pointer f; |
||||
} pf; |
||||
pf.p = p; |
||||
return pf.f; |
||||
} |
||||
|
||||
static INLINE void * |
||||
func_to_pointer( func_pointer f ) |
||||
{ |
||||
union { |
||||
void *p; |
||||
func_pointer f; |
||||
} pf; |
||||
pf.f = f; |
||||
return pf.p; |
||||
} |
||||
|
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* U_POINTER_H */ |
@ -0,0 +1,268 @@ |
||||
/**************************************************************************
|
||||
* |
||||
* 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 U_PRIM_H |
||||
#define U_PRIM_H |
||||
|
||||
|
||||
#include "pipe/p_defines.h" |
||||
#include "util/u_debug.h" |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
struct u_prim_vertex_count { |
||||
unsigned min; |
||||
unsigned incr; |
||||
}; |
||||
|
||||
/**
|
||||
* Decompose a primitive that is a loop, a strip, or a fan. Return the |
||||
* original primitive if it is already decomposed. |
||||
*/ |
||||
static INLINE unsigned |
||||
u_decomposed_prim(unsigned prim) |
||||
{ |
||||
switch (prim) { |
||||
case PIPE_PRIM_LINE_LOOP: |
||||
case PIPE_PRIM_LINE_STRIP: |
||||
return PIPE_PRIM_LINES; |
||||
case PIPE_PRIM_TRIANGLE_STRIP: |
||||
case PIPE_PRIM_TRIANGLE_FAN: |
||||
return PIPE_PRIM_TRIANGLES; |
||||
case PIPE_PRIM_QUAD_STRIP: |
||||
return PIPE_PRIM_QUADS; |
||||
case PIPE_PRIM_LINE_STRIP_ADJACENCY: |
||||
return PIPE_PRIM_LINES_ADJACENCY; |
||||
case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: |
||||
return PIPE_PRIM_TRIANGLES_ADJACENCY; |
||||
default: |
||||
return prim; |
||||
} |
||||
} |
||||
|
||||
/**
|
||||
* Reduce a primitive to one of PIPE_PRIM_POINTS, PIPE_PRIM_LINES, and |
||||
* PIPE_PRIM_TRIANGLES. |
||||
*/ |
||||
static INLINE unsigned |
||||
u_reduced_prim(unsigned prim) |
||||
{ |
||||
switch (prim) { |
||||
case PIPE_PRIM_POINTS: |
||||
return PIPE_PRIM_POINTS; |
||||
case PIPE_PRIM_LINES: |
||||
case PIPE_PRIM_LINE_LOOP: |
||||
case PIPE_PRIM_LINE_STRIP: |
||||
case PIPE_PRIM_LINES_ADJACENCY: |
||||
case PIPE_PRIM_LINE_STRIP_ADJACENCY: |
||||
return PIPE_PRIM_LINES; |
||||
default: |
||||
return PIPE_PRIM_TRIANGLES; |
||||
} |
||||
} |
||||
|
||||
/**
|
||||
* Re-assemble a primitive to remove its adjacency. |
||||
*/ |
||||
static INLINE unsigned |
||||
u_assembled_prim(unsigned prim) |
||||
{ |
||||
switch (prim) { |
||||
case PIPE_PRIM_LINES_ADJACENCY: |
||||
case PIPE_PRIM_LINE_STRIP_ADJACENCY: |
||||
return PIPE_PRIM_LINES; |
||||
case PIPE_PRIM_TRIANGLES_ADJACENCY: |
||||
case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: |
||||
return PIPE_PRIM_TRIANGLES; |
||||
default: |
||||
return prim; |
||||
} |
||||
} |
||||
|
||||
/**
|
||||
* Return the vertex count information for a primitive. |
||||
* |
||||
* Note that if this function is called directly or indirectly anywhere in a |
||||
* source file, it will increase the size of the binary slightly more than |
||||
* expected because of the use of a table. |
||||
*/ |
||||
static INLINE const struct u_prim_vertex_count * |
||||
u_prim_vertex_count(unsigned prim) |
||||
{ |
||||
static const struct u_prim_vertex_count prim_table[PIPE_PRIM_MAX] = { |
||||
{ 1, 1 }, /* PIPE_PRIM_POINTS */ |
||||
{ 2, 2 }, /* PIPE_PRIM_LINES */ |
||||
{ 2, 1 }, /* PIPE_PRIM_LINE_LOOP */ |
||||
{ 2, 1 }, /* PIPE_PRIM_LINE_STRIP */ |
||||
{ 3, 3 }, /* PIPE_PRIM_TRIANGLES */ |
||||
{ 3, 1 }, /* PIPE_PRIM_TRIANGLE_STRIP */ |
||||
{ 3, 1 }, /* PIPE_PRIM_TRIANGLE_FAN */ |
||||
{ 4, 4 }, /* PIPE_PRIM_QUADS */ |
||||
{ 4, 2 }, /* PIPE_PRIM_QUAD_STRIP */ |
||||
{ 3, 1 }, /* PIPE_PRIM_POLYGON */ |
||||
{ 4, 4 }, /* PIPE_PRIM_LINES_ADJACENCY */ |
||||
{ 4, 1 }, /* PIPE_PRIM_LINE_STRIP_ADJACENCY */ |
||||
{ 6, 6 }, /* PIPE_PRIM_TRIANGLES_ADJACENCY */ |
||||
{ 6, 2 }, /* PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY */ |
||||
}; |
||||
|
||||
return (likely(prim < PIPE_PRIM_MAX)) ? &prim_table[prim] : NULL; |
||||
} |
||||
|
||||
static INLINE boolean u_validate_pipe_prim( unsigned pipe_prim, unsigned nr ) |
||||
{ |
||||
const struct u_prim_vertex_count *count = u_prim_vertex_count(pipe_prim); |
||||
|
||||
return (count && nr >= count->min); |
||||
} |
||||
|
||||
|
||||
static INLINE boolean u_trim_pipe_prim( unsigned pipe_prim, unsigned *nr ) |
||||
{ |
||||
const struct u_prim_vertex_count *count = u_prim_vertex_count(pipe_prim); |
||||
|
||||
if (count && *nr >= count->min) { |
||||
if (count->incr > 1) |
||||
*nr -= (*nr % count->incr); |
||||
return TRUE; |
||||
} |
||||
else { |
||||
*nr = 0; |
||||
return FALSE; |
||||
} |
||||
} |
||||
|
||||
static INLINE unsigned |
||||
u_vertices_per_prim(int primitive) |
||||
{ |
||||
switch(primitive) { |
||||
case PIPE_PRIM_POINTS: |
||||
return 1; |
||||
case PIPE_PRIM_LINES: |
||||
case PIPE_PRIM_LINE_LOOP: |
||||
case PIPE_PRIM_LINE_STRIP: |
||||
return 2; |
||||
case PIPE_PRIM_TRIANGLES: |
||||
case PIPE_PRIM_TRIANGLE_STRIP: |
||||
case PIPE_PRIM_TRIANGLE_FAN: |
||||
return 3; |
||||
case PIPE_PRIM_LINES_ADJACENCY: |
||||
case PIPE_PRIM_LINE_STRIP_ADJACENCY: |
||||
return 4; |
||||
case PIPE_PRIM_TRIANGLES_ADJACENCY: |
||||
case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: |
||||
return 6; |
||||
|
||||
/* following primitives should never be used
|
||||
* with geometry shaders abd their size is |
||||
* undefined */ |
||||
case PIPE_PRIM_POLYGON: |
||||
case PIPE_PRIM_QUADS: |
||||
case PIPE_PRIM_QUAD_STRIP: |
||||
default: |
||||
debug_printf("Unrecognized geometry shader primitive"); |
||||
return 3; |
||||
} |
||||
} |
||||
|
||||
/**
|
||||
* Returns the number of decomposed primitives for the given |
||||
* vertex count. |
||||
* Parts of the pipline are invoked once for each triangle in |
||||
* triangle strip, triangle fans and triangles and once |
||||
* for each line in line strip, line loop, lines. Also
|
||||
* statistics depend on knowing the exact number of decomposed |
||||
* primitives for a set of vertices. |
||||
*/ |
||||
static INLINE unsigned |
||||
u_decomposed_prims_for_vertices(int primitive, int vertices) |
||||
{ |
||||
switch (primitive) { |
||||
case PIPE_PRIM_POINTS: |
||||
return vertices; |
||||
case PIPE_PRIM_LINES: |
||||
return vertices / 2; |
||||
case PIPE_PRIM_LINE_LOOP: |
||||
return (vertices >= 2) ? vertices : 0; |
||||
case PIPE_PRIM_LINE_STRIP: |
||||
return (vertices >= 2) ? vertices - 1 : 0; |
||||
case PIPE_PRIM_TRIANGLES: |
||||
return vertices / 3; |
||||
case PIPE_PRIM_TRIANGLE_STRIP: |
||||
return (vertices >= 3) ? vertices - 2 : 0; |
||||
case PIPE_PRIM_TRIANGLE_FAN: |
||||
return (vertices >= 3) ? vertices - 2 : 0; |
||||
case PIPE_PRIM_LINES_ADJACENCY: |
||||
return vertices / 4; |
||||
case PIPE_PRIM_LINE_STRIP_ADJACENCY: |
||||
return (vertices >= 4) ? vertices - 3 : 0; |
||||
case PIPE_PRIM_TRIANGLES_ADJACENCY: |
||||
return vertices / 6; |
||||
case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: |
||||
return (vertices >= 6) ? 1 + (vertices - 6) / 2 : 0; |
||||
case PIPE_PRIM_QUADS: |
||||
return vertices / 4; |
||||
case PIPE_PRIM_QUAD_STRIP: |
||||
return (vertices >= 4) ? (vertices - 2) / 2 : 0; |
||||
/* Polygons can't be decomposed
|
||||
* because the number of their vertices isn't known so |
||||
* for them and whatever else we don't recognize just |
||||
* return 1 if the number of vertices is greater than |
||||
* or equal to 3 and zero otherwise */ |
||||
case PIPE_PRIM_POLYGON: |
||||
default: |
||||
debug_printf("Invalid decomposition primitive!\n"); |
||||
return (vertices >= 3) ? 1 : 0; |
||||
} |
||||
} |
||||
|
||||
/**
|
||||
* Returns the number of reduced/tessellated primitives for the given vertex |
||||
* count. Each quad is treated as two triangles. Polygons are treated as |
||||
* triangle fans. |
||||
*/ |
||||
static INLINE unsigned |
||||
u_reduced_prims_for_vertices(int primitive, int vertices) |
||||
{ |
||||
switch (primitive) { |
||||
case PIPE_PRIM_QUADS: |
||||
case PIPE_PRIM_QUAD_STRIP: |
||||
return u_decomposed_prims_for_vertices(primitive, vertices) * 2; |
||||
case PIPE_PRIM_POLYGON: |
||||
primitive = PIPE_PRIM_TRIANGLE_FAN; |
||||
/* fall through */ |
||||
default: |
||||
return u_decomposed_prims_for_vertices(primitive, vertices); |
||||
} |
||||
} |
||||
|
||||
const char *u_prim_name( unsigned pipe_prim ); |
||||
|
||||
#endif |
@ -0,0 +1,232 @@ |
||||
/**************************************************************************
|
||||
* |
||||
* 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. |
||||
* |
||||
**************************************************************************/ |
||||
|
||||
/**
|
||||
* @file |
||||
* Platform independent functions for string manipulation. |
||||
* |
||||
* @author Jose Fonseca <jfonseca@vmware.com> |
||||
*/ |
||||
|
||||
#ifndef U_STRING_H_ |
||||
#define U_STRING_H_ |
||||
|
||||
#if !defined(_MSC_VER) && !defined(XF86_LIBC_H) |
||||
#include <stdio.h> |
||||
#endif |
||||
#include <stddef.h> |
||||
#include <stdarg.h> |
||||
|
||||
#include "pipe/p_compiler.h" |
||||
|
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
#ifdef _GNU_SOURCE |
||||
|
||||
#define util_strchrnul strchrnul |
||||
|
||||
#else |
||||
|
||||
static INLINE char * |
||||
util_strchrnul(const char *s, char c) |
||||
{ |
||||
for (; *s && *s != c; ++s); |
||||
|
||||
return (char *)s; |
||||
} |
||||
|
||||
#endif |
||||
|
||||
#ifdef _MSC_VER |
||||
|
||||
int util_vsnprintf(char *, size_t, const char *, va_list); |
||||
int util_snprintf(char *str, size_t size, const char *format, ...); |
||||
|
||||
static INLINE void |
||||
util_vsprintf(char *str, const char *format, va_list ap) |
||||
{ |
||||
util_vsnprintf(str, (size_t)-1, format, ap); |
||||
} |
||||
|
||||
static INLINE void |
||||
util_sprintf(char *str, const char *format, ...) |
||||
{ |
||||
va_list ap; |
||||
va_start(ap, format); |
||||
util_vsnprintf(str, (size_t)-1, format, ap); |
||||
va_end(ap); |
||||
} |
||||
|
||||
static INLINE char * |
||||
util_strchr(const char *s, char c) |
||||
{ |
||||
char *p = util_strchrnul(s, c); |
||||
|
||||
return *p ? p : NULL; |
||||
} |
||||
|
||||
static INLINE char* |
||||
util_strncat(char *dst, const char *src, size_t n) |
||||
{ |
||||
char *p = dst + strlen(dst); |
||||
const char *q = src; |
||||
size_t i; |
||||
|
||||
for (i = 0; i < n && *q != '\0'; ++i) |
||||
*p++ = *q++; |
||||
*p = '\0'; |
||||
|
||||
return dst; |
||||
} |
||||
|
||||
static INLINE int |
||||
util_strcmp(const char *s1, const char *s2) |
||||
{ |
||||
unsigned char u1, u2; |
||||
|
||||
while (1) { |
||||
u1 = (unsigned char) *s1++; |
||||
u2 = (unsigned char) *s2++; |
||||
if (u1 != u2) |
||||
return u1 - u2; |
||||
if (u1 == '\0') |
||||
return 0; |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
static INLINE int |
||||
util_strncmp(const char *s1, const char *s2, size_t n) |
||||
{ |
||||
unsigned char u1, u2; |
||||
|
||||
while (n-- > 0) { |
||||
u1 = (unsigned char) *s1++; |
||||
u2 = (unsigned char) *s2++; |
||||
if (u1 != u2) |
||||
return u1 - u2; |
||||
if (u1 == '\0') |
||||
return 0; |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
static INLINE char * |
||||
util_strstr(const char *haystack, const char *needle) |
||||
{ |
||||
const char *p = haystack; |
||||
size_t len = strlen(needle); |
||||
|
||||
for (; (p = util_strchr(p, *needle)) != 0; p++) { |
||||
if (util_strncmp(p, needle, len) == 0) { |
||||
return (char *)p; |
||||
} |
||||
} |
||||
return NULL; |
||||
} |
||||
|
||||
static INLINE void * |
||||
util_memmove(void *dest, const void *src, size_t n) |
||||
{ |
||||
char *p = (char *)dest; |
||||
const char *q = (const char *)src; |
||||
if (dest < src) { |
||||
while (n--) |
||||
*p++ = *q++; |
||||
} |
||||
else |
||||
{ |
||||
p += n; |
||||
q += n; |
||||
while (n--) |
||||
*--p = *--q; |
||||
} |
||||
return dest; |
||||
} |
||||
|
||||
|
||||
#else |
||||
|
||||
#define util_vsnprintf vsnprintf |
||||
#define util_snprintf snprintf |
||||
#define util_vsprintf vsprintf |
||||
#define util_sprintf sprintf |
||||
#define util_strchr strchr |
||||
#define util_strcmp strcmp |
||||
#define util_strncmp strncmp |
||||
#define util_strncat strncat |
||||
#define util_strstr strstr |
||||
#define util_memmove memmove |
||||
|
||||
#endif |
||||
|
||||
|
||||
/**
|
||||
* Printable string buffer |
||||
*/ |
||||
struct util_strbuf |
||||
{ |
||||
char *str; |
||||
char *ptr; |
||||
size_t left; |
||||
}; |
||||
|
||||
|
||||
static INLINE void |
||||
util_strbuf_init(struct util_strbuf *sbuf, char *str, size_t size)
|
||||
{ |
||||
sbuf->str = str; |
||||
sbuf->str[0] = 0; |
||||
sbuf->ptr = sbuf->str; |
||||
sbuf->left = size; |
||||
} |
||||
|
||||
|
||||
static INLINE void |
||||
util_strbuf_printf(struct util_strbuf *sbuf, const char *format, ...) |
||||
{ |
||||
if(sbuf->left > 1) { |
||||
size_t written; |
||||
va_list ap; |
||||
va_start(ap, format); |
||||
written = util_vsnprintf(sbuf->ptr, sbuf->left, format, ap); |
||||
va_end(ap); |
||||
sbuf->ptr += written; |
||||
sbuf->left -= written; |
||||
} |
||||
} |
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* U_STRING_H_ */ |
@ -0,0 +1,111 @@ |
||||
/**************************************************************************
|
||||
* |
||||
* 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 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_SURFACE_H |
||||
#define U_SURFACE_H |
||||
|
||||
|
||||
#include "pipe/p_compiler.h" |
||||
#include "pipe/p_state.h" |
||||
|
||||
#include "util/u_pack_color.h" |
||||
|
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
|
||||
extern void |
||||
u_surface_default_template(struct pipe_surface *view, |
||||
const struct pipe_resource *texture); |
||||
|
||||
extern void |
||||
util_copy_rect(ubyte * dst, enum pipe_format format, |
||||
unsigned dst_stride, unsigned dst_x, unsigned dst_y, |
||||
unsigned width, unsigned height, const ubyte * src, |
||||
int src_stride, unsigned src_x, unsigned src_y); |
||||
|
||||
extern void |
||||
util_copy_box(ubyte * dst, |
||||
enum pipe_format format, |
||||
unsigned dst_stride, unsigned dst_slice_stride, |
||||
unsigned dst_x, unsigned dst_y, unsigned dst_z, |
||||
unsigned width, unsigned height, unsigned depth, |
||||
const ubyte * src, |
||||
int src_stride, unsigned src_slice_stride, |
||||
unsigned src_x, unsigned src_y, unsigned src_z); |
||||
|
||||
extern void |
||||
util_fill_rect(ubyte * dst, enum pipe_format format, |
||||
unsigned dst_stride, unsigned dst_x, unsigned dst_y, |
||||
unsigned width, unsigned height, union util_color *uc); |
||||
|
||||
extern void |
||||
util_fill_box(ubyte * dst, enum pipe_format format, |
||||
unsigned stride, unsigned layer_stride, |
||||
unsigned x, unsigned y, unsigned z, |
||||
unsigned width, unsigned height, unsigned depth, |
||||
union util_color *uc); |
||||
|
||||
|
||||
extern void |
||||
util_resource_copy_region(struct pipe_context *pipe, |
||||
struct pipe_resource *dst, |
||||
unsigned dst_level, |
||||
unsigned dst_x, unsigned dst_y, unsigned dst_z, |
||||
struct pipe_resource *src, |
||||
unsigned src_level, |
||||
const struct pipe_box *src_box); |
||||
|
||||
extern void |
||||
util_clear_render_target(struct pipe_context *pipe, |
||||
struct pipe_surface *dst, |
||||
const union pipe_color_union *color, |
||||
unsigned dstx, unsigned dsty, |
||||
unsigned width, unsigned height); |
||||
|
||||
extern void |
||||
util_clear_depth_stencil(struct pipe_context *pipe, |
||||
struct pipe_surface *dst, |
||||
unsigned clear_flags, |
||||
double depth, |
||||
unsigned stencil, |
||||
unsigned dstx, unsigned dsty, |
||||
unsigned width, unsigned height); |
||||
|
||||
extern boolean |
||||
util_try_blit_via_copy_region(struct pipe_context *ctx, |
||||
const struct pipe_blit_info *blit); |
||||
|
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
|
||||
#endif /* U_SURFACE_H */ |
@ -0,0 +1,165 @@ |
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 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 P_TILE_H |
||||
#define P_TILE_H |
||||
|
||||
#include "pipe/p_compiler.h" |
||||
#include "pipe/p_format.h" |
||||
#include "pipe/p_state.h" |
||||
|
||||
struct pipe_context; |
||||
struct pipe_transfer; |
||||
|
||||
/**
|
||||
* Clip tile against transfer dims. |
||||
* |
||||
* XXX: this only clips width and height! |
||||
* |
||||
* \return TRUE if tile is totally clipped, FALSE otherwise |
||||
*/ |
||||
static INLINE boolean |
||||
u_clip_tile(uint x, uint y, uint *w, uint *h, const struct pipe_box *box) |
||||
{ |
||||
if ((int) x >= box->width) |
||||
return TRUE; |
||||
if ((int) y >= box->height) |
||||
return TRUE; |
||||
if ((int) (x + *w) > box->width) |
||||
*w = box->width - x; |
||||
if ((int) (y + *h) > box->height) |
||||
*h = box->height - y; |
||||
return FALSE; |
||||
} |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
void |
||||
pipe_get_tile_raw(struct pipe_transfer *pt, |
||||
const void *src, |
||||
uint x, uint y, uint w, uint h, |
||||
void *p, int dst_stride); |
||||
|
||||
void |
||||
pipe_put_tile_raw(struct pipe_transfer *pt, |
||||
void *dst, |
||||
uint x, uint y, uint w, uint h, |
||||
const void *p, int src_stride); |
||||
|
||||
|
||||
void |
||||
pipe_get_tile_rgba(struct pipe_transfer *pt, |
||||
const void *src, |
||||
uint x, uint y, uint w, uint h, |
||||
float *p); |
||||
|
||||
void |
||||
pipe_get_tile_rgba_format(struct pipe_transfer *pt, |
||||
const void *src, |
||||
uint x, uint y, uint w, uint h, |
||||
enum pipe_format format, |
||||
float *p); |
||||
|
||||
void |
||||
pipe_put_tile_rgba(struct pipe_transfer *pt, |
||||
void *dst, |
||||
uint x, uint y, uint w, uint h, |
||||
const float *p); |
||||
|
||||
void |
||||
pipe_put_tile_rgba_format(struct pipe_transfer *pt, |
||||
void *dst, |
||||
uint x, uint y, uint w, uint h, |
||||
enum pipe_format format, |
||||
const float *p); |
||||
|
||||
|
||||
void |
||||
pipe_get_tile_z(struct pipe_transfer *pt, |
||||
const void *src, |
||||
uint x, uint y, uint w, uint h, |
||||
uint *z); |
||||
|
||||
void |
||||
pipe_put_tile_z(struct pipe_transfer *pt, |
||||
void *dst, |
||||
uint x, uint y, uint w, uint h, |
||||
const uint *z); |
||||
|
||||
void |
||||
pipe_tile_raw_to_rgba(enum pipe_format format, |
||||
const void *src, |
||||
uint w, uint h, |
||||
float *dst, unsigned dst_stride); |
||||
|
||||
void |
||||
pipe_tile_raw_to_unsigned(enum pipe_format format, |
||||
const void *src, |
||||
uint w, uint h, |
||||
unsigned *dst, unsigned dst_stride); |
||||
|
||||
void |
||||
pipe_tile_raw_to_signed(enum pipe_format format, |
||||
void *src, |
||||
uint w, uint h, |
||||
int *dst, unsigned dst_stride); |
||||
|
||||
void |
||||
pipe_get_tile_ui_format(struct pipe_transfer *pt, |
||||
const void *src, |
||||
uint x, uint y, uint w, uint h, |
||||
enum pipe_format format, |
||||
unsigned int *p); |
||||
|
||||
void |
||||
pipe_get_tile_i_format(struct pipe_transfer *pt, |
||||
const void *src, |
||||
uint x, uint y, uint w, uint h, |
||||
enum pipe_format format, |
||||
int *p); |
||||
|
||||
void |
||||
pipe_put_tile_ui_format(struct pipe_transfer *pt, |
||||
void *dst, |
||||
uint x, uint y, uint w, uint h, |
||||
enum pipe_format format, |
||||
const unsigned *p); |
||||
|
||||
void |
||||
pipe_put_tile_i_format(struct pipe_transfer *pt, |
||||
void *dst, |
||||
uint x, uint y, uint w, uint h, |
||||
enum pipe_format format, |
||||
const int *p); |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif |
@ -0,0 +1,109 @@ |
||||
|
||||
#ifndef U_TRANSFER_H |
||||
#define U_TRANSFER_H |
||||
|
||||
/* Fallback implementations for inline read/writes which just go back
|
||||
* to the regular transfer behaviour. |
||||
*/ |
||||
#include "pipe/p_state.h" |
||||
|
||||
struct pipe_context; |
||||
struct winsys_handle; |
||||
|
||||
boolean u_default_resource_get_handle(struct pipe_screen *screen, |
||||
struct pipe_resource *resource, |
||||
struct winsys_handle *handle); |
||||
|
||||
void u_default_transfer_inline_write( struct pipe_context *pipe, |
||||
struct pipe_resource *resource, |
||||
unsigned level, |
||||
unsigned usage, |
||||
const struct pipe_box *box, |
||||
const void *data, |
||||
unsigned stride, |
||||
unsigned layer_stride); |
||||
|
||||
void u_default_transfer_flush_region( struct pipe_context *pipe, |
||||
struct pipe_transfer *transfer, |
||||
const struct pipe_box *box); |
||||
|
||||
void u_default_transfer_unmap( struct pipe_context *pipe, |
||||
struct pipe_transfer *transfer ); |
||||
|
||||
|
||||
|
||||
/* Useful helper to allow >1 implementation of resource functionality
|
||||
* to exist in a single driver. This is intended to be transitionary! |
||||
*/ |
||||
struct u_resource_vtbl { |
||||
|
||||
boolean (*resource_get_handle)(struct pipe_screen *, |
||||
struct pipe_resource *tex, |
||||
struct winsys_handle *handle); |
||||
|
||||
void (*resource_destroy)(struct pipe_screen *, |
||||
struct pipe_resource *pt); |
||||
|
||||
void *(*transfer_map)(struct pipe_context *, |
||||
struct pipe_resource *resource, |
||||
unsigned level, |
||||
unsigned usage, |
||||
const struct pipe_box *, |
||||
struct pipe_transfer **); |
||||
|
||||
|
||||
void (*transfer_flush_region)( struct pipe_context *, |
||||
struct pipe_transfer *transfer, |
||||
const struct pipe_box *); |
||||
|
||||
void (*transfer_unmap)( struct pipe_context *, |
||||
struct pipe_transfer *transfer ); |
||||
|
||||
void (*transfer_inline_write)( struct pipe_context *pipe, |
||||
struct pipe_resource *resource, |
||||
unsigned level, |
||||
unsigned usage, |
||||
const struct pipe_box *box, |
||||
const void *data, |
||||
unsigned stride, |
||||
unsigned layer_stride); |
||||
}; |
||||
|
||||
|
||||
struct u_resource { |
||||
struct pipe_resource b; |
||||
const struct u_resource_vtbl *vtbl; |
||||
}; |
||||
|
||||
|
||||
boolean u_resource_get_handle_vtbl(struct pipe_screen *screen, |
||||
struct pipe_resource *resource, |
||||
struct winsys_handle *handle); |
||||
|
||||
void u_resource_destroy_vtbl(struct pipe_screen *screen, |
||||
struct pipe_resource *resource); |
||||
|
||||
void *u_transfer_map_vtbl(struct pipe_context *context, |
||||
struct pipe_resource *resource, |
||||
unsigned level, |
||||
unsigned usage, |
||||
const struct pipe_box *box, |
||||
struct pipe_transfer **transfer); |
||||
|
||||
void u_transfer_flush_region_vtbl( struct pipe_context *pipe, |
||||
struct pipe_transfer *transfer, |
||||
const struct pipe_box *box); |
||||
|
||||
void u_transfer_unmap_vtbl( struct pipe_context *rm_ctx, |
||||
struct pipe_transfer *transfer ); |
||||
|
||||
void u_transfer_inline_write_vtbl( struct pipe_context *rm_ctx, |
||||
struct pipe_resource *resource, |
||||
unsigned level, |
||||
unsigned usage, |
||||
const struct pipe_box *box, |
||||
const void *data, |
||||
unsigned stride, |
||||
unsigned layer_stride); |
||||
|
||||
#endif |
@ -0,0 +1,162 @@ |
||||
#include <epoxy/gl.h> |
||||
#include <stdio.h> |
||||
#include "graw_renderer.h" |
||||
#include "vrend_object.h" |
||||
#include "graw_cursor.h" |
||||
|
||||
static const GLchar *cursor_vs_shader =
|
||||
"attribute vec2 position;\n" |
||||
"attribute vec2 textureCoords;\n" |
||||
"varying vec2 texCoords;\n" |
||||
"void main()\n" |
||||
"{\n" |
||||
" texCoords = textureCoords;\n" |
||||
" gl_Position = vec4(position, 0.0, 1.0);\n" |
||||
"}\n"; |
||||
|
||||
static const GLchar *cursor_fs_shader = |
||||
"uniform sampler2D texSampler;\n" |
||||
"varying vec2 texCoords;\n" |
||||
"void main()\n" |
||||
"{\n" |
||||
" gl_FragColor = texture2D(texSampler, texCoords);\n" |
||||
"}\n"; |
||||
|
||||
void graw_cursor_init(struct graw_cursor_info *cursor) |
||||
{ |
||||
GLuint curs_vs_id, curs_fs_id; |
||||
|
||||
cursor->prog_id = glCreateProgram(); |
||||
curs_vs_id = glCreateShader(GL_VERTEX_SHADER); |
||||
glShaderSource(curs_vs_id, 1, &cursor_vs_shader, NULL); |
||||
glCompileShader(curs_vs_id); |
||||
|
||||
curs_fs_id = glCreateShader(GL_FRAGMENT_SHADER); |
||||
glShaderSource(curs_fs_id, 1, &cursor_fs_shader, NULL); |
||||
glCompileShader(curs_fs_id); |
||||
|
||||
glAttachShader(cursor->prog_id, curs_vs_id); |
||||
glAttachShader(cursor->prog_id, curs_fs_id); |
||||
glLinkProgram(cursor->prog_id); |
||||
|
||||
glGenBuffersARB(1, &cursor->vbo_id); |
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, cursor->vbo_id); |
||||
glBufferData(GL_ARRAY_BUFFER_ARB, 4 * 4 * sizeof(GLfloat), NULL, GL_STREAM_DRAW); |
||||
|
||||
cursor->attrib_locs[0] = glGetAttribLocation(cursor->prog_id, "position"); |
||||
cursor->attrib_locs[1] = glGetAttribLocation(cursor->prog_id, "textureCoords"); |
||||
cursor->samp_loc = glGetUniformLocation(cursor->prog_id, "texSampler"); |
||||
|
||||
glGenVertexArrays(1, &cursor->vaoid); |
||||
|
||||
grend_bind_va(cursor->vaoid); |
||||
|
||||
glVertexAttribPointer(cursor->attrib_locs[0], 2, GL_FLOAT, GL_FALSE, 16, 0); |
||||
glVertexAttribDivisorARB(cursor->attrib_locs[0], 0); |
||||
glVertexAttribPointer(cursor->attrib_locs[1], 2, GL_FLOAT, GL_FALSE, 16, (GLvoid *)8); |
||||
glVertexAttribDivisorARB(cursor->attrib_locs[1], 0); |
||||
|
||||
glEnableVertexAttribArray(cursor->attrib_locs[0]); |
||||
glEnableVertexAttribArray(cursor->attrib_locs[1]); |
||||
|
||||
} |
||||
|
||||
int graw_renderer_remove_cursor(struct graw_cursor_info *cursor, |
||||
struct grend_resource *dst_res) |
||||
{ |
||||
struct pipe_box box; |
||||
box.x = cursor->last_x; |
||||
box.y = cursor->last_y; |
||||
box.z = 0; |
||||
box.width = 64; |
||||
box.height = 64; |
||||
box.depth = 1; |
||||
|
||||
graw_renderer_flush_buffer_res(dst_res, &box); |
||||
return 0; |
||||
} |
||||
|
||||
int graw_renderer_paint_cursor(struct graw_cursor_info *cursor, |
||||
struct grend_resource *dst_res) |
||||
{ |
||||
GLuint fb_id; |
||||
struct grend_resource *cursor_res; |
||||
struct vertex { |
||||
GLfloat x, y, s, t; |
||||
}; |
||||
struct vertex verts[4]; |
||||
GLuint locs[2]; |
||||
GLfloat x0, y0, x1, y1; |
||||
int s_w, s_h; |
||||
if (!cursor->res_handle) |
||||
return 0; |
||||
|
||||
cursor_res = vrend_resource_lookup(cursor->res_handle, 0); |
||||
if (!cursor_res) |
||||
return 0; |
||||
|
||||
s_w = dst_res->base.width0; |
||||
s_h = dst_res->base.height0; |
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); |
||||
glDrawBuffer(GL_BACK); |
||||
|
||||
grend_use_program(cursor->prog_id); |
||||
|
||||
glUniform1i(cursor->samp_loc, 0); |
||||
|
||||
grend_blend_enable(GL_TRUE); |
||||
grend_depth_test_enable(GL_FALSE); |
||||
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); |
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
||||
glBlendEquation(GL_FUNC_ADD); |
||||
|
||||
glActiveTexture(GL_TEXTURE0); |
||||
glBindTexture(cursor_res->target, cursor_res->id); |
||||
|
||||
glTexParameteri(cursor_res->target, GL_TEXTURE_BASE_LEVEL, 0); |
||||
glTexParameteri(cursor_res->target, GL_TEXTURE_MAX_LEVEL, 0); |
||||
glTexParameterf(cursor_res->target, GL_TEXTURE_MIN_LOD, 0); |
||||
glTexParameterf(cursor_res->target, GL_TEXTURE_MAX_LOD, 0); |
||||
glTexParameterf(cursor_res->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
||||
glTexParameterf(cursor_res->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
||||
|
||||
grend_bind_va(cursor->vaoid); |
||||
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, cursor->vbo_id); |
||||
|
||||
cursor->last_x = cursor->x; |
||||
cursor->last_y = cursor->y; |
||||
|
||||
x0 = ((float)cursor->x / (s_w / 2)) - 1.0; |
||||
y0 = ((float)(s_h - cursor->y - cursor_res->base.width0) / (s_h / 2)) - 1.0; |
||||
x1 = (((float)cursor->x + cursor_res->base.height0) / (s_w / 2)) - 1.0; |
||||
y1 = (((float)(s_h - cursor->y)) / (s_h / 2)) - 1.0; |
||||
|
||||
verts[0].x = x0; |
||||
verts[0].y = y0; |
||||
|
||||
verts[1].x = x1; |
||||
verts[1].y = y0; |
||||
|
||||
verts[2].x = x1; |
||||
verts[2].y = y1; |
||||
|
||||
verts[3].x = x0; |
||||
verts[3].y = y1; |
||||
|
||||
verts[0].s = 0.0; |
||||
verts[0].t = 1.0; |
||||
verts[1].s = 1.0; |
||||
verts[1].t = 1.0; |
||||
verts[2].s = 1.0; |
||||
verts[2].t = 0.0; |
||||
verts[3].s = 0.0; |
||||
verts[3].t = 0.0; |
||||
|
||||
glBufferSubData(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); |
||||
|
||||
glDrawArrays(GL_QUADS, 0, 4); |
||||
return 0; |
||||
} |
@ -0,0 +1,24 @@ |
||||
#ifndef GRAW_CURSOR_H |
||||
#define GRAW_CURSOR_H |
||||
|
||||
/* cursor drawing state */ |
||||
|
||||
struct graw_cursor_info { |
||||
GLuint prog_id; |
||||
GLuint vaoid; |
||||
GLuint vbo_id; |
||||
uint32_t res_handle; |
||||
int x, y; |
||||
GLuint attrib_locs[2]; |
||||
GLuint samp_loc; |
||||
|
||||
int last_x, last_y; |
||||
}; |
||||
|
||||
void graw_cursor_init(struct graw_cursor_info *cursor); |
||||
|
||||
int graw_renderer_paint_cursor(struct graw_cursor_info *cursor, |
||||
struct grend_resource *dst_res); |
||||
int graw_renderer_remove_cursor(struct graw_cursor_info *cursor, |
||||
struct grend_resource *dst_res); |
||||
#endif |
@ -0,0 +1,911 @@ |
||||
#include <stdint.h> |
||||
#include <string.h> |
||||
#include <stdio.h> |
||||
#include <epoxy/gl.h> |
||||
|
||||
#include "util/u_memory.h" |
||||
#include "pipe/p_state.h" |
||||
#include "pipe/p_shader_tokens.h" |
||||
#include "graw_decode.h" |
||||
#include "graw_renderer.h" |
||||
#include "vrend_object.h" |
||||
#include "tgsi/tgsi_text.h" |
||||
|
||||
/* decode side */ |
||||
#define DECODE_MAX_TOKENS 8000 |
||||
|
||||
struct grend_decode_ctx { |
||||
struct graw_decoder_state ids, *ds; |
||||
struct grend_context *grctx; |
||||
}; |
||||
|
||||
#define GRAW_MAX_CTX 16 |
||||
static struct grend_decode_ctx *dec_ctx[GRAW_MAX_CTX]; |
||||
|
||||
static int graw_decode_create_shader(struct grend_decode_ctx *ctx, uint32_t type, |
||||
uint32_t handle, |
||||
uint16_t length) |
||||
{ |
||||
struct pipe_shader_state *state = CALLOC_STRUCT(pipe_shader_state); |
||||
struct tgsi_token *tokens; |
||||
int i; |
||||
uint32_t shader_offset; |
||||
unsigned num_tokens; |
||||
if (!state) |
||||
return NULL; |
||||
|
||||
num_tokens = ctx->ds->buf[ctx->ds->buf_offset + 2]; |
||||
|
||||
if (num_tokens == 0) |
||||
num_tokens = 300; |
||||
|
||||
tokens = calloc(num_tokens + 10, sizeof(struct tgsi_token)); |
||||
if (!tokens) { |
||||
free(state); |
||||
return -1; |
||||
} |
||||
|
||||
state->stream_output.num_outputs = ctx->ds->buf[ctx->ds->buf_offset + 3]; |
||||
if (state->stream_output.num_outputs) { |
||||
for (i = 0; i < 4; i++) |
||||
state->stream_output.stride[i] = ctx->ds->buf[ctx->ds->buf_offset + 4 + i]; |
||||
for (i = 0; i < state->stream_output.num_outputs; i++) { |
||||
uint32_t tmp = ctx->ds->buf[ctx->ds->buf_offset + 8 + i]; |
||||
|
||||
state->stream_output.output[i].register_index = tmp & 0xff; |
||||
state->stream_output.output[i].start_component = (tmp >> 8) & 0x3; |
||||
state->stream_output.output[i].num_components = (tmp >> 10) & 0x7; |
||||
state->stream_output.output[i].output_buffer = (tmp >> 13) & 0x7; |
||||
state->stream_output.output[i].dst_offset = (tmp >> 16) & 0xffff;
|
||||
} |
||||
shader_offset = 8 + state->stream_output.num_outputs; |
||||
} else |
||||
shader_offset = 4; |
||||
if (vrend_dump_shaders) |
||||
fprintf(stderr,"shader\n%s\n", &ctx->ds->buf[ctx->ds->buf_offset + shader_offset]); |
||||
if (!tgsi_text_translate(&ctx->ds->buf[ctx->ds->buf_offset + shader_offset], tokens, num_tokens + 10)) { |
||||
fprintf(stderr,"failed to translate\n %s\n",&ctx->ds->buf[ctx->ds->buf_offset + shader_offset]); |
||||
free(tokens); |
||||
free(state); |
||||
return -1; |
||||
} |
||||
|
||||
state->tokens = tokens; |
||||
|
||||
if (type == VIRGL_OBJECT_FS) |
||||
grend_create_fs(ctx->grctx, handle, state); |
||||
else |
||||
grend_create_vs(ctx->grctx, handle, state); |
||||
|
||||
free(tokens); |
||||
free(state); |
||||
return 0; |
||||
} |
||||
|
||||
static int graw_decode_create_stream_output_target(struct grend_decode_ctx *ctx, uint32_t handle) |
||||
{ |
||||
uint32_t res_handle, buffer_size, buffer_offset; |
||||
|
||||
res_handle = ctx->ds->buf[ctx->ds->buf_offset + 2]; |
||||
buffer_offset = ctx->ds->buf[ctx->ds->buf_offset + 3]; |
||||
buffer_size = ctx->ds->buf[ctx->ds->buf_offset + 4]; |
||||
|
||||
grend_create_so_target(ctx->grctx, handle, res_handle, buffer_offset, |
||||
buffer_size); |
||||
} |
||||
|
||||
static void graw_decode_set_framebuffer_state(struct grend_decode_ctx *ctx) |
||||
{ |
||||
uint32_t nr_cbufs = ctx->ds->buf[ctx->ds->buf_offset + 1]; |
||||
uint32_t zsurf_handle = ctx->ds->buf[ctx->ds->buf_offset + 2]; |
||||
uint32_t surf_handle[8]; |
||||
int i; |
||||
|
||||
for (i = 0; i < nr_cbufs; i++) |
||||
surf_handle[i] = ctx->ds->buf[ctx->ds->buf_offset + 3 + i]; |
||||
grend_set_framebuffer_state(ctx->grctx, nr_cbufs, surf_handle, zsurf_handle); |
||||
} |
||||
|
||||
static void graw_decode_clear(struct grend_decode_ctx *ctx) |
||||
{ |
||||
union pipe_color_union color; |
||||
double depth; |
||||
unsigned stencil, buffers; |
||||
int i; |
||||
int index = ctx->ds->buf_offset + 1; |
||||
|
||||
buffers = ctx->ds->buf[index++]; |
||||
for (i = 0; i < 4; i++) |
||||
color.ui[i] = ctx->ds->buf[index++]; |
||||
depth = *(double *)(uint64_t *)(&ctx->ds->buf[index]); |
||||
index += 2; |
||||
stencil = ctx->ds->buf[index++]; |
||||
|
||||
grend_clear(ctx->grctx, buffers, &color, depth, stencil); |
||||
} |
||||
|
||||
static float uif(unsigned int ui) |
||||
{ |
||||
union { float f; unsigned int ui; } myuif; |
||||
myuif.ui = ui; |
||||
return myuif.f; |
||||
} |
||||
|
||||
static void graw_decode_set_viewport_state(struct grend_decode_ctx *ctx) |
||||
{ |
||||
struct pipe_viewport_state vps; |
||||
int i; |
||||
|
||||
for (i = 0; i < 4; i++) |
||||
vps.scale[i] = uif(ctx->ds->buf[ctx->ds->buf_offset + 1 + i]); |
||||
for (i = 0; i < 4; i++) |
||||
vps.translate[i] = uif(ctx->ds->buf[ctx->ds->buf_offset + 5 + i]); |
||||
|
||||
grend_set_viewport_state(ctx->grctx, &vps); |
||||
} |
||||
|
||||
static void graw_decode_set_index_buffer(struct grend_decode_ctx *ctx) |
||||
{ |
||||
int offset = ctx->ds->buf_offset; |
||||
grend_set_index_buffer(ctx->grctx, ctx->ds->buf[offset + 1], |
||||
ctx->ds->buf[offset + 2], |
||||
ctx->ds->buf[offset + 3]); |
||||
} |
||||
|
||||
static void graw_decode_set_constant_buffer(struct grend_decode_ctx *ctx, uint16_t length) |
||||
{ |
||||
int offset = ctx->ds->buf_offset; |
||||
uint32_t shader = ctx->ds->buf[offset + 1]; |
||||
uint32_t index = ctx->ds->buf[offset + 2]; |
||||
int nc = (length - 2); |
||||
grend_set_constants(ctx->grctx, shader, index, nc, &ctx->ds->buf[offset + 3]); |
||||
} |
||||
|
||||
static void graw_decode_set_vertex_buffers(struct grend_decode_ctx *ctx, uint16_t length) |
||||
{ |
||||
int num_vbo; |
||||
int i; |
||||
num_vbo = (length / 3); |
||||
|
||||
for (i = 0; i < num_vbo; i++) { |
||||
int element_offset = ctx->ds->buf_offset + 1 + (i * 3); |
||||
grend_set_single_vbo(ctx->grctx, i, |
||||
ctx->ds->buf[element_offset], |
||||
ctx->ds->buf[element_offset + 1], |
||||
ctx->ds->buf[element_offset + 2]); |
||||
} |
||||
grend_set_num_vbo(ctx->grctx, num_vbo); |
||||
} |
||||
|
||||
static void graw_decode_set_sampler_views(struct grend_decode_ctx *ctx, uint16_t length) |
||||
{ |
||||
int num_samps; |
||||
int i; |
||||
uint32_t shader_type, start_slot; |
||||
num_samps = length - 2; |
||||
shader_type = ctx->ds->buf[ctx->ds->buf_offset + 1]; |
||||
start_slot = ctx->ds->buf[ctx->ds->buf_offset + 2]; |
||||
for (i = 0; i < num_samps; i++) { |
||||
uint32_t handle = ctx->ds->buf[ctx->ds->buf_offset + 3 + i]; |
||||
grend_set_single_sampler_view(ctx->grctx, shader_type, i + start_slot, handle); |
||||
} |
||||
grend_set_num_sampler_views(ctx->grctx, shader_type, start_slot, num_samps); |
||||
} |
||||
|
||||
static void graw_decode_resource_inline_write(struct grend_decode_ctx *ctx, uint16_t length) |
||||
{ |
||||
struct pipe_box box; |
||||
uint32_t res_handle = ctx->ds->buf[ctx->ds->buf_offset + 1]; |
||||
uint32_t level, usage, stride, layer_stride; |
||||
void *data; |
||||
|
||||
level = ctx->ds->buf[ctx->ds->buf_offset + 2]; |
||||
usage = ctx->ds->buf[ctx->ds->buf_offset + 3]; |
||||
stride = ctx->ds->buf[ctx->ds->buf_offset + 4]; |
||||
layer_stride = ctx->ds->buf[ctx->ds->buf_offset + 5]; |
||||
box.x = ctx->ds->buf[ctx->ds->buf_offset + 6]; |
||||
box.y = ctx->ds->buf[ctx->ds->buf_offset + 7]; |
||||
box.z = ctx->ds->buf[ctx->ds->buf_offset + 8]; |
||||
box.width = ctx->ds->buf[ctx->ds->buf_offset + 9]; |
||||
box.height = ctx->ds->buf[ctx->ds->buf_offset + 10]; |
||||
box.depth = ctx->ds->buf[ctx->ds->buf_offset + 11]; |
||||
|
||||
data = &ctx->ds->buf[ctx->ds->buf_offset + 12]; |
||||
grend_transfer_inline_write(ctx->grctx, res_handle, level, |
||||
usage, &box, data, stride, layer_stride); |
||||
|
||||
} |
||||
|
||||
static void graw_decode_draw_vbo(struct grend_decode_ctx *ctx) |
||||
{ |
||||
struct pipe_draw_info info; |
||||
|
||||
memset(&info, 0, sizeof(struct pipe_draw_info)); |
||||
|
||||
info.start = ctx->ds->buf[ctx->ds->buf_offset + 1]; |
||||
info.count = ctx->ds->buf[ctx->ds->buf_offset + 2]; |
||||
info.mode = ctx->ds->buf[ctx->ds->buf_offset + 3]; |
||||
info.indexed = ctx->ds->buf[ctx->ds->buf_offset + 4]; |
||||
info.instance_count = ctx->ds->buf[ctx->ds->buf_offset + 5]; |
||||
info.index_bias = ctx->ds->buf[ctx->ds->buf_offset + 6]; |
||||
info.start_instance = ctx->ds->buf[ctx->ds->buf_offset + 7]; |
||||
info.primitive_restart = ctx->ds->buf[ctx->ds->buf_offset + 8]; |
||||
info.restart_index = ctx->ds->buf[ctx->ds->buf_offset + 9]; |
||||
info.min_index = ctx->ds->buf[ctx->ds->buf_offset + 10]; |
||||
info.max_index = ctx->ds->buf[ctx->ds->buf_offset + 11]; |
||||
grend_draw_vbo(ctx->grctx, &info); |
||||
} |
||||
|
||||
static void graw_decode_create_blend(struct grend_decode_ctx *ctx, uint32_t handle, uint16_t length) |
||||
{ |
||||
struct pipe_blend_state *blend_state = CALLOC_STRUCT(pipe_blend_state); |
||||
uint32_t tmp; |
||||
int i; |
||||
tmp = ctx->ds->buf[ctx->ds->buf_offset + 2]; |
||||
blend_state->independent_blend_enable = (tmp & 1); |
||||
blend_state->logicop_enable = (tmp >> 1) & 0x1; |
||||
blend_state->dither = (tmp >> 2) & 0x1; |
||||
blend_state->alpha_to_coverage = (tmp >> 3) & 0x1; |
||||
blend_state->alpha_to_one = (tmp >> 4) & 0x1; |
||||
|
||||
tmp = ctx->ds->buf[ctx->ds->buf_offset + 3]; |
||||
blend_state->logicop_func = tmp & 0xf; |
||||
|
||||
for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { |
||||
tmp = ctx->ds->buf[ctx->ds->buf_offset + 4 + i]; |
||||
blend_state->rt[i].blend_enable = tmp & 0x1; |
||||
blend_state->rt[i].rgb_func = (tmp >> 1) & 0x7; |
||||
blend_state->rt[i].rgb_src_factor = (tmp >> 4) & 0x1f; |
||||
blend_state->rt[i].rgb_dst_factor = (tmp >> 9) & 0x1f; |
||||
blend_state->rt[i].alpha_func = (tmp >> 14) & 0x7; |
||||
blend_state->rt[i].alpha_src_factor = (tmp >> 17) & 0x1f; |
||||
blend_state->rt[i].alpha_dst_factor = (tmp >> 22) & 0x1f; |
||||
blend_state->rt[i].colormask = (tmp >> 27) & 0xf; |
||||
} |
||||
|
||||
graw_renderer_object_insert(ctx->grctx, blend_state, sizeof(struct pipe_blend_state), handle, |
||||
VIRGL_OBJECT_BLEND); |
||||
} |
||||
|
||||
static void graw_decode_create_dsa(struct grend_decode_ctx *ctx, uint32_t handle, uint16_t length) |
||||
{ |
||||
int i; |
||||
struct pipe_depth_stencil_alpha_state *dsa_state = CALLOC_STRUCT(pipe_depth_stencil_alpha_state); |
||||
uint32_t tmp; |
||||
|
||||
tmp = ctx->ds->buf[ctx->ds->buf_offset + 2]; |
||||
dsa_state->depth.enabled = tmp & 0x1; |
||||
dsa_state->depth.writemask = (tmp >> 1) & 0x1; |
||||
dsa_state->depth.func = (tmp >> 2) & 0x7; |
||||
|
||||
dsa_state->alpha.enabled = (tmp >> 8) & 0x1; |
||||
dsa_state->alpha.func = (tmp >> 9) & 0x7; |
||||
|
||||
for (i = 0; i < 2; i++) { |
||||
tmp = ctx->ds->buf[ctx->ds->buf_offset + 3 + i]; |
||||
dsa_state->stencil[i].enabled = tmp & 0x1; |
||||
dsa_state->stencil[i].func = (tmp >> 1) & 0x7; |
||||
dsa_state->stencil[i].fail_op = (tmp >> 4) & 0x7; |
||||
dsa_state->stencil[i].zpass_op = (tmp >> 7) & 0x7; |
||||
dsa_state->stencil[i].zfail_op = (tmp >> 10) & 0x7; |
||||
dsa_state->stencil[i].valuemask = (tmp >> 13) & 0xff; |
||||
dsa_state->stencil[i].writemask = (tmp >> 21) & 0xff; |
||||
} |
||||
|
||||
tmp = ctx->ds->buf[ctx->ds->buf_offset + 5]; |
||||
dsa_state->alpha.ref_value = uif(tmp); |
||||
|
||||
graw_renderer_object_insert(ctx->grctx, dsa_state, sizeof(struct pipe_depth_stencil_alpha_state), handle, |
||||
VIRGL_OBJECT_DSA); |
||||
} |
||||
|
||||
static void graw_decode_create_rasterizer(struct grend_decode_ctx *ctx, uint32_t handle, uint16_t length) |
||||
{ |
||||
struct pipe_rasterizer_state *rs_state = CALLOC_STRUCT(pipe_rasterizer_state); |
||||
uint32_t tmp; |
||||
|
||||
tmp = ctx->ds->buf[ctx->ds->buf_offset + 2]; |
||||
#define ebit(name, bit) rs_state->name = (tmp >> bit) & 0x1 |
||||
#define emask(name, bit, mask) rs_state->name = (tmp >> bit) & mask |
||||
|
||||
ebit(flatshade, 0); |
||||
ebit(depth_clip, 1); |
||||
ebit(clip_halfz, 2); |
||||
ebit(rasterizer_discard, 3); |
||||
ebit(flatshade_first, 4); |
||||
ebit(light_twoside, 5); |
||||
ebit(sprite_coord_mode, 6); |
||||
ebit(point_quad_rasterization, 7); |
||||
emask(cull_face, 8, 0x3); |
||||
emask(fill_front, 10, 0x3); |
||||
emask(fill_back, 12, 0x3); |
||||
ebit(scissor, 14); |
||||
ebit(front_ccw, 15); |
||||
ebit(clamp_vertex_color, 16); |
||||
ebit(clamp_fragment_color, 17); |
||||
ebit(offset_line, 18); |
||||
ebit(offset_point, 19); |
||||
ebit(offset_tri, 20); |
||||
ebit(poly_smooth, 21); |
||||
ebit(poly_stipple_enable, 22); |
||||
ebit(point_smooth, 23); |
||||
ebit(point_size_per_vertex, 24); |
||||
ebit(multisample, 25); |
||||
ebit(line_smooth, 26); |
||||
ebit(line_stipple_enable, 27); |
||||
ebit(line_last_pixel, 28); |
||||
ebit(half_pixel_center, 29); |
||||
ebit(bottom_edge_rule, 30); |
||||
rs_state->point_size = uif(ctx->ds->buf[ctx->ds->buf_offset + 3]); |
||||
rs_state->sprite_coord_enable = ctx->ds->buf[ctx->ds->buf_offset + 4]; |
||||
tmp = ctx->ds->buf[ctx->ds->buf_offset + 5]; |
||||
emask(line_stipple_pattern, 0, 0xffff); |
||||
emask(line_stipple_factor, 16, 0xff); |
||||
emask(clip_plane_enable, 24, 0xff); |
||||
|
||||
rs_state->line_width = uif(ctx->ds->buf[ctx->ds->buf_offset + 6]); |
||||
rs_state->offset_units = uif(ctx->ds->buf[ctx->ds->buf_offset + 7]); |
||||
rs_state->offset_scale = uif(ctx->ds->buf[ctx->ds->buf_offset + 8]); |
||||
rs_state->offset_clamp = uif(ctx->ds->buf[ctx->ds->buf_offset + 9]); |
||||
|
||||
|
||||
graw_renderer_object_insert(ctx->grctx, rs_state, sizeof(struct pipe_rasterizer_state), handle, |
||||
VIRGL_OBJECT_RASTERIZER); |
||||
} |
||||
|
||||
static void graw_decode_create_surface(struct grend_decode_ctx *ctx, uint32_t handle) |
||||
{ |
||||
uint32_t res_handle, format, val0, val1; |
||||
res_handle = ctx->ds->buf[ctx->ds->buf_offset + 2]; |
||||
format = ctx->ds->buf[ctx->ds->buf_offset + 3]; |
||||
val0 = ctx->ds->buf[ctx->ds->buf_offset + 4]; |
||||
val1 = ctx->ds->buf[ctx->ds->buf_offset + 5]; |
||||
grend_create_surface(ctx->grctx, handle, res_handle, format, val0, val1); |
||||
} |
||||
|
||||
static void graw_decode_create_sampler_view(struct grend_decode_ctx *ctx, uint32_t handle) |
||||
{ |
||||
uint32_t res_handle, format, val0, val1, swizzle_packed; |
||||
|
||||
res_handle = ctx->ds->buf[ctx->ds->buf_offset + 2]; |
||||
format = ctx->ds->buf[ctx->ds->buf_offset + 3]; |
||||
val0 = ctx->ds->buf[ctx->ds->buf_offset + 4]; |
||||
val1 = ctx->ds->buf[ctx->ds->buf_offset + 5]; |
||||
swizzle_packed = ctx->ds->buf[ctx->ds->buf_offset + 6]; |
||||
grend_create_sampler_view(ctx->grctx, handle, res_handle, format, val0, val1,swizzle_packed); |
||||
} |
||||
|
||||
static void graw_decode_create_sampler_state(struct grend_decode_ctx *ctx, uint32_t handle, uint16_t length) |
||||
{ |
||||
struct pipe_sampler_state *state = CALLOC_STRUCT(pipe_sampler_state); |
||||
int i; |
||||
uint32_t tmp; |
||||
|
||||
tmp = ctx->ds->buf[ctx->ds->buf_offset + 2]; |
||||
state->wrap_s = tmp & 0x7; |
||||
state->wrap_t = (tmp >> 3) & 0x7; |
||||
state->wrap_r = (tmp >> 6) & 0x7; |
||||
state->min_img_filter = (tmp >> 9) & 0x3; |
||||
state->min_mip_filter = (tmp >> 11) & 0x3; |
||||
state->mag_img_filter = (tmp >> 13) & 0x3; |
||||
state->compare_mode = (tmp >> 15) & 0x1; |
||||
state->compare_func = (tmp >> 16) & 0x7; |
||||
|
||||
state->lod_bias = uif(ctx->ds->buf[ctx->ds->buf_offset + 3]); |
||||
state->min_lod = uif(ctx->ds->buf[ctx->ds->buf_offset + 4]); |
||||
state->max_lod = uif(ctx->ds->buf[ctx->ds->buf_offset + 5]); |
||||
|
||||
for (i = 0; i < 4; i++) |
||||
state->border_color.ui[i] = ctx->ds->buf[ctx->ds->buf_offset + 6 + i]; |
||||
graw_renderer_object_insert(ctx->grctx, state, sizeof(struct pipe_sampler_state), handle, |
||||
VIRGL_OBJECT_SAMPLER_STATE); |
||||
} |
||||
|
||||
static void graw_decode_create_ve(struct grend_decode_ctx *ctx, uint32_t handle, uint16_t length) |
||||
{ |
||||
struct pipe_vertex_element *ve; |
||||
int num_elements; |
||||
int i; |
||||
|
||||
num_elements = (length - 1) / 4; |
||||
ve = calloc(num_elements, sizeof(struct pipe_vertex_element)); |
||||
if (!ve) |
||||
return; |
||||
|
||||
for (i = 0; i < num_elements; i++) { |
||||
uint32_t element_offset = ctx->ds->buf_offset + 2 + (i * 4); |
||||
ve[i].src_offset = ctx->ds->buf[element_offset]; |
||||
ve[i].instance_divisor = ctx->ds->buf[element_offset + 1]; |
||||
ve[i].vertex_buffer_index = ctx->ds->buf[element_offset + 2]; |
||||
ve[i].src_format = ctx->ds->buf[element_offset + 3]; |
||||
} |
||||
|
||||
grend_create_vertex_elements_state(ctx->grctx, handle, num_elements, |
||||
ve); |
||||
} |
||||
|
||||
static void graw_decode_create_query(struct grend_decode_ctx *ctx, uint32_t handle) |
||||
{ |
||||
uint32_t query_type; |
||||
uint32_t res_handle; |
||||
uint32_t offset; |
||||
query_type = ctx->ds->buf[ctx->ds->buf_offset + 2]; |
||||
offset = ctx->ds->buf[ctx->ds->buf_offset + 3]; |
||||
res_handle = ctx->ds->buf[ctx->ds->buf_offset + 4]; |
||||
|
||||
grend_create_query(ctx->grctx, handle, query_type, res_handle, offset); |
||||
} |
||||
|
||||
static void graw_decode_create_object(struct grend_decode_ctx *ctx) |
||||
{ |
||||
uint32_t header = ctx->ds->buf[ctx->ds->buf_offset]; |
||||
uint32_t handle = ctx->ds->buf[ctx->ds->buf_offset+1]; |
||||
uint16_t length; |
||||
uint8_t obj_type = (header >> 8) & 0xff; |
||||
|
||||
length = header >> 16; |
||||
|
||||
switch (obj_type){ |
||||
case VIRGL_OBJECT_BLEND: |
||||
graw_decode_create_blend(ctx, handle, length); |
||||
break; |
||||
case VIRGL_OBJECT_DSA: |
||||
graw_decode_create_dsa(ctx, handle, length); |
||||
break; |
||||
case VIRGL_OBJECT_RASTERIZER: |
||||
graw_decode_create_rasterizer(ctx, handle, length); |
||||
break; |
||||
case VIRGL_OBJECT_VS: |
||||
case VIRGL_OBJECT_FS: |
||||
graw_decode_create_shader(ctx, obj_type, handle, length); |
||||
break; |
||||
case VIRGL_OBJECT_VERTEX_ELEMENTS: |
||||
graw_decode_create_ve(ctx, handle, length); |
||||
break; |
||||
case VIRGL_OBJECT_SURFACE: |
||||
graw_decode_create_surface(ctx, handle); |
||||
break; |
||||
case VIRGL_OBJECT_SAMPLER_VIEW: |
||||
graw_decode_create_sampler_view(ctx, handle); |
||||
break; |
||||
case VIRGL_OBJECT_SAMPLER_STATE: |
||||
graw_decode_create_sampler_state(ctx, handle, length); |
||||
break; |
||||
case VIRGL_OBJECT_QUERY: |
||||
graw_decode_create_query(ctx, handle); |
||||
break; |
||||
case VIRGL_OBJECT_STREAMOUT_TARGET: |
||||
graw_decode_create_stream_output_target(ctx, handle); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
static void graw_decode_bind_object(struct grend_decode_ctx *ctx) |
||||
{ |
||||
uint32_t header = ctx->ds->buf[ctx->ds->buf_offset]; |
||||
uint32_t handle = ctx->ds->buf[ctx->ds->buf_offset+1]; |
||||
uint16_t length; |
||||
uint8_t obj_type = (header >> 8) & 0xff; |
||||
|
||||
length = header >> 16; |
||||
|
||||
switch (obj_type) { |
||||
case VIRGL_OBJECT_BLEND: |
||||
grend_object_bind_blend(ctx->grctx, handle); |
||||
break; |
||||
case VIRGL_OBJECT_DSA: |
||||
grend_object_bind_dsa(ctx->grctx, handle); |
||||
break; |
||||
case VIRGL_OBJECT_RASTERIZER: |
||||
grend_object_bind_rasterizer(ctx->grctx, handle); |
||||
break; |
||||
case VIRGL_OBJECT_VS: |
||||
grend_bind_vs(ctx->grctx, handle); |
||||
break; |
||||
case VIRGL_OBJECT_FS: |
||||
grend_bind_fs(ctx->grctx, handle); |
||||
break; |
||||
case VIRGL_OBJECT_VERTEX_ELEMENTS: |
||||
grend_bind_vertex_elements_state(ctx->grctx, handle); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
static void graw_decode_destroy_object(struct grend_decode_ctx *ctx) |
||||
{ |
||||
uint32_t handle = ctx->ds->buf[ctx->ds->buf_offset+1]; |
||||
graw_renderer_object_destroy(ctx->grctx, handle); |
||||
} |
||||
|
||||
void graw_reset_decode(void) |
||||
{ |
||||
// free(gdctx->grctx);
|
||||
// gdctx->grctx = NULL;
|
||||
//gdctx->ds = NULL;
|
||||
} |
||||
|
||||
static void graw_decode_set_stencil_ref(struct grend_decode_ctx *ctx) |
||||
{ |
||||
struct pipe_stencil_ref ref; |
||||
uint32_t val = ctx->ds->buf[ctx->ds->buf_offset + 1]; |
||||
ref.ref_value[0] = val & 0xff; |
||||
ref.ref_value[1] = (val >> 8) & 0xff; |
||||
grend_set_stencil_ref(ctx->grctx, &ref); |
||||
} |
||||
|
||||
static void graw_decode_set_blend_color(struct grend_decode_ctx *ctx) |
||||
{ |
||||
struct pipe_blend_color color; |
||||
int i; |
||||
|
||||
for (i = 0; i < 4; i++) |
||||
color.color[i] = uif(ctx->ds->buf[ctx->ds->buf_offset + 1 + i]); |
||||
|
||||
grend_set_blend_color(ctx->grctx, &color); |
||||
} |
||||
|
||||
static void graw_decode_set_scissor_state(struct grend_decode_ctx *ctx) |
||||
{ |
||||
struct pipe_scissor_state ss; |
||||
uint32_t temp; |
||||
|
||||
temp = ctx->ds->buf[ctx->ds->buf_offset + 1]; |
||||
ss.minx = temp & 0xffff; |
||||
ss.miny = (temp >> 16) & 0xffff; |
||||
|
||||
temp = ctx->ds->buf[ctx->ds->buf_offset + 2]; |
||||
ss.maxx = temp & 0xffff; |
||||
ss.maxy = (temp >> 16) & 0xffff; |
||||
|
||||
grend_set_scissor_state(ctx->grctx, &ss); |
||||
} |
||||
|
||||
static void graw_decode_set_polygon_stipple(struct grend_decode_ctx *ctx) |
||||
{ |
||||
struct pipe_poly_stipple ps; |
||||
int i; |
||||
|
||||
for (i = 0; i < 32; i++) |
||||
ps.stipple[i] = ctx->ds->buf[ctx->ds->buf_offset + 1 + i]; |
||||
|
||||
grend_set_polygon_stipple(ctx->grctx, &ps); |
||||
} |
||||
|
||||
static void graw_decode_set_clip_state(struct grend_decode_ctx *ctx) |
||||
{ |
||||
struct pipe_clip_state clip; |
||||
int i, j; |
||||
|
||||
for (i = 0; i < 8; i++) |
||||
for (j = 0; j < 4; j++) |
||||
clip.ucp[i][j] = uif(ctx->ds->buf[ctx->ds->buf_offset + 1 + (i * 4) + j]); |
||||
grend_set_clip_state(ctx->grctx, &clip); |
||||
} |
||||
|
||||
static void graw_decode_set_sample_mask(struct grend_decode_ctx *ctx) |
||||
{ |
||||
unsigned mask; |
||||
|
||||
mask = ctx->ds->buf[ctx->ds->buf_offset + 1]; |
||||
grend_set_sample_mask(ctx->grctx, mask); |
||||
} |
||||
|
||||
static void graw_decode_resource_copy_region(struct grend_decode_ctx *ctx) |
||||
{ |
||||
struct pipe_box box; |
||||
uint32_t dst_handle, src_handle; |
||||
uint32_t dst_level, dstx, dsty, dstz; |
||||
uint32_t src_level; |
||||
|
||||
dst_handle = ctx->ds->buf[ctx->ds->buf_offset + 1]; |
||||
dst_level = ctx->ds->buf[ctx->ds->buf_offset + 2]; |
||||
dstx = ctx->ds->buf[ctx->ds->buf_offset + 3]; |
||||
dsty = ctx->ds->buf[ctx->ds->buf_offset + 4]; |
||||
dstz = ctx->ds->buf[ctx->ds->buf_offset + 5]; |
||||
src_handle = ctx->ds->buf[ctx->ds->buf_offset + 6]; |
||||
src_level = ctx->ds->buf[ctx->ds->buf_offset + 7]; |
||||
box.x = ctx->ds->buf[ctx->ds->buf_offset + 8]; |
||||
box.y = ctx->ds->buf[ctx->ds->buf_offset + 9]; |
||||
box.z = ctx->ds->buf[ctx->ds->buf_offset + 10]; |
||||
box.width = ctx->ds->buf[ctx->ds->buf_offset + 11]; |
||||
box.height = ctx->ds->buf[ctx->ds->buf_offset + 12]; |
||||
box.depth = ctx->ds->buf[ctx->ds->buf_offset + 13]; |
||||
|
||||
graw_renderer_resource_copy_region(ctx->grctx, dst_handle, |
||||
dst_level, dstx, dsty, dstz, |
||||
src_handle, src_level, |
||||
&box); |
||||
} |
||||
|
||||
|
||||
static void graw_decode_blit(struct grend_decode_ctx *ctx) |
||||
{ |
||||
struct pipe_blit_info info; |
||||
uint32_t dst_handle, src_handle, temp; |
||||
|
||||
info.mask = ctx->ds->buf[ctx->ds->buf_offset + 1]; |
||||
info.filter = ctx->ds->buf[ctx->ds->buf_offset + 2]; |
||||
info.scissor_enable = ctx->ds->buf[ctx->ds->buf_offset + 3] & 1; |
||||
temp = ctx->ds->buf[ctx->ds->buf_offset + 4]; |
||||
info.scissor.minx = temp & 0xffff; |
||||
info.scissor.miny = (temp >> 16) & 0xffff; |
||||
temp = ctx->ds->buf[ctx->ds->buf_offset + 5]; |
||||
info.scissor.maxx = temp & 0xffff; |
||||
info.scissor.maxy = (temp >> 16) & 0xffff; |
||||
dst_handle = ctx->ds->buf[ctx->ds->buf_offset + 6]; |
||||
info.dst.level = ctx->ds->buf[ctx->ds->buf_offset + 7]; |
||||
info.dst.format = ctx->ds->buf[ctx->ds->buf_offset + 8]; |
||||
info.dst.box.x = ctx->ds->buf[ctx->ds->buf_offset + 9]; |
||||
info.dst.box.y = ctx->ds->buf[ctx->ds->buf_offset + 10]; |
||||
info.dst.box.z = ctx->ds->buf[ctx->ds->buf_offset + 11]; |
||||
info.dst.box.width = ctx->ds->buf[ctx->ds->buf_offset + 12]; |
||||
info.dst.box.height = ctx->ds->buf[ctx->ds->buf_offset + 13]; |
||||
info.dst.box.depth = ctx->ds->buf[ctx->ds->buf_offset + 14]; |
||||
|
||||
src_handle = ctx->ds->buf[ctx->ds->buf_offset + 15]; |
||||
info.src.level = ctx->ds->buf[ctx->ds->buf_offset + 16]; |
||||
info.src.format = ctx->ds->buf[ctx->ds->buf_offset + 17]; |
||||
info.src.box.x = ctx->ds->buf[ctx->ds->buf_offset + 18]; |
||||
info.src.box.y = ctx->ds->buf[ctx->ds->buf_offset + 19]; |
||||
info.src.box.z = ctx->ds->buf[ctx->ds->buf_offset + 20]; |
||||
info.src.box.width = ctx->ds->buf[ctx->ds->buf_offset + 21]; |
||||
info.src.box.height = ctx->ds->buf[ctx->ds->buf_offset + 22]; |
||||
info.src.box.depth = ctx->ds->buf[ctx->ds->buf_offset + 23];
|
||||
|
||||
graw_renderer_blit(ctx->grctx, dst_handle, src_handle, &info); |
||||
} |
||||
|
||||
static void graw_decode_bind_sampler_states(struct grend_decode_ctx *ctx, int length) |
||||
{ |
||||
uint32_t shader_type = ctx->ds->buf[ctx->ds->buf_offset + 1]; |
||||
uint32_t start_slot = ctx->ds->buf[ctx->ds->buf_offset + 2]; |
||||
uint32_t num_states = length - 1; |
||||
|
||||
grend_bind_sampler_states(ctx->grctx, shader_type, start_slot, num_states, |
||||
&ctx->ds->buf[ctx->ds->buf_offset + 3]); |
||||
} |
||||
|
||||
static void graw_decode_begin_query(struct grend_decode_ctx *ctx) |
||||
{ |
||||
uint32_t handle = ctx->ds->buf[ctx->ds->buf_offset + 1]; |
||||
|
||||
grend_begin_query(ctx->grctx, handle); |
||||
} |
||||
|
||||
static void graw_decode_end_query(struct grend_decode_ctx *ctx) |
||||
{ |
||||
uint32_t handle = ctx->ds->buf[ctx->ds->buf_offset + 1]; |
||||
|
||||
grend_end_query(ctx->grctx, handle); |
||||
} |
||||
|
||||
static void graw_decode_get_query_result(struct grend_decode_ctx *ctx) |
||||
{ |
||||
uint32_t handle = ctx->ds->buf[ctx->ds->buf_offset + 1]; |
||||
uint32_t wait = ctx->ds->buf[ctx->ds->buf_offset + 2]; |
||||
grend_get_query_result(ctx->grctx, handle, wait); |
||||
} |
||||
|
||||
static void graw_decode_set_render_condition(struct grend_decode_ctx *ctx) |
||||
{ |
||||
uint32_t handle = ctx->ds->buf[ctx->ds->buf_offset + 1]; |
||||
boolean condition = ctx->ds->buf[ctx->ds->buf_offset + 2] & 1; |
||||
uint mode = ctx->ds->buf[ctx->ds->buf_offset + 3]; |
||||
grend_render_condition(ctx->grctx, handle, condition, mode); |
||||
} |
||||
|
||||
static void graw_decode_set_streamout_targets(struct grend_decode_ctx *ctx, |
||||
uint16_t length) |
||||
{ |
||||
uint32_t handles[16]; |
||||
uint32_t num_handles = length - 1; |
||||
uint32_t append_bitmask; |
||||
int i; |
||||
|
||||
append_bitmask = ctx->ds->buf[ctx->ds->buf_offset + 1]; |
||||
for (i = 0; i < num_handles; i++) |
||||
handles[i] = ctx->ds->buf[ctx->ds->buf_offset + 2 + i]; |
||||
grend_set_streamout_targets(ctx->grctx, append_bitmask, num_handles, handles); |
||||
} |
||||
|
||||
static void graw_decode_set_query_state(struct grend_decode_ctx *ctx) |
||||
{ |
||||
boolean enabled; |
||||
|
||||
enabled = ctx->ds->buf[ctx->ds->buf_offset + 1] & 0x1; |
||||
grend_set_query_state(ctx->grctx, enabled); |
||||
} |
||||
|
||||
void graw_renderer_context_create_internal(uint32_t handle, uint32_t nlen, |
||||
const char *debug_name) |
||||
{ |
||||
struct grend_decode_ctx *dctx; |
||||
|
||||
if (handle > GRAW_MAX_CTX) |
||||
return; |
||||
|
||||
dctx = malloc(sizeof(struct grend_decode_ctx)); |
||||
if (!dctx) |
||||
return; |
||||
|
||||
dctx->grctx = grend_create_context(handle, nlen, debug_name); |
||||
if (!dctx->grctx) { |
||||
free(dctx); |
||||
return; |
||||
} |
||||
|
||||
dctx->ds = &dctx->ids; |
||||
|
||||
dec_ctx[handle] = dctx; |
||||
} |
||||
|
||||
void graw_renderer_context_create(uint32_t handle, uint32_t nlen, const char *debug_name) |
||||
{ |
||||
if (handle > GRAW_MAX_CTX) |
||||
return; |
||||
/* context 0 is always available with no guarantees */ |
||||
if (handle == 0) |
||||
return; |
||||
|
||||
graw_renderer_context_create_internal(handle, nlen, debug_name); |
||||
} |
||||
|
||||
void graw_renderer_context_destroy(uint32_t handle) |
||||
{ |
||||
struct grend_decode_ctx *ctx; |
||||
bool ret; |
||||
if (handle > GRAW_MAX_CTX) |
||||
return; |
||||
|
||||
ctx = dec_ctx[handle]; |
||||
dec_ctx[handle] = NULL; |
||||
ret = grend_destroy_context(ctx->grctx); |
||||
free(ctx); |
||||
/* switch to ctx 0 */ |
||||
if (ret) |
||||
grend_hw_switch_context(dec_ctx[0]->grctx, TRUE); |
||||
} |
||||
|
||||
struct grend_context *vrend_lookup_renderer_ctx(uint32_t ctx_id) |
||||
{ |
||||
if (ctx_id > GRAW_MAX_CTX) |
||||
return NULL; |
||||
|
||||
if (dec_ctx[ctx_id] == NULL) |
||||
return NULL; |
||||
|
||||
return dec_ctx[ctx_id]->grctx; |
||||
} |
||||
|
||||
static void graw_decode_block(uint32_t ctx_id, uint32_t *block, int ndw) |
||||
{ |
||||
int i = 0; |
||||
struct grend_decode_ctx *gdctx; |
||||
boolean ret; |
||||
if (ctx_id > GRAW_MAX_CTX) |
||||
return; |
||||
|
||||
if (dec_ctx[ctx_id] == NULL) |
||||
return; |
||||
|
||||
gdctx = dec_ctx[ctx_id]; |
||||
|
||||
ret = grend_hw_switch_context(gdctx->grctx, TRUE); |
||||
if (ret == FALSE) |
||||
return; |
||||
|
||||
gdctx->ds->buf = block; |
||||
gdctx->ds->buf_total = ndw; |
||||
gdctx->ds->buf_offset = 0; |
||||
|
||||
while (gdctx->ds->buf_offset < gdctx->ds->buf_total) { |
||||
uint32_t header = gdctx->ds->buf[gdctx->ds->buf_offset]; |
||||
|
||||
// fprintf(stderr,"[%d] cmd is %d (obj %d) len %d\n", gdctx->ds->buf_offset, header & 0xff, (header >> 8 & 0xff), (header >> 16));
|
||||
|
||||
switch (header & 0xff) { |
||||
case VIRGL_CCMD_CREATE_OBJECT: |
||||
graw_decode_create_object(gdctx); |
||||
break; |
||||
case VIRGL_CCMD_BIND_OBJECT: |
||||
graw_decode_bind_object(gdctx); |
||||
break; |
||||
case VIRGL_CCMD_DESTROY_OBJECT: |
||||
graw_decode_destroy_object(gdctx); |
||||
break; |
||||
case VIRGL_CCMD_CLEAR: |
||||
graw_decode_clear(gdctx); |
||||
break; |
||||
case VIRGL_CCMD_DRAW_VBO: |
||||
graw_decode_draw_vbo(gdctx); |
||||
break; |
||||
case VIRGL_CCMD_SET_FRAMEBUFFER_STATE: |
||||
graw_decode_set_framebuffer_state(gdctx); |
||||
break; |
||||
case VIRGL_CCMD_SET_VERTEX_BUFFERS: |
||||
graw_decode_set_vertex_buffers(gdctx, header >> 16); |
||||
break; |
||||
case VIRGL_CCMD_RESOURCE_INLINE_WRITE: |
||||
graw_decode_resource_inline_write(gdctx, header >> 16); |
||||
break; |
||||
case VIRGL_CCMD_SET_VIEWPORT_STATE: |
||||
graw_decode_set_viewport_state(gdctx); |
||||
break; |
||||
case VIRGL_CCMD_SET_SAMPLER_VIEWS: |
||||
graw_decode_set_sampler_views(gdctx, header >> 16); |
||||
break; |
||||
case VIRGL_CCMD_SET_INDEX_BUFFER: |
||||
graw_decode_set_index_buffer(gdctx); |
||||
break; |
||||
case VIRGL_CCMD_SET_CONSTANT_BUFFER: |
||||
graw_decode_set_constant_buffer(gdctx, header >> 16); |
||||
break; |
||||
case VIRGL_CCMD_SET_STENCIL_REF: |
||||
graw_decode_set_stencil_ref(gdctx); |
||||
break; |
||||
case VIRGL_CCMD_SET_BLEND_COLOR: |
||||
graw_decode_set_blend_color(gdctx); |
||||
break; |
||||
case VIRGL_CCMD_SET_SCISSOR_STATE: |
||||
graw_decode_set_scissor_state(gdctx); |
||||
break; |
||||
case VIRGL_CCMD_BLIT: |
||||
graw_decode_blit(gdctx); |
||||
break; |
||||
case VIRGL_CCMD_RESOURCE_COPY_REGION: |
||||
graw_decode_resource_copy_region(gdctx); |
||||
break; |
||||
case VIRGL_CCMD_BIND_SAMPLER_STATES: |
||||
graw_decode_bind_sampler_states(gdctx, header >> 16); |
||||
break; |
||||
case VIRGL_CCMD_BEGIN_QUERY: |
||||
graw_decode_begin_query(gdctx); |
||||
break; |
||||
case VIRGL_CCMD_END_QUERY: |
||||
graw_decode_end_query(gdctx); |
||||
break; |
||||
case VIRGL_CCMD_GET_QUERY_RESULT: |
||||
graw_decode_get_query_result(gdctx); |
||||
break; |
||||
case VIRGL_CCMD_SET_POLYGON_STIPPLE: |
||||
graw_decode_set_polygon_stipple(gdctx); |
||||
break; |
||||
case VIRGL_CCMD_SET_CLIP_STATE: |
||||
graw_decode_set_clip_state(gdctx); |
||||
break; |
||||
case VIRGL_CCMD_SET_SAMPLE_MASK: |
||||
graw_decode_set_sample_mask(gdctx); |
||||
break; |
||||
case VIRGL_CCMD_SET_STREAMOUT_TARGETS: |
||||
graw_decode_set_streamout_targets(gdctx, header >> 16); |
||||
break; |
||||
case VIRGL_CCMD_SET_QUERY_STATE: |
||||
graw_decode_set_query_state(gdctx); |
||||
break; |
||||
case VIRGL_CCMD_SET_RENDER_CONDITION: |
||||
graw_decode_set_render_condition(gdctx); |
||||
break; |
||||
} |
||||
gdctx->ds->buf_offset += (header >> 16) + 1; |
||||
|
||||
} |
||||
|
||||
} |
||||
|
||||
void graw_decode_block_iov(struct virgl_iovec *iov, unsigned int niovs, |
||||
uint32_t ctx_id, uint64_t offset, int ndw) |
||||
{ |
||||
uint32_t *block = (uint32_t *)(iov[0].iov_base + offset); |
||||
void *data; |
||||
if (niovs > 1) { |
||||
data = malloc(ndw * 4); |
||||
graw_iov_to_buf(iov, niovs, offset, data, ndw * 4); |
||||
} |
||||
else |
||||
data = (uint32_t *)(iov[0].iov_base + offset); |
||||
graw_decode_block(ctx_id, data, ndw); |
||||
if (niovs > 1) |
||||
free(data); |
||||
|
||||
} |
||||
|
@ -0,0 +1,13 @@ |
||||
#ifndef GRAW_DECODE_H |
||||
#define GRAW_DECODE_H |
||||
|
||||
struct graw_decoder_state { |
||||
uint32_t *buf; |
||||
uint32_t buf_total; |
||||
uint32_t buf_offset; |
||||
}; |
||||
|
||||
|
||||
void graw_decode_transfer(uint32_t *data, uint32_t ndw); |
||||
void graw_decode_get_transfer(uint32_t *data, uint32_t ndw); |
||||
#endif |
@ -0,0 +1,307 @@ |
||||
#include <epoxy/gl.h> |
||||
|
||||
#include "graw_renderer.h" |
||||
#include "util/u_memory.h" |
||||
#include "util/u_format.h" |
||||
/* fill the format table */ |
||||
static struct grend_format_table base_rgba_formats[] =
|
||||
{ |
||||
{ VIRGL_FORMAT_B8G8R8X8_UNORM, GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, 0 }, |
||||
{ VIRGL_FORMAT_B8G8R8A8_UNORM, GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, 0 }, |
||||
|
||||
{ VIRGL_FORMAT_R8G8B8X8_UNORM, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, 0 }, |
||||
{ VIRGL_FORMAT_R8G8B8A8_UNORM, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, 0 }, |
||||
|
||||
{ VIRGL_FORMAT_A8R8G8B8_UNORM, GL_RGBA8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0 }, |
||||
{ VIRGL_FORMAT_X8R8G8B8_UNORM, GL_RGBA8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0 }, |
||||
|
||||
{ VIRGL_FORMAT_A8B8G8R8_UNORM, GL_RGBA8, GL_ABGR_EXT, GL_UNSIGNED_BYTE, 0}, |
||||
|
||||
{ VIRGL_FORMAT_B4G4R4A4_UNORM, GL_RGBA4, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV }, |
||||
{ VIRGL_FORMAT_B4G4R4X4_UNORM, GL_RGBA4, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV }, |
||||
{ VIRGL_FORMAT_B5G5R5X1_UNORM, GL_RGB5_A1, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV }, |
||||
{ VIRGL_FORMAT_B5G5R5A1_UNORM, GL_RGB5_A1, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV }, |
||||
|
||||
{ VIRGL_FORMAT_B5G6R5_UNORM, GL_RGB4, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 }, |
||||
{ VIRGL_FORMAT_B2G3R3_UNORM, GL_R3_G3_B2, GL_RGB, GL_UNSIGNED_BYTE_3_3_2 }, |
||||
|
||||
{ VIRGL_FORMAT_R16G16B16X16_UNORM, GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT }, |
||||
|
||||
{ VIRGL_FORMAT_R16G16B16A16_UNORM, GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT }, |
||||
}; |
||||
|
||||
static struct grend_format_table base_depth_formats[] =
|
||||
{ |
||||
{ VIRGL_FORMAT_Z16_UNORM, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, 0 }, |
||||
{ VIRGL_FORMAT_Z32_UNORM, GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0 }, |
||||
{ VIRGL_FORMAT_S8_UINT_Z24_UNORM, GL_DEPTH24_STENCIL8_EXT, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 0 }, |
||||
{ VIRGL_FORMAT_Z24X8_UNORM, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT }, |
||||
{ VIRGL_FORMAT_Z32_FLOAT, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT },
|
||||
/* this is probably a separate format */ |
||||
{ VIRGL_FORMAT_Z32_FLOAT_S8X24_UINT, GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV}, |
||||
}; |
||||
|
||||
static struct grend_format_table base_la_formats[] = { |
||||
{ VIRGL_FORMAT_A8_UNORM, GL_ALPHA8, GL_ALPHA, GL_UNSIGNED_BYTE }, |
||||
{ VIRGL_FORMAT_L8_UNORM, GL_LUMINANCE8, GL_LUMINANCE, GL_UNSIGNED_BYTE }, |
||||
{ VIRGL_FORMAT_L8A8_UNORM, GL_LUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE }, |
||||
{ VIRGL_FORMAT_A16_UNORM, GL_ALPHA16, GL_ALPHA, GL_UNSIGNED_SHORT }, |
||||
{ VIRGL_FORMAT_L16_UNORM, GL_LUMINANCE16, GL_LUMINANCE, GL_UNSIGNED_SHORT }, |
||||
{ VIRGL_FORMAT_L16A16_UNORM, GL_LUMINANCE16_ALPHA16, GL_LUMINANCE_ALPHA, GL_UNSIGNED_SHORT }, |
||||
}; |
||||
|
||||
static struct grend_format_table rg_base_formats[] = { |
||||
{ VIRGL_FORMAT_R8_UNORM, GL_RED, GL_RED, GL_UNSIGNED_BYTE }, |
||||
{ VIRGL_FORMAT_R8G8_UNORM, GL_RG, GL_RG, GL_UNSIGNED_BYTE }, |
||||
{ VIRGL_FORMAT_R16_UNORM, GL_R16, GL_RED, GL_UNSIGNED_SHORT }, |
||||
{ VIRGL_FORMAT_R16G16_UNORM, GL_RG16, GL_RG, GL_UNSIGNED_SHORT }, |
||||
}; |
||||
|
||||
static struct grend_format_table integer_base_formats[] = { |
||||
{ VIRGL_FORMAT_R8G8B8A8_UINT, GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE }, |
||||
{ VIRGL_FORMAT_R8G8B8A8_SINT, GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE }, |
||||
|
||||
{ VIRGL_FORMAT_R16G16B16A16_UINT, GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT }, |
||||
{ VIRGL_FORMAT_R16G16B16A16_SINT, GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT }, |
||||
|
||||
{ VIRGL_FORMAT_R32G32B32A32_UINT, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT }, |
||||
{ VIRGL_FORMAT_R32G32B32A32_SINT, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT }, |
||||
}; |
||||
|
||||
static struct grend_format_table integer_3comp_formats[] = { |
||||
{ VIRGL_FORMAT_R8G8B8_UINT, GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE }, |
||||
{ VIRGL_FORMAT_R8G8B8_SINT, GL_RGB8I, GL_RGB_INTEGER, GL_BYTE }, |
||||
{ VIRGL_FORMAT_R16G16B16_UINT, GL_RGB16UI, GL_RGB_INTEGER, GL_UNSIGNED_SHORT }, |
||||
{ VIRGL_FORMAT_R16G16B16_SINT, GL_RGB16I, GL_RGB_INTEGER, GL_SHORT }, |
||||
{ VIRGL_FORMAT_R32G32B32_UINT, GL_RGB32UI, GL_RGB_INTEGER, GL_UNSIGNED_INT }, |
||||
{ VIRGL_FORMAT_R32G32B32_SINT, GL_RGB32I, GL_RGB_INTEGER, GL_INT }, |
||||
}; |
||||
|
||||
static struct grend_format_table float_base_formats[] = { |
||||
{ VIRGL_FORMAT_R16G16B16A16_FLOAT, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT }, |
||||
{ VIRGL_FORMAT_R32G32B32A32_FLOAT, GL_RGBA32F, GL_RGBA, GL_FLOAT }, |
||||
}; |
||||
|
||||
static struct grend_format_table float_la_formats[] = { |
||||
{ VIRGL_FORMAT_A16_FLOAT, GL_ALPHA16F_ARB, GL_ALPHA, GL_HALF_FLOAT }, |
||||
{ VIRGL_FORMAT_L16_FLOAT, GL_LUMINANCE16F_ARB, GL_LUMINANCE, GL_HALF_FLOAT }, |
||||
{ VIRGL_FORMAT_L16A16_FLOAT, GL_LUMINANCE_ALPHA16F_ARB, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT }, |
||||
|
||||
{ VIRGL_FORMAT_A32_FLOAT, GL_ALPHA32F_ARB, GL_ALPHA, GL_FLOAT }, |
||||
{ VIRGL_FORMAT_L32_FLOAT, GL_LUMINANCE32F_ARB, GL_LUMINANCE, GL_FLOAT }, |
||||
{ VIRGL_FORMAT_L32A32_FLOAT, GL_LUMINANCE_ALPHA32F_ARB, GL_LUMINANCE_ALPHA, GL_FLOAT }, |
||||
}; |
||||
|
||||
static struct grend_format_table integer_rg_formats[] = { |
||||
{ VIRGL_FORMAT_R8_UINT, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE }, |
||||
{ VIRGL_FORMAT_R8G8_UINT, GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE }, |
||||
{ VIRGL_FORMAT_R8_SINT, GL_R8I, GL_RED_INTEGER, GL_BYTE }, |
||||
{ VIRGL_FORMAT_R8G8_SINT, GL_RG8I, GL_RG_INTEGER, GL_BYTE }, |
||||
|
||||
{ VIRGL_FORMAT_R16_UINT, GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT }, |
||||
{ VIRGL_FORMAT_R16G16_UINT, GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT }, |
||||
{ VIRGL_FORMAT_R16_SINT, GL_R16I, GL_RED_INTEGER, GL_SHORT }, |
||||
{ VIRGL_FORMAT_R16G16_SINT, GL_RG16I, GL_RG_INTEGER, GL_SHORT }, |
||||
|
||||
{ VIRGL_FORMAT_R32_UINT, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT }, |
||||
{ VIRGL_FORMAT_R32G32_UINT, GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT }, |
||||
{ VIRGL_FORMAT_R32_SINT, GL_R32I, GL_RED_INTEGER, GL_INT }, |
||||
{ VIRGL_FORMAT_R32G32_SINT, GL_RG32I, GL_RG_INTEGER, GL_INT }, |
||||
}; |
||||
|
||||
static struct grend_format_table float_rg_formats[] = { |
||||
{ VIRGL_FORMAT_R16_FLOAT, GL_R16F, GL_RED, GL_HALF_FLOAT }, |
||||
{ VIRGL_FORMAT_R16G16_FLOAT, GL_RG16F, GL_RG, GL_HALF_FLOAT }, |
||||
{ VIRGL_FORMAT_R32_FLOAT, GL_R32F, GL_RED, GL_FLOAT }, |
||||
{ VIRGL_FORMAT_R32G32_FLOAT, GL_RG32F, GL_RG, GL_FLOAT }, |
||||
}; |
||||
|
||||
static struct grend_format_table float_3comp_formats[] = { |
||||
{ VIRGL_FORMAT_R16G16B16_FLOAT, GL_RGB16F, GL_RGB, GL_HALF_FLOAT }, |
||||
{ VIRGL_FORMAT_R32G32B32_FLOAT, GL_RGB32F, GL_RGB, GL_FLOAT }, |
||||
}; |
||||
|
||||
|
||||
static struct grend_format_table integer_la_formats[] = { |
||||
{ VIRGL_FORMAT_A8_UINT, GL_ALPHA8UI_EXT, GL_ALPHA_INTEGER, GL_UNSIGNED_BYTE}, |
||||
{ VIRGL_FORMAT_L8_UINT, GL_LUMINANCE8UI_EXT, GL_LUMINANCE_INTEGER_EXT, GL_UNSIGNED_BYTE}, |
||||
{ VIRGL_FORMAT_L8A8_UINT, GL_LUMINANCE_ALPHA8UI_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_UNSIGNED_BYTE}, |
||||
{ VIRGL_FORMAT_A8_SINT, GL_ALPHA8I_EXT, GL_ALPHA_INTEGER, GL_BYTE}, |
||||
{ VIRGL_FORMAT_L8_SINT, GL_LUMINANCE8I_EXT, GL_LUMINANCE_INTEGER_EXT, GL_BYTE}, |
||||
{ VIRGL_FORMAT_L8A8_SINT, GL_LUMINANCE_ALPHA8I_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_BYTE}, |
||||
|
||||
{ VIRGL_FORMAT_A16_UINT, GL_ALPHA16UI_EXT, GL_ALPHA_INTEGER, GL_UNSIGNED_SHORT}, |
||||
{ VIRGL_FORMAT_L16_UINT, GL_LUMINANCE16UI_EXT, GL_LUMINANCE_INTEGER_EXT, GL_UNSIGNED_SHORT}, |
||||
{ VIRGL_FORMAT_L16A16_UINT, GL_LUMINANCE_ALPHA16UI_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_UNSIGNED_SHORT}, |
||||
|
||||
{ VIRGL_FORMAT_A16_SINT, GL_ALPHA16I_EXT, GL_ALPHA_INTEGER, GL_SHORT}, |
||||
{ VIRGL_FORMAT_L16_SINT, GL_LUMINANCE16I_EXT, GL_LUMINANCE_INTEGER_EXT, GL_SHORT}, |
||||
{ VIRGL_FORMAT_L16A16_SINT, GL_LUMINANCE_ALPHA16I_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_SHORT}, |
||||
|
||||
{ VIRGL_FORMAT_A32_UINT, GL_ALPHA32UI_EXT, GL_ALPHA_INTEGER, GL_UNSIGNED_INT}, |
||||
{ VIRGL_FORMAT_L32_UINT, GL_LUMINANCE32UI_EXT, GL_LUMINANCE_INTEGER_EXT, GL_UNSIGNED_INT}, |
||||
{ VIRGL_FORMAT_L32A32_UINT, GL_LUMINANCE_ALPHA32UI_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_UNSIGNED_INT}, |
||||
|
||||
{ VIRGL_FORMAT_A32_SINT, GL_ALPHA32I_EXT, GL_ALPHA_INTEGER, GL_INT}, |
||||
{ VIRGL_FORMAT_L32_SINT, GL_LUMINANCE32I_EXT, GL_LUMINANCE_INTEGER_EXT, GL_INT}, |
||||
{ VIRGL_FORMAT_L32A32_SINT, GL_LUMINANCE_ALPHA32I_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_INT}, |
||||
|
||||
|
||||
}; |
||||
|
||||
static struct grend_format_table snorm_formats[] = { |
||||
{ VIRGL_FORMAT_R8_SNORM, GL_R8_SNORM, GL_RED, GL_BYTE }, |
||||
{ VIRGL_FORMAT_R8G8_SNORM, GL_RG8_SNORM, GL_RG, GL_BYTE }, |
||||
|
||||
{ VIRGL_FORMAT_R8G8B8A8_SNORM, GL_RGBA8_SNORM, GL_RGBA, GL_BYTE }, |
||||
{ VIRGL_FORMAT_R8G8B8X8_SNORM, GL_RGBA8_SNORM, GL_RGB, GL_BYTE }, |
||||
|
||||
{ VIRGL_FORMAT_R16_SNORM, GL_R16_SNORM, GL_RED, GL_SHORT }, |
||||
{ VIRGL_FORMAT_R16G16_SNORM, GL_RG16_SNORM, GL_RG, GL_SHORT }, |
||||
{ VIRGL_FORMAT_R16G16B16A16_SNORM, GL_RGBA16_SNORM, GL_RGBA, GL_SHORT }, |
||||
|
||||
{ VIRGL_FORMAT_R16G16B16X16_SNORM, GL_RGBA16_SNORM, GL_RGBA, GL_SHORT }, |
||||
}; |
||||
|
||||
static struct grend_format_table snorm_la_formats[] = { |
||||
{ VIRGL_FORMAT_A8_SNORM, GL_ALPHA8_SNORM, GL_ALPHA, GL_BYTE }, |
||||
{ VIRGL_FORMAT_L8_SNORM, GL_LUMINANCE8_SNORM, GL_LUMINANCE, GL_BYTE }, |
||||
{ VIRGL_FORMAT_L8A8_SNORM, GL_LUMINANCE8_ALPHA8_SNORM, GL_LUMINANCE_ALPHA, GL_BYTE }, |
||||
{ VIRGL_FORMAT_A16_SNORM, GL_ALPHA16_SNORM, GL_ALPHA, GL_SHORT }, |
||||
{ VIRGL_FORMAT_L16_SNORM, GL_LUMINANCE16_SNORM, GL_LUMINANCE, GL_SHORT }, |
||||
{ VIRGL_FORMAT_L16A16_SNORM, GL_LUMINANCE16_ALPHA16_SNORM, GL_LUMINANCE_ALPHA, GL_SHORT }, |
||||
}; |
||||
|
||||
static struct grend_format_table dxtn_formats[] = { |
||||
{ VIRGL_FORMAT_DXT1_RGB, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, GL_UNSIGNED_BYTE }, |
||||
{ VIRGL_FORMAT_DXT1_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_RGBA, GL_UNSIGNED_BYTE }, |
||||
{ VIRGL_FORMAT_DXT3_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_BYTE }, |
||||
{ VIRGL_FORMAT_DXT5_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_BYTE }, |
||||
}; |
||||
|
||||
static struct grend_format_table dxtn_srgb_formats[] = { |
||||
{ VIRGL_FORMAT_DXT1_SRGB, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, GL_RGB, GL_UNSIGNED_BYTE }, |
||||
{ VIRGL_FORMAT_DXT1_SRGBA, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, GL_RGBA, GL_UNSIGNED_BYTE }, |
||||
{ VIRGL_FORMAT_DXT3_SRGBA, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_BYTE }, |
||||
{ VIRGL_FORMAT_DXT5_SRGBA, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_BYTE }, |
||||
}; |
||||
|
||||
static struct grend_format_table rgtc_formats[] = { |
||||
{ VIRGL_FORMAT_RGTC1_UNORM, GL_COMPRESSED_RED_RGTC1, GL_RED, GL_UNSIGNED_BYTE }, |
||||
{ VIRGL_FORMAT_RGTC1_SNORM, GL_COMPRESSED_SIGNED_RED_RGTC1, GL_RED, GL_BYTE }, |
||||
|
||||
{ VIRGL_FORMAT_RGTC2_UNORM, GL_COMPRESSED_RG_RGTC2, GL_RG, GL_UNSIGNED_BYTE }, |
||||
{ VIRGL_FORMAT_RGTC2_SNORM, GL_COMPRESSED_SIGNED_RG_RGTC2, GL_RG, GL_BYTE }, |
||||
}; |
||||
|
||||
static struct grend_format_table srgb_formats[] = { |
||||
|
||||
{ VIRGL_FORMAT_B8G8R8X8_SRGB, GL_SRGB8_ALPHA8, GL_BGRA, GL_UNSIGNED_BYTE }, |
||||
{ VIRGL_FORMAT_B8G8R8A8_SRGB, GL_SRGB8_ALPHA8, GL_BGRA, GL_UNSIGNED_BYTE }, |
||||
{ VIRGL_FORMAT_R8G8B8X8_SRGB, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE }, |
||||
|
||||
{ VIRGL_FORMAT_L8_SRGB, GL_SLUMINANCE8_EXT, GL_LUMINANCE, GL_UNSIGNED_BYTE }, |
||||
{ VIRGL_FORMAT_L8A8_SRGB, GL_SLUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE }, |
||||
}; |
||||
|
||||
static struct grend_format_table bit10_formats[] = { |
||||
{ VIRGL_FORMAT_B10G10R10X2_UNORM, GL_RGB10_A2, GL_BGRA, GL_UNSIGNED_INT_2_10_10_10_REV }, |
||||
{ VIRGL_FORMAT_B10G10R10A2_UNORM, GL_RGB10_A2, GL_BGRA, GL_UNSIGNED_INT_2_10_10_10_REV }, |
||||
{ VIRGL_FORMAT_B10G10R10A2_UINT, GL_RGB10_A2UI, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV }, |
||||
}; |
||||
|
||||
static struct grend_format_table packed_float_formats[] = { |
||||
{ VIRGL_FORMAT_R11G11B10_FLOAT, GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV}, |
||||
}; |
||||
|
||||
static struct grend_format_table exponent_float_formats[] = { |
||||
{ VIRGL_FORMAT_R9G9B9E5_FLOAT, GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV}, |
||||
}; |
||||
|
||||
static void vrend_add_formats(struct grend_format_table *table, int num_entries) |
||||
{ |
||||
int i; |
||||
uint32_t binding = 0; |
||||
GLuint tex_id, fb_id; |
||||
for (i = 0; i < num_entries; i++) { |
||||
GLenum status; |
||||
boolean is_depth = FALSE; |
||||
/**/ |
||||
glGenTextures(1, &tex_id); |
||||
glGenFramebuffers(1, &fb_id); |
||||
|
||||
glBindTexture(GL_TEXTURE_2D, tex_id); |
||||
glBindFramebuffer(GL_FRAMEBUFFER, fb_id); |
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, table[i].internalformat, 32, 32, 0, table[i].glformat, table[i].gltype, NULL); |
||||
|
||||
if (util_format_is_depth_or_stencil(table[i].format)) { |
||||
GLenum attachment; |
||||
|
||||
if (table[i].format == PIPE_FORMAT_Z24X8_UNORM || table[i].format == PIPE_FORMAT_Z32_UNORM || table[i].format == PIPE_FORMAT_Z16_UNORM || table[i].format == PIPE_FORMAT_Z32_FLOAT) |
||||
attachment = GL_DEPTH_ATTACHMENT; |
||||
else |
||||
attachment = GL_DEPTH_STENCIL_ATTACHMENT; |
||||
glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, attachment, GL_TEXTURE_2D, tex_id, 0); |
||||
|
||||
is_depth = TRUE; |
||||
glDrawBuffer(GL_NONE); |
||||
} else { |
||||
glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, tex_id, 0); |
||||
|
||||
glDrawBuffer(GL_COLOR_ATTACHMENT0); |
||||
} |
||||
|
||||
status = glCheckFramebufferStatus(GL_FRAMEBUFFER); |
||||
binding = 0; |
||||
if (status == GL_FRAMEBUFFER_COMPLETE) |
||||
binding |= (is_depth ? VREND_BIND_DEPTHSTENCIL : VREND_BIND_RENDER); |
||||
|
||||
glDeleteTextures(1, &tex_id); |
||||
glDeleteFramebuffers(1, &fb_id); |
||||
grend_insert_format(&table[i], binding); |
||||
} |
||||
} |
||||
|
||||
#define add_formats(x) vrend_add_formats((x), Elements((x))) |
||||
|
||||
void vrend_build_format_list(void) |
||||
{ |
||||
add_formats(base_rgba_formats); |
||||
add_formats(base_depth_formats); |
||||
add_formats(base_la_formats); |
||||
|
||||
/* float support */ |
||||
add_formats(float_base_formats); |
||||
add_formats(float_la_formats); |
||||
add_formats(float_3comp_formats); |
||||
|
||||
/* texture integer support ? */ |
||||
add_formats(integer_base_formats); |
||||
add_formats(integer_la_formats); |
||||
add_formats(integer_3comp_formats); |
||||
|
||||
/* RG support? */ |
||||
add_formats(rg_base_formats); |
||||
/* integer + rg */ |
||||
add_formats(integer_rg_formats); |
||||
/* float + rg */ |
||||
add_formats(float_rg_formats); |
||||
|
||||
/* snorm */ |
||||
add_formats(snorm_formats); |
||||
add_formats(snorm_la_formats); |
||||
|
||||
/* compressed */ |
||||
add_formats(rgtc_formats); |
||||
add_formats(dxtn_formats); |
||||
add_formats(dxtn_srgb_formats); |
||||
|
||||
add_formats(srgb_formats); |
||||
|
||||
add_formats(bit10_formats); |
||||
|
||||
add_formats(packed_float_formats); |
||||
add_formats(exponent_float_formats); |
||||
|
||||
} |
@ -0,0 +1,22 @@ |
||||
|
||||
#ifndef GRAW_IOV_H |
||||
#define GRAW_IOV_H |
||||
|
||||
/* stolen from qemu for now until later integration */ |
||||
struct virgl_iovec { |
||||
void *iov_base; |
||||
size_t iov_len; |
||||
}; |
||||
|
||||
typedef void (*IOCallback)(void *cookie, unsigned int doff, void *src, int len); |
||||
|
||||
size_t graw_iov_size(const struct virgl_iovec *iov, const unsigned int iov_cnt); |
||||
size_t graw_iov_from_buf(const struct virgl_iovec *iov, unsigned int iov_cnt, |
||||
size_t offset, const void *buf, size_t bytes); |
||||
size_t graw_iov_to_buf(const struct virgl_iovec *iov, const unsigned int iov_cnt, |
||||
size_t offset, void *buf, size_t bytes); |
||||
|
||||
size_t graw_iov_to_buf_cb(const struct virgl_iovec *iov, const unsigned int iov_cnt, |
||||
size_t offset, size_t bytes, IOCallback iocb, void *cookie); |
||||
|
||||
#endif |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,322 @@ |
||||
#ifndef GRAW_RENDERER_H |
||||
#define GRAW_RENDERER_H |
||||
|
||||
#include "pipe/p_state.h" |
||||
#include "util/u_inlines.h" |
||||
#include "virgl_protocol.h" |
||||
#include "graw_iov.h" |
||||
#include "virgl_hw.h" |
||||
|
||||
typedef void *virgl_gl_context; |
||||
typedef void *virgl_gl_drawable; |
||||
|
||||
extern int vrend_dump_shaders; |
||||
struct grend_context; |
||||
|
||||
struct grend_resource { |
||||
struct pipe_resource base; |
||||
GLuint id; |
||||
GLenum target; |
||||
/* fb id if we need to readback this resource */ |
||||
GLuint readback_fb_id; |
||||
GLuint readback_fb_level; |
||||
GLuint readback_fb_z; |
||||
int is_front; |
||||
GLboolean renderer_flipped; |
||||
void *ptr; |
||||
GLuint handle; |
||||
|
||||
struct virgl_iovec *iov; |
||||
uint32_t num_iovs; |
||||
boolean y_0_top; |
||||
|
||||
boolean scannedout; |
||||
}; |
||||
|
||||
/* assume every format is sampler friendly */ |
||||
#define VREND_BIND_RENDER (1 << 0) |
||||
#define VREND_BIND_DEPTHSTENCIL (1 << 1) |
||||
|
||||
struct grend_format_table { |
||||
enum virgl_formats format; |
||||
GLenum internalformat; |
||||
GLenum glformat; |
||||
GLenum gltype; |
||||
uint32_t bindings; |
||||
}; |
||||
|
||||
struct grend_if_cbs { |
||||
void (*write_fence)(unsigned fence_id); |
||||
/* inform the control layer about a new scanout */ |
||||
void (*scanout_rect_info)(int scanout_id, GLuint tex_id, int x, int y, |
||||
uint32_t width, uint32_t height); |
||||
void (*scanout_resource_info)(int scanout_id, GLuint tex_id, uint32_t flags, |
||||
uint32_t stride, |
||||
uint32_t width, uint32_t height, uint32_t format); |
||||
|
||||
virgl_gl_context (*create_gl_context)(int scanout); |
||||
void (*destroy_gl_context)(virgl_gl_context ctx); |
||||
int (*make_current)(int scanout, virgl_gl_context ctx); |
||||
|
||||
void (*flush_scanout)(int scanout, int x, int y, uint32_t width, uint32_t height); |
||||
void (*inval_backing)(struct virgl_iovec *iov, uint32_t iov_cnt); |
||||
}; |
||||
void graw_renderer_init(struct grend_if_cbs *cbs); |
||||
|
||||
void grend_insert_format(struct grend_format_table *entry, uint32_t bindings); |
||||
void grend_create_vs(struct grend_context *ctx, |
||||
uint32_t handle, |
||||
const struct pipe_shader_state *vs); |
||||
|
||||
void grend_create_fs(struct grend_context *ctx, |
||||
uint32_t handle, |
||||
const struct pipe_shader_state *vs); |
||||
|
||||
void grend_bind_vs(struct grend_context *ctx, |
||||
uint32_t handle); |
||||
|
||||
void grend_bind_fs(struct grend_context *ctx, |
||||
uint32_t handle); |
||||
|
||||
void grend_bind_vs_so(struct grend_context *ctx, |
||||
uint32_t handle); |
||||
void grend_clear(struct grend_context *ctx, |
||||
unsigned buffers, |
||||
const union pipe_color_union *color, |
||||
double depth, unsigned stencil); |
||||
|
||||
void grend_draw_vbo(struct grend_context *ctx, |
||||
const struct pipe_draw_info *info); |
||||
|
||||
void grend_set_framebuffer_state(struct grend_context *ctx, |
||||
uint32_t nr_cbufs, uint32_t surf_handle[8], |
||||
uint32_t zsurf_handle); |
||||
|
||||
void grend_flush(struct grend_context *ctx); |
||||
|
||||
|
||||
void grend_flush_frontbuffer(uint32_t res_handle); |
||||
struct grend_context *grend_create_context(int id, uint32_t nlen, const char *debug_name); |
||||
bool grend_destroy_context(struct grend_context *ctx); |
||||
void graw_renderer_context_create(uint32_t handle, uint32_t nlen, const char *name); |
||||
void graw_renderer_context_create_internal(uint32_t handle, uint32_t nlen, const char *name); |
||||
void graw_renderer_context_destroy(uint32_t handle); |
||||
|
||||
struct graw_renderer_resource_create_args { |
||||
uint32_t handle; |
||||
enum pipe_texture_target target; |
||||
uint32_t format; |
||||
uint32_t bind; |
||||
uint32_t width; |
||||
uint32_t height; |
||||
uint32_t depth; |
||||
uint32_t array_size; |
||||
uint32_t last_level; |
||||
uint32_t nr_samples; |
||||
uint32_t flags; |
||||
}; |
||||
|
||||
void graw_renderer_resource_create(struct graw_renderer_resource_create_args *args, struct virgl_iovec *iov, uint32_t num_iovs); |
||||
|
||||
void graw_renderer_resource_unref(uint32_t handle); |
||||
|
||||
void grend_create_surface(struct grend_context *ctx, |
||||
uint32_t handle, |
||||
uint32_t res_handle, uint32_t format, |
||||
uint32_t val0, uint32_t val1); |
||||
void grend_create_sampler_view(struct grend_context *ctx, |
||||
uint32_t handle, |
||||
uint32_t res_handle, uint32_t format, |
||||
uint32_t val0, uint32_t val1, uint32_t swizzle_packed); |
||||
|
||||
void grend_create_so_target(struct grend_context *ctx, |
||||
uint32_t handle, |
||||
uint32_t res_handle, |
||||
uint32_t buffer_offset, |
||||
uint32_t buffer_size); |
||||
void grend_set_streamout_targets(struct grend_context *ctx, |
||||
uint32_t append_bitmask, |
||||
uint32_t num_targets, |
||||
uint32_t *handles); |
||||
|
||||
void grend_create_vertex_elements_state(struct grend_context *ctx, |
||||
uint32_t handle, |
||||
unsigned num_elements, |
||||
const struct pipe_vertex_element *elements); |
||||
void grend_bind_vertex_elements_state(struct grend_context *ctx, |
||||
uint32_t handle); |
||||
|
||||
void grend_set_single_vbo(struct grend_context *ctx, |
||||
int index, |
||||
uint32_t stride, |
||||
uint32_t buffer_offset, |
||||
uint32_t res_handle); |
||||
void grend_set_num_vbo(struct grend_context *ctx, |
||||
int num_vbo); |
||||
|
||||
void grend_transfer_inline_write(struct grend_context *ctx, |
||||
uint32_t res_handle, |
||||
unsigned level, |
||||
unsigned usage, |
||||
const struct pipe_box *box, |
||||
const void *data, |
||||
unsigned stride, |
||||
unsigned layer_stride); |
||||
|
||||
void grend_set_viewport_state(struct grend_context *ctx, |
||||
const struct pipe_viewport_state *state); |
||||
void grend_set_num_sampler_views(struct grend_context *ctx, |
||||
uint32_t shader_type, |
||||
uint32_t start_slot, |
||||
int num_sampler_views); |
||||
void grend_set_single_sampler_view(struct grend_context *ctx, |
||||
uint32_t shader_type, |
||||
int index, |
||||
uint32_t res_handle); |
||||
|
||||
void grend_object_bind_blend(struct grend_context *ctx, |
||||
uint32_t handle); |
||||
void grend_object_bind_dsa(struct grend_context *ctx, |
||||
uint32_t handle); |
||||
void grend_object_bind_rasterizer(struct grend_context *ctx, |
||||
uint32_t handle); |
||||
|
||||
void grend_bind_sampler_states(struct grend_context *ctx, |
||||
uint32_t shader_type, |
||||
uint32_t start_slot, |
||||
uint32_t num_states, |
||||
uint32_t *handles); |
||||
void grend_set_index_buffer(struct grend_context *ctx, |
||||
uint32_t res_handle, |
||||
uint32_t index_size, |
||||
uint32_t offset); |
||||
|
||||
void graw_renderer_transfer_write_iov(uint32_t handle,
|
||||
uint32_t ctx_id, |
||||
int level, |
||||
uint32_t stride, |
||||
uint32_t layer_stride, |
||||
struct pipe_box *box, |
||||
uint64_t offset, |
||||
struct virgl_iovec *iovec, |
||||
unsigned int iovec_cnt); |
||||
|
||||
void graw_renderer_resource_copy_region(struct grend_context *ctx, |
||||
uint32_t dst_handle, uint32_t dst_level, |
||||
uint32_t dstx, uint32_t dsty, uint32_t dstz, |
||||
uint32_t src_handle, uint32_t src_level, |
||||
const struct pipe_box *src_box); |
||||
|
||||
void graw_renderer_blit(struct grend_context *ctx, |
||||
uint32_t dst_handle, uint32_t src_handle, |
||||
const struct pipe_blit_info *info); |
||||
|
||||
void graw_renderer_transfer_send_iov(uint32_t handle, uint32_t ctx_id, |
||||
uint32_t level, uint32_t stride, |
||||
uint32_t layer_stride, |
||||
struct pipe_box *box, |
||||
uint64_t offset, struct virgl_iovec *iov, |
||||
int iovec_cnt); |
||||
void grend_set_stencil_ref(struct grend_context *ctx, struct pipe_stencil_ref *ref); |
||||
void grend_set_blend_color(struct grend_context *ctx, struct pipe_blend_color *color); |
||||
void grend_set_scissor_state(struct grend_context *ctx, struct pipe_scissor_state *ss); |
||||
|
||||
void grend_set_polygon_stipple(struct grend_context *ctx, struct pipe_poly_stipple *ps); |
||||
|
||||
void grend_set_clip_state(struct grend_context *ctx, struct pipe_clip_state *ucp); |
||||
void grend_set_sample_mask(struct grend_context *ctx, unsigned sample_mask); |
||||
|
||||
void grend_set_constants(struct grend_context *ctx, |
||||
uint32_t shader, |
||||
uint32_t index, |
||||
uint32_t num_constant, |
||||
float *data); |
||||
|
||||
void graw_transfer_write_return(void *data, uint32_t bytes, uint64_t offset, |
||||
struct virgl_iovec *iov, int iovec_cnt); |
||||
|
||||
void graw_transfer_write_tex_return(struct pipe_resource *res, |
||||
struct pipe_box *box, |
||||
uint32_t level, |
||||
uint32_t dst_stride, |
||||
uint64_t offset, |
||||
struct virgl_iovec *iov, |
||||
int num_iovs, |
||||
void *myptr, int size, int invert); |
||||
|
||||
int graw_renderer_set_scanout(uint32_t res_handle, |
||||
uint32_t scanout_id, |
||||
uint32_t ctx_id, |
||||
struct pipe_box *box); |
||||
|
||||
int graw_renderer_flush_buffer(uint32_t res_handle, |
||||
uint32_t ctx_id, |
||||
struct pipe_box *box); |
||||
|
||||
void graw_renderer_fini(void); |
||||
void graw_reset_decode(void); |
||||
|
||||
void graw_decode_block_iov(struct virgl_iovec *iov, uint32_t niovs, uint32_t ctx_id, uint64_t offset, int ndw); |
||||
struct grend_context *vrend_lookup_renderer_ctx(uint32_t ctx_id); |
||||
|
||||
int graw_renderer_create_fence(int client_fence_id, uint32_t ctx_id); |
||||
|
||||
void graw_renderer_check_fences(void); |
||||
void graw_renderer_check_queries(void); |
||||
void grend_stop_current_queries(void); |
||||
|
||||
boolean grend_hw_switch_context(struct grend_context *ctx, boolean now); |
||||
void graw_renderer_object_insert(struct grend_context *ctx, void *data, |
||||
uint32_t size, uint32_t handle, enum virgl_object_type type); |
||||
void graw_renderer_object_destroy(struct grend_context *ctx, uint32_t handle); |
||||
|
||||
void grend_create_query(struct grend_context *ctx, uint32_t handle, |
||||
uint32_t query_type, uint32_t res_handle, |
||||
uint32_t offset); |
||||
|
||||
void grend_begin_query(struct grend_context *ctx, uint32_t handle); |
||||
void grend_end_query(struct grend_context *ctx, uint32_t handle); |
||||
void grend_get_query_result(struct grend_context *ctx, uint32_t handle, |
||||
uint32_t wait); |
||||
void grend_set_query_state(struct grend_context *ctx, |
||||
boolean enabled); |
||||
void grend_render_condition(struct grend_context *ctx, |
||||
uint32_t handle, |
||||
boolean condtion, |
||||
uint mode); |
||||
void grend_set_cursor_info(uint32_t cursor_handle, int x, int y); |
||||
void *graw_renderer_get_cursor_contents(uint32_t res_handle, uint32_t *width, uint32_t *height); |
||||
void grend_use_program(GLuint program_id); |
||||
void grend_blend_enable(GLboolean blend_enable); |
||||
void grend_depth_test_enable(GLboolean depth_test_enable); |
||||
void grend_bind_va(GLuint vaoid); |
||||
int graw_renderer_flush_buffer_res(struct grend_resource *res, |
||||
struct pipe_box *box); |
||||
|
||||
void graw_renderer_fill_caps(uint32_t set, uint32_t version, |
||||
union virgl_caps *caps); |
||||
|
||||
GLint64 graw_renderer_get_timestamp(void); |
||||
/* formats */ |
||||
void vrend_build_format_list(void); |
||||
|
||||
int graw_renderer_resource_attach_iov(int res_handle, struct virgl_iovec *iov, |
||||
int num_iovs); |
||||
void graw_renderer_resource_invalid_iov(int res_handle); |
||||
void graw_renderer_resource_destroy(struct grend_resource *res); |
||||
|
||||
static INLINE void |
||||
grend_resource_reference(struct grend_resource **ptr, struct grend_resource *tex) |
||||
{ |
||||
struct grend_resource *old_tex = *ptr; |
||||
|
||||
if (pipe_reference(&(*ptr)->base.reference, &tex->base.reference)) |
||||
graw_renderer_resource_destroy(old_tex); |
||||
*ptr = tex; |
||||
} |
||||
|
||||
void graw_renderer_force_ctx_0(void); |
||||
|
||||
void graw_renderer_get_rect(int idx, struct virgl_iovec *iov, unsigned int num_iovs, |
||||
uint32_t offset, int x, int y, int width, int height); |
||||
#endif |
@ -0,0 +1,72 @@ |
||||
/* helper library for qemu local renderers like SDL / GTK
|
||||
flushes the given texture to the frontbuffer */ |
||||
#include <epoxy/gl.h> |
||||
#include "virgl_helper.h" |
||||
|
||||
#define MAX_HELPER_SCANOUT 4 |
||||
|
||||
static struct helper_scanout { |
||||
GLuint tex_id; |
||||
GLuint fb_id; |
||||
int x, y; |
||||
uint32_t width, height; |
||||
unsigned flags; |
||||
} frontbuf[MAX_HELPER_SCANOUT]; |
||||
|
||||
void virgl_helper_scanout_info(int idx, |
||||
uint32_t tex_id, |
||||
uint32_t flags, |
||||
int x, int y, |
||||
uint32_t width, uint32_t height) |
||||
{ |
||||
|
||||
frontbuf[idx].x = x; |
||||
frontbuf[idx].y = y; |
||||
frontbuf[idx].width = width; |
||||
frontbuf[idx].height = height; |
||||
frontbuf[idx].tex_id = tex_id; |
||||
frontbuf[idx].flags = flags; |
||||
if (tex_id == 0 && width == 0 && height == 0) { |
||||
if (frontbuf[idx].fb_id) { |
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, |
||||
GL_TEXTURE_2D, 0, 0); |
||||
glDeleteFramebuffers(1, &frontbuf[idx].fb_id); |
||||
} |
||||
return; |
||||
} |
||||
if (!frontbuf[idx].fb_id) |
||||
glGenFramebuffers(1, &frontbuf[idx].fb_id); |
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER_EXT, frontbuf[idx].fb_id); |
||||
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, |
||||
GL_TEXTURE_2D, tex_id, 0); |
||||
} |
||||
|
||||
void virgl_helper_flush_scanout(int idx, |
||||
int x, int y, |
||||
uint32_t width, uint32_t height) |
||||
{ |
||||
uint32_t sy1, sy2, dy1, dy2; |
||||
|
||||
if (!frontbuf[idx].width || !frontbuf[idx].height) |
||||
return; |
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, frontbuf[idx].fb_id); |
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); |
||||
|
||||
dy1 = frontbuf[idx].height - y - frontbuf[idx].y; |
||||
dy2 = frontbuf[idx].height - y - height - frontbuf[idx].y; |
||||
if (frontbuf[idx].flags & VIRGL_HELPER_Y_0_TOP) { |
||||
sy1 = frontbuf[idx].height - y; |
||||
sy2 = frontbuf[idx].height - y - height; |
||||
} else { |
||||
sy1 = y; |
||||
sy2 = y + height; |
||||
} |
||||
|
||||
glViewport(0, 0, frontbuf[idx].width, frontbuf[idx].height); |
||||
glBlitFramebuffer(x, sy1, x + width, sy2, |
||||
x - frontbuf[idx].x, dy1, x + width - frontbuf[idx].x, dy2, |
||||
GL_COLOR_BUFFER_BIT, GL_NEAREST); |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,40 @@ |
||||
#ifndef GRAW_SHADER_H |
||||
#define GRAW_SHADER_H |
||||
|
||||
#include "pipe/p_state.h" |
||||
|
||||
#define SHADER_FLAG_FS_INVERT 1 |
||||
|
||||
/* need to store patching info for interpolation */ |
||||
struct vrend_interp_info { |
||||
int semantic_name; |
||||
int semantic_index; |
||||
int interpolate; |
||||
}; |
||||
|
||||
struct vrend_shader_info { |
||||
uint32_t samplers_used_mask; |
||||
int num_consts; |
||||
int num_inputs; |
||||
int num_interps; |
||||
int num_outputs; |
||||
uint32_t shadow_samp_mask; |
||||
struct pipe_stream_output_info so_info; |
||||
|
||||
struct vrend_interp_info *interpinfo; |
||||
}; |
||||
|
||||
struct vrend_shader_key { |
||||
uint32_t coord_replace; |
||||
boolean invert_fs_origin; |
||||
}; |
||||
|
||||
boolean vrend_patch_vertex_shader_interpolants(char *program, |
||||
struct vrend_shader_info *vs_info, |
||||
struct vrend_shader_info *fs_info); |
||||
|
||||
char *tgsi_convert(const struct tgsi_token *tokens, |
||||
struct vrend_shader_key *key, |
||||
struct vrend_shader_info *sinfo); |
||||
|
||||
#endif |
@ -0,0 +1,426 @@ |
||||
#include <stdio.h> |
||||
#include <time.h> |
||||
|
||||
#include <epoxy/gl.h> |
||||
|
||||
#include <sys/mman.h> |
||||
#include <sys/stat.h> |
||||
#include <fcntl.h> |
||||
#include <errno.h> |
||||
#include <unistd.h> |
||||
#include <sys/socket.h> |
||||
#include <sys/un.h> |
||||
#include <sys/eventfd.h> |
||||
#include "virtgpu_hw.h" |
||||
#include "pipe/p_state.h" |
||||
#include "util/u_format.h" |
||||
#include "util/u_math.h" |
||||
#include "graw_renderer.h" |
||||
|
||||
#include "virglrenderer.h" |
||||
#include "virgl_egl.h" |
||||
|
||||
static struct virgl_renderer_callbacks *rcbs; |
||||
|
||||
static void *dev_cookie; |
||||
extern int localrender; |
||||
static int use_egl_context; |
||||
struct virgl_egl *egl_info; |
||||
static struct grend_if_cbs virgl_cbs; |
||||
|
||||
static int graw_process_cmd(struct virtgpu_command *cmd, struct virgl_iovec *iov, |
||||
unsigned int niovs); |
||||
|
||||
int virgl_renderer_process_vcmd(void *cmd, struct virgl_iovec *iov, unsigned int niovs) |
||||
{ |
||||
struct virtgpu_command *qcmd = cmd; |
||||
int ret; |
||||
ret = graw_process_cmd(qcmd, iov, niovs); |
||||
graw_renderer_check_fences(); |
||||
return ret; |
||||
} |
||||
|
||||
static void virgl_cmd_create_resource_2d(struct virtgpu_command *cmd) |
||||
{ |
||||
struct graw_renderer_resource_create_args args; |
||||
|
||||
args.handle = cmd->u.resource_create_2d.resource_id; |
||||
args.target = 2; |
||||
args.format = cmd->u.resource_create_2d.format; |
||||
args.bind = (1 << 1); |
||||
args.width = cmd->u.resource_create_2d.width; |
||||
args.height = cmd->u.resource_create_2d.height; |
||||
args.depth = 1; |
||||
args.array_size = 1; |
||||
args.last_level = 0; |
||||
args.nr_samples = 0; |
||||
args.flags = VIRGL_RESOURCE_Y_0_TOP; |
||||
graw_renderer_resource_create(&args, NULL, 0); |
||||
} |
||||
|
||||
static void virgl_cmd_create_resource_3d(struct virtgpu_command *cmd) |
||||
{ |
||||
struct graw_renderer_resource_create_args args; |
||||
|
||||
args.handle = cmd->u.resource_create_3d.resource_id; |
||||
args.target = cmd->u.resource_create_3d.target; |
||||
args.format = cmd->u.resource_create_3d.format; |
||||
args.bind = cmd->u.resource_create_3d.bind; |
||||
args.width = cmd->u.resource_create_3d.width; |
||||
args.height = cmd->u.resource_create_3d.height; |
||||
args.depth = cmd->u.resource_create_3d.depth; |
||||
args.array_size = cmd->u.resource_create_3d.array_size; |
||||
args.last_level = cmd->u.resource_create_3d.last_level; |
||||
args.nr_samples = cmd->u.resource_create_3d.nr_samples; |
||||
args.flags = cmd->u.resource_create_3d.flags; |
||||
graw_renderer_resource_create(&args, NULL, 0); |
||||
} |
||||
|
||||
static void virgl_resource_attach_backing(struct virtgpu_resource_attach_backing *att_rb, |
||||
struct iovec *iov, |
||||
unsigned int iov_cnt) |
||||
{ |
||||
uint32_t gsize = graw_iov_size(iov, iov_cnt); |
||||
struct virgl_iovec *res_iovs; |
||||
int i; |
||||
void *data; |
||||
int ret; |
||||
|
||||
res_iovs = malloc(att_rb->nr_entries * sizeof(struct virgl_iovec)); |
||||
if (!res_iovs) |
||||
return; |
||||
|
||||
if (iov_cnt > 1) { |
||||
data = malloc(gsize); |
||||
graw_iov_to_buf(iov, iov_cnt, 0, data, gsize); |
||||
} else |
||||
data = iov[0].iov_base; |
||||
|
||||
for (i = 0; i < att_rb->nr_entries; i++) { |
||||
struct virtgpu_mem_entry *ent = ((struct virtgpu_mem_entry *)data) + i; |
||||
res_iovs[i].iov_len = ent->length; |
||||
ret = rcbs->map_iov(&res_iovs[i], ent->addr); |
||||
if (ret) { |
||||
fprintf(stderr, "failed to attach backing %d\n", att_rb->resource_id); |
||||
free(res_iovs); |
||||
res_iovs = NULL; |
||||
goto fail_free; |
||||
} |
||||
} |
||||
|
||||
ret = graw_renderer_resource_attach_iov(att_rb->resource_id, res_iovs, |
||||
att_rb->nr_entries); |
||||
goto out; |
||||
fail_free: |
||||
free(res_iovs); |
||||
out: |
||||
|
||||
if (iov_cnt > 1) |
||||
free(data); |
||||
} |
||||
|
||||
static void virgl_resource_inval_backing_iov(struct virgl_iovec *iov, uint32_t iov_cnt) |
||||
{ |
||||
int i; |
||||
for (i = 0; i < iov_cnt; i++) { |
||||
rcbs->unmap_iov(&iov[i]); |
||||
} |
||||
free(iov); |
||||
} |
||||
|
||||
static void virgl_resource_inval_backing(int resource_id) |
||||
{ |
||||
graw_renderer_resource_invalid_iov(resource_id); |
||||
} |
||||
|
||||
static int graw_process_cmd(struct virtgpu_command *cmd, struct virgl_iovec *iov, |
||||
unsigned int niovs) |
||||
{ |
||||
static int inited; |
||||
int fence_ctx_id = 0; |
||||
|
||||
graw_renderer_force_ctx_0(); |
||||
switch (cmd->type) { |
||||
case VIRTGPU_CMD_CTX_CREATE: |
||||
graw_renderer_context_create(cmd->u.ctx_create.ctx_id, cmd->u.ctx_create.nlen, |
||||
cmd->u.ctx_create.debug_name); |
||||
break; |
||||
case VIRTGPU_CMD_CTX_DESTROY: |
||||
graw_renderer_context_destroy(cmd->u.ctx_destroy.ctx_id); |
||||
break; |
||||
case VIRTGPU_CMD_RESOURCE_CREATE_2D: |
||||
virgl_cmd_create_resource_2d(cmd); |
||||
break; |
||||
case VIRTGPU_CMD_RESOURCE_CREATE_3D: |
||||
virgl_cmd_create_resource_3d(cmd); |
||||
break; |
||||
case VIRTGPU_CMD_SUBMIT_3D: |
||||
// fprintf(stderr,"cmd submit %lx %d\n", cmd->u.cmd_submit.data, cmd->u.cmd_submit.size);
|
||||
|
||||
{ |
||||
graw_decode_block_iov(iov, niovs, cmd->u.cmd_submit.ctx_id, cmd->u.cmd_submit.phy_addr, cmd->u.cmd_submit.size / 4); |
||||
fence_ctx_id = cmd->u.cmd_submit.ctx_id; |
||||
} |
||||
|
||||
break; |
||||
case VIRTGPU_CMD_TRANSFER_TO_HOST_2D: { |
||||
struct pipe_box box; |
||||
|
||||
box.x = cmd->u.transfer_to_host_2d.x; |
||||
box.y = cmd->u.transfer_to_host_2d.y; |
||||
box.z = 0; |
||||
box.width = cmd->u.transfer_to_host_2d.width; |
||||
box.height = cmd->u.transfer_to_host_2d.height; |
||||
box.depth = 1; |
||||
|
||||
// fprintf(stderr,"got transfer get %d\n", cmd->u.transfer_to_host_3d.res_handle);
|
||||
graw_renderer_transfer_write_iov(cmd->u.transfer_to_host_2d.resource_id, |
||||
0, |
||||
0, |
||||
0, |
||||
0, |
||||
(struct pipe_box *)&box, |
||||
cmd->u.transfer_to_host_2d.offset, NULL, 0); |
||||
break; |
||||
} |
||||
case VIRTGPU_CMD_TRANSFER_TO_HOST_3D: |
||||
// fprintf(stderr,"got transfer get %d\n", cmd->u.transfer_to_host_3d.res_handle);
|
||||
graw_renderer_transfer_write_iov(cmd->u.transfer_to_host_3d.resource_id, |
||||
cmd->u.transfer_to_host_3d.ctx_id, |
||||
cmd->u.transfer_to_host_3d.level, |
||||
cmd->u.transfer_to_host_3d.stride, |
||||
cmd->u.transfer_to_host_3d.layer_stride, |
||||
(struct pipe_box *)&cmd->u.transfer_to_host_3d.box, |
||||
cmd->u.transfer_to_host_3d.data, NULL, 0); |
||||
fence_ctx_id = cmd->u.transfer_to_host_3d.ctx_id; |
||||
break; |
||||
case VIRTGPU_CMD_TRANSFER_FROM_HOST_3D: |
||||
graw_renderer_transfer_send_iov(cmd->u.transfer_from_host_3d.resource_id, |
||||
cmd->u.transfer_from_host_3d.ctx_id, |
||||
cmd->u.transfer_from_host_3d.level, |
||||
cmd->u.transfer_from_host_3d.stride, |
||||
cmd->u.transfer_from_host_3d.layer_stride, |
||||
(struct pipe_box *)&cmd->u.transfer_from_host_3d.box, |
||||
cmd->u.transfer_from_host_3d.data, NULL, 0); |
||||
fence_ctx_id = cmd->u.transfer_from_host_3d.ctx_id; |
||||
break; |
||||
|
||||
case VIRTGPU_CMD_RESOURCE_ATTACH_BACKING: |
||||
virgl_resource_attach_backing(&cmd->u.resource_attach_backing, iov, niovs); |
||||
break; |
||||
case VIRTGPU_CMD_RESOURCE_INVAL_BACKING: |
||||
virgl_resource_inval_backing(cmd->u.resource_inval_backing.resource_id); |
||||
break; |
||||
case VIRTGPU_CMD_SET_SCANOUT: { |
||||
struct pipe_box box; |
||||
box.x = cmd->u.set_scanout.x; |
||||
box.y = cmd->u.set_scanout.y; |
||||
box.z = 0; |
||||
box.width = cmd->u.set_scanout.width; |
||||
box.height = cmd->u.set_scanout.height; |
||||
box.depth = 1; |
||||
graw_renderer_set_scanout(cmd->u.set_scanout.resource_id, cmd->u.set_scanout.scanout_id, |
||||
0, &box); |
||||
break; |
||||
} |
||||
case VIRTGPU_CMD_RESOURCE_FLUSH: |
||||
{ |
||||
struct pipe_box box; |
||||
box.x = cmd->u.resource_flush.x; |
||||
box.y = cmd->u.resource_flush.y; |
||||
box.z = 0; |
||||
box.width = cmd->u.resource_flush.width; |
||||
box.height = cmd->u.resource_flush.height; |
||||
box.depth = 1; |
||||
graw_renderer_flush_buffer(cmd->u.resource_flush.resource_id, |
||||
0, &box); |
||||
break; |
||||
}
|
||||
case VIRTGPU_CMD_RESOURCE_UNREF: |
||||
graw_renderer_resource_unref(cmd->u.resource_unref.resource_id); |
||||
break; |
||||
case VIRTGPU_CMD_CTX_ATTACH_RESOURCE: |
||||
/* TODO add security */ |
||||
break; |
||||
case VIRTGPU_CMD_CTX_DETACH_RESOURCE: |
||||
/* TODO add security */ |
||||
break; |
||||
case VIRTGPU_CMD_GET_CAPS: |
||||
if (!niovs) |
||||
return 0; |
||||
|
||||
{ |
||||
struct virtgpu_response resp; |
||||
graw_renderer_fill_caps(cmd->u.get_cap.cap_set, |
||||
cmd->u.get_cap.cap_set_version, |
||||
(union virgl_caps *)&resp.u.caps); |
||||
resp.flags = 0; |
||||
resp.type = VIRTGPU_CMD_GET_CAPS; |
||||
graw_iov_from_buf(iov, niovs, 0, &resp, sizeof(struct virtgpu_response)); |
||||
} |
||||
|
||||
break; |
||||
case VIRTGPU_CMD_GET_DISPLAY_INFO: |
||||
return -1; |
||||
case 0xdeadbeef: |
||||
if (inited) { |
||||
graw_renderer_fini(); |
||||
|
||||
} |
||||
graw_renderer_init(&virgl_cbs); |
||||
inited = 1; |
||||
break; |
||||
} |
||||
|
||||
if (cmd->flags & VIRGL_COMMAND_EMIT_FENCE) |
||||
graw_renderer_create_fence(cmd->fence_id, fence_ctx_id); |
||||
return 0; |
||||
} |
||||
|
||||
void graw_transfer_write_return(void *data, uint32_t bytes, uint64_t offset, |
||||
struct virgl_iovec *iov, int num_iovs) |
||||
{ |
||||
graw_iov_from_buf(iov, num_iovs, offset, data, bytes); |
||||
} |
||||
|
||||
void graw_transfer_write_tex_return(struct pipe_resource *res, |
||||
struct pipe_box *box, |
||||
uint32_t level, |
||||
uint32_t dst_stride, |
||||
uint64_t offset, |
||||
struct virgl_iovec *iov, |
||||
int num_iovs, |
||||
void *myptr, int size, int invert) |
||||
{ |
||||
int elsize = util_format_get_blocksize(res->format); |
||||
int h; |
||||
uint32_t myoffset = offset; |
||||
uint32_t stride = dst_stride ? dst_stride : util_format_get_nblocksx(res->format, u_minify(res->width0, level)) * elsize; |
||||
// uint32_t stride = dst_stride ? dst_stride : util_format_get_nblocksx(res->format, box->width) * elsize;
|
||||
|
||||
if (!invert && (stride == util_format_get_nblocksx(res->format, box->width) * elsize)) |
||||
graw_iov_from_buf(iov, num_iovs, offset, myptr, size); |
||||
else if (invert) { |
||||
for (h = box->height - 1; h >= 0; h--) { |
||||
void *sptr = myptr + (h * elsize * box->width); |
||||
graw_iov_from_buf(iov, num_iovs, myoffset, sptr, box->width * elsize); |
||||
myoffset += stride; |
||||
} |
||||
} else { |
||||
for (h = 0; h < box->height; h++) { |
||||
void *sptr = myptr + (h * elsize * box->width); |
||||
graw_iov_from_buf(iov, num_iovs, myoffset, sptr, box->width * elsize); |
||||
myoffset += stride; |
||||
} |
||||
} |
||||
} |
||||
|
||||
static void virgl_write_fence(uint32_t fence_id) |
||||
{ |
||||
rcbs->write_fence(dev_cookie, fence_id);
|
||||
} |
||||
|
||||
static virgl_gl_context create_gl_context(int scanout_idx) |
||||
{ |
||||
if (use_egl_context) |
||||
return virgl_egl_create_context(egl_info); |
||||
return rcbs->create_gl_context(dev_cookie, scanout_idx); |
||||
} |
||||
|
||||
static void destroy_gl_context(virgl_gl_context ctx) |
||||
{ |
||||
if (use_egl_context) |
||||
return virgl_egl_destroy_context(egl_info, ctx); |
||||
return rcbs->destroy_gl_context(dev_cookie, ctx); |
||||
} |
||||
|
||||
static int make_current(int scanout_idx, virgl_gl_context ctx) |
||||
{ |
||||
if (use_egl_context) |
||||
return virgl_egl_make_context_current(egl_info, ctx); |
||||
return rcbs->make_current(dev_cookie, scanout_idx, ctx); |
||||
} |
||||
|
||||
static void flush_scanout(int scanout_id, int x, int y, uint32_t width, uint32_t height) |
||||
{ |
||||
if (rcbs->rect_update) |
||||
rcbs->rect_update(dev_cookie, scanout_id, x, y, width, height); |
||||
} |
||||
|
||||
static void scanout_rect_info(int scanout_id, GLuint tex_id, |
||||
int x, int y, uint32_t width, |
||||
uint32_t height) |
||||
{ |
||||
if (rcbs->scanout_rect_info) |
||||
rcbs->scanout_rect_info(dev_cookie, scanout_id, tex_id, |
||||
x, y, width, height); |
||||
} |
||||
|
||||
static void scanout_resource_info(int scanout_id, GLuint tex_id, uint32_t flags, |
||||
uint32_t stride, uint32_t width, |
||||
uint32_t height, uint32_t format) |
||||
{ |
||||
if (rcbs->scanout_resource_info) |
||||
rcbs->scanout_resource_info(dev_cookie, scanout_id, tex_id, flags, |
||||
stride, width, height, virgl_egl_get_gbm_format(format)); |
||||
} |
||||
|
||||
static struct grend_if_cbs virgl_cbs = { |
||||
virgl_write_fence, |
||||
scanout_rect_info, |
||||
scanout_resource_info, |
||||
create_gl_context, |
||||
destroy_gl_context, |
||||
make_current, |
||||
flush_scanout, |
||||
virgl_resource_inval_backing_iov, |
||||
}; |
||||
|
||||
void *virgl_get_cursor_data(uint32_t resource_id, uint32_t *width, uint32_t *height) |
||||
{ |
||||
return graw_renderer_get_cursor_contents(resource_id, width, height); |
||||
} |
||||
|
||||
void virgl_renderer_set_cursor_info(uint32_t cursor_handle, int x, int y) |
||||
{ |
||||
grend_set_cursor_info(cursor_handle, x, y); |
||||
} |
||||
|
||||
void virgl_renderer_poll(void) |
||||
{ |
||||
graw_renderer_check_queries(); |
||||
graw_renderer_check_fences(); |
||||
} |
||||
|
||||
void virgl_renderer_get_rect(int idx, struct virgl_iovec *iov, unsigned int num_iovs, |
||||
uint32_t offset, int x, int y, int width, int height) |
||||
{ |
||||
graw_renderer_get_rect(idx, iov, num_iovs, offset, x, y, width, height); |
||||
|
||||
} |
||||
|
||||
int virgl_renderer_init(void *cookie, int flags, struct virgl_renderer_callbacks *cbs) |
||||
{ |
||||
dev_cookie = cookie; |
||||
rcbs = cbs; |
||||
localrender = 1; |
||||
|
||||
fprintf(stderr,"initied renderer %d\n", flags); |
||||
if (flags & VIRGL_RENDERER_USE_EGL) { |
||||
egl_info = virgl_egl_init(); |
||||
if (!egl_info) |
||||
return -1; |
||||
use_egl_context = 1; |
||||
} |
||||
|
||||
if (cbs->version != 1) |
||||
return -1; |
||||
graw_renderer_init(&virgl_cbs); |
||||
return 0; |
||||
} |
||||
|
||||
int virgl_renderer_get_fd_for_texture(uint32_t tex_id, int *fd) |
||||
{ |
||||
return virgl_egl_get_fd_for_texture(egl_info, tex_id, fd); |
||||
|
||||
} |
@ -0,0 +1,256 @@ |
||||
/*
|
||||
* Helpers for getting linearized buffers from iov / filling buffers into iovs |
||||
* |
||||
* Copyright IBM, Corp. 2007, 2008 |
||||
* Copyright (C) 2010 Red Hat, Inc. |
||||
* |
||||
* Author(s): |
||||
* Anthony Liguori <aliguori@us.ibm.com> |
||||
* Amit Shah <amit.shah@redhat.com> |
||||
* Michael Tokarev <mjt@tls.msk.ru> |
||||
* |
||||
* This work is licensed under the terms of the GNU GPL, version 2. See |
||||
* the COPYING file in the top-level directory. |
||||
* |
||||
* Contributions after 2012-01-13 are licensed under the terms of the |
||||
* GNU GPL, version 2 or (at your option) any later version. |
||||
*/ |
||||
|
||||
#include <string.h> |
||||
#include <assert.h> |
||||
|
||||
#include <sys/types.h> |
||||
|
||||
|
||||
#include "graw_iov.h" |
||||
|
||||
#ifndef MIN |
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b)) |
||||
#endif |
||||
|
||||
|
||||
size_t graw_iov_from_buf(const struct virgl_iovec *iov, unsigned int iov_cnt, |
||||
size_t offset, const void *buf, size_t bytes) |
||||
{ |
||||
size_t done; |
||||
unsigned int i; |
||||
for (i = 0, done = 0; (offset || done < bytes) && i < iov_cnt; i++) { |
||||
if (offset < iov[i].iov_len) { |
||||
size_t len = MIN(iov[i].iov_len - offset, bytes - done); |
||||
memcpy(iov[i].iov_base + offset, buf + done, len); |
||||
done += len; |
||||
offset = 0; |
||||
} else { |
||||
offset -= iov[i].iov_len; |
||||
} |
||||
} |
||||
assert(offset == 0); |
||||
return done; |
||||
} |
||||
|
||||
size_t graw_iov_to_buf(const struct virgl_iovec *iov, const unsigned int iov_cnt, |
||||
size_t offset, void *buf, size_t bytes) |
||||
{ |
||||
size_t done; |
||||
unsigned int i; |
||||
for (i = 0, done = 0; (offset || done < bytes) && i < iov_cnt; i++) { |
||||
if (offset < iov[i].iov_len) { |
||||
size_t len = MIN(iov[i].iov_len - offset, bytes - done); |
||||
memcpy(buf + done, iov[i].iov_base + offset, len); |
||||
done += len; |
||||
offset = 0; |
||||
} else { |
||||
offset -= iov[i].iov_len; |
||||
} |
||||
} |
||||
assert(offset == 0); |
||||
return done; |
||||
} |
||||
|
||||
size_t graw_iov_to_buf_cb(const struct virgl_iovec *iov, const unsigned int iov_cnt, |
||||
size_t offset, size_t bytes, IOCallback iovcb, |
||||
void *cookie) |
||||
{ |
||||
size_t done; |
||||
unsigned int i; |
||||
for (i = 0, done = 0; (offset || done < bytes) && i < iov_cnt; i++) { |
||||
if (offset < iov[i].iov_len) { |
||||
size_t len = MIN(iov[i].iov_len - offset, bytes - done); |
||||
(*iovcb)(cookie, done, iov[i].iov_base + offset, len); |
||||
done += len; |
||||
offset = 0; |
||||
} else { |
||||
offset -= iov[i].iov_len; |
||||
} |
||||
} |
||||
assert(offset == 0); |
||||
return done; |
||||
} |
||||
|
||||
#if 0 |
||||
size_t iov_memset(const struct virgl_iovec *iov, const unsigned int iov_cnt, |
||||
size_t offset, int fillc, size_t bytes) |
||||
{ |
||||
size_t done; |
||||
unsigned int i; |
||||
for (i = 0, done = 0; (offset || done < bytes) && i < iov_cnt; i++) { |
||||
if (offset < iov[i].iov_len) { |
||||
size_t len = MIN(iov[i].iov_len - offset, bytes - done); |
||||
memset(iov[i].iov_base + offset, fillc, len); |
||||
done += len; |
||||
offset = 0; |
||||
} else { |
||||
offset -= iov[i].iov_len; |
||||
} |
||||
} |
||||
assert(offset == 0); |
||||
return done; |
||||
} |
||||
#endif |
||||
size_t graw_iov_size(const struct virgl_iovec *iov, const unsigned int iov_cnt) |
||||
{ |
||||
size_t len; |
||||
unsigned int i; |
||||
|
||||
len = 0; |
||||
for (i = 0; i < iov_cnt; i++) { |
||||
len += iov[i].iov_len; |
||||
} |
||||
return len; |
||||
} |
||||
|
||||
#if 0 |
||||
/* helper function for iov_send_recv() */ |
||||
static ssize_t |
||||
do_send_recv(int sockfd, struct virgl_iovec *iov, unsigned iov_cnt, bool do_send) |
||||
{ |
||||
#if defined CONFIG_IOVEC && defined CONFIG_POSIX |
||||
ssize_t ret; |
||||
struct msghdr msg; |
||||
memset(&msg, 0, sizeof(msg)); |
||||
msg.msg_iov = iov; |
||||
msg.msg_iovlen = iov_cnt; |
||||
do { |
||||
ret = do_send |
||||
? sendmsg(sockfd, &msg, 0) |
||||
: recvmsg(sockfd, &msg, 0); |
||||
} while (ret < 0 && errno == EINTR); |
||||
return ret; |
||||
#else |
||||
/* else send piece-by-piece */ |
||||
/*XXX Note: windows has WSASend() and WSARecv() */ |
||||
unsigned i = 0; |
||||
ssize_t ret = 0; |
||||
while (i < iov_cnt) { |
||||
ssize_t r = do_send |
||||
? send(sockfd, iov[i].iov_base, iov[i].iov_len, 0) |
||||
: recv(sockfd, iov[i].iov_base, iov[i].iov_len, 0); |
||||
if (r > 0) { |
||||
ret += r; |
||||
} else if (!r) { |
||||
break; |
||||
} else if (errno == EINTR) { |
||||
continue; |
||||
} else { |
||||
/* else it is some "other" error,
|
||||
* only return if there was no data processed. */ |
||||
if (ret == 0) { |
||||
ret = -1; |
||||
} |
||||
break; |
||||
} |
||||
i++; |
||||
} |
||||
return ret; |
||||
#endif |
||||
} |
||||
|
||||
ssize_t iov_send_recv(int sockfd, struct virgl_iovec *iov, unsigned iov_cnt, |
||||
size_t offset, size_t bytes, |
||||
bool do_send) |
||||
{ |
||||
ssize_t ret; |
||||
unsigned si, ei; /* start and end indexes */ |
||||
if (bytes == 0) { |
||||
/* Catch the do-nothing case early, as otherwise we will pass an
|
||||
* empty virgl_iovec to sendmsg/recvmsg(), and not all implementations |
||||
* accept this. |
||||
*/ |
||||
return 0; |
||||
} |
||||
|
||||
/* Find the start position, skipping `offset' bytes:
|
||||
* first, skip all full-sized vector elements, */ |
||||
for (si = 0; si < iov_cnt && offset >= iov[si].iov_len; ++si) { |
||||
offset -= iov[si].iov_len; |
||||
} |
||||
if (offset) { |
||||
assert(si < iov_cnt); |
||||
/* second, skip `offset' bytes from the (now) first element,
|
||||
* undo it on exit */ |
||||
iov[si].iov_base += offset; |
||||
iov[si].iov_len -= offset; |
||||
} |
||||
/* Find the end position skipping `bytes' bytes: */ |
||||
/* first, skip all full-sized elements */ |
||||
for (ei = si; ei < iov_cnt && iov[ei].iov_len <= bytes; ++ei) { |
||||
bytes -= iov[ei].iov_len; |
||||
} |
||||
if (bytes) { |
||||
/* second, fixup the last element, and remember
|
||||
* the length we've cut from the end of it in `bytes' */ |
||||
size_t tail; |
||||
assert(ei < iov_cnt); |
||||
assert(iov[ei].iov_len > bytes); |
||||
tail = iov[ei].iov_len - bytes; |
||||
iov[ei].iov_len = bytes; |
||||
bytes = tail; /* bytes is now equal to the tail size */ |
||||
++ei; |
||||
} |
||||
|
||||
ret = do_send_recv(sockfd, iov + si, ei - si, do_send); |
||||
|
||||
/* Undo the changes above */ |
||||
if (offset) { |
||||
iov[si].iov_base -= offset; |
||||
iov[si].iov_len += offset; |
||||
} |
||||
if (bytes) { |
||||
iov[ei-1].iov_len += bytes; |
||||
} |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
|
||||
void iov_hexdump(const struct virgl_iovec *iov, const unsigned int iov_cnt, |
||||
FILE *fp, const char *prefix, size_t limit) |
||||
{ |
||||
unsigned int i, v, b; |
||||
uint8_t *c; |
||||
|
||||
c = iov[0].iov_base; |
||||
for (i = 0, v = 0, b = 0; b < limit; i++, b++) { |
||||
if (i == iov[v].iov_len) { |
||||
i = 0; v++; |
||||
if (v == iov_cnt) { |
||||
break; |
||||
} |
||||
c = iov[v].iov_base; |
||||
} |
||||
if ((b % 16) == 0) { |
||||
fprintf(fp, "%s: %04x:", prefix, b); |
||||
} |
||||
if ((b % 4) == 0) { |
||||
fprintf(fp, " "); |
||||
} |
||||
fprintf(fp, " %02x", c[i]); |
||||
if ((b % 16) == 15) { |
||||
fprintf(fp, "\n"); |
||||
} |
||||
} |
||||
if ((b % 16) != 0) { |
||||
fprintf(fp, "\n"); |
||||
} |
||||
} |
||||
#endif |
@ -0,0 +1,16 @@ |
||||
#ifndef VIRGL_EGL_H |
||||
#define VIRGL_EGL_H |
||||
|
||||
struct virgl_egl; |
||||
|
||||
struct virgl_egl *virgl_egl_init(void); |
||||
void virgl_egl_destroy(struct virgl_egl *ve); |
||||
|
||||
virgl_gl_context virgl_egl_create_context(struct virgl_egl *ve); |
||||
void virgl_egl_destroy_context(struct virgl_egl *ve, virgl_gl_context virglctx); |
||||
int virgl_egl_make_context_current(struct virgl_egl *ve, virgl_gl_context virglctx); |
||||
virgl_gl_context virgl_egl_get_current_context(struct virgl_egl *ve); |
||||
|
||||
int virgl_egl_get_fd_for_texture(struct virgl_egl *ve, uint32_t tex_id, int *fd); |
||||
uint32_t virgl_egl_get_gbm_format(uint32_t format); |
||||
#endif |
@ -0,0 +1,295 @@ |
||||
/* create our own EGL offscreen rendering context via gbm and rendernodes */ |
||||
|
||||
|
||||
/* if we are using EGL and rendernodes then we talk via file descriptors to the remote
|
||||
node */ |
||||
#ifdef HAVE_CONFIG_H |
||||
#include "config.h" |
||||
#endif |
||||
|
||||
#include <dirent.h> |
||||
#include <fcntl.h> |
||||
#include <unistd.h> |
||||
#include <stdio.h> |
||||
#include <string.h> |
||||
#include <stdlib.h> |
||||
#include <stdbool.h> |
||||
#include <epoxy/egl.h> |
||||
#include <gbm.h> |
||||
#include <xf86drm.h> |
||||
#include "virglrenderer.h" |
||||
#include "virgl_egl.h" |
||||
|
||||
#include "virgl_hw.h" |
||||
struct virgl_egl { |
||||
int fd; |
||||
struct gbm_device *gbm_dev; |
||||
EGLDisplay egl_display; |
||||
EGLConfig egl_conf; |
||||
EGLContext egl_ctx; |
||||
bool have_mesa_drm_image; |
||||
bool have_mesa_dma_buf_img_export; |
||||
}; |
||||
|
||||
static int egl_rendernode_open(void) |
||||
{ |
||||
DIR *dir; |
||||
struct dirent *e; |
||||
int r, fd; |
||||
char *p; |
||||
dir = opendir("/dev/dri"); |
||||
if (!dir) |
||||
return -1; |
||||
|
||||
fd = -1; |
||||
while ((e = readdir(dir))) { |
||||
if (e->d_type != DT_CHR) |
||||
continue; |
||||
|
||||
if (strncmp(e->d_name, "renderD", 7)) |
||||
continue; |
||||
|
||||
r = asprintf(&p, "/dev/dri/%s", e->d_name); |
||||
if (r < 0) |
||||
return -1; |
||||
|
||||
r = open(p, O_RDWR | O_CLOEXEC | O_NOCTTY | O_NONBLOCK); |
||||
if (r < 0){ |
||||
fprintf(stderr, "failed to open render node %s\n", p); |
||||
free(p); |
||||
continue; |
||||
} |
||||
fd = r; |
||||
fprintf(stderr, "using render node %s\n", p); |
||||
free(p); |
||||
break; |
||||
} |
||||
|
||||
if (fd < 0) |
||||
return -1; |
||||
return fd; |
||||
} |
||||
|
||||
static bool virgl_egl_has_extension_in_string(const char *haystack, const char *needle) |
||||
{ |
||||
const unsigned needle_len = strlen(needle); |
||||
|
||||
if (needle_len == 0) |
||||
return false; |
||||
|
||||
while (true) { |
||||
const char *const s = strstr(haystack, needle); |
||||
|
||||
if (s == NULL) |
||||
return false; |
||||
|
||||
if (s[needle_len] == ' ' || s[needle_len] == '\0') { |
||||
return true; |
||||
} |
||||
|
||||
/* strstr found an extension whose name begins with
|
||||
* needle, but whose name is not equal to needle. |
||||
* Restart the search at s + needle_len so that we |
||||
* don't just find the same extension again and go |
||||
* into an infinite loop. |
||||
*/ |
||||
haystack = s + needle_len; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
struct virgl_egl *virgl_egl_init(void) |
||||
{ |
||||
static const EGLint conf_att[] = { |
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT, |
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, |
||||
EGL_RED_SIZE, 1, |
||||
EGL_GREEN_SIZE, 1, |
||||
EGL_BLUE_SIZE, 1, |
||||
EGL_ALPHA_SIZE, 0, |
||||
EGL_NONE, |
||||
}; |
||||
static const EGLint ctx_att[] = { |
||||
EGL_CONTEXT_CLIENT_VERSION, 2, |
||||
EGL_NONE |
||||
}; |
||||
EGLBoolean b; |
||||
EGLenum api; |
||||
EGLint major, minor, n; |
||||
const char *extension_list; |
||||
struct virgl_egl *d; |
||||
|
||||
fprintf(stderr,"egl init\n"); |
||||
d = malloc(sizeof(struct virgl_egl)); |
||||
if (!d) |
||||
return NULL; |
||||
|
||||
d->fd = egl_rendernode_open(); |
||||
d->gbm_dev = gbm_create_device(d->fd); |
||||
if (!d->gbm_dev) |
||||
goto fail; |
||||
|
||||
d->egl_display = eglGetDisplay((EGLNativeDisplayType)d->gbm_dev); |
||||
if (!d->egl_display) |
||||
goto fail; |
||||
|
||||
b = eglInitialize(d->egl_display, &major, &minor); |
||||
if (!b) |
||||
goto fail; |
||||
|
||||
extension_list = eglQueryString(d->egl_display, EGL_EXTENSIONS); |
||||
fprintf(stderr, "EGL major/minor: %d.%d\n", major, minor); |
||||
fprintf(stderr, "EGL version: %s\n", |
||||
eglQueryString(d->egl_display, EGL_VERSION)); |
||||
fprintf(stderr, "EGL vendor: %s\n", |
||||
eglQueryString(d->egl_display, EGL_VENDOR)); |
||||
fprintf(stderr, "EGL extensions: %s\n", extension_list); |
||||
|
||||
/* require surfaceless context */ |
||||
if (!virgl_egl_has_extension_in_string(extension_list, "EGL_KHR_surfaceless_context")) |
||||
goto fail; |
||||
|
||||
d->have_mesa_drm_image = false; |
||||
d->have_mesa_dma_buf_img_export = false; |
||||
if (virgl_egl_has_extension_in_string(extension_list, "EGL_MESA_drm_image")) |
||||
d->have_mesa_drm_image = true; |
||||
|
||||
if (virgl_egl_has_extension_in_string(extension_list, "EGL_MESA_image_dma_buf_export")) |
||||
d->have_mesa_dma_buf_img_export = true; |
||||
|
||||
if (d->have_mesa_drm_image == false && d->have_mesa_dma_buf_img_export == false) { |
||||
fprintf(stderr, "failed to find drm image extensions\n"); |
||||
goto fail; |
||||
} |
||||
|
||||
api = EGL_OPENGL_API; |
||||
b = eglBindAPI(api); |
||||
if (!b) |
||||
goto fail; |
||||
|
||||
b = eglChooseConfig(d->egl_display, conf_att, &d->egl_conf, |
||||
1, &n); |
||||
|
||||
if (!b || n != 1) |
||||
goto fail; |
||||
|
||||
d->egl_ctx = eglCreateContext(d->egl_display, |
||||
d->egl_conf, |
||||
EGL_NO_CONTEXT, |
||||
ctx_att); |
||||
if (!d->egl_ctx) |
||||
goto fail; |
||||
|
||||
|
||||
eglMakeCurrent(d->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, |
||||
d->egl_ctx); |
||||
return d; |
||||
fail: |
||||
|
||||
fprintf(stderr,"fail\n"); |
||||
free(d); |
||||
return NULL; |
||||
} |
||||
|
||||
void virgl_egl_destroy(struct virgl_egl *d) |
||||
{ |
||||
eglMakeCurrent(d->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, |
||||
EGL_NO_CONTEXT); |
||||
eglDestroyContext(d->egl_display, d->egl_ctx); |
||||
eglTerminate(d->egl_display); |
||||
gbm_device_destroy(d->gbm_dev); |
||||
close(d->fd); |
||||
free(d); |
||||
} |
||||
|
||||
virgl_gl_context virgl_egl_create_context(struct virgl_egl *ve) |
||||
{ |
||||
EGLContext eglctx; |
||||
static const EGLint ctx_att[] = { |
||||
EGL_CONTEXT_CLIENT_VERSION, 2, |
||||
EGL_NONE |
||||
}; |
||||
eglctx = eglCreateContext(ve->egl_display, |
||||
ve->egl_conf, |
||||
ve->egl_ctx, |
||||
ctx_att); |
||||
return (virgl_gl_context)eglctx; |
||||
} |
||||
|
||||
void virgl_egl_destroy_context(struct virgl_egl *ve, virgl_gl_context virglctx) |
||||
{ |
||||
EGLContext eglctx = (EGLContext)virglctx; |
||||
eglDestroyContext(ve->egl_display, eglctx); |
||||
} |
||||
|
||||
int virgl_egl_make_context_current(struct virgl_egl *ve, virgl_gl_context virglctx) |
||||
{ |
||||
EGLContext eglctx = (EGLContext)virglctx; |
||||
|
||||
return eglMakeCurrent(ve->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, |
||||
eglctx); |
||||
} |
||||
|
||||
virgl_gl_context virgl_egl_get_current_context(struct virgl_egl *ve) |
||||
{ |
||||
EGLContext eglctx = eglGetCurrentContext(); |
||||
return (virgl_gl_context)eglctx; |
||||
} |
||||
|
||||
int virgl_egl_get_fd_for_texture(struct virgl_egl *ve, uint32_t tex_id, int *fd) |
||||
{ |
||||
EGLImageKHR image; |
||||
EGLint stride; |
||||
EGLBoolean b; |
||||
|
||||
image = eglCreateImageKHR(ve->egl_display, ve->egl_ctx, EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer)(unsigned long)tex_id, NULL); |
||||
|
||||
if (!image) |
||||
return -1; |
||||
|
||||
if (ve->have_mesa_dma_buf_img_export) { |
||||
#ifdef EGL_MESA_image_dma_buf_export |
||||
b = eglExportDMABUFImageMESA(ve->egl_display, |
||||
image, |
||||
fd, |
||||
&stride); |
||||
#else |
||||
return -1; |
||||
#endif |
||||
} else { |
||||
#ifdef EGL_MESA_drm_image |
||||
EGLint handle; |
||||
int r; |
||||
b = eglExportDRMImageMESA(ve->egl_display, |
||||
image, |
||||
NULL, &handle, |
||||
&stride); |
||||
|
||||
if (!b) |
||||
return -1; |
||||
|
||||
fprintf(stderr,"image exported %d %d\n", handle, stride); |
||||
|
||||
r = drmPrimeHandleToFD(ve->fd, handle, DRM_CLOEXEC, fd); |
||||
if (r < 0) |
||||
return -1; |
||||
#else |
||||
return -1; |
||||
#endif |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
uint32_t virgl_egl_get_gbm_format(uint32_t format) |
||||
{ |
||||
switch (format) { |
||||
case VIRGL_FORMAT_B8G8R8X8_UNORM: |
||||
return GBM_FORMAT_XRGB8888; |
||||
case VIRGL_FORMAT_B8G8R8A8_UNORM: |
||||
return GBM_FORMAT_ARGB8888; |
||||
default: |
||||
fprintf(stderr, "unknown format to convert to GBM %d\n", format); |
||||
return 0; |
||||
} |
||||
} |
@ -0,0 +1,17 @@ |
||||
#ifndef VIRGL_HELPER_H |
||||
#define VIRGL_HELPER_H |
||||
|
||||
#define GREND_EXPORT __attribute__((visibility("default"))) |
||||
|
||||
/* add helpers for local renderers - not used by remote viewers */ |
||||
#define VIRGL_HELPER_Y_0_TOP (1 << 0) |
||||
GREND_EXPORT void virgl_helper_scanout_info(int idx, |
||||
uint32_t tex_id, |
||||
uint32_t flags, |
||||
int x, int y, |
||||
uint32_t width, uint32_t height); |
||||
GREND_EXPORT void virgl_helper_flush_scanout(int idx, |
||||
int x, int y, |
||||
uint32_t width, uint32_t height); |
||||
|
||||
#endif |
@ -0,0 +1,390 @@ |
||||
#ifndef VIRGL_HW_H |
||||
#define VIRGL_HW_H |
||||
|
||||
typedef uint64_t VIRGLPHYSICAL; |
||||
/* specification for the HW command processor */ |
||||
|
||||
struct virgl_box { |
||||
uint32_t x, y, z; |
||||
uint32_t w, h, d; |
||||
}; |
||||
|
||||
enum virgl_cmd_type { |
||||
VIRGL_CMD_NOP, |
||||
VIRGL_CMD_CREATE_CONTEXT, |
||||
VIRGL_CMD_CREATE_RESOURCE, |
||||
VIRGL_CMD_SUBMIT, |
||||
VIRGL_CMD_DESTROY_CONTEXT, |
||||
VIRGL_CMD_TRANSFER_GET, |
||||
VIRGL_CMD_TRANSFER_PUT, |
||||
VIRGL_CMD_SET_SCANOUT, |
||||
VIRGL_CMD_FLUSH_BUFFER, |
||||
VIRGL_CMD_RESOURCE_UNREF, |
||||
VIRGL_CMD_ATTACH_RES_CTX, |
||||
VIRGL_CMD_DETACH_RES_CTX, |
||||
VIRGL_CMD_RESOURCE_ATTACH_SG_LIST, |
||||
VIRGL_CMD_RESOURCE_INVALIDATE_SG_LIST, |
||||
VIRGL_CMD_GET_3D_CAPABILITIES, |
||||
VIRGL_CMD_TIMESTAMP_GET, |
||||
}; |
||||
|
||||
/* put a box of data from a BO into a tex/buffer resource */ |
||||
struct virgl_transfer_put { |
||||
VIRGLPHYSICAL data; |
||||
uint32_t res_handle; |
||||
struct virgl_box box; |
||||
uint32_t level; |
||||
uint32_t stride; |
||||
uint32_t layer_stride; |
||||
uint32_t ctx_id; |
||||
}; |
||||
|
||||
struct virgl_transfer_get { |
||||
VIRGLPHYSICAL data; |
||||
uint32_t res_handle; |
||||
struct virgl_box box; |
||||
int level; |
||||
uint32_t stride; |
||||
uint32_t layer_stride; |
||||
uint32_t ctx_id; |
||||
}; |
||||
|
||||
struct virgl_flush_buffer { |
||||
uint32_t res_handle; |
||||
uint32_t ctx_id; |
||||
struct virgl_box box; |
||||
}; |
||||
|
||||
struct virgl_set_scanout { |
||||
uint32_t res_handle; |
||||
uint32_t ctx_id; |
||||
struct virgl_box box; |
||||
}; |
||||
|
||||
/* is 0,0 for this resource at the top or the bottom?
|
||||
kernel console and X want this, 3D driver doesn't. |
||||
this flag should only be used with formats that are |
||||
renderable. otherwise the context will get locked up. |
||||
*/ |
||||
#define VIRGL_RESOURCE_Y_0_TOP (1 << 0) |
||||
struct virgl_resource_create { |
||||
uint32_t handle; |
||||
uint32_t target; |
||||
uint32_t format; |
||||
uint32_t bind; |
||||
uint32_t width; |
||||
uint32_t height; |
||||
uint32_t depth; |
||||
uint32_t array_size; |
||||
uint32_t last_level; |
||||
uint32_t nr_samples; |
||||
uint32_t nr_sg_entries; |
||||
uint32_t flags; |
||||
}; |
||||
|
||||
struct virgl_resource_unref { |
||||
uint32_t res_handle; |
||||
}; |
||||
|
||||
struct virgl_cmd_submit { |
||||
uint64_t phy_addr; |
||||
uint32_t size; |
||||
uint32_t ctx_id; |
||||
}; |
||||
|
||||
struct virgl_cmd_context { |
||||
uint32_t handle; |
||||
uint32_t pad; |
||||
}; |
||||
|
||||
struct virgl_cmd_context_create { |
||||
uint32_t handle; |
||||
uint32_t nlen; |
||||
char debug_name[64]; |
||||
}; |
||||
|
||||
struct virgl_cmd_resource_context { |
||||
uint32_t resource; |
||||
uint32_t ctx_id; |
||||
}; |
||||
|
||||
struct virgl_cmd_resource_attach_sg { |
||||
uint32_t resource; |
||||
uint32_t num_sg_entries; |
||||
}; |
||||
|
||||
struct virgl_cmd_resource_invalidate_sg { |
||||
uint32_t resource; |
||||
}; |
||||
|
||||
struct virgl_cmd_get_cap { |
||||
uint32_t cap_set; |
||||
uint32_t cap_set_version; |
||||
VIRGLPHYSICAL offset; |
||||
}; |
||||
|
||||
struct virgl_iov_entry { |
||||
VIRGLPHYSICAL addr; |
||||
uint32_t length; |
||||
uint32_t pad; |
||||
}; |
||||
|
||||
struct virgl_cmd_timestamp_get { |
||||
uint64_t timestamp; |
||||
}; |
||||
|
||||
#define VIRGL_COMMAND_EMIT_FENCE (1 << 0) |
||||
|
||||
struct virgl_command { |
||||
uint32_t type; |
||||
uint32_t flags; |
||||
uint64_t fence_id; |
||||
union virgl_cmds { |
||||
struct virgl_cmd_context ctx; |
||||
struct virgl_cmd_context_create ctx_create; |
||||
struct virgl_resource_create res_create; |
||||
struct virgl_transfer_put transfer_put; |
||||
struct virgl_transfer_get transfer_get; |
||||
struct virgl_cmd_submit cmd_submit; |
||||
struct virgl_set_scanout set_scanout; |
||||
struct virgl_flush_buffer flush_buffer; |
||||
struct virgl_resource_unref res_unref; |
||||
struct virgl_cmd_resource_context res_ctx; |
||||
|
||||
struct virgl_cmd_resource_attach_sg attach_sg; |
||||
struct virgl_cmd_resource_invalidate_sg inval_sg; |
||||
struct virgl_cmd_get_cap get_cap; |
||||
struct virgl_cmd_timestamp_get get_timestamp; |
||||
} u; |
||||
}; |
||||
|
||||
/* formats known by the HW device - based on gallium subset */ |
||||
enum virgl_formats { |
||||
VIRGL_FORMAT_B8G8R8A8_UNORM = 1, |
||||
VIRGL_FORMAT_B8G8R8X8_UNORM = 2, |
||||
VIRGL_FORMAT_A8R8G8B8_UNORM = 3, |
||||
VIRGL_FORMAT_X8R8G8B8_UNORM = 4, |
||||
VIRGL_FORMAT_B5G5R5A1_UNORM = 5, |
||||
VIRGL_FORMAT_B4G4R4A4_UNORM = 6, |
||||
VIRGL_FORMAT_B5G6R5_UNORM = 7, |
||||
VIRGL_FORMAT_L8_UNORM = 9, /**< ubyte luminance */ |
||||
VIRGL_FORMAT_A8_UNORM = 10, /**< ubyte alpha */ |
||||
VIRGL_FORMAT_L8A8_UNORM = 12, /**< ubyte alpha, luminance */ |
||||
VIRGL_FORMAT_L16_UNORM = 13, /**< ushort luminance */ |
||||
|
||||
VIRGL_FORMAT_Z16_UNORM = 16, |
||||
VIRGL_FORMAT_Z32_UNORM = 17, |
||||
VIRGL_FORMAT_Z32_FLOAT = 18, |
||||
VIRGL_FORMAT_Z24_UNORM_S8_UINT = 19, |
||||
VIRGL_FORMAT_S8_UINT_Z24_UNORM = 20, |
||||
VIRGL_FORMAT_Z24X8_UNORM = 21, |
||||
VIRGL_FORMAT_S8_UINT = 23, /**< ubyte stencil */ |
||||
|
||||
VIRGL_FORMAT_R32_FLOAT = 28, |
||||
VIRGL_FORMAT_R32G32_FLOAT = 29, |
||||
VIRGL_FORMAT_R32G32B32_FLOAT = 30, |
||||
VIRGL_FORMAT_R32G32B32A32_FLOAT = 31, |
||||
|
||||
VIRGL_FORMAT_R16_UNORM = 48, |
||||
VIRGL_FORMAT_R16G16_UNORM = 49, |
||||
|
||||
VIRGL_FORMAT_R16G16B16A16_UNORM = 51, |
||||
|
||||
VIRGL_FORMAT_R16_SNORM = 56, |
||||
VIRGL_FORMAT_R16G16_SNORM = 57, |
||||
VIRGL_FORMAT_R16G16B16A16_SNORM = 59, |
||||
|
||||
VIRGL_FORMAT_R8_UNORM = 64, |
||||
VIRGL_FORMAT_R8G8_UNORM = 65, |
||||
|
||||
VIRGL_FORMAT_R8G8B8A8_UNORM = 67, |
||||
|
||||
VIRGL_FORMAT_R8_SNORM = 74, |
||||
VIRGL_FORMAT_R8G8_SNORM = 75, |
||||
VIRGL_FORMAT_R8G8B8_SNORM = 76, |
||||
VIRGL_FORMAT_R8G8B8A8_SNORM = 77, |
||||
|
||||
VIRGL_FORMAT_R16_FLOAT = 91, |
||||
VIRGL_FORMAT_R16G16_FLOAT = 92, |
||||
VIRGL_FORMAT_R16G16B16_FLOAT = 93, |
||||
VIRGL_FORMAT_R16G16B16A16_FLOAT = 94, |
||||
|
||||
VIRGL_FORMAT_L8_SRGB = 95, |
||||
VIRGL_FORMAT_L8A8_SRGB = 96, |
||||
VIRGL_FORMAT_B8G8R8A8_SRGB = 100, |
||||
VIRGL_FORMAT_B8G8R8X8_SRGB = 101, |
||||
|
||||
/* compressed formats */ |
||||
VIRGL_FORMAT_DXT1_RGB = 105, |
||||
VIRGL_FORMAT_DXT1_RGBA = 106, |
||||
VIRGL_FORMAT_DXT3_RGBA = 107, |
||||
VIRGL_FORMAT_DXT5_RGBA = 108, |
||||
|
||||
/* sRGB, compressed */ |
||||
VIRGL_FORMAT_DXT1_SRGB = 109, |
||||
VIRGL_FORMAT_DXT1_SRGBA = 110, |
||||
VIRGL_FORMAT_DXT3_SRGBA = 111, |
||||
VIRGL_FORMAT_DXT5_SRGBA = 112, |
||||
|
||||
/* rgtc compressed */ |
||||
VIRGL_FORMAT_RGTC1_UNORM = 113, |
||||
VIRGL_FORMAT_RGTC1_SNORM = 114, |
||||
VIRGL_FORMAT_RGTC2_UNORM = 115, |
||||
VIRGL_FORMAT_RGTC2_SNORM = 116, |
||||
|
||||
VIRGL_FORMAT_A8B8G8R8_UNORM = 121, |
||||
VIRGL_FORMAT_B5G5R5X1_UNORM = 122, |
||||
VIRGL_FORMAT_R11G11B10_FLOAT = 124, |
||||
VIRGL_FORMAT_R9G9B9E5_FLOAT = 125, |
||||
VIRGL_FORMAT_Z32_FLOAT_S8X24_UINT = 126, |
||||
|
||||
VIRGL_FORMAT_B10G10R10A2_UNORM = 131, |
||||
VIRGL_FORMAT_R8G8B8X8_UNORM = 134, |
||||
VIRGL_FORMAT_B4G4R4X4_UNORM = 135, |
||||
VIRGL_FORMAT_B2G3R3_UNORM = 139, |
||||
|
||||
VIRGL_FORMAT_L16A16_UNORM = 140, |
||||
VIRGL_FORMAT_A16_UNORM = 141, |
||||
|
||||
VIRGL_FORMAT_A8_SNORM = 147, |
||||
VIRGL_FORMAT_L8_SNORM = 148, |
||||
VIRGL_FORMAT_L8A8_SNORM = 149, |
||||
|
||||
VIRGL_FORMAT_A16_SNORM = 151, |
||||
VIRGL_FORMAT_L16_SNORM = 152, |
||||
VIRGL_FORMAT_L16A16_SNORM = 153, |
||||
|
||||
VIRGL_FORMAT_A16_FLOAT = 155, |
||||
VIRGL_FORMAT_L16_FLOAT = 156, |
||||
VIRGL_FORMAT_L16A16_FLOAT = 157, |
||||
|
||||
VIRGL_FORMAT_A32_FLOAT = 159, |
||||
VIRGL_FORMAT_L32_FLOAT = 160, |
||||
VIRGL_FORMAT_L32A32_FLOAT = 161, |
||||
|
||||
VIRGL_FORMAT_R8_UINT = 177, |
||||
VIRGL_FORMAT_R8G8_UINT = 178, |
||||
VIRGL_FORMAT_R8G8B8_UINT = 179, |
||||
VIRGL_FORMAT_R8G8B8A8_UINT = 180, |
||||
|
||||
VIRGL_FORMAT_R8_SINT = 181, |
||||
VIRGL_FORMAT_R8G8_SINT = 182, |
||||
VIRGL_FORMAT_R8G8B8_SINT = 183, |
||||
VIRGL_FORMAT_R8G8B8A8_SINT = 184, |
||||
|
||||
VIRGL_FORMAT_R16_UINT = 185, |
||||
VIRGL_FORMAT_R16G16_UINT = 186, |
||||
VIRGL_FORMAT_R16G16B16_UINT = 187, |
||||
VIRGL_FORMAT_R16G16B16A16_UINT = 188, |
||||
|
||||
VIRGL_FORMAT_R16_SINT = 189, |
||||
VIRGL_FORMAT_R16G16_SINT = 190, |
||||
VIRGL_FORMAT_R16G16B16_SINT = 191, |
||||
VIRGL_FORMAT_R16G16B16A16_SINT = 192, |
||||
VIRGL_FORMAT_R32_UINT = 193, |
||||
VIRGL_FORMAT_R32G32_UINT = 194, |
||||
VIRGL_FORMAT_R32G32B32_UINT = 195, |
||||
VIRGL_FORMAT_R32G32B32A32_UINT = 196, |
||||
|
||||
VIRGL_FORMAT_R32_SINT = 197, |
||||
VIRGL_FORMAT_R32G32_SINT = 198, |
||||
VIRGL_FORMAT_R32G32B32_SINT = 199, |
||||
VIRGL_FORMAT_R32G32B32A32_SINT = 200, |
||||
|
||||
VIRGL_FORMAT_A8_UINT = 201, |
||||
VIRGL_FORMAT_L8_UINT = 203, |
||||
VIRGL_FORMAT_L8A8_UINT = 204, |
||||
|
||||
VIRGL_FORMAT_A8_SINT = 205, |
||||
VIRGL_FORMAT_L8_SINT = 207, |
||||
VIRGL_FORMAT_L8A8_SINT = 208, |
||||
|
||||
VIRGL_FORMAT_A16_UINT = 209, |
||||
VIRGL_FORMAT_L16_UINT = 211, |
||||
VIRGL_FORMAT_L16A16_UINT = 212, |
||||
|
||||
VIRGL_FORMAT_A16_SINT = 213, |
||||
VIRGL_FORMAT_L16_SINT = 215, |
||||
VIRGL_FORMAT_L16A16_SINT = 216, |
||||
|
||||
VIRGL_FORMAT_A32_UINT = 217, |
||||
VIRGL_FORMAT_L32_UINT = 219, |
||||
VIRGL_FORMAT_L32A32_UINT = 220, |
||||
|
||||
VIRGL_FORMAT_A32_SINT = 221, |
||||
VIRGL_FORMAT_L32_SINT = 223, |
||||
VIRGL_FORMAT_L32A32_SINT = 224, |
||||
|
||||
VIRGL_FORMAT_B10G10R10A2_UINT = 225,
|
||||
VIRGL_FORMAT_R8G8B8X8_SNORM = 229, |
||||
|
||||
VIRGL_FORMAT_R8G8B8X8_SRGB = 230, |
||||
|
||||
VIRGL_FORMAT_B10G10R10X2_UNORM = 233, |
||||
VIRGL_FORMAT_R16G16B16X16_UNORM = 234, |
||||
VIRGL_FORMAT_R16G16B16X16_SNORM = 235, |
||||
VIRGL_FORMAT_MAX, |
||||
}; |
||||
|
||||
struct virgl_caps_bool_set1 { |
||||
unsigned indep_blend_enable:1; |
||||
unsigned indep_blend_func:1; |
||||
unsigned cube_map_array:1; |
||||
unsigned shader_stencil_export:1; |
||||
unsigned conditional_render:1; |
||||
unsigned start_instance:1; |
||||
unsigned primitive_restart:1; |
||||
unsigned blend_eq_sep:1; |
||||
unsigned instanceid:1; |
||||
unsigned vertex_element_instance_divisor:1; |
||||
unsigned seamless_cube_map:1; |
||||
unsigned occlusion_query:1; |
||||
unsigned timer_query:1; |
||||
unsigned streamout_pause_resume:1; |
||||
unsigned texture_buffer_object:1; |
||||
unsigned texture_multisample:1; |
||||
unsigned fragment_coord_conventions:1; |
||||
}; |
||||
|
||||
/* endless expansion capabilites - current gallium has 252 formats */ |
||||
struct virgl_supported_format_mask { |
||||
uint32_t bitmask[16]; |
||||
}; |
||||
/* capabilities set 2 - version 1 - 32-bit and float values */ |
||||
struct virgl_caps_v1 { |
||||
uint32_t max_version; |
||||
struct virgl_supported_format_mask sampler; |
||||
struct virgl_supported_format_mask render; |
||||
struct virgl_supported_format_mask depthstencil; |
||||
struct virgl_supported_format_mask vertexbuffer; |
||||
struct virgl_caps_bool_set1 bset; |
||||
uint32_t glsl_level; |
||||
uint32_t max_texture_array_layers; |
||||
uint32_t max_streamout_buffers; |
||||
uint32_t max_dual_source_render_targets; |
||||
uint32_t max_render_targets; |
||||
uint32_t max_samples; |
||||
}; |
||||
|
||||
union virgl_caps { |
||||
uint32_t max_version; |
||||
struct virgl_caps_v1 v1; |
||||
}; |
||||
|
||||
enum virgl_errors { |
||||
VIRGL_ERROR_NONE, |
||||
VIRGL_ERROR_UNKNOWN, |
||||
VIRGL_ERROR_UNKNOWN_RESOURCE_FORMAT, |
||||
}; |
||||
|
||||
enum virgl_ctx_errors { |
||||
VIRGL_ERROR_CTX_NONE, |
||||
VIRGL_ERROR_CTX_UNKNOWN, |
||||
VIRGL_ERROR_CTX_ILLEGAL_SHADER, |
||||
VIRGL_ERROR_CTX_ILLEGAL_HANDLE, |
||||
VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, |
||||
VIRGL_ERROR_CTX_ILLEGAL_SURFACE, |
||||
VIRGL_ERROR_CTX_ILLEGAL_VERTEX_FORMAT, |
||||
}; |
||||
|
||||
#endif |
@ -0,0 +1,70 @@ |
||||
#ifndef GRAW_PROTOCOL_H |
||||
#define GRAW_PROTOCOL_H |
||||
|
||||
#define VIRGL_QUERY_STATE_NEW 0 |
||||
#define VIRGL_QUERY_STATE_DONE 1 |
||||
#define VIRGL_QUERY_STATE_WAIT_HOST 2 |
||||
|
||||
struct virgl_host_query_state { |
||||
uint32_t query_state; |
||||
uint32_t result_size; |
||||
uint64_t result; |
||||
}; |
||||
|
||||
enum virgl_object_type { |
||||
VIRGL_OBJECT_NULL, |
||||
VIRGL_OBJECT_BLEND, |
||||
VIRGL_OBJECT_RASTERIZER, |
||||
VIRGL_OBJECT_DSA, |
||||
VIRGL_OBJECT_VS, |
||||
VIRGL_OBJECT_FS, |
||||
VIRGL_OBJECT_VERTEX_ELEMENTS, |
||||
VIRGL_OBJECT_SAMPLER_VIEW, |
||||
VIRGL_OBJECT_SAMPLER_STATE, |
||||
VIRGL_OBJECT_SURFACE, |
||||
VIRGL_OBJECT_QUERY, |
||||
VIRGL_OBJECT_STREAMOUT_TARGET, |
||||
VIRGL_MAX_OBJECTS, |
||||
}; |
||||
|
||||
/* context cmds to be encoded in the command stream */ |
||||
enum virgl_context_cmd { |
||||
VIRGL_CCMD_NOP = 0, |
||||
VIRGL_CCMD_CREATE_OBJECT = 1, |
||||
VIRGL_CCMD_BIND_OBJECT, |
||||
VIRGL_CCMD_DESTROY_OBJECT, |
||||
VIRGL_CCMD_SET_VIEWPORT_STATE, |
||||
VIRGL_CCMD_SET_FRAMEBUFFER_STATE, |
||||
VIRGL_CCMD_SET_VERTEX_BUFFERS, |
||||
VIRGL_CCMD_CLEAR, |
||||
VIRGL_CCMD_DRAW_VBO, |
||||
VIRGL_CCMD_RESOURCE_INLINE_WRITE, |
||||
VIRGL_CCMD_SET_SAMPLER_VIEWS, |
||||
VIRGL_CCMD_SET_INDEX_BUFFER, |
||||
VIRGL_CCMD_SET_CONSTANT_BUFFER, |
||||
VIRGL_CCMD_SET_STENCIL_REF, |
||||
VIRGL_CCMD_SET_BLEND_COLOR, |
||||
VIRGL_CCMD_SET_SCISSOR_STATE, |
||||
VIRGL_CCMD_BLIT, |
||||
VIRGL_CCMD_RESOURCE_COPY_REGION, |
||||
VIRGL_CCMD_BIND_SAMPLER_STATES, |
||||
VIRGL_CCMD_BEGIN_QUERY, |
||||
VIRGL_CCMD_END_QUERY, |
||||
VIRGL_CCMD_GET_QUERY_RESULT, |
||||
VIRGL_CCMD_SET_POLYGON_STIPPLE, |
||||
VIRGL_CCMD_SET_CLIP_STATE, |
||||
VIRGL_CCMD_SET_SAMPLE_MASK, |
||||
VIRGL_CCMD_SET_STREAMOUT_TARGETS, |
||||
VIRGL_CCMD_SET_QUERY_STATE, |
||||
VIRGL_CCMD_SET_RENDER_CONDITION, |
||||
}; |
||||
|
||||
/*
|
||||
8-bit cmd headers |
||||
8-bit object type |
||||
16-bit length |
||||
*/ |
||||
|
||||
#define VIRGL_CMD0(cmd, obj, len) ((cmd) | ((obj) << 8) | ((len) << 16)) |
||||
|
||||
#endif |
@ -0,0 +1,52 @@ |
||||
/* library interface from QEMU to virglrenderer */ |
||||
|
||||
#ifndef VIRGLRENDERER_H |
||||
#define VIRGLRENDERER_H |
||||
|
||||
#include <stdint.h> |
||||
|
||||
struct virgl_iovec; |
||||
|
||||
#define VIRGL_EXPORT __attribute__((visibility("default"))) |
||||
|
||||
typedef void *virgl_gl_context; |
||||
|
||||
struct virgl_renderer_callbacks { |
||||
int version; |
||||
void (*write_fence)(void *cookie, uint32_t fence); |
||||
|
||||
int (*map_iov)(struct virgl_iovec *iov, uint64_t addr); |
||||
void (*unmap_iov)(struct virgl_iovec *iov); |
||||
|
||||
/* interact with GL implementation */ |
||||
virgl_gl_context (*create_gl_context)(void *cookie, int scanout_idx); |
||||
void (*destroy_gl_context)(void *cookie, virgl_gl_context ctx); |
||||
int (*make_current)(void *cookie, int scanout_idx, virgl_gl_context ctx); |
||||
|
||||
/* */ |
||||
void (*rect_update)(void *cookie, int idx, int x, int y, int width, int height); |
||||
void (*scanout_resource_info)(void *cookie, int idx, uint32_t tex_id, uint32_t flags, |
||||
uint32_t stride, uint32_t width, uint32_t height, uint32_t format); |
||||
void (*scanout_rect_info)(void *cookie, int idx, uint32_t tex_id, |
||||
int x, int y, |
||||
uint32_t width, uint32_t height); |
||||
}; |
||||
|
||||
/* virtio-gpu compatible interface */ |
||||
#define VIRGL_RENDERER_USE_EGL 1 |
||||
|
||||
VIRGL_EXPORT int virgl_renderer_init(void *cookie, int flags, struct virgl_renderer_callbacks *cb); |
||||
VIRGL_EXPORT void virgl_renderer_poll(void); /* force fences */ |
||||
|
||||
VIRGL_EXPORT int virgl_renderer_process_vcmd(void *cmd, struct virgl_iovec *iov, unsigned int num_iovs); |
||||
|
||||
VIRGL_EXPORT void virgl_renderer_set_cursor_info(uint32_t cursor_handle, int x, int y); |
||||
|
||||
/* we need to give qemu the cursor resource contents */ |
||||
VIRGL_EXPORT void *virgl_get_cursor_data(uint32_t resource_id, uint32_t *width, uint32_t *height); |
||||
|
||||
VIRGL_EXPORT void virgl_renderer_get_rect(int idx, struct virgl_iovec *iov, unsigned int num_iovs, |
||||
uint32_t offset, int x, int y, int width, int height); |
||||
|
||||
VIRGL_EXPORT int virgl_renderer_get_fd_for_texture(uint32_t tex_id, int *fd); |
||||
#endif |
@ -0,0 +1,266 @@ |
||||
#ifndef VIRTGPU_HW_H |
||||
#define VIRTGPU_HW_H |
||||
|
||||
#define VIRTGPU_CMD_HAS_RESP (1 << 31) |
||||
#define VIRTGPU_CMD_3D_ONLY (1 << 30) |
||||
enum virtgpu_ctrl_cmd { |
||||
VIRTGPU_CMD_NOP, |
||||
VIRTGPU_CMD_GET_DISPLAY_INFO = (1 | VIRTGPU_CMD_HAS_RESP), |
||||
VIRTGPU_CMD_GET_CAPS = (2 | VIRTGPU_CMD_HAS_RESP), |
||||
VIRTGPU_CMD_RESOURCE_CREATE_2D = 3, |
||||
VIRTGPU_CMD_RESOURCE_UNREF = 4, |
||||
VIRTGPU_CMD_SET_SCANOUT = 5, |
||||
VIRTGPU_CMD_RESOURCE_FLUSH = 6, |
||||
VIRTGPU_CMD_TRANSFER_TO_HOST_2D = 7, |
||||
VIRTGPU_CMD_RESOURCE_ATTACH_BACKING = 8, |
||||
VIRTGPU_CMD_RESOURCE_INVAL_BACKING = 9, |
||||
|
||||
VIRTGPU_CMD_CTX_CREATE = (10 | VIRTGPU_CMD_3D_ONLY), |
||||
VIRTGPU_CMD_CTX_DESTROY = (11 | VIRTGPU_CMD_3D_ONLY), |
||||
VIRTGPU_CMD_CTX_ATTACH_RESOURCE = (12 | VIRTGPU_CMD_3D_ONLY), |
||||
VIRTGPU_CMD_CTX_DETACH_RESOURCE = (13 | VIRTGPU_CMD_3D_ONLY), |
||||
|
||||
VIRTGPU_CMD_RESOURCE_CREATE_3D = (14 | VIRTGPU_CMD_3D_ONLY), |
||||
|
||||
VIRTGPU_CMD_TRANSFER_TO_HOST_3D = (15 | VIRTGPU_CMD_3D_ONLY), |
||||
VIRTGPU_CMD_TRANSFER_FROM_HOST_3D = (16 | VIRTGPU_CMD_3D_ONLY), |
||||
|
||||
VIRTGPU_CMD_SUBMIT_3D = (17 | VIRTGPU_CMD_3D_ONLY), |
||||
}; |
||||
|
||||
enum virtgpu_ctrl_event { |
||||
VIRTGPU_EVENT_NOP, |
||||
VIRTGPU_EVENT_ERROR, |
||||
VIRTGPU_EVENT_DISPLAY_CHANGE, |
||||
}; |
||||
|
||||
/* data passed in the cursor vq */ |
||||
struct virtgpu_hw_cursor_page { |
||||
uint32_t cursor_x, cursor_y; |
||||
uint32_t cursor_hot_x, cursor_hot_y; |
||||
uint32_t cursor_id; |
||||
}; |
||||
|
||||
struct virtgpu_resource_unref { |
||||
uint32_t resource_id; |
||||
}; |
||||
|
||||
/* create a simple 2d resource with a format */ |
||||
struct virtgpu_resource_create_2d { |
||||
uint32_t resource_id; |
||||
uint32_t format; |
||||
uint32_t width; |
||||
uint32_t height; |
||||
}; |
||||
|
||||
struct virtgpu_set_scanout { |
||||
uint32_t scanout_id; |
||||
uint32_t resource_id; |
||||
uint32_t width; |
||||
uint32_t height; |
||||
uint32_t x; |
||||
uint32_t y; |
||||
}; |
||||
|
||||
struct virtgpu_resource_flush { |
||||
uint32_t resource_id; |
||||
uint32_t width; |
||||
uint32_t height; |
||||
uint32_t x; |
||||
uint32_t y; |
||||
}; |
||||
|
||||
/* simple transfer to_host */ |
||||
struct virtgpu_transfer_to_host_2d { |
||||
uint32_t resource_id; |
||||
uint32_t offset; |
||||
uint32_t width; |
||||
uint32_t height; |
||||
uint32_t x; |
||||
uint32_t y; |
||||
}; |
||||
|
||||
struct virtgpu_mem_entry { |
||||
uint64_t addr; |
||||
uint32_t length; |
||||
uint32_t pad; |
||||
}; |
||||
|
||||
struct virtgpu_resource_attach_backing { |
||||
uint32_t resource_id; |
||||
uint32_t nr_entries; |
||||
}; |
||||
|
||||
struct virtgpu_resource_inval_backing { |
||||
uint32_t resource_id; |
||||
}; |
||||
|
||||
#define VIRTGPU_MAX_SCANOUTS 16 |
||||
struct virtgpu_display_info { |
||||
uint32_t num_scanouts; |
||||
struct { |
||||
uint32_t enabled; |
||||
uint32_t width; |
||||
uint32_t height; |
||||
uint32_t x; |
||||
uint32_t y; |
||||
uint32_t flags; |
||||
} pmodes[VIRTGPU_MAX_SCANOUTS]; |
||||
}; |
||||
|
||||
|
||||
/* 3d related */ |
||||
struct virtgpu_box { |
||||
uint32_t x, y, z; |
||||
uint32_t w, h, d; |
||||
}; |
||||
|
||||
struct virtgpu_transfer_to_host_3d { |
||||
uint64_t data; |
||||
uint32_t resource_id; |
||||
uint32_t level; |
||||
struct virtgpu_box box; |
||||
uint32_t stride; |
||||
uint32_t layer_stride; |
||||
uint32_t ctx_id; |
||||
}; |
||||
|
||||
struct virtgpu_transfer_from_host_3d { |
||||
uint64_t data; |
||||
uint32_t resource_id; |
||||
uint32_t level; |
||||
struct virtgpu_box box; |
||||
uint32_t stride; |
||||
uint32_t layer_stride; |
||||
uint32_t ctx_id; |
||||
}; |
||||
|
||||
#define VIRTGPU_RESOURCE_FLAG_Y_0_TOP (1 << 0) |
||||
struct virtgpu_resource_create_3d { |
||||
uint32_t resource_id; |
||||
uint32_t target; |
||||
uint32_t format; |
||||
uint32_t bind; |
||||
uint32_t width; |
||||
uint32_t height; |
||||
uint32_t depth; |
||||
uint32_t array_size; |
||||
uint32_t last_level; |
||||
uint32_t nr_samples; |
||||
uint32_t flags; |
||||
}; |
||||
|
||||
struct virtgpu_ctx_create { |
||||
uint32_t ctx_id; |
||||
uint32_t nlen; |
||||
char debug_name[64]; |
||||
}; |
||||
|
||||
struct virtgpu_ctx_destroy { |
||||
uint32_t ctx_id; |
||||
}; |
||||
|
||||
struct virtgpu_ctx_resource { |
||||
uint32_t resource_id; |
||||
uint32_t ctx_id; |
||||
}; |
||||
|
||||
struct virtgpu_cmd_submit { |
||||
uint64_t phy_addr; |
||||
uint32_t size; |
||||
uint32_t ctx_id; |
||||
}; |
||||
|
||||
struct virtgpu_caps_bool_set1 { |
||||
unsigned indep_blend_enable:1; |
||||
unsigned indep_blend_func:1; |
||||
unsigned cube_map_array:1; |
||||
unsigned shader_stencil_export:1; |
||||
unsigned conditional_render:1; |
||||
unsigned start_instance:1; |
||||
unsigned primitive_restart:1; |
||||
unsigned blend_eq_sep:1; |
||||
unsigned instanceid:1; |
||||
unsigned vertex_element_instance_divisor:1; |
||||
unsigned seamless_cube_map:1; |
||||
unsigned occlusion_query:1; |
||||
unsigned timer_query:1; |
||||
unsigned streamout_pause_resume:1; |
||||
}; |
||||
|
||||
/* endless expansion capabilites - current gallium has 252 formats */ |
||||
struct virtgpu_supported_format_mask { |
||||
uint32_t bitmask[16]; |
||||
}; |
||||
/* capabilities set 2 - version 1 - 32-bit and float values */ |
||||
struct virtgpu_caps_v1 { |
||||
uint32_t max_version; |
||||
struct virtgpu_supported_format_mask sampler; |
||||
struct virtgpu_supported_format_mask render; |
||||
struct virtgpu_supported_format_mask depthstencil; |
||||
struct virtgpu_supported_format_mask vertexbuffer; |
||||
struct virtgpu_caps_bool_set1 bset; |
||||
uint32_t glsl_level; |
||||
uint32_t max_texture_array_layers; |
||||
uint32_t max_streamout_buffers; |
||||
uint32_t max_dual_source_render_targets; |
||||
uint32_t max_render_targets; |
||||
|
||||
}; |
||||
|
||||
union virtgpu_caps { |
||||
uint32_t max_version; |
||||
struct virtgpu_caps_v1 v1; |
||||
}; |
||||
|
||||
struct virtgpu_cmd_get_cap { |
||||
uint32_t cap_set; |
||||
uint32_t cap_set_version; |
||||
}; |
||||
|
||||
#define VIRTGPU_COMMAND_EMIT_FENCE (1 << 0) |
||||
|
||||
struct virtgpu_command { |
||||
uint32_t type; |
||||
uint32_t flags; |
||||
uint64_t fence_id; |
||||
union virtgpu_cmds { |
||||
struct virtgpu_resource_create_2d resource_create_2d; |
||||
struct virtgpu_resource_unref resource_unref; |
||||
struct virtgpu_resource_flush resource_flush; |
||||
struct virtgpu_set_scanout set_scanout; |
||||
struct virtgpu_transfer_to_host_2d transfer_to_host_2d; |
||||
struct virtgpu_resource_attach_backing resource_attach_backing; |
||||
struct virtgpu_resource_inval_backing resource_inval_backing; |
||||
|
||||
struct virtgpu_cmd_submit cmd_submit; |
||||
struct virtgpu_ctx_create ctx_create; |
||||
struct virtgpu_ctx_destroy ctx_destroy; |
||||
struct virtgpu_ctx_resource ctx_resource; |
||||
struct virtgpu_resource_create_3d resource_create_3d; |
||||
struct virtgpu_transfer_to_host_3d transfer_to_host_3d; |
||||
struct virtgpu_transfer_from_host_3d transfer_from_host_3d; |
||||
|
||||
struct virtgpu_cmd_get_cap get_cap; |
||||
} u; |
||||
}; |
||||
|
||||
struct virtgpu_response { |
||||
uint32_t type; |
||||
uint32_t flags; |
||||
union virtgpu_resps { |
||||
struct virtgpu_display_info display_info; |
||||
union virtgpu_caps caps; |
||||
} u; |
||||
}; |
||||
|
||||
struct virtgpu_event { |
||||
uint32_t type; |
||||
uint32_t err_code; |
||||
union virtgpu_events { |
||||
struct virtgpu_display_info display_info; |
||||
} u; |
||||
}; |
||||
|
||||
|
||||
#endif |
@ -0,0 +1,182 @@ |
||||
#include <stdio.h> |
||||
#include "util/u_pointer.h" |
||||
#include "util/u_memory.h" |
||||
#include "util/u_hash_table.h" |
||||
|
||||
#include "vrend_object.h" |
||||
|
||||
struct vrend_object_types { |
||||
void (*unref)(void *); |
||||
} obj_types[VIRGL_MAX_OBJECTS]; |
||||
|
||||
void vrend_object_set_destroy_callback(int type, void (*cb)(void *))
|
||||
{ |
||||
obj_types[type].unref = cb; |
||||
} |
||||
|
||||
static unsigned |
||||
hash_func(void *key) |
||||
{ |
||||
intptr_t ip = pointer_to_intptr(key); |
||||
return (unsigned)(ip & 0xffffffff); |
||||
} |
||||
|
||||
static int |
||||
compare(void *key1, void *key2) |
||||
{ |
||||
if (key1 < key2) |
||||
return -1; |
||||
if (key1 > key2) |
||||
return 1; |
||||
else |
||||
return 0; |
||||
} |
||||
|
||||
static struct util_hash_table *res_hash; |
||||
|
||||
struct vrend_object { |
||||
enum virgl_object_type type; |
||||
uint32_t handle; |
||||
void *data; |
||||
}; |
||||
|
||||
struct util_hash_table *vrend_object_init_ctx_table(void) |
||||
{ |
||||
struct util_hash_table *ctx_hash; |
||||
ctx_hash = util_hash_table_create(hash_func, compare); |
||||
return ctx_hash; |
||||
} |
||||
|
||||
static void vrend_object_free(struct vrend_object *obj) |
||||
{ |
||||
if (obj_types[obj->type].unref) |
||||
obj_types[obj->type].unref(obj->data); |
||||
else { |
||||
/* for objects with no callback just free them */ |
||||
free(obj->data); |
||||
} |
||||
free(obj); |
||||
} |
||||
|
||||
static enum pipe_error free_cb(void *key, void *value, void *data) |
||||
{ |
||||
struct vrend_object *obj = value; |
||||
vrend_object_free(obj); |
||||
return PIPE_OK; |
||||
} |
||||
|
||||
void vrend_object_fini_ctx_table(struct util_hash_table *ctx_hash) |
||||
{ |
||||
if (!ctx_hash) |
||||
return; |
||||
|
||||
util_hash_table_foreach(ctx_hash, free_cb, NULL); |
||||
util_hash_table_destroy(ctx_hash); |
||||
} |
||||
|
||||
void |
||||
vrend_object_init_resource_table(void) |
||||
{ |
||||
if (!res_hash) |
||||
res_hash = util_hash_table_create(hash_func, compare); |
||||
} |
||||
|
||||
void vrend_object_fini_resource_table(void) |
||||
{ |
||||
if (res_hash) |
||||
util_hash_table_destroy(res_hash); |
||||
res_hash = NULL; |
||||
} |
||||
|
||||
uint32_t |
||||
vrend_object_insert(struct util_hash_table *handle_hash, |
||||
void *data, uint32_t length, uint32_t handle, enum virgl_object_type type) |
||||
{ |
||||
struct vrend_object *obj = CALLOC_STRUCT(vrend_object); |
||||
|
||||
if (!obj) |
||||
return 0; |
||||
obj->handle = handle; |
||||
obj->data = data; |
||||
obj->type = type; |
||||
util_hash_table_set(handle_hash, intptr_to_pointer(obj->handle), obj); |
||||
return obj->handle; |
||||
} |
||||
|
||||
void |
||||
vrend_object_remove(struct util_hash_table *handle_hash, |
||||
uint32_t handle, enum virgl_object_type type) |
||||
{ |
||||
struct vrend_object *obj; |
||||
|
||||
obj = util_hash_table_get(handle_hash, intptr_to_pointer(handle)); |
||||
if (!obj) |
||||
return; |
||||
util_hash_table_remove(handle_hash, intptr_to_pointer(handle)); |
||||
|
||||
|
||||
vrend_object_free(obj); |
||||
} |
||||
|
||||
void *vrend_object_lookup(struct util_hash_table *handle_hash, |
||||
uint32_t handle, enum virgl_object_type type) |
||||
{ |
||||
struct vrend_object *obj; |
||||
|
||||
obj = util_hash_table_get(handle_hash, intptr_to_pointer(handle)); |
||||
if (!obj) { |
||||
return NULL; |
||||
} |
||||
|
||||
if (obj->type != type) |
||||
return NULL; |
||||
return obj->data; |
||||
} |
||||
|
||||
void *vrend_resource_insert(void *data, uint32_t length, uint32_t handle) |
||||
{ |
||||
struct vrend_object *obj = CALLOC_STRUCT(vrend_object); |
||||
|
||||
if (!obj) |
||||
return 0; |
||||
obj->handle = handle; |
||||
obj->data = data; |
||||
util_hash_table_set(res_hash, intptr_to_pointer(obj->handle), obj); |
||||
return obj->handle; |
||||
} |
||||
|
||||
void vrend_resource_remove(uint32_t handle) |
||||
{ |
||||
struct vrend_object *obj; |
||||
|
||||
obj = util_hash_table_get(res_hash, intptr_to_pointer(handle)); |
||||
if (!obj) |
||||
return; |
||||
util_hash_table_remove(res_hash, intptr_to_pointer(handle)); |
||||
free(obj); |
||||
} |
||||
|
||||
void *vrend_resource_lookup(uint32_t handle, uint32_t ctx_id) |
||||
{ |
||||
struct vrend_object *obj; |
||||
obj = util_hash_table_get(res_hash, intptr_to_pointer(handle)); |
||||
if (!obj) |
||||
return NULL; |
||||
return obj->data; |
||||
} |
||||
|
||||
static enum pipe_error dump_cb(void *key, void *value, void *data) |
||||
{ |
||||
struct vrend_object *obj = value; |
||||
fprintf(stderr, "%p: %d %d\n", key, obj->type, obj->handle); |
||||
graw_renderer_dump_resource(obj->data); |
||||
return PIPE_OK; |
||||
} |
||||
|
||||
void vrend_object_dumb_ctx_table(struct util_hash_table *ctx_hash) |
||||
{ |
||||
if (!ctx_hash) |
||||
return; |
||||
|
||||
util_hash_table_foreach(ctx_hash, dump_cb, NULL); |
||||
} |
@ -0,0 +1,27 @@ |
||||
#ifndef VREND_OBJECT_H |
||||
#define VREND_OBJECT_H |
||||
|
||||
#include "virgl_protocol.h" |
||||
|
||||
void vrend_object_init_resource_table(void); |
||||
void vrend_object_fini_resource_table(void); |
||||
|
||||
struct grend_context; |
||||
|
||||
struct util_hash_table *vrend_object_init_ctx_table(void); |
||||
void vrend_object_fini_ctx_table(struct util_hash_table *ctx_hash); |
||||
|
||||
void vrend_object_remove(struct util_hash_table *handle_hash, uint32_t handle, enum virgl_object_type obj); |
||||
void *vrend_object_lookup(struct util_hash_table *handle_hash, uint32_t handle, enum virgl_object_type obj); |
||||
uint32_t vrend_object_insert(struct util_hash_table *handle_hash, void *data, uint32_t length, uint32_t handle, enum virgl_object_type type); |
||||
|
||||
/* resources are global */ |
||||
void *vrend_resource_insert(void *data, uint32_t length, uint32_t handle); |
||||
void vrend_resource_remove(uint32_t handle); |
||||
void *vrend_resource_lookup(uint32_t handle, uint32_t ctx_id); |
||||
|
||||
void vrend_object_set_destroy_callback(int type, void (*cb)(void *)); |
||||
|
||||
void vrend_object_dumb_ctx_table(struct util_hash_table *ctx_hash); |
||||
void graw_renderer_dump_resource(void *data); |
||||
#endif |
@ -0,0 +1,10 @@ |
||||
prefix=@prefix@ |
||||
exec_prefix=@exec_prefix@ |
||||
libdir=@libdir@ |
||||
includedir=@includedir@ |
||||
|
||||
Name: virglrenderer |
||||
Description: virgl GL renderer |
||||
Version: @PACKAGE_VERSION@ |
||||
Cflags: -I${includedir} |
||||
Libs: -L${libdir} -lvirglrenderer |
Loading…
Reference in new issue