initial import of standalone renderer

macos/master
Dave Airlie 11 years ago
commit a3a2c64cd6
  1. 28
      Makefile.am
  2. 14
      autogen.sh
  3. 48
      configure.ac
  4. 50
      src/Makefile.am
  5. 18
      src/gallium/auxiliary/Makefile.am
  6. 20
      src/gallium/auxiliary/Makefile.sources
  7. 80
      src/gallium/auxiliary/os/os_memory.h
  8. 72
      src/gallium/auxiliary/os/os_memory_aligned.h
  9. 92
      src/gallium/auxiliary/os/os_memory_debug.h
  10. 76
      src/gallium/auxiliary/os/os_memory_stdc.h
  11. 91
      src/gallium/auxiliary/os/os_misc.c
  12. 95
      src/gallium/auxiliary/os/os_misc.h
  13. 87
      src/gallium/auxiliary/os/os_mman.h
  14. 92
      src/gallium/auxiliary/os/os_process.c
  15. 40
      src/gallium/auxiliary/os/os_process.h
  16. 300
      src/gallium/auxiliary/os/os_thread.h
  17. 94
      src/gallium/auxiliary/os/os_time.c
  18. 101
      src/gallium/auxiliary/os/os_time.h
  19. 1373
      src/gallium/auxiliary/tgsi/tgsi_build.c
  20. 118
      src/gallium/auxiliary/tgsi/tgsi_build.h
  21. 763
      src/gallium/auxiliary/tgsi/tgsi_dump.c
  22. 86
      src/gallium/auxiliary/tgsi/tgsi_dump.h
  23. 4555
      src/gallium/auxiliary/tgsi/tgsi_exec.c
  24. 463
      src/gallium/auxiliary/tgsi/tgsi_exec.h
  25. 375
      src/gallium/auxiliary/tgsi/tgsi_info.c
  26. 113
      src/gallium/auxiliary/tgsi/tgsi_info.h
  27. 90
      src/gallium/auxiliary/tgsi/tgsi_iterate.c
  28. 80
      src/gallium/auxiliary/tgsi/tgsi_iterate.h
  29. 234
      src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h
  30. 307
      src/gallium/auxiliary/tgsi/tgsi_parse.c
  31. 159
      src/gallium/auxiliary/tgsi/tgsi_parse.h
  32. 52
      src/gallium/auxiliary/tgsi/tgsi_sanity.h
  33. 409
      src/gallium/auxiliary/tgsi/tgsi_scan.c
  34. 110
      src/gallium/auxiliary/tgsi/tgsi_scan.h
  35. 201
      src/gallium/auxiliary/tgsi/tgsi_strings.c
  36. 71
      src/gallium/auxiliary/tgsi/tgsi_strings.h
  37. 1662
      src/gallium/auxiliary/tgsi/tgsi_text.c
  38. 49
      src/gallium/auxiliary/tgsi/tgsi_text.h
  39. 250
      src/gallium/auxiliary/tgsi/tgsi_transform.c
  40. 96
      src/gallium/auxiliary/tgsi/tgsi_transform.h
  41. 1810
      src/gallium/auxiliary/tgsi/tgsi_ureg.c
  42. 1324
      src/gallium/auxiliary/tgsi/tgsi_ureg.h
  43. 463
      src/gallium/auxiliary/tgsi/tgsi_util.c
  44. 89
      src/gallium/auxiliary/tgsi/tgsi_util.h
  45. 349
      src/gallium/auxiliary/util/u_atomic.h
  46. 117
      src/gallium/auxiliary/util/u_bitmask.h
  47. 80
      src/gallium/auxiliary/util/u_box.h
  48. 730
      src/gallium/auxiliary/util/u_debug.c
  49. 459
      src/gallium/auxiliary/util/u_debug.h
  50. 91
      src/gallium/auxiliary/util/u_debug_describe.c
  51. 51
      src/gallium/auxiliary/util/u_debug_describe.h
  52. 63
      src/gallium/auxiliary/util/u_debug_refcnt.h
  53. 147
      src/gallium/auxiliary/util/u_double_list.h
  54. 1234
      src/gallium/auxiliary/util/u_format.h
  55. 46
      src/gallium/auxiliary/util/u_format_etc.h
  56. 108
      src/gallium/auxiliary/util/u_format_latc.h
  57. 134
      src/gallium/auxiliary/util/u_format_other.h
  58. 114
      src/gallium/auxiliary/util/u_format_rgtc.h
  59. 218
      src/gallium/auxiliary/util/u_format_s3tc.h
  60. 178
      src/gallium/auxiliary/util/u_format_srgb.c
  61. 147
      src/gallium/auxiliary/util/u_format_srgb.h
  62. 33985
      src/gallium/auxiliary/util/u_format_table.c
  63. 364
      src/gallium/auxiliary/util/u_format_yuv.h
  64. 212
      src/gallium/auxiliary/util/u_format_zs.h
  65. 131
      src/gallium/auxiliary/util/u_half.h
  66. 96
      src/gallium/auxiliary/util/u_hash_table.h
  67. 644
      src/gallium/auxiliary/util/u_inlines.h
  68. 868
      src/gallium/auxiliary/util/u_math.h
  69. 100
      src/gallium/auxiliary/util/u_memory.h
  70. 651
      src/gallium/auxiliary/util/u_pack_color.h
  71. 130
      src/gallium/auxiliary/util/u_pointer.h
  72. 268
      src/gallium/auxiliary/util/u_prim.h
  73. 232
      src/gallium/auxiliary/util/u_string.h
  74. 111
      src/gallium/auxiliary/util/u_surface.h
  75. 165
      src/gallium/auxiliary/util/u_tile.h
  76. 109
      src/gallium/auxiliary/util/u_transfer.h
  77. 162
      src/graw_cursor.c
  78. 24
      src/graw_cursor.h
  79. 911
      src/graw_decode.c
  80. 13
      src/graw_decode.h
  81. 307
      src/graw_formats.c
  82. 22
      src/graw_iov.h
  83. 4486
      src/graw_renderer.c
  84. 322
      src/graw_renderer.h
  85. 72
      src/graw_renderer_helper.c
  86. 1612
      src/graw_shader.c
  87. 40
      src/graw_shader.h
  88. 426
      src/graw_virtio_lib_renderer.c
  89. 256
      src/iov.c
  90. 16
      src/virgl_egl.h
  91. 295
      src/virgl_egl_context.c
  92. 17
      src/virgl_helper.h
  93. 390
      src/virgl_hw.h
  94. 70
      src/virgl_protocol.h
  95. 52
      src/virglrenderer.h
  96. 266
      src/virtgpu_hw.h
  97. 182
      src/vrend_object.c
  98. 27
      src/vrend_object.h
  99. 10
      virglrenderer.pc.in

@ -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(
&reg->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…
Cancel
Save