From a3a2c64cd662c64bf46e028dcd10121028c25a8c Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 31 Mar 2014 14:07:58 +1000 Subject: [PATCH] initial import of standalone renderer --- Makefile.am | 28 + autogen.sh | 14 + configure.ac | 48 + src/Makefile.am | 50 + src/gallium/auxiliary/Makefile.am | 18 + src/gallium/auxiliary/Makefile.sources | 20 + src/gallium/auxiliary/os/os_memory.h | 80 + src/gallium/auxiliary/os/os_memory_aligned.h | 72 + src/gallium/auxiliary/os/os_memory_debug.h | 92 + src/gallium/auxiliary/os/os_memory_stdc.h | 76 + src/gallium/auxiliary/os/os_misc.c | 91 + src/gallium/auxiliary/os/os_misc.h | 95 + src/gallium/auxiliary/os/os_mman.h | 87 + src/gallium/auxiliary/os/os_process.c | 92 + src/gallium/auxiliary/os/os_process.h | 40 + src/gallium/auxiliary/os/os_thread.h | 300 + src/gallium/auxiliary/os/os_time.c | 94 + src/gallium/auxiliary/os/os_time.h | 101 + src/gallium/auxiliary/tgsi/tgsi_build.c | 1373 + src/gallium/auxiliary/tgsi/tgsi_build.h | 118 + src/gallium/auxiliary/tgsi/tgsi_dump.c | 763 + src/gallium/auxiliary/tgsi/tgsi_dump.h | 86 + src/gallium/auxiliary/tgsi/tgsi_exec.c | 4555 +++ src/gallium/auxiliary/tgsi/tgsi_exec.h | 463 + src/gallium/auxiliary/tgsi/tgsi_info.c | 375 + src/gallium/auxiliary/tgsi/tgsi_info.h | 113 + src/gallium/auxiliary/tgsi/tgsi_iterate.c | 90 + src/gallium/auxiliary/tgsi/tgsi_iterate.h | 80 + src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h | 234 + src/gallium/auxiliary/tgsi/tgsi_parse.c | 307 + src/gallium/auxiliary/tgsi/tgsi_parse.h | 159 + src/gallium/auxiliary/tgsi/tgsi_sanity.h | 52 + src/gallium/auxiliary/tgsi/tgsi_scan.c | 409 + src/gallium/auxiliary/tgsi/tgsi_scan.h | 110 + src/gallium/auxiliary/tgsi/tgsi_strings.c | 201 + src/gallium/auxiliary/tgsi/tgsi_strings.h | 71 + src/gallium/auxiliary/tgsi/tgsi_text.c | 1662 + src/gallium/auxiliary/tgsi/tgsi_text.h | 49 + src/gallium/auxiliary/tgsi/tgsi_transform.c | 250 + src/gallium/auxiliary/tgsi/tgsi_transform.h | 96 + src/gallium/auxiliary/tgsi/tgsi_ureg.c | 1810 + src/gallium/auxiliary/tgsi/tgsi_ureg.h | 1324 + src/gallium/auxiliary/tgsi/tgsi_util.c | 463 + src/gallium/auxiliary/tgsi/tgsi_util.h | 89 + src/gallium/auxiliary/util/u_atomic.h | 349 + src/gallium/auxiliary/util/u_bitmask.h | 117 + src/gallium/auxiliary/util/u_box.h | 80 + src/gallium/auxiliary/util/u_debug.c | 730 + src/gallium/auxiliary/util/u_debug.h | 459 + src/gallium/auxiliary/util/u_debug_describe.c | 91 + src/gallium/auxiliary/util/u_debug_describe.h | 51 + src/gallium/auxiliary/util/u_debug_refcnt.h | 63 + src/gallium/auxiliary/util/u_double_list.h | 147 + src/gallium/auxiliary/util/u_format.h | 1234 + src/gallium/auxiliary/util/u_format_etc.h | 46 + src/gallium/auxiliary/util/u_format_latc.h | 108 + src/gallium/auxiliary/util/u_format_other.h | 134 + src/gallium/auxiliary/util/u_format_rgtc.h | 114 + src/gallium/auxiliary/util/u_format_s3tc.h | 218 + src/gallium/auxiliary/util/u_format_srgb.c | 178 + src/gallium/auxiliary/util/u_format_srgb.h | 147 + src/gallium/auxiliary/util/u_format_table.c | 33985 ++++++++++++++++ src/gallium/auxiliary/util/u_format_yuv.h | 364 + src/gallium/auxiliary/util/u_format_zs.h | 212 + src/gallium/auxiliary/util/u_half.h | 131 + src/gallium/auxiliary/util/u_hash_table.h | 96 + src/gallium/auxiliary/util/u_inlines.h | 644 + src/gallium/auxiliary/util/u_math.h | 868 + src/gallium/auxiliary/util/u_memory.h | 100 + src/gallium/auxiliary/util/u_pack_color.h | 651 + src/gallium/auxiliary/util/u_pointer.h | 130 + src/gallium/auxiliary/util/u_prim.h | 268 + src/gallium/auxiliary/util/u_string.h | 232 + src/gallium/auxiliary/util/u_surface.h | 111 + src/gallium/auxiliary/util/u_tile.h | 165 + src/gallium/auxiliary/util/u_transfer.h | 109 + src/graw_cursor.c | 162 + src/graw_cursor.h | 24 + src/graw_decode.c | 911 + src/graw_decode.h | 13 + src/graw_formats.c | 307 + src/graw_iov.h | 22 + src/graw_renderer.c | 4486 ++ src/graw_renderer.h | 322 + src/graw_renderer_helper.c | 72 + src/graw_shader.c | 1612 + src/graw_shader.h | 40 + src/graw_virtio_lib_renderer.c | 426 + src/iov.c | 256 + src/virgl_egl.h | 16 + src/virgl_egl_context.c | 295 + src/virgl_helper.h | 17 + src/virgl_hw.h | 390 + src/virgl_protocol.h | 70 + src/virglrenderer.h | 52 + src/virtgpu_hw.h | 266 + src/vrend_object.c | 182 + src/vrend_object.h | 27 + virglrenderer.pc.in | 10 + 99 files changed, 69010 insertions(+) create mode 100644 Makefile.am create mode 100755 autogen.sh create mode 100644 configure.ac create mode 100644 src/Makefile.am create mode 100644 src/gallium/auxiliary/Makefile.am create mode 100644 src/gallium/auxiliary/Makefile.sources create mode 100644 src/gallium/auxiliary/os/os_memory.h create mode 100644 src/gallium/auxiliary/os/os_memory_aligned.h create mode 100644 src/gallium/auxiliary/os/os_memory_debug.h create mode 100644 src/gallium/auxiliary/os/os_memory_stdc.h create mode 100644 src/gallium/auxiliary/os/os_misc.c create mode 100644 src/gallium/auxiliary/os/os_misc.h create mode 100644 src/gallium/auxiliary/os/os_mman.h create mode 100644 src/gallium/auxiliary/os/os_process.c create mode 100644 src/gallium/auxiliary/os/os_process.h create mode 100644 src/gallium/auxiliary/os/os_thread.h create mode 100644 src/gallium/auxiliary/os/os_time.c create mode 100644 src/gallium/auxiliary/os/os_time.h create mode 100644 src/gallium/auxiliary/tgsi/tgsi_build.c create mode 100644 src/gallium/auxiliary/tgsi/tgsi_build.h create mode 100644 src/gallium/auxiliary/tgsi/tgsi_dump.c create mode 100644 src/gallium/auxiliary/tgsi/tgsi_dump.h create mode 100644 src/gallium/auxiliary/tgsi/tgsi_exec.c create mode 100644 src/gallium/auxiliary/tgsi/tgsi_exec.h create mode 100644 src/gallium/auxiliary/tgsi/tgsi_info.c create mode 100644 src/gallium/auxiliary/tgsi/tgsi_info.h create mode 100644 src/gallium/auxiliary/tgsi/tgsi_iterate.c create mode 100644 src/gallium/auxiliary/tgsi/tgsi_iterate.h create mode 100644 src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h create mode 100644 src/gallium/auxiliary/tgsi/tgsi_parse.c create mode 100644 src/gallium/auxiliary/tgsi/tgsi_parse.h create mode 100644 src/gallium/auxiliary/tgsi/tgsi_sanity.h create mode 100644 src/gallium/auxiliary/tgsi/tgsi_scan.c create mode 100644 src/gallium/auxiliary/tgsi/tgsi_scan.h create mode 100644 src/gallium/auxiliary/tgsi/tgsi_strings.c create mode 100644 src/gallium/auxiliary/tgsi/tgsi_strings.h create mode 100644 src/gallium/auxiliary/tgsi/tgsi_text.c create mode 100644 src/gallium/auxiliary/tgsi/tgsi_text.h create mode 100644 src/gallium/auxiliary/tgsi/tgsi_transform.c create mode 100644 src/gallium/auxiliary/tgsi/tgsi_transform.h create mode 100644 src/gallium/auxiliary/tgsi/tgsi_ureg.c create mode 100644 src/gallium/auxiliary/tgsi/tgsi_ureg.h create mode 100644 src/gallium/auxiliary/tgsi/tgsi_util.c create mode 100644 src/gallium/auxiliary/tgsi/tgsi_util.h create mode 100644 src/gallium/auxiliary/util/u_atomic.h create mode 100644 src/gallium/auxiliary/util/u_bitmask.h create mode 100644 src/gallium/auxiliary/util/u_box.h create mode 100644 src/gallium/auxiliary/util/u_debug.c create mode 100644 src/gallium/auxiliary/util/u_debug.h create mode 100644 src/gallium/auxiliary/util/u_debug_describe.c create mode 100644 src/gallium/auxiliary/util/u_debug_describe.h create mode 100644 src/gallium/auxiliary/util/u_debug_refcnt.h create mode 100644 src/gallium/auxiliary/util/u_double_list.h create mode 100644 src/gallium/auxiliary/util/u_format.h create mode 100644 src/gallium/auxiliary/util/u_format_etc.h create mode 100644 src/gallium/auxiliary/util/u_format_latc.h create mode 100644 src/gallium/auxiliary/util/u_format_other.h create mode 100644 src/gallium/auxiliary/util/u_format_rgtc.h create mode 100644 src/gallium/auxiliary/util/u_format_s3tc.h create mode 100644 src/gallium/auxiliary/util/u_format_srgb.c create mode 100644 src/gallium/auxiliary/util/u_format_srgb.h create mode 100644 src/gallium/auxiliary/util/u_format_table.c create mode 100644 src/gallium/auxiliary/util/u_format_yuv.h create mode 100644 src/gallium/auxiliary/util/u_format_zs.h create mode 100644 src/gallium/auxiliary/util/u_half.h create mode 100644 src/gallium/auxiliary/util/u_hash_table.h create mode 100644 src/gallium/auxiliary/util/u_inlines.h create mode 100644 src/gallium/auxiliary/util/u_math.h create mode 100644 src/gallium/auxiliary/util/u_memory.h create mode 100644 src/gallium/auxiliary/util/u_pack_color.h create mode 100644 src/gallium/auxiliary/util/u_pointer.h create mode 100644 src/gallium/auxiliary/util/u_prim.h create mode 100644 src/gallium/auxiliary/util/u_string.h create mode 100644 src/gallium/auxiliary/util/u_surface.h create mode 100644 src/gallium/auxiliary/util/u_tile.h create mode 100644 src/gallium/auxiliary/util/u_transfer.h create mode 100644 src/graw_cursor.c create mode 100644 src/graw_cursor.h create mode 100644 src/graw_decode.c create mode 100644 src/graw_decode.h create mode 100644 src/graw_formats.c create mode 100644 src/graw_iov.h create mode 100644 src/graw_renderer.c create mode 100644 src/graw_renderer.h create mode 100644 src/graw_renderer_helper.c create mode 100644 src/graw_shader.c create mode 100644 src/graw_shader.h create mode 100644 src/graw_virtio_lib_renderer.c create mode 100644 src/iov.c create mode 100644 src/virgl_egl.h create mode 100644 src/virgl_egl_context.c create mode 100644 src/virgl_helper.h create mode 100644 src/virgl_hw.h create mode 100644 src/virgl_protocol.h create mode 100644 src/virglrenderer.h create mode 100644 src/virtgpu_hw.h create mode 100644 src/vrend_object.c create mode 100644 src/vrend_object.h create mode 100644 virglrenderer.pc.in diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..74d3b98 --- /dev/null +++ b/Makefile.am @@ -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 diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..626d213 --- /dev/null +++ b/autogen.sh @@ -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 diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..c8e510c --- /dev/null +++ b/configure.ac @@ -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 + diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..64204c6 --- /dev/null +++ b/src/Makefile.am @@ -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 diff --git a/src/gallium/auxiliary/Makefile.am b/src/gallium/auxiliary/Makefile.am new file mode 100644 index 0000000..811d435 --- /dev/null +++ b/src/gallium/auxiliary/Makefile.am @@ -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) + diff --git a/src/gallium/auxiliary/Makefile.sources b/src/gallium/auxiliary/Makefile.sources new file mode 100644 index 0000000..92802c9 --- /dev/null +++ b/src/gallium/auxiliary/Makefile.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 + + diff --git a/src/gallium/auxiliary/os/os_memory.h b/src/gallium/auxiliary/os/os_memory.h new file mode 100644 index 0000000..46a6b6e --- /dev/null +++ b/src/gallium/auxiliary/os/os_memory.h @@ -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_ */ diff --git a/src/gallium/auxiliary/os/os_memory_aligned.h b/src/gallium/auxiliary/os/os_memory_aligned.h new file mode 100644 index 0000000..72c5cf6 --- /dev/null +++ b/src/gallium/auxiliary/os/os_memory_aligned.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); + } +} diff --git a/src/gallium/auxiliary/os/os_memory_debug.h b/src/gallium/auxiliary/os/os_memory_debug.h new file mode 100644 index 0000000..9a487de --- /dev/null +++ b/src/gallium/auxiliary/os/os_memory_debug.h @@ -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 */ diff --git a/src/gallium/auxiliary/os/os_memory_stdc.h b/src/gallium/auxiliary/os/os_memory_stdc.h new file mode 100644 index 0000000..806e536 --- /dev/null +++ b/src/gallium/auxiliary/os/os_memory_stdc.h @@ -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 + +#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 + +#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 diff --git a/src/gallium/auxiliary/os/os_misc.c b/src/gallium/auxiliary/os/os_misc.c new file mode 100644 index 0000000..447e720 --- /dev/null +++ b/src/gallium/auxiliary/os/os_misc.c @@ -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 + + +#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 +#include + +#else + +#include +#include + +#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); +} + diff --git a/src/gallium/auxiliary/os/os_misc.h b/src/gallium/auxiliary/os/os_misc.h new file mode 100644 index 0000000..5029ab9 --- /dev/null +++ b/src/gallium/auxiliary/os/os_misc.h @@ -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 /* for kill() */ +# include /* 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_ */ diff --git a/src/gallium/auxiliary/os/os_mman.h b/src/gallium/auxiliary/os/os_mman.h new file mode 100644 index 0000000..b48eb05 --- /dev/null +++ b/src/gallium/auxiliary/os/os_mman.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 + */ + +#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 +#else +# error Unsupported OS +#endif + +#if defined(PIPE_OS_ANDROID) +# include /* 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_ */ diff --git a/src/gallium/auxiliary/os/os_process.c b/src/gallium/auxiliary/os/os_process.c new file mode 100644 index 0000000..ef38e1d --- /dev/null +++ b/src/gallium/auxiliary/os/os_process.c @@ -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 +#elif defined(__GLIBC__) +# include +#elif defined(PIPE_OS_BSD) || defined(PIPE_OS_APPLE) +# include +#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; + } +} diff --git a/src/gallium/auxiliary/os/os_process.h b/src/gallium/auxiliary/os/os_process.h new file mode 100644 index 0000000..0d50ddc --- /dev/null +++ b/src/gallium/auxiliary/os/os_process.h @@ -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 */ diff --git a/src/gallium/auxiliary/os/os_thread.h b/src/gallium/auxiliary/os/os_thread.h new file mode 100644 index 0000000..ff46a89 --- /dev/null +++ b/src/gallium/auxiliary/os/os_thread.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 +#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_ */ diff --git a/src/gallium/auxiliary/os/os_time.c b/src/gallium/auxiliary/os/os_time.c new file mode 100644 index 0000000..f7e4ca4 --- /dev/null +++ b/src/gallium/auxiliary/os/os_time.c @@ -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 + */ + + +#include "pipe/p_config.h" + +#if defined(PIPE_OS_UNIX) +# include /* timeval */ +# include /* timeval */ +#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) +# include +#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 diff --git a/src/gallium/auxiliary/os/os_time.h b/src/gallium/auxiliary/os/os_time.h new file mode 100644 index 0000000..4fab03c --- /dev/null +++ b/src/gallium/auxiliary/os/os_time.h @@ -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 + */ + +#ifndef _OS_TIME_H_ +#define _OS_TIME_H_ + + +#include "pipe/p_config.h" + +#if defined(PIPE_OS_UNIX) +# include /* 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_ */ diff --git a/src/gallium/auxiliary/tgsi/tgsi_build.c b/src/gallium/auxiliary/tgsi/tgsi_build.c new file mode 100644 index 0000000..7621b6a --- /dev/null +++ b/src/gallium/auxiliary/tgsi/tgsi_build.c @@ -0,0 +1,1373 @@ +/************************************************************************** + * + * 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_format.h" +#include "pipe/p_shader_tokens.h" +#include "tgsi_build.h" +#include "tgsi_parse.h" + + +/* + * header + */ + +struct tgsi_header +tgsi_build_header( void ) +{ + struct tgsi_header header; + + header.HeaderSize = 1; + header.BodySize = 0; + + return header; +} + +static void +header_headersize_grow( struct tgsi_header *header ) +{ + assert( header->HeaderSize < 0xFF ); + assert( header->BodySize == 0 ); + + header->HeaderSize++; +} + +static void +header_bodysize_grow( struct tgsi_header *header ) +{ + assert( header->BodySize < 0xFFFFFF ); + + header->BodySize++; +} + +struct tgsi_processor +tgsi_build_processor( + unsigned type, + struct tgsi_header *header ) +{ + struct tgsi_processor processor; + + processor.Processor = type; + processor.Padding = 0; + + header_headersize_grow( header ); + + return processor; +} + +/* + * declaration + */ + +static void +declaration_grow( + struct tgsi_declaration *declaration, + struct tgsi_header *header ) +{ + assert( declaration->NrTokens < 0xFF ); + + declaration->NrTokens++; + + header_bodysize_grow( header ); +} + +static struct tgsi_declaration +tgsi_default_declaration( void ) +{ + struct tgsi_declaration declaration; + + declaration.Type = TGSI_TOKEN_TYPE_DECLARATION; + declaration.NrTokens = 1; + declaration.File = TGSI_FILE_NULL; + declaration.UsageMask = TGSI_WRITEMASK_XYZW; + declaration.Interpolate = 0; + declaration.Dimension = 0; + declaration.Semantic = 0; + declaration.Invariant = 0; + declaration.Local = 0; + declaration.Array = 0; + declaration.Padding = 0; + + return declaration; +} + +static struct tgsi_declaration +tgsi_build_declaration( + unsigned file, + unsigned usage_mask, + unsigned interpolate, + unsigned dimension, + unsigned semantic, + unsigned invariant, + unsigned local, + unsigned array, + struct tgsi_header *header ) +{ + struct tgsi_declaration declaration; + + assert( file < TGSI_FILE_COUNT ); + assert( interpolate < TGSI_INTERPOLATE_COUNT ); + + declaration = tgsi_default_declaration(); + declaration.File = file; + declaration.UsageMask = usage_mask; + declaration.Interpolate = interpolate; + declaration.Dimension = dimension; + declaration.Semantic = semantic; + declaration.Invariant = invariant; + declaration.Local = local; + declaration.Array = array; + header_bodysize_grow( header ); + + return declaration; +} + +static struct tgsi_declaration_range +tgsi_default_declaration_range( void ) +{ + struct tgsi_declaration_range dr; + + dr.First = 0; + dr.Last = 0; + + return dr; +} + +static struct tgsi_declaration_range +tgsi_build_declaration_range( + unsigned first, + unsigned last, + struct tgsi_declaration *declaration, + struct tgsi_header *header ) +{ + struct tgsi_declaration_range declaration_range; + + assert( last >= first ); + assert( last <= 0xFFFF ); + + declaration_range.First = first; + declaration_range.Last = last; + + declaration_grow( declaration, header ); + + return declaration_range; +} + +static struct tgsi_declaration_dimension +tgsi_build_declaration_dimension(unsigned index_2d, + struct tgsi_declaration *declaration, + struct tgsi_header *header) +{ + struct tgsi_declaration_dimension dd; + + assert(index_2d <= 0xFFFF); + + dd.Index2D = index_2d; + dd.Padding = 0; + + declaration_grow(declaration, header); + + return dd; +} + +static struct tgsi_declaration_interp +tgsi_default_declaration_interp( void ) +{ + struct tgsi_declaration_interp di; + + di.Interpolate = TGSI_INTERPOLATE_CONSTANT; + di.Centroid = 0; + di.CylindricalWrap = 0; + di.Padding = 0; + + return di; +} + +static struct tgsi_declaration_interp +tgsi_build_declaration_interp(unsigned interpolate, + unsigned centroid, + unsigned cylindrical_wrap, + struct tgsi_declaration *declaration, + struct tgsi_header *header) +{ + struct tgsi_declaration_interp di; + + di.Interpolate = interpolate; + di.Centroid = centroid; + di.CylindricalWrap = cylindrical_wrap; + di.Padding = 0; + + declaration_grow(declaration, header); + + return di; +} + +static struct tgsi_declaration_semantic +tgsi_default_declaration_semantic( void ) +{ + struct tgsi_declaration_semantic ds; + + ds.Name = TGSI_SEMANTIC_POSITION; + ds.Index = 0; + ds.Padding = 0; + + return ds; +} + +static struct tgsi_declaration_semantic +tgsi_build_declaration_semantic( + unsigned semantic_name, + unsigned semantic_index, + struct tgsi_declaration *declaration, + struct tgsi_header *header ) +{ + struct tgsi_declaration_semantic ds; + + assert( semantic_name <= TGSI_SEMANTIC_COUNT ); + assert( semantic_index <= 0xFFFF ); + + ds.Name = semantic_name; + ds.Index = semantic_index; + ds.Padding = 0; + + declaration_grow( declaration, header ); + + return ds; +} + +static struct tgsi_declaration_resource +tgsi_default_declaration_resource(void) +{ + struct tgsi_declaration_resource dr; + + dr.Resource = TGSI_TEXTURE_BUFFER; + dr.Raw = 0; + dr.Writable = 0; + dr.Padding = 0; + + return dr; +} + +static struct tgsi_declaration_resource +tgsi_build_declaration_resource(unsigned texture, + unsigned raw, + unsigned writable, + struct tgsi_declaration *declaration, + struct tgsi_header *header) +{ + struct tgsi_declaration_resource dr; + + dr = tgsi_default_declaration_resource(); + dr.Resource = texture; + dr.Raw = raw; + dr.Writable = writable; + + declaration_grow(declaration, header); + + return dr; +} + +static struct tgsi_declaration_sampler_view +tgsi_default_declaration_sampler_view(void) +{ + struct tgsi_declaration_sampler_view dsv; + + dsv.Resource = TGSI_TEXTURE_BUFFER; + dsv.ReturnTypeX = PIPE_TYPE_UNORM; + dsv.ReturnTypeY = PIPE_TYPE_UNORM; + dsv.ReturnTypeZ = PIPE_TYPE_UNORM; + dsv.ReturnTypeW = PIPE_TYPE_UNORM; + + return dsv; +} + +static struct tgsi_declaration_sampler_view +tgsi_build_declaration_sampler_view(unsigned texture, + unsigned return_type_x, + unsigned return_type_y, + unsigned return_type_z, + unsigned return_type_w, + struct tgsi_declaration *declaration, + struct tgsi_header *header) +{ + struct tgsi_declaration_sampler_view dsv; + + dsv = tgsi_default_declaration_sampler_view(); + dsv.Resource = texture; + dsv.ReturnTypeX = return_type_x; + dsv.ReturnTypeY = return_type_y; + dsv.ReturnTypeZ = return_type_z; + dsv.ReturnTypeW = return_type_w; + + declaration_grow(declaration, header); + + return dsv; +} + + +static struct tgsi_declaration_array +tgsi_default_declaration_array( void ) +{ + struct tgsi_declaration_array a; + + a.ArrayID = 0; + a.Padding = 0; + + return a; +} + +static struct tgsi_declaration_array +tgsi_build_declaration_array(unsigned arrayid, + struct tgsi_declaration *declaration, + struct tgsi_header *header) +{ + struct tgsi_declaration_array da; + + da = tgsi_default_declaration_array(); + da.ArrayID = arrayid; + + declaration_grow(declaration, header); + + return da; +} + +struct tgsi_full_declaration +tgsi_default_full_declaration( void ) +{ + struct tgsi_full_declaration full_declaration; + + full_declaration.Declaration = tgsi_default_declaration(); + full_declaration.Range = tgsi_default_declaration_range(); + full_declaration.Semantic = tgsi_default_declaration_semantic(); + full_declaration.Interp = tgsi_default_declaration_interp(); + full_declaration.Resource = tgsi_default_declaration_resource(); + full_declaration.SamplerView = tgsi_default_declaration_sampler_view(); + full_declaration.Array = tgsi_default_declaration_array(); + + return full_declaration; +} + +unsigned +tgsi_build_full_declaration( + const struct tgsi_full_declaration *full_decl, + struct tgsi_token *tokens, + struct tgsi_header *header, + unsigned maxsize ) +{ + unsigned size = 0; + struct tgsi_declaration *declaration; + struct tgsi_declaration_range *dr; + + if( maxsize <= size ) + return 0; + declaration = (struct tgsi_declaration *) &tokens[size]; + size++; + + *declaration = tgsi_build_declaration( + full_decl->Declaration.File, + full_decl->Declaration.UsageMask, + full_decl->Declaration.Interpolate, + full_decl->Declaration.Dimension, + full_decl->Declaration.Semantic, + full_decl->Declaration.Invariant, + full_decl->Declaration.Local, + full_decl->Declaration.Array, + header ); + + if (maxsize <= size) + return 0; + dr = (struct tgsi_declaration_range *) &tokens[size]; + size++; + + *dr = tgsi_build_declaration_range( + full_decl->Range.First, + full_decl->Range.Last, + declaration, + header ); + + if (full_decl->Declaration.Dimension) { + struct tgsi_declaration_dimension *dd; + + if (maxsize <= size) { + return 0; + } + dd = (struct tgsi_declaration_dimension *)&tokens[size]; + size++; + + *dd = tgsi_build_declaration_dimension(full_decl->Dim.Index2D, + declaration, + header); + } + + if (full_decl->Declaration.Interpolate) { + struct tgsi_declaration_interp *di; + + if (maxsize <= size) { + return 0; + } + di = (struct tgsi_declaration_interp *)&tokens[size]; + size++; + + *di = tgsi_build_declaration_interp(full_decl->Interp.Interpolate, + full_decl->Interp.Centroid, + full_decl->Interp.CylindricalWrap, + declaration, + header); + } + + if( full_decl->Declaration.Semantic ) { + struct tgsi_declaration_semantic *ds; + + if( maxsize <= size ) + return 0; + ds = (struct tgsi_declaration_semantic *) &tokens[size]; + size++; + + *ds = tgsi_build_declaration_semantic( + full_decl->Semantic.Name, + full_decl->Semantic.Index, + declaration, + header ); + } + + if (full_decl->Declaration.File == TGSI_FILE_RESOURCE) { + struct tgsi_declaration_resource *dr; + + if (maxsize <= size) { + return 0; + } + dr = (struct tgsi_declaration_resource *)&tokens[size]; + size++; + + *dr = tgsi_build_declaration_resource(full_decl->Resource.Resource, + full_decl->Resource.Raw, + full_decl->Resource.Writable, + declaration, + header); + } + + if (full_decl->Declaration.File == TGSI_FILE_SAMPLER_VIEW) { + struct tgsi_declaration_sampler_view *dsv; + + if (maxsize <= size) { + return 0; + } + dsv = (struct tgsi_declaration_sampler_view *)&tokens[size]; + size++; + + *dsv = tgsi_build_declaration_sampler_view( + full_decl->SamplerView.Resource, + full_decl->SamplerView.ReturnTypeX, + full_decl->SamplerView.ReturnTypeY, + full_decl->SamplerView.ReturnTypeZ, + full_decl->SamplerView.ReturnTypeW, + declaration, + header); + } + + if (full_decl->Declaration.Array) { + struct tgsi_declaration_array *da; + + if (maxsize <= size) { + return 0; + } + da = (struct tgsi_declaration_array *)&tokens[size]; + size++; + *da = tgsi_build_declaration_array( + full_decl->Array.ArrayID, + declaration, + header); + } + return size; +} + +/* + * immediate + */ + +static struct tgsi_immediate +tgsi_default_immediate( void ) +{ + struct tgsi_immediate immediate; + + immediate.Type = TGSI_TOKEN_TYPE_IMMEDIATE; + immediate.NrTokens = 1; + immediate.DataType = TGSI_IMM_FLOAT32; + immediate.Padding = 0; + + return immediate; +} + +static struct tgsi_immediate +tgsi_build_immediate( + struct tgsi_header *header, + unsigned type ) +{ + struct tgsi_immediate immediate; + + immediate = tgsi_default_immediate(); + immediate.DataType = type; + + header_bodysize_grow( header ); + + return immediate; +} + +struct tgsi_full_immediate +tgsi_default_full_immediate( void ) +{ + struct tgsi_full_immediate fullimm; + + fullimm.Immediate = tgsi_default_immediate(); + fullimm.u[0].Float = 0.0f; + fullimm.u[1].Float = 0.0f; + fullimm.u[2].Float = 0.0f; + fullimm.u[3].Float = 0.0f; + + return fullimm; +} + +static void +immediate_grow( + struct tgsi_immediate *immediate, + struct tgsi_header *header ) +{ + assert( immediate->NrTokens < 0xFF ); + + immediate->NrTokens++; + + header_bodysize_grow( header ); +} + +unsigned +tgsi_build_full_immediate( + const struct tgsi_full_immediate *full_imm, + struct tgsi_token *tokens, + struct tgsi_header *header, + unsigned maxsize ) +{ + unsigned size = 0, i; + struct tgsi_immediate *immediate; + + if( maxsize <= size ) + return 0; + immediate = (struct tgsi_immediate *) &tokens[size]; + size++; + + *immediate = tgsi_build_immediate( header, full_imm->Immediate.DataType ); + + assert( full_imm->Immediate.NrTokens <= 4 + 1 ); + + for( i = 0; i < full_imm->Immediate.NrTokens - 1; i++ ) { + union tgsi_immediate_data *data; + + if( maxsize <= size ) + return 0; + + data = (union tgsi_immediate_data *) &tokens[size]; + *data = full_imm->u[i]; + + immediate_grow( immediate, header ); + size++; + } + + return size; +} + +/* + * instruction + */ + +struct tgsi_instruction +tgsi_default_instruction( void ) +{ + struct tgsi_instruction instruction; + + instruction.Type = TGSI_TOKEN_TYPE_INSTRUCTION; + instruction.NrTokens = 0; + instruction.Opcode = TGSI_OPCODE_MOV; + instruction.Saturate = TGSI_SAT_NONE; + instruction.Predicate = 0; + instruction.NumDstRegs = 1; + instruction.NumSrcRegs = 1; + instruction.Label = 0; + instruction.Texture = 0; + instruction.Padding = 0; + + return instruction; +} + +static struct tgsi_instruction +tgsi_build_instruction(unsigned opcode, + unsigned saturate, + unsigned predicate, + unsigned num_dst_regs, + unsigned num_src_regs, + struct tgsi_header *header) +{ + struct tgsi_instruction instruction; + + assert (opcode <= TGSI_OPCODE_LAST); + assert (saturate <= TGSI_SAT_MINUS_PLUS_ONE); + assert (num_dst_regs <= 3); + assert (num_src_regs <= 15); + + instruction = tgsi_default_instruction(); + instruction.Opcode = opcode; + instruction.Saturate = saturate; + instruction.Predicate = predicate; + instruction.NumDstRegs = num_dst_regs; + instruction.NumSrcRegs = num_src_regs; + + header_bodysize_grow( header ); + + return instruction; +} + +static void +instruction_grow( + struct tgsi_instruction *instruction, + struct tgsi_header *header ) +{ + assert (instruction->NrTokens < 0xFF); + + instruction->NrTokens++; + + header_bodysize_grow( header ); +} + +struct tgsi_instruction_predicate +tgsi_default_instruction_predicate(void) +{ + struct tgsi_instruction_predicate instruction_predicate; + + instruction_predicate.SwizzleX = TGSI_SWIZZLE_X; + instruction_predicate.SwizzleY = TGSI_SWIZZLE_Y; + instruction_predicate.SwizzleZ = TGSI_SWIZZLE_Z; + instruction_predicate.SwizzleW = TGSI_SWIZZLE_W; + instruction_predicate.Negate = 0; + instruction_predicate.Index = 0; + instruction_predicate.Padding = 0; + + return instruction_predicate; +} + +static struct tgsi_instruction_predicate +tgsi_build_instruction_predicate(int index, + unsigned negate, + unsigned swizzleX, + unsigned swizzleY, + unsigned swizzleZ, + unsigned swizzleW, + struct tgsi_instruction *instruction, + struct tgsi_header *header) +{ + struct tgsi_instruction_predicate instruction_predicate; + + instruction_predicate = tgsi_default_instruction_predicate(); + instruction_predicate.SwizzleX = swizzleX; + instruction_predicate.SwizzleY = swizzleY; + instruction_predicate.SwizzleZ = swizzleZ; + instruction_predicate.SwizzleW = swizzleW; + instruction_predicate.Negate = negate; + instruction_predicate.Index = index; + + instruction_grow(instruction, header); + + return instruction_predicate; +} + +static struct tgsi_instruction_label +tgsi_default_instruction_label( void ) +{ + struct tgsi_instruction_label instruction_label; + + instruction_label.Label = 0; + instruction_label.Padding = 0; + + return instruction_label; +} + +static struct tgsi_instruction_label +tgsi_build_instruction_label( + unsigned label, + struct tgsi_token *prev_token, + struct tgsi_instruction *instruction, + struct tgsi_header *header ) +{ + struct tgsi_instruction_label instruction_label; + + instruction_label.Label = label; + instruction_label.Padding = 0; + instruction->Label = 1; + + instruction_grow( instruction, header ); + + return instruction_label; +} + +static struct tgsi_instruction_texture +tgsi_default_instruction_texture( void ) +{ + struct tgsi_instruction_texture instruction_texture; + + instruction_texture.Texture = TGSI_TEXTURE_UNKNOWN; + instruction_texture.NumOffsets = 0; + instruction_texture.Padding = 0; + + return instruction_texture; +} + +static struct tgsi_instruction_texture +tgsi_build_instruction_texture( + unsigned texture, + unsigned num_offsets, + struct tgsi_token *prev_token, + struct tgsi_instruction *instruction, + struct tgsi_header *header ) +{ + struct tgsi_instruction_texture instruction_texture; + + instruction_texture.Texture = texture; + instruction_texture.NumOffsets = num_offsets; + instruction_texture.Padding = 0; + instruction->Texture = 1; + + instruction_grow( instruction, header ); + + return instruction_texture; +} + + +static struct tgsi_texture_offset +tgsi_default_texture_offset( void ) +{ + struct tgsi_texture_offset texture_offset; + + texture_offset.Index = 0; + texture_offset.File = 0; + texture_offset.SwizzleX = 0; + texture_offset.SwizzleY = 0; + texture_offset.SwizzleZ = 0; + texture_offset.Padding = 0; + + return texture_offset; +} + +static struct tgsi_texture_offset +tgsi_build_texture_offset( + int index, int file, int swizzle_x, int swizzle_y, int swizzle_z, + struct tgsi_token *prev_token, + struct tgsi_instruction *instruction, + struct tgsi_header *header ) +{ + struct tgsi_texture_offset texture_offset; + + texture_offset.Index = index; + texture_offset.File = file; + texture_offset.SwizzleX = swizzle_x; + texture_offset.SwizzleY = swizzle_y; + texture_offset.SwizzleZ = swizzle_z; + texture_offset.Padding = 0; + + instruction_grow( instruction, header ); + + return texture_offset; +} + +static struct tgsi_src_register +tgsi_default_src_register( void ) +{ + struct tgsi_src_register src_register; + + src_register.File = TGSI_FILE_NULL; + src_register.SwizzleX = TGSI_SWIZZLE_X; + src_register.SwizzleY = TGSI_SWIZZLE_Y; + src_register.SwizzleZ = TGSI_SWIZZLE_Z; + src_register.SwizzleW = TGSI_SWIZZLE_W; + src_register.Negate = 0; + src_register.Absolute = 0; + src_register.Indirect = 0; + src_register.Dimension = 0; + src_register.Index = 0; + + return src_register; +} + +static struct tgsi_src_register +tgsi_build_src_register( + unsigned file, + unsigned swizzle_x, + unsigned swizzle_y, + unsigned swizzle_z, + unsigned swizzle_w, + unsigned negate, + unsigned absolute, + unsigned indirect, + unsigned dimension, + int index, + struct tgsi_instruction *instruction, + struct tgsi_header *header ) +{ + struct tgsi_src_register src_register; + + assert( file < TGSI_FILE_COUNT ); + assert( swizzle_x <= TGSI_SWIZZLE_W ); + assert( swizzle_y <= TGSI_SWIZZLE_W ); + assert( swizzle_z <= TGSI_SWIZZLE_W ); + assert( swizzle_w <= TGSI_SWIZZLE_W ); + assert( negate <= 1 ); + assert( index >= -0x8000 && index <= 0x7FFF ); + + src_register.File = file; + src_register.SwizzleX = swizzle_x; + src_register.SwizzleY = swizzle_y; + src_register.SwizzleZ = swizzle_z; + src_register.SwizzleW = swizzle_w; + src_register.Negate = negate; + src_register.Absolute = absolute; + src_register.Indirect = indirect; + src_register.Dimension = dimension; + src_register.Index = index; + + instruction_grow( instruction, header ); + + return src_register; +} + +static struct tgsi_ind_register +tgsi_default_ind_register( void ) +{ + struct tgsi_ind_register ind_register; + + ind_register.File = TGSI_FILE_NULL; + ind_register.Index = 0; + ind_register.Swizzle = TGSI_SWIZZLE_X; + ind_register.ArrayID = 0; + + return ind_register; +} + +static struct tgsi_ind_register +tgsi_build_ind_register( + unsigned file, + unsigned swizzle, + int index, + unsigned arrayid, + struct tgsi_instruction *instruction, + struct tgsi_header *header ) +{ + struct tgsi_ind_register ind_register; + + assert( file < TGSI_FILE_COUNT ); + assert( swizzle <= TGSI_SWIZZLE_W ); + assert( index >= -0x8000 && index <= 0x7FFF ); + + ind_register.File = file; + ind_register.Swizzle = swizzle; + ind_register.Index = index; + ind_register.ArrayID = arrayid; + + instruction_grow( instruction, header ); + + return ind_register; +} + +static struct tgsi_dimension +tgsi_default_dimension( void ) +{ + struct tgsi_dimension dimension; + + dimension.Indirect = 0; + dimension.Dimension = 0; + dimension.Padding = 0; + dimension.Index = 0; + + return dimension; +} + +static struct tgsi_full_src_register +tgsi_default_full_src_register( void ) +{ + struct tgsi_full_src_register full_src_register; + + full_src_register.Register = tgsi_default_src_register(); + full_src_register.Indirect = tgsi_default_ind_register(); + full_src_register.Dimension = tgsi_default_dimension(); + full_src_register.DimIndirect = tgsi_default_ind_register(); + + return full_src_register; +} + +static struct tgsi_dimension +tgsi_build_dimension( + unsigned indirect, + unsigned index, + struct tgsi_instruction *instruction, + struct tgsi_header *header ) +{ + struct tgsi_dimension dimension; + + dimension.Indirect = indirect; + dimension.Dimension = 0; + dimension.Padding = 0; + dimension.Index = index; + + instruction_grow( instruction, header ); + + return dimension; +} + +static struct tgsi_dst_register +tgsi_default_dst_register( void ) +{ + struct tgsi_dst_register dst_register; + + dst_register.File = TGSI_FILE_NULL; + dst_register.WriteMask = TGSI_WRITEMASK_XYZW; + dst_register.Indirect = 0; + dst_register.Dimension = 0; + dst_register.Index = 0; + dst_register.Padding = 0; + + return dst_register; +} + +static struct tgsi_dst_register +tgsi_build_dst_register( + unsigned file, + unsigned mask, + unsigned indirect, + unsigned dimension, + int index, + struct tgsi_instruction *instruction, + struct tgsi_header *header ) +{ + struct tgsi_dst_register dst_register; + + assert( file < TGSI_FILE_COUNT ); + assert( mask <= TGSI_WRITEMASK_XYZW ); + assert( index >= -32768 && index <= 32767 ); + + dst_register.File = file; + dst_register.WriteMask = mask; + dst_register.Indirect = indirect; + dst_register.Dimension = dimension; + dst_register.Index = index; + dst_register.Padding = 0; + + instruction_grow( instruction, header ); + + return dst_register; +} + +static struct tgsi_full_dst_register +tgsi_default_full_dst_register( void ) +{ + struct tgsi_full_dst_register full_dst_register; + + full_dst_register.Register = tgsi_default_dst_register(); + full_dst_register.Indirect = tgsi_default_ind_register(); + full_dst_register.Dimension = tgsi_default_dimension(); + full_dst_register.DimIndirect = tgsi_default_ind_register(); + + return full_dst_register; +} + +struct tgsi_full_instruction +tgsi_default_full_instruction( void ) +{ + struct tgsi_full_instruction full_instruction; + unsigned i; + + full_instruction.Instruction = tgsi_default_instruction(); + full_instruction.Predicate = tgsi_default_instruction_predicate(); + full_instruction.Label = tgsi_default_instruction_label(); + full_instruction.Texture = tgsi_default_instruction_texture(); + for( i = 0; i < TGSI_FULL_MAX_TEX_OFFSETS; i++ ) { + full_instruction.TexOffsets[i] = tgsi_default_texture_offset(); + } + for( i = 0; i < TGSI_FULL_MAX_DST_REGISTERS; i++ ) { + full_instruction.Dst[i] = tgsi_default_full_dst_register(); + } + for( i = 0; i < TGSI_FULL_MAX_SRC_REGISTERS; i++ ) { + full_instruction.Src[i] = tgsi_default_full_src_register(); + } + + return full_instruction; +} + +unsigned +tgsi_build_full_instruction( + const struct tgsi_full_instruction *full_inst, + struct tgsi_token *tokens, + struct tgsi_header *header, + unsigned maxsize ) +{ + unsigned size = 0; + unsigned i; + struct tgsi_instruction *instruction; + struct tgsi_token *prev_token; + + if( maxsize <= size ) + return 0; + instruction = (struct tgsi_instruction *) &tokens[size]; + size++; + + *instruction = tgsi_build_instruction(full_inst->Instruction.Opcode, + full_inst->Instruction.Saturate, + full_inst->Instruction.Predicate, + full_inst->Instruction.NumDstRegs, + full_inst->Instruction.NumSrcRegs, + header); + prev_token = (struct tgsi_token *) instruction; + + if (full_inst->Instruction.Predicate) { + struct tgsi_instruction_predicate *instruction_predicate; + + if (maxsize <= size) { + return 0; + } + instruction_predicate = (struct tgsi_instruction_predicate *)&tokens[size]; + size++; + + *instruction_predicate = + tgsi_build_instruction_predicate(full_inst->Predicate.Index, + full_inst->Predicate.Negate, + full_inst->Predicate.SwizzleX, + full_inst->Predicate.SwizzleY, + full_inst->Predicate.SwizzleZ, + full_inst->Predicate.SwizzleW, + instruction, + header); + } + + if (full_inst->Instruction.Label) { + struct tgsi_instruction_label *instruction_label; + + if( maxsize <= size ) + return 0; + instruction_label = + (struct tgsi_instruction_label *) &tokens[size]; + size++; + + *instruction_label = tgsi_build_instruction_label( + full_inst->Label.Label, + prev_token, + instruction, + header ); + prev_token = (struct tgsi_token *) instruction_label; + } + + if (full_inst->Instruction.Texture) { + struct tgsi_instruction_texture *instruction_texture; + + if( maxsize <= size ) + return 0; + instruction_texture = + (struct tgsi_instruction_texture *) &tokens[size]; + size++; + + *instruction_texture = tgsi_build_instruction_texture( + full_inst->Texture.Texture, + full_inst->Texture.NumOffsets, + prev_token, + instruction, + header ); + prev_token = (struct tgsi_token *) instruction_texture; + + for (i = 0; i < full_inst->Texture.NumOffsets; i++) { + struct tgsi_texture_offset *texture_offset; + + if ( maxsize <= size ) + return 0; + texture_offset = (struct tgsi_texture_offset *)&tokens[size]; + size++; + *texture_offset = tgsi_build_texture_offset( + full_inst->TexOffsets[i].Index, + full_inst->TexOffsets[i].File, + full_inst->TexOffsets[i].SwizzleX, + full_inst->TexOffsets[i].SwizzleY, + full_inst->TexOffsets[i].SwizzleZ, + prev_token, + instruction, + header); + prev_token = (struct tgsi_token *) texture_offset; + } + } + for( i = 0; i < full_inst->Instruction.NumDstRegs; i++ ) { + const struct tgsi_full_dst_register *reg = &full_inst->Dst[i]; + struct tgsi_dst_register *dst_register; + + if( maxsize <= size ) + return 0; + dst_register = (struct tgsi_dst_register *) &tokens[size]; + size++; + + *dst_register = tgsi_build_dst_register( + reg->Register.File, + reg->Register.WriteMask, + reg->Register.Indirect, + reg->Register.Dimension, + reg->Register.Index, + instruction, + header ); + + if( reg->Register.Indirect ) { + struct tgsi_ind_register *ind; + + if( maxsize <= size ) + return 0; + ind = (struct tgsi_ind_register *) &tokens[size]; + size++; + + *ind = tgsi_build_ind_register( + reg->Indirect.File, + reg->Indirect.Swizzle, + reg->Indirect.Index, + reg->Indirect.ArrayID, + instruction, + header ); + } + + if( reg->Register.Dimension ) { + struct tgsi_dimension *dim; + + assert( !reg->Dimension.Dimension ); + + if( maxsize <= size ) + return 0; + dim = (struct tgsi_dimension *) &tokens[size]; + size++; + + *dim = tgsi_build_dimension( + reg->Dimension.Indirect, + reg->Dimension.Index, + instruction, + header ); + + if( reg->Dimension.Indirect ) { + struct tgsi_ind_register *ind; + + if( maxsize <= size ) + return 0; + ind = (struct tgsi_ind_register *) &tokens[size]; + size++; + + *ind = tgsi_build_ind_register( + reg->DimIndirect.File, + reg->DimIndirect.Swizzle, + reg->DimIndirect.Index, + reg->DimIndirect.ArrayID, + instruction, + header ); + } + } + } + + for( i = 0; i < full_inst->Instruction.NumSrcRegs; i++ ) { + const struct tgsi_full_src_register *reg = &full_inst->Src[i]; + struct tgsi_src_register *src_register; + + if( maxsize <= size ) + return 0; + src_register = (struct tgsi_src_register *) &tokens[size]; + size++; + + *src_register = tgsi_build_src_register( + reg->Register.File, + reg->Register.SwizzleX, + reg->Register.SwizzleY, + reg->Register.SwizzleZ, + reg->Register.SwizzleW, + reg->Register.Negate, + reg->Register.Absolute, + reg->Register.Indirect, + reg->Register.Dimension, + reg->Register.Index, + instruction, + header ); + + if( reg->Register.Indirect ) { + struct tgsi_ind_register *ind; + + if( maxsize <= size ) + return 0; + ind = (struct tgsi_ind_register *) &tokens[size]; + size++; + + *ind = tgsi_build_ind_register( + reg->Indirect.File, + reg->Indirect.Swizzle, + reg->Indirect.Index, + reg->Indirect.ArrayID, + instruction, + header ); + } + + if( reg->Register.Dimension ) { + struct tgsi_dimension *dim; + + assert( !reg->Dimension.Dimension ); + + if( maxsize <= size ) + return 0; + dim = (struct tgsi_dimension *) &tokens[size]; + size++; + + *dim = tgsi_build_dimension( + reg->Dimension.Indirect, + reg->Dimension.Index, + instruction, + header ); + + if( reg->Dimension.Indirect ) { + struct tgsi_ind_register *ind; + + if( maxsize <= size ) + return 0; + ind = (struct tgsi_ind_register *) &tokens[size]; + size++; + + *ind = tgsi_build_ind_register( + reg->DimIndirect.File, + reg->DimIndirect.Swizzle, + reg->DimIndirect.Index, + reg->DimIndirect.ArrayID, + instruction, + header ); + } + } + } + + return size; +} + +static struct tgsi_property +tgsi_default_property( void ) +{ + struct tgsi_property property; + + property.Type = TGSI_TOKEN_TYPE_PROPERTY; + property.NrTokens = 1; + property.PropertyName = TGSI_PROPERTY_GS_INPUT_PRIM; + property.Padding = 0; + + return property; +} + +static struct tgsi_property +tgsi_build_property(unsigned property_name, + struct tgsi_header *header) +{ + struct tgsi_property property; + + property = tgsi_default_property(); + property.PropertyName = property_name; + + header_bodysize_grow( header ); + + return property; +} + + +struct tgsi_full_property +tgsi_default_full_property( void ) +{ + struct tgsi_full_property full_property; + + full_property.Property = tgsi_default_property(); + memset(full_property.u, 0, + sizeof(struct tgsi_property_data) * 8); + + return full_property; +} + +static void +property_grow( + struct tgsi_property *property, + struct tgsi_header *header ) +{ + assert( property->NrTokens < 0xFF ); + + property->NrTokens++; + + header_bodysize_grow( header ); +} + +static struct tgsi_property_data +tgsi_build_property_data( + unsigned value, + struct tgsi_property *property, + struct tgsi_header *header ) +{ + struct tgsi_property_data property_data; + + property_data.Data = value; + + property_grow( property, header ); + + return property_data; +} + +unsigned +tgsi_build_full_property( + const struct tgsi_full_property *full_prop, + struct tgsi_token *tokens, + struct tgsi_header *header, + unsigned maxsize ) +{ + unsigned size = 0, i; + struct tgsi_property *property; + + if( maxsize <= size ) + return 0; + property = (struct tgsi_property *) &tokens[size]; + size++; + + *property = tgsi_build_property( + full_prop->Property.PropertyName, + header ); + + assert( full_prop->Property.NrTokens <= 8 + 1 ); + + for( i = 0; i < full_prop->Property.NrTokens - 1; i++ ) { + struct tgsi_property_data *data; + + if( maxsize <= size ) + return 0; + data = (struct tgsi_property_data *) &tokens[size]; + size++; + + *data = tgsi_build_property_data( + full_prop->u[i].Data, + property, + header ); + } + + return size; +} diff --git a/src/gallium/auxiliary/tgsi/tgsi_build.h b/src/gallium/auxiliary/tgsi/tgsi_build.h new file mode 100644 index 0000000..c5127e1 --- /dev/null +++ b/src/gallium/auxiliary/tgsi/tgsi_build.h @@ -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 */ diff --git a/src/gallium/auxiliary/tgsi/tgsi_dump.c b/src/gallium/auxiliary/tgsi/tgsi_dump.c new file mode 100644 index 0000000..b2e30d2 --- /dev/null +++ b/src/gallium/auxiliary/tgsi/tgsi_dump.c @@ -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 ); +} diff --git a/src/gallium/auxiliary/tgsi/tgsi_dump.h b/src/gallium/auxiliary/tgsi/tgsi_dump.h new file mode 100644 index 0000000..bb7f53f --- /dev/null +++ b/src/gallium/auxiliary/tgsi/tgsi_dump.h @@ -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 */ diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.c b/src/gallium/auxiliary/tgsi/tgsi_exec.c new file mode 100644 index 0000000..55da60a --- /dev/null +++ b/src/gallium/auxiliary/tgsi/tgsi_exec.c @@ -0,0 +1,4555 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + +/** + * TGSI interpreter/executor. + * + * Flow control information: + * + * Since we operate on 'quads' (4 pixels or 4 vertices in parallel) + * flow control statements (IF/ELSE/ENDIF, LOOP/ENDLOOP) require special + * care since a condition may be true for some quad components but false + * for other components. + * + * We basically execute all statements (even if they're in the part of + * an IF/ELSE clause that's "not taken") and use a special mask to + * control writing to destination registers. This is the ExecMask. + * See store_dest(). + * + * The ExecMask is computed from three other masks (CondMask, LoopMask and + * ContMask) which are controlled by the flow control instructions (namely: + * (IF/ELSE/ENDIF, LOOP/ENDLOOP and CONT). + * + * + * Authors: + * Michal Krol + * Brian Paul + */ + +#include "pipe/p_compiler.h" +#include "pipe/p_state.h" +#include "pipe/p_shader_tokens.h" +#include "tgsi/tgsi_dump.h" +#include "tgsi/tgsi_parse.h" +#include "tgsi/tgsi_util.h" +#include "tgsi_exec.h" +#include "util/u_memory.h" +#include "util/u_math.h" + + +#define DEBUG_EXECUTION 0 + + +#define FAST_MATH 0 + +#define TILE_TOP_LEFT 0 +#define TILE_TOP_RIGHT 1 +#define TILE_BOTTOM_LEFT 2 +#define TILE_BOTTOM_RIGHT 3 + +static void +micro_abs(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src) +{ + dst->f[0] = fabsf(src->f[0]); + dst->f[1] = fabsf(src->f[1]); + dst->f[2] = fabsf(src->f[2]); + dst->f[3] = fabsf(src->f[3]); +} + +static void +micro_arl(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src) +{ + dst->i[0] = (int)floorf(src->f[0]); + dst->i[1] = (int)floorf(src->f[1]); + dst->i[2] = (int)floorf(src->f[2]); + dst->i[3] = (int)floorf(src->f[3]); +} + +static void +micro_arr(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src) +{ + dst->i[0] = (int)floorf(src->f[0] + 0.5f); + dst->i[1] = (int)floorf(src->f[1] + 0.5f); + dst->i[2] = (int)floorf(src->f[2] + 0.5f); + dst->i[3] = (int)floorf(src->f[3] + 0.5f); +} + +static void +micro_ceil(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src) +{ + dst->f[0] = ceilf(src->f[0]); + dst->f[1] = ceilf(src->f[1]); + dst->f[2] = ceilf(src->f[2]); + dst->f[3] = ceilf(src->f[3]); +} + +static void +micro_clamp(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1, + const union tgsi_exec_channel *src2) +{ + dst->f[0] = src0->f[0] < src1->f[0] ? src1->f[0] : src0->f[0] > src2->f[0] ? src2->f[0] : src0->f[0]; + dst->f[1] = src0->f[1] < src1->f[1] ? src1->f[1] : src0->f[1] > src2->f[1] ? src2->f[1] : src0->f[1]; + dst->f[2] = src0->f[2] < src1->f[2] ? src1->f[2] : src0->f[2] > src2->f[2] ? src2->f[2] : src0->f[2]; + dst->f[3] = src0->f[3] < src1->f[3] ? src1->f[3] : src0->f[3] > src2->f[3] ? src2->f[3] : src0->f[3]; +} + +static void +micro_cmp(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1, + const union tgsi_exec_channel *src2) +{ + dst->f[0] = src0->f[0] < 0.0f ? src1->f[0] : src2->f[0]; + dst->f[1] = src0->f[1] < 0.0f ? src1->f[1] : src2->f[1]; + dst->f[2] = src0->f[2] < 0.0f ? src1->f[2] : src2->f[2]; + dst->f[3] = src0->f[3] < 0.0f ? src1->f[3] : src2->f[3]; +} + +static void +micro_cnd(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1, + const union tgsi_exec_channel *src2) +{ + dst->f[0] = src2->f[0] > 0.5f ? src0->f[0] : src1->f[0]; + dst->f[1] = src2->f[1] > 0.5f ? src0->f[1] : src1->f[1]; + dst->f[2] = src2->f[2] > 0.5f ? src0->f[2] : src1->f[2]; + dst->f[3] = src2->f[3] > 0.5f ? src0->f[3] : src1->f[3]; +} + +static void +micro_cos(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src) +{ + dst->f[0] = cosf(src->f[0]); + dst->f[1] = cosf(src->f[1]); + dst->f[2] = cosf(src->f[2]); + dst->f[3] = cosf(src->f[3]); +} + +static void +micro_ddx(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src) +{ + dst->f[0] = + dst->f[1] = + dst->f[2] = + dst->f[3] = src->f[TILE_BOTTOM_RIGHT] - src->f[TILE_BOTTOM_LEFT]; +} + +static void +micro_ddy(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src) +{ + dst->f[0] = + dst->f[1] = + dst->f[2] = + dst->f[3] = src->f[TILE_BOTTOM_LEFT] - src->f[TILE_TOP_LEFT]; +} + +static void +micro_exp2(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src) +{ +#if FAST_MATH + dst->f[0] = util_fast_exp2(src->f[0]); + dst->f[1] = util_fast_exp2(src->f[1]); + dst->f[2] = util_fast_exp2(src->f[2]); + dst->f[3] = util_fast_exp2(src->f[3]); +#else +#if DEBUG + /* Inf is okay for this instruction, so clamp it to silence assertions. */ + uint i; + union tgsi_exec_channel clamped; + + for (i = 0; i < 4; i++) { + if (src->f[i] > 127.99999f) { + clamped.f[i] = 127.99999f; + } else if (src->f[i] < -126.99999f) { + clamped.f[i] = -126.99999f; + } else { + clamped.f[i] = src->f[i]; + } + } + src = &clamped; +#endif /* DEBUG */ + + dst->f[0] = powf(2.0f, src->f[0]); + dst->f[1] = powf(2.0f, src->f[1]); + dst->f[2] = powf(2.0f, src->f[2]); + dst->f[3] = powf(2.0f, src->f[3]); +#endif /* FAST_MATH */ +} + +static void +micro_flr(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src) +{ + dst->f[0] = floorf(src->f[0]); + dst->f[1] = floorf(src->f[1]); + dst->f[2] = floorf(src->f[2]); + dst->f[3] = floorf(src->f[3]); +} + +static void +micro_frc(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src) +{ + dst->f[0] = src->f[0] - floorf(src->f[0]); + dst->f[1] = src->f[1] - floorf(src->f[1]); + dst->f[2] = src->f[2] - floorf(src->f[2]); + dst->f[3] = src->f[3] - floorf(src->f[3]); +} + +static void +micro_iabs(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src) +{ + dst->i[0] = src->i[0] >= 0 ? src->i[0] : -src->i[0]; + dst->i[1] = src->i[1] >= 0 ? src->i[1] : -src->i[1]; + dst->i[2] = src->i[2] >= 0 ? src->i[2] : -src->i[2]; + dst->i[3] = src->i[3] >= 0 ? src->i[3] : -src->i[3]; +} + +static void +micro_ineg(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src) +{ + dst->i[0] = -src->i[0]; + dst->i[1] = -src->i[1]; + dst->i[2] = -src->i[2]; + dst->i[3] = -src->i[3]; +} + +static void +micro_lg2(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src) +{ +#if FAST_MATH + dst->f[0] = util_fast_log2(src->f[0]); + dst->f[1] = util_fast_log2(src->f[1]); + dst->f[2] = util_fast_log2(src->f[2]); + dst->f[3] = util_fast_log2(src->f[3]); +#else + dst->f[0] = logf(src->f[0]) * 1.442695f; + dst->f[1] = logf(src->f[1]) * 1.442695f; + dst->f[2] = logf(src->f[2]) * 1.442695f; + dst->f[3] = logf(src->f[3]) * 1.442695f; +#endif +} + +static void +micro_lrp(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1, + const union tgsi_exec_channel *src2) +{ + dst->f[0] = src0->f[0] * (src1->f[0] - src2->f[0]) + src2->f[0]; + dst->f[1] = src0->f[1] * (src1->f[1] - src2->f[1]) + src2->f[1]; + dst->f[2] = src0->f[2] * (src1->f[2] - src2->f[2]) + src2->f[2]; + dst->f[3] = src0->f[3] * (src1->f[3] - src2->f[3]) + src2->f[3]; +} + +static void +micro_mad(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1, + const union tgsi_exec_channel *src2) +{ + dst->f[0] = src0->f[0] * src1->f[0] + src2->f[0]; + dst->f[1] = src0->f[1] * src1->f[1] + src2->f[1]; + dst->f[2] = src0->f[2] * src1->f[2] + src2->f[2]; + dst->f[3] = src0->f[3] * src1->f[3] + src2->f[3]; +} + +static void +micro_mov(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src) +{ + dst->u[0] = src->u[0]; + dst->u[1] = src->u[1]; + dst->u[2] = src->u[2]; + dst->u[3] = src->u[3]; +} + +static void +micro_rcp(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src) +{ +#if 0 /* for debugging */ + assert(src->f[0] != 0.0f); + assert(src->f[1] != 0.0f); + assert(src->f[2] != 0.0f); + assert(src->f[3] != 0.0f); +#endif + dst->f[0] = 1.0f / src->f[0]; + dst->f[1] = 1.0f / src->f[1]; + dst->f[2] = 1.0f / src->f[2]; + dst->f[3] = 1.0f / src->f[3]; +} + +static void +micro_rnd(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src) +{ + dst->f[0] = floorf(src->f[0] + 0.5f); + dst->f[1] = floorf(src->f[1] + 0.5f); + dst->f[2] = floorf(src->f[2] + 0.5f); + dst->f[3] = floorf(src->f[3] + 0.5f); +} + +static void +micro_rsq(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src) +{ +#if 0 /* for debugging */ + assert(src->f[0] != 0.0f); + assert(src->f[1] != 0.0f); + assert(src->f[2] != 0.0f); + assert(src->f[3] != 0.0f); +#endif + dst->f[0] = 1.0f / sqrtf(src->f[0]); + dst->f[1] = 1.0f / sqrtf(src->f[1]); + dst->f[2] = 1.0f / sqrtf(src->f[2]); + dst->f[3] = 1.0f / sqrtf(src->f[3]); +} + +static void +micro_sqrt(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src) +{ + dst->f[0] = sqrtf(src->f[0]); + dst->f[1] = sqrtf(src->f[1]); + dst->f[2] = sqrtf(src->f[2]); + dst->f[3] = sqrtf(src->f[3]); +} + +static void +micro_seq(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + dst->f[0] = src0->f[0] == src1->f[0] ? 1.0f : 0.0f; + dst->f[1] = src0->f[1] == src1->f[1] ? 1.0f : 0.0f; + dst->f[2] = src0->f[2] == src1->f[2] ? 1.0f : 0.0f; + dst->f[3] = src0->f[3] == src1->f[3] ? 1.0f : 0.0f; +} + +static void +micro_sge(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + dst->f[0] = src0->f[0] >= src1->f[0] ? 1.0f : 0.0f; + dst->f[1] = src0->f[1] >= src1->f[1] ? 1.0f : 0.0f; + dst->f[2] = src0->f[2] >= src1->f[2] ? 1.0f : 0.0f; + dst->f[3] = src0->f[3] >= src1->f[3] ? 1.0f : 0.0f; +} + +static void +micro_sgn(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src) +{ + dst->f[0] = src->f[0] < 0.0f ? -1.0f : src->f[0] > 0.0f ? 1.0f : 0.0f; + dst->f[1] = src->f[1] < 0.0f ? -1.0f : src->f[1] > 0.0f ? 1.0f : 0.0f; + dst->f[2] = src->f[2] < 0.0f ? -1.0f : src->f[2] > 0.0f ? 1.0f : 0.0f; + dst->f[3] = src->f[3] < 0.0f ? -1.0f : src->f[3] > 0.0f ? 1.0f : 0.0f; +} + +static void +micro_isgn(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src) +{ + dst->i[0] = src->i[0] < 0 ? -1 : src->i[0] > 0 ? 1 : 0; + dst->i[1] = src->i[1] < 0 ? -1 : src->i[1] > 0 ? 1 : 0; + dst->i[2] = src->i[2] < 0 ? -1 : src->i[2] > 0 ? 1 : 0; + dst->i[3] = src->i[3] < 0 ? -1 : src->i[3] > 0 ? 1 : 0; +} + +static void +micro_sgt(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + dst->f[0] = src0->f[0] > src1->f[0] ? 1.0f : 0.0f; + dst->f[1] = src0->f[1] > src1->f[1] ? 1.0f : 0.0f; + dst->f[2] = src0->f[2] > src1->f[2] ? 1.0f : 0.0f; + dst->f[3] = src0->f[3] > src1->f[3] ? 1.0f : 0.0f; +} + +static void +micro_sin(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src) +{ + dst->f[0] = sinf(src->f[0]); + dst->f[1] = sinf(src->f[1]); + dst->f[2] = sinf(src->f[2]); + dst->f[3] = sinf(src->f[3]); +} + +static void +micro_sle(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + dst->f[0] = src0->f[0] <= src1->f[0] ? 1.0f : 0.0f; + dst->f[1] = src0->f[1] <= src1->f[1] ? 1.0f : 0.0f; + dst->f[2] = src0->f[2] <= src1->f[2] ? 1.0f : 0.0f; + dst->f[3] = src0->f[3] <= src1->f[3] ? 1.0f : 0.0f; +} + +static void +micro_slt(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + dst->f[0] = src0->f[0] < src1->f[0] ? 1.0f : 0.0f; + dst->f[1] = src0->f[1] < src1->f[1] ? 1.0f : 0.0f; + dst->f[2] = src0->f[2] < src1->f[2] ? 1.0f : 0.0f; + dst->f[3] = src0->f[3] < src1->f[3] ? 1.0f : 0.0f; +} + +static void +micro_sne(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + dst->f[0] = src0->f[0] != src1->f[0] ? 1.0f : 0.0f; + dst->f[1] = src0->f[1] != src1->f[1] ? 1.0f : 0.0f; + dst->f[2] = src0->f[2] != src1->f[2] ? 1.0f : 0.0f; + dst->f[3] = src0->f[3] != src1->f[3] ? 1.0f : 0.0f; +} + +static void +micro_sfl(union tgsi_exec_channel *dst) +{ + dst->f[0] = 0.0f; + dst->f[1] = 0.0f; + dst->f[2] = 0.0f; + dst->f[3] = 0.0f; +} + +static void +micro_str(union tgsi_exec_channel *dst) +{ + dst->f[0] = 1.0f; + dst->f[1] = 1.0f; + dst->f[2] = 1.0f; + dst->f[3] = 1.0f; +} + +static void +micro_trunc(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src) +{ + dst->f[0] = (float)(int)src->f[0]; + dst->f[1] = (float)(int)src->f[1]; + dst->f[2] = (float)(int)src->f[2]; + dst->f[3] = (float)(int)src->f[3]; +} + + +enum tgsi_exec_datatype { + TGSI_EXEC_DATA_FLOAT, + TGSI_EXEC_DATA_INT, + TGSI_EXEC_DATA_UINT +}; + +/* + * Shorthand locations of various utility registers (_I = Index, _C = Channel) + */ +#define TEMP_KILMASK_I TGSI_EXEC_TEMP_KILMASK_I +#define TEMP_KILMASK_C TGSI_EXEC_TEMP_KILMASK_C +#define TEMP_OUTPUT_I TGSI_EXEC_TEMP_OUTPUT_I +#define TEMP_OUTPUT_C TGSI_EXEC_TEMP_OUTPUT_C +#define TEMP_PRIMITIVE_I TGSI_EXEC_TEMP_PRIMITIVE_I +#define TEMP_PRIMITIVE_C TGSI_EXEC_TEMP_PRIMITIVE_C + + +/** The execution mask depends on the conditional mask and the loop mask */ +#define UPDATE_EXEC_MASK(MACH) \ + MACH->ExecMask = MACH->CondMask & MACH->LoopMask & MACH->ContMask & MACH->Switch.mask & MACH->FuncMask + + +static const union tgsi_exec_channel ZeroVec = + { { 0.0, 0.0, 0.0, 0.0 } }; + +static const union tgsi_exec_channel OneVec = { + {1.0f, 1.0f, 1.0f, 1.0f} +}; + +static const union tgsi_exec_channel P128Vec = { + {128.0f, 128.0f, 128.0f, 128.0f} +}; + +static const union tgsi_exec_channel M128Vec = { + {-128.0f, -128.0f, -128.0f, -128.0f} +}; + + +/** + * Assert that none of the float values in 'chan' are infinite or NaN. + * NaN and Inf may occur normally during program execution and should + * not lead to crashes, etc. But when debugging, it's helpful to catch + * them. + */ +static INLINE void +check_inf_or_nan(const union tgsi_exec_channel *chan) +{ + assert(!util_is_inf_or_nan((chan)->f[0])); + assert(!util_is_inf_or_nan((chan)->f[1])); + assert(!util_is_inf_or_nan((chan)->f[2])); + assert(!util_is_inf_or_nan((chan)->f[3])); +} + + +#ifdef DEBUG +static void +print_chan(const char *msg, const union tgsi_exec_channel *chan) +{ + debug_printf("%s = {%f, %f, %f, %f}\n", + msg, chan->f[0], chan->f[1], chan->f[2], chan->f[3]); +} +#endif + + +#ifdef DEBUG +static void +print_temp(const struct tgsi_exec_machine *mach, uint index) +{ + const struct tgsi_exec_vector *tmp = &mach->Temps[index]; + int i; + debug_printf("Temp[%u] =\n", index); + for (i = 0; i < 4; i++) { + debug_printf(" %c: { %f, %f, %f, %f }\n", + "XYZW"[i], + tmp->xyzw[i].f[0], + tmp->xyzw[i].f[1], + tmp->xyzw[i].f[2], + tmp->xyzw[i].f[3]); + } +} +#endif + + +void +tgsi_exec_set_constant_buffers(struct tgsi_exec_machine *mach, + unsigned num_bufs, + const void **bufs, + const unsigned *buf_sizes) +{ + unsigned i; + + for (i = 0; i < num_bufs; i++) { + mach->Consts[i] = bufs[i]; + mach->ConstsSize[i] = buf_sizes[i]; + } +} + + +/** + * Check if there's a potential src/dst register data dependency when + * using SOA execution. + * Example: + * MOV T, T.yxwz; + * This would expand into: + * MOV t0, t1; + * MOV t1, t0; + * MOV t2, t3; + * MOV t3, t2; + * The second instruction will have the wrong value for t0 if executed as-is. + */ +boolean +tgsi_check_soa_dependencies(const struct tgsi_full_instruction *inst) +{ + uint i, chan; + + uint writemask = inst->Dst[0].Register.WriteMask; + if (writemask == TGSI_WRITEMASK_X || + writemask == TGSI_WRITEMASK_Y || + writemask == TGSI_WRITEMASK_Z || + writemask == TGSI_WRITEMASK_W || + writemask == TGSI_WRITEMASK_NONE) { + /* no chance of data dependency */ + return FALSE; + } + + /* loop over src regs */ + for (i = 0; i < inst->Instruction.NumSrcRegs; i++) { + if ((inst->Src[i].Register.File == + inst->Dst[0].Register.File) && + ((inst->Src[i].Register.Index == + inst->Dst[0].Register.Index) || + inst->Src[i].Register.Indirect || + inst->Dst[0].Register.Indirect)) { + /* loop over dest channels */ + uint channelsWritten = 0x0; + for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) { + if (inst->Dst[0].Register.WriteMask & (1 << chan)) { + /* check if we're reading a channel that's been written */ + uint swizzle = tgsi_util_get_full_src_register_swizzle(&inst->Src[i], chan); + if (channelsWritten & (1 << swizzle)) { + return TRUE; + } + + channelsWritten |= (1 << chan); + } + } + } + } + return FALSE; +} + + +/** + * Initialize machine state by expanding tokens to full instructions, + * allocating temporary storage, setting up constants, etc. + * After this, we can call tgsi_exec_machine_run() many times. + */ +void +tgsi_exec_machine_bind_shader( + struct tgsi_exec_machine *mach, + const struct tgsi_token *tokens, + struct tgsi_sampler *sampler) +{ + uint k; + struct tgsi_parse_context parse; + struct tgsi_full_instruction *instructions; + struct tgsi_full_declaration *declarations; + uint maxInstructions = 10, numInstructions = 0; + uint maxDeclarations = 10, numDeclarations = 0; + +#if 0 + tgsi_dump(tokens, 0); +#endif + + util_init_math(); + + + mach->Tokens = tokens; + mach->Sampler = sampler; + + if (!tokens) { + /* unbind and free all */ + FREE(mach->Declarations); + mach->Declarations = NULL; + mach->NumDeclarations = 0; + + FREE(mach->Instructions); + mach->Instructions = NULL; + mach->NumInstructions = 0; + + return; + } + + k = tgsi_parse_init (&parse, mach->Tokens); + if (k != TGSI_PARSE_OK) { + debug_printf( "Problem parsing!\n" ); + return; + } + + mach->Processor = parse.FullHeader.Processor.Processor; + mach->ImmLimit = 0; + mach->NumOutputs = 0; + + if (mach->Processor == TGSI_PROCESSOR_GEOMETRY && + !mach->UsedGeometryShader) { + struct tgsi_exec_vector *inputs; + struct tgsi_exec_vector *outputs; + + inputs = align_malloc(sizeof(struct tgsi_exec_vector) * + TGSI_MAX_PRIM_VERTICES * PIPE_MAX_ATTRIBS, + 16); + + if (!inputs) + return; + + outputs = align_malloc(sizeof(struct tgsi_exec_vector) * + TGSI_MAX_TOTAL_VERTICES, 16); + + if (!outputs) { + align_free(inputs); + return; + } + + align_free(mach->Inputs); + align_free(mach->Outputs); + + mach->Inputs = inputs; + mach->Outputs = outputs; + mach->UsedGeometryShader = TRUE; + } + + declarations = (struct tgsi_full_declaration *) + MALLOC( maxDeclarations * sizeof(struct tgsi_full_declaration) ); + + if (!declarations) { + return; + } + + instructions = (struct tgsi_full_instruction *) + MALLOC( maxInstructions * sizeof(struct tgsi_full_instruction) ); + + if (!instructions) { + FREE( declarations ); + return; + } + + while( !tgsi_parse_end_of_tokens( &parse ) ) { + uint i; + + tgsi_parse_token( &parse ); + switch( parse.FullToken.Token.Type ) { + case TGSI_TOKEN_TYPE_DECLARATION: + /* save expanded declaration */ + if (numDeclarations == maxDeclarations) { + declarations = REALLOC(declarations, + maxDeclarations + * sizeof(struct tgsi_full_declaration), + (maxDeclarations + 10) + * sizeof(struct tgsi_full_declaration)); + maxDeclarations += 10; + } + if (parse.FullToken.FullDeclaration.Declaration.File == TGSI_FILE_OUTPUT) { + unsigned reg; + for (reg = parse.FullToken.FullDeclaration.Range.First; + reg <= parse.FullToken.FullDeclaration.Range.Last; + ++reg) { + ++mach->NumOutputs; + } + } + memcpy(declarations + numDeclarations, + &parse.FullToken.FullDeclaration, + sizeof(declarations[0])); + numDeclarations++; + break; + + case TGSI_TOKEN_TYPE_IMMEDIATE: + { + uint size = parse.FullToken.FullImmediate.Immediate.NrTokens - 1; + assert( size <= 4 ); + assert( mach->ImmLimit + 1 <= TGSI_EXEC_NUM_IMMEDIATES ); + + for( i = 0; i < size; i++ ) { + mach->Imms[mach->ImmLimit][i] = + parse.FullToken.FullImmediate.u[i].Float; + } + mach->ImmLimit += 1; + } + break; + + case TGSI_TOKEN_TYPE_INSTRUCTION: + + /* save expanded instruction */ + if (numInstructions == maxInstructions) { + instructions = REALLOC(instructions, + maxInstructions + * sizeof(struct tgsi_full_instruction), + (maxInstructions + 10) + * sizeof(struct tgsi_full_instruction)); + maxInstructions += 10; + } + + memcpy(instructions + numInstructions, + &parse.FullToken.FullInstruction, + sizeof(instructions[0])); + + numInstructions++; + break; + + case TGSI_TOKEN_TYPE_PROPERTY: + break; + + default: + assert( 0 ); + } + } + tgsi_parse_free (&parse); + + FREE(mach->Declarations); + mach->Declarations = declarations; + mach->NumDeclarations = numDeclarations; + + FREE(mach->Instructions); + mach->Instructions = instructions; + mach->NumInstructions = numInstructions; +} + + +struct tgsi_exec_machine * +tgsi_exec_machine_create( void ) +{ + struct tgsi_exec_machine *mach; + uint i; + + mach = align_malloc( sizeof *mach, 16 ); + if (!mach) + goto fail; + + memset(mach, 0, sizeof(*mach)); + + mach->Addrs = &mach->Temps[TGSI_EXEC_TEMP_ADDR]; + mach->MaxGeometryShaderOutputs = TGSI_MAX_TOTAL_VERTICES; + mach->Predicates = &mach->Temps[TGSI_EXEC_TEMP_P0]; + + mach->Inputs = align_malloc(sizeof(struct tgsi_exec_vector) * PIPE_MAX_ATTRIBS, 16); + mach->Outputs = align_malloc(sizeof(struct tgsi_exec_vector) * PIPE_MAX_ATTRIBS, 16); + if (!mach->Inputs || !mach->Outputs) + goto fail; + + /* Setup constants needed by the SSE2 executor. */ + for( i = 0; i < 4; i++ ) { + mach->Temps[TGSI_EXEC_TEMP_00000000_I].xyzw[TGSI_EXEC_TEMP_00000000_C].u[i] = 0x00000000; + mach->Temps[TGSI_EXEC_TEMP_7FFFFFFF_I].xyzw[TGSI_EXEC_TEMP_7FFFFFFF_C].u[i] = 0x7FFFFFFF; + mach->Temps[TGSI_EXEC_TEMP_80000000_I].xyzw[TGSI_EXEC_TEMP_80000000_C].u[i] = 0x80000000; + mach->Temps[TGSI_EXEC_TEMP_FFFFFFFF_I].xyzw[TGSI_EXEC_TEMP_FFFFFFFF_C].u[i] = 0xFFFFFFFF; /* not used */ + mach->Temps[TGSI_EXEC_TEMP_ONE_I].xyzw[TGSI_EXEC_TEMP_ONE_C].f[i] = 1.0f; + mach->Temps[TGSI_EXEC_TEMP_TWO_I].xyzw[TGSI_EXEC_TEMP_TWO_C].f[i] = 2.0f; /* not used */ + mach->Temps[TGSI_EXEC_TEMP_128_I].xyzw[TGSI_EXEC_TEMP_128_C].f[i] = 128.0f; + mach->Temps[TGSI_EXEC_TEMP_MINUS_128_I].xyzw[TGSI_EXEC_TEMP_MINUS_128_C].f[i] = -128.0f; + mach->Temps[TGSI_EXEC_TEMP_THREE_I].xyzw[TGSI_EXEC_TEMP_THREE_C].f[i] = 3.0f; + mach->Temps[TGSI_EXEC_TEMP_HALF_I].xyzw[TGSI_EXEC_TEMP_HALF_C].f[i] = 0.5f; + } + +#ifdef DEBUG + /* silence warnings */ + (void) print_chan; + (void) print_temp; +#endif + + return mach; + +fail: + if (mach) { + align_free(mach->Inputs); + align_free(mach->Outputs); + align_free(mach); + } + return NULL; +} + + +void +tgsi_exec_machine_destroy(struct tgsi_exec_machine *mach) +{ + if (mach) { + FREE(mach->Instructions); + FREE(mach->Declarations); + + align_free(mach->Inputs); + align_free(mach->Outputs); + + align_free(mach); + } +} + +static void +micro_add(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + dst->f[0] = src0->f[0] + src1->f[0]; + dst->f[1] = src0->f[1] + src1->f[1]; + dst->f[2] = src0->f[2] + src1->f[2]; + dst->f[3] = src0->f[3] + src1->f[3]; +} + +static void +micro_div( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1 ) +{ + if (src1->f[0] != 0) { + dst->f[0] = src0->f[0] / src1->f[0]; + } + if (src1->f[1] != 0) { + dst->f[1] = src0->f[1] / src1->f[1]; + } + if (src1->f[2] != 0) { + dst->f[2] = src0->f[2] / src1->f[2]; + } + if (src1->f[3] != 0) { + dst->f[3] = src0->f[3] / src1->f[3]; + } +} + +static void +micro_rcc(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src) +{ + uint i; + + for (i = 0; i < 4; i++) { + float recip = 1.0f / src->f[i]; + + if (recip > 0.0f) + dst->f[i] = CLAMP(recip, 5.42101e-020f, 1.84467e+019f); + else + dst->f[i] = CLAMP(recip, -1.84467e+019f, -5.42101e-020f); + } +} + +static void +micro_lt( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1, + const union tgsi_exec_channel *src2, + const union tgsi_exec_channel *src3 ) +{ + dst->f[0] = src0->f[0] < src1->f[0] ? src2->f[0] : src3->f[0]; + dst->f[1] = src0->f[1] < src1->f[1] ? src2->f[1] : src3->f[1]; + dst->f[2] = src0->f[2] < src1->f[2] ? src2->f[2] : src3->f[2]; + dst->f[3] = src0->f[3] < src1->f[3] ? src2->f[3] : src3->f[3]; +} + +static void +micro_max(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + dst->f[0] = src0->f[0] > src1->f[0] ? src0->f[0] : src1->f[0]; + dst->f[1] = src0->f[1] > src1->f[1] ? src0->f[1] : src1->f[1]; + dst->f[2] = src0->f[2] > src1->f[2] ? src0->f[2] : src1->f[2]; + dst->f[3] = src0->f[3] > src1->f[3] ? src0->f[3] : src1->f[3]; +} + +static void +micro_min(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + dst->f[0] = src0->f[0] < src1->f[0] ? src0->f[0] : src1->f[0]; + dst->f[1] = src0->f[1] < src1->f[1] ? src0->f[1] : src1->f[1]; + dst->f[2] = src0->f[2] < src1->f[2] ? src0->f[2] : src1->f[2]; + dst->f[3] = src0->f[3] < src1->f[3] ? src0->f[3] : src1->f[3]; +} + +static void +micro_mul(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + dst->f[0] = src0->f[0] * src1->f[0]; + dst->f[1] = src0->f[1] * src1->f[1]; + dst->f[2] = src0->f[2] * src1->f[2]; + dst->f[3] = src0->f[3] * src1->f[3]; +} + +static void +micro_neg( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src ) +{ + dst->f[0] = -src->f[0]; + dst->f[1] = -src->f[1]; + dst->f[2] = -src->f[2]; + dst->f[3] = -src->f[3]; +} + +static void +micro_pow( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1 ) +{ +#if FAST_MATH + dst->f[0] = util_fast_pow( src0->f[0], src1->f[0] ); + dst->f[1] = util_fast_pow( src0->f[1], src1->f[1] ); + dst->f[2] = util_fast_pow( src0->f[2], src1->f[2] ); + dst->f[3] = util_fast_pow( src0->f[3], src1->f[3] ); +#else + dst->f[0] = powf( src0->f[0], src1->f[0] ); + dst->f[1] = powf( src0->f[1], src1->f[1] ); + dst->f[2] = powf( src0->f[2], src1->f[2] ); + dst->f[3] = powf( src0->f[3], src1->f[3] ); +#endif +} + +static void +micro_sub(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + dst->f[0] = src0->f[0] - src1->f[0]; + dst->f[1] = src0->f[1] - src1->f[1]; + dst->f[2] = src0->f[2] - src1->f[2]; + dst->f[3] = src0->f[3] - src1->f[3]; +} + +static void +fetch_src_file_channel(const struct tgsi_exec_machine *mach, + const uint chan_index, + const uint file, + const uint swizzle, + const union tgsi_exec_channel *index, + const union tgsi_exec_channel *index2D, + union tgsi_exec_channel *chan) +{ + uint i; + + assert(swizzle < 4); + + switch (file) { + case TGSI_FILE_CONSTANT: + for (i = 0; i < TGSI_QUAD_SIZE; i++) { + assert(index2D->i[i] >= 0 && index2D->i[i] < PIPE_MAX_CONSTANT_BUFFERS); + assert(mach->Consts[index2D->i[i]]); + + if (index->i[i] < 0) { + chan->u[i] = 0; + } else { + /* NOTE: copying the const value as a uint instead of float */ + const uint constbuf = index2D->i[i]; + const uint *buf = (const uint *)mach->Consts[constbuf]; + const int pos = index->i[i] * 4 + swizzle; + /* const buffer bounds check */ + if (pos < 0 || pos >= (int) mach->ConstsSize[constbuf]) { + if (0) { + /* Debug: print warning */ + static int count = 0; + if (count++ < 100) + debug_printf("TGSI Exec: const buffer index %d" + " out of bounds\n", pos); + } + chan->u[i] = 0; + } + else + chan->u[i] = buf[pos]; + } + } + break; + + case TGSI_FILE_INPUT: + for (i = 0; i < TGSI_QUAD_SIZE; i++) { + /* + if (TGSI_PROCESSOR_GEOMETRY == mach->Processor) { + debug_printf("Fetching Input[%d] (2d=%d, 1d=%d)\n", + index2D->i[i] * TGSI_EXEC_MAX_INPUT_ATTRIBS + index->i[i], + index2D->i[i], index->i[i]); + }*/ + int pos = index2D->i[i] * TGSI_EXEC_MAX_INPUT_ATTRIBS + index->i[i]; + assert(pos >= 0); + assert(pos < TGSI_MAX_PRIM_VERTICES * PIPE_MAX_ATTRIBS); + chan->u[i] = mach->Inputs[pos].xyzw[swizzle].u[i]; + } + break; + + case TGSI_FILE_SYSTEM_VALUE: + /* XXX no swizzling at this point. Will be needed if we put + * gl_FragCoord, for example, in a sys value register. + */ + for (i = 0; i < TGSI_QUAD_SIZE; i++) { + chan->u[i] = mach->SystemValue[index->i[i]].u[i]; + } + break; + + case TGSI_FILE_TEMPORARY: + for (i = 0; i < TGSI_QUAD_SIZE; i++) { + assert(index->i[i] < TGSI_EXEC_NUM_TEMPS); + assert(index2D->i[i] == 0); + + chan->u[i] = mach->Temps[index->i[i]].xyzw[swizzle].u[i]; + } + break; + + case TGSI_FILE_IMMEDIATE: + for (i = 0; i < TGSI_QUAD_SIZE; i++) { + assert(index->i[i] >= 0 && index->i[i] < (int)mach->ImmLimit); + assert(index2D->i[i] == 0); + + chan->f[i] = mach->Imms[index->i[i]][swizzle]; + } + break; + + case TGSI_FILE_ADDRESS: + for (i = 0; i < TGSI_QUAD_SIZE; i++) { + assert(index->i[i] >= 0); + assert(index2D->i[i] == 0); + + chan->u[i] = mach->Addrs[index->i[i]].xyzw[swizzle].u[i]; + } + break; + + case TGSI_FILE_PREDICATE: + for (i = 0; i < TGSI_QUAD_SIZE; i++) { + assert(index->i[i] >= 0 && index->i[i] < TGSI_EXEC_NUM_PREDS); + assert(index2D->i[i] == 0); + + chan->u[i] = mach->Predicates[0].xyzw[swizzle].u[i]; + } + break; + + case TGSI_FILE_OUTPUT: + /* vertex/fragment output vars can be read too */ + for (i = 0; i < TGSI_QUAD_SIZE; i++) { + assert(index->i[i] >= 0); + assert(index2D->i[i] == 0); + + chan->u[i] = mach->Outputs[index->i[i]].xyzw[swizzle].u[i]; + } + break; + + default: + assert(0); + for (i = 0; i < TGSI_QUAD_SIZE; i++) { + chan->u[i] = 0; + } + } +} + +static void +fetch_source(const struct tgsi_exec_machine *mach, + union tgsi_exec_channel *chan, + const struct tgsi_full_src_register *reg, + const uint chan_index, + enum tgsi_exec_datatype src_datatype) +{ + union tgsi_exec_channel index; + union tgsi_exec_channel index2D; + uint swizzle; + + /* We start with a direct index into a register file. + * + * file[1], + * where: + * file = Register.File + * [1] = Register.Index + */ + index.i[0] = + index.i[1] = + index.i[2] = + index.i[3] = reg->Register.Index; + + /* There is an extra source register that indirectly subscripts + * a register file. The direct index now becomes an offset + * that is being added to the indirect register. + * + * file[ind[2].x+1], + * where: + * ind = Indirect.File + * [2] = Indirect.Index + * .x = Indirect.SwizzleX + */ + if (reg->Register.Indirect) { + union tgsi_exec_channel index2; + union tgsi_exec_channel indir_index; + const uint execmask = mach->ExecMask; + uint i; + + /* which address register (always zero now) */ + index2.i[0] = + index2.i[1] = + index2.i[2] = + index2.i[3] = reg->Indirect.Index; + /* get current value of address register[swizzle] */ + swizzle = reg->Indirect.Swizzle; + fetch_src_file_channel(mach, + chan_index, + reg->Indirect.File, + swizzle, + &index2, + &ZeroVec, + &indir_index); + + /* add value of address register to the offset */ + index.i[0] += indir_index.i[0]; + index.i[1] += indir_index.i[1]; + index.i[2] += indir_index.i[2]; + index.i[3] += indir_index.i[3]; + + /* for disabled execution channels, zero-out the index to + * avoid using a potential garbage value. + */ + for (i = 0; i < TGSI_QUAD_SIZE; i++) { + if ((execmask & (1 << i)) == 0) + index.i[i] = 0; + } + } + + /* There is an extra source register that is a second + * subscript to a register file. Effectively it means that + * the register file is actually a 2D array of registers. + * + * file[3][1], + * where: + * [3] = Dimension.Index + */ + if (reg->Register.Dimension) { + index2D.i[0] = + index2D.i[1] = + index2D.i[2] = + index2D.i[3] = reg->Dimension.Index; + + /* Again, the second subscript index can be addressed indirectly + * identically to the first one. + * Nothing stops us from indirectly addressing the indirect register, + * but there is no need for that, so we won't exercise it. + * + * file[ind[4].y+3][1], + * where: + * ind = DimIndirect.File + * [4] = DimIndirect.Index + * .y = DimIndirect.SwizzleX + */ + if (reg->Dimension.Indirect) { + union tgsi_exec_channel index2; + union tgsi_exec_channel indir_index; + const uint execmask = mach->ExecMask; + uint i; + + index2.i[0] = + index2.i[1] = + index2.i[2] = + index2.i[3] = reg->DimIndirect.Index; + + swizzle = reg->DimIndirect.Swizzle; + fetch_src_file_channel(mach, + chan_index, + reg->DimIndirect.File, + swizzle, + &index2, + &ZeroVec, + &indir_index); + + index2D.i[0] += indir_index.i[0]; + index2D.i[1] += indir_index.i[1]; + index2D.i[2] += indir_index.i[2]; + index2D.i[3] += indir_index.i[3]; + + /* for disabled execution channels, zero-out the index to + * avoid using a potential garbage value. + */ + for (i = 0; i < TGSI_QUAD_SIZE; i++) { + if ((execmask & (1 << i)) == 0) { + index2D.i[i] = 0; + } + } + } + + /* If by any chance there was a need for a 3D array of register + * files, we would have to check whether Dimension is followed + * by a dimension register and continue the saga. + */ + } else { + index2D.i[0] = + index2D.i[1] = + index2D.i[2] = + index2D.i[3] = 0; + } + + swizzle = tgsi_util_get_full_src_register_swizzle( reg, chan_index ); + fetch_src_file_channel(mach, + chan_index, + reg->Register.File, + swizzle, + &index, + &index2D, + chan); + + if (reg->Register.Absolute) { + if (src_datatype == TGSI_EXEC_DATA_FLOAT) { + micro_abs(chan, chan); + } else { + micro_iabs(chan, chan); + } + } + + if (reg->Register.Negate) { + if (src_datatype == TGSI_EXEC_DATA_FLOAT) { + micro_neg(chan, chan); + } else { + micro_ineg(chan, chan); + } + } +} + +static void +store_dest(struct tgsi_exec_machine *mach, + const union tgsi_exec_channel *chan, + const struct tgsi_full_dst_register *reg, + const struct tgsi_full_instruction *inst, + uint chan_index, + enum tgsi_exec_datatype dst_datatype) +{ + uint i; + union tgsi_exec_channel null; + union tgsi_exec_channel *dst; + union tgsi_exec_channel index2D; + uint execmask = mach->ExecMask; + int offset = 0; /* indirection offset */ + int index; + + /* for debugging */ + if (0 && dst_datatype == TGSI_EXEC_DATA_FLOAT) { + check_inf_or_nan(chan); + } + + /* There is an extra source register that indirectly subscripts + * a register file. The direct index now becomes an offset + * that is being added to the indirect register. + * + * file[ind[2].x+1], + * where: + * ind = Indirect.File + * [2] = Indirect.Index + * .x = Indirect.SwizzleX + */ + if (reg->Register.Indirect) { + union tgsi_exec_channel index; + union tgsi_exec_channel indir_index; + uint swizzle; + + /* which address register (always zero for now) */ + index.i[0] = + index.i[1] = + index.i[2] = + index.i[3] = reg->Indirect.Index; + + /* get current value of address register[swizzle] */ + swizzle = reg->Indirect.Swizzle; + + /* fetch values from the address/indirection register */ + fetch_src_file_channel(mach, + chan_index, + reg->Indirect.File, + swizzle, + &index, + &ZeroVec, + &indir_index); + + /* save indirection offset */ + offset = indir_index.i[0]; + } + + /* There is an extra source register that is a second + * subscript to a register file. Effectively it means that + * the register file is actually a 2D array of registers. + * + * file[3][1], + * where: + * [3] = Dimension.Index + */ + if (reg->Register.Dimension) { + index2D.i[0] = + index2D.i[1] = + index2D.i[2] = + index2D.i[3] = reg->Dimension.Index; + + /* Again, the second subscript index can be addressed indirectly + * identically to the first one. + * Nothing stops us from indirectly addressing the indirect register, + * but there is no need for that, so we won't exercise it. + * + * file[ind[4].y+3][1], + * where: + * ind = DimIndirect.File + * [4] = DimIndirect.Index + * .y = DimIndirect.SwizzleX + */ + if (reg->Dimension.Indirect) { + union tgsi_exec_channel index2; + union tgsi_exec_channel indir_index; + const uint execmask = mach->ExecMask; + unsigned swizzle; + uint i; + + index2.i[0] = + index2.i[1] = + index2.i[2] = + index2.i[3] = reg->DimIndirect.Index; + + swizzle = reg->DimIndirect.Swizzle; + fetch_src_file_channel(mach, + chan_index, + reg->DimIndirect.File, + swizzle, + &index2, + &ZeroVec, + &indir_index); + + index2D.i[0] += indir_index.i[0]; + index2D.i[1] += indir_index.i[1]; + index2D.i[2] += indir_index.i[2]; + index2D.i[3] += indir_index.i[3]; + + /* for disabled execution channels, zero-out the index to + * avoid using a potential garbage value. + */ + for (i = 0; i < TGSI_QUAD_SIZE; i++) { + if ((execmask & (1 << i)) == 0) { + index2D.i[i] = 0; + } + } + } + + /* If by any chance there was a need for a 3D array of register + * files, we would have to check whether Dimension is followed + * by a dimension register and continue the saga. + */ + } else { + index2D.i[0] = + index2D.i[1] = + index2D.i[2] = + index2D.i[3] = 0; + } + + switch (reg->Register.File) { + case TGSI_FILE_NULL: + dst = &null; + break; + + case TGSI_FILE_OUTPUT: + index = mach->Temps[TEMP_OUTPUT_I].xyzw[TEMP_OUTPUT_C].u[0] + + reg->Register.Index; + dst = &mach->Outputs[offset + index].xyzw[chan_index]; +#if 0 + debug_printf("NumOutputs = %d, TEMP_O_C/I = %d, redindex = %d\n", + mach->NumOutputs, mach->Temps[TEMP_OUTPUT_I].xyzw[TEMP_OUTPUT_C].u[0], + reg->Register.Index); + if (TGSI_PROCESSOR_GEOMETRY == mach->Processor) { + debug_printf("STORING OUT[%d] mask(%d), = (", offset + index, execmask); + for (i = 0; i < TGSI_QUAD_SIZE; i++) + if (execmask & (1 << i)) + debug_printf("%f, ", chan->f[i]); + debug_printf(")\n"); + } +#endif + break; + + case TGSI_FILE_TEMPORARY: + index = reg->Register.Index; + assert( index < TGSI_EXEC_NUM_TEMPS ); + dst = &mach->Temps[offset + index].xyzw[chan_index]; + break; + + case TGSI_FILE_ADDRESS: + index = reg->Register.Index; + dst = &mach->Addrs[index].xyzw[chan_index]; + break; + + case TGSI_FILE_PREDICATE: + index = reg->Register.Index; + assert(index < TGSI_EXEC_NUM_PREDS); + dst = &mach->Predicates[index].xyzw[chan_index]; + break; + + default: + assert( 0 ); + return; + } + + if (inst->Instruction.Predicate) { + uint swizzle; + union tgsi_exec_channel *pred; + + switch (chan_index) { + case TGSI_CHAN_X: + swizzle = inst->Predicate.SwizzleX; + break; + case TGSI_CHAN_Y: + swizzle = inst->Predicate.SwizzleY; + break; + case TGSI_CHAN_Z: + swizzle = inst->Predicate.SwizzleZ; + break; + case TGSI_CHAN_W: + swizzle = inst->Predicate.SwizzleW; + break; + default: + assert(0); + return; + } + + assert(inst->Predicate.Index == 0); + + pred = &mach->Predicates[inst->Predicate.Index].xyzw[swizzle]; + + if (inst->Predicate.Negate) { + for (i = 0; i < TGSI_QUAD_SIZE; i++) { + if (pred->u[i]) { + execmask &= ~(1 << i); + } + } + } else { + for (i = 0; i < TGSI_QUAD_SIZE; i++) { + if (!pred->u[i]) { + execmask &= ~(1 << i); + } + } + } + } + + switch (inst->Instruction.Saturate) { + case TGSI_SAT_NONE: + for (i = 0; i < TGSI_QUAD_SIZE; i++) + if (execmask & (1 << i)) + dst->i[i] = chan->i[i]; + break; + + case TGSI_SAT_ZERO_ONE: + for (i = 0; i < TGSI_QUAD_SIZE; i++) + if (execmask & (1 << i)) { + if (chan->f[i] < 0.0f) + dst->f[i] = 0.0f; + else if (chan->f[i] > 1.0f) + dst->f[i] = 1.0f; + else + dst->i[i] = chan->i[i]; + } + break; + + case TGSI_SAT_MINUS_PLUS_ONE: + for (i = 0; i < TGSI_QUAD_SIZE; i++) + if (execmask & (1 << i)) { + if (chan->f[i] < -1.0f) + dst->f[i] = -1.0f; + else if (chan->f[i] > 1.0f) + dst->f[i] = 1.0f; + else + dst->i[i] = chan->i[i]; + } + break; + + default: + assert( 0 ); + } +} + +#define FETCH(VAL,INDEX,CHAN)\ + fetch_source(mach, VAL, &inst->Src[INDEX], CHAN, TGSI_EXEC_DATA_FLOAT) + +#define IFETCH(VAL,INDEX,CHAN)\ + fetch_source(mach, VAL, &inst->Src[INDEX], CHAN, TGSI_EXEC_DATA_INT) + + +/** + * Execute ARB-style KIL which is predicated by a src register. + * Kill fragment if any of the four values is less than zero. + */ +static void +exec_kill_if(struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst) +{ + uint uniquemask; + uint chan_index; + uint kilmask = 0; /* bit 0 = pixel 0, bit 1 = pixel 1, etc */ + union tgsi_exec_channel r[1]; + + /* This mask stores component bits that were already tested. */ + uniquemask = 0; + + for (chan_index = 0; chan_index < 4; chan_index++) + { + uint swizzle; + uint i; + + /* unswizzle channel */ + swizzle = tgsi_util_get_full_src_register_swizzle ( + &inst->Src[0], + chan_index); + + /* check if the component has not been already tested */ + if (uniquemask & (1 << swizzle)) + continue; + uniquemask |= 1 << swizzle; + + FETCH(&r[0], 0, chan_index); + for (i = 0; i < 4; i++) + if (r[0].f[i] < 0.0f) + kilmask |= 1 << i; + } + + /* restrict to fragments currently executing */ + kilmask &= mach->ExecMask; + + mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0] |= kilmask; +} + +/** + * Unconditional fragment kill/discard. + */ +static void +exec_kill(struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst) +{ + uint kilmask; /* bit 0 = pixel 0, bit 1 = pixel 1, etc */ + + /* kill fragment for all fragments currently executing */ + kilmask = mach->ExecMask; + mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0] |= kilmask; +} + +static void +emit_vertex(struct tgsi_exec_machine *mach) +{ + /* FIXME: check for exec mask correctly + unsigned i; + for (i = 0; i < TGSI_QUAD_SIZE; ++i) { + if ((mach->ExecMask & (1 << i))) + */ + if (mach->ExecMask) { + mach->Temps[TEMP_OUTPUT_I].xyzw[TEMP_OUTPUT_C].u[0] += mach->NumOutputs; + mach->Primitives[mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0]]++; + } +} + +static void +emit_primitive(struct tgsi_exec_machine *mach) +{ + unsigned *prim_count = &mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0]; + /* FIXME: check for exec mask correctly + unsigned i; + for (i = 0; i < TGSI_QUAD_SIZE; ++i) { + if ((mach->ExecMask & (1 << i))) + */ + if (mach->ExecMask) { + ++(*prim_count); + debug_assert((*prim_count * mach->NumOutputs) < mach->MaxGeometryShaderOutputs); + mach->Primitives[*prim_count] = 0; + } +} + +static void +conditional_emit_primitive(struct tgsi_exec_machine *mach) +{ + if (TGSI_PROCESSOR_GEOMETRY == mach->Processor) { + int emitted_verts = + mach->Primitives[mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0]]; + if (emitted_verts) { + emit_primitive(mach); + } + } +} + + +/* + * Fetch four texture samples using STR texture coordinates. + */ +static void +fetch_texel( struct tgsi_sampler *sampler, + const unsigned sview_idx, + const unsigned sampler_idx, + const union tgsi_exec_channel *s, + const union tgsi_exec_channel *t, + const union tgsi_exec_channel *p, + const union tgsi_exec_channel *c0, + const union tgsi_exec_channel *c1, + float derivs[3][2][TGSI_QUAD_SIZE], + const int8_t offset[3], + enum tgsi_sampler_control control, + union tgsi_exec_channel *r, + union tgsi_exec_channel *g, + union tgsi_exec_channel *b, + union tgsi_exec_channel *a ) +{ + uint j; + float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]; + + /* FIXME: handle explicit derivs, offsets */ + sampler->get_samples(sampler, sview_idx, sampler_idx, + s->f, t->f, p->f, c0->f, c1->f, derivs, offset, control, rgba); + + for (j = 0; j < 4; j++) { + r->f[j] = rgba[0][j]; + g->f[j] = rgba[1][j]; + b->f[j] = rgba[2][j]; + a->f[j] = rgba[3][j]; + } +} + + +#define TEX_MODIFIER_NONE 0 +#define TEX_MODIFIER_PROJECTED 1 +#define TEX_MODIFIER_LOD_BIAS 2 +#define TEX_MODIFIER_EXPLICIT_LOD 3 +#define TEX_MODIFIER_LEVEL_ZERO 4 + + +/* + * Fetch all 3 (for s,t,r coords) texel offsets, put them into int array. + */ +static void +fetch_texel_offsets(struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst, + int8_t offsets[3]) +{ + if (inst->Texture.NumOffsets == 1) { + union tgsi_exec_channel index; + union tgsi_exec_channel offset[3]; + index.i[0] = index.i[1] = index.i[2] = index.i[3] = inst->TexOffsets[0].Index; + fetch_src_file_channel(mach, 0, inst->TexOffsets[0].File, + inst->TexOffsets[0].SwizzleX, &index, &ZeroVec, &offset[0]); + fetch_src_file_channel(mach, 0, inst->TexOffsets[0].File, + inst->TexOffsets[0].SwizzleY, &index, &ZeroVec, &offset[1]); + fetch_src_file_channel(mach, 0, inst->TexOffsets[0].File, + inst->TexOffsets[0].SwizzleZ, &index, &ZeroVec, &offset[2]); + offsets[0] = offset[0].i[0]; + offsets[1] = offset[1].i[0]; + offsets[2] = offset[2].i[0]; + } else { + assert(inst->Texture.NumOffsets == 0); + offsets[0] = offsets[1] = offsets[2] = 0; + } +} + + +/* + * Fetch dx and dy values for one channel (s, t or r). + * Put dx values into one float array, dy values into another. + */ +static void +fetch_assign_deriv_channel(struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst, + unsigned regdsrcx, + unsigned chan, + float derivs[2][TGSI_QUAD_SIZE]) +{ + union tgsi_exec_channel d; + FETCH(&d, regdsrcx, chan); + derivs[0][0] = d.f[0]; + derivs[0][1] = d.f[1]; + derivs[0][2] = d.f[2]; + derivs[0][3] = d.f[3]; + FETCH(&d, regdsrcx + 1, chan); + derivs[1][0] = d.f[0]; + derivs[1][1] = d.f[1]; + derivs[1][2] = d.f[2]; + derivs[1][3] = d.f[3]; +} + + +/* + * execute a texture instruction. + * + * modifier is used to control the channel routing for the\ + * instruction variants like proj, lod, and texture with lod bias. + * sampler indicates which src register the sampler is contained in. + */ +static void +exec_tex(struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst, + uint modifier, uint sampler) +{ + const uint unit = inst->Src[sampler].Register.Index; + const union tgsi_exec_channel *args[5], *proj = NULL; + union tgsi_exec_channel r[5]; + enum tgsi_sampler_control control = tgsi_sampler_lod_none; + uint chan; + int8_t offsets[3]; + int dim, shadow_ref, i; + + /* always fetch all 3 offsets, overkill but keeps code simple */ + fetch_texel_offsets(mach, inst, offsets); + + assert(modifier != TEX_MODIFIER_LEVEL_ZERO); + assert(inst->Texture.Texture != TGSI_TEXTURE_BUFFER); + + dim = tgsi_util_get_texture_coord_dim(inst->Texture.Texture, &shadow_ref); + + assert(dim <= 4); + if (shadow_ref >= 0) + assert(shadow_ref >= dim && shadow_ref < Elements(args)); + + /* fetch modifier to the last argument */ + if (modifier != TEX_MODIFIER_NONE) { + const int last = Elements(args) - 1; + + /* fetch modifier from src0.w or src1.x */ + if (sampler == 1) { + assert(dim <= TGSI_CHAN_W && shadow_ref != TGSI_CHAN_W); + FETCH(&r[last], 0, TGSI_CHAN_W); + } + else { + assert(shadow_ref != 4); + FETCH(&r[last], 1, TGSI_CHAN_X); + } + + if (modifier != TEX_MODIFIER_PROJECTED) { + args[last] = &r[last]; + } + else { + proj = &r[last]; + args[last] = &ZeroVec; + } + + /* point unused arguments to zero vector */ + for (i = dim; i < last; i++) + args[i] = &ZeroVec; + + if (modifier == TEX_MODIFIER_EXPLICIT_LOD) + control = tgsi_sampler_lod_explicit; + else if (modifier == TEX_MODIFIER_LOD_BIAS) + control = tgsi_sampler_lod_bias; + } + else { + for (i = dim; i < Elements(args); i++) + args[i] = &ZeroVec; + } + + /* fetch coordinates */ + for (i = 0; i < dim; i++) { + FETCH(&r[i], 0, TGSI_CHAN_X + i); + + if (proj) + micro_div(&r[i], &r[i], proj); + + args[i] = &r[i]; + } + + /* fetch reference value */ + if (shadow_ref >= 0) { + FETCH(&r[shadow_ref], shadow_ref / 4, TGSI_CHAN_X + (shadow_ref % 4)); + + if (proj) + micro_div(&r[shadow_ref], &r[shadow_ref], proj); + + args[shadow_ref] = &r[shadow_ref]; + } + + fetch_texel(mach->Sampler, unit, unit, + args[0], args[1], args[2], args[3], args[4], + NULL, offsets, control, + &r[0], &r[1], &r[2], &r[3]); /* R, G, B, A */ + +#if 0 + debug_printf("fetch r: %g %g %g %g\n", + r[0].f[0], r[0].f[1], r[0].f[2], r[0].f[3]); + debug_printf("fetch g: %g %g %g %g\n", + r[1].f[0], r[1].f[1], r[1].f[2], r[1].f[3]); + debug_printf("fetch b: %g %g %g %g\n", + r[2].f[0], r[2].f[1], r[2].f[2], r[2].f[3]); + debug_printf("fetch a: %g %g %g %g\n", + r[3].f[0], r[3].f[1], r[3].f[2], r[3].f[3]); +#endif + + for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) { + if (inst->Dst[0].Register.WriteMask & (1 << chan)) { + store_dest(mach, &r[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT); + } + } +} + + +static void +exec_txd(struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst) +{ + const uint unit = inst->Src[3].Register.Index; + union tgsi_exec_channel r[4]; + float derivs[3][2][TGSI_QUAD_SIZE]; + uint chan; + int8_t offsets[3]; + + /* always fetch all 3 offsets, overkill but keeps code simple */ + fetch_texel_offsets(mach, inst, offsets); + + switch (inst->Texture.Texture) { + case TGSI_TEXTURE_1D: + FETCH(&r[0], 0, TGSI_CHAN_X); + + fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_X, derivs[0]); + + fetch_texel(mach->Sampler, unit, unit, + &r[0], &ZeroVec, &ZeroVec, &ZeroVec, &ZeroVec, /* S, T, P, C, LOD */ + derivs, offsets, tgsi_sampler_derivs_explicit, + &r[0], &r[1], &r[2], &r[3]); /* R, G, B, A */ + break; + + case TGSI_TEXTURE_SHADOW1D: + case TGSI_TEXTURE_1D_ARRAY: + case TGSI_TEXTURE_SHADOW1D_ARRAY: + /* SHADOW1D/1D_ARRAY would not need Y/Z respectively, but don't bother */ + FETCH(&r[0], 0, TGSI_CHAN_X); + FETCH(&r[1], 0, TGSI_CHAN_Y); + FETCH(&r[2], 0, TGSI_CHAN_Z); + + fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_X, derivs[0]); + + fetch_texel(mach->Sampler, unit, unit, + &r[0], &r[1], &r[2], &ZeroVec, &ZeroVec, /* S, T, P, C, LOD */ + derivs, offsets, tgsi_sampler_derivs_explicit, + &r[0], &r[1], &r[2], &r[3]); /* R, G, B, A */ + break; + + case TGSI_TEXTURE_2D: + case TGSI_TEXTURE_RECT: + FETCH(&r[0], 0, TGSI_CHAN_X); + FETCH(&r[1], 0, TGSI_CHAN_Y); + + fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_X, derivs[0]); + fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_Y, derivs[1]); + + fetch_texel(mach->Sampler, unit, unit, + &r[0], &r[1], &ZeroVec, &ZeroVec, &ZeroVec, /* S, T, P, C, LOD */ + derivs, offsets, tgsi_sampler_derivs_explicit, + &r[0], &r[1], &r[2], &r[3]); /* R, G, B, A */ + break; + + + case TGSI_TEXTURE_SHADOW2D: + case TGSI_TEXTURE_SHADOWRECT: + case TGSI_TEXTURE_2D_ARRAY: + case TGSI_TEXTURE_SHADOW2D_ARRAY: + /* only SHADOW2D_ARRAY actually needs W */ + FETCH(&r[0], 0, TGSI_CHAN_X); + FETCH(&r[1], 0, TGSI_CHAN_Y); + FETCH(&r[2], 0, TGSI_CHAN_Z); + FETCH(&r[3], 0, TGSI_CHAN_W); + + fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_X, derivs[0]); + fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_Y, derivs[1]); + + fetch_texel(mach->Sampler, unit, unit, + &r[0], &r[1], &r[2], &r[3], &ZeroVec, /* inputs */ + derivs, offsets, tgsi_sampler_derivs_explicit, + &r[0], &r[1], &r[2], &r[3]); /* outputs */ + break; + + case TGSI_TEXTURE_3D: + case TGSI_TEXTURE_CUBE: + case TGSI_TEXTURE_CUBE_ARRAY: + /* only TEXTURE_CUBE_ARRAY actually needs W */ + FETCH(&r[0], 0, TGSI_CHAN_X); + FETCH(&r[1], 0, TGSI_CHAN_Y); + FETCH(&r[2], 0, TGSI_CHAN_Z); + FETCH(&r[3], 0, TGSI_CHAN_W); + + fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_X, derivs[0]); + fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_Y, derivs[1]); + fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_Z, derivs[2]); + + fetch_texel(mach->Sampler, unit, unit, + &r[0], &r[1], &r[2], &r[3], &ZeroVec, /* inputs */ + derivs, offsets, tgsi_sampler_derivs_explicit, + &r[0], &r[1], &r[2], &r[3]); /* outputs */ + break; + + default: + assert(0); + } + + for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) { + if (inst->Dst[0].Register.WriteMask & (1 << chan)) { + store_dest(mach, &r[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT); + } + } +} + + +static void +exec_txf(struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst) +{ + const uint unit = inst->Src[1].Register.Index; + union tgsi_exec_channel r[4]; + uint chan; + float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]; + int j; + int8_t offsets[3]; + unsigned target; + + /* always fetch all 3 offsets, overkill but keeps code simple */ + fetch_texel_offsets(mach, inst, offsets); + + IFETCH(&r[3], 0, TGSI_CHAN_W); + + if (inst->Instruction.Opcode == TGSI_OPCODE_SAMPLE_I) { + target = mach->SamplerViews[unit].Resource; + } + else { + target = inst->Texture.Texture; + } + switch(target) { + case TGSI_TEXTURE_3D: + case TGSI_TEXTURE_2D_ARRAY: + case TGSI_TEXTURE_SHADOW2D_ARRAY: + IFETCH(&r[2], 0, TGSI_CHAN_Z); + /* fallthrough */ + case TGSI_TEXTURE_2D: + case TGSI_TEXTURE_RECT: + case TGSI_TEXTURE_SHADOW1D_ARRAY: + case TGSI_TEXTURE_SHADOW2D: + case TGSI_TEXTURE_SHADOWRECT: + case TGSI_TEXTURE_1D_ARRAY: + IFETCH(&r[1], 0, TGSI_CHAN_Y); + /* fallthrough */ + case TGSI_TEXTURE_BUFFER: + case TGSI_TEXTURE_1D: + case TGSI_TEXTURE_SHADOW1D: + IFETCH(&r[0], 0, TGSI_CHAN_X); + break; + default: + assert(0); + break; + } + + mach->Sampler->get_texel(mach->Sampler, unit, r[0].i, r[1].i, r[2].i, r[3].i, + offsets, rgba); + + for (j = 0; j < TGSI_QUAD_SIZE; j++) { + r[0].f[j] = rgba[0][j]; + r[1].f[j] = rgba[1][j]; + r[2].f[j] = rgba[2][j]; + r[3].f[j] = rgba[3][j]; + } + + if (inst->Instruction.Opcode == TGSI_OPCODE_SAMPLE_I) { + unsigned char swizzles[4]; + swizzles[0] = inst->Src[1].Register.SwizzleX; + swizzles[1] = inst->Src[1].Register.SwizzleY; + swizzles[2] = inst->Src[1].Register.SwizzleZ; + swizzles[3] = inst->Src[1].Register.SwizzleW; + + for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) { + if (inst->Dst[0].Register.WriteMask & (1 << chan)) { + store_dest(mach, &r[swizzles[chan]], + &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT); + } + } + } + else { + for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) { + if (inst->Dst[0].Register.WriteMask & (1 << chan)) { + store_dest(mach, &r[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT); + } + } + } +} + +static void +exec_txq(struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst) +{ + const uint unit = inst->Src[1].Register.Index; + int result[4]; + union tgsi_exec_channel r[4], src; + uint chan; + int i,j; + + fetch_source(mach, &src, &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_INT); + + /* XXX: This interface can't return per-pixel values */ + mach->Sampler->get_dims(mach->Sampler, unit, src.i[0], result); + + for (i = 0; i < TGSI_QUAD_SIZE; i++) { + for (j = 0; j < 4; j++) { + r[j].i[i] = result[j]; + } + } + + for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) { + if (inst->Dst[0].Register.WriteMask & (1 << chan)) { + store_dest(mach, &r[chan], &inst->Dst[0], inst, chan, + TGSI_EXEC_DATA_INT); + } + } +} + +static void +exec_sample(struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst, + uint modifier, boolean compare) +{ + const uint resource_unit = inst->Src[1].Register.Index; + const uint sampler_unit = inst->Src[2].Register.Index; + union tgsi_exec_channel r[4], c1; + const union tgsi_exec_channel *lod = &ZeroVec; + enum tgsi_sampler_control control = tgsi_sampler_lod_none; + uint chan; + unsigned char swizzles[4]; + int8_t offsets[3]; + + /* always fetch all 3 offsets, overkill but keeps code simple */ + fetch_texel_offsets(mach, inst, offsets); + + assert(modifier != TEX_MODIFIER_PROJECTED); + + if (modifier != TEX_MODIFIER_NONE) { + if (modifier == TEX_MODIFIER_LOD_BIAS) { + FETCH(&c1, 3, TGSI_CHAN_X); + lod = &c1; + control = tgsi_sampler_lod_bias; + } + else if (modifier == TEX_MODIFIER_EXPLICIT_LOD) { + FETCH(&c1, 3, TGSI_CHAN_X); + lod = &c1; + control = tgsi_sampler_lod_explicit; + } + else { + assert(modifier == TEX_MODIFIER_LEVEL_ZERO); + control = tgsi_sampler_lod_zero; + } + } + + FETCH(&r[0], 0, TGSI_CHAN_X); + + switch (mach->SamplerViews[resource_unit].Resource) { + case TGSI_TEXTURE_1D: + if (compare) { + FETCH(&r[2], 3, TGSI_CHAN_X); + fetch_texel(mach->Sampler, resource_unit, sampler_unit, + &r[0], &ZeroVec, &r[2], &ZeroVec, lod, /* S, T, P, C, LOD */ + NULL, offsets, control, + &r[0], &r[1], &r[2], &r[3]); /* R, G, B, A */ + } + else { + fetch_texel(mach->Sampler, resource_unit, sampler_unit, + &r[0], &ZeroVec, &ZeroVec, &ZeroVec, lod, /* S, T, P, C, LOD */ + NULL, offsets, control, + &r[0], &r[1], &r[2], &r[3]); /* R, G, B, A */ + } + break; + + case TGSI_TEXTURE_1D_ARRAY: + case TGSI_TEXTURE_2D: + case TGSI_TEXTURE_RECT: + FETCH(&r[1], 0, TGSI_CHAN_Y); + if (compare) { + FETCH(&r[2], 3, TGSI_CHAN_X); + fetch_texel(mach->Sampler, resource_unit, sampler_unit, + &r[0], &r[1], &r[2], &ZeroVec, lod, /* S, T, P, C, LOD */ + NULL, offsets, control, + &r[0], &r[1], &r[2], &r[3]); /* outputs */ + } + else { + fetch_texel(mach->Sampler, resource_unit, sampler_unit, + &r[0], &r[1], &ZeroVec, &ZeroVec, lod, /* S, T, P, C, LOD */ + NULL, offsets, control, + &r[0], &r[1], &r[2], &r[3]); /* outputs */ + } + break; + + case TGSI_TEXTURE_2D_ARRAY: + case TGSI_TEXTURE_3D: + case TGSI_TEXTURE_CUBE: + FETCH(&r[1], 0, TGSI_CHAN_Y); + FETCH(&r[2], 0, TGSI_CHAN_Z); + if(compare) { + FETCH(&r[3], 3, TGSI_CHAN_X); + fetch_texel(mach->Sampler, resource_unit, sampler_unit, + &r[0], &r[1], &r[2], &r[3], lod, + NULL, offsets, control, + &r[0], &r[1], &r[2], &r[3]); + } + else { + fetch_texel(mach->Sampler, resource_unit, sampler_unit, + &r[0], &r[1], &r[2], &ZeroVec, lod, + NULL, offsets, control, + &r[0], &r[1], &r[2], &r[3]); + } + break; + + case TGSI_TEXTURE_CUBE_ARRAY: + FETCH(&r[1], 0, TGSI_CHAN_Y); + FETCH(&r[2], 0, TGSI_CHAN_Z); + FETCH(&r[3], 0, TGSI_CHAN_W); + if(compare) { + FETCH(&r[4], 3, TGSI_CHAN_X); + fetch_texel(mach->Sampler, resource_unit, sampler_unit, + &r[0], &r[1], &r[2], &r[3], &r[4], + NULL, offsets, control, + &r[0], &r[1], &r[2], &r[3]); + } + else { + fetch_texel(mach->Sampler, resource_unit, sampler_unit, + &r[0], &r[1], &r[2], &r[3], lod, + NULL, offsets, control, + &r[0], &r[1], &r[2], &r[3]); + } + break; + + + default: + assert(0); + } + + swizzles[0] = inst->Src[1].Register.SwizzleX; + swizzles[1] = inst->Src[1].Register.SwizzleY; + swizzles[2] = inst->Src[1].Register.SwizzleZ; + swizzles[3] = inst->Src[1].Register.SwizzleW; + + for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) { + if (inst->Dst[0].Register.WriteMask & (1 << chan)) { + store_dest(mach, &r[swizzles[chan]], + &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT); + } + } +} + +static void +exec_sample_d(struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst) +{ + const uint resource_unit = inst->Src[1].Register.Index; + const uint sampler_unit = inst->Src[2].Register.Index; + union tgsi_exec_channel r[4]; + float derivs[3][2][TGSI_QUAD_SIZE]; + uint chan; + unsigned char swizzles[4]; + int8_t offsets[3]; + + /* always fetch all 3 offsets, overkill but keeps code simple */ + fetch_texel_offsets(mach, inst, offsets); + + FETCH(&r[0], 0, TGSI_CHAN_X); + + switch (mach->SamplerViews[resource_unit].Resource) { + case TGSI_TEXTURE_1D: + case TGSI_TEXTURE_1D_ARRAY: + /* only 1D array actually needs Y */ + FETCH(&r[1], 0, TGSI_CHAN_Y); + + fetch_assign_deriv_channel(mach, inst, 3, TGSI_CHAN_X, derivs[0]); + + fetch_texel(mach->Sampler, resource_unit, sampler_unit, + &r[0], &r[1], &ZeroVec, &ZeroVec, &ZeroVec, /* S, T, P, C, LOD */ + derivs, offsets, tgsi_sampler_derivs_explicit, + &r[0], &r[1], &r[2], &r[3]); /* R, G, B, A */ + break; + + case TGSI_TEXTURE_2D: + case TGSI_TEXTURE_RECT: + case TGSI_TEXTURE_2D_ARRAY: + /* only 2D array actually needs Z */ + FETCH(&r[1], 0, TGSI_CHAN_Y); + FETCH(&r[2], 0, TGSI_CHAN_Z); + + fetch_assign_deriv_channel(mach, inst, 3, TGSI_CHAN_X, derivs[0]); + fetch_assign_deriv_channel(mach, inst, 3, TGSI_CHAN_Y, derivs[1]); + + fetch_texel(mach->Sampler, resource_unit, sampler_unit, + &r[0], &r[1], &r[2], &ZeroVec, &ZeroVec, /* inputs */ + derivs, offsets, tgsi_sampler_derivs_explicit, + &r[0], &r[1], &r[2], &r[3]); /* outputs */ + break; + + case TGSI_TEXTURE_3D: + case TGSI_TEXTURE_CUBE: + case TGSI_TEXTURE_CUBE_ARRAY: + /* only cube array actually needs W */ + FETCH(&r[1], 0, TGSI_CHAN_Y); + FETCH(&r[2], 0, TGSI_CHAN_Z); + FETCH(&r[3], 0, TGSI_CHAN_W); + + fetch_assign_deriv_channel(mach, inst, 3, TGSI_CHAN_X, derivs[0]); + fetch_assign_deriv_channel(mach, inst, 3, TGSI_CHAN_Y, derivs[1]); + fetch_assign_deriv_channel(mach, inst, 3, TGSI_CHAN_Z, derivs[2]); + + fetch_texel(mach->Sampler, resource_unit, sampler_unit, + &r[0], &r[1], &r[2], &r[3], &ZeroVec, + derivs, offsets, tgsi_sampler_derivs_explicit, + &r[0], &r[1], &r[2], &r[3]); + break; + + default: + assert(0); + } + + swizzles[0] = inst->Src[1].Register.SwizzleX; + swizzles[1] = inst->Src[1].Register.SwizzleY; + swizzles[2] = inst->Src[1].Register.SwizzleZ; + swizzles[3] = inst->Src[1].Register.SwizzleW; + + for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) { + if (inst->Dst[0].Register.WriteMask & (1 << chan)) { + store_dest(mach, &r[swizzles[chan]], + &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT); + } + } +} + + +/** + * Evaluate a constant-valued coefficient at the position of the + * current quad. + */ +static void +eval_constant_coef( + struct tgsi_exec_machine *mach, + unsigned attrib, + unsigned chan ) +{ + unsigned i; + + for( i = 0; i < TGSI_QUAD_SIZE; i++ ) { + mach->Inputs[attrib].xyzw[chan].f[i] = mach->InterpCoefs[attrib].a0[chan]; + } +} + +/** + * Evaluate a linear-valued coefficient at the position of the + * current quad. + */ +static void +eval_linear_coef( + struct tgsi_exec_machine *mach, + unsigned attrib, + unsigned chan ) +{ + const float x = mach->QuadPos.xyzw[0].f[0]; + const float y = mach->QuadPos.xyzw[1].f[0]; + const float dadx = mach->InterpCoefs[attrib].dadx[chan]; + const float dady = mach->InterpCoefs[attrib].dady[chan]; + const float a0 = mach->InterpCoefs[attrib].a0[chan] + dadx * x + dady * y; + mach->Inputs[attrib].xyzw[chan].f[0] = a0; + mach->Inputs[attrib].xyzw[chan].f[1] = a0 + dadx; + mach->Inputs[attrib].xyzw[chan].f[2] = a0 + dady; + mach->Inputs[attrib].xyzw[chan].f[3] = a0 + dadx + dady; +} + +/** + * Evaluate a perspective-valued coefficient at the position of the + * current quad. + */ +static void +eval_perspective_coef( + struct tgsi_exec_machine *mach, + unsigned attrib, + unsigned chan ) +{ + const float x = mach->QuadPos.xyzw[0].f[0]; + const float y = mach->QuadPos.xyzw[1].f[0]; + const float dadx = mach->InterpCoefs[attrib].dadx[chan]; + const float dady = mach->InterpCoefs[attrib].dady[chan]; + const float a0 = mach->InterpCoefs[attrib].a0[chan] + dadx * x + dady * y; + const float *w = mach->QuadPos.xyzw[3].f; + /* divide by W here */ + mach->Inputs[attrib].xyzw[chan].f[0] = a0 / w[0]; + mach->Inputs[attrib].xyzw[chan].f[1] = (a0 + dadx) / w[1]; + mach->Inputs[attrib].xyzw[chan].f[2] = (a0 + dady) / w[2]; + mach->Inputs[attrib].xyzw[chan].f[3] = (a0 + dadx + dady) / w[3]; +} + + +typedef void (* eval_coef_func)( + struct tgsi_exec_machine *mach, + unsigned attrib, + unsigned chan ); + +static void +exec_declaration(struct tgsi_exec_machine *mach, + const struct tgsi_full_declaration *decl) +{ + if (decl->Declaration.File == TGSI_FILE_SAMPLER_VIEW) { + mach->SamplerViews[decl->Range.First] = decl->SamplerView; + return; + } + + if (mach->Processor == TGSI_PROCESSOR_FRAGMENT) { + if (decl->Declaration.File == TGSI_FILE_INPUT) { + uint first, last, mask; + + first = decl->Range.First; + last = decl->Range.Last; + mask = decl->Declaration.UsageMask; + + /* XXX we could remove this special-case code since + * mach->InterpCoefs[first].a0 should already have the + * front/back-face value. But we should first update the + * ureg code to emit the right UsageMask value (WRITEMASK_X). + * Then, we could remove the tgsi_exec_machine::Face field. + */ + /* XXX make FACE a system value */ + if (decl->Semantic.Name == TGSI_SEMANTIC_FACE) { + uint i; + + assert(decl->Semantic.Index == 0); + assert(first == last); + + for (i = 0; i < TGSI_QUAD_SIZE; i++) { + mach->Inputs[first].xyzw[0].f[i] = mach->Face; + } + } else { + eval_coef_func eval; + uint i, j; + + switch (decl->Interp.Interpolate) { + case TGSI_INTERPOLATE_CONSTANT: + eval = eval_constant_coef; + break; + + case TGSI_INTERPOLATE_LINEAR: + eval = eval_linear_coef; + break; + + case TGSI_INTERPOLATE_PERSPECTIVE: + eval = eval_perspective_coef; + break; + + case TGSI_INTERPOLATE_COLOR: + eval = mach->flatshade_color ? eval_constant_coef : eval_perspective_coef; + break; + + default: + assert(0); + return; + } + + for (j = 0; j < TGSI_NUM_CHANNELS; j++) { + if (mask & (1 << j)) { + for (i = first; i <= last; i++) { + eval(mach, i, j); + } + } + } + } + + if (DEBUG_EXECUTION) { + uint i, j; + for (i = first; i <= last; ++i) { + debug_printf("IN[%2u] = ", i); + for (j = 0; j < TGSI_NUM_CHANNELS; j++) { + if (j > 0) { + debug_printf(" "); + } + debug_printf("(%6f %u, %6f %u, %6f %u, %6f %u)\n", + mach->Inputs[i].xyzw[0].f[j], mach->Inputs[i].xyzw[0].u[j], + mach->Inputs[i].xyzw[1].f[j], mach->Inputs[i].xyzw[1].u[j], + mach->Inputs[i].xyzw[2].f[j], mach->Inputs[i].xyzw[2].u[j], + mach->Inputs[i].xyzw[3].f[j], mach->Inputs[i].xyzw[3].u[j]); + } + } + } + } + } + + if (decl->Declaration.File == TGSI_FILE_SYSTEM_VALUE) { + mach->SysSemanticToIndex[decl->Declaration.Semantic] = decl->Range.First; + } +} + + +typedef void (* micro_op)(union tgsi_exec_channel *dst); + +static void +exec_vector(struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst, + micro_op op, + enum tgsi_exec_datatype dst_datatype) +{ + unsigned int chan; + + for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) { + if (inst->Dst[0].Register.WriteMask & (1 << chan)) { + union tgsi_exec_channel dst; + + op(&dst); + store_dest(mach, &dst, &inst->Dst[0], inst, chan, dst_datatype); + } + } +} + +typedef void (* micro_unary_op)(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src); + +static void +exec_scalar_unary(struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst, + micro_unary_op op, + enum tgsi_exec_datatype dst_datatype, + enum tgsi_exec_datatype src_datatype) +{ + unsigned int chan; + union tgsi_exec_channel src; + union tgsi_exec_channel dst; + + fetch_source(mach, &src, &inst->Src[0], TGSI_CHAN_X, src_datatype); + op(&dst, &src); + for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) { + if (inst->Dst[0].Register.WriteMask & (1 << chan)) { + store_dest(mach, &dst, &inst->Dst[0], inst, chan, dst_datatype); + } + } +} + +static void +exec_vector_unary(struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst, + micro_unary_op op, + enum tgsi_exec_datatype dst_datatype, + enum tgsi_exec_datatype src_datatype) +{ + unsigned int chan; + struct tgsi_exec_vector dst; + + for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) { + if (inst->Dst[0].Register.WriteMask & (1 << chan)) { + union tgsi_exec_channel src; + + fetch_source(mach, &src, &inst->Src[0], chan, src_datatype); + op(&dst.xyzw[chan], &src); + } + } + for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) { + if (inst->Dst[0].Register.WriteMask & (1 << chan)) { + store_dest(mach, &dst.xyzw[chan], &inst->Dst[0], inst, chan, dst_datatype); + } + } +} + +typedef void (* micro_binary_op)(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1); + +static void +exec_scalar_binary(struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst, + micro_binary_op op, + enum tgsi_exec_datatype dst_datatype, + enum tgsi_exec_datatype src_datatype) +{ + unsigned int chan; + union tgsi_exec_channel src[2]; + union tgsi_exec_channel dst; + + fetch_source(mach, &src[0], &inst->Src[0], TGSI_CHAN_X, src_datatype); + fetch_source(mach, &src[1], &inst->Src[1], TGSI_CHAN_X, src_datatype); + op(&dst, &src[0], &src[1]); + for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) { + if (inst->Dst[0].Register.WriteMask & (1 << chan)) { + store_dest(mach, &dst, &inst->Dst[0], inst, chan, dst_datatype); + } + } +} + +static void +exec_vector_binary(struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst, + micro_binary_op op, + enum tgsi_exec_datatype dst_datatype, + enum tgsi_exec_datatype src_datatype) +{ + unsigned int chan; + struct tgsi_exec_vector dst; + + for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) { + if (inst->Dst[0].Register.WriteMask & (1 << chan)) { + union tgsi_exec_channel src[2]; + + fetch_source(mach, &src[0], &inst->Src[0], chan, src_datatype); + fetch_source(mach, &src[1], &inst->Src[1], chan, src_datatype); + op(&dst.xyzw[chan], &src[0], &src[1]); + } + } + for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) { + if (inst->Dst[0].Register.WriteMask & (1 << chan)) { + store_dest(mach, &dst.xyzw[chan], &inst->Dst[0], inst, chan, dst_datatype); + } + } +} + +typedef void (* micro_trinary_op)(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1, + const union tgsi_exec_channel *src2); + +static void +exec_vector_trinary(struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst, + micro_trinary_op op, + enum tgsi_exec_datatype dst_datatype, + enum tgsi_exec_datatype src_datatype) +{ + unsigned int chan; + struct tgsi_exec_vector dst; + + for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) { + if (inst->Dst[0].Register.WriteMask & (1 << chan)) { + union tgsi_exec_channel src[3]; + + fetch_source(mach, &src[0], &inst->Src[0], chan, src_datatype); + fetch_source(mach, &src[1], &inst->Src[1], chan, src_datatype); + fetch_source(mach, &src[2], &inst->Src[2], chan, src_datatype); + op(&dst.xyzw[chan], &src[0], &src[1], &src[2]); + } + } + for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) { + if (inst->Dst[0].Register.WriteMask & (1 << chan)) { + store_dest(mach, &dst.xyzw[chan], &inst->Dst[0], inst, chan, dst_datatype); + } + } +} + +static void +exec_dp3(struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst) +{ + unsigned int chan; + union tgsi_exec_channel arg[3]; + + fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT); + fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT); + micro_mul(&arg[2], &arg[0], &arg[1]); + + for (chan = TGSI_CHAN_Y; chan <= TGSI_CHAN_Z; chan++) { + fetch_source(mach, &arg[0], &inst->Src[0], chan, TGSI_EXEC_DATA_FLOAT); + fetch_source(mach, &arg[1], &inst->Src[1], chan, TGSI_EXEC_DATA_FLOAT); + micro_mad(&arg[2], &arg[0], &arg[1], &arg[2]); + } + + for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) { + if (inst->Dst[0].Register.WriteMask & (1 << chan)) { + store_dest(mach, &arg[2], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT); + } + } +} + +static void +exec_dp4(struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst) +{ + unsigned int chan; + union tgsi_exec_channel arg[3]; + + fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT); + fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT); + micro_mul(&arg[2], &arg[0], &arg[1]); + + for (chan = TGSI_CHAN_Y; chan <= TGSI_CHAN_W; chan++) { + fetch_source(mach, &arg[0], &inst->Src[0], chan, TGSI_EXEC_DATA_FLOAT); + fetch_source(mach, &arg[1], &inst->Src[1], chan, TGSI_EXEC_DATA_FLOAT); + micro_mad(&arg[2], &arg[0], &arg[1], &arg[2]); + } + + for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) { + if (inst->Dst[0].Register.WriteMask & (1 << chan)) { + store_dest(mach, &arg[2], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT); + } + } +} + +static void +exec_dp2a(struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst) +{ + unsigned int chan; + union tgsi_exec_channel arg[3]; + + fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT); + fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT); + micro_mul(&arg[2], &arg[0], &arg[1]); + + fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT); + fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT); + micro_mad(&arg[0], &arg[0], &arg[1], &arg[2]); + + fetch_source(mach, &arg[1], &inst->Src[2], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT); + micro_add(&arg[0], &arg[0], &arg[1]); + + for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) { + if (inst->Dst[0].Register.WriteMask & (1 << chan)) { + store_dest(mach, &arg[0], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT); + } + } +} + +static void +exec_dph(struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst) +{ + unsigned int chan; + union tgsi_exec_channel arg[3]; + + fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT); + fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT); + micro_mul(&arg[2], &arg[0], &arg[1]); + + fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT); + fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT); + micro_mad(&arg[2], &arg[0], &arg[1], &arg[2]); + + fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT); + fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT); + micro_mad(&arg[0], &arg[0], &arg[1], &arg[2]); + + fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT); + micro_add(&arg[0], &arg[0], &arg[1]); + + for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) { + if (inst->Dst[0].Register.WriteMask & (1 << chan)) { + store_dest(mach, &arg[0], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT); + } + } +} + +static void +exec_dp2(struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst) +{ + unsigned int chan; + union tgsi_exec_channel arg[3]; + + fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT); + fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT); + micro_mul(&arg[2], &arg[0], &arg[1]); + + fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT); + fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT); + micro_mad(&arg[2], &arg[0], &arg[1], &arg[2]); + + for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) { + if (inst->Dst[0].Register.WriteMask & (1 << chan)) { + store_dest(mach, &arg[2], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT); + } + } +} + +static void +exec_nrm4(struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst) +{ + unsigned int chan; + union tgsi_exec_channel arg[4]; + union tgsi_exec_channel scale; + + fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT); + micro_mul(&scale, &arg[0], &arg[0]); + + for (chan = TGSI_CHAN_Y; chan <= TGSI_CHAN_W; chan++) { + union tgsi_exec_channel product; + + fetch_source(mach, &arg[chan], &inst->Src[0], chan, TGSI_EXEC_DATA_FLOAT); + micro_mul(&product, &arg[chan], &arg[chan]); + micro_add(&scale, &scale, &product); + } + + micro_rsq(&scale, &scale); + + for (chan = TGSI_CHAN_X; chan <= TGSI_CHAN_W; chan++) { + if (inst->Dst[0].Register.WriteMask & (1 << chan)) { + micro_mul(&arg[chan], &arg[chan], &scale); + store_dest(mach, &arg[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT); + } + } +} + +static void +exec_nrm3(struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst) +{ + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_XYZ) { + unsigned int chan; + union tgsi_exec_channel arg[3]; + union tgsi_exec_channel scale; + + fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT); + micro_mul(&scale, &arg[0], &arg[0]); + + for (chan = TGSI_CHAN_Y; chan <= TGSI_CHAN_Z; chan++) { + union tgsi_exec_channel product; + + fetch_source(mach, &arg[chan], &inst->Src[0], chan, TGSI_EXEC_DATA_FLOAT); + micro_mul(&product, &arg[chan], &arg[chan]); + micro_add(&scale, &scale, &product); + } + + micro_rsq(&scale, &scale); + + for (chan = TGSI_CHAN_X; chan <= TGSI_CHAN_Z; chan++) { + if (inst->Dst[0].Register.WriteMask & (1 << chan)) { + micro_mul(&arg[chan], &arg[chan], &scale); + store_dest(mach, &arg[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT); + } + } + } + + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_W) { + store_dest(mach, &OneVec, &inst->Dst[0], inst, TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT); + } +} + +static void +exec_scs(struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst) +{ + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_XY) { + union tgsi_exec_channel arg; + union tgsi_exec_channel result; + + fetch_source(mach, &arg, &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT); + + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_X) { + micro_cos(&result, &arg); + store_dest(mach, &result, &inst->Dst[0], inst, TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT); + } + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) { + micro_sin(&result, &arg); + store_dest(mach, &result, &inst->Dst[0], inst, TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT); + } + } + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Z) { + store_dest(mach, &ZeroVec, &inst->Dst[0], inst, TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT); + } + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_W) { + store_dest(mach, &OneVec, &inst->Dst[0], inst, TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT); + } +} + +static void +exec_x2d(struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst) +{ + union tgsi_exec_channel r[4]; + union tgsi_exec_channel d[2]; + + fetch_source(mach, &r[0], &inst->Src[1], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT); + fetch_source(mach, &r[1], &inst->Src[1], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT); + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_XZ) { + fetch_source(mach, &r[2], &inst->Src[2], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT); + micro_mul(&r[2], &r[2], &r[0]); + fetch_source(mach, &r[3], &inst->Src[2], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT); + micro_mul(&r[3], &r[3], &r[1]); + micro_add(&r[2], &r[2], &r[3]); + fetch_source(mach, &r[3], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT); + micro_add(&d[0], &r[2], &r[3]); + } + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_YW) { + fetch_source(mach, &r[2], &inst->Src[2], TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT); + micro_mul(&r[2], &r[2], &r[0]); + fetch_source(mach, &r[3], &inst->Src[2], TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT); + micro_mul(&r[3], &r[3], &r[1]); + micro_add(&r[2], &r[2], &r[3]); + fetch_source(mach, &r[3], &inst->Src[0], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT); + micro_add(&d[1], &r[2], &r[3]); + } + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_X) { + store_dest(mach, &d[0], &inst->Dst[0], inst, TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT); + } + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) { + store_dest(mach, &d[1], &inst->Dst[0], inst, TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT); + } + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Z) { + store_dest(mach, &d[0], &inst->Dst[0], inst, TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT); + } + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_W) { + store_dest(mach, &d[1], &inst->Dst[0], inst, TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT); + } +} + +static void +exec_rfl(struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst) +{ + union tgsi_exec_channel r[9]; + + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_XYZ) { + /* r0 = dp3(src0, src0) */ + fetch_source(mach, &r[2], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT); + micro_mul(&r[0], &r[2], &r[2]); + fetch_source(mach, &r[4], &inst->Src[0], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT); + micro_mul(&r[8], &r[4], &r[4]); + micro_add(&r[0], &r[0], &r[8]); + fetch_source(mach, &r[6], &inst->Src[0], TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT); + micro_mul(&r[8], &r[6], &r[6]); + micro_add(&r[0], &r[0], &r[8]); + + /* r1 = dp3(src0, src1) */ + fetch_source(mach, &r[3], &inst->Src[1], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT); + micro_mul(&r[1], &r[2], &r[3]); + fetch_source(mach, &r[5], &inst->Src[1], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT); + micro_mul(&r[8], &r[4], &r[5]); + micro_add(&r[1], &r[1], &r[8]); + fetch_source(mach, &r[7], &inst->Src[1], TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT); + micro_mul(&r[8], &r[6], &r[7]); + micro_add(&r[1], &r[1], &r[8]); + + /* r1 = 2 * r1 / r0 */ + micro_add(&r[1], &r[1], &r[1]); + micro_div(&r[1], &r[1], &r[0]); + + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_X) { + micro_mul(&r[2], &r[2], &r[1]); + micro_sub(&r[2], &r[2], &r[3]); + store_dest(mach, &r[2], &inst->Dst[0], inst, TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT); + } + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) { + micro_mul(&r[4], &r[4], &r[1]); + micro_sub(&r[4], &r[4], &r[5]); + store_dest(mach, &r[4], &inst->Dst[0], inst, TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT); + } + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Z) { + micro_mul(&r[6], &r[6], &r[1]); + micro_sub(&r[6], &r[6], &r[7]); + store_dest(mach, &r[6], &inst->Dst[0], inst, TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT); + } + } + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_W) { + store_dest(mach, &OneVec, &inst->Dst[0], inst, TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT); + } +} + +static void +exec_xpd(struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst) +{ + union tgsi_exec_channel r[6]; + union tgsi_exec_channel d[3]; + + fetch_source(mach, &r[0], &inst->Src[0], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT); + fetch_source(mach, &r[1], &inst->Src[1], TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT); + + micro_mul(&r[2], &r[0], &r[1]); + + fetch_source(mach, &r[3], &inst->Src[0], TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT); + fetch_source(mach, &r[4], &inst->Src[1], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT); + + micro_mul(&r[5], &r[3], &r[4] ); + micro_sub(&d[TGSI_CHAN_X], &r[2], &r[5]); + + fetch_source(mach, &r[2], &inst->Src[1], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT); + + micro_mul(&r[3], &r[3], &r[2]); + + fetch_source(mach, &r[5], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT); + + micro_mul(&r[1], &r[1], &r[5]); + micro_sub(&d[TGSI_CHAN_Y], &r[3], &r[1]); + + micro_mul(&r[5], &r[5], &r[4]); + micro_mul(&r[0], &r[0], &r[2]); + micro_sub(&d[TGSI_CHAN_Z], &r[5], &r[0]); + + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_X) { + store_dest(mach, &d[TGSI_CHAN_X], &inst->Dst[0], inst, TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT); + } + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) { + store_dest(mach, &d[TGSI_CHAN_Y], &inst->Dst[0], inst, TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT); + } + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Z) { + store_dest(mach, &d[TGSI_CHAN_Z], &inst->Dst[0], inst, TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT); + } + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_W) { + store_dest(mach, &OneVec, &inst->Dst[0], inst, TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT); + } +} + +static void +exec_dst(struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst) +{ + union tgsi_exec_channel r[2]; + union tgsi_exec_channel d[4]; + + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) { + fetch_source(mach, &r[0], &inst->Src[0], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT); + fetch_source(mach, &r[1], &inst->Src[1], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT); + micro_mul(&d[TGSI_CHAN_Y], &r[0], &r[1]); + } + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Z) { + fetch_source(mach, &d[TGSI_CHAN_Z], &inst->Src[0], TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT); + } + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_W) { + fetch_source(mach, &d[TGSI_CHAN_W], &inst->Src[1], TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT); + } + + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_X) { + store_dest(mach, &OneVec, &inst->Dst[0], inst, TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT); + } + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) { + store_dest(mach, &d[TGSI_CHAN_Y], &inst->Dst[0], inst, TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT); + } + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Z) { + store_dest(mach, &d[TGSI_CHAN_Z], &inst->Dst[0], inst, TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT); + } + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_W) { + store_dest(mach, &d[TGSI_CHAN_W], &inst->Dst[0], inst, TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT); + } +} + +static void +exec_log(struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst) +{ + union tgsi_exec_channel r[3]; + + fetch_source(mach, &r[0], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT); + micro_abs(&r[2], &r[0]); /* r2 = abs(r0) */ + micro_lg2(&r[1], &r[2]); /* r1 = lg2(r2) */ + micro_flr(&r[0], &r[1]); /* r0 = floor(r1) */ + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_X) { + store_dest(mach, &r[0], &inst->Dst[0], inst, TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT); + } + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) { + micro_exp2(&r[0], &r[0]); /* r0 = 2 ^ r0 */ + micro_div(&r[0], &r[2], &r[0]); /* r0 = r2 / r0 */ + store_dest(mach, &r[0], &inst->Dst[0], inst, TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT); + } + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Z) { + store_dest(mach, &r[1], &inst->Dst[0], inst, TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT); + } + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_W) { + store_dest(mach, &OneVec, &inst->Dst[0], inst, TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT); + } +} + +static void +exec_exp(struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst) +{ + union tgsi_exec_channel r[3]; + + fetch_source(mach, &r[0], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT); + micro_flr(&r[1], &r[0]); /* r1 = floor(r0) */ + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_X) { + micro_exp2(&r[2], &r[1]); /* r2 = 2 ^ r1 */ + store_dest(mach, &r[2], &inst->Dst[0], inst, TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT); + } + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) { + micro_sub(&r[2], &r[0], &r[1]); /* r2 = r0 - r1 */ + store_dest(mach, &r[2], &inst->Dst[0], inst, TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT); + } + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Z) { + micro_exp2(&r[2], &r[0]); /* r2 = 2 ^ r0 */ + store_dest(mach, &r[2], &inst->Dst[0], inst, TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT); + } + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_W) { + store_dest(mach, &OneVec, &inst->Dst[0], inst, TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT); + } +} + +static void +exec_lit(struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst) +{ + union tgsi_exec_channel r[3]; + union tgsi_exec_channel d[3]; + + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_YZ) { + fetch_source(mach, &r[0], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT); + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Z) { + fetch_source(mach, &r[1], &inst->Src[0], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT); + micro_max(&r[1], &r[1], &ZeroVec); + + fetch_source(mach, &r[2], &inst->Src[0], TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT); + micro_min(&r[2], &r[2], &P128Vec); + micro_max(&r[2], &r[2], &M128Vec); + micro_pow(&r[1], &r[1], &r[2]); + micro_lt(&d[TGSI_CHAN_Z], &ZeroVec, &r[0], &r[1], &ZeroVec); + store_dest(mach, &d[TGSI_CHAN_Z], &inst->Dst[0], inst, TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT); + } + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) { + micro_max(&d[TGSI_CHAN_Y], &r[0], &ZeroVec); + store_dest(mach, &d[TGSI_CHAN_Y], &inst->Dst[0], inst, TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT); + } + } + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_X) { + store_dest(mach, &OneVec, &inst->Dst[0], inst, TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT); + } + + if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_W) { + store_dest(mach, &OneVec, &inst->Dst[0], inst, TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT); + } +} + +static void +exec_break(struct tgsi_exec_machine *mach) +{ + if (mach->BreakType == TGSI_EXEC_BREAK_INSIDE_LOOP) { + /* turn off loop channels for each enabled exec channel */ + mach->LoopMask &= ~mach->ExecMask; + /* Todo: if mach->LoopMask == 0, jump to end of loop */ + UPDATE_EXEC_MASK(mach); + } else { + assert(mach->BreakType == TGSI_EXEC_BREAK_INSIDE_SWITCH); + + mach->Switch.mask = 0x0; + + UPDATE_EXEC_MASK(mach); + } +} + +static void +exec_switch(struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst) +{ + assert(mach->SwitchStackTop < TGSI_EXEC_MAX_SWITCH_NESTING); + assert(mach->BreakStackTop < TGSI_EXEC_MAX_BREAK_STACK); + + mach->SwitchStack[mach->SwitchStackTop++] = mach->Switch; + fetch_source(mach, &mach->Switch.selector, &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_UINT); + mach->Switch.mask = 0x0; + mach->Switch.defaultMask = 0x0; + + mach->BreakStack[mach->BreakStackTop++] = mach->BreakType; + mach->BreakType = TGSI_EXEC_BREAK_INSIDE_SWITCH; + + UPDATE_EXEC_MASK(mach); +} + +static void +exec_case(struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst) +{ + uint prevMask = mach->SwitchStack[mach->SwitchStackTop - 1].mask; + union tgsi_exec_channel src; + uint mask = 0; + + fetch_source(mach, &src, &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_UINT); + + if (mach->Switch.selector.u[0] == src.u[0]) { + mask |= 0x1; + } + if (mach->Switch.selector.u[1] == src.u[1]) { + mask |= 0x2; + } + if (mach->Switch.selector.u[2] == src.u[2]) { + mask |= 0x4; + } + if (mach->Switch.selector.u[3] == src.u[3]) { + mask |= 0x8; + } + + mach->Switch.defaultMask |= mask; + + mach->Switch.mask |= mask & prevMask; + + UPDATE_EXEC_MASK(mach); +} + +/* FIXME: this will only work if default is last */ +static void +exec_default(struct tgsi_exec_machine *mach) +{ + uint prevMask = mach->SwitchStack[mach->SwitchStackTop - 1].mask; + + mach->Switch.mask |= ~mach->Switch.defaultMask & prevMask; + + UPDATE_EXEC_MASK(mach); +} + +static void +exec_endswitch(struct tgsi_exec_machine *mach) +{ + mach->Switch = mach->SwitchStack[--mach->SwitchStackTop]; + mach->BreakType = mach->BreakStack[--mach->BreakStackTop]; + + UPDATE_EXEC_MASK(mach); +} + +static void +micro_i2f(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src) +{ + dst->f[0] = (float)src->i[0]; + dst->f[1] = (float)src->i[1]; + dst->f[2] = (float)src->i[2]; + dst->f[3] = (float)src->i[3]; +} + +static void +micro_not(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src) +{ + dst->u[0] = ~src->u[0]; + dst->u[1] = ~src->u[1]; + dst->u[2] = ~src->u[2]; + dst->u[3] = ~src->u[3]; +} + +static void +micro_shl(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + unsigned masked_count; + masked_count = src1->u[0] & 0x1f; + dst->u[0] = src0->u[0] << masked_count; + masked_count = src1->u[1] & 0x1f; + dst->u[1] = src0->u[1] << masked_count; + masked_count = src1->u[2] & 0x1f; + dst->u[2] = src0->u[2] << masked_count; + masked_count = src1->u[3] & 0x1f; + dst->u[3] = src0->u[3] << masked_count; +} + +static void +micro_and(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + dst->u[0] = src0->u[0] & src1->u[0]; + dst->u[1] = src0->u[1] & src1->u[1]; + dst->u[2] = src0->u[2] & src1->u[2]; + dst->u[3] = src0->u[3] & src1->u[3]; +} + +static void +micro_or(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + dst->u[0] = src0->u[0] | src1->u[0]; + dst->u[1] = src0->u[1] | src1->u[1]; + dst->u[2] = src0->u[2] | src1->u[2]; + dst->u[3] = src0->u[3] | src1->u[3]; +} + +static void +micro_xor(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + dst->u[0] = src0->u[0] ^ src1->u[0]; + dst->u[1] = src0->u[1] ^ src1->u[1]; + dst->u[2] = src0->u[2] ^ src1->u[2]; + dst->u[3] = src0->u[3] ^ src1->u[3]; +} + +static void +micro_mod(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + dst->i[0] = src0->i[0] % src1->i[0]; + dst->i[1] = src0->i[1] % src1->i[1]; + dst->i[2] = src0->i[2] % src1->i[2]; + dst->i[3] = src0->i[3] % src1->i[3]; +} + +static void +micro_f2i(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src) +{ + dst->i[0] = (int)src->f[0]; + dst->i[1] = (int)src->f[1]; + dst->i[2] = (int)src->f[2]; + dst->i[3] = (int)src->f[3]; +} + +static void +micro_fseq(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + dst->u[0] = src0->f[0] == src1->f[0] ? ~0 : 0; + dst->u[1] = src0->f[1] == src1->f[1] ? ~0 : 0; + dst->u[2] = src0->f[2] == src1->f[2] ? ~0 : 0; + dst->u[3] = src0->f[3] == src1->f[3] ? ~0 : 0; +} + +static void +micro_fsge(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + dst->u[0] = src0->f[0] >= src1->f[0] ? ~0 : 0; + dst->u[1] = src0->f[1] >= src1->f[1] ? ~0 : 0; + dst->u[2] = src0->f[2] >= src1->f[2] ? ~0 : 0; + dst->u[3] = src0->f[3] >= src1->f[3] ? ~0 : 0; +} + +static void +micro_fslt(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + dst->u[0] = src0->f[0] < src1->f[0] ? ~0 : 0; + dst->u[1] = src0->f[1] < src1->f[1] ? ~0 : 0; + dst->u[2] = src0->f[2] < src1->f[2] ? ~0 : 0; + dst->u[3] = src0->f[3] < src1->f[3] ? ~0 : 0; +} + +static void +micro_fsne(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + dst->u[0] = src0->f[0] != src1->f[0] ? ~0 : 0; + dst->u[1] = src0->f[1] != src1->f[1] ? ~0 : 0; + dst->u[2] = src0->f[2] != src1->f[2] ? ~0 : 0; + dst->u[3] = src0->f[3] != src1->f[3] ? ~0 : 0; +} + +static void +micro_idiv(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + dst->i[0] = src0->i[0] / src1->i[0]; + dst->i[1] = src0->i[1] / src1->i[1]; + dst->i[2] = src0->i[2] / src1->i[2]; + dst->i[3] = src0->i[3] / src1->i[3]; +} + +static void +micro_imax(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + dst->i[0] = src0->i[0] > src1->i[0] ? src0->i[0] : src1->i[0]; + dst->i[1] = src0->i[1] > src1->i[1] ? src0->i[1] : src1->i[1]; + dst->i[2] = src0->i[2] > src1->i[2] ? src0->i[2] : src1->i[2]; + dst->i[3] = src0->i[3] > src1->i[3] ? src0->i[3] : src1->i[3]; +} + +static void +micro_imin(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + dst->i[0] = src0->i[0] < src1->i[0] ? src0->i[0] : src1->i[0]; + dst->i[1] = src0->i[1] < src1->i[1] ? src0->i[1] : src1->i[1]; + dst->i[2] = src0->i[2] < src1->i[2] ? src0->i[2] : src1->i[2]; + dst->i[3] = src0->i[3] < src1->i[3] ? src0->i[3] : src1->i[3]; +} + +static void +micro_isge(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + dst->i[0] = src0->i[0] >= src1->i[0] ? -1 : 0; + dst->i[1] = src0->i[1] >= src1->i[1] ? -1 : 0; + dst->i[2] = src0->i[2] >= src1->i[2] ? -1 : 0; + dst->i[3] = src0->i[3] >= src1->i[3] ? -1 : 0; +} + +static void +micro_ishr(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + unsigned masked_count; + masked_count = src1->i[0] & 0x1f; + dst->i[0] = src0->i[0] >> masked_count; + masked_count = src1->i[1] & 0x1f; + dst->i[1] = src0->i[1] >> masked_count; + masked_count = src1->i[2] & 0x1f; + dst->i[2] = src0->i[2] >> masked_count; + masked_count = src1->i[3] & 0x1f; + dst->i[3] = src0->i[3] >> masked_count; +} + +static void +micro_islt(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + dst->i[0] = src0->i[0] < src1->i[0] ? -1 : 0; + dst->i[1] = src0->i[1] < src1->i[1] ? -1 : 0; + dst->i[2] = src0->i[2] < src1->i[2] ? -1 : 0; + dst->i[3] = src0->i[3] < src1->i[3] ? -1 : 0; +} + +static void +micro_f2u(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src) +{ + dst->u[0] = (uint)src->f[0]; + dst->u[1] = (uint)src->f[1]; + dst->u[2] = (uint)src->f[2]; + dst->u[3] = (uint)src->f[3]; +} + +static void +micro_u2f(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src) +{ + dst->f[0] = (float)src->u[0]; + dst->f[1] = (float)src->u[1]; + dst->f[2] = (float)src->u[2]; + dst->f[3] = (float)src->u[3]; +} + +static void +micro_uadd(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + dst->u[0] = src0->u[0] + src1->u[0]; + dst->u[1] = src0->u[1] + src1->u[1]; + dst->u[2] = src0->u[2] + src1->u[2]; + dst->u[3] = src0->u[3] + src1->u[3]; +} + +static void +micro_udiv(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + dst->u[0] = src1->u[0] ? src0->u[0] / src1->u[0] : ~0u; + dst->u[1] = src1->u[1] ? src0->u[1] / src1->u[1] : ~0u; + dst->u[2] = src1->u[2] ? src0->u[2] / src1->u[2] : ~0u; + dst->u[3] = src1->u[3] ? src0->u[3] / src1->u[3] : ~0u; +} + +static void +micro_umad(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1, + const union tgsi_exec_channel *src2) +{ + dst->u[0] = src0->u[0] * src1->u[0] + src2->u[0]; + dst->u[1] = src0->u[1] * src1->u[1] + src2->u[1]; + dst->u[2] = src0->u[2] * src1->u[2] + src2->u[2]; + dst->u[3] = src0->u[3] * src1->u[3] + src2->u[3]; +} + +static void +micro_umax(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + dst->u[0] = src0->u[0] > src1->u[0] ? src0->u[0] : src1->u[0]; + dst->u[1] = src0->u[1] > src1->u[1] ? src0->u[1] : src1->u[1]; + dst->u[2] = src0->u[2] > src1->u[2] ? src0->u[2] : src1->u[2]; + dst->u[3] = src0->u[3] > src1->u[3] ? src0->u[3] : src1->u[3]; +} + +static void +micro_umin(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + dst->u[0] = src0->u[0] < src1->u[0] ? src0->u[0] : src1->u[0]; + dst->u[1] = src0->u[1] < src1->u[1] ? src0->u[1] : src1->u[1]; + dst->u[2] = src0->u[2] < src1->u[2] ? src0->u[2] : src1->u[2]; + dst->u[3] = src0->u[3] < src1->u[3] ? src0->u[3] : src1->u[3]; +} + +static void +micro_umod(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + dst->u[0] = src1->u[0] ? src0->u[0] % src1->u[0] : ~0u; + dst->u[1] = src1->u[1] ? src0->u[1] % src1->u[1] : ~0u; + dst->u[2] = src1->u[2] ? src0->u[2] % src1->u[2] : ~0u; + dst->u[3] = src1->u[3] ? src0->u[3] % src1->u[3] : ~0u; +} + +static void +micro_umul(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + dst->u[0] = src0->u[0] * src1->u[0]; + dst->u[1] = src0->u[1] * src1->u[1]; + dst->u[2] = src0->u[2] * src1->u[2]; + dst->u[3] = src0->u[3] * src1->u[3]; +} + +static void +micro_imul_hi(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ +#define I64M(x, y) ((((int64_t)x) * ((int64_t)y)) >> 32) + dst->i[0] = I64M(src0->i[0], src1->i[0]); + dst->i[1] = I64M(src0->i[1], src1->i[1]); + dst->i[2] = I64M(src0->i[2], src1->i[2]); + dst->i[3] = I64M(src0->i[3], src1->i[3]); +#undef I64M +} + +static void +micro_umul_hi(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ +#define U64M(x, y) ((((uint64_t)x) * ((uint64_t)y)) >> 32) + dst->u[0] = U64M(src0->u[0], src1->u[0]); + dst->u[1] = U64M(src0->u[1], src1->u[1]); + dst->u[2] = U64M(src0->u[2], src1->u[2]); + dst->u[3] = U64M(src0->u[3], src1->u[3]); +#undef U64M +} + +static void +micro_useq(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + dst->u[0] = src0->u[0] == src1->u[0] ? ~0 : 0; + dst->u[1] = src0->u[1] == src1->u[1] ? ~0 : 0; + dst->u[2] = src0->u[2] == src1->u[2] ? ~0 : 0; + dst->u[3] = src0->u[3] == src1->u[3] ? ~0 : 0; +} + +static void +micro_usge(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + dst->u[0] = src0->u[0] >= src1->u[0] ? ~0 : 0; + dst->u[1] = src0->u[1] >= src1->u[1] ? ~0 : 0; + dst->u[2] = src0->u[2] >= src1->u[2] ? ~0 : 0; + dst->u[3] = src0->u[3] >= src1->u[3] ? ~0 : 0; +} + +static void +micro_ushr(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + unsigned masked_count; + masked_count = src1->u[0] & 0x1f; + dst->u[0] = src0->u[0] >> masked_count; + masked_count = src1->u[1] & 0x1f; + dst->u[1] = src0->u[1] >> masked_count; + masked_count = src1->u[2] & 0x1f; + dst->u[2] = src0->u[2] >> masked_count; + masked_count = src1->u[3] & 0x1f; + dst->u[3] = src0->u[3] >> masked_count; +} + +static void +micro_uslt(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + dst->u[0] = src0->u[0] < src1->u[0] ? ~0 : 0; + dst->u[1] = src0->u[1] < src1->u[1] ? ~0 : 0; + dst->u[2] = src0->u[2] < src1->u[2] ? ~0 : 0; + dst->u[3] = src0->u[3] < src1->u[3] ? ~0 : 0; +} + +static void +micro_usne(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1) +{ + dst->u[0] = src0->u[0] != src1->u[0] ? ~0 : 0; + dst->u[1] = src0->u[1] != src1->u[1] ? ~0 : 0; + dst->u[2] = src0->u[2] != src1->u[2] ? ~0 : 0; + dst->u[3] = src0->u[3] != src1->u[3] ? ~0 : 0; +} + +static void +micro_uarl(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src) +{ + dst->i[0] = src->u[0]; + dst->i[1] = src->u[1]; + dst->i[2] = src->u[2]; + dst->i[3] = src->u[3]; +} + +static void +micro_ucmp(union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1, + const union tgsi_exec_channel *src2) +{ + dst->u[0] = src0->u[0] ? src1->u[0] : src2->u[0]; + dst->u[1] = src0->u[1] ? src1->u[1] : src2->u[1]; + dst->u[2] = src0->u[2] ? src1->u[2] : src2->u[2]; + dst->u[3] = src0->u[3] ? src1->u[3] : src2->u[3]; +} + +static void +exec_instruction( + struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst, + int *pc ) +{ + union tgsi_exec_channel r[10]; + + (*pc)++; + + switch (inst->Instruction.Opcode) { + case TGSI_OPCODE_ARL: + exec_vector_unary(mach, inst, micro_arl, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_MOV: + exec_vector_unary(mach, inst, micro_mov, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_LIT: + exec_lit(mach, inst); + break; + + case TGSI_OPCODE_RCP: + exec_scalar_unary(mach, inst, micro_rcp, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_RSQ: + exec_scalar_unary(mach, inst, micro_rsq, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_EXP: + exec_exp(mach, inst); + break; + + case TGSI_OPCODE_LOG: + exec_log(mach, inst); + break; + + case TGSI_OPCODE_MUL: + exec_vector_binary(mach, inst, micro_mul, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_ADD: + exec_vector_binary(mach, inst, micro_add, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_DP3: + exec_dp3(mach, inst); + break; + + case TGSI_OPCODE_DP4: + exec_dp4(mach, inst); + break; + + case TGSI_OPCODE_DST: + exec_dst(mach, inst); + break; + + case TGSI_OPCODE_MIN: + exec_vector_binary(mach, inst, micro_min, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_MAX: + exec_vector_binary(mach, inst, micro_max, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_SLT: + exec_vector_binary(mach, inst, micro_slt, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_SGE: + exec_vector_binary(mach, inst, micro_sge, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_MAD: + exec_vector_trinary(mach, inst, micro_mad, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_SUB: + exec_vector_binary(mach, inst, micro_sub, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_LRP: + exec_vector_trinary(mach, inst, micro_lrp, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_CND: + exec_vector_trinary(mach, inst, micro_cnd, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_SQRT: + exec_scalar_unary(mach, inst, micro_sqrt, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_DP2A: + exec_dp2a(mach, inst); + break; + + case TGSI_OPCODE_FRC: + exec_vector_unary(mach, inst, micro_frc, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_CLAMP: + exec_vector_trinary(mach, inst, micro_clamp, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_FLR: + exec_vector_unary(mach, inst, micro_flr, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_ROUND: + exec_vector_unary(mach, inst, micro_rnd, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_EX2: + exec_scalar_unary(mach, inst, micro_exp2, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_LG2: + exec_scalar_unary(mach, inst, micro_lg2, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_POW: + exec_scalar_binary(mach, inst, micro_pow, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_XPD: + exec_xpd(mach, inst); + break; + + case TGSI_OPCODE_ABS: + exec_vector_unary(mach, inst, micro_abs, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_RCC: + exec_scalar_unary(mach, inst, micro_rcc, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_DPH: + exec_dph(mach, inst); + break; + + case TGSI_OPCODE_COS: + exec_scalar_unary(mach, inst, micro_cos, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_DDX: + exec_vector_unary(mach, inst, micro_ddx, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_DDY: + exec_vector_unary(mach, inst, micro_ddy, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_KILL: + exec_kill (mach, inst); + break; + + case TGSI_OPCODE_KILL_IF: + exec_kill_if (mach, inst); + break; + + case TGSI_OPCODE_PK2H: + assert (0); + break; + + case TGSI_OPCODE_PK2US: + assert (0); + break; + + case TGSI_OPCODE_PK4B: + assert (0); + break; + + case TGSI_OPCODE_PK4UB: + assert (0); + break; + + case TGSI_OPCODE_RFL: + exec_rfl(mach, inst); + break; + + case TGSI_OPCODE_SEQ: + exec_vector_binary(mach, inst, micro_seq, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_SFL: + exec_vector(mach, inst, micro_sfl, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_SGT: + exec_vector_binary(mach, inst, micro_sgt, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_SIN: + exec_scalar_unary(mach, inst, micro_sin, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_SLE: + exec_vector_binary(mach, inst, micro_sle, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_SNE: + exec_vector_binary(mach, inst, micro_sne, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_STR: + exec_vector(mach, inst, micro_str, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_TEX: + /* simple texture lookup */ + /* src[0] = texcoord */ + /* src[1] = sampler unit */ + exec_tex(mach, inst, TEX_MODIFIER_NONE, 1); + break; + + case TGSI_OPCODE_TXB: + /* Texture lookup with lod bias */ + /* src[0] = texcoord (src[0].w = LOD bias) */ + /* src[1] = sampler unit */ + exec_tex(mach, inst, TEX_MODIFIER_LOD_BIAS, 1); + break; + + case TGSI_OPCODE_TXD: + /* Texture lookup with explict partial derivatives */ + /* src[0] = texcoord */ + /* src[1] = d[strq]/dx */ + /* src[2] = d[strq]/dy */ + /* src[3] = sampler unit */ + exec_txd(mach, inst); + break; + + case TGSI_OPCODE_TXL: + /* Texture lookup with explit LOD */ + /* src[0] = texcoord (src[0].w = LOD) */ + /* src[1] = sampler unit */ + exec_tex(mach, inst, TEX_MODIFIER_EXPLICIT_LOD, 1); + break; + + case TGSI_OPCODE_TXP: + /* Texture lookup with projection */ + /* src[0] = texcoord (src[0].w = projection) */ + /* src[1] = sampler unit */ + exec_tex(mach, inst, TEX_MODIFIER_PROJECTED, 1); + break; + + case TGSI_OPCODE_UP2H: + assert (0); + break; + + case TGSI_OPCODE_UP2US: + assert (0); + break; + + case TGSI_OPCODE_UP4B: + assert (0); + break; + + case TGSI_OPCODE_UP4UB: + assert (0); + break; + + case TGSI_OPCODE_X2D: + exec_x2d(mach, inst); + break; + + case TGSI_OPCODE_ARA: + assert (0); + break; + + case TGSI_OPCODE_ARR: + exec_vector_unary(mach, inst, micro_arr, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_BRA: + assert (0); + break; + + case TGSI_OPCODE_CAL: + /* skip the call if no execution channels are enabled */ + if (mach->ExecMask) { + /* do the call */ + + /* First, record the depths of the execution stacks. + * This is important for deeply nested/looped return statements. + * We have to unwind the stacks by the correct amount. For a + * real code generator, we could determine the number of entries + * to pop off each stack with simple static analysis and avoid + * implementing this data structure at run time. + */ + mach->CallStack[mach->CallStackTop].CondStackTop = mach->CondStackTop; + mach->CallStack[mach->CallStackTop].LoopStackTop = mach->LoopStackTop; + mach->CallStack[mach->CallStackTop].ContStackTop = mach->ContStackTop; + mach->CallStack[mach->CallStackTop].SwitchStackTop = mach->SwitchStackTop; + mach->CallStack[mach->CallStackTop].BreakStackTop = mach->BreakStackTop; + /* note that PC was already incremented above */ + mach->CallStack[mach->CallStackTop].ReturnAddr = *pc; + + mach->CallStackTop++; + + /* Second, push the Cond, Loop, Cont, Func stacks */ + assert(mach->CondStackTop < TGSI_EXEC_MAX_COND_NESTING); + assert(mach->LoopStackTop < TGSI_EXEC_MAX_LOOP_NESTING); + assert(mach->ContStackTop < TGSI_EXEC_MAX_LOOP_NESTING); + assert(mach->SwitchStackTop < TGSI_EXEC_MAX_SWITCH_NESTING); + assert(mach->BreakStackTop < TGSI_EXEC_MAX_BREAK_STACK); + assert(mach->FuncStackTop < TGSI_EXEC_MAX_CALL_NESTING); + + mach->CondStack[mach->CondStackTop++] = mach->CondMask; + mach->LoopStack[mach->LoopStackTop++] = mach->LoopMask; + mach->ContStack[mach->ContStackTop++] = mach->ContMask; + mach->SwitchStack[mach->SwitchStackTop++] = mach->Switch; + mach->BreakStack[mach->BreakStackTop++] = mach->BreakType; + mach->FuncStack[mach->FuncStackTop++] = mach->FuncMask; + + /* Finally, jump to the subroutine */ + *pc = inst->Label.Label; + } + break; + + case TGSI_OPCODE_RET: + mach->FuncMask &= ~mach->ExecMask; + UPDATE_EXEC_MASK(mach); + + if (mach->FuncMask == 0x0) { + /* really return now (otherwise, keep executing */ + + if (mach->CallStackTop == 0) { + /* returning from main() */ + mach->CondStackTop = 0; + mach->LoopStackTop = 0; + *pc = -1; + return; + } + + assert(mach->CallStackTop > 0); + mach->CallStackTop--; + + mach->CondStackTop = mach->CallStack[mach->CallStackTop].CondStackTop; + mach->CondMask = mach->CondStack[mach->CondStackTop]; + + mach->LoopStackTop = mach->CallStack[mach->CallStackTop].LoopStackTop; + mach->LoopMask = mach->LoopStack[mach->LoopStackTop]; + + mach->ContStackTop = mach->CallStack[mach->CallStackTop].ContStackTop; + mach->ContMask = mach->ContStack[mach->ContStackTop]; + + mach->SwitchStackTop = mach->CallStack[mach->CallStackTop].SwitchStackTop; + mach->Switch = mach->SwitchStack[mach->SwitchStackTop]; + + mach->BreakStackTop = mach->CallStack[mach->CallStackTop].BreakStackTop; + mach->BreakType = mach->BreakStack[mach->BreakStackTop]; + + assert(mach->FuncStackTop > 0); + mach->FuncMask = mach->FuncStack[--mach->FuncStackTop]; + + *pc = mach->CallStack[mach->CallStackTop].ReturnAddr; + + UPDATE_EXEC_MASK(mach); + } + break; + + case TGSI_OPCODE_SSG: + exec_vector_unary(mach, inst, micro_sgn, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_CMP: + exec_vector_trinary(mach, inst, micro_cmp, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_SCS: + exec_scs(mach, inst); + break; + + case TGSI_OPCODE_NRM: + exec_nrm3(mach, inst); + break; + + case TGSI_OPCODE_NRM4: + exec_nrm4(mach, inst); + break; + + case TGSI_OPCODE_DIV: + exec_vector_binary(mach, inst, micro_div, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_DP2: + exec_dp2(mach, inst); + break; + + case TGSI_OPCODE_IF: + /* push CondMask */ + assert(mach->CondStackTop < TGSI_EXEC_MAX_COND_NESTING); + mach->CondStack[mach->CondStackTop++] = mach->CondMask; + FETCH( &r[0], 0, TGSI_CHAN_X ); + /* update CondMask */ + if( ! r[0].f[0] ) { + mach->CondMask &= ~0x1; + } + if( ! r[0].f[1] ) { + mach->CondMask &= ~0x2; + } + if( ! r[0].f[2] ) { + mach->CondMask &= ~0x4; + } + if( ! r[0].f[3] ) { + mach->CondMask &= ~0x8; + } + UPDATE_EXEC_MASK(mach); + /* Todo: If CondMask==0, jump to ELSE */ + break; + + case TGSI_OPCODE_UIF: + /* push CondMask */ + assert(mach->CondStackTop < TGSI_EXEC_MAX_COND_NESTING); + mach->CondStack[mach->CondStackTop++] = mach->CondMask; + IFETCH( &r[0], 0, TGSI_CHAN_X ); + /* update CondMask */ + if( ! r[0].u[0] ) { + mach->CondMask &= ~0x1; + } + if( ! r[0].u[1] ) { + mach->CondMask &= ~0x2; + } + if( ! r[0].u[2] ) { + mach->CondMask &= ~0x4; + } + if( ! r[0].u[3] ) { + mach->CondMask &= ~0x8; + } + UPDATE_EXEC_MASK(mach); + /* Todo: If CondMask==0, jump to ELSE */ + break; + + case TGSI_OPCODE_ELSE: + /* invert CondMask wrt previous mask */ + { + uint prevMask; + assert(mach->CondStackTop > 0); + prevMask = mach->CondStack[mach->CondStackTop - 1]; + mach->CondMask = ~mach->CondMask & prevMask; + UPDATE_EXEC_MASK(mach); + /* Todo: If CondMask==0, jump to ENDIF */ + } + break; + + case TGSI_OPCODE_ENDIF: + /* pop CondMask */ + assert(mach->CondStackTop > 0); + mach->CondMask = mach->CondStack[--mach->CondStackTop]; + UPDATE_EXEC_MASK(mach); + break; + + case TGSI_OPCODE_END: + /* make sure we end primitives which haven't + * been explicitly emitted */ + conditional_emit_primitive(mach); + /* halt execution */ + *pc = -1; + break; + + case TGSI_OPCODE_PUSHA: + assert (0); + break; + + case TGSI_OPCODE_POPA: + assert (0); + break; + + case TGSI_OPCODE_CEIL: + exec_vector_unary(mach, inst, micro_ceil, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_I2F: + exec_vector_unary(mach, inst, micro_i2f, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_INT); + break; + + case TGSI_OPCODE_NOT: + exec_vector_unary(mach, inst, micro_not, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT); + break; + + case TGSI_OPCODE_TRUNC: + exec_vector_unary(mach, inst, micro_trunc, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_SHL: + exec_vector_binary(mach, inst, micro_shl, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT); + break; + + case TGSI_OPCODE_AND: + exec_vector_binary(mach, inst, micro_and, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT); + break; + + case TGSI_OPCODE_OR: + exec_vector_binary(mach, inst, micro_or, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT); + break; + + case TGSI_OPCODE_MOD: + exec_vector_binary(mach, inst, micro_mod, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT); + break; + + case TGSI_OPCODE_XOR: + exec_vector_binary(mach, inst, micro_xor, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT); + break; + + case TGSI_OPCODE_SAD: + assert (0); + break; + + case TGSI_OPCODE_TXF: + exec_txf(mach, inst); + break; + + case TGSI_OPCODE_TXQ: + exec_txq(mach, inst); + break; + + case TGSI_OPCODE_EMIT: + emit_vertex(mach); + break; + + case TGSI_OPCODE_ENDPRIM: + emit_primitive(mach); + break; + + case TGSI_OPCODE_BGNLOOP: + /* push LoopMask and ContMasks */ + assert(mach->LoopStackTop < TGSI_EXEC_MAX_LOOP_NESTING); + assert(mach->ContStackTop < TGSI_EXEC_MAX_LOOP_NESTING); + assert(mach->LoopLabelStackTop < TGSI_EXEC_MAX_LOOP_NESTING); + assert(mach->BreakStackTop < TGSI_EXEC_MAX_BREAK_STACK); + + mach->LoopStack[mach->LoopStackTop++] = mach->LoopMask; + mach->ContStack[mach->ContStackTop++] = mach->ContMask; + mach->LoopLabelStack[mach->LoopLabelStackTop++] = *pc - 1; + mach->BreakStack[mach->BreakStackTop++] = mach->BreakType; + mach->BreakType = TGSI_EXEC_BREAK_INSIDE_LOOP; + break; + + case TGSI_OPCODE_ENDLOOP: + /* Restore ContMask, but don't pop */ + assert(mach->ContStackTop > 0); + mach->ContMask = mach->ContStack[mach->ContStackTop - 1]; + UPDATE_EXEC_MASK(mach); + if (mach->ExecMask) { + /* repeat loop: jump to instruction just past BGNLOOP */ + assert(mach->LoopLabelStackTop > 0); + *pc = mach->LoopLabelStack[mach->LoopLabelStackTop - 1] + 1; + } + else { + /* exit loop: pop LoopMask */ + assert(mach->LoopStackTop > 0); + mach->LoopMask = mach->LoopStack[--mach->LoopStackTop]; + /* pop ContMask */ + assert(mach->ContStackTop > 0); + mach->ContMask = mach->ContStack[--mach->ContStackTop]; + assert(mach->LoopLabelStackTop > 0); + --mach->LoopLabelStackTop; + + mach->BreakType = mach->BreakStack[--mach->BreakStackTop]; + } + UPDATE_EXEC_MASK(mach); + break; + + case TGSI_OPCODE_BRK: + exec_break(mach); + break; + + case TGSI_OPCODE_CONT: + /* turn off cont channels for each enabled exec channel */ + mach->ContMask &= ~mach->ExecMask; + /* Todo: if mach->LoopMask == 0, jump to end of loop */ + UPDATE_EXEC_MASK(mach); + break; + + case TGSI_OPCODE_BGNSUB: + /* no-op */ + break; + + case TGSI_OPCODE_ENDSUB: + /* + * XXX: This really should be a no-op. We should never reach this opcode. + */ + + assert(mach->CallStackTop > 0); + mach->CallStackTop--; + + mach->CondStackTop = mach->CallStack[mach->CallStackTop].CondStackTop; + mach->CondMask = mach->CondStack[mach->CondStackTop]; + + mach->LoopStackTop = mach->CallStack[mach->CallStackTop].LoopStackTop; + mach->LoopMask = mach->LoopStack[mach->LoopStackTop]; + + mach->ContStackTop = mach->CallStack[mach->CallStackTop].ContStackTop; + mach->ContMask = mach->ContStack[mach->ContStackTop]; + + mach->SwitchStackTop = mach->CallStack[mach->CallStackTop].SwitchStackTop; + mach->Switch = mach->SwitchStack[mach->SwitchStackTop]; + + mach->BreakStackTop = mach->CallStack[mach->CallStackTop].BreakStackTop; + mach->BreakType = mach->BreakStack[mach->BreakStackTop]; + + assert(mach->FuncStackTop > 0); + mach->FuncMask = mach->FuncStack[--mach->FuncStackTop]; + + *pc = mach->CallStack[mach->CallStackTop].ReturnAddr; + + UPDATE_EXEC_MASK(mach); + break; + + case TGSI_OPCODE_NOP: + break; + + case TGSI_OPCODE_BREAKC: + IFETCH(&r[0], 0, TGSI_CHAN_X); + /* update CondMask */ + if (r[0].u[0] && (mach->ExecMask & 0x1)) { + mach->LoopMask &= ~0x1; + } + if (r[0].u[1] && (mach->ExecMask & 0x2)) { + mach->LoopMask &= ~0x2; + } + if (r[0].u[2] && (mach->ExecMask & 0x4)) { + mach->LoopMask &= ~0x4; + } + if (r[0].u[3] && (mach->ExecMask & 0x8)) { + mach->LoopMask &= ~0x8; + } + /* Todo: if mach->LoopMask == 0, jump to end of loop */ + UPDATE_EXEC_MASK(mach); + break; + + case TGSI_OPCODE_F2I: + exec_vector_unary(mach, inst, micro_f2i, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_FSEQ: + exec_vector_binary(mach, inst, micro_fseq, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_FSGE: + exec_vector_binary(mach, inst, micro_fsge, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_FSLT: + exec_vector_binary(mach, inst, micro_fslt, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_FSNE: + exec_vector_binary(mach, inst, micro_fsne, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_IDIV: + exec_vector_binary(mach, inst, micro_idiv, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT); + break; + + case TGSI_OPCODE_IMAX: + exec_vector_binary(mach, inst, micro_imax, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT); + break; + + case TGSI_OPCODE_IMIN: + exec_vector_binary(mach, inst, micro_imin, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT); + break; + + case TGSI_OPCODE_INEG: + exec_vector_unary(mach, inst, micro_ineg, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT); + break; + + case TGSI_OPCODE_ISGE: + exec_vector_binary(mach, inst, micro_isge, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT); + break; + + case TGSI_OPCODE_ISHR: + exec_vector_binary(mach, inst, micro_ishr, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT); + break; + + case TGSI_OPCODE_ISLT: + exec_vector_binary(mach, inst, micro_islt, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT); + break; + + case TGSI_OPCODE_F2U: + exec_vector_unary(mach, inst, micro_f2u, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_FLOAT); + break; + + case TGSI_OPCODE_U2F: + exec_vector_unary(mach, inst, micro_u2f, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_UINT); + break; + + case TGSI_OPCODE_UADD: + exec_vector_binary(mach, inst, micro_uadd, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT); + break; + + case TGSI_OPCODE_UDIV: + exec_vector_binary(mach, inst, micro_udiv, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT); + break; + + case TGSI_OPCODE_UMAD: + exec_vector_trinary(mach, inst, micro_umad, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT); + break; + + case TGSI_OPCODE_UMAX: + exec_vector_binary(mach, inst, micro_umax, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT); + break; + + case TGSI_OPCODE_UMIN: + exec_vector_binary(mach, inst, micro_umin, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT); + break; + + case TGSI_OPCODE_UMOD: + exec_vector_binary(mach, inst, micro_umod, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT); + break; + + case TGSI_OPCODE_UMUL: + exec_vector_binary(mach, inst, micro_umul, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT); + break; + + case TGSI_OPCODE_IMUL_HI: + exec_vector_binary(mach, inst, micro_imul_hi, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT); + break; + + case TGSI_OPCODE_UMUL_HI: + exec_vector_binary(mach, inst, micro_umul_hi, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT); + break; + + case TGSI_OPCODE_USEQ: + exec_vector_binary(mach, inst, micro_useq, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT); + break; + + case TGSI_OPCODE_USGE: + exec_vector_binary(mach, inst, micro_usge, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT); + break; + + case TGSI_OPCODE_USHR: + exec_vector_binary(mach, inst, micro_ushr, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT); + break; + + case TGSI_OPCODE_USLT: + exec_vector_binary(mach, inst, micro_uslt, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT); + break; + + case TGSI_OPCODE_USNE: + exec_vector_binary(mach, inst, micro_usne, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT); + break; + + case TGSI_OPCODE_SWITCH: + exec_switch(mach, inst); + break; + + case TGSI_OPCODE_CASE: + exec_case(mach, inst); + break; + + case TGSI_OPCODE_DEFAULT: + exec_default(mach); + break; + + case TGSI_OPCODE_ENDSWITCH: + exec_endswitch(mach); + break; + + case TGSI_OPCODE_SAMPLE_I: + exec_txf(mach, inst); + break; + + case TGSI_OPCODE_SAMPLE_I_MS: + assert(0); + break; + + case TGSI_OPCODE_SAMPLE: + exec_sample(mach, inst, TEX_MODIFIER_NONE, FALSE); + break; + + case TGSI_OPCODE_SAMPLE_B: + exec_sample(mach, inst, TEX_MODIFIER_LOD_BIAS, FALSE); + break; + + case TGSI_OPCODE_SAMPLE_C: + exec_sample(mach, inst, TEX_MODIFIER_NONE, TRUE); + break; + + case TGSI_OPCODE_SAMPLE_C_LZ: + exec_sample(mach, inst, TEX_MODIFIER_LEVEL_ZERO, TRUE); + break; + + case TGSI_OPCODE_SAMPLE_D: + exec_sample_d(mach, inst); + break; + + case TGSI_OPCODE_SAMPLE_L: + exec_sample(mach, inst, TEX_MODIFIER_EXPLICIT_LOD, FALSE); + break; + + case TGSI_OPCODE_GATHER4: + assert(0); + break; + + case TGSI_OPCODE_SVIEWINFO: + exec_txq(mach, inst); + break; + + case TGSI_OPCODE_SAMPLE_POS: + assert(0); + break; + + case TGSI_OPCODE_SAMPLE_INFO: + assert(0); + break; + + case TGSI_OPCODE_UARL: + exec_vector_unary(mach, inst, micro_uarl, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_UINT); + break; + + case TGSI_OPCODE_UCMP: + exec_vector_trinary(mach, inst, micro_ucmp, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT); + break; + + case TGSI_OPCODE_IABS: + exec_vector_unary(mach, inst, micro_iabs, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT); + break; + + case TGSI_OPCODE_ISSG: + exec_vector_unary(mach, inst, micro_isgn, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT); + break; + + case TGSI_OPCODE_TEX2: + /* simple texture lookup */ + /* src[0] = texcoord */ + /* src[1] = compare */ + /* src[2] = sampler unit */ + exec_tex(mach, inst, TEX_MODIFIER_NONE, 2); + break; + case TGSI_OPCODE_TXB2: + /* simple texture lookup */ + /* src[0] = texcoord */ + /* src[1] = bias */ + /* src[2] = sampler unit */ + exec_tex(mach, inst, TEX_MODIFIER_LOD_BIAS, 2); + break; + case TGSI_OPCODE_TXL2: + /* simple texture lookup */ + /* src[0] = texcoord */ + /* src[1] = lod */ + /* src[2] = sampler unit */ + exec_tex(mach, inst, TEX_MODIFIER_EXPLICIT_LOD, 2); + break; + default: + assert( 0 ); + } +} + + +/** + * Run TGSI interpreter. + * \return bitmask of "alive" quad components + */ +uint +tgsi_exec_machine_run( struct tgsi_exec_machine *mach ) +{ + uint i; + int pc = 0; + uint default_mask = 0xf; + + mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0] = 0; + mach->Temps[TEMP_OUTPUT_I].xyzw[TEMP_OUTPUT_C].u[0] = 0; + + if( mach->Processor == TGSI_PROCESSOR_GEOMETRY ) { + mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0] = 0; + mach->Primitives[0] = 0; + /* GS runs on a single primitive for now */ + default_mask = 0x1; + } + + mach->CondMask = default_mask; + mach->LoopMask = default_mask; + mach->ContMask = default_mask; + mach->FuncMask = default_mask; + mach->ExecMask = default_mask; + + mach->Switch.mask = default_mask; + + assert(mach->CondStackTop == 0); + assert(mach->LoopStackTop == 0); + assert(mach->ContStackTop == 0); + assert(mach->SwitchStackTop == 0); + assert(mach->BreakStackTop == 0); + assert(mach->CallStackTop == 0); + + + /* execute declarations (interpolants) */ + for (i = 0; i < mach->NumDeclarations; i++) { + exec_declaration( mach, mach->Declarations+i ); + } + + { +#if DEBUG_EXECUTION + struct tgsi_exec_vector temps[TGSI_EXEC_NUM_TEMPS + TGSI_EXEC_NUM_TEMP_EXTRAS]; + struct tgsi_exec_vector outputs[PIPE_MAX_ATTRIBS]; + uint inst = 1; + + memset(mach->Temps, 0, sizeof(temps)); + memset(mach->Outputs, 0, sizeof(outputs)); + memset(temps, 0, sizeof(temps)); + memset(outputs, 0, sizeof(outputs)); +#endif + + /* execute instructions, until pc is set to -1 */ + while (pc != -1) { + +#if DEBUG_EXECUTION + uint i; + + tgsi_dump_instruction(&mach->Instructions[pc], inst++); +#endif + + assert(pc < (int) mach->NumInstructions); + exec_instruction(mach, mach->Instructions + pc, &pc); + +#if DEBUG_EXECUTION + for (i = 0; i < TGSI_EXEC_NUM_TEMPS + TGSI_EXEC_NUM_TEMP_EXTRAS; i++) { + if (memcmp(&temps[i], &mach->Temps[i], sizeof(temps[i]))) { + uint j; + + memcpy(&temps[i], &mach->Temps[i], sizeof(temps[i])); + debug_printf("TEMP[%2u] = ", i); + for (j = 0; j < 4; j++) { + if (j > 0) { + debug_printf(" "); + } + debug_printf("(%6f %u, %6f %u, %6f %u, %6f %u)\n", + temps[i].xyzw[0].f[j], temps[i].xyzw[0].u[j], + temps[i].xyzw[1].f[j], temps[i].xyzw[1].u[j], + temps[i].xyzw[2].f[j], temps[i].xyzw[2].u[j], + temps[i].xyzw[3].f[j], temps[i].xyzw[3].u[j]); + } + } + } + for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { + if (memcmp(&outputs[i], &mach->Outputs[i], sizeof(outputs[i]))) { + uint j; + + memcpy(&outputs[i], &mach->Outputs[i], sizeof(outputs[i])); + debug_printf("OUT[%2u] = ", i); + for (j = 0; j < 4; j++) { + if (j > 0) { + debug_printf(" "); + } + debug_printf("(%6f %u, %6f %u, %6f %u, %6f %u)\n", + outputs[i].xyzw[0].f[j], outputs[i].xyzw[0].u[j], + outputs[i].xyzw[1].f[j], outputs[i].xyzw[1].u[j], + outputs[i].xyzw[2].f[j], outputs[i].xyzw[2].u[j], + outputs[i].xyzw[3].f[j], outputs[i].xyzw[3].u[j]); + } + } + } +#endif + } + } + +#if 0 + /* we scale from floats in [0,1] to Zbuffer ints in sp_quad_depth_test.c */ + if (mach->Processor == TGSI_PROCESSOR_FRAGMENT) { + /* + * Scale back depth component. + */ + for (i = 0; i < 4; i++) + mach->Outputs[0].xyzw[2].f[i] *= ctx->DrawBuffer->_DepthMaxF; + } +#endif + + /* Strictly speaking, these assertions aren't really needed but they + * can potentially catch some bugs in the control flow code. + */ + assert(mach->CondStackTop == 0); + assert(mach->LoopStackTop == 0); + assert(mach->ContStackTop == 0); + assert(mach->SwitchStackTop == 0); + assert(mach->BreakStackTop == 0); + assert(mach->CallStackTop == 0); + + return ~mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0]; +} diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.h b/src/gallium/auxiliary/tgsi/tgsi_exec.h new file mode 100644 index 0000000..9b1995c --- /dev/null +++ b/src/gallium/auxiliary/tgsi/tgsi_exec.h @@ -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 */ diff --git a/src/gallium/auxiliary/tgsi/tgsi_info.c b/src/gallium/auxiliary/tgsi/tgsi_info.c new file mode 100644 index 0000000..565f274 --- /dev/null +++ b/src/gallium/auxiliary/tgsi/tgsi_info.c @@ -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); +} diff --git a/src/gallium/auxiliary/tgsi/tgsi_info.h b/src/gallium/auxiliary/tgsi/tgsi_info.h new file mode 100644 index 0000000..aa7edd1 --- /dev/null +++ b/src/gallium/auxiliary/tgsi/tgsi_info.h @@ -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 */ diff --git a/src/gallium/auxiliary/tgsi/tgsi_iterate.c b/src/gallium/auxiliary/tgsi/tgsi_iterate.c new file mode 100644 index 0000000..ca31894 --- /dev/null +++ b/src/gallium/auxiliary/tgsi/tgsi_iterate.c @@ -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; +} diff --git a/src/gallium/auxiliary/tgsi/tgsi_iterate.h b/src/gallium/auxiliary/tgsi/tgsi_iterate.h new file mode 100644 index 0000000..d925a06 --- /dev/null +++ b/src/gallium/auxiliary/tgsi/tgsi_iterate.h @@ -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 */ diff --git a/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h b/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h new file mode 100644 index 0000000..cc5c03b --- /dev/null +++ b/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.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 diff --git a/src/gallium/auxiliary/tgsi/tgsi_parse.c b/src/gallium/auxiliary/tgsi/tgsi_parse.c new file mode 100644 index 0000000..5bf8f48 --- /dev/null +++ b/src/gallium/auxiliary/tgsi/tgsi_parse.c @@ -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"); +} diff --git a/src/gallium/auxiliary/tgsi/tgsi_parse.h b/src/gallium/auxiliary/tgsi/tgsi_parse.h new file mode 100644 index 0000000..2e450a4 --- /dev/null +++ b/src/gallium/auxiliary/tgsi/tgsi_parse.h @@ -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 */ + diff --git a/src/gallium/auxiliary/tgsi/tgsi_sanity.h b/src/gallium/auxiliary/tgsi/tgsi_sanity.h new file mode 100644 index 0000000..1ff7874 --- /dev/null +++ b/src/gallium/auxiliary/tgsi/tgsi_sanity.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 */ diff --git a/src/gallium/auxiliary/tgsi/tgsi_scan.c b/src/gallium/auxiliary/tgsi/tgsi_scan.c new file mode 100644 index 0000000..00fdcfb --- /dev/null +++ b/src/gallium/auxiliary/tgsi/tgsi_scan.c @@ -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; +} diff --git a/src/gallium/auxiliary/tgsi/tgsi_scan.h b/src/gallium/auxiliary/tgsi/tgsi_scan.h new file mode 100644 index 0000000..0be2feb --- /dev/null +++ b/src/gallium/auxiliary/tgsi/tgsi_scan.h @@ -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 */ diff --git a/src/gallium/auxiliary/tgsi/tgsi_strings.c b/src/gallium/auxiliary/tgsi/tgsi_strings.c new file mode 100644 index 0000000..b0ba3ef --- /dev/null +++ b/src/gallium/auxiliary/tgsi/tgsi_strings.c @@ -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"; +} diff --git a/src/gallium/auxiliary/tgsi/tgsi_strings.h b/src/gallium/auxiliary/tgsi/tgsi_strings.h new file mode 100644 index 0000000..3477d50 --- /dev/null +++ b/src/gallium/auxiliary/tgsi/tgsi_strings.h @@ -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 */ diff --git a/src/gallium/auxiliary/tgsi/tgsi_text.c b/src/gallium/auxiliary/tgsi/tgsi_text.c new file mode 100644 index 0000000..2dbbaac --- /dev/null +++ b/src/gallium/auxiliary/tgsi/tgsi_text.c @@ -0,0 +1,1662 @@ +/************************************************************************** + * + * 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 "util/u_prim.h" +#include "pipe/p_defines.h" +#include "util/u_inlines.h" +#include "tgsi_text.h" +#include "tgsi_build.h" +#include "tgsi_info.h" +#include "tgsi_parse.h" +#include "tgsi_sanity.h" +#include "tgsi_strings.h" +#include "tgsi_util.h" +#include "tgsi_dump.h" + +static boolean is_alpha_underscore( const char *cur ) +{ + return + (*cur >= 'a' && *cur <= 'z') || + (*cur >= 'A' && *cur <= 'Z') || + *cur == '_'; +} + +static boolean is_digit( const char *cur ) +{ + return *cur >= '0' && *cur <= '9'; +} + +static boolean is_digit_alpha_underscore( const char *cur ) +{ + return is_digit( cur ) || is_alpha_underscore( cur ); +} + +static char uprcase( char c ) +{ + if (c >= 'a' && c <= 'z') + return c + 'A' - 'a'; + return c; +} + +/* + * Ignore case of str1 and assume str1 is already uppercase. + * Return TRUE iff str1 and str2 are equal. + */ +static int +streq_nocase_uprcase(const char *str1, + const char *str2) +{ + while (*str1 && *str2) { + if (*str1 != uprcase(*str2)) + return FALSE; + str1++; + str2++; + } + return *str1 == 0 && *str2 == 0; +} + +/* Return TRUE if both strings match. + * The second string is terminated by zero. + * The pointer to the first string is moved at end of the read word + * on success. + */ +static boolean str_match_no_case( const char **pcur, const char *str ) +{ + const char *cur = *pcur; + + while (*str != '\0' && *str == uprcase( *cur )) { + str++; + cur++; + } + if (*str == '\0') { + *pcur = cur; + return TRUE; + } + return FALSE; +} + +/* Return TRUE if both strings match. + * The first string is be terminated by a non-digit non-letter non-underscore + * character, the second string is terminated by zero. + * The pointer to the first string is moved at end of the read word + * on success. + */ +static boolean str_match_nocase_whole( const char **pcur, const char *str ) +{ + const char *cur = *pcur; + + if (str_match_no_case(&cur, str) && + !is_digit_alpha_underscore(cur)) { + *pcur = cur; + return TRUE; + } + return FALSE; +} + +/* Eat zero or more whitespaces. + */ +static void eat_opt_white( const char **pcur ) +{ + while (**pcur == ' ' || **pcur == '\t' || **pcur == '\n') + (*pcur)++; +} + +/* Eat one or more whitespaces. + * Return TRUE if at least one whitespace eaten. + */ +static boolean eat_white( const char **pcur ) +{ + const char *cur = *pcur; + + eat_opt_white( pcur ); + return *pcur > cur; +} + +/* Parse unsigned integer. + * No checks for overflow. + */ +static boolean parse_uint( const char **pcur, uint *val ) +{ + const char *cur = *pcur; + + if (is_digit( cur )) { + *val = *cur++ - '0'; + while (is_digit( cur )) + *val = *val * 10 + *cur++ - '0'; + *pcur = cur; + return TRUE; + } + return FALSE; +} + +static boolean parse_int( const char **pcur, int *val ) +{ + const char *cur = *pcur; + int sign = (*cur == '-' ? -1 : 1); + + if (*cur == '+' || *cur == '-') + cur++; + + if (parse_uint(&cur, (uint *)val)) { + *val *= sign; + *pcur = cur; + return TRUE; + } + + return FALSE; +} + +static boolean parse_identifier( const char **pcur, char *ret ) +{ + const char *cur = *pcur; + int i = 0; + if (is_alpha_underscore( cur )) { + ret[i++] = *cur++; + while (is_alpha_underscore( cur ) || is_digit( cur )) + ret[i++] = *cur++; + ret[i++] = '\0'; + *pcur = cur; + return TRUE; + } + return FALSE; +} + +/* Parse floating point. + */ +static boolean parse_float( const char **pcur, float *val ) +{ + const char *cur = *pcur; + boolean integral_part = FALSE; + boolean fractional_part = FALSE; + + if (*cur == '0' && *(cur + 1) == 'x') { + union fi fi; + fi.ui = strtoul(cur, NULL, 16); + *val = fi.f; + cur += 10; + goto out; + } + + *val = (float) atof( cur ); + if (*cur == '-' || *cur == '+') + cur++; + if (is_digit( cur )) { + cur++; + integral_part = TRUE; + while (is_digit( cur )) + cur++; + } + if (*cur == '.') { + cur++; + if (is_digit( cur )) { + cur++; + fractional_part = TRUE; + while (is_digit( cur )) + cur++; + } + } + if (!integral_part && !fractional_part) + return FALSE; + if (uprcase( *cur ) == 'E') { + cur++; + if (*cur == '-' || *cur == '+') + cur++; + if (is_digit( cur )) { + cur++; + while (is_digit( cur )) + cur++; + } + else + return FALSE; + } + +out: + *pcur = cur; + return TRUE; +} + +struct translate_ctx +{ + const char *text; + const char *cur; + struct tgsi_token *tokens; + struct tgsi_token *tokens_cur; + struct tgsi_token *tokens_end; + struct tgsi_header *header; + unsigned processor : 4; + int implied_array_size : 5; + unsigned num_immediates; +}; + +static void report_error( struct translate_ctx *ctx, const char *msg ) +{ + int line = 1; + int column = 1; + const char *itr = ctx->text; + + while (itr != ctx->cur) { + if (*itr == '\n') { + column = 1; + ++line; + } + ++column; + ++itr; + } + + debug_printf( "\nTGSI asm error: %s [%d : %d] \n", msg, line, column ); +} + +/* Parse shader header. + * Return TRUE for one of the following headers. + * FRAG + * GEOM + * VERT + */ +static boolean parse_header( struct translate_ctx *ctx ) +{ + uint processor; + + if (str_match_nocase_whole( &ctx->cur, "FRAG" )) + processor = TGSI_PROCESSOR_FRAGMENT; + else if (str_match_nocase_whole( &ctx->cur, "VERT" )) + processor = TGSI_PROCESSOR_VERTEX; + else if (str_match_nocase_whole( &ctx->cur, "GEOM" )) + processor = TGSI_PROCESSOR_GEOMETRY; + else if (str_match_nocase_whole( &ctx->cur, "COMP" )) + processor = TGSI_PROCESSOR_COMPUTE; + else { + report_error( ctx, "Unknown header" ); + return FALSE; + } + + if (ctx->tokens_cur >= ctx->tokens_end) + return FALSE; + ctx->header = (struct tgsi_header *) ctx->tokens_cur++; + *ctx->header = tgsi_build_header(); + + if (ctx->tokens_cur >= ctx->tokens_end) + return FALSE; + *(struct tgsi_processor *) ctx->tokens_cur++ = tgsi_build_processor( processor, ctx->header ); + ctx->processor = processor; + + return TRUE; +} + +static boolean parse_label( struct translate_ctx *ctx, uint *val ) +{ + const char *cur = ctx->cur; + + if (parse_uint( &cur, val )) { + eat_opt_white( &cur ); + if (*cur == ':') { + cur++; + ctx->cur = cur; + return TRUE; + } + } + return FALSE; +} + +static boolean +parse_file( const char **pcur, uint *file ) +{ + uint i; + + for (i = 0; i < TGSI_FILE_COUNT; i++) { + const char *cur = *pcur; + + if (str_match_nocase_whole( &cur, tgsi_file_name(i) )) { + *pcur = cur; + *file = i; + return TRUE; + } + } + return FALSE; +} + +static boolean +parse_opt_writemask( + struct translate_ctx *ctx, + uint *writemask ) +{ + const char *cur; + + cur = ctx->cur; + eat_opt_white( &cur ); + if (*cur == '.') { + cur++; + *writemask = TGSI_WRITEMASK_NONE; + eat_opt_white( &cur ); + if (uprcase( *cur ) == 'X') { + cur++; + *writemask |= TGSI_WRITEMASK_X; + } + if (uprcase( *cur ) == 'Y') { + cur++; + *writemask |= TGSI_WRITEMASK_Y; + } + if (uprcase( *cur ) == 'Z') { + cur++; + *writemask |= TGSI_WRITEMASK_Z; + } + if (uprcase( *cur ) == 'W') { + cur++; + *writemask |= TGSI_WRITEMASK_W; + } + + if (*writemask == TGSI_WRITEMASK_NONE) { + report_error( ctx, "Writemask expected" ); + return FALSE; + } + + ctx->cur = cur; + } + else { + *writemask = TGSI_WRITEMASK_XYZW; + } + return TRUE; +} + + +/* ::= `[' + */ +static boolean +parse_register_file_bracket( + struct translate_ctx *ctx, + uint *file ) +{ + if (!parse_file( &ctx->cur, file )) { + report_error( ctx, "Unknown register file" ); + return FALSE; + } + eat_opt_white( &ctx->cur ); + if (*ctx->cur != '[') { + report_error( ctx, "Expected `['" ); + return FALSE; + } + ctx->cur++; + return TRUE; +} + +/* ::= + */ +static boolean +parse_register_file_bracket_index( + struct translate_ctx *ctx, + uint *file, + int *index ) +{ + uint uindex; + + if (!parse_register_file_bracket( ctx, file )) + return FALSE; + eat_opt_white( &ctx->cur ); + if (!parse_uint( &ctx->cur, &uindex )) { + report_error( ctx, "Expected literal unsigned integer" ); + return FALSE; + } + *index = (int) uindex; + return TRUE; +} + +/* Parse simple 1d register operand. + * ::= `]' + */ +static boolean +parse_register_1d(struct translate_ctx *ctx, + uint *file, + int *index ) +{ + if (!parse_register_file_bracket_index( ctx, file, index )) + return FALSE; + eat_opt_white( &ctx->cur ); + if (*ctx->cur != ']') { + report_error( ctx, "Expected `]'" ); + return FALSE; + } + ctx->cur++; + return TRUE; +} + +struct parsed_bracket { + int index; + + uint ind_file; + int ind_index; + uint ind_comp; + uint ind_array; +}; + + +static boolean +parse_register_bracket( + struct translate_ctx *ctx, + struct parsed_bracket *brackets) +{ + const char *cur; + uint uindex; + + memset(brackets, 0, sizeof(struct parsed_bracket)); + + eat_opt_white( &ctx->cur ); + + cur = ctx->cur; + if (parse_file( &cur, &brackets->ind_file )) { + if (!parse_register_1d( ctx, &brackets->ind_file, + &brackets->ind_index )) + return FALSE; + eat_opt_white( &ctx->cur ); + + if (*ctx->cur == '.') { + ctx->cur++; + eat_opt_white(&ctx->cur); + + switch (uprcase(*ctx->cur)) { + case 'X': + brackets->ind_comp = TGSI_SWIZZLE_X; + break; + case 'Y': + brackets->ind_comp = TGSI_SWIZZLE_Y; + break; + case 'Z': + brackets->ind_comp = TGSI_SWIZZLE_Z; + break; + case 'W': + brackets->ind_comp = TGSI_SWIZZLE_W; + break; + default: + report_error(ctx, "Expected indirect register swizzle component `x', `y', `z' or `w'"); + return FALSE; + } + ctx->cur++; + eat_opt_white(&ctx->cur); + } + + if (*ctx->cur == '+' || *ctx->cur == '-') + parse_int( &ctx->cur, &brackets->index ); + else + brackets->index = 0; + } + else { + if (!parse_uint( &ctx->cur, &uindex )) { + report_error( ctx, "Expected literal unsigned integer" ); + return FALSE; + } + brackets->index = (int) uindex; + brackets->ind_file = TGSI_FILE_NULL; + brackets->ind_index = 0; + } + eat_opt_white( &ctx->cur ); + if (*ctx->cur != ']') { + report_error( ctx, "Expected `]'" ); + return FALSE; + } + ctx->cur++; + if (*ctx->cur == '(') { + ctx->cur++; + eat_opt_white( &ctx->cur ); + if (!parse_uint( &ctx->cur, &brackets->ind_array )) { + report_error( ctx, "Expected literal unsigned integer" ); + return FALSE; + } + eat_opt_white( &ctx->cur ); + if (*ctx->cur != ')') { + report_error( ctx, "Expected `)'" ); + return FALSE; + } + ctx->cur++; + } + return TRUE; +} + +static boolean +parse_opt_register_src_bracket( + struct translate_ctx *ctx, + struct parsed_bracket *brackets, + int *parsed_brackets) +{ + const char *cur = ctx->cur; + + *parsed_brackets = 0; + + eat_opt_white( &cur ); + if (cur[0] == '[') { + ++cur; + ctx->cur = cur; + + if (!parse_register_bracket(ctx, brackets)) + return FALSE; + + *parsed_brackets = 1; + } + + return TRUE; +} + + +/* Parse source register operand. + * ::= `]' | + * [`.' (`x' | `y' | `z' | `w')] `]' | + * [`.' (`x' | `y' | `z' | `w')] `+' `]' | + * [`.' (`x' | `y' | `z' | `w')] `-' `]' + */ +static boolean +parse_register_src( + struct translate_ctx *ctx, + uint *file, + struct parsed_bracket *brackets) +{ + brackets->ind_comp = TGSI_SWIZZLE_X; + if (!parse_register_file_bracket( ctx, file )) + return FALSE; + if (!parse_register_bracket( ctx, brackets )) + return FALSE; + + return TRUE; +} + +struct parsed_dcl_bracket { + uint first; + uint last; +}; + +static boolean +parse_register_dcl_bracket( + struct translate_ctx *ctx, + struct parsed_dcl_bracket *bracket) +{ + uint uindex; + memset(bracket, 0, sizeof(struct parsed_dcl_bracket)); + + eat_opt_white( &ctx->cur ); + + if (!parse_uint( &ctx->cur, &uindex )) { + /* it can be an empty bracket [] which means its range + * is from 0 to some implied size */ + if (ctx->cur[0] == ']' && ctx->implied_array_size != 0) { + bracket->first = 0; + bracket->last = ctx->implied_array_size - 1; + goto cleanup; + } + report_error( ctx, "Expected literal unsigned integer" ); + return FALSE; + } + bracket->first = uindex; + + eat_opt_white( &ctx->cur ); + + if (ctx->cur[0] == '.' && ctx->cur[1] == '.') { + uint uindex; + + ctx->cur += 2; + eat_opt_white( &ctx->cur ); + if (!parse_uint( &ctx->cur, &uindex )) { + report_error( ctx, "Expected literal integer" ); + return FALSE; + } + bracket->last = (int) uindex; + eat_opt_white( &ctx->cur ); + } + else { + bracket->last = bracket->first; + } + +cleanup: + if (*ctx->cur != ']') { + report_error( ctx, "Expected `]' or `..'" ); + return FALSE; + } + ctx->cur++; + return TRUE; +} + +/* Parse register declaration. + * ::= `]' | + * `..' `]' + */ +static boolean +parse_register_dcl( + struct translate_ctx *ctx, + uint *file, + struct parsed_dcl_bracket *brackets, + int *num_brackets) +{ + const char *cur; + + *num_brackets = 0; + + if (!parse_register_file_bracket( ctx, file )) + return FALSE; + if (!parse_register_dcl_bracket( ctx, &brackets[0] )) + return FALSE; + + *num_brackets = 1; + + cur = ctx->cur; + eat_opt_white( &cur ); + + if (cur[0] == '[') { + ++cur; + ctx->cur = cur; + if (!parse_register_dcl_bracket( ctx, &brackets[1] )) + return FALSE; + /* for geometry shader we don't really care about + * the first brackets it's always the size of the + * input primitive. so we want to declare just + * the index relevant to the semantics which is in + * the second bracket */ + if (ctx->processor == TGSI_PROCESSOR_GEOMETRY && *file == TGSI_FILE_INPUT) { + brackets[0] = brackets[1]; + *num_brackets = 1; + } else { + *num_brackets = 2; + } + } + + return TRUE; +} + + +/* Parse destination register operand.*/ +static boolean +parse_register_dst( + struct translate_ctx *ctx, + uint *file, + struct parsed_bracket *brackets) +{ + brackets->ind_comp = TGSI_SWIZZLE_X; + if (!parse_register_file_bracket( ctx, file )) + return FALSE; + if (!parse_register_bracket( ctx, brackets )) + return FALSE; + + return TRUE; +} + +static boolean +parse_dst_operand( + struct translate_ctx *ctx, + struct tgsi_full_dst_register *dst ) +{ + uint file; + uint writemask; + const char *cur; + struct parsed_bracket bracket[2]; + int parsed_opt_brackets; + + if (!parse_register_dst( ctx, &file, &bracket[0] )) + return FALSE; + if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets)) + return FALSE; + + cur = ctx->cur; + eat_opt_white( &cur ); + + if (!parse_opt_writemask( ctx, &writemask )) + return FALSE; + + dst->Register.File = file; + if (parsed_opt_brackets) { + dst->Register.Dimension = 1; + dst->Dimension.Indirect = 0; + dst->Dimension.Dimension = 0; + dst->Dimension.Index = bracket[0].index; + bracket[0] = bracket[1]; + } + dst->Register.Index = bracket[0].index; + dst->Register.WriteMask = writemask; + if (bracket[0].ind_file != TGSI_FILE_NULL) { + dst->Register.Indirect = 1; + dst->Indirect.File = bracket[0].ind_file; + dst->Indirect.Index = bracket[0].ind_index; + dst->Indirect.Swizzle = bracket[0].ind_comp; + dst->Indirect.ArrayID = bracket[0].ind_array; + } + return TRUE; +} + +static boolean +parse_optional_swizzle( + struct translate_ctx *ctx, + uint swizzle[4], + boolean *parsed_swizzle, int max ) +{ + const char *cur = ctx->cur; + + *parsed_swizzle = FALSE; + + eat_opt_white( &cur ); + if (*cur == '.') { + uint i; + + cur++; + eat_opt_white( &cur ); + for (i = 0; i < max; i++) { + if (uprcase( *cur ) == 'X') + swizzle[i] = TGSI_SWIZZLE_X; + else if (uprcase( *cur ) == 'Y') + swizzle[i] = TGSI_SWIZZLE_Y; + else if (uprcase( *cur ) == 'Z') + swizzle[i] = TGSI_SWIZZLE_Z; + else if (uprcase( *cur ) == 'W') + swizzle[i] = TGSI_SWIZZLE_W; + else { + report_error( ctx, "Expected register swizzle component `x', `y', `z' or `w'" ); + return FALSE; + } + cur++; + } + *parsed_swizzle = TRUE; + ctx->cur = cur; + } + return TRUE; +} + +static boolean +parse_src_operand( + struct translate_ctx *ctx, + struct tgsi_full_src_register *src ) +{ + uint file; + uint swizzle[4]; + boolean parsed_swizzle; + struct parsed_bracket bracket[2]; + int parsed_opt_brackets; + + if (*ctx->cur == '-') { + ctx->cur++; + eat_opt_white( &ctx->cur ); + src->Register.Negate = 1; + } + + if (*ctx->cur == '|') { + ctx->cur++; + eat_opt_white( &ctx->cur ); + src->Register.Absolute = 1; + } + + if (!parse_register_src(ctx, &file, &bracket[0])) + return FALSE; + if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets)) + return FALSE; + + src->Register.File = file; + if (parsed_opt_brackets) { + src->Register.Dimension = 1; + src->Dimension.Indirect = 0; + src->Dimension.Dimension = 0; + src->Dimension.Index = bracket[0].index; + bracket[0] = bracket[1]; + } + src->Register.Index = bracket[0].index; + if (bracket[0].ind_file != TGSI_FILE_NULL) { + src->Register.Indirect = 1; + src->Indirect.File = bracket[0].ind_file; + src->Indirect.Index = bracket[0].ind_index; + src->Indirect.Swizzle = bracket[0].ind_comp; + src->Indirect.ArrayID = bracket[0].ind_array; + } + + /* Parse optional swizzle. + */ + if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, 4 )) { + if (parsed_swizzle) { + src->Register.SwizzleX = swizzle[0]; + src->Register.SwizzleY = swizzle[1]; + src->Register.SwizzleZ = swizzle[2]; + src->Register.SwizzleW = swizzle[3]; + } + } + + if (src->Register.Absolute) { + eat_opt_white( &ctx->cur ); + if (*ctx->cur != '|') { + report_error( ctx, "Expected `|'" ); + return FALSE; + } + ctx->cur++; + } + + + return TRUE; +} + +static boolean +parse_tex_offset_operand( + struct translate_ctx *ctx, + struct tgsi_texture_offset *tex_offset ) +{ + uint file; + uint swizzle[4]; + boolean parsed_swizzle; + struct parsed_bracket bracket[2]; + int parsed_opt_brackets; + + if (!parse_register_src(ctx, &file, &bracket[0])) + return FALSE; + if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets)) + return FALSE; + + tex_offset->File = file; + tex_offset->Index = bracket[0].index; + + /* Parse optional swizzle. + */ + if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, 3 )) { + if (parsed_swizzle) { + tex_offset->SwizzleX = swizzle[0]; + tex_offset->SwizzleY = swizzle[1]; + tex_offset->SwizzleZ = swizzle[2]; + } + } + + return TRUE; +} + +static boolean +match_inst(const char **pcur, + unsigned *saturate, + const struct tgsi_opcode_info *info) +{ + const char *cur = *pcur; + + /* simple case: the whole string matches the instruction name */ + if (str_match_nocase_whole(&cur, info->mnemonic)) { + *pcur = cur; + *saturate = TGSI_SAT_NONE; + return TRUE; + } + + if (str_match_no_case(&cur, info->mnemonic)) { + /* the instruction has a suffix, figure it out */ + if (str_match_nocase_whole(&cur, "_SAT")) { + *pcur = cur; + *saturate = TGSI_SAT_ZERO_ONE; + return TRUE; + } + + if (str_match_nocase_whole(&cur, "_SATNV")) { + *pcur = cur; + *saturate = TGSI_SAT_MINUS_PLUS_ONE; + return TRUE; + } + } + + return FALSE; +} + +static boolean +parse_instruction( + struct translate_ctx *ctx, + boolean has_label ) +{ + uint i; + uint saturate = TGSI_SAT_NONE; + const struct tgsi_opcode_info *info; + struct tgsi_full_instruction inst; + const char *cur; + uint advance; + + inst = tgsi_default_full_instruction(); + + /* Parse predicate. + */ + eat_opt_white( &ctx->cur ); + if (*ctx->cur == '(') { + uint file; + int index; + uint swizzle[4]; + boolean parsed_swizzle; + + inst.Instruction.Predicate = 1; + + ctx->cur++; + if (*ctx->cur == '!') { + ctx->cur++; + inst.Predicate.Negate = 1; + } + + if (!parse_register_1d( ctx, &file, &index )) + return FALSE; + + if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, 4 )) { + if (parsed_swizzle) { + inst.Predicate.SwizzleX = swizzle[0]; + inst.Predicate.SwizzleY = swizzle[1]; + inst.Predicate.SwizzleZ = swizzle[2]; + inst.Predicate.SwizzleW = swizzle[3]; + } + } + + if (*ctx->cur != ')') { + report_error( ctx, "Expected `)'" ); + return FALSE; + } + + ctx->cur++; + } + + /* Parse instruction name. + */ + eat_opt_white( &ctx->cur ); + for (i = 0; i < TGSI_OPCODE_LAST; i++) { + cur = ctx->cur; + + info = tgsi_get_opcode_info( i ); + if (match_inst(&cur, &saturate, info)) { + if (info->num_dst + info->num_src + info->is_tex == 0) { + ctx->cur = cur; + break; + } + else if (*cur == '\0' || eat_white( &cur )) { + ctx->cur = cur; + break; + } + } + } + if (i == TGSI_OPCODE_LAST) { + if (has_label) + report_error( ctx, "Unknown opcode" ); + else + report_error( ctx, "Expected `DCL', `IMM' or a label" ); + return FALSE; + } + + inst.Instruction.Opcode = i; + inst.Instruction.Saturate = saturate; + inst.Instruction.NumDstRegs = info->num_dst; + inst.Instruction.NumSrcRegs = info->num_src; + + if (i >= TGSI_OPCODE_SAMPLE && i <= TGSI_OPCODE_GATHER4) { + /* + * These are not considered tex opcodes here (no additional + * target argument) however we're required to set the Texture + * bit so we can set the number of tex offsets (offsets aren't + * actually handled here yet in any case). + */ + inst.Instruction.Texture = 1; + inst.Texture.Texture = TGSI_TEXTURE_UNKNOWN; + } + + /* Parse instruction operands. + */ + for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) { + if (i > 0) { + eat_opt_white( &ctx->cur ); + if (*ctx->cur != ',') { + report_error( ctx, "Expected `,'" ); + return FALSE; + } + ctx->cur++; + eat_opt_white( &ctx->cur ); + } + + if (i < info->num_dst) { + if (!parse_dst_operand( ctx, &inst.Dst[i] )) + return FALSE; + } + else if (i < info->num_dst + info->num_src) { + if (!parse_src_operand( ctx, &inst.Src[i - info->num_dst] )) + return FALSE; + } + else { + uint j; + + for (j = 0; j < TGSI_TEXTURE_COUNT; j++) { + if (str_match_nocase_whole( &ctx->cur, tgsi_texture_names[j] )) { + inst.Instruction.Texture = 1; + inst.Texture.Texture = j; + break; + } + } + if (j == TGSI_TEXTURE_COUNT) { + report_error( ctx, "Expected texture target" ); + return FALSE; + } + } + } + + if (inst.Instruction.Texture) { + uint j = 0; + + cur = ctx->cur; + eat_opt_white( &cur ); + for (j = 0; j < 4; j++) { + if (*cur == ',') { + ctx->cur = cur; + ctx->cur++; + eat_opt_white( &ctx->cur ); + if (!parse_tex_offset_operand(ctx, &inst.TexOffsets[j])) + return FALSE; + cur = ctx->cur; + } else + break; + } + inst.Texture.NumOffsets = j; + } + + cur = ctx->cur; + eat_opt_white( &cur ); + if (info->is_branch && *cur == ':') { + uint target; + + cur++; + eat_opt_white( &cur ); + if (!parse_uint( &cur, &target )) { + report_error( ctx, "Expected a label" ); + return FALSE; + } + inst.Instruction.Label = 1; + inst.Label.Label = target; + ctx->cur = cur; + } + + advance = tgsi_build_full_instruction( + &inst, + ctx->tokens_cur, + ctx->header, + (uint) (ctx->tokens_end - ctx->tokens_cur) ); + if (advance == 0) + return FALSE; + ctx->tokens_cur += advance; + + return TRUE; +} + +/* parses a 4-touple of the form {x, y, z, w} + * where x, y, z, w are numbers */ +static boolean parse_immediate_data(struct translate_ctx *ctx, unsigned type, + union tgsi_immediate_data *values) +{ + unsigned i; + int ret; + + eat_opt_white( &ctx->cur ); + if (*ctx->cur != '{') { + report_error( ctx, "Expected `{'" ); + return FALSE; + } + ctx->cur++; + for (i = 0; i < 4; i++) { + eat_opt_white( &ctx->cur ); + if (i > 0) { + if (*ctx->cur != ',') { + report_error( ctx, "Expected `,'" ); + return FALSE; + } + ctx->cur++; + eat_opt_white( &ctx->cur ); + } + + switch (type) { + case TGSI_IMM_FLOAT32: + ret = parse_float(&ctx->cur, &values[i].Float); + break; + case TGSI_IMM_UINT32: + ret = parse_uint(&ctx->cur, &values[i].Uint); + break; + case TGSI_IMM_INT32: + ret = parse_int(&ctx->cur, &values[i].Int); + break; + default: + assert(0); + ret = FALSE; + break; + } + + if (!ret) { + report_error( ctx, "Expected immediate constant" ); + return FALSE; + } + } + eat_opt_white( &ctx->cur ); + if (*ctx->cur != '}') { + report_error( ctx, "Expected `}'" ); + return FALSE; + } + ctx->cur++; + + return TRUE; +} + +static boolean parse_declaration( struct translate_ctx *ctx ) +{ + struct tgsi_full_declaration decl; + uint file; + struct parsed_dcl_bracket brackets[2]; + int num_brackets; + uint writemask; + const char *cur, *cur2; + uint advance; + boolean is_vs_input; + + if (!eat_white( &ctx->cur )) { + report_error( ctx, "Syntax error" ); + return FALSE; + } + if (!parse_register_dcl( ctx, &file, brackets, &num_brackets)) + return FALSE; + if (!parse_opt_writemask( ctx, &writemask )) + return FALSE; + + decl = tgsi_default_full_declaration(); + decl.Declaration.File = file; + decl.Declaration.UsageMask = writemask; + + if (num_brackets == 1) { + decl.Range.First = brackets[0].first; + decl.Range.Last = brackets[0].last; + } else { + decl.Range.First = brackets[1].first; + decl.Range.Last = brackets[1].last; + + decl.Declaration.Dimension = 1; + decl.Dim.Index2D = brackets[0].first; + } + + is_vs_input = (file == TGSI_FILE_INPUT && + ctx->processor == TGSI_PROCESSOR_VERTEX); + + cur = ctx->cur; + eat_opt_white( &cur ); + if (*cur == ',') { + cur2 = cur; + cur2++; + eat_opt_white( &cur2 ); + if (str_match_nocase_whole( &cur2, "ARRAY" )) { + int arrayid; + if (*cur2 != '(') { + report_error( ctx, "Expected `('" ); + return FALSE; + } + cur2++; + eat_opt_white( &cur2 ); + if (!parse_int( &cur2, &arrayid )) { + report_error( ctx, "Expected `,'" ); + return FALSE; + } + eat_opt_white( &cur2 ); + if (*cur2 != ')') { + report_error( ctx, "Expected `)'" ); + return FALSE; + } + cur2++; + decl.Declaration.Array = 1; + decl.Array.ArrayID = arrayid; + ctx->cur = cur = cur2; + } + } + + if (*cur == ',' && !is_vs_input) { + uint i, j; + + cur++; + eat_opt_white( &cur ); + if (file == TGSI_FILE_RESOURCE) { + for (i = 0; i < TGSI_TEXTURE_COUNT; i++) { + if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) { + decl.Resource.Resource = i; + break; + } + } + if (i == TGSI_TEXTURE_COUNT) { + report_error(ctx, "Expected texture target"); + return FALSE; + } + + cur2 = cur; + eat_opt_white(&cur2); + while (*cur2 == ',') { + cur2++; + eat_opt_white(&cur2); + if (str_match_nocase_whole(&cur2, "RAW")) { + decl.Resource.Raw = 1; + + } else if (str_match_nocase_whole(&cur2, "WR")) { + decl.Resource.Writable = 1; + + } else { + break; + } + cur = cur2; + eat_opt_white(&cur2); + } + + ctx->cur = cur; + + } else if (file == TGSI_FILE_SAMPLER_VIEW) { + for (i = 0; i < TGSI_TEXTURE_COUNT; i++) { + if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) { + decl.SamplerView.Resource = i; + break; + } + } + if (i == TGSI_TEXTURE_COUNT) { + report_error(ctx, "Expected texture target"); + return FALSE; + } + eat_opt_white( &cur ); + if (*cur != ',') { + report_error( ctx, "Expected `,'" ); + return FALSE; + } + ++cur; + eat_opt_white( &cur ); + for (j = 0; j < 4; ++j) { + for (i = 0; i < PIPE_TYPE_COUNT; ++i) { + if (str_match_nocase_whole(&cur, tgsi_type_names[i])) { + switch (j) { + case 0: + decl.SamplerView.ReturnTypeX = i; + break; + case 1: + decl.SamplerView.ReturnTypeY = i; + break; + case 2: + decl.SamplerView.ReturnTypeZ = i; + break; + case 3: + decl.SamplerView.ReturnTypeW = i; + break; + default: + assert(0); + } + break; + } + } + if (i == PIPE_TYPE_COUNT) { + if (j == 0 || j > 2) { + report_error(ctx, "Expected type name"); + return FALSE; + } + break; + } else { + cur2 = cur; + eat_opt_white( &cur2 ); + if (*cur2 == ',') { + cur2++; + eat_opt_white( &cur2 ); + cur = cur2; + continue; + } else + break; + } + } + if (j < 4) { + decl.SamplerView.ReturnTypeY = + decl.SamplerView.ReturnTypeZ = + decl.SamplerView.ReturnTypeW = + decl.SamplerView.ReturnTypeX; + } + ctx->cur = cur; + } else { + if (str_match_nocase_whole(&cur, "LOCAL")) { + decl.Declaration.Local = 1; + ctx->cur = cur; + } + + cur = ctx->cur; + eat_opt_white( &cur ); + if (*cur == ',') { + cur++; + eat_opt_white( &cur ); + + for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) { + if (str_match_nocase_whole(&cur, tgsi_semantic_names[i])) { + uint index; + + cur2 = cur; + eat_opt_white( &cur2 ); + if (*cur2 == '[') { + cur2++; + eat_opt_white( &cur2 ); + if (!parse_uint( &cur2, &index )) { + report_error( ctx, "Expected literal integer" ); + return FALSE; + } + eat_opt_white( &cur2 ); + if (*cur2 != ']') { + report_error( ctx, "Expected `]'" ); + return FALSE; + } + cur2++; + + decl.Semantic.Index = index; + + cur = cur2; + } + + decl.Declaration.Semantic = 1; + decl.Semantic.Name = i; + + ctx->cur = cur; + break; + } + } + } + } + } + + cur = ctx->cur; + eat_opt_white( &cur ); + if (*cur == ',' && !is_vs_input) { + uint i; + + cur++; + eat_opt_white( &cur ); + for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) { + if (str_match_nocase_whole( &cur, tgsi_interpolate_names[i] )) { + decl.Declaration.Interpolate = 1; + decl.Interp.Interpolate = i; + + ctx->cur = cur; + break; + } + } + if (i == TGSI_INTERPOLATE_COUNT) { + report_error( ctx, "Expected semantic or interpolate attribute" ); + return FALSE; + } + } + + cur = ctx->cur; + eat_opt_white( &cur ); + if (*cur == ',' && !is_vs_input) { + cur++; + eat_opt_white( &cur ); + if (str_match_nocase_whole( &cur, "CENTROID" )) { + decl.Interp.Centroid = 1; + ctx->cur = cur; + } + } + + advance = tgsi_build_full_declaration( + &decl, + ctx->tokens_cur, + ctx->header, + (uint) (ctx->tokens_end - ctx->tokens_cur) ); + + if (advance == 0) + return FALSE; + ctx->tokens_cur += advance; + + return TRUE; +} + +static boolean parse_immediate( struct translate_ctx *ctx ) +{ + struct tgsi_full_immediate imm; + uint advance; + int type; + + if (*ctx->cur == '[') { + uint uindex; + + ++ctx->cur; + + eat_opt_white( &ctx->cur ); + if (!parse_uint( &ctx->cur, &uindex )) { + report_error( ctx, "Expected literal unsigned integer" ); + return FALSE; + } + + if (uindex != ctx->num_immediates) { + report_error( ctx, "Immediates must be sorted" ); + return FALSE; + } + + eat_opt_white( &ctx->cur ); + if (*ctx->cur != ']') { + report_error( ctx, "Expected `]'" ); + return FALSE; + } + + ctx->cur++; + } + + if (!eat_white( &ctx->cur )) { + report_error( ctx, "Syntax error" ); + return FALSE; + } + for (type = 0; type < Elements(tgsi_immediate_type_names); ++type) { + if (str_match_nocase_whole(&ctx->cur, tgsi_immediate_type_names[type])) + break; + } + if (type == Elements(tgsi_immediate_type_names)) { + report_error( ctx, "Expected immediate type" ); + return FALSE; + } + + imm = tgsi_default_full_immediate(); + imm.Immediate.NrTokens += 4; + imm.Immediate.DataType = type; + parse_immediate_data(ctx, type, imm.u); + + advance = tgsi_build_full_immediate( + &imm, + ctx->tokens_cur, + ctx->header, + (uint) (ctx->tokens_end - ctx->tokens_cur) ); + if (advance == 0) + return FALSE; + ctx->tokens_cur += advance; + + ctx->num_immediates++; + + return TRUE; +} + +static boolean +parse_primitive( const char **pcur, uint *primitive ) +{ + uint i; + + for (i = 0; i < PIPE_PRIM_MAX; i++) { + const char *cur = *pcur; + + if (str_match_nocase_whole( &cur, tgsi_primitive_names[i])) { + *primitive = i; + *pcur = cur; + return TRUE; + } + } + return FALSE; +} + +static boolean +parse_fs_coord_origin( const char **pcur, uint *fs_coord_origin ) +{ + uint i; + + for (i = 0; i < Elements(tgsi_fs_coord_origin_names); i++) { + const char *cur = *pcur; + + if (str_match_nocase_whole( &cur, tgsi_fs_coord_origin_names[i])) { + *fs_coord_origin = i; + *pcur = cur; + return TRUE; + } + } + return FALSE; +} + +static boolean +parse_fs_coord_pixel_center( const char **pcur, uint *fs_coord_pixel_center ) +{ + uint i; + + for (i = 0; i < Elements(tgsi_fs_coord_pixel_center_names); i++) { + const char *cur = *pcur; + + if (str_match_nocase_whole( &cur, tgsi_fs_coord_pixel_center_names[i])) { + *fs_coord_pixel_center = i; + *pcur = cur; + return TRUE; + } + } + return FALSE; +} + + +static boolean parse_property( struct translate_ctx *ctx ) +{ + struct tgsi_full_property prop; + uint property_name; + uint values[8]; + uint advance; + char id[64]; + + if (!eat_white( &ctx->cur )) { + report_error( ctx, "Syntax error" ); + return FALSE; + } + if (!parse_identifier( &ctx->cur, id )) { + report_error( ctx, "Syntax error" ); + return FALSE; + } + for (property_name = 0; property_name < TGSI_PROPERTY_COUNT; + ++property_name) { + if (streq_nocase_uprcase(tgsi_property_names[property_name], id)) { + break; + } + } + if (property_name >= TGSI_PROPERTY_COUNT) { + debug_printf( "\nError: Unknown property : '%s'", id ); + return FALSE; + } + + eat_opt_white( &ctx->cur ); + switch(property_name) { + case TGSI_PROPERTY_GS_INPUT_PRIM: + case TGSI_PROPERTY_GS_OUTPUT_PRIM: + if (!parse_primitive(&ctx->cur, &values[0] )) { + report_error( ctx, "Unknown primitive name as property!" ); + return FALSE; + } + if (property_name == TGSI_PROPERTY_GS_INPUT_PRIM && + ctx->processor == TGSI_PROCESSOR_GEOMETRY) { + ctx->implied_array_size = u_vertices_per_prim(values[0]); + } + break; + case TGSI_PROPERTY_FS_COORD_ORIGIN: + if (!parse_fs_coord_origin(&ctx->cur, &values[0] )) { + report_error( ctx, "Unknown coord origin as property: must be UPPER_LEFT or LOWER_LEFT!" ); + return FALSE; + } + break; + case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER: + if (!parse_fs_coord_pixel_center(&ctx->cur, &values[0] )) { + report_error( ctx, "Unknown coord pixel center as property: must be HALF_INTEGER or INTEGER!" ); + return FALSE; + } + break; + case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS: + default: + if (!parse_uint(&ctx->cur, &values[0] )) { + report_error( ctx, "Expected unsigned integer as property!" ); + return FALSE; + } + } + + prop = tgsi_default_full_property(); + prop.Property.PropertyName = property_name; + prop.Property.NrTokens += 1; + prop.u[0].Data = values[0]; + + advance = tgsi_build_full_property( + &prop, + ctx->tokens_cur, + ctx->header, + (uint) (ctx->tokens_end - ctx->tokens_cur) ); + if (advance == 0) + return FALSE; + ctx->tokens_cur += advance; + + return TRUE; +} + + +static boolean translate( struct translate_ctx *ctx ) +{ + eat_opt_white( &ctx->cur ); + if (!parse_header( ctx )) + return FALSE; + + while (*ctx->cur != '\0') { + uint label_val = 0; + if (!eat_white( &ctx->cur )) { + report_error( ctx, "Syntax error" ); + return FALSE; + } + + if (*ctx->cur == '\0') + break; + if (parse_label( ctx, &label_val )) { + if (!parse_instruction( ctx, TRUE )) + return FALSE; + } + else if (str_match_nocase_whole( &ctx->cur, "DCL" )) { + if (!parse_declaration( ctx )) + return FALSE; + } + else if (str_match_nocase_whole( &ctx->cur, "IMM" )) { + if (!parse_immediate( ctx )) + return FALSE; + } + else if (str_match_nocase_whole( &ctx->cur, "PROPERTY" )) { + if (!parse_property( ctx )) + return FALSE; + } + else if (!parse_instruction( ctx, FALSE )) { + return FALSE; + } + } + + return TRUE; +} + +boolean +tgsi_text_translate( + const char *text, + struct tgsi_token *tokens, + uint num_tokens ) +{ + struct translate_ctx ctx = {0}; + + ctx.text = text; + ctx.cur = text; + ctx.tokens = tokens; + ctx.tokens_cur = tokens; + ctx.tokens_end = tokens + num_tokens; + + if (!translate( &ctx )) + return FALSE; + + return tgsi_sanity_check( tokens ); +} diff --git a/src/gallium/auxiliary/tgsi/tgsi_text.h b/src/gallium/auxiliary/tgsi/tgsi_text.h new file mode 100644 index 0000000..6a306e6 --- /dev/null +++ b/src/gallium/auxiliary/tgsi/tgsi_text.h @@ -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 */ diff --git a/src/gallium/auxiliary/tgsi/tgsi_transform.c b/src/gallium/auxiliary/tgsi/tgsi_transform.c new file mode 100644 index 0000000..b16d296 --- /dev/null +++ b/src/gallium/auxiliary/tgsi/tgsi_transform.c @@ -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 ); +} diff --git a/src/gallium/auxiliary/tgsi/tgsi_transform.h b/src/gallium/auxiliary/tgsi/tgsi_transform.h new file mode 100644 index 0000000..8b96664 --- /dev/null +++ b/src/gallium/auxiliary/tgsi/tgsi_transform.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. + * + **************************************************************************/ + +#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 */ diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.c b/src/gallium/auxiliary/tgsi/tgsi_ureg.c new file mode 100644 index 0000000..38cce58 --- /dev/null +++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.c @@ -0,0 +1,1810 @@ +/************************************************************************** + * + * 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, INC 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_context.h" +#include "pipe/p_state.h" +#include "tgsi/tgsi_ureg.h" +#include "tgsi/tgsi_build.h" +#include "tgsi/tgsi_info.h" +#include "tgsi/tgsi_dump.h" +#include "tgsi/tgsi_sanity.h" +#include "util/u_debug.h" +#include "util/u_memory.h" +#include "util/u_math.h" +#include "util/u_bitmask.h" + +union tgsi_any_token { + struct tgsi_header header; + struct tgsi_processor processor; + struct tgsi_token token; + struct tgsi_property prop; + struct tgsi_property_data prop_data; + struct tgsi_declaration decl; + struct tgsi_declaration_range decl_range; + struct tgsi_declaration_dimension decl_dim; + struct tgsi_declaration_interp decl_interp; + struct tgsi_declaration_semantic decl_semantic; + struct tgsi_declaration_sampler_view decl_sampler_view; + struct tgsi_declaration_array array; + struct tgsi_immediate imm; + union tgsi_immediate_data imm_data; + struct tgsi_instruction insn; + struct tgsi_instruction_predicate insn_predicate; + struct tgsi_instruction_label insn_label; + struct tgsi_instruction_texture insn_texture; + struct tgsi_texture_offset insn_texture_offset; + struct tgsi_src_register src; + struct tgsi_ind_register ind; + struct tgsi_dimension dim; + struct tgsi_dst_register dst; + unsigned value; +}; + + +struct ureg_tokens { + union tgsi_any_token *tokens; + unsigned size; + unsigned order; + unsigned count; +}; + +#define UREG_MAX_INPUT PIPE_MAX_ATTRIBS +#define UREG_MAX_SYSTEM_VALUE PIPE_MAX_ATTRIBS +#define UREG_MAX_OUTPUT PIPE_MAX_SHADER_OUTPUTS +#define UREG_MAX_CONSTANT_RANGE 32 +#define UREG_MAX_IMMEDIATE 4096 +#define UREG_MAX_ADDR 2 +#define UREG_MAX_PRED 1 +#define UREG_MAX_ARRAY_TEMPS 256 + +struct const_decl { + struct { + unsigned first; + unsigned last; + } constant_range[UREG_MAX_CONSTANT_RANGE]; + unsigned nr_constant_ranges; +}; + +#define DOMAIN_DECL 0 +#define DOMAIN_INSN 1 + +struct ureg_program +{ + unsigned processor; + struct pipe_context *pipe; + + struct { + unsigned semantic_name; + unsigned semantic_index; + unsigned interp; + unsigned char cylindrical_wrap; + unsigned char centroid; + } fs_input[UREG_MAX_INPUT]; + unsigned nr_fs_inputs; + + unsigned vs_inputs[UREG_MAX_INPUT/32]; + + struct { + unsigned index; + unsigned semantic_name; + unsigned semantic_index; + } gs_input[UREG_MAX_INPUT]; + unsigned nr_gs_inputs; + + struct { + unsigned index; + unsigned semantic_name; + unsigned semantic_index; + } system_value[UREG_MAX_SYSTEM_VALUE]; + unsigned nr_system_values; + + struct { + unsigned semantic_name; + unsigned semantic_index; + unsigned usage_mask; /* = TGSI_WRITEMASK_* */ + } output[UREG_MAX_OUTPUT]; + unsigned nr_outputs; + + struct { + union { + float f[4]; + unsigned u[4]; + int i[4]; + } value; + unsigned nr; + unsigned type; + } immediate[UREG_MAX_IMMEDIATE]; + unsigned nr_immediates; + + struct ureg_src sampler[PIPE_MAX_SAMPLERS]; + unsigned nr_samplers; + + struct { + unsigned index; + unsigned target; + unsigned return_type_x; + unsigned return_type_y; + unsigned return_type_z; + unsigned return_type_w; + } sampler_view[PIPE_MAX_SHADER_SAMPLER_VIEWS]; + unsigned nr_sampler_views; + + struct util_bitmask *free_temps; + struct util_bitmask *local_temps; + struct util_bitmask *decl_temps; + unsigned nr_temps; + + unsigned array_temps[UREG_MAX_ARRAY_TEMPS]; + unsigned nr_array_temps; + + struct const_decl const_decls; + struct const_decl const_decls2D[PIPE_MAX_CONSTANT_BUFFERS]; + + unsigned property_gs_input_prim; + unsigned property_gs_output_prim; + unsigned property_gs_max_vertices; + unsigned property_gs_invocations; + unsigned char property_fs_coord_origin; /* = TGSI_FS_COORD_ORIGIN_* */ + unsigned char property_fs_coord_pixel_center; /* = TGSI_FS_COORD_PIXEL_CENTER_* */ + unsigned char property_fs_color0_writes_all_cbufs; /* = TGSI_FS_COLOR0_WRITES_ALL_CBUFS * */ + unsigned char property_fs_depth_layout; /* TGSI_FS_DEPTH_LAYOUT */ + + unsigned nr_addrs; + unsigned nr_preds; + unsigned nr_instructions; + + struct ureg_tokens domain[2]; +}; + +static union tgsi_any_token error_tokens[32]; + +static void tokens_error( struct ureg_tokens *tokens ) +{ + if (tokens->tokens && tokens->tokens != error_tokens) + FREE(tokens->tokens); + + tokens->tokens = error_tokens; + tokens->size = Elements(error_tokens); + tokens->count = 0; +} + + +static void tokens_expand( struct ureg_tokens *tokens, + unsigned count ) +{ + unsigned old_size = tokens->size * sizeof(unsigned); + + if (tokens->tokens == error_tokens) { + return; + } + + while (tokens->count + count > tokens->size) { + tokens->size = (1 << ++tokens->order); + } + + tokens->tokens = REALLOC(tokens->tokens, + old_size, + tokens->size * sizeof(unsigned)); + if (tokens->tokens == NULL) { + tokens_error(tokens); + } +} + +static void set_bad( struct ureg_program *ureg ) +{ + tokens_error(&ureg->domain[0]); +} + + + +static union tgsi_any_token *get_tokens( struct ureg_program *ureg, + unsigned domain, + unsigned count ) +{ + struct ureg_tokens *tokens = &ureg->domain[domain]; + union tgsi_any_token *result; + + if (tokens->count + count > tokens->size) + tokens_expand(tokens, count); + + result = &tokens->tokens[tokens->count]; + tokens->count += count; + return result; +} + + +static union tgsi_any_token *retrieve_token( struct ureg_program *ureg, + unsigned domain, + unsigned nr ) +{ + if (ureg->domain[domain].tokens == error_tokens) + return &error_tokens[0]; + + return &ureg->domain[domain].tokens[nr]; +} + + + +static INLINE struct ureg_dst +ureg_dst_register( unsigned file, + unsigned index ) +{ + struct ureg_dst dst; + + dst.File = file; + dst.WriteMask = TGSI_WRITEMASK_XYZW; + dst.Indirect = 0; + dst.IndirectFile = TGSI_FILE_NULL; + dst.IndirectIndex = 0; + dst.IndirectSwizzle = 0; + dst.Saturate = 0; + dst.Predicate = 0; + dst.PredNegate = 0; + dst.PredSwizzleX = TGSI_SWIZZLE_X; + dst.PredSwizzleY = TGSI_SWIZZLE_Y; + dst.PredSwizzleZ = TGSI_SWIZZLE_Z; + dst.PredSwizzleW = TGSI_SWIZZLE_W; + dst.Index = index; + dst.ArrayID = 0; + + return dst; +} + + +void +ureg_property_gs_input_prim(struct ureg_program *ureg, + unsigned input_prim) +{ + ureg->property_gs_input_prim = input_prim; +} + +void +ureg_property_gs_output_prim(struct ureg_program *ureg, + unsigned output_prim) +{ + ureg->property_gs_output_prim = output_prim; +} + +void +ureg_property_gs_max_vertices(struct ureg_program *ureg, + unsigned max_vertices) +{ + ureg->property_gs_max_vertices = max_vertices; +} +void +ureg_property_gs_invocations(struct ureg_program *ureg, + unsigned invocations) +{ + ureg->property_gs_invocations = invocations; +} + +void +ureg_property_fs_coord_origin(struct ureg_program *ureg, + unsigned fs_coord_origin) +{ + ureg->property_fs_coord_origin = fs_coord_origin; +} + +void +ureg_property_fs_coord_pixel_center(struct ureg_program *ureg, + unsigned fs_coord_pixel_center) +{ + ureg->property_fs_coord_pixel_center = fs_coord_pixel_center; +} + +void +ureg_property_fs_color0_writes_all_cbufs(struct ureg_program *ureg, + unsigned fs_color0_writes_all_cbufs) +{ + ureg->property_fs_color0_writes_all_cbufs = fs_color0_writes_all_cbufs; +} + +void +ureg_property_fs_depth_layout(struct ureg_program *ureg, + unsigned fs_depth_layout) +{ + ureg->property_fs_depth_layout = fs_depth_layout; +} + +struct ureg_src +ureg_DECL_fs_input_cyl_centroid(struct ureg_program *ureg, + unsigned semantic_name, + unsigned semantic_index, + unsigned interp_mode, + unsigned cylindrical_wrap, + unsigned centroid) +{ + unsigned i; + + for (i = 0; i < ureg->nr_fs_inputs; i++) { + if (ureg->fs_input[i].semantic_name == semantic_name && + ureg->fs_input[i].semantic_index == semantic_index) { + goto out; + } + } + + if (ureg->nr_fs_inputs < UREG_MAX_INPUT) { + ureg->fs_input[i].semantic_name = semantic_name; + ureg->fs_input[i].semantic_index = semantic_index; + ureg->fs_input[i].interp = interp_mode; + ureg->fs_input[i].cylindrical_wrap = cylindrical_wrap; + ureg->fs_input[i].centroid = centroid; + ureg->nr_fs_inputs++; + } else { + set_bad(ureg); + } + +out: + return ureg_src_register(TGSI_FILE_INPUT, i); +} + + +struct ureg_src +ureg_DECL_vs_input( struct ureg_program *ureg, + unsigned index ) +{ + assert(ureg->processor == TGSI_PROCESSOR_VERTEX); + + ureg->vs_inputs[index/32] |= 1 << (index % 32); + return ureg_src_register( TGSI_FILE_INPUT, index ); +} + + +struct ureg_src +ureg_DECL_gs_input(struct ureg_program *ureg, + unsigned index, + unsigned semantic_name, + unsigned semantic_index) +{ + if (ureg->nr_gs_inputs < UREG_MAX_INPUT) { + ureg->gs_input[ureg->nr_gs_inputs].index = index; + ureg->gs_input[ureg->nr_gs_inputs].semantic_name = semantic_name; + ureg->gs_input[ureg->nr_gs_inputs].semantic_index = semantic_index; + ureg->nr_gs_inputs++; + } else { + set_bad(ureg); + } + + /* XXX: Add suport for true 2D input registers. */ + return ureg_src_register(TGSI_FILE_INPUT, index); +} + + +struct ureg_src +ureg_DECL_system_value(struct ureg_program *ureg, + unsigned index, + unsigned semantic_name, + unsigned semantic_index) +{ + if (ureg->nr_system_values < UREG_MAX_SYSTEM_VALUE) { + ureg->system_value[ureg->nr_system_values].index = index; + ureg->system_value[ureg->nr_system_values].semantic_name = semantic_name; + ureg->system_value[ureg->nr_system_values].semantic_index = semantic_index; + ureg->nr_system_values++; + } else { + set_bad(ureg); + } + + return ureg_src_register(TGSI_FILE_SYSTEM_VALUE, index); +} + + +struct ureg_dst +ureg_DECL_output_masked( struct ureg_program *ureg, + unsigned name, + unsigned index, + unsigned usage_mask ) +{ + unsigned i; + + assert(usage_mask != 0); + + for (i = 0; i < ureg->nr_outputs; i++) { + if (ureg->output[i].semantic_name == name && + ureg->output[i].semantic_index == index) { + ureg->output[i].usage_mask |= usage_mask; + goto out; + } + } + + if (ureg->nr_outputs < UREG_MAX_OUTPUT) { + ureg->output[i].semantic_name = name; + ureg->output[i].semantic_index = index; + ureg->output[i].usage_mask = usage_mask; + ureg->nr_outputs++; + } + else { + set_bad( ureg ); + } + +out: + return ureg_dst_register( TGSI_FILE_OUTPUT, i ); +} + + +struct ureg_dst +ureg_DECL_output( struct ureg_program *ureg, + unsigned name, + unsigned index ) +{ + return ureg_DECL_output_masked(ureg, name, index, TGSI_WRITEMASK_XYZW); +} + + +/* Returns a new constant register. Keep track of which have been + * referred to so that we can emit decls later. + * + * Constant operands declared with this function must be addressed + * with a two-dimensional index. + * + * There is nothing in this code to bind this constant to any tracked + * value or manage any constant_buffer contents -- that's the + * resposibility of the calling code. + */ +void +ureg_DECL_constant2D(struct ureg_program *ureg, + unsigned first, + unsigned last, + unsigned index2D) +{ + struct const_decl *decl = &ureg->const_decls2D[index2D]; + + assert(index2D < PIPE_MAX_CONSTANT_BUFFERS); + + if (decl->nr_constant_ranges < UREG_MAX_CONSTANT_RANGE) { + uint i = decl->nr_constant_ranges++; + + decl->constant_range[i].first = first; + decl->constant_range[i].last = last; + } +} + + +/* A one-dimensional, depricated version of ureg_DECL_constant2D(). + * + * Constant operands declared with this function must be addressed + * with a one-dimensional index. + */ +struct ureg_src +ureg_DECL_constant(struct ureg_program *ureg, + unsigned index) +{ + struct const_decl *decl = &ureg->const_decls; + unsigned minconst = index, maxconst = index; + unsigned i; + + /* Inside existing range? + */ + for (i = 0; i < decl->nr_constant_ranges; i++) { + if (decl->constant_range[i].first <= index && + decl->constant_range[i].last >= index) { + goto out; + } + } + + /* Extend existing range? + */ + for (i = 0; i < decl->nr_constant_ranges; i++) { + if (decl->constant_range[i].last == index - 1) { + decl->constant_range[i].last = index; + goto out; + } + + if (decl->constant_range[i].first == index + 1) { + decl->constant_range[i].first = index; + goto out; + } + + minconst = MIN2(minconst, decl->constant_range[i].first); + maxconst = MAX2(maxconst, decl->constant_range[i].last); + } + + /* Create new range? + */ + if (decl->nr_constant_ranges < UREG_MAX_CONSTANT_RANGE) { + i = decl->nr_constant_ranges++; + decl->constant_range[i].first = index; + decl->constant_range[i].last = index; + goto out; + } + + /* Collapse all ranges down to one: + */ + i = 0; + decl->constant_range[0].first = minconst; + decl->constant_range[0].last = maxconst; + decl->nr_constant_ranges = 1; + +out: + assert(i < decl->nr_constant_ranges); + assert(decl->constant_range[i].first <= index); + assert(decl->constant_range[i].last >= index); + return ureg_src_register(TGSI_FILE_CONSTANT, index); +} + +static struct ureg_dst alloc_temporary( struct ureg_program *ureg, + boolean local ) +{ + unsigned i; + + /* Look for a released temporary. + */ + for (i = util_bitmask_get_first_index(ureg->free_temps); + i != UTIL_BITMASK_INVALID_INDEX; + i = util_bitmask_get_next_index(ureg->free_temps, i + 1)) { + if (util_bitmask_get(ureg->local_temps, i) == local) + break; + } + + /* Or allocate a new one. + */ + if (i == UTIL_BITMASK_INVALID_INDEX) { + i = ureg->nr_temps++; + + if (local) + util_bitmask_set(ureg->local_temps, i); + + /* Start a new declaration when the local flag changes */ + if (!i || util_bitmask_get(ureg->local_temps, i - 1) != local) + util_bitmask_set(ureg->decl_temps, i); + } + + util_bitmask_clear(ureg->free_temps, i); + + return ureg_dst_register( TGSI_FILE_TEMPORARY, i ); +} + +struct ureg_dst ureg_DECL_temporary( struct ureg_program *ureg ) +{ + return alloc_temporary(ureg, FALSE); +} + +struct ureg_dst ureg_DECL_local_temporary( struct ureg_program *ureg ) +{ + return alloc_temporary(ureg, TRUE); +} + +struct ureg_dst ureg_DECL_array_temporary( struct ureg_program *ureg, + unsigned size, + boolean local ) +{ + unsigned i = ureg->nr_temps; + struct ureg_dst dst = ureg_dst_register( TGSI_FILE_TEMPORARY, i ); + + if (local) + util_bitmask_set(ureg->local_temps, i); + + /* Always start a new declaration at the start */ + util_bitmask_set(ureg->decl_temps, i); + + ureg->nr_temps += size; + + /* and also at the end of the array */ + util_bitmask_set(ureg->decl_temps, ureg->nr_temps); + + if (ureg->nr_array_temps < UREG_MAX_ARRAY_TEMPS) { + ureg->array_temps[ureg->nr_array_temps++] = i; + dst.ArrayID = ureg->nr_array_temps; + } + + return dst; +} + +void ureg_release_temporary( struct ureg_program *ureg, + struct ureg_dst tmp ) +{ + if(tmp.File == TGSI_FILE_TEMPORARY) + util_bitmask_set(ureg->free_temps, tmp.Index); +} + + +/* Allocate a new address register. + */ +struct ureg_dst ureg_DECL_address( struct ureg_program *ureg ) +{ + if (ureg->nr_addrs < UREG_MAX_ADDR) + return ureg_dst_register( TGSI_FILE_ADDRESS, ureg->nr_addrs++ ); + + assert( 0 ); + return ureg_dst_register( TGSI_FILE_ADDRESS, 0 ); +} + +/* Allocate a new predicate register. + */ +struct ureg_dst +ureg_DECL_predicate(struct ureg_program *ureg) +{ + if (ureg->nr_preds < UREG_MAX_PRED) { + return ureg_dst_register(TGSI_FILE_PREDICATE, ureg->nr_preds++); + } + + assert(0); + return ureg_dst_register(TGSI_FILE_PREDICATE, 0); +} + +/* Allocate a new sampler. + */ +struct ureg_src ureg_DECL_sampler( struct ureg_program *ureg, + unsigned nr ) +{ + unsigned i; + + for (i = 0; i < ureg->nr_samplers; i++) + if (ureg->sampler[i].Index == nr) + return ureg->sampler[i]; + + if (i < PIPE_MAX_SAMPLERS) { + ureg->sampler[i] = ureg_src_register( TGSI_FILE_SAMPLER, nr ); + ureg->nr_samplers++; + return ureg->sampler[i]; + } + + assert( 0 ); + return ureg->sampler[0]; +} + +/* + * Allocate a new shader sampler view. + */ +struct ureg_src +ureg_DECL_sampler_view(struct ureg_program *ureg, + unsigned index, + unsigned target, + unsigned return_type_x, + unsigned return_type_y, + unsigned return_type_z, + unsigned return_type_w) +{ + struct ureg_src reg = ureg_src_register(TGSI_FILE_SAMPLER_VIEW, index); + uint i; + + for (i = 0; i < ureg->nr_sampler_views; i++) { + if (ureg->sampler_view[i].index == index) { + return reg; + } + } + + if (i < PIPE_MAX_SHADER_SAMPLER_VIEWS) { + ureg->sampler_view[i].index = index; + ureg->sampler_view[i].target = target; + ureg->sampler_view[i].return_type_x = return_type_x; + ureg->sampler_view[i].return_type_y = return_type_y; + ureg->sampler_view[i].return_type_z = return_type_z; + ureg->sampler_view[i].return_type_w = return_type_w; + ureg->nr_sampler_views++; + return reg; + } + + assert(0); + return reg; +} + +static int +match_or_expand_immediate( const unsigned *v, + unsigned nr, + unsigned *v2, + unsigned *pnr2, + unsigned *swizzle ) +{ + unsigned nr2 = *pnr2; + unsigned i, j; + + *swizzle = 0; + + for (i = 0; i < nr; i++) { + boolean found = FALSE; + + for (j = 0; j < nr2 && !found; j++) { + if (v[i] == v2[j]) { + *swizzle |= j << (i * 2); + found = TRUE; + } + } + + if (!found) { + if (nr2 >= 4) { + return FALSE; + } + + v2[nr2] = v[i]; + *swizzle |= nr2 << (i * 2); + nr2++; + } + } + + /* Actually expand immediate only when fully succeeded. + */ + *pnr2 = nr2; + return TRUE; +} + + +static struct ureg_src +decl_immediate( struct ureg_program *ureg, + const unsigned *v, + unsigned nr, + unsigned type ) +{ + unsigned i, j; + unsigned swizzle = 0; + + /* Could do a first pass where we examine all existing immediates + * without expanding. + */ + + for (i = 0; i < ureg->nr_immediates; i++) { + if (ureg->immediate[i].type != type) { + continue; + } + if (match_or_expand_immediate(v, + nr, + ureg->immediate[i].value.u, + &ureg->immediate[i].nr, + &swizzle)) { + goto out; + } + } + + if (ureg->nr_immediates < UREG_MAX_IMMEDIATE) { + i = ureg->nr_immediates++; + ureg->immediate[i].type = type; + if (match_or_expand_immediate(v, + nr, + ureg->immediate[i].value.u, + &ureg->immediate[i].nr, + &swizzle)) { + goto out; + } + } + + set_bad(ureg); + +out: + /* Make sure that all referenced elements are from this immediate. + * Has the effect of making size-one immediates into scalars. + */ + for (j = nr; j < 4; j++) { + swizzle |= (swizzle & 0x3) << (j * 2); + } + + return ureg_swizzle(ureg_src_register(TGSI_FILE_IMMEDIATE, i), + (swizzle >> 0) & 0x3, + (swizzle >> 2) & 0x3, + (swizzle >> 4) & 0x3, + (swizzle >> 6) & 0x3); +} + + +struct ureg_src +ureg_DECL_immediate( struct ureg_program *ureg, + const float *v, + unsigned nr ) +{ + union { + float f[4]; + unsigned u[4]; + } fu; + unsigned int i; + + for (i = 0; i < nr; i++) { + fu.f[i] = v[i]; + } + + return decl_immediate(ureg, fu.u, nr, TGSI_IMM_FLOAT32); +} + + +struct ureg_src +ureg_DECL_immediate_uint( struct ureg_program *ureg, + const unsigned *v, + unsigned nr ) +{ + return decl_immediate(ureg, v, nr, TGSI_IMM_UINT32); +} + + +struct ureg_src +ureg_DECL_immediate_block_uint( struct ureg_program *ureg, + const unsigned *v, + unsigned nr ) +{ + uint index; + uint i; + + if (ureg->nr_immediates + (nr + 3) / 4 > UREG_MAX_IMMEDIATE) { + set_bad(ureg); + return ureg_src_register(TGSI_FILE_IMMEDIATE, 0); + } + + index = ureg->nr_immediates; + ureg->nr_immediates += (nr + 3) / 4; + + for (i = index; i < ureg->nr_immediates; i++) { + ureg->immediate[i].type = TGSI_IMM_UINT32; + ureg->immediate[i].nr = nr > 4 ? 4 : nr; + memcpy(ureg->immediate[i].value.u, + &v[(i - index) * 4], + ureg->immediate[i].nr * sizeof(uint)); + nr -= 4; + } + + return ureg_src_register(TGSI_FILE_IMMEDIATE, index); +} + + +struct ureg_src +ureg_DECL_immediate_int( struct ureg_program *ureg, + const int *v, + unsigned nr ) +{ + return decl_immediate(ureg, (const unsigned *)v, nr, TGSI_IMM_INT32); +} + + +void +ureg_emit_src( struct ureg_program *ureg, + struct ureg_src src ) +{ + unsigned size = 1 + (src.Indirect ? 1 : 0) + + (src.Dimension ? (src.DimIndirect ? 2 : 1) : 0); + + union tgsi_any_token *out = get_tokens( ureg, DOMAIN_INSN, size ); + unsigned n = 0; + + assert(src.File != TGSI_FILE_NULL); + assert(src.File < TGSI_FILE_COUNT); + + out[n].value = 0; + out[n].src.File = src.File; + out[n].src.SwizzleX = src.SwizzleX; + out[n].src.SwizzleY = src.SwizzleY; + out[n].src.SwizzleZ = src.SwizzleZ; + out[n].src.SwizzleW = src.SwizzleW; + out[n].src.Index = src.Index; + out[n].src.Negate = src.Negate; + out[0].src.Absolute = src.Absolute; + n++; + + if (src.Indirect) { + out[0].src.Indirect = 1; + out[n].value = 0; + out[n].ind.File = src.IndirectFile; + out[n].ind.Swizzle = src.IndirectSwizzle; + out[n].ind.Index = src.IndirectIndex; + out[n].ind.ArrayID = src.ArrayID; + n++; + } + + if (src.Dimension) { + out[0].src.Dimension = 1; + out[n].dim.Dimension = 0; + out[n].dim.Padding = 0; + if (src.DimIndirect) { + out[n].dim.Indirect = 1; + out[n].dim.Index = src.DimensionIndex; + n++; + out[n].value = 0; + out[n].ind.File = src.DimIndFile; + out[n].ind.Swizzle = src.DimIndSwizzle; + out[n].ind.Index = src.DimIndIndex; + out[n].ind.ArrayID = src.ArrayID; + } else { + out[n].dim.Indirect = 0; + out[n].dim.Index = src.DimensionIndex; + } + n++; + } + + assert(n == size); +} + + +void +ureg_emit_dst( struct ureg_program *ureg, + struct ureg_dst dst ) +{ + unsigned size = (1 + + (dst.Indirect ? 1 : 0)); + + union tgsi_any_token *out = get_tokens( ureg, DOMAIN_INSN, size ); + unsigned n = 0; + + assert(dst.File != TGSI_FILE_NULL); + assert(dst.File != TGSI_FILE_CONSTANT); + assert(dst.File != TGSI_FILE_INPUT); + assert(dst.File != TGSI_FILE_SAMPLER); + assert(dst.File != TGSI_FILE_SAMPLER_VIEW); + assert(dst.File != TGSI_FILE_IMMEDIATE); + assert(dst.File < TGSI_FILE_COUNT); + + out[n].value = 0; + out[n].dst.File = dst.File; + out[n].dst.WriteMask = dst.WriteMask; + out[n].dst.Indirect = dst.Indirect; + out[n].dst.Index = dst.Index; + n++; + + if (dst.Indirect) { + out[n].value = 0; + out[n].ind.File = dst.IndirectFile; + out[n].ind.Swizzle = dst.IndirectSwizzle; + out[n].ind.Index = dst.IndirectIndex; + out[n].ind.ArrayID = dst.ArrayID; + n++; + } + + assert(n == size); +} + + +static void validate( unsigned opcode, + unsigned nr_dst, + unsigned nr_src ) +{ +#ifdef DEBUG + const struct tgsi_opcode_info *info = tgsi_get_opcode_info( opcode ); + assert(info); + if(info) { + assert(nr_dst == info->num_dst); + assert(nr_src == info->num_src); + } +#endif +} + +struct ureg_emit_insn_result +ureg_emit_insn(struct ureg_program *ureg, + unsigned opcode, + boolean saturate, + boolean predicate, + boolean pred_negate, + unsigned pred_swizzle_x, + unsigned pred_swizzle_y, + unsigned pred_swizzle_z, + unsigned pred_swizzle_w, + unsigned num_dst, + unsigned num_src ) +{ + union tgsi_any_token *out; + uint count = predicate ? 2 : 1; + struct ureg_emit_insn_result result; + + validate( opcode, num_dst, num_src ); + + out = get_tokens( ureg, DOMAIN_INSN, count ); + out[0].insn = tgsi_default_instruction(); + out[0].insn.Opcode = opcode; + out[0].insn.Saturate = saturate; + out[0].insn.NumDstRegs = num_dst; + out[0].insn.NumSrcRegs = num_src; + + result.insn_token = ureg->domain[DOMAIN_INSN].count - count; + result.extended_token = result.insn_token; + + if (predicate) { + out[0].insn.Predicate = 1; + out[1].insn_predicate = tgsi_default_instruction_predicate(); + out[1].insn_predicate.Negate = pred_negate; + out[1].insn_predicate.SwizzleX = pred_swizzle_x; + out[1].insn_predicate.SwizzleY = pred_swizzle_y; + out[1].insn_predicate.SwizzleZ = pred_swizzle_z; + out[1].insn_predicate.SwizzleW = pred_swizzle_w; + } + + ureg->nr_instructions++; + + return result; +} + + +void +ureg_emit_label(struct ureg_program *ureg, + unsigned extended_token, + unsigned *label_token ) +{ + union tgsi_any_token *out, *insn; + + if(!label_token) + return; + + out = get_tokens( ureg, DOMAIN_INSN, 1 ); + out[0].value = 0; + + insn = retrieve_token( ureg, DOMAIN_INSN, extended_token ); + insn->insn.Label = 1; + + *label_token = ureg->domain[DOMAIN_INSN].count - 1; +} + +/* Will return a number which can be used in a label to point to the + * next instruction to be emitted. + */ +unsigned +ureg_get_instruction_number( struct ureg_program *ureg ) +{ + return ureg->nr_instructions; +} + +/* Patch a given label (expressed as a token number) to point to a + * given instruction (expressed as an instruction number). + */ +void +ureg_fixup_label(struct ureg_program *ureg, + unsigned label_token, + unsigned instruction_number ) +{ + union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_INSN, label_token ); + + out->insn_label.Label = instruction_number; +} + + +void +ureg_emit_texture(struct ureg_program *ureg, + unsigned extended_token, + unsigned target, unsigned num_offsets) +{ + union tgsi_any_token *out, *insn; + + out = get_tokens( ureg, DOMAIN_INSN, 1 ); + insn = retrieve_token( ureg, DOMAIN_INSN, extended_token ); + + insn->insn.Texture = 1; + + out[0].value = 0; + out[0].insn_texture.Texture = target; + out[0].insn_texture.NumOffsets = num_offsets; +} + +void +ureg_emit_texture_offset(struct ureg_program *ureg, + const struct tgsi_texture_offset *offset) +{ + union tgsi_any_token *out; + + out = get_tokens( ureg, DOMAIN_INSN, 1); + + out[0].value = 0; + out[0].insn_texture_offset = *offset; + +} + + +void +ureg_fixup_insn_size(struct ureg_program *ureg, + unsigned insn ) +{ + union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_INSN, insn ); + + assert(out->insn.Type == TGSI_TOKEN_TYPE_INSTRUCTION); + out->insn.NrTokens = ureg->domain[DOMAIN_INSN].count - insn - 1; +} + + +void +ureg_insn(struct ureg_program *ureg, + unsigned opcode, + const struct ureg_dst *dst, + unsigned nr_dst, + const struct ureg_src *src, + unsigned nr_src ) +{ + struct ureg_emit_insn_result insn; + unsigned i; + boolean saturate; + boolean predicate; + boolean negate = FALSE; + unsigned swizzle[4] = { 0 }; + + if (nr_dst && ureg_dst_is_empty(dst[0])) { + return; + } + + saturate = nr_dst ? dst[0].Saturate : FALSE; + predicate = nr_dst ? dst[0].Predicate : FALSE; + if (predicate) { + negate = dst[0].PredNegate; + swizzle[0] = dst[0].PredSwizzleX; + swizzle[1] = dst[0].PredSwizzleY; + swizzle[2] = dst[0].PredSwizzleZ; + swizzle[3] = dst[0].PredSwizzleW; + } + + insn = ureg_emit_insn(ureg, + opcode, + saturate, + predicate, + negate, + swizzle[0], + swizzle[1], + swizzle[2], + swizzle[3], + nr_dst, + nr_src); + + for (i = 0; i < nr_dst; i++) + ureg_emit_dst( ureg, dst[i] ); + + for (i = 0; i < nr_src; i++) + ureg_emit_src( ureg, src[i] ); + + ureg_fixup_insn_size( ureg, insn.insn_token ); +} + +void +ureg_tex_insn(struct ureg_program *ureg, + unsigned opcode, + const struct ureg_dst *dst, + unsigned nr_dst, + unsigned target, + const struct tgsi_texture_offset *texoffsets, + unsigned nr_offset, + const struct ureg_src *src, + unsigned nr_src ) +{ + struct ureg_emit_insn_result insn; + unsigned i; + boolean saturate; + boolean predicate; + boolean negate = FALSE; + unsigned swizzle[4] = { 0 }; + + if (nr_dst && ureg_dst_is_empty(dst[0])) { + return; + } + + saturate = nr_dst ? dst[0].Saturate : FALSE; + predicate = nr_dst ? dst[0].Predicate : FALSE; + if (predicate) { + negate = dst[0].PredNegate; + swizzle[0] = dst[0].PredSwizzleX; + swizzle[1] = dst[0].PredSwizzleY; + swizzle[2] = dst[0].PredSwizzleZ; + swizzle[3] = dst[0].PredSwizzleW; + } + + insn = ureg_emit_insn(ureg, + opcode, + saturate, + predicate, + negate, + swizzle[0], + swizzle[1], + swizzle[2], + swizzle[3], + nr_dst, + nr_src); + + ureg_emit_texture( ureg, insn.extended_token, target, nr_offset ); + + for (i = 0; i < nr_offset; i++) + ureg_emit_texture_offset( ureg, &texoffsets[i]); + + for (i = 0; i < nr_dst; i++) + ureg_emit_dst( ureg, dst[i] ); + + for (i = 0; i < nr_src; i++) + ureg_emit_src( ureg, src[i] ); + + ureg_fixup_insn_size( ureg, insn.insn_token ); +} + + +void +ureg_label_insn(struct ureg_program *ureg, + unsigned opcode, + const struct ureg_src *src, + unsigned nr_src, + unsigned *label_token ) +{ + struct ureg_emit_insn_result insn; + unsigned i; + + insn = ureg_emit_insn(ureg, + opcode, + FALSE, + FALSE, + FALSE, + TGSI_SWIZZLE_X, + TGSI_SWIZZLE_Y, + TGSI_SWIZZLE_Z, + TGSI_SWIZZLE_W, + 0, + nr_src); + + ureg_emit_label( ureg, insn.extended_token, label_token ); + + for (i = 0; i < nr_src; i++) + ureg_emit_src( ureg, src[i] ); + + ureg_fixup_insn_size( ureg, insn.insn_token ); +} + + +static void +emit_decl_semantic(struct ureg_program *ureg, + unsigned file, + unsigned index, + unsigned semantic_name, + unsigned semantic_index, + unsigned usage_mask) +{ + union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 3); + + out[0].value = 0; + out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; + out[0].decl.NrTokens = 3; + out[0].decl.File = file; + out[0].decl.UsageMask = usage_mask; + out[0].decl.Semantic = 1; + + out[1].value = 0; + out[1].decl_range.First = index; + out[1].decl_range.Last = index; + + out[2].value = 0; + out[2].decl_semantic.Name = semantic_name; + out[2].decl_semantic.Index = semantic_index; +} + + +static void +emit_decl_fs(struct ureg_program *ureg, + unsigned file, + unsigned index, + unsigned semantic_name, + unsigned semantic_index, + unsigned interpolate, + unsigned cylindrical_wrap, + unsigned centroid) +{ + union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 4); + + out[0].value = 0; + out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; + out[0].decl.NrTokens = 4; + out[0].decl.File = file; + out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW; /* FIXME! */ + out[0].decl.Interpolate = 1; + out[0].decl.Semantic = 1; + + out[1].value = 0; + out[1].decl_range.First = index; + out[1].decl_range.Last = index; + + out[2].value = 0; + out[2].decl_interp.Interpolate = interpolate; + out[2].decl_interp.CylindricalWrap = cylindrical_wrap; + out[2].decl_interp.Centroid = centroid; + + out[3].value = 0; + out[3].decl_semantic.Name = semantic_name; + out[3].decl_semantic.Index = semantic_index; +} + +static void +emit_decl_temps( struct ureg_program *ureg, + unsigned first, unsigned last, + boolean local, + unsigned arrayid ) +{ + union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, + arrayid ? 3 : 2 ); + + out[0].value = 0; + out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; + out[0].decl.NrTokens = 2; + out[0].decl.File = TGSI_FILE_TEMPORARY; + out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW; + out[0].decl.Local = local; + + out[1].value = 0; + out[1].decl_range.First = first; + out[1].decl_range.Last = last; + + if (arrayid) { + out[0].decl.Array = 1; + out[2].value = 0; + out[2].array.ArrayID = arrayid; + } +} + +static void emit_decl_range( struct ureg_program *ureg, + unsigned file, + unsigned first, + unsigned count ) +{ + union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 2 ); + + out[0].value = 0; + out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; + out[0].decl.NrTokens = 2; + out[0].decl.File = file; + out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW; + out[0].decl.Semantic = 0; + + out[1].value = 0; + out[1].decl_range.First = first; + out[1].decl_range.Last = first + count - 1; +} + +static void +emit_decl_range2D(struct ureg_program *ureg, + unsigned file, + unsigned first, + unsigned last, + unsigned index2D) +{ + union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 3); + + out[0].value = 0; + out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; + out[0].decl.NrTokens = 3; + out[0].decl.File = file; + out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW; + out[0].decl.Dimension = 1; + + out[1].value = 0; + out[1].decl_range.First = first; + out[1].decl_range.Last = last; + + out[2].value = 0; + out[2].decl_dim.Index2D = index2D; +} + +static void +emit_decl_sampler_view(struct ureg_program *ureg, + unsigned index, + unsigned target, + unsigned return_type_x, + unsigned return_type_y, + unsigned return_type_z, + unsigned return_type_w ) +{ + union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 3); + + out[0].value = 0; + out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; + out[0].decl.NrTokens = 3; + out[0].decl.File = TGSI_FILE_SAMPLER_VIEW; + out[0].decl.UsageMask = 0xf; + + out[1].value = 0; + out[1].decl_range.First = index; + out[1].decl_range.Last = index; + + out[2].value = 0; + out[2].decl_sampler_view.Resource = target; + out[2].decl_sampler_view.ReturnTypeX = return_type_x; + out[2].decl_sampler_view.ReturnTypeY = return_type_y; + out[2].decl_sampler_view.ReturnTypeZ = return_type_z; + out[2].decl_sampler_view.ReturnTypeW = return_type_w; +} + +static void +emit_immediate( struct ureg_program *ureg, + const unsigned *v, + unsigned type ) +{ + union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 5 ); + + out[0].value = 0; + out[0].imm.Type = TGSI_TOKEN_TYPE_IMMEDIATE; + out[0].imm.NrTokens = 5; + out[0].imm.DataType = type; + out[0].imm.Padding = 0; + + out[1].imm_data.Uint = v[0]; + out[2].imm_data.Uint = v[1]; + out[3].imm_data.Uint = v[2]; + out[4].imm_data.Uint = v[3]; +} + +static void +emit_property(struct ureg_program *ureg, + unsigned name, + unsigned data) +{ + union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 2); + + out[0].value = 0; + out[0].prop.Type = TGSI_TOKEN_TYPE_PROPERTY; + out[0].prop.NrTokens = 2; + out[0].prop.PropertyName = name; + + out[1].prop_data.Data = data; +} + + +static void emit_decls( struct ureg_program *ureg ) +{ + unsigned i; + + if (ureg->property_gs_input_prim != ~0) { + assert(ureg->processor == TGSI_PROCESSOR_GEOMETRY); + + emit_property(ureg, + TGSI_PROPERTY_GS_INPUT_PRIM, + ureg->property_gs_input_prim); + } + + if (ureg->property_gs_output_prim != ~0) { + assert(ureg->processor == TGSI_PROCESSOR_GEOMETRY); + + emit_property(ureg, + TGSI_PROPERTY_GS_OUTPUT_PRIM, + ureg->property_gs_output_prim); + } + + if (ureg->property_gs_max_vertices != ~0) { + assert(ureg->processor == TGSI_PROCESSOR_GEOMETRY); + + emit_property(ureg, + TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES, + ureg->property_gs_max_vertices); + } + + if (ureg->property_fs_coord_origin) { + assert(ureg->processor == TGSI_PROCESSOR_FRAGMENT); + + emit_property(ureg, + TGSI_PROPERTY_FS_COORD_ORIGIN, + ureg->property_fs_coord_origin); + } + + if (ureg->property_fs_coord_pixel_center) { + assert(ureg->processor == TGSI_PROCESSOR_FRAGMENT); + + emit_property(ureg, + TGSI_PROPERTY_FS_COORD_PIXEL_CENTER, + ureg->property_fs_coord_pixel_center); + } + + if (ureg->property_fs_color0_writes_all_cbufs) { + assert(ureg->processor == TGSI_PROCESSOR_FRAGMENT); + + emit_property(ureg, + TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS, + ureg->property_fs_color0_writes_all_cbufs); + } + + if (ureg->property_fs_depth_layout) { + assert(ureg->processor == TGSI_PROCESSOR_FRAGMENT); + + emit_property(ureg, + TGSI_PROPERTY_FS_DEPTH_LAYOUT, + ureg->property_fs_depth_layout); + } + + if (ureg->processor == TGSI_PROCESSOR_VERTEX) { + for (i = 0; i < UREG_MAX_INPUT; i++) { + if (ureg->vs_inputs[i/32] & (1 << (i%32))) { + emit_decl_range( ureg, TGSI_FILE_INPUT, i, 1 ); + } + } + } else if (ureg->processor == TGSI_PROCESSOR_FRAGMENT) { + for (i = 0; i < ureg->nr_fs_inputs; i++) { + emit_decl_fs(ureg, + TGSI_FILE_INPUT, + i, + ureg->fs_input[i].semantic_name, + ureg->fs_input[i].semantic_index, + ureg->fs_input[i].interp, + ureg->fs_input[i].cylindrical_wrap, + ureg->fs_input[i].centroid); + } + } else { + for (i = 0; i < ureg->nr_gs_inputs; i++) { + emit_decl_semantic(ureg, + TGSI_FILE_INPUT, + ureg->gs_input[i].index, + ureg->gs_input[i].semantic_name, + ureg->gs_input[i].semantic_index, + TGSI_WRITEMASK_XYZW); + } + } + + for (i = 0; i < ureg->nr_system_values; i++) { + emit_decl_semantic(ureg, + TGSI_FILE_SYSTEM_VALUE, + ureg->system_value[i].index, + ureg->system_value[i].semantic_name, + ureg->system_value[i].semantic_index, + TGSI_WRITEMASK_XYZW); + } + + for (i = 0; i < ureg->nr_outputs; i++) { + emit_decl_semantic(ureg, + TGSI_FILE_OUTPUT, + i, + ureg->output[i].semantic_name, + ureg->output[i].semantic_index, + ureg->output[i].usage_mask); + } + + for (i = 0; i < ureg->nr_samplers; i++) { + emit_decl_range( ureg, + TGSI_FILE_SAMPLER, + ureg->sampler[i].Index, 1 ); + } + + for (i = 0; i < ureg->nr_sampler_views; i++) { + emit_decl_sampler_view(ureg, + ureg->sampler_view[i].index, + ureg->sampler_view[i].target, + ureg->sampler_view[i].return_type_x, + ureg->sampler_view[i].return_type_y, + ureg->sampler_view[i].return_type_z, + ureg->sampler_view[i].return_type_w); + } + + if (ureg->const_decls.nr_constant_ranges) { + for (i = 0; i < ureg->const_decls.nr_constant_ranges; i++) { + emit_decl_range(ureg, + TGSI_FILE_CONSTANT, + ureg->const_decls.constant_range[i].first, + ureg->const_decls.constant_range[i].last - ureg->const_decls.constant_range[i].first + 1); + } + } + + for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) { + struct const_decl *decl = &ureg->const_decls2D[i]; + + if (decl->nr_constant_ranges) { + uint j; + + for (j = 0; j < decl->nr_constant_ranges; j++) { + emit_decl_range2D(ureg, + TGSI_FILE_CONSTANT, + decl->constant_range[j].first, + decl->constant_range[j].last, + i); + } + } + } + + if (ureg->nr_temps) { + unsigned array = 0; + for (i = 0; i < ureg->nr_temps;) { + boolean local = util_bitmask_get(ureg->local_temps, i); + unsigned first = i; + i = util_bitmask_get_next_index(ureg->decl_temps, i + 1); + if (i == UTIL_BITMASK_INVALID_INDEX) + i = ureg->nr_temps; + + if (array < ureg->nr_array_temps && ureg->array_temps[array] == first) + emit_decl_temps( ureg, first, i - 1, local, ++array ); + else + emit_decl_temps( ureg, first, i - 1, local, 0 ); + } + } + + if (ureg->nr_addrs) { + emit_decl_range( ureg, + TGSI_FILE_ADDRESS, + 0, ureg->nr_addrs ); + } + + if (ureg->nr_preds) { + emit_decl_range(ureg, + TGSI_FILE_PREDICATE, + 0, + ureg->nr_preds); + } + + for (i = 0; i < ureg->nr_immediates; i++) { + emit_immediate( ureg, + ureg->immediate[i].value.u, + ureg->immediate[i].type ); + } +} + +/* Append the instruction tokens onto the declarations to build a + * contiguous stream suitable to send to the driver. + */ +static void copy_instructions( struct ureg_program *ureg ) +{ + unsigned nr_tokens = ureg->domain[DOMAIN_INSN].count; + union tgsi_any_token *out = get_tokens( ureg, + DOMAIN_DECL, + nr_tokens ); + + memcpy(out, + ureg->domain[DOMAIN_INSN].tokens, + nr_tokens * sizeof out[0] ); +} + + +static void +fixup_header_size(struct ureg_program *ureg) +{ + union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_DECL, 0 ); + + out->header.BodySize = ureg->domain[DOMAIN_DECL].count - 2; +} + + +static void +emit_header( struct ureg_program *ureg ) +{ + union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 2 ); + + out[0].header.HeaderSize = 2; + out[0].header.BodySize = 0; + + out[1].processor.Processor = ureg->processor; + out[1].processor.Padding = 0; +} + + +const struct tgsi_token *ureg_finalize( struct ureg_program *ureg ) +{ + const struct tgsi_token *tokens; + + emit_header( ureg ); + emit_decls( ureg ); + copy_instructions( ureg ); + fixup_header_size( ureg ); + + if (ureg->domain[0].tokens == error_tokens || + ureg->domain[1].tokens == error_tokens) { + debug_printf("%s: error in generated shader\n", __FUNCTION__); + assert(0); + return NULL; + } + + tokens = &ureg->domain[DOMAIN_DECL].tokens[0].token; + + if (0) { + debug_printf("%s: emitted shader %d tokens:\n", __FUNCTION__, + ureg->domain[DOMAIN_DECL].count); + tgsi_dump( tokens, 0 ); + } + +#if DEBUG + if (tokens && !tgsi_sanity_check(tokens)) { + debug_printf("tgsi_ureg.c, sanity check failed on generated tokens:\n"); + tgsi_dump(tokens, 0); + assert(0); + } +#endif + + + return tokens; +} + + +void *ureg_create_shader( struct ureg_program *ureg, + struct pipe_context *pipe, + const struct pipe_stream_output_info *so ) +{ + struct pipe_shader_state state; + + state.tokens = ureg_finalize(ureg); + if(!state.tokens) + return NULL; + + if (so) + state.stream_output = *so; + else + memset(&state.stream_output, 0, sizeof(state.stream_output)); + + if (ureg->processor == TGSI_PROCESSOR_VERTEX) + return pipe->create_vs_state( pipe, &state ); + else + return pipe->create_fs_state( pipe, &state ); +} + + +const struct tgsi_token *ureg_get_tokens( struct ureg_program *ureg, + unsigned *nr_tokens ) +{ + const struct tgsi_token *tokens; + + ureg_finalize(ureg); + + tokens = &ureg->domain[DOMAIN_DECL].tokens[0].token; + + if (nr_tokens) + *nr_tokens = ureg->domain[DOMAIN_DECL].size; + + ureg->domain[DOMAIN_DECL].tokens = 0; + ureg->domain[DOMAIN_DECL].size = 0; + ureg->domain[DOMAIN_DECL].order = 0; + ureg->domain[DOMAIN_DECL].count = 0; + + return tokens; +} + + +void ureg_free_tokens( const struct tgsi_token *tokens ) +{ + FREE((struct tgsi_token *)tokens); +} + + +struct ureg_program *ureg_create( unsigned processor ) +{ + struct ureg_program *ureg = CALLOC_STRUCT( ureg_program ); + if (ureg == NULL) + goto no_ureg; + + ureg->processor = processor; + ureg->property_gs_input_prim = ~0; + ureg->property_gs_output_prim = ~0; + ureg->property_gs_max_vertices = ~0; + + ureg->free_temps = util_bitmask_create(); + if (ureg->free_temps == NULL) + goto no_free_temps; + + ureg->local_temps = util_bitmask_create(); + if (ureg->local_temps == NULL) + goto no_local_temps; + + ureg->decl_temps = util_bitmask_create(); + if (ureg->decl_temps == NULL) + goto no_decl_temps; + + return ureg; + +no_decl_temps: + util_bitmask_destroy(ureg->local_temps); +no_local_temps: + util_bitmask_destroy(ureg->free_temps); +no_free_temps: + FREE(ureg); +no_ureg: + return NULL; +} + + +const unsigned +ureg_get_nr_outputs( const struct ureg_program *ureg ) +{ + if (!ureg) + return 0; + return ureg->nr_outputs; +} + + +void ureg_destroy( struct ureg_program *ureg ) +{ + unsigned i; + + for (i = 0; i < Elements(ureg->domain); i++) { + if (ureg->domain[i].tokens && + ureg->domain[i].tokens != error_tokens) + FREE(ureg->domain[i].tokens); + } + + util_bitmask_destroy(ureg->free_temps); + util_bitmask_destroy(ureg->local_temps); + util_bitmask_destroy(ureg->decl_temps); + + FREE(ureg); +} diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.h b/src/gallium/auxiliary/tgsi/tgsi_ureg.h new file mode 100644 index 0000000..a0a50b7 --- /dev/null +++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.h @@ -0,0 +1,1324 @@ +/************************************************************************** + * + * 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, INC 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_UREG_H +#define TGSI_UREG_H + +#include "pipe/p_compiler.h" +#include "pipe/p_shader_tokens.h" +#include "util/u_debug.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct ureg_program; +struct pipe_stream_output_info; + +/* Almost a tgsi_src_register, but we need to pull in the Absolute + * flag from the _ext token. Indirect flag always implies ADDR[0]. + */ +struct ureg_src +{ + unsigned File : 4; /* TGSI_FILE_ */ + unsigned SwizzleX : 2; /* TGSI_SWIZZLE_ */ + unsigned SwizzleY : 2; /* TGSI_SWIZZLE_ */ + unsigned SwizzleZ : 2; /* TGSI_SWIZZLE_ */ + unsigned SwizzleW : 2; /* TGSI_SWIZZLE_ */ + unsigned Indirect : 1; /* BOOL */ + unsigned DimIndirect : 1; /* BOOL */ + unsigned Dimension : 1; /* BOOL */ + unsigned Absolute : 1; /* BOOL */ + unsigned Negate : 1; /* BOOL */ + unsigned IndirectFile : 4; /* TGSI_FILE_ */ + unsigned IndirectSwizzle : 2; /* TGSI_SWIZZLE_ */ + unsigned DimIndFile : 4; /* TGSI_FILE_ */ + unsigned DimIndSwizzle : 2; /* TGSI_SWIZZLE_ */ + int Index : 16; /* SINT */ + int IndirectIndex : 16; /* SINT */ + int DimensionIndex : 16; /* SINT */ + int DimIndIndex : 16; /* SINT */ + unsigned ArrayID : 10; /* UINT */ +}; + +/* Very similar to a tgsi_dst_register, removing unsupported fields + * and adding a Saturate flag. It's easier to push saturate into the + * destination register than to try and create a _SAT variant of each + * instruction function. + */ +struct ureg_dst +{ + unsigned File : 4; /* TGSI_FILE_ */ + unsigned WriteMask : 4; /* TGSI_WRITEMASK_ */ + unsigned Indirect : 1; /* BOOL */ + unsigned Saturate : 1; /* BOOL */ + unsigned Predicate : 1; + unsigned PredNegate : 1; /* BOOL */ + unsigned PredSwizzleX : 2; /* TGSI_SWIZZLE_ */ + unsigned PredSwizzleY : 2; /* TGSI_SWIZZLE_ */ + unsigned PredSwizzleZ : 2; /* TGSI_SWIZZLE_ */ + unsigned PredSwizzleW : 2; /* TGSI_SWIZZLE_ */ + int Index : 16; /* SINT */ + int IndirectIndex : 16; /* SINT */ + unsigned IndirectFile : 4; /* TGSI_FILE_ */ + int IndirectSwizzle : 2; /* TGSI_SWIZZLE_ */ + unsigned ArrayID : 10; /* UINT */ +}; + +struct pipe_context; + +struct ureg_program * +ureg_create( unsigned processor ); + +const struct tgsi_token * +ureg_finalize( struct ureg_program * ); + +/* Create and return a shader: + */ +void * +ureg_create_shader( struct ureg_program *, + struct pipe_context *pipe, + const struct pipe_stream_output_info *so ); + + +/* Alternately, return the built token stream and hand ownership of + * that memory to the caller: + */ +const struct tgsi_token * +ureg_get_tokens( struct ureg_program *ureg, + unsigned *nr_tokens ); + +/* + * Returns the number of currently declared outputs. + */ +const unsigned +ureg_get_nr_outputs( const struct ureg_program *ureg ); + + +/* Free the tokens created by ureg_get_tokens() */ +void ureg_free_tokens( const struct tgsi_token *tokens ); + + +void +ureg_destroy( struct ureg_program * ); + + +/*********************************************************************** + * Convenience routine: + */ +static INLINE void * +ureg_create_shader_with_so_and_destroy( struct ureg_program *p, + struct pipe_context *pipe, + const struct pipe_stream_output_info *so ) +{ + void *result = ureg_create_shader( p, pipe, so ); + ureg_destroy( p ); + return result; +} + +static INLINE void * +ureg_create_shader_and_destroy( struct ureg_program *p, + struct pipe_context *pipe ) +{ + return ureg_create_shader_with_so_and_destroy(p, pipe, NULL); +} + + +/*********************************************************************** + * Build shader properties: + */ + +void +ureg_property_gs_input_prim(struct ureg_program *ureg, + unsigned input_prim); + +void +ureg_property_gs_output_prim(struct ureg_program *ureg, + unsigned output_prim); + +void +ureg_property_gs_max_vertices(struct ureg_program *ureg, + unsigned max_vertices); + +void +ureg_property_gs_invocations(struct ureg_program *ureg, + unsigned invocations); + +void +ureg_property_fs_coord_origin(struct ureg_program *ureg, + unsigned fs_coord_origin); + +void +ureg_property_fs_coord_pixel_center(struct ureg_program *ureg, + unsigned fs_coord_pixel_center); + +void +ureg_property_fs_color0_writes_all_cbufs(struct ureg_program *ureg, + unsigned fs_color0_writes_all_cbufs); + +void +ureg_property_fs_depth_layout(struct ureg_program *ureg, + unsigned fs_depth_layout); + + +/*********************************************************************** + * Build shader declarations: + */ + +struct ureg_src +ureg_DECL_fs_input_cyl_centroid(struct ureg_program *, + unsigned semantic_name, + unsigned semantic_index, + unsigned interp_mode, + unsigned cylindrical_wrap, + unsigned centroid); + +static INLINE struct ureg_src +ureg_DECL_fs_input_cyl(struct ureg_program *ureg, + unsigned semantic_name, + unsigned semantic_index, + unsigned interp_mode, + unsigned cylindrical_wrap) +{ + return ureg_DECL_fs_input_cyl_centroid(ureg, + semantic_name, + semantic_index, + interp_mode, + cylindrical_wrap, + 0); +} + +static INLINE struct ureg_src +ureg_DECL_fs_input(struct ureg_program *ureg, + unsigned semantic_name, + unsigned semantic_index, + unsigned interp_mode) +{ + return ureg_DECL_fs_input_cyl_centroid(ureg, + semantic_name, + semantic_index, + interp_mode, + 0, 0); +} + +struct ureg_src +ureg_DECL_vs_input( struct ureg_program *, + unsigned index ); + +struct ureg_src +ureg_DECL_gs_input(struct ureg_program *, + unsigned index, + unsigned semantic_name, + unsigned semantic_index); + +struct ureg_src +ureg_DECL_system_value(struct ureg_program *, + unsigned index, + unsigned semantic_name, + unsigned semantic_index); + +struct ureg_dst +ureg_DECL_output_masked( struct ureg_program *, + unsigned semantic_name, + unsigned semantic_index, + unsigned usage_mask ); + +struct ureg_dst +ureg_DECL_output( struct ureg_program *, + unsigned semantic_name, + unsigned semantic_index ); + +struct ureg_src +ureg_DECL_immediate( struct ureg_program *, + const float *v, + unsigned nr ); + +struct ureg_src +ureg_DECL_immediate_uint( struct ureg_program *, + const unsigned *v, + unsigned nr ); + +struct ureg_src +ureg_DECL_immediate_block_uint( struct ureg_program *, + const unsigned *v, + unsigned nr ); + +struct ureg_src +ureg_DECL_immediate_int( struct ureg_program *, + const int *v, + unsigned nr ); + +void +ureg_DECL_constant2D(struct ureg_program *ureg, + unsigned first, + unsigned last, + unsigned index2D); + +struct ureg_src +ureg_DECL_constant( struct ureg_program *, + unsigned index ); + +struct ureg_dst +ureg_DECL_temporary( struct ureg_program * ); + +/** + * Emit a temporary with the LOCAL declaration flag set. For use when + * the register value is not required to be preserved across + * subroutine boundaries. + */ +struct ureg_dst +ureg_DECL_local_temporary( struct ureg_program * ); + +/** + * Declare "size" continuous temporary registers. + */ +struct ureg_dst +ureg_DECL_array_temporary( struct ureg_program *, + unsigned size, + boolean local ); + +void +ureg_release_temporary( struct ureg_program *ureg, + struct ureg_dst tmp ); + +struct ureg_dst +ureg_DECL_address( struct ureg_program * ); + +struct ureg_dst +ureg_DECL_predicate(struct ureg_program *); + +/* Supply an index to the sampler declaration as this is the hook to + * the external pipe_sampler state. Users of this function probably + * don't want just any sampler, but a specific one which they've set + * up state for in the context. + */ +struct ureg_src +ureg_DECL_sampler( struct ureg_program *, + unsigned index ); + +struct ureg_src +ureg_DECL_sampler_view(struct ureg_program *, + unsigned index, + unsigned target, + unsigned return_type_x, + unsigned return_type_y, + unsigned return_type_z, + unsigned return_type_w ); + + +static INLINE struct ureg_src +ureg_imm4f( struct ureg_program *ureg, + float a, float b, + float c, float d) +{ + float v[4]; + v[0] = a; + v[1] = b; + v[2] = c; + v[3] = d; + return ureg_DECL_immediate( ureg, v, 4 ); +} + +static INLINE struct ureg_src +ureg_imm3f( struct ureg_program *ureg, + float a, float b, + float c) +{ + float v[3]; + v[0] = a; + v[1] = b; + v[2] = c; + return ureg_DECL_immediate( ureg, v, 3 ); +} + +static INLINE struct ureg_src +ureg_imm2f( struct ureg_program *ureg, + float a, float b) +{ + float v[2]; + v[0] = a; + v[1] = b; + return ureg_DECL_immediate( ureg, v, 2 ); +} + +static INLINE struct ureg_src +ureg_imm1f( struct ureg_program *ureg, + float a) +{ + float v[1]; + v[0] = a; + return ureg_DECL_immediate( ureg, v, 1 ); +} + +static INLINE struct ureg_src +ureg_imm4u( struct ureg_program *ureg, + unsigned a, unsigned b, + unsigned c, unsigned d) +{ + unsigned v[4]; + v[0] = a; + v[1] = b; + v[2] = c; + v[3] = d; + return ureg_DECL_immediate_uint( ureg, v, 4 ); +} + +static INLINE struct ureg_src +ureg_imm3u( struct ureg_program *ureg, + unsigned a, unsigned b, + unsigned c) +{ + unsigned v[3]; + v[0] = a; + v[1] = b; + v[2] = c; + return ureg_DECL_immediate_uint( ureg, v, 3 ); +} + +static INLINE struct ureg_src +ureg_imm2u( struct ureg_program *ureg, + unsigned a, unsigned b) +{ + unsigned v[2]; + v[0] = a; + v[1] = b; + return ureg_DECL_immediate_uint( ureg, v, 2 ); +} + +static INLINE struct ureg_src +ureg_imm1u( struct ureg_program *ureg, + unsigned a) +{ + return ureg_DECL_immediate_uint( ureg, &a, 1 ); +} + +static INLINE struct ureg_src +ureg_imm4i( struct ureg_program *ureg, + int a, int b, + int c, int d) +{ + int v[4]; + v[0] = a; + v[1] = b; + v[2] = c; + v[3] = d; + return ureg_DECL_immediate_int( ureg, v, 4 ); +} + +static INLINE struct ureg_src +ureg_imm3i( struct ureg_program *ureg, + int a, int b, + int c) +{ + int v[3]; + v[0] = a; + v[1] = b; + v[2] = c; + return ureg_DECL_immediate_int( ureg, v, 3 ); +} + +static INLINE struct ureg_src +ureg_imm2i( struct ureg_program *ureg, + int a, int b) +{ + int v[2]; + v[0] = a; + v[1] = b; + return ureg_DECL_immediate_int( ureg, v, 2 ); +} + +static INLINE struct ureg_src +ureg_imm1i( struct ureg_program *ureg, + int a) +{ + return ureg_DECL_immediate_int( ureg, &a, 1 ); +} + +/* Where the destination register has a valid file, but an empty + * writemask. + */ +static INLINE boolean +ureg_dst_is_empty( struct ureg_dst dst ) +{ + return dst.File != TGSI_FILE_NULL && + dst.WriteMask == 0; +} + +/*********************************************************************** + * Functions for patching up labels + */ + + +/* Will return a number which can be used in a label to point to the + * next instruction to be emitted. + */ +unsigned +ureg_get_instruction_number( struct ureg_program *ureg ); + + +/* Patch a given label (expressed as a token number) to point to a + * given instruction (expressed as an instruction number). + * + * Labels are obtained from instruction emitters, eg ureg_CAL(). + * Instruction numbers are obtained from ureg_get_instruction_number(), + * above. + */ +void +ureg_fixup_label(struct ureg_program *ureg, + unsigned label_token, + unsigned instruction_number ); + + +/* Generic instruction emitter. Use if you need to pass the opcode as + * a parameter, rather than using the emit_OP() variants below. + */ +void +ureg_insn(struct ureg_program *ureg, + unsigned opcode, + const struct ureg_dst *dst, + unsigned nr_dst, + const struct ureg_src *src, + unsigned nr_src ); + + +void +ureg_tex_insn(struct ureg_program *ureg, + unsigned opcode, + const struct ureg_dst *dst, + unsigned nr_dst, + unsigned target, + const struct tgsi_texture_offset *texoffsets, + unsigned nr_offset, + const struct ureg_src *src, + unsigned nr_src ); + + +void +ureg_label_insn(struct ureg_program *ureg, + unsigned opcode, + const struct ureg_src *src, + unsigned nr_src, + unsigned *label); + + +/*********************************************************************** + * Internal instruction helpers, don't call these directly: + */ + +struct ureg_emit_insn_result { + unsigned insn_token; /*< Used to fixup insn size. */ + unsigned extended_token; /*< Used to set the Extended bit, usually the same as insn_token. */ +}; + +struct ureg_emit_insn_result +ureg_emit_insn(struct ureg_program *ureg, + unsigned opcode, + boolean saturate, + boolean predicate, + boolean pred_negate, + unsigned pred_swizzle_x, + unsigned pred_swizzle_y, + unsigned pred_swizzle_z, + unsigned pred_swizzle_w, + unsigned num_dst, + unsigned num_src ); + +void +ureg_emit_label(struct ureg_program *ureg, + unsigned insn_token, + unsigned *label_token ); + +void +ureg_emit_texture(struct ureg_program *ureg, + unsigned insn_token, + unsigned target, unsigned num_offsets); + +void +ureg_emit_texture_offset(struct ureg_program *ureg, + const struct tgsi_texture_offset *offset); + +void +ureg_emit_dst( struct ureg_program *ureg, + struct ureg_dst dst ); + +void +ureg_emit_src( struct ureg_program *ureg, + struct ureg_src src ); + +void +ureg_fixup_insn_size(struct ureg_program *ureg, + unsigned insn ); + + +#define OP00( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + struct ureg_emit_insn_result insn; \ + insn = ureg_emit_insn(ureg, \ + opcode, \ + FALSE, \ + FALSE, \ + FALSE, \ + TGSI_SWIZZLE_X, \ + TGSI_SWIZZLE_Y, \ + TGSI_SWIZZLE_Z, \ + TGSI_SWIZZLE_W, \ + 0, \ + 0); \ + ureg_fixup_insn_size( ureg, insn.insn_token ); \ +} + +#define OP01( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg, \ + struct ureg_src src ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + struct ureg_emit_insn_result insn; \ + insn = ureg_emit_insn(ureg, \ + opcode, \ + FALSE, \ + FALSE, \ + FALSE, \ + TGSI_SWIZZLE_X, \ + TGSI_SWIZZLE_Y, \ + TGSI_SWIZZLE_Z, \ + TGSI_SWIZZLE_W, \ + 0, \ + 1); \ + ureg_emit_src( ureg, src ); \ + ureg_fixup_insn_size( ureg, insn.insn_token ); \ +} + +#define OP00_LBL( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg, \ + unsigned *label_token ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + struct ureg_emit_insn_result insn; \ + insn = ureg_emit_insn(ureg, \ + opcode, \ + FALSE, \ + FALSE, \ + FALSE, \ + TGSI_SWIZZLE_X, \ + TGSI_SWIZZLE_Y, \ + TGSI_SWIZZLE_Z, \ + TGSI_SWIZZLE_W, \ + 0, \ + 0); \ + ureg_emit_label( ureg, insn.extended_token, label_token ); \ + ureg_fixup_insn_size( ureg, insn.insn_token ); \ +} + +#define OP01_LBL( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg, \ + struct ureg_src src, \ + unsigned *label_token ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + struct ureg_emit_insn_result insn; \ + insn = ureg_emit_insn(ureg, \ + opcode, \ + FALSE, \ + FALSE, \ + FALSE, \ + TGSI_SWIZZLE_X, \ + TGSI_SWIZZLE_Y, \ + TGSI_SWIZZLE_Z, \ + TGSI_SWIZZLE_W, \ + 0, \ + 1); \ + ureg_emit_label( ureg, insn.extended_token, label_token ); \ + ureg_emit_src( ureg, src ); \ + ureg_fixup_insn_size( ureg, insn.insn_token ); \ +} + +#define OP10( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg, \ + struct ureg_dst dst ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + struct ureg_emit_insn_result insn; \ + if (ureg_dst_is_empty(dst)) \ + return; \ + insn = ureg_emit_insn(ureg, \ + opcode, \ + dst.Saturate, \ + dst.Predicate, \ + dst.PredNegate, \ + dst.PredSwizzleX, \ + dst.PredSwizzleY, \ + dst.PredSwizzleZ, \ + dst.PredSwizzleW, \ + 1, \ + 0); \ + ureg_emit_dst( ureg, dst ); \ + ureg_fixup_insn_size( ureg, insn.insn_token ); \ +} + + +#define OP11( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg, \ + struct ureg_dst dst, \ + struct ureg_src src ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + struct ureg_emit_insn_result insn; \ + if (ureg_dst_is_empty(dst)) \ + return; \ + insn = ureg_emit_insn(ureg, \ + opcode, \ + dst.Saturate, \ + dst.Predicate, \ + dst.PredNegate, \ + dst.PredSwizzleX, \ + dst.PredSwizzleY, \ + dst.PredSwizzleZ, \ + dst.PredSwizzleW, \ + 1, \ + 1); \ + ureg_emit_dst( ureg, dst ); \ + ureg_emit_src( ureg, src ); \ + ureg_fixup_insn_size( ureg, insn.insn_token ); \ +} + +#define OP12( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg, \ + struct ureg_dst dst, \ + struct ureg_src src0, \ + struct ureg_src src1 ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + struct ureg_emit_insn_result insn; \ + if (ureg_dst_is_empty(dst)) \ + return; \ + insn = ureg_emit_insn(ureg, \ + opcode, \ + dst.Saturate, \ + dst.Predicate, \ + dst.PredNegate, \ + dst.PredSwizzleX, \ + dst.PredSwizzleY, \ + dst.PredSwizzleZ, \ + dst.PredSwizzleW, \ + 1, \ + 2); \ + ureg_emit_dst( ureg, dst ); \ + ureg_emit_src( ureg, src0 ); \ + ureg_emit_src( ureg, src1 ); \ + ureg_fixup_insn_size( ureg, insn.insn_token ); \ +} + +#define OP12_TEX( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg, \ + struct ureg_dst dst, \ + unsigned target, \ + struct ureg_src src0, \ + struct ureg_src src1 ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + struct ureg_emit_insn_result insn; \ + if (ureg_dst_is_empty(dst)) \ + return; \ + insn = ureg_emit_insn(ureg, \ + opcode, \ + dst.Saturate, \ + dst.Predicate, \ + dst.PredNegate, \ + dst.PredSwizzleX, \ + dst.PredSwizzleY, \ + dst.PredSwizzleZ, \ + dst.PredSwizzleW, \ + 1, \ + 2); \ + ureg_emit_texture( ureg, insn.extended_token, target, 0 ); \ + ureg_emit_dst( ureg, dst ); \ + ureg_emit_src( ureg, src0 ); \ + ureg_emit_src( ureg, src1 ); \ + ureg_fixup_insn_size( ureg, insn.insn_token ); \ +} + +#define OP12_SAMPLE( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg, \ + struct ureg_dst dst, \ + struct ureg_src src0, \ + struct ureg_src src1 ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + unsigned target = TGSI_TEXTURE_UNKNOWN; \ + struct ureg_emit_insn_result insn; \ + if (ureg_dst_is_empty(dst)) \ + return; \ + insn = ureg_emit_insn(ureg, \ + opcode, \ + dst.Saturate, \ + dst.Predicate, \ + dst.PredNegate, \ + dst.PredSwizzleX, \ + dst.PredSwizzleY, \ + dst.PredSwizzleZ, \ + dst.PredSwizzleW, \ + 1, \ + 2); \ + ureg_emit_texture( ureg, insn.extended_token, target, 0 ); \ + ureg_emit_dst( ureg, dst ); \ + ureg_emit_src( ureg, src0 ); \ + ureg_emit_src( ureg, src1 ); \ + ureg_fixup_insn_size( ureg, insn.insn_token ); \ +} + +#define OP13( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg, \ + struct ureg_dst dst, \ + struct ureg_src src0, \ + struct ureg_src src1, \ + struct ureg_src src2 ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + struct ureg_emit_insn_result insn; \ + if (ureg_dst_is_empty(dst)) \ + return; \ + insn = ureg_emit_insn(ureg, \ + opcode, \ + dst.Saturate, \ + dst.Predicate, \ + dst.PredNegate, \ + dst.PredSwizzleX, \ + dst.PredSwizzleY, \ + dst.PredSwizzleZ, \ + dst.PredSwizzleW, \ + 1, \ + 3); \ + ureg_emit_dst( ureg, dst ); \ + ureg_emit_src( ureg, src0 ); \ + ureg_emit_src( ureg, src1 ); \ + ureg_emit_src( ureg, src2 ); \ + ureg_fixup_insn_size( ureg, insn.insn_token ); \ +} + +#define OP13_SAMPLE( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg, \ + struct ureg_dst dst, \ + struct ureg_src src0, \ + struct ureg_src src1, \ + struct ureg_src src2 ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + unsigned target = TGSI_TEXTURE_UNKNOWN; \ + struct ureg_emit_insn_result insn; \ + if (ureg_dst_is_empty(dst)) \ + return; \ + insn = ureg_emit_insn(ureg, \ + opcode, \ + dst.Saturate, \ + dst.Predicate, \ + dst.PredNegate, \ + dst.PredSwizzleX, \ + dst.PredSwizzleY, \ + dst.PredSwizzleZ, \ + dst.PredSwizzleW, \ + 1, \ + 3); \ + ureg_emit_texture( ureg, insn.extended_token, target, 0 ); \ + ureg_emit_dst( ureg, dst ); \ + ureg_emit_src( ureg, src0 ); \ + ureg_emit_src( ureg, src1 ); \ + ureg_emit_src( ureg, src2 ); \ + ureg_fixup_insn_size( ureg, insn.insn_token ); \ +} + +#define OP14_TEX( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg, \ + struct ureg_dst dst, \ + unsigned target, \ + struct ureg_src src0, \ + struct ureg_src src1, \ + struct ureg_src src2, \ + struct ureg_src src3 ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + struct ureg_emit_insn_result insn; \ + if (ureg_dst_is_empty(dst)) \ + return; \ + insn = ureg_emit_insn(ureg, \ + opcode, \ + dst.Saturate, \ + dst.Predicate, \ + dst.PredNegate, \ + dst.PredSwizzleX, \ + dst.PredSwizzleY, \ + dst.PredSwizzleZ, \ + dst.PredSwizzleW, \ + 1, \ + 4); \ + ureg_emit_texture( ureg, insn.extended_token, target, 0 ); \ + ureg_emit_dst( ureg, dst ); \ + ureg_emit_src( ureg, src0 ); \ + ureg_emit_src( ureg, src1 ); \ + ureg_emit_src( ureg, src2 ); \ + ureg_emit_src( ureg, src3 ); \ + ureg_fixup_insn_size( ureg, insn.insn_token ); \ +} + +#define OP14_SAMPLE( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg, \ + struct ureg_dst dst, \ + struct ureg_src src0, \ + struct ureg_src src1, \ + struct ureg_src src2, \ + struct ureg_src src3 ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + unsigned target = TGSI_TEXTURE_UNKNOWN; \ + struct ureg_emit_insn_result insn; \ + if (ureg_dst_is_empty(dst)) \ + return; \ + insn = ureg_emit_insn(ureg, \ + opcode, \ + dst.Saturate, \ + dst.Predicate, \ + dst.PredNegate, \ + dst.PredSwizzleX, \ + dst.PredSwizzleY, \ + dst.PredSwizzleZ, \ + dst.PredSwizzleW, \ + 1, \ + 4); \ + ureg_emit_texture( ureg, insn.extended_token, target, 0 ); \ + ureg_emit_dst( ureg, dst ); \ + ureg_emit_src( ureg, src0 ); \ + ureg_emit_src( ureg, src1 ); \ + ureg_emit_src( ureg, src2 ); \ + ureg_emit_src( ureg, src3 ); \ + ureg_fixup_insn_size( ureg, insn.insn_token ); \ +} + + +#define OP14( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg, \ + struct ureg_dst dst, \ + struct ureg_src src0, \ + struct ureg_src src1, \ + struct ureg_src src2, \ + struct ureg_src src3 ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + struct ureg_emit_insn_result insn; \ + if (ureg_dst_is_empty(dst)) \ + return; \ + insn = ureg_emit_insn(ureg, \ + opcode, \ + dst.Saturate, \ + dst.Predicate, \ + dst.PredNegate, \ + dst.PredSwizzleX, \ + dst.PredSwizzleY, \ + dst.PredSwizzleZ, \ + dst.PredSwizzleW, \ + 1, \ + 4); \ + ureg_emit_dst( ureg, dst ); \ + ureg_emit_src( ureg, src0 ); \ + ureg_emit_src( ureg, src1 ); \ + ureg_emit_src( ureg, src2 ); \ + ureg_emit_src( ureg, src3 ); \ + ureg_fixup_insn_size( ureg, insn.insn_token ); \ +} + + +#define OP15( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg, \ + struct ureg_dst dst, \ + struct ureg_src src0, \ + struct ureg_src src1, \ + struct ureg_src src2, \ + struct ureg_src src3, \ + struct ureg_src src4 ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + struct ureg_emit_insn_result insn; \ + if (ureg_dst_is_empty(dst)) \ + return; \ + insn = ureg_emit_insn(ureg, \ + opcode, \ + dst.Saturate, \ + dst.Predicate, \ + dst.PredNegate, \ + dst.PredSwizzleX, \ + dst.PredSwizzleY, \ + dst.PredSwizzleZ, \ + dst.PredSwizzleW, \ + 1, \ + 5); \ + ureg_emit_dst( ureg, dst ); \ + ureg_emit_src( ureg, src0 ); \ + ureg_emit_src( ureg, src1 ); \ + ureg_emit_src( ureg, src2 ); \ + ureg_emit_src( ureg, src3 ); \ + ureg_emit_src( ureg, src4 ); \ + ureg_fixup_insn_size( ureg, insn.insn_token ); \ +} + +#define OP15_SAMPLE( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg, \ + struct ureg_dst dst, \ + struct ureg_src src0, \ + struct ureg_src src1, \ + struct ureg_src src2, \ + struct ureg_src src3, \ + struct ureg_src src4 ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + unsigned target = TGSI_TEXTURE_UNKNOWN; \ + struct ureg_emit_insn_result insn; \ + if (ureg_dst_is_empty(dst)) \ + return; \ + insn = ureg_emit_insn(ureg, \ + opcode, \ + dst.Saturate, \ + dst.Predicate, \ + dst.PredNegate, \ + dst.PredSwizzleX, \ + dst.PredSwizzleY, \ + dst.PredSwizzleZ, \ + dst.PredSwizzleW, \ + 1, \ + 5); \ + ureg_emit_texture( ureg, insn.extended_token, target, 0 ); \ + ureg_emit_dst( ureg, dst ); \ + ureg_emit_src( ureg, src0 ); \ + ureg_emit_src( ureg, src1 ); \ + ureg_emit_src( ureg, src2 ); \ + ureg_emit_src( ureg, src3 ); \ + ureg_emit_src( ureg, src4 ); \ + ureg_fixup_insn_size( ureg, insn.insn_token ); \ +} + +/* Use a template include to generate a correctly-typed ureg_OP() + * function for each TGSI opcode: + */ +#include "tgsi_opcode_tmp.h" + + +/*********************************************************************** + * Inline helpers for manipulating register structs: + */ +static INLINE struct ureg_src +ureg_negate( struct ureg_src reg ) +{ + assert(reg.File != TGSI_FILE_NULL); + reg.Negate ^= 1; + return reg; +} + +static INLINE struct ureg_src +ureg_abs( struct ureg_src reg ) +{ + assert(reg.File != TGSI_FILE_NULL); + reg.Absolute = 1; + reg.Negate = 0; + return reg; +} + +static INLINE struct ureg_src +ureg_swizzle( struct ureg_src reg, + int x, int y, int z, int w ) +{ + unsigned swz = ( (reg.SwizzleX << 0) | + (reg.SwizzleY << 2) | + (reg.SwizzleZ << 4) | + (reg.SwizzleW << 6)); + + assert(reg.File != TGSI_FILE_NULL); + assert(x < 4); + assert(y < 4); + assert(z < 4); + assert(w < 4); + + reg.SwizzleX = (swz >> (x*2)) & 0x3; + reg.SwizzleY = (swz >> (y*2)) & 0x3; + reg.SwizzleZ = (swz >> (z*2)) & 0x3; + reg.SwizzleW = (swz >> (w*2)) & 0x3; + return reg; +} + +static INLINE struct ureg_src +ureg_scalar( struct ureg_src reg, int x ) +{ + return ureg_swizzle(reg, x, x, x, x); +} + +static INLINE struct ureg_dst +ureg_writemask( struct ureg_dst reg, + unsigned writemask ) +{ + assert(reg.File != TGSI_FILE_NULL); + reg.WriteMask &= writemask; + return reg; +} + +static INLINE struct ureg_dst +ureg_saturate( struct ureg_dst reg ) +{ + assert(reg.File != TGSI_FILE_NULL); + reg.Saturate = 1; + return reg; +} + +static INLINE struct ureg_dst +ureg_predicate(struct ureg_dst reg, + boolean negate, + unsigned swizzle_x, + unsigned swizzle_y, + unsigned swizzle_z, + unsigned swizzle_w) +{ + assert(reg.File != TGSI_FILE_NULL); + reg.Predicate = 1; + reg.PredNegate = negate; + reg.PredSwizzleX = swizzle_x; + reg.PredSwizzleY = swizzle_y; + reg.PredSwizzleZ = swizzle_z; + reg.PredSwizzleW = swizzle_w; + return reg; +} + +static INLINE struct ureg_dst +ureg_dst_indirect( struct ureg_dst reg, struct ureg_src addr ) +{ + assert(reg.File != TGSI_FILE_NULL); + assert(addr.File == TGSI_FILE_ADDRESS || addr.File == TGSI_FILE_TEMPORARY); + reg.Indirect = 1; + reg.IndirectFile = addr.File; + reg.IndirectIndex = addr.Index; + reg.IndirectSwizzle = addr.SwizzleX; + return reg; +} + +static INLINE struct ureg_src +ureg_src_indirect( struct ureg_src reg, struct ureg_src addr ) +{ + assert(reg.File != TGSI_FILE_NULL); + assert(addr.File == TGSI_FILE_ADDRESS || addr.File == TGSI_FILE_TEMPORARY); + reg.Indirect = 1; + reg.IndirectFile = addr.File; + reg.IndirectIndex = addr.Index; + reg.IndirectSwizzle = addr.SwizzleX; + return reg; +} + +static INLINE struct ureg_src +ureg_src_dimension( struct ureg_src reg, int index ) +{ + assert(reg.File != TGSI_FILE_NULL); + reg.Dimension = 1; + reg.DimIndirect = 0; + reg.DimensionIndex = index; + return reg; +} + + +static INLINE struct ureg_src +ureg_src_dimension_indirect( struct ureg_src reg, struct ureg_src addr, + int index ) +{ + assert(reg.File != TGSI_FILE_NULL); + reg.Dimension = 1; + reg.DimIndirect = 1; + reg.DimensionIndex = index; + reg.DimIndFile = addr.File; + reg.DimIndIndex = addr.Index; + reg.DimIndSwizzle = addr.SwizzleX; + return reg; +} + +static INLINE struct ureg_dst +ureg_dst_array_offset( struct ureg_dst reg, int offset ) +{ + assert(reg.File == TGSI_FILE_TEMPORARY); + reg.Index += offset; + return reg; +} + +static INLINE struct ureg_dst +ureg_dst( struct ureg_src src ) +{ + struct ureg_dst dst; + + assert(!src.Indirect || + (src.IndirectFile == TGSI_FILE_ADDRESS || + src.IndirectFile == TGSI_FILE_TEMPORARY)); + + dst.File = src.File; + dst.WriteMask = TGSI_WRITEMASK_XYZW; + dst.IndirectFile = src.IndirectFile; + dst.Indirect = src.Indirect; + dst.IndirectIndex = src.IndirectIndex; + dst.IndirectSwizzle = src.IndirectSwizzle; + dst.Saturate = 0; + dst.Predicate = 0; + dst.PredNegate = 0; + dst.PredSwizzleX = TGSI_SWIZZLE_X; + dst.PredSwizzleY = TGSI_SWIZZLE_Y; + dst.PredSwizzleZ = TGSI_SWIZZLE_Z; + dst.PredSwizzleW = TGSI_SWIZZLE_W; + dst.Index = src.Index; + dst.ArrayID = src.ArrayID; + + return dst; +} + +static INLINE struct ureg_src +ureg_src_register(unsigned file, + unsigned index) +{ + struct ureg_src src; + + src.File = file; + src.SwizzleX = TGSI_SWIZZLE_X; + src.SwizzleY = TGSI_SWIZZLE_Y; + src.SwizzleZ = TGSI_SWIZZLE_Z; + src.SwizzleW = TGSI_SWIZZLE_W; + src.Indirect = 0; + src.IndirectFile = TGSI_FILE_NULL; + src.IndirectIndex = 0; + src.IndirectSwizzle = 0; + src.Absolute = 0; + src.Index = index; + src.Negate = 0; + src.Dimension = 0; + src.DimensionIndex = 0; + src.DimIndirect = 0; + src.DimIndFile = TGSI_FILE_NULL; + src.DimIndIndex = 0; + src.DimIndSwizzle = 0; + src.ArrayID = 0; + + return src; +} + +static INLINE struct ureg_src +ureg_src( struct ureg_dst dst ) +{ + struct ureg_src src; + + src.File = dst.File; + src.SwizzleX = TGSI_SWIZZLE_X; + src.SwizzleY = TGSI_SWIZZLE_Y; + src.SwizzleZ = TGSI_SWIZZLE_Z; + src.SwizzleW = TGSI_SWIZZLE_W; + src.Indirect = dst.Indirect; + src.IndirectFile = dst.IndirectFile; + src.IndirectIndex = dst.IndirectIndex; + src.IndirectSwizzle = dst.IndirectSwizzle; + src.Absolute = 0; + src.Index = dst.Index; + src.Negate = 0; + src.Dimension = 0; + src.DimensionIndex = 0; + src.DimIndirect = 0; + src.DimIndFile = TGSI_FILE_NULL; + src.DimIndIndex = 0; + src.DimIndSwizzle = 0; + src.ArrayID = dst.ArrayID; + + return src; +} + + + +static INLINE struct ureg_dst +ureg_dst_undef( void ) +{ + struct ureg_dst dst; + + dst.File = TGSI_FILE_NULL; + dst.WriteMask = 0; + dst.Indirect = 0; + dst.IndirectFile = TGSI_FILE_NULL; + dst.IndirectIndex = 0; + dst.IndirectSwizzle = 0; + dst.Saturate = 0; + dst.Predicate = 0; + dst.PredNegate = 0; + dst.PredSwizzleX = TGSI_SWIZZLE_X; + dst.PredSwizzleY = TGSI_SWIZZLE_Y; + dst.PredSwizzleZ = TGSI_SWIZZLE_Z; + dst.PredSwizzleW = TGSI_SWIZZLE_W; + dst.Index = 0; + dst.ArrayID = 0; + + return dst; +} + +static INLINE struct ureg_src +ureg_src_undef( void ) +{ + struct ureg_src src; + + src.File = TGSI_FILE_NULL; + src.SwizzleX = 0; + src.SwizzleY = 0; + src.SwizzleZ = 0; + src.SwizzleW = 0; + src.Indirect = 0; + src.IndirectFile = TGSI_FILE_NULL; + src.IndirectIndex = 0; + src.IndirectSwizzle = 0; + src.Absolute = 0; + src.Index = 0; + src.Negate = 0; + src.Dimension = 0; + src.DimensionIndex = 0; + src.DimIndirect = 0; + src.DimIndFile = TGSI_FILE_NULL; + src.DimIndIndex = 0; + src.DimIndSwizzle = 0; + src.ArrayID = 0; + + return src; +} + +static INLINE boolean +ureg_src_is_undef( struct ureg_src src ) +{ + return src.File == TGSI_FILE_NULL; +} + +static INLINE boolean +ureg_dst_is_undef( struct ureg_dst dst ) +{ + return dst.File == TGSI_FILE_NULL; +} + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/gallium/auxiliary/tgsi/tgsi_util.c b/src/gallium/auxiliary/tgsi/tgsi_util.c new file mode 100644 index 0000000..e48159c --- /dev/null +++ b/src/gallium/auxiliary/tgsi/tgsi_util.c @@ -0,0 +1,463 @@ +/************************************************************************** + * + * Copyright 2007 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "util/u_debug.h" +#include "pipe/p_shader_tokens.h" +#include "tgsi_parse.h" +#include "tgsi_util.h" + +union pointer_hack +{ + void *pointer; + uint64_t uint64; +}; + +void * +tgsi_align_128bit( + void *unaligned ) +{ + union pointer_hack ph; + + ph.uint64 = 0; + ph.pointer = unaligned; + ph.uint64 = (ph.uint64 + 15) & ~15; + return ph.pointer; +} + +unsigned +tgsi_util_get_src_register_swizzle( + const struct tgsi_src_register *reg, + unsigned component ) +{ + switch( component ) { + case 0: + return reg->SwizzleX; + case 1: + return reg->SwizzleY; + case 2: + return reg->SwizzleZ; + case 3: + return reg->SwizzleW; + default: + assert( 0 ); + } + return 0; +} + + +unsigned +tgsi_util_get_full_src_register_swizzle( + const struct tgsi_full_src_register *reg, + unsigned component ) +{ + return tgsi_util_get_src_register_swizzle( + ®->Register, + component ); +} + +void +tgsi_util_set_src_register_swizzle( + struct tgsi_src_register *reg, + unsigned swizzle, + unsigned component ) +{ + switch( component ) { + case 0: + reg->SwizzleX = swizzle; + break; + case 1: + reg->SwizzleY = swizzle; + break; + case 2: + reg->SwizzleZ = swizzle; + break; + case 3: + reg->SwizzleW = swizzle; + break; + default: + assert( 0 ); + } +} + +unsigned +tgsi_util_get_full_src_register_sign_mode( + const struct tgsi_full_src_register *reg, + unsigned component ) +{ + unsigned sign_mode; + + if( reg->Register.Absolute ) { + /* Consider only the post-abs negation. */ + + if( reg->Register.Negate ) { + sign_mode = TGSI_UTIL_SIGN_SET; + } + else { + sign_mode = TGSI_UTIL_SIGN_CLEAR; + } + } + else { + if( reg->Register.Negate ) { + sign_mode = TGSI_UTIL_SIGN_TOGGLE; + } + else { + sign_mode = TGSI_UTIL_SIGN_KEEP; + } + } + + return sign_mode; +} + +void +tgsi_util_set_full_src_register_sign_mode( + struct tgsi_full_src_register *reg, + unsigned sign_mode ) +{ + switch (sign_mode) + { + case TGSI_UTIL_SIGN_CLEAR: + reg->Register.Negate = 0; + reg->Register.Absolute = 1; + break; + + case TGSI_UTIL_SIGN_SET: + reg->Register.Absolute = 1; + reg->Register.Negate = 1; + break; + + case TGSI_UTIL_SIGN_TOGGLE: + reg->Register.Negate = 1; + reg->Register.Absolute = 0; + break; + + case TGSI_UTIL_SIGN_KEEP: + reg->Register.Negate = 0; + reg->Register.Absolute = 0; + break; + + default: + assert( 0 ); + } +} + +/** + * Determine which channels of the specificed src register are effectively + * used by this instruction. + */ +unsigned +tgsi_util_get_inst_usage_mask(const struct tgsi_full_instruction *inst, + unsigned src_idx) +{ + const struct tgsi_full_src_register *src = &inst->Src[src_idx]; + unsigned write_mask = inst->Dst[0].Register.WriteMask; + unsigned read_mask; + unsigned usage_mask; + unsigned chan; + + switch (inst->Instruction.Opcode) { + case TGSI_OPCODE_MOV: + case TGSI_OPCODE_ARL: + case TGSI_OPCODE_ARR: + case TGSI_OPCODE_RCP: + case TGSI_OPCODE_MUL: + case TGSI_OPCODE_DIV: + case TGSI_OPCODE_ADD: + case TGSI_OPCODE_MIN: + case TGSI_OPCODE_MAX: + case TGSI_OPCODE_SLT: + case TGSI_OPCODE_SGE: + case TGSI_OPCODE_MAD: + case TGSI_OPCODE_SUB: + case TGSI_OPCODE_LRP: + case TGSI_OPCODE_CND: + case TGSI_OPCODE_FRC: + case TGSI_OPCODE_CEIL: + case TGSI_OPCODE_CLAMP: + case TGSI_OPCODE_FLR: + case TGSI_OPCODE_ROUND: + case TGSI_OPCODE_POW: + case TGSI_OPCODE_ABS: + case TGSI_OPCODE_COS: + case TGSI_OPCODE_SIN: + case TGSI_OPCODE_DDX: + case TGSI_OPCODE_DDY: + case TGSI_OPCODE_SEQ: + case TGSI_OPCODE_SGT: + case TGSI_OPCODE_SLE: + case TGSI_OPCODE_SNE: + case TGSI_OPCODE_SSG: + case TGSI_OPCODE_CMP: + case TGSI_OPCODE_TRUNC: + case TGSI_OPCODE_NOT: + case TGSI_OPCODE_AND: + case TGSI_OPCODE_OR: + case TGSI_OPCODE_XOR: + case TGSI_OPCODE_SAD: + case TGSI_OPCODE_FSEQ: + case TGSI_OPCODE_FSGE: + case TGSI_OPCODE_FSLT: + case TGSI_OPCODE_FSNE: + case TGSI_OPCODE_F2I: + case TGSI_OPCODE_IDIV: + case TGSI_OPCODE_IMAX: + case TGSI_OPCODE_IMIN: + case TGSI_OPCODE_INEG: + case TGSI_OPCODE_ISGE: + case TGSI_OPCODE_ISHR: + case TGSI_OPCODE_ISLT: + case TGSI_OPCODE_F2U: + case TGSI_OPCODE_U2F: + case TGSI_OPCODE_UADD: + case TGSI_OPCODE_UDIV: + case TGSI_OPCODE_UMAD: + case TGSI_OPCODE_UMAX: + case TGSI_OPCODE_UMIN: + case TGSI_OPCODE_UMOD: + case TGSI_OPCODE_UMUL: + case TGSI_OPCODE_USEQ: + case TGSI_OPCODE_USGE: + case TGSI_OPCODE_USHR: + case TGSI_OPCODE_USLT: + case TGSI_OPCODE_USNE: + case TGSI_OPCODE_IMUL_HI: + case TGSI_OPCODE_UMUL_HI: + /* Channel-wise operations */ + read_mask = write_mask; + break; + + case TGSI_OPCODE_EX2: + case TGSI_OPCODE_LG2: + case TGSI_OPCODE_RCC: + read_mask = TGSI_WRITEMASK_X; + break; + + case TGSI_OPCODE_SCS: + read_mask = write_mask & TGSI_WRITEMASK_XY ? TGSI_WRITEMASK_X : 0; + break; + + case TGSI_OPCODE_EXP: + case TGSI_OPCODE_LOG: + read_mask = write_mask & TGSI_WRITEMASK_XYZ ? TGSI_WRITEMASK_X : 0; + break; + + case TGSI_OPCODE_DP2A: + read_mask = src_idx == 2 ? TGSI_WRITEMASK_X : TGSI_WRITEMASK_XY; + break; + + case TGSI_OPCODE_DP2: + read_mask = TGSI_WRITEMASK_XY; + break; + + case TGSI_OPCODE_DP3: + read_mask = TGSI_WRITEMASK_XYZ; + break; + + case TGSI_OPCODE_DP4: + read_mask = TGSI_WRITEMASK_XYZW; + break; + + case TGSI_OPCODE_DPH: + read_mask = src_idx == 0 ? TGSI_WRITEMASK_XYZ : TGSI_WRITEMASK_XYZW; + break; + + case TGSI_OPCODE_TEX: + case TGSI_OPCODE_TXD: + case TGSI_OPCODE_TXB: + case TGSI_OPCODE_TXL: + case TGSI_OPCODE_TXP: + if (src_idx == 0) { + /* Note that the SHADOW variants use the Z component too */ + switch (inst->Texture.Texture) { + case TGSI_TEXTURE_1D: + read_mask = TGSI_WRITEMASK_X; + break; + case TGSI_TEXTURE_SHADOW1D: + read_mask = TGSI_WRITEMASK_XZ; + break; + case TGSI_TEXTURE_1D_ARRAY: + case TGSI_TEXTURE_2D: + case TGSI_TEXTURE_RECT: + read_mask = TGSI_WRITEMASK_XY; + break; + case TGSI_TEXTURE_SHADOW1D_ARRAY: + case TGSI_TEXTURE_SHADOW2D: + case TGSI_TEXTURE_SHADOWRECT: + case TGSI_TEXTURE_2D_ARRAY: + case TGSI_TEXTURE_3D: + case TGSI_TEXTURE_CUBE: + case TGSI_TEXTURE_2D_MSAA: + read_mask = TGSI_WRITEMASK_XYZ; + break; + case TGSI_TEXTURE_SHADOW2D_ARRAY: + case TGSI_TEXTURE_CUBE_ARRAY: + case TGSI_TEXTURE_SHADOWCUBE: + case TGSI_TEXTURE_2D_ARRAY_MSAA: + case TGSI_TEXTURE_SHADOWCUBE_ARRAY: + read_mask = TGSI_WRITEMASK_XYZW; + break; + default: + assert(0); + read_mask = 0; + } + + if (inst->Instruction.Opcode != TGSI_OPCODE_TEX) { + read_mask |= TGSI_WRITEMASK_W; + } + } else { + /* A safe approximation */ + read_mask = TGSI_WRITEMASK_XYZW; + } + break; + + default: + /* Assume all channels are read */ + read_mask = TGSI_WRITEMASK_XYZW; + break; + } + + usage_mask = 0; + for (chan = 0; chan < 4; ++chan) { + if (read_mask & (1 << chan)) { + usage_mask |= 1 << tgsi_util_get_full_src_register_swizzle(src, chan); + } + } + + return usage_mask; +} + +/** + * Convert a tgsi_ind_register into a tgsi_src_register + */ +struct tgsi_src_register +tgsi_util_get_src_from_ind(const struct tgsi_ind_register *reg) +{ + struct tgsi_src_register src = { 0 }; + + src.File = reg->File; + src.Index = reg->Index; + src.SwizzleX = reg->Swizzle; + src.SwizzleY = reg->Swizzle; + src.SwizzleZ = reg->Swizzle; + src.SwizzleW = reg->Swizzle; + + return src; +} + +/** + * Return the dimension of the texture coordinates (layer included for array + * textures), as well as the location of the shadow reference value or the + * sample index. + */ +int +tgsi_util_get_texture_coord_dim(int tgsi_tex, int *shadow_or_sample) +{ + int dim; + + /* + * Depending on the texture target, (src0.xyzw, src1.x) is interpreted + * differently: + * + * (s, X, X, X, X), for BUFFER + * (s, X, X, X, X), for 1D + * (s, t, X, X, X), for 2D, RECT + * (s, t, r, X, X), for 3D, CUBE + * + * (s, layer, X, X, X), for 1D_ARRAY + * (s, t, layer, X, X), for 2D_ARRAY + * (s, t, r, layer, X), for CUBE_ARRAY + * + * (s, X, shadow, X, X), for SHADOW1D + * (s, t, shadow, X, X), for SHADOW2D, SHADOWRECT + * (s, t, r, shadow, X), for SHADOWCUBE + * + * (s, layer, shadow, X, X), for SHADOW1D_ARRAY + * (s, t, layer, shadow, X), for SHADOW2D_ARRAY + * (s, t, r, layer, shadow), for SHADOWCUBE_ARRAY + * + * (s, t, sample, X, X), for 2D_MSAA + * (s, t, layer, sample, X), for 2D_ARRAY_MSAA + */ + switch (tgsi_tex) { + case TGSI_TEXTURE_BUFFER: + case TGSI_TEXTURE_1D: + case TGSI_TEXTURE_SHADOW1D: + dim = 1; + break; + case TGSI_TEXTURE_2D: + case TGSI_TEXTURE_RECT: + case TGSI_TEXTURE_1D_ARRAY: + case TGSI_TEXTURE_SHADOW2D: + case TGSI_TEXTURE_SHADOWRECT: + case TGSI_TEXTURE_SHADOW1D_ARRAY: + case TGSI_TEXTURE_2D_MSAA: + dim = 2; + break; + case TGSI_TEXTURE_3D: + case TGSI_TEXTURE_CUBE: + case TGSI_TEXTURE_2D_ARRAY: + case TGSI_TEXTURE_SHADOWCUBE: + case TGSI_TEXTURE_SHADOW2D_ARRAY: + case TGSI_TEXTURE_2D_ARRAY_MSAA: + dim = 3; + break; + case TGSI_TEXTURE_CUBE_ARRAY: + case TGSI_TEXTURE_SHADOWCUBE_ARRAY: + dim = 4; + break; + default: + assert(!"unknown texture target"); + dim = 0; + break; + } + + if (shadow_or_sample) { + switch (tgsi_tex) { + case TGSI_TEXTURE_SHADOW1D: + /* there is a gap */ + *shadow_or_sample = 2; + break; + case TGSI_TEXTURE_SHADOW2D: + case TGSI_TEXTURE_SHADOWRECT: + case TGSI_TEXTURE_SHADOWCUBE: + case TGSI_TEXTURE_SHADOW1D_ARRAY: + case TGSI_TEXTURE_SHADOW2D_ARRAY: + case TGSI_TEXTURE_SHADOWCUBE_ARRAY: + *shadow_or_sample = dim; + break; + case TGSI_TEXTURE_2D_MSAA: + case TGSI_TEXTURE_2D_ARRAY_MSAA: + *shadow_or_sample = 3; + break; + default: + /* no shadow nor sample */ + *shadow_or_sample = -1; + break; + } + } + + return dim; +} diff --git a/src/gallium/auxiliary/tgsi/tgsi_util.h b/src/gallium/auxiliary/tgsi/tgsi_util.h new file mode 100644 index 0000000..deb1ecc --- /dev/null +++ b/src/gallium/auxiliary/tgsi/tgsi_util.h @@ -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 */ diff --git a/src/gallium/auxiliary/util/u_atomic.h b/src/gallium/auxiliary/util/u_atomic.h new file mode 100644 index 0000000..2f2b42b --- /dev/null +++ b/src/gallium/auxiliary/util/u_atomic.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 + +#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 + +#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 */ diff --git a/src/gallium/auxiliary/util/u_bitmask.h b/src/gallium/auxiliary/util/u_bitmask.h new file mode 100644 index 0000000..98b85dd --- /dev/null +++ b/src/gallium/auxiliary/util/u_bitmask.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 + */ + +#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_ */ diff --git a/src/gallium/auxiliary/util/u_box.h b/src/gallium/auxiliary/util/u_box.h new file mode 100644 index 0000000..0b28d0f --- /dev/null +++ b/src/gallium/auxiliary/util/u_box.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 diff --git a/src/gallium/auxiliary/util/u_debug.c b/src/gallium/auxiliary/util/u_debug.c new file mode 100644 index 0000000..ae248e0 --- /dev/null +++ b/src/gallium/auxiliary/util/u_debug.c @@ -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 +#include /* CHAR_BIT */ +#include /* 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 diff --git a/src/gallium/auxiliary/util/u_debug.h b/src/gallium/auxiliary/util/u_debug.h new file mode 100644 index 0000000..9e4eb41 --- /dev/null +++ b/src/gallium/auxiliary/util/u_debug.h @@ -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 + */ + +#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 +#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_ */ diff --git a/src/gallium/auxiliary/util/u_debug_describe.c b/src/gallium/auxiliary/util/u_debug_describe.c new file mode 100644 index 0000000..df73ed8 --- /dev/null +++ b/src/gallium/auxiliary/util/u_debug_describe.c @@ -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); +} diff --git a/src/gallium/auxiliary/util/u_debug_describe.h b/src/gallium/auxiliary/util/u_debug_describe.h new file mode 100644 index 0000000..4f7882b --- /dev/null +++ b/src/gallium/auxiliary/util/u_debug_describe.h @@ -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_ */ diff --git a/src/gallium/auxiliary/util/u_debug_refcnt.h b/src/gallium/auxiliary/util/u_debug_refcnt.h new file mode 100644 index 0000000..c02fba2 --- /dev/null +++ b/src/gallium/auxiliary/util/u_debug_refcnt.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_ */ diff --git a/src/gallium/auxiliary/util/u_double_list.h b/src/gallium/auxiliary/util/u_double_list.h new file mode 100644 index 0000000..247f0f2 --- /dev/null +++ b/src/gallium/auxiliary/util/u_double_list.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 +#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_*/ diff --git a/src/gallium/auxiliary/util/u_format.h b/src/gallium/auxiliary/util/u_format.h new file mode 100644 index 0000000..5f86e2d --- /dev/null +++ b/src/gallium/auxiliary/util/u_format.h @@ -0,0 +1,1234 @@ +/************************************************************************** + * + * 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 U_FORMAT_H +#define U_FORMAT_H + + +#include "pipe/p_format.h" +#include "pipe/p_defines.h" +#include "util/u_debug.h" + +union pipe_color_union; + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Describe how to pack/unpack pixels into/from the prescribed format. + * + * XXX: This could be renamed to something like util_format_pack, or broke down + * in flags inside util_format_block that said exactly what we want. + */ +enum util_format_layout { + /** + * Formats with util_format_block::width == util_format_block::height == 1 + * that can be described as an ordinary data structure. + */ + UTIL_FORMAT_LAYOUT_PLAIN = 0, + + /** + * Formats with sub-sampled channels. + * + * This is for formats like YVYU where there is less than one sample per + * pixel. + */ + UTIL_FORMAT_LAYOUT_SUBSAMPLED = 3, + + /** + * S3 Texture Compression formats. + */ + UTIL_FORMAT_LAYOUT_S3TC = 4, + + /** + * Red-Green Texture Compression formats. + */ + UTIL_FORMAT_LAYOUT_RGTC = 5, + + /** + * Ericsson Texture Compression + */ + UTIL_FORMAT_LAYOUT_ETC = 6, + + /** + * Everything else that doesn't fit in any of the above layouts. + */ + UTIL_FORMAT_LAYOUT_OTHER = 7 +}; + + +struct util_format_block +{ + /** Block width in pixels */ + unsigned width; + + /** Block height in pixels */ + unsigned height; + + /** Block size in bits */ + unsigned bits; +}; + + +enum util_format_type { + UTIL_FORMAT_TYPE_VOID = 0, + UTIL_FORMAT_TYPE_UNSIGNED = 1, + UTIL_FORMAT_TYPE_SIGNED = 2, + UTIL_FORMAT_TYPE_FIXED = 3, + UTIL_FORMAT_TYPE_FLOAT = 4 +}; + + +enum util_format_swizzle { + UTIL_FORMAT_SWIZZLE_X = 0, + UTIL_FORMAT_SWIZZLE_Y = 1, + UTIL_FORMAT_SWIZZLE_Z = 2, + UTIL_FORMAT_SWIZZLE_W = 3, + UTIL_FORMAT_SWIZZLE_0 = 4, + UTIL_FORMAT_SWIZZLE_1 = 5, + UTIL_FORMAT_SWIZZLE_NONE = 6, + UTIL_FORMAT_SWIZZLE_MAX = 7 /**< Number of enums counter (must be last) */ +}; + + +enum util_format_colorspace { + UTIL_FORMAT_COLORSPACE_RGB = 0, + UTIL_FORMAT_COLORSPACE_SRGB = 1, + UTIL_FORMAT_COLORSPACE_YUV = 2, + UTIL_FORMAT_COLORSPACE_ZS = 3 +}; + + +struct util_format_channel_description +{ + unsigned type:5; /**< UTIL_FORMAT_TYPE_x */ + unsigned normalized:1; + unsigned pure_integer:1; + unsigned size:9; /**< bits per channel */ + unsigned shift:16; /** number of bits from lsb */ +}; + + +struct util_format_description +{ + enum pipe_format format; + + const char *name; + + /** + * Short name, striped of the prefix, lower case. + */ + const char *short_name; + + /** + * Pixel block dimensions. + */ + struct util_format_block block; + + enum util_format_layout layout; + + /** + * The number of channels. + */ + unsigned nr_channels:3; + + /** + * Whether all channels have the same number of (whole) bytes and type. + */ + unsigned is_array:1; + + /** + * Whether the pixel format can be described as a bitfield structure. + * + * In particular: + * - pixel depth must be 8, 16, or 32 bits; + * - all channels must be unsigned, signed, or void + */ + unsigned is_bitmask:1; + + /** + * Whether channels have mixed types (ignoring UTIL_FORMAT_TYPE_VOID). + */ + unsigned is_mixed:1; + + /** + * Input channel description, in the order XYZW. + * + * Only valid for UTIL_FORMAT_LAYOUT_PLAIN formats. + * + * If each channel is accessed as an individual N-byte value, X is always + * at the lowest address in memory, Y is always next, and so on. For all + * currently-defined formats, the N-byte value has native endianness. + * + * If instead a group of channels is accessed as a single N-byte value, + * the order of the channels within that value depends on endianness. + * For big-endian targets, X is the most significant subvalue, + * otherwise it is the least significant one. + * + * For example, if X is 8 bits and Y is 24 bits, the memory order is: + * + * 0 1 2 3 + * little-endian: X Yl Ym Yu (l = lower, m = middle, u = upper) + * big-endian: X Yu Ym Yl + * + * If X is 5 bits, Y is 5 bits, Z is 5 bits and W is 1 bit, the layout is: + * + * 0 1 + * msb lsb msb lsb + * little-endian: YYYXXXXX WZZZZZYY + * big-endian: XXXXXYYY YYZZZZZW + */ + struct util_format_channel_description channel[4]; + + /** + * Output channel swizzle. + * + * The order is either: + * - RGBA + * - YUV(A) + * - ZS + * depending on the colorspace. + */ + unsigned char swizzle[4]; + + /** + * Colorspace transformation. + */ + enum util_format_colorspace colorspace; + + /** + * Unpack pixel blocks to R8G8B8A8_UNORM. + * Note: strides are in bytes. + * + * Only defined for non-depth-stencil formats. + */ + void + (*unpack_rgba_8unorm)(uint8_t *dst, unsigned dst_stride, + const uint8_t *src, unsigned src_stride, + unsigned width, unsigned height); + + /** + * Pack pixel blocks from R8G8B8A8_UNORM. + * Note: strides are in bytes. + * + * Only defined for non-depth-stencil formats. + */ + void + (*pack_rgba_8unorm)(uint8_t *dst, unsigned dst_stride, + const uint8_t *src, unsigned src_stride, + unsigned width, unsigned height); + + /** + * Fetch a single pixel (i, j) from a block. + * + * XXX: Only defined for a very few select formats. + */ + void + (*fetch_rgba_8unorm)(uint8_t *dst, + const uint8_t *src, + unsigned i, unsigned j); + + /** + * Unpack pixel blocks to R32G32B32A32_FLOAT. + * Note: strides are in bytes. + * + * Only defined for non-depth-stencil formats. + */ + void + (*unpack_rgba_float)(float *dst, unsigned dst_stride, + const uint8_t *src, unsigned src_stride, + unsigned width, unsigned height); + + /** + * Pack pixel blocks from R32G32B32A32_FLOAT. + * Note: strides are in bytes. + * + * Only defined for non-depth-stencil formats. + */ + void + (*pack_rgba_float)(uint8_t *dst, unsigned dst_stride, + const float *src, unsigned src_stride, + unsigned width, unsigned height); + + /** + * Fetch a single pixel (i, j) from a block. + * + * Only defined for non-depth-stencil and non-integer formats. + */ + void + (*fetch_rgba_float)(float *dst, + const uint8_t *src, + unsigned i, unsigned j); + + /** + * Unpack pixels to Z32_UNORM. + * Note: strides are in bytes. + * + * Only defined for depth formats. + */ + void + (*unpack_z_32unorm)(uint32_t *dst, unsigned dst_stride, + const uint8_t *src, unsigned src_stride, + unsigned width, unsigned height); + + /** + * Pack pixels from Z32_FLOAT. + * Note: strides are in bytes. + * + * Only defined for depth formats. + */ + void + (*pack_z_32unorm)(uint8_t *dst, unsigned dst_stride, + const uint32_t *src, unsigned src_stride, + unsigned width, unsigned height); + + /** + * Unpack pixels to Z32_FLOAT. + * Note: strides are in bytes. + * + * Only defined for depth formats. + */ + void + (*unpack_z_float)(float *dst, unsigned dst_stride, + const uint8_t *src, unsigned src_stride, + unsigned width, unsigned height); + + /** + * Pack pixels from Z32_FLOAT. + * Note: strides are in bytes. + * + * Only defined for depth formats. + */ + void + (*pack_z_float)(uint8_t *dst, unsigned dst_stride, + const float *src, unsigned src_stride, + unsigned width, unsigned height); + + /** + * Unpack pixels to S8_UINT. + * Note: strides are in bytes. + * + * Only defined for stencil formats. + */ + void + (*unpack_s_8uint)(uint8_t *dst, unsigned dst_stride, + const uint8_t *src, unsigned src_stride, + unsigned width, unsigned height); + + /** + * Pack pixels from S8_UINT. + * Note: strides are in bytes. + * + * Only defined for stencil formats. + */ + void + (*pack_s_8uint)(uint8_t *dst, unsigned dst_stride, + const uint8_t *src, unsigned src_stride, + unsigned width, unsigned height); + + /** + * Unpack pixel blocks to R32G32B32A32_UINT. + * Note: strides are in bytes. + * + * Only defined for INT formats. + */ + void + (*unpack_rgba_uint)(uint32_t *dst, unsigned dst_stride, + const uint8_t *src, unsigned src_stride, + unsigned width, unsigned height); + + void + (*pack_rgba_uint)(uint8_t *dst, unsigned dst_stride, + const uint32_t *src, unsigned src_stride, + unsigned width, unsigned height); + + /** + * Unpack pixel blocks to R32G32B32A32_SINT. + * Note: strides are in bytes. + * + * Only defined for INT formats. + */ + void + (*unpack_rgba_sint)(int32_t *dst, unsigned dst_stride, + const uint8_t *src, unsigned src_stride, + unsigned width, unsigned height); + + void + (*pack_rgba_sint)(uint8_t *dst, unsigned dst_stride, + const int32_t *src, unsigned src_stride, + unsigned width, unsigned height); + + /** + * Fetch a single pixel (i, j) from a block. + * + * Only defined for unsigned (pure) integer formats. + */ + void + (*fetch_rgba_uint)(uint32_t *dst, + const uint8_t *src, + unsigned i, unsigned j); + + /** + * Fetch a single pixel (i, j) from a block. + * + * Only defined for signed (pure) integer formats. + */ + void + (*fetch_rgba_sint)(int32_t *dst, + const uint8_t *src, + unsigned i, unsigned j); +}; + + +extern const struct util_format_description +util_format_description_table[]; + + +const struct util_format_description * +util_format_description(enum pipe_format format); + + +/* + * Format query functions. + */ + +static INLINE const char * +util_format_name(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + + assert(desc); + if (!desc) { + return "PIPE_FORMAT_???"; + } + + return desc->name; +} + +static INLINE const char * +util_format_short_name(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + + assert(desc); + if (!desc) { + return "???"; + } + + return desc->short_name; +} + +/** + * Whether this format is plain, see UTIL_FORMAT_LAYOUT_PLAIN for more info. + */ +static INLINE boolean +util_format_is_plain(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + + if (!format) { + return FALSE; + } + + return desc->layout == UTIL_FORMAT_LAYOUT_PLAIN ? TRUE : FALSE; +} + +static INLINE boolean +util_format_is_compressed(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + + assert(desc); + if (!desc) { + return FALSE; + } + + switch (desc->layout) { + case UTIL_FORMAT_LAYOUT_S3TC: + case UTIL_FORMAT_LAYOUT_RGTC: + case UTIL_FORMAT_LAYOUT_ETC: + /* XXX add other formats in the future */ + return TRUE; + default: + return FALSE; + } +} + +static INLINE boolean +util_format_is_s3tc(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + + assert(desc); + if (!desc) { + return FALSE; + } + + return desc->layout == UTIL_FORMAT_LAYOUT_S3TC ? TRUE : FALSE; +} + +static INLINE boolean +util_format_is_srgb(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + return desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB; +} + +static INLINE boolean +util_format_has_depth(const struct util_format_description *desc) +{ + return desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS && + desc->swizzle[0] != UTIL_FORMAT_SWIZZLE_NONE; +} + +static INLINE boolean +util_format_has_stencil(const struct util_format_description *desc) +{ + return desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS && + desc->swizzle[1] != UTIL_FORMAT_SWIZZLE_NONE; +} + +static INLINE boolean +util_format_is_depth_or_stencil(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + + assert(desc); + if (!desc) { + return FALSE; + } + + return util_format_has_depth(desc) || + util_format_has_stencil(desc); +} + +static INLINE boolean +util_format_is_depth_and_stencil(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + + assert(desc); + if (!desc) { + return FALSE; + } + + return util_format_has_depth(desc) && + util_format_has_stencil(desc); +} + + +/** + * Calculates the depth format type based upon the incoming format description. + */ +static INLINE unsigned +util_get_depth_format_type(const struct util_format_description *desc) +{ + unsigned depth_channel = desc->swizzle[0]; + if (desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS && + depth_channel != UTIL_FORMAT_SWIZZLE_NONE) { + return desc->channel[depth_channel].type; + } else { + return UTIL_FORMAT_TYPE_VOID; + } +} + + +/** + * Calculates the MRD for the depth format. MRD is used in depth bias + * for UNORM and unbound depth buffers. When the depth buffer is floating + * point, the depth bias calculation does not use the MRD. However, the + * default MRD will be 1.0 / ((1 << 24) - 1). + */ +double +util_get_depth_format_mrd(const struct util_format_description *desc); + + +/** + * Return whether this is an RGBA, Z, S, or combined ZS format. + * Useful for initializing pipe_blit_info::mask. + */ +static INLINE unsigned +util_format_get_mask(enum pipe_format format) +{ + const struct util_format_description *desc = + util_format_description(format); + + if (!desc) + return 0; + + if (util_format_has_depth(desc)) { + if (util_format_has_stencil(desc)) { + return PIPE_MASK_ZS; + } else { + return PIPE_MASK_Z; + } + } else { + if (util_format_has_stencil(desc)) { + return PIPE_MASK_S; + } else { + return PIPE_MASK_RGBA; + } + } +} + +/** + * Give the RGBA colormask of the channels that can be represented in this + * format. + * + * That is, the channels whose values are preserved. + */ +static INLINE unsigned +util_format_colormask(const struct util_format_description *desc) +{ + unsigned colormask; + unsigned chan; + + switch (desc->colorspace) { + case UTIL_FORMAT_COLORSPACE_RGB: + case UTIL_FORMAT_COLORSPACE_SRGB: + case UTIL_FORMAT_COLORSPACE_YUV: + colormask = 0; + for (chan = 0; chan < 4; ++chan) { + if (desc->swizzle[chan] < 4) { + colormask |= (1 << chan); + } + } + return colormask; + case UTIL_FORMAT_COLORSPACE_ZS: + return 0; + default: + assert(0); + return 0; + } +} + + +/** + * Checks if color mask covers every channel for the specified format + * + * @param desc a format description to check colormask with + * @param colormask a bit mask for channels, matches format of PIPE_MASK_RGBA + */ +static INLINE boolean +util_format_colormask_full(const struct util_format_description *desc, unsigned colormask) +{ + return (~colormask & util_format_colormask(desc)) == 0; +} + + +boolean +util_format_is_float(enum pipe_format format); + + +boolean +util_format_has_alpha(enum pipe_format format); + + +boolean +util_format_is_luminance(enum pipe_format format); + + +boolean +util_format_is_luminance_alpha(enum pipe_format format); + + +boolean +util_format_is_intensity(enum pipe_format format); + +boolean +util_format_is_pure_integer(enum pipe_format format); + +boolean +util_format_is_pure_sint(enum pipe_format format); + +boolean +util_format_is_pure_uint(enum pipe_format format); + +boolean +util_format_is_snorm(enum pipe_format format); + +/** + * Check if the src format can be blitted to the destination format with + * a simple memcpy. For example, blitting from RGBA to RGBx is OK, but not + * the reverse. + */ +boolean +util_is_format_compatible(const struct util_format_description *src_desc, + const struct util_format_description *dst_desc); + +/** + * Whether the format is supported by Gallium for the given bindings. + * This covers S3TC textures and floating-point render targets. + */ +boolean +util_format_is_supported(enum pipe_format format, unsigned bind); + +/** + * Whether this format is a rgab8 variant. + * + * That is, any format that matches the + * + * PIPE_FORMAT_?8?8?8?8_UNORM + */ +static INLINE boolean +util_format_is_rgba8_variant(const struct util_format_description *desc) +{ + unsigned chan; + + if(desc->block.width != 1 || + desc->block.height != 1 || + desc->block.bits != 32) + return FALSE; + + for(chan = 0; chan < 4; ++chan) { + if(desc->channel[chan].type != UTIL_FORMAT_TYPE_UNSIGNED && + desc->channel[chan].type != UTIL_FORMAT_TYPE_VOID) + return FALSE; + if(desc->channel[chan].type == UTIL_FORMAT_TYPE_UNSIGNED && + !desc->channel[chan].normalized) + return FALSE; + if(desc->channel[chan].size != 8) + return FALSE; + } + + return TRUE; +} + + +/** + * Return total bits needed for the pixel format per block. + */ +static INLINE uint +util_format_get_blocksizebits(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + + assert(desc); + if (!desc) { + return 0; + } + + return desc->block.bits; +} + +/** + * Return bytes per block (not pixel) for the given format. + */ +static INLINE uint +util_format_get_blocksize(enum pipe_format format) +{ + uint bits = util_format_get_blocksizebits(format); + uint bytes = bits / 8; + + assert(bits % 8 == 0); + assert(bytes > 0); + if (bytes == 0) { + bytes = 1; + } + + return bytes; +} + +static INLINE uint +util_format_get_blockwidth(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + + assert(desc); + if (!desc) { + return 1; + } + + return desc->block.width; +} + +static INLINE uint +util_format_get_blockheight(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + + assert(desc); + if (!desc) { + return 1; + } + + return desc->block.height; +} + +static INLINE unsigned +util_format_get_nblocksx(enum pipe_format format, + unsigned x) +{ + unsigned blockwidth = util_format_get_blockwidth(format); + return (x + blockwidth - 1) / blockwidth; +} + +static INLINE unsigned +util_format_get_nblocksy(enum pipe_format format, + unsigned y) +{ + unsigned blockheight = util_format_get_blockheight(format); + return (y + blockheight - 1) / blockheight; +} + +static INLINE unsigned +util_format_get_nblocks(enum pipe_format format, + unsigned width, + unsigned height) +{ + return util_format_get_nblocksx(format, width) * util_format_get_nblocksy(format, height); +} + +static INLINE size_t +util_format_get_stride(enum pipe_format format, + unsigned width) +{ + return util_format_get_nblocksx(format, width) * util_format_get_blocksize(format); +} + +static INLINE size_t +util_format_get_2d_size(enum pipe_format format, + size_t stride, + unsigned height) +{ + return util_format_get_nblocksy(format, height) * stride; +} + +static INLINE uint +util_format_get_component_bits(enum pipe_format format, + enum util_format_colorspace colorspace, + uint component) +{ + const struct util_format_description *desc = util_format_description(format); + enum util_format_colorspace desc_colorspace; + + assert(format); + if (!format) { + return 0; + } + + assert(component < 4); + + /* Treat RGB and SRGB as equivalent. */ + if (colorspace == UTIL_FORMAT_COLORSPACE_SRGB) { + colorspace = UTIL_FORMAT_COLORSPACE_RGB; + } + if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) { + desc_colorspace = UTIL_FORMAT_COLORSPACE_RGB; + } else { + desc_colorspace = desc->colorspace; + } + + if (desc_colorspace != colorspace) { + return 0; + } + + switch (desc->swizzle[component]) { + case UTIL_FORMAT_SWIZZLE_X: + return desc->channel[0].size; + case UTIL_FORMAT_SWIZZLE_Y: + return desc->channel[1].size; + case UTIL_FORMAT_SWIZZLE_Z: + return desc->channel[2].size; + case UTIL_FORMAT_SWIZZLE_W: + return desc->channel[3].size; + default: + return 0; + } +} + +/** + * Given a linear RGB colorspace format, return the corresponding SRGB + * format, or PIPE_FORMAT_NONE if none. + */ +static INLINE enum pipe_format +util_format_srgb(enum pipe_format format) +{ + if (util_format_is_srgb(format)) + return format; + + switch (format) { + case PIPE_FORMAT_L8_UNORM: + return PIPE_FORMAT_L8_SRGB; + case PIPE_FORMAT_L8A8_UNORM: + return PIPE_FORMAT_L8A8_SRGB; + case PIPE_FORMAT_R8G8B8_UNORM: + return PIPE_FORMAT_R8G8B8_SRGB; + case PIPE_FORMAT_A8B8G8R8_UNORM: + return PIPE_FORMAT_A8B8G8R8_SRGB; + case PIPE_FORMAT_X8B8G8R8_UNORM: + return PIPE_FORMAT_X8B8G8R8_SRGB; + case PIPE_FORMAT_B8G8R8A8_UNORM: + return PIPE_FORMAT_B8G8R8A8_SRGB; + case PIPE_FORMAT_B8G8R8X8_UNORM: + return PIPE_FORMAT_B8G8R8X8_SRGB; + case PIPE_FORMAT_A8R8G8B8_UNORM: + return PIPE_FORMAT_A8R8G8B8_SRGB; + case PIPE_FORMAT_X8R8G8B8_UNORM: + return PIPE_FORMAT_X8R8G8B8_SRGB; + case PIPE_FORMAT_R8G8B8A8_UNORM: + return PIPE_FORMAT_R8G8B8A8_SRGB; + case PIPE_FORMAT_R8G8B8X8_UNORM: + return PIPE_FORMAT_R8G8B8X8_SRGB; + case PIPE_FORMAT_DXT1_RGB: + return PIPE_FORMAT_DXT1_SRGB; + case PIPE_FORMAT_DXT1_RGBA: + return PIPE_FORMAT_DXT1_SRGBA; + case PIPE_FORMAT_DXT3_RGBA: + return PIPE_FORMAT_DXT3_SRGBA; + case PIPE_FORMAT_DXT5_RGBA: + return PIPE_FORMAT_DXT5_SRGBA; + default: + return PIPE_FORMAT_NONE; + } +} + +/** + * Given an sRGB format, return the corresponding linear colorspace format. + * For non sRGB formats, return the format unchanged. + */ +static INLINE enum pipe_format +util_format_linear(enum pipe_format format) +{ + switch (format) { + case PIPE_FORMAT_L8_SRGB: + return PIPE_FORMAT_L8_UNORM; + case PIPE_FORMAT_L8A8_SRGB: + return PIPE_FORMAT_L8A8_UNORM; + case PIPE_FORMAT_R8G8B8_SRGB: + return PIPE_FORMAT_R8G8B8_UNORM; + case PIPE_FORMAT_A8B8G8R8_SRGB: + return PIPE_FORMAT_A8B8G8R8_UNORM; + case PIPE_FORMAT_X8B8G8R8_SRGB: + return PIPE_FORMAT_X8B8G8R8_UNORM; + case PIPE_FORMAT_B8G8R8A8_SRGB: + return PIPE_FORMAT_B8G8R8A8_UNORM; + case PIPE_FORMAT_B8G8R8X8_SRGB: + return PIPE_FORMAT_B8G8R8X8_UNORM; + case PIPE_FORMAT_A8R8G8B8_SRGB: + return PIPE_FORMAT_A8R8G8B8_UNORM; + case PIPE_FORMAT_X8R8G8B8_SRGB: + return PIPE_FORMAT_X8R8G8B8_UNORM; + case PIPE_FORMAT_R8G8B8A8_SRGB: + return PIPE_FORMAT_R8G8B8A8_UNORM; + case PIPE_FORMAT_R8G8B8X8_SRGB: + return PIPE_FORMAT_R8G8B8X8_UNORM; + case PIPE_FORMAT_DXT1_SRGB: + return PIPE_FORMAT_DXT1_RGB; + case PIPE_FORMAT_DXT1_SRGBA: + return PIPE_FORMAT_DXT1_RGBA; + case PIPE_FORMAT_DXT3_SRGBA: + return PIPE_FORMAT_DXT3_RGBA; + case PIPE_FORMAT_DXT5_SRGBA: + return PIPE_FORMAT_DXT5_RGBA; + default: + return format; + } +} + +/** + * Given a depth-stencil format, return the corresponding stencil-only format. + * For stencil-only formats, return the format unchanged. + */ +static INLINE enum pipe_format +util_format_stencil_only(enum pipe_format format) +{ + switch (format) { + /* mask out the depth component */ + case PIPE_FORMAT_Z24_UNORM_S8_UINT: + return PIPE_FORMAT_X24S8_UINT; + case PIPE_FORMAT_S8_UINT_Z24_UNORM: + return PIPE_FORMAT_S8X24_UINT; + case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: + return PIPE_FORMAT_X32_S8X24_UINT; + + /* stencil only formats */ + case PIPE_FORMAT_X24S8_UINT: + case PIPE_FORMAT_S8X24_UINT: + case PIPE_FORMAT_X32_S8X24_UINT: + case PIPE_FORMAT_S8_UINT: + return format; + + default: + assert(0); + return PIPE_FORMAT_NONE; + } +} + +/** + * Converts PIPE_FORMAT_*I* to PIPE_FORMAT_*R*. + * This is identity for non-intensity formats. + */ +static INLINE enum pipe_format +util_format_intensity_to_red(enum pipe_format format) +{ + switch (format) { + case PIPE_FORMAT_I8_UNORM: + return PIPE_FORMAT_R8_UNORM; + case PIPE_FORMAT_I8_SNORM: + return PIPE_FORMAT_R8_SNORM; + case PIPE_FORMAT_I16_UNORM: + return PIPE_FORMAT_R16_UNORM; + case PIPE_FORMAT_I16_SNORM: + return PIPE_FORMAT_R16_SNORM; + case PIPE_FORMAT_I16_FLOAT: + return PIPE_FORMAT_R16_FLOAT; + case PIPE_FORMAT_I32_FLOAT: + return PIPE_FORMAT_R32_FLOAT; + case PIPE_FORMAT_I8_UINT: + return PIPE_FORMAT_R8_UINT; + case PIPE_FORMAT_I8_SINT: + return PIPE_FORMAT_R8_SINT; + case PIPE_FORMAT_I16_UINT: + return PIPE_FORMAT_R16_UINT; + case PIPE_FORMAT_I16_SINT: + return PIPE_FORMAT_R16_SINT; + case PIPE_FORMAT_I32_UINT: + return PIPE_FORMAT_R32_UINT; + case PIPE_FORMAT_I32_SINT: + return PIPE_FORMAT_R32_SINT; + default: + assert(!util_format_is_intensity(format)); + return format; + } +} + +/** + * Converts PIPE_FORMAT_*L* to PIPE_FORMAT_*R*. + * This is identity for non-luminance formats. + */ +static INLINE enum pipe_format +util_format_luminance_to_red(enum pipe_format format) +{ + switch (format) { + case PIPE_FORMAT_L8_UNORM: + return PIPE_FORMAT_R8_UNORM; + case PIPE_FORMAT_L8_SNORM: + return PIPE_FORMAT_R8_SNORM; + case PIPE_FORMAT_L16_UNORM: + return PIPE_FORMAT_R16_UNORM; + case PIPE_FORMAT_L16_SNORM: + return PIPE_FORMAT_R16_SNORM; + case PIPE_FORMAT_L16_FLOAT: + return PIPE_FORMAT_R16_FLOAT; + case PIPE_FORMAT_L32_FLOAT: + return PIPE_FORMAT_R32_FLOAT; + case PIPE_FORMAT_L8_UINT: + return PIPE_FORMAT_R8_UINT; + case PIPE_FORMAT_L8_SINT: + return PIPE_FORMAT_R8_SINT; + case PIPE_FORMAT_L16_UINT: + return PIPE_FORMAT_R16_UINT; + case PIPE_FORMAT_L16_SINT: + return PIPE_FORMAT_R16_SINT; + case PIPE_FORMAT_L32_UINT: + return PIPE_FORMAT_R32_UINT; + case PIPE_FORMAT_L32_SINT: + return PIPE_FORMAT_R32_SINT; + + case PIPE_FORMAT_LATC1_UNORM: + return PIPE_FORMAT_RGTC1_UNORM; + case PIPE_FORMAT_LATC1_SNORM: + return PIPE_FORMAT_RGTC1_SNORM; + + case PIPE_FORMAT_L4A4_UNORM: + /* XXX A4R4 is defined as x00y in u_format.csv */ + return PIPE_FORMAT_A4R4_UNORM; + + case PIPE_FORMAT_L8A8_UNORM: + return PIPE_FORMAT_R8A8_UNORM; + case PIPE_FORMAT_L8A8_SNORM: + return PIPE_FORMAT_R8A8_SNORM; + case PIPE_FORMAT_L16A16_UNORM: + return PIPE_FORMAT_R16A16_UNORM; + case PIPE_FORMAT_L16A16_SNORM: + return PIPE_FORMAT_R16A16_SNORM; + case PIPE_FORMAT_L16A16_FLOAT: + return PIPE_FORMAT_R16A16_FLOAT; + case PIPE_FORMAT_L32A32_FLOAT: + return PIPE_FORMAT_R32A32_FLOAT; + case PIPE_FORMAT_L8A8_UINT: + return PIPE_FORMAT_R8A8_UINT; + case PIPE_FORMAT_L8A8_SINT: + return PIPE_FORMAT_R8A8_SINT; + case PIPE_FORMAT_L16A16_UINT: + return PIPE_FORMAT_R16A16_UINT; + case PIPE_FORMAT_L16A16_SINT: + return PIPE_FORMAT_R16A16_SINT; + case PIPE_FORMAT_L32A32_UINT: + return PIPE_FORMAT_R32A32_UINT; + case PIPE_FORMAT_L32A32_SINT: + return PIPE_FORMAT_R32A32_SINT; + + /* We don't have compressed red-alpha variants for these. */ + case PIPE_FORMAT_LATC2_UNORM: + case PIPE_FORMAT_LATC2_SNORM: + return PIPE_FORMAT_NONE; + + default: + assert(!util_format_is_luminance(format) && + !util_format_is_luminance_alpha(format)); + return format; + } +} + +/** + * Return the number of components stored. + * Formats with block size != 1x1 will always have 1 component (the block). + */ +static INLINE unsigned +util_format_get_nr_components(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + return desc->nr_channels; +} + +/** + * Return the index of the first non-void channel + * -1 if no non-void channels + */ +static INLINE int +util_format_get_first_non_void_channel(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + int i; + + for (i = 0; i < 4; i++) + if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID) + break; + + if (i == 4) + return -1; + + return i; +} + +/* + * Format access functions. + */ + +void +util_format_read_4f(enum pipe_format format, + float *dst, unsigned dst_stride, + const void *src, unsigned src_stride, + unsigned x, unsigned y, unsigned w, unsigned h); + +void +util_format_write_4f(enum pipe_format format, + const float *src, unsigned src_stride, + void *dst, unsigned dst_stride, + unsigned x, unsigned y, unsigned w, unsigned h); + +void +util_format_read_4ub(enum pipe_format format, + uint8_t *dst, unsigned dst_stride, + const void *src, unsigned src_stride, + unsigned x, unsigned y, unsigned w, unsigned h); + +void +util_format_write_4ub(enum pipe_format format, + const uint8_t *src, unsigned src_stride, + void *dst, unsigned dst_stride, + unsigned x, unsigned y, unsigned w, unsigned h); + +void +util_format_read_4ui(enum pipe_format format, + unsigned *dst, unsigned dst_stride, + const void *src, unsigned src_stride, + unsigned x, unsigned y, unsigned w, unsigned h); + +void +util_format_write_4ui(enum pipe_format format, + const unsigned int *src, unsigned src_stride, + void *dst, unsigned dst_stride, + unsigned x, unsigned y, unsigned w, unsigned h); + +void +util_format_read_4i(enum pipe_format format, + int *dst, unsigned dst_stride, + const void *src, unsigned src_stride, + unsigned x, unsigned y, unsigned w, unsigned h); + +void +util_format_write_4i(enum pipe_format format, + const int *src, unsigned src_stride, + void *dst, unsigned dst_stride, + unsigned x, unsigned y, unsigned w, unsigned h); + +/* + * Generic format conversion; + */ + +boolean +util_format_fits_8unorm(const struct util_format_description *format_desc); + +void +util_format_translate(enum pipe_format dst_format, + void *dst, unsigned dst_stride, + unsigned dst_x, unsigned dst_y, + enum pipe_format src_format, + const void *src, unsigned src_stride, + unsigned src_x, unsigned src_y, + unsigned width, unsigned height); + +/* + * Swizzle operations. + */ + +/* Compose two sets of swizzles. + * If V is a 4D vector and the function parameters represent functions that + * swizzle vector components, this holds: + * swz2(swz1(V)) = dst(V) + */ +void util_format_compose_swizzles(const unsigned char swz1[4], + const unsigned char swz2[4], + unsigned char dst[4]); + +/* Apply the swizzle provided in \param swz (which is one of PIPE_SWIZZLE_x) + * to \param src and store the result in \param dst. + * \param is_integer determines the value written for PIPE_SWIZZLE_ONE. + */ +void util_format_apply_color_swizzle(union pipe_color_union *dst, + const union pipe_color_union *src, + const unsigned char swz[4], + const boolean is_integer); + +void util_format_swizzle_4f(float *dst, const float *src, + const unsigned char swz[4]); + +void util_format_unswizzle_4f(float *dst, const float *src, + const unsigned char swz[4]); + +#ifdef __cplusplus +} // extern "C" { +#endif + +#endif /* ! U_FORMAT_H */ diff --git a/src/gallium/auxiliary/util/u_format_etc.h b/src/gallium/auxiliary/util/u_format_etc.h new file mode 100644 index 0000000..30c3dcb --- /dev/null +++ b/src/gallium/auxiliary/util/u_format_etc.h @@ -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_ */ diff --git a/src/gallium/auxiliary/util/u_format_latc.h b/src/gallium/auxiliary/util/u_format_latc.h new file mode 100644 index 0000000..1f08887 --- /dev/null +++ b/src/gallium/auxiliary/util/u_format_latc.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 diff --git a/src/gallium/auxiliary/util/u_format_other.h b/src/gallium/auxiliary/util/u_format_other.h new file mode 100644 index 0000000..2f6a908 --- /dev/null +++ b/src/gallium/auxiliary/util/u_format_other.h @@ -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_ */ diff --git a/src/gallium/auxiliary/util/u_format_rgtc.h b/src/gallium/auxiliary/util/u_format_rgtc.h new file mode 100644 index 0000000..67ac472 --- /dev/null +++ b/src/gallium/auxiliary/util/u_format_rgtc.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 diff --git a/src/gallium/auxiliary/util/u_format_s3tc.h b/src/gallium/auxiliary/util/u_format_s3tc.h new file mode 100644 index 0000000..97770ab --- /dev/null +++ b/src/gallium/auxiliary/util/u_format_s3tc.h @@ -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_ */ diff --git a/src/gallium/auxiliary/util/u_format_srgb.c b/src/gallium/auxiliary/util/u_format_srgb.c new file mode 100644 index 0000000..2649089 --- /dev/null +++ b/src/gallium/auxiliary/util/u_format_srgb.c @@ -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 + * @author Michal Krol + * @author Jose Fonseca + */ + +#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, +}; + diff --git a/src/gallium/auxiliary/util/u_format_srgb.h b/src/gallium/auxiliary/util/u_format_srgb.h new file mode 100644 index 0000000..740a919 --- /dev/null +++ b/src/gallium/auxiliary/util/u_format_srgb.h @@ -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 + * @author Michal Krol + * @author Jose Fonseca + */ + +#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_ */ diff --git a/src/gallium/auxiliary/util/u_format_table.c b/src/gallium/auxiliary/util/u_format_table.c new file mode 100644 index 0000000..1cb0484 --- /dev/null +++ b/src/gallium/auxiliary/util/u_format_table.c @@ -0,0 +1,33985 @@ +/* This file is autogenerated by u_format_table.py from u_format.csv. 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. + * + **************************************************************************/ + +#include "u_format.h" +#include "u_format_s3tc.h" +#include "u_format_rgtc.h" +#include "u_format_latc.h" +#include "u_format_etc.h" + + +#include "pipe/p_compiler.h" +#include "u_math.h" +#include "u_half.h" +#include "u_format.h" +#include "u_format_other.h" +#include "u_format_srgb.h" +#include "u_format_yuv.h" +#include "u_format_zs.h" + +union util_format_none { + uint8_t value; + struct { + uint8_t r; + } chan; +}; + +static INLINE void +util_format_none_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + uint8_t r; + r = value; + dst[0] = (float)r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_none_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= (uint8_t)CLAMP(src[0], 0, 255); + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_none_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint8_t value = *(const uint8_t *)src; + uint8_t r; + r = value; + dst[0] = (float)r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_none_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + uint8_t r; + r = value; + dst[0] = (uint8_t)(((uint32_t)MIN2(r, 1)) * 0xff / 0x1); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 255; /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_none_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= (uint8_t)(((uint32_t)src[0]) * 0x1 / 0xff); + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_b8g8r8a8_unorm { + uint32_t value; + struct { + uint8_t b; + uint8_t g; + uint8_t r; + uint8_t a; + } chan; +}; + +static INLINE void +util_format_b8g8r8a8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t b; + uint32_t g; + uint32_t r; + uint32_t a; + b = (value) & 0xff; + g = (value >> 8) & 0xff; + r = (value >> 16) & 0xff; + a = value >> 24; + dst[0] = ubyte_to_float(r); /* r */ + dst[1] = ubyte_to_float(g); /* g */ + dst[2] = ubyte_to_float(b); /* b */ + dst[3] = ubyte_to_float(a); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_b8g8r8a8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (float_to_ubyte(src[2])) & 0xff; + value |= ((float_to_ubyte(src[1])) & 0xff) << 8; + value |= ((float_to_ubyte(src[0])) & 0xff) << 16; + value |= (float_to_ubyte(src[3])) << 24; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_b8g8r8a8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t b; + uint32_t g; + uint32_t r; + uint32_t a; + b = (value) & 0xff; + g = (value >> 8) & 0xff; + r = (value >> 16) & 0xff; + a = value >> 24; + dst[0] = ubyte_to_float(r); /* r */ + dst[1] = ubyte_to_float(g); /* g */ + dst[2] = ubyte_to_float(b); /* b */ + dst[3] = ubyte_to_float(a); /* a */ +} + +static INLINE void +util_format_b8g8r8a8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t b; + uint32_t g; + uint32_t r; + uint32_t a; + b = (value) & 0xff; + g = (value >> 8) & 0xff; + r = (value >> 16) & 0xff; + a = value >> 24; + dst[0] = r; /* r */ + dst[1] = g; /* g */ + dst[2] = b; /* b */ + dst[3] = a; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_b8g8r8a8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (src[2]) & 0xff; + value |= ((src[1]) & 0xff) << 8; + value |= ((src[0]) & 0xff) << 16; + value |= (src[3]) << 24; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_b8g8r8x8_unorm { + uint32_t value; + struct { + uint8_t b; + uint8_t g; + uint8_t r; + uint8_t x; + } chan; +}; + +static INLINE void +util_format_b8g8r8x8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t b; + uint32_t g; + uint32_t r; + b = (value) & 0xff; + g = (value >> 8) & 0xff; + r = (value >> 16) & 0xff; + dst[0] = ubyte_to_float(r); /* r */ + dst[1] = ubyte_to_float(g); /* g */ + dst[2] = ubyte_to_float(b); /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_b8g8r8x8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (float_to_ubyte(src[2])) & 0xff; + value |= ((float_to_ubyte(src[1])) & 0xff) << 8; + value |= ((float_to_ubyte(src[0])) & 0xff) << 16; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_b8g8r8x8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t b; + uint32_t g; + uint32_t r; + b = (value) & 0xff; + g = (value >> 8) & 0xff; + r = (value >> 16) & 0xff; + dst[0] = ubyte_to_float(r); /* r */ + dst[1] = ubyte_to_float(g); /* g */ + dst[2] = ubyte_to_float(b); /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_b8g8r8x8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t b; + uint32_t g; + uint32_t r; + b = (value) & 0xff; + g = (value >> 8) & 0xff; + r = (value >> 16) & 0xff; + dst[0] = r; /* r */ + dst[1] = g; /* g */ + dst[2] = b; /* b */ + dst[3] = 255; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_b8g8r8x8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (src[2]) & 0xff; + value |= ((src[1]) & 0xff) << 8; + value |= ((src[0]) & 0xff) << 16; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_a8r8g8b8_unorm { + uint32_t value; + struct { + uint8_t a; + uint8_t r; + uint8_t g; + uint8_t b; + } chan; +}; + +static INLINE void +util_format_a8r8g8b8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t a; + uint32_t r; + uint32_t g; + uint32_t b; + a = (value) & 0xff; + r = (value >> 8) & 0xff; + g = (value >> 16) & 0xff; + b = value >> 24; + dst[0] = ubyte_to_float(r); /* r */ + dst[1] = ubyte_to_float(g); /* g */ + dst[2] = ubyte_to_float(b); /* b */ + dst[3] = ubyte_to_float(a); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a8r8g8b8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (float_to_ubyte(src[3])) & 0xff; + value |= ((float_to_ubyte(src[0])) & 0xff) << 8; + value |= ((float_to_ubyte(src[1])) & 0xff) << 16; + value |= (float_to_ubyte(src[2])) << 24; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_a8r8g8b8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t a; + uint32_t r; + uint32_t g; + uint32_t b; + a = (value) & 0xff; + r = (value >> 8) & 0xff; + g = (value >> 16) & 0xff; + b = value >> 24; + dst[0] = ubyte_to_float(r); /* r */ + dst[1] = ubyte_to_float(g); /* g */ + dst[2] = ubyte_to_float(b); /* b */ + dst[3] = ubyte_to_float(a); /* a */ +} + +static INLINE void +util_format_a8r8g8b8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t a; + uint32_t r; + uint32_t g; + uint32_t b; + a = (value) & 0xff; + r = (value >> 8) & 0xff; + g = (value >> 16) & 0xff; + b = value >> 24; + dst[0] = r; /* r */ + dst[1] = g; /* g */ + dst[2] = b; /* b */ + dst[3] = a; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a8r8g8b8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (src[3]) & 0xff; + value |= ((src[0]) & 0xff) << 8; + value |= ((src[1]) & 0xff) << 16; + value |= (src[2]) << 24; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_x8r8g8b8_unorm { + uint32_t value; + struct { + uint8_t x; + uint8_t r; + uint8_t g; + uint8_t b; + } chan; +}; + +static INLINE void +util_format_x8r8g8b8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + r = (value >> 8) & 0xff; + g = (value >> 16) & 0xff; + b = value >> 24; + dst[0] = ubyte_to_float(r); /* r */ + dst[1] = ubyte_to_float(g); /* g */ + dst[2] = ubyte_to_float(b); /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_x8r8g8b8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((float_to_ubyte(src[0])) & 0xff) << 8; + value |= ((float_to_ubyte(src[1])) & 0xff) << 16; + value |= (float_to_ubyte(src[2])) << 24; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_x8r8g8b8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + r = (value >> 8) & 0xff; + g = (value >> 16) & 0xff; + b = value >> 24; + dst[0] = ubyte_to_float(r); /* r */ + dst[1] = ubyte_to_float(g); /* g */ + dst[2] = ubyte_to_float(b); /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_x8r8g8b8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + r = (value >> 8) & 0xff; + g = (value >> 16) & 0xff; + b = value >> 24; + dst[0] = r; /* r */ + dst[1] = g; /* g */ + dst[2] = b; /* b */ + dst[3] = 255; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_x8r8g8b8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((src[0]) & 0xff) << 8; + value |= ((src[1]) & 0xff) << 16; + value |= (src[2]) << 24; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_a8b8g8r8_unorm { + uint32_t value; + struct { + uint8_t a; + uint8_t b; + uint8_t g; + uint8_t r; + } chan; +}; + +static INLINE void +util_format_a8b8g8r8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t a; + uint32_t b; + uint32_t g; + uint32_t r; + a = (value) & 0xff; + b = (value >> 8) & 0xff; + g = (value >> 16) & 0xff; + r = value >> 24; + dst[0] = ubyte_to_float(r); /* r */ + dst[1] = ubyte_to_float(g); /* g */ + dst[2] = ubyte_to_float(b); /* b */ + dst[3] = ubyte_to_float(a); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a8b8g8r8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (float_to_ubyte(src[3])) & 0xff; + value |= ((float_to_ubyte(src[2])) & 0xff) << 8; + value |= ((float_to_ubyte(src[1])) & 0xff) << 16; + value |= (float_to_ubyte(src[0])) << 24; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_a8b8g8r8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t a; + uint32_t b; + uint32_t g; + uint32_t r; + a = (value) & 0xff; + b = (value >> 8) & 0xff; + g = (value >> 16) & 0xff; + r = value >> 24; + dst[0] = ubyte_to_float(r); /* r */ + dst[1] = ubyte_to_float(g); /* g */ + dst[2] = ubyte_to_float(b); /* b */ + dst[3] = ubyte_to_float(a); /* a */ +} + +static INLINE void +util_format_a8b8g8r8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t a; + uint32_t b; + uint32_t g; + uint32_t r; + a = (value) & 0xff; + b = (value >> 8) & 0xff; + g = (value >> 16) & 0xff; + r = value >> 24; + dst[0] = r; /* r */ + dst[1] = g; /* g */ + dst[2] = b; /* b */ + dst[3] = a; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a8b8g8r8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (src[3]) & 0xff; + value |= ((src[2]) & 0xff) << 8; + value |= ((src[1]) & 0xff) << 16; + value |= (src[0]) << 24; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_x8b8g8r8_unorm { + uint32_t value; + struct { + uint8_t x; + uint8_t b; + uint8_t g; + uint8_t r; + } chan; +}; + +static INLINE void +util_format_x8b8g8r8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t b; + uint32_t g; + uint32_t r; + b = (value >> 8) & 0xff; + g = (value >> 16) & 0xff; + r = value >> 24; + dst[0] = ubyte_to_float(r); /* r */ + dst[1] = ubyte_to_float(g); /* g */ + dst[2] = ubyte_to_float(b); /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_x8b8g8r8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((float_to_ubyte(src[2])) & 0xff) << 8; + value |= ((float_to_ubyte(src[1])) & 0xff) << 16; + value |= (float_to_ubyte(src[0])) << 24; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_x8b8g8r8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t b; + uint32_t g; + uint32_t r; + b = (value >> 8) & 0xff; + g = (value >> 16) & 0xff; + r = value >> 24; + dst[0] = ubyte_to_float(r); /* r */ + dst[1] = ubyte_to_float(g); /* g */ + dst[2] = ubyte_to_float(b); /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_x8b8g8r8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t b; + uint32_t g; + uint32_t r; + b = (value >> 8) & 0xff; + g = (value >> 16) & 0xff; + r = value >> 24; + dst[0] = r; /* r */ + dst[1] = g; /* g */ + dst[2] = b; /* b */ + dst[3] = 255; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_x8b8g8r8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((src[2]) & 0xff) << 8; + value |= ((src[1]) & 0xff) << 16; + value |= (src[0]) << 24; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8g8b8x8_unorm { + uint32_t value; + struct { + uint8_t r; + uint8_t g; + uint8_t b; + uint8_t x; + } chan; +}; + +static INLINE void +util_format_r8g8b8x8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + r = (value) & 0xff; + g = (value >> 8) & 0xff; + b = (value >> 16) & 0xff; + dst[0] = ubyte_to_float(r); /* r */ + dst[1] = ubyte_to_float(g); /* g */ + dst[2] = ubyte_to_float(b); /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8x8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (float_to_ubyte(src[0])) & 0xff; + value |= ((float_to_ubyte(src[1])) & 0xff) << 8; + value |= ((float_to_ubyte(src[2])) & 0xff) << 16; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8g8b8x8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + r = (value) & 0xff; + g = (value >> 8) & 0xff; + b = (value >> 16) & 0xff; + dst[0] = ubyte_to_float(r); /* r */ + dst[1] = ubyte_to_float(g); /* g */ + dst[2] = ubyte_to_float(b); /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r8g8b8x8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + r = (value) & 0xff; + g = (value >> 8) & 0xff; + b = (value >> 16) & 0xff; + dst[0] = r; /* r */ + dst[1] = g; /* g */ + dst[2] = b; /* b */ + dst[3] = 255; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8x8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (src[0]) & 0xff; + value |= ((src[1]) & 0xff) << 8; + value |= ((src[2]) & 0xff) << 16; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_b5g5r5x1_unorm { + uint16_t value; + struct { + unsigned b:5; + unsigned g:5; + unsigned r:5; + unsigned x:1; + } chan; +}; + +static INLINE void +util_format_b5g5r5x1_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t b; + uint16_t g; + uint16_t r; + b = (value) & 0x1f; + g = (value >> 5) & 0x1f; + r = (value >> 10) & 0x1f; + dst[0] = (float)(r * (1.0f/0x1f)); /* r */ + dst[1] = (float)(g * (1.0f/0x1f)); /* g */ + dst[2] = (float)(b * (1.0f/0x1f)); /* b */ + dst[3] = 1; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_b5g5r5x1_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= ((uint16_t)util_iround(CLAMP(src[2], 0, 1) * 0x1f)) & 0x1f; + value |= (((uint16_t)util_iround(CLAMP(src[1], 0, 1) * 0x1f)) & 0x1f) << 5; + value |= (((uint16_t)util_iround(CLAMP(src[0], 0, 1) * 0x1f)) & 0x1f) << 10; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_b5g5r5x1_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + uint16_t b; + uint16_t g; + uint16_t r; + b = (value) & 0x1f; + g = (value >> 5) & 0x1f; + r = (value >> 10) & 0x1f; + dst[0] = (float)(r * (1.0f/0x1f)); /* r */ + dst[1] = (float)(g * (1.0f/0x1f)); /* g */ + dst[2] = (float)(b * (1.0f/0x1f)); /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_b5g5r5x1_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t b; + uint16_t g; + uint16_t r; + b = (value) & 0x1f; + g = (value >> 5) & 0x1f; + r = (value >> 10) & 0x1f; + dst[0] = (uint8_t)(((uint32_t)r) * 0xff / 0x1f); /* r */ + dst[1] = (uint8_t)(((uint32_t)g) * 0xff / 0x1f); /* g */ + dst[2] = (uint8_t)(((uint32_t)b) * 0xff / 0x1f); /* b */ + dst[3] = 255; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_b5g5r5x1_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= ((uint16_t)(src[2] >> 3)) & 0x1f; + value |= (((uint16_t)(src[1] >> 3)) & 0x1f) << 5; + value |= (((uint16_t)(src[0] >> 3)) & 0x1f) << 10; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_b5g5r5a1_unorm { + uint16_t value; + struct { + unsigned b:5; + unsigned g:5; + unsigned r:5; + unsigned a:1; + } chan; +}; + +static INLINE void +util_format_b5g5r5a1_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t b; + uint16_t g; + uint16_t r; + uint16_t a; + b = (value) & 0x1f; + g = (value >> 5) & 0x1f; + r = (value >> 10) & 0x1f; + a = value >> 15; + dst[0] = (float)(r * (1.0f/0x1f)); /* r */ + dst[1] = (float)(g * (1.0f/0x1f)); /* g */ + dst[2] = (float)(b * (1.0f/0x1f)); /* b */ + dst[3] = (float)(a * (1.0f/0x1)); /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_b5g5r5a1_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= ((uint16_t)util_iround(CLAMP(src[2], 0, 1) * 0x1f)) & 0x1f; + value |= (((uint16_t)util_iround(CLAMP(src[1], 0, 1) * 0x1f)) & 0x1f) << 5; + value |= (((uint16_t)util_iround(CLAMP(src[0], 0, 1) * 0x1f)) & 0x1f) << 10; + value |= ((uint16_t)util_iround(CLAMP(src[3], 0, 1) * 0x1)) << 15; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_b5g5r5a1_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + uint16_t b; + uint16_t g; + uint16_t r; + uint16_t a; + b = (value) & 0x1f; + g = (value >> 5) & 0x1f; + r = (value >> 10) & 0x1f; + a = value >> 15; + dst[0] = (float)(r * (1.0f/0x1f)); /* r */ + dst[1] = (float)(g * (1.0f/0x1f)); /* g */ + dst[2] = (float)(b * (1.0f/0x1f)); /* b */ + dst[3] = (float)(a * (1.0f/0x1)); /* a */ +} + +static INLINE void +util_format_b5g5r5a1_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t b; + uint16_t g; + uint16_t r; + uint16_t a; + b = (value) & 0x1f; + g = (value >> 5) & 0x1f; + r = (value >> 10) & 0x1f; + a = value >> 15; + dst[0] = (uint8_t)(((uint32_t)r) * 0xff / 0x1f); /* r */ + dst[1] = (uint8_t)(((uint32_t)g) * 0xff / 0x1f); /* g */ + dst[2] = (uint8_t)(((uint32_t)b) * 0xff / 0x1f); /* b */ + dst[3] = (uint8_t)(((uint32_t)a) * 0xff / 0x1); /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_b5g5r5a1_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= ((uint16_t)(src[2] >> 3)) & 0x1f; + value |= (((uint16_t)(src[1] >> 3)) & 0x1f) << 5; + value |= (((uint16_t)(src[0] >> 3)) & 0x1f) << 10; + value |= ((uint16_t)(src[3] >> 7)) << 15; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_b4g4r4a4_unorm { + uint16_t value; + struct { + unsigned b:4; + unsigned g:4; + unsigned r:4; + unsigned a:4; + } chan; +}; + +static INLINE void +util_format_b4g4r4a4_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t b; + uint16_t g; + uint16_t r; + uint16_t a; + b = (value) & 0xf; + g = (value >> 4) & 0xf; + r = (value >> 8) & 0xf; + a = value >> 12; + dst[0] = (float)(r * (1.0f/0xf)); /* r */ + dst[1] = (float)(g * (1.0f/0xf)); /* g */ + dst[2] = (float)(b * (1.0f/0xf)); /* b */ + dst[3] = (float)(a * (1.0f/0xf)); /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_b4g4r4a4_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= ((uint16_t)util_iround(CLAMP(src[2], 0, 1) * 0xf)) & 0xf; + value |= (((uint16_t)util_iround(CLAMP(src[1], 0, 1) * 0xf)) & 0xf) << 4; + value |= (((uint16_t)util_iround(CLAMP(src[0], 0, 1) * 0xf)) & 0xf) << 8; + value |= ((uint16_t)util_iround(CLAMP(src[3], 0, 1) * 0xf)) << 12; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_b4g4r4a4_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + uint16_t b; + uint16_t g; + uint16_t r; + uint16_t a; + b = (value) & 0xf; + g = (value >> 4) & 0xf; + r = (value >> 8) & 0xf; + a = value >> 12; + dst[0] = (float)(r * (1.0f/0xf)); /* r */ + dst[1] = (float)(g * (1.0f/0xf)); /* g */ + dst[2] = (float)(b * (1.0f/0xf)); /* b */ + dst[3] = (float)(a * (1.0f/0xf)); /* a */ +} + +static INLINE void +util_format_b4g4r4a4_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t b; + uint16_t g; + uint16_t r; + uint16_t a; + b = (value) & 0xf; + g = (value >> 4) & 0xf; + r = (value >> 8) & 0xf; + a = value >> 12; + dst[0] = (uint8_t)(((uint32_t)r) * 0xff / 0xf); /* r */ + dst[1] = (uint8_t)(((uint32_t)g) * 0xff / 0xf); /* g */ + dst[2] = (uint8_t)(((uint32_t)b) * 0xff / 0xf); /* b */ + dst[3] = (uint8_t)(((uint32_t)a) * 0xff / 0xf); /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_b4g4r4a4_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= ((uint16_t)(src[2] >> 4)) & 0xf; + value |= (((uint16_t)(src[1] >> 4)) & 0xf) << 4; + value |= (((uint16_t)(src[0] >> 4)) & 0xf) << 8; + value |= ((uint16_t)(src[3] >> 4)) << 12; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_b4g4r4x4_unorm { + uint16_t value; + struct { + unsigned b:4; + unsigned g:4; + unsigned r:4; + unsigned x:4; + } chan; +}; + +static INLINE void +util_format_b4g4r4x4_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t b; + uint16_t g; + uint16_t r; + b = (value) & 0xf; + g = (value >> 4) & 0xf; + r = (value >> 8) & 0xf; + dst[0] = (float)(r * (1.0f/0xf)); /* r */ + dst[1] = (float)(g * (1.0f/0xf)); /* g */ + dst[2] = (float)(b * (1.0f/0xf)); /* b */ + dst[3] = 1; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_b4g4r4x4_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= ((uint16_t)util_iround(CLAMP(src[2], 0, 1) * 0xf)) & 0xf; + value |= (((uint16_t)util_iround(CLAMP(src[1], 0, 1) * 0xf)) & 0xf) << 4; + value |= (((uint16_t)util_iround(CLAMP(src[0], 0, 1) * 0xf)) & 0xf) << 8; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_b4g4r4x4_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + uint16_t b; + uint16_t g; + uint16_t r; + b = (value) & 0xf; + g = (value >> 4) & 0xf; + r = (value >> 8) & 0xf; + dst[0] = (float)(r * (1.0f/0xf)); /* r */ + dst[1] = (float)(g * (1.0f/0xf)); /* g */ + dst[2] = (float)(b * (1.0f/0xf)); /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_b4g4r4x4_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t b; + uint16_t g; + uint16_t r; + b = (value) & 0xf; + g = (value >> 4) & 0xf; + r = (value >> 8) & 0xf; + dst[0] = (uint8_t)(((uint32_t)r) * 0xff / 0xf); /* r */ + dst[1] = (uint8_t)(((uint32_t)g) * 0xff / 0xf); /* g */ + dst[2] = (uint8_t)(((uint32_t)b) * 0xff / 0xf); /* b */ + dst[3] = 255; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_b4g4r4x4_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= ((uint16_t)(src[2] >> 4)) & 0xf; + value |= (((uint16_t)(src[1] >> 4)) & 0xf) << 4; + value |= (((uint16_t)(src[0] >> 4)) & 0xf) << 8; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_b5g6r5_unorm { + uint16_t value; + struct { + unsigned b:5; + unsigned g:6; + unsigned r:5; + } chan; +}; + +static INLINE void +util_format_b5g6r5_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t b; + uint16_t g; + uint16_t r; + b = (value) & 0x1f; + g = (value >> 5) & 0x3f; + r = value >> 11; + dst[0] = (float)(r * (1.0f/0x1f)); /* r */ + dst[1] = (float)(g * (1.0f/0x3f)); /* g */ + dst[2] = (float)(b * (1.0f/0x1f)); /* b */ + dst[3] = 1; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_b5g6r5_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= ((uint16_t)util_iround(CLAMP(src[2], 0, 1) * 0x1f)) & 0x1f; + value |= (((uint16_t)util_iround(CLAMP(src[1], 0, 1) * 0x3f)) & 0x3f) << 5; + value |= ((uint16_t)util_iround(CLAMP(src[0], 0, 1) * 0x1f)) << 11; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_b5g6r5_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + uint16_t b; + uint16_t g; + uint16_t r; + b = (value) & 0x1f; + g = (value >> 5) & 0x3f; + r = value >> 11; + dst[0] = (float)(r * (1.0f/0x1f)); /* r */ + dst[1] = (float)(g * (1.0f/0x3f)); /* g */ + dst[2] = (float)(b * (1.0f/0x1f)); /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_b5g6r5_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t b; + uint16_t g; + uint16_t r; + b = (value) & 0x1f; + g = (value >> 5) & 0x3f; + r = value >> 11; + dst[0] = (uint8_t)(((uint32_t)r) * 0xff / 0x1f); /* r */ + dst[1] = (uint8_t)(((uint32_t)g) * 0xff / 0x3f); /* g */ + dst[2] = (uint8_t)(((uint32_t)b) * 0xff / 0x1f); /* b */ + dst[3] = 255; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_b5g6r5_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= ((uint16_t)(src[2] >> 3)) & 0x1f; + value |= (((uint16_t)(src[1] >> 2)) & 0x3f) << 5; + value |= ((uint16_t)(src[0] >> 3)) << 11; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r10g10b10a2_unorm { + uint32_t value; + struct { + unsigned r:10; + unsigned g:10; + unsigned b:10; + unsigned a:2; + } chan; +}; + +static INLINE void +util_format_r10g10b10a2_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + uint32_t a; + r = (value) & 0x3ff; + g = (value >> 10) & 0x3ff; + b = (value >> 20) & 0x3ff; + a = value >> 30; + dst[0] = (float)(r * (1.0f/0x3ff)); /* r */ + dst[1] = (float)(g * (1.0f/0x3ff)); /* g */ + dst[2] = (float)(b * (1.0f/0x3ff)); /* b */ + dst[3] = (float)(a * (1.0f/0x3)); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r10g10b10a2_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint32_t)util_iround(CLAMP(src[0], 0, 1) * 0x3ff)) & 0x3ff; + value |= (((uint32_t)util_iround(CLAMP(src[1], 0, 1) * 0x3ff)) & 0x3ff) << 10; + value |= (((uint32_t)util_iround(CLAMP(src[2], 0, 1) * 0x3ff)) & 0x3ff) << 20; + value |= ((uint32_t)util_iround(CLAMP(src[3], 0, 1) * 0x3)) << 30; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r10g10b10a2_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + uint32_t a; + r = (value) & 0x3ff; + g = (value >> 10) & 0x3ff; + b = (value >> 20) & 0x3ff; + a = value >> 30; + dst[0] = (float)(r * (1.0f/0x3ff)); /* r */ + dst[1] = (float)(g * (1.0f/0x3ff)); /* g */ + dst[2] = (float)(b * (1.0f/0x3ff)); /* b */ + dst[3] = (float)(a * (1.0f/0x3)); /* a */ +} + +static INLINE void +util_format_r10g10b10a2_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + uint32_t a; + r = (value) & 0x3ff; + g = (value >> 10) & 0x3ff; + b = (value >> 20) & 0x3ff; + a = value >> 30; + dst[0] = (uint8_t)(r >> 2); /* r */ + dst[1] = (uint8_t)(g >> 2); /* g */ + dst[2] = (uint8_t)(b >> 2); /* b */ + dst[3] = (uint8_t)(((uint32_t)a) * 0xff / 0x3); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r10g10b10a2_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint32_t)(((uint32_t)src[0]) * 0x3ff / 0xff)) & 0x3ff; + value |= (((uint32_t)(((uint32_t)src[1]) * 0x3ff / 0xff)) & 0x3ff) << 10; + value |= (((uint32_t)(((uint32_t)src[2]) * 0x3ff / 0xff)) & 0x3ff) << 20; + value |= ((uint32_t)(src[3] >> 6)) << 30; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_b10g10r10a2_unorm { + uint32_t value; + struct { + unsigned b:10; + unsigned g:10; + unsigned r:10; + unsigned a:2; + } chan; +}; + +static INLINE void +util_format_b10g10r10a2_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t b; + uint32_t g; + uint32_t r; + uint32_t a; + b = (value) & 0x3ff; + g = (value >> 10) & 0x3ff; + r = (value >> 20) & 0x3ff; + a = value >> 30; + dst[0] = (float)(r * (1.0f/0x3ff)); /* r */ + dst[1] = (float)(g * (1.0f/0x3ff)); /* g */ + dst[2] = (float)(b * (1.0f/0x3ff)); /* b */ + dst[3] = (float)(a * (1.0f/0x3)); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_b10g10r10a2_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint32_t)util_iround(CLAMP(src[2], 0, 1) * 0x3ff)) & 0x3ff; + value |= (((uint32_t)util_iround(CLAMP(src[1], 0, 1) * 0x3ff)) & 0x3ff) << 10; + value |= (((uint32_t)util_iround(CLAMP(src[0], 0, 1) * 0x3ff)) & 0x3ff) << 20; + value |= ((uint32_t)util_iround(CLAMP(src[3], 0, 1) * 0x3)) << 30; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_b10g10r10a2_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t b; + uint32_t g; + uint32_t r; + uint32_t a; + b = (value) & 0x3ff; + g = (value >> 10) & 0x3ff; + r = (value >> 20) & 0x3ff; + a = value >> 30; + dst[0] = (float)(r * (1.0f/0x3ff)); /* r */ + dst[1] = (float)(g * (1.0f/0x3ff)); /* g */ + dst[2] = (float)(b * (1.0f/0x3ff)); /* b */ + dst[3] = (float)(a * (1.0f/0x3)); /* a */ +} + +static INLINE void +util_format_b10g10r10a2_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t b; + uint32_t g; + uint32_t r; + uint32_t a; + b = (value) & 0x3ff; + g = (value >> 10) & 0x3ff; + r = (value >> 20) & 0x3ff; + a = value >> 30; + dst[0] = (uint8_t)(r >> 2); /* r */ + dst[1] = (uint8_t)(g >> 2); /* g */ + dst[2] = (uint8_t)(b >> 2); /* b */ + dst[3] = (uint8_t)(((uint32_t)a) * 0xff / 0x3); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_b10g10r10a2_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint32_t)(((uint32_t)src[2]) * 0x3ff / 0xff)) & 0x3ff; + value |= (((uint32_t)(((uint32_t)src[1]) * 0x3ff / 0xff)) & 0x3ff) << 10; + value |= (((uint32_t)(((uint32_t)src[0]) * 0x3ff / 0xff)) & 0x3ff) << 20; + value |= ((uint32_t)(src[3] >> 6)) << 30; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_b2g3r3_unorm { + uint8_t value; + struct { + unsigned b:2; + unsigned g:3; + unsigned r:3; + } chan; +}; + +static INLINE void +util_format_b2g3r3_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + uint8_t b; + uint8_t g; + uint8_t r; + b = (value) & 0x3; + g = (value >> 2) & 0x7; + r = value >> 5; + dst[0] = (float)(r * (1.0f/0x7)); /* r */ + dst[1] = (float)(g * (1.0f/0x7)); /* g */ + dst[2] = (float)(b * (1.0f/0x3)); /* b */ + dst[3] = 1; /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_b2g3r3_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= ((uint8_t)util_iround(CLAMP(src[2], 0, 1) * 0x3)) & 0x3; + value |= (((uint8_t)util_iround(CLAMP(src[1], 0, 1) * 0x7)) & 0x7) << 2; + value |= ((uint8_t)util_iround(CLAMP(src[0], 0, 1) * 0x7)) << 5; + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_b2g3r3_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint8_t value = *(const uint8_t *)src; + uint8_t b; + uint8_t g; + uint8_t r; + b = (value) & 0x3; + g = (value >> 2) & 0x7; + r = value >> 5; + dst[0] = (float)(r * (1.0f/0x7)); /* r */ + dst[1] = (float)(g * (1.0f/0x7)); /* g */ + dst[2] = (float)(b * (1.0f/0x3)); /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_b2g3r3_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + uint8_t b; + uint8_t g; + uint8_t r; + b = (value) & 0x3; + g = (value >> 2) & 0x7; + r = value >> 5; + dst[0] = (uint8_t)(((uint32_t)r) * 0xff / 0x7); /* r */ + dst[1] = (uint8_t)(((uint32_t)g) * 0xff / 0x7); /* g */ + dst[2] = (uint8_t)(((uint32_t)b) * 0xff / 0x3); /* b */ + dst[3] = 255; /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_b2g3r3_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= ((uint8_t)(src[2] >> 6)) & 0x3; + value |= (((uint8_t)(src[1] >> 5)) & 0x7) << 2; + value |= ((uint8_t)(src[0] >> 5)) << 5; + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_l8_unorm { + uint8_t value; + struct { + uint8_t rgb; + } chan; +}; + +static INLINE void +util_format_l8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + uint8_t rgb; + rgb = value; + dst[0] = ubyte_to_float(rgb); /* r */ + dst[1] = ubyte_to_float(rgb); /* g */ + dst[2] = ubyte_to_float(rgb); /* b */ + dst[3] = 1; /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= float_to_ubyte(src[0]); + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_l8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint8_t value = *(const uint8_t *)src; + uint8_t rgb; + rgb = value; + dst[0] = ubyte_to_float(rgb); /* r */ + dst[1] = ubyte_to_float(rgb); /* g */ + dst[2] = ubyte_to_float(rgb); /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_l8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + uint8_t rgb; + rgb = value; + dst[0] = rgb; /* r */ + dst[1] = rgb; /* g */ + dst[2] = rgb; /* b */ + dst[3] = 255; /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= src[0]; + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_a8_unorm { + uint8_t value; + struct { + uint8_t a; + } chan; +}; + +static INLINE void +util_format_a8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + uint8_t a; + a = value; + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = ubyte_to_float(a); /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= float_to_ubyte(src[3]); + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_a8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint8_t value = *(const uint8_t *)src; + uint8_t a; + a = value; + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = ubyte_to_float(a); /* a */ +} + +static INLINE void +util_format_a8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + uint8_t a; + a = value; + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = a; /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= src[3]; + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_i8_unorm { + uint8_t value; + struct { + uint8_t rgba; + } chan; +}; + +static INLINE void +util_format_i8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + uint8_t rgba; + rgba = value; + dst[0] = ubyte_to_float(rgba); /* r */ + dst[1] = ubyte_to_float(rgba); /* g */ + dst[2] = ubyte_to_float(rgba); /* b */ + dst[3] = ubyte_to_float(rgba); /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_i8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= float_to_ubyte(src[0]); + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_i8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint8_t value = *(const uint8_t *)src; + uint8_t rgba; + rgba = value; + dst[0] = ubyte_to_float(rgba); /* r */ + dst[1] = ubyte_to_float(rgba); /* g */ + dst[2] = ubyte_to_float(rgba); /* b */ + dst[3] = ubyte_to_float(rgba); /* a */ +} + +static INLINE void +util_format_i8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + uint8_t rgba; + rgba = value; + dst[0] = rgba; /* r */ + dst[1] = rgba; /* g */ + dst[2] = rgba; /* b */ + dst[3] = rgba; /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_i8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= src[0]; + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_l4a4_unorm { + uint8_t value; + struct { + unsigned rgb:4; + unsigned a:4; + } chan; +}; + +static INLINE void +util_format_l4a4_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + uint8_t rgb; + uint8_t a; + rgb = (value) & 0xf; + a = value >> 4; + dst[0] = (float)(rgb * (1.0f/0xf)); /* r */ + dst[1] = (float)(rgb * (1.0f/0xf)); /* g */ + dst[2] = (float)(rgb * (1.0f/0xf)); /* b */ + dst[3] = (float)(a * (1.0f/0xf)); /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l4a4_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= ((uint8_t)util_iround(CLAMP(src[0], 0, 1) * 0xf)) & 0xf; + value |= ((uint8_t)util_iround(CLAMP(src[3], 0, 1) * 0xf)) << 4; + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_l4a4_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint8_t value = *(const uint8_t *)src; + uint8_t rgb; + uint8_t a; + rgb = (value) & 0xf; + a = value >> 4; + dst[0] = (float)(rgb * (1.0f/0xf)); /* r */ + dst[1] = (float)(rgb * (1.0f/0xf)); /* g */ + dst[2] = (float)(rgb * (1.0f/0xf)); /* b */ + dst[3] = (float)(a * (1.0f/0xf)); /* a */ +} + +static INLINE void +util_format_l4a4_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + uint8_t rgb; + uint8_t a; + rgb = (value) & 0xf; + a = value >> 4; + dst[0] = (uint8_t)(((uint32_t)rgb) * 0xff / 0xf); /* r */ + dst[1] = (uint8_t)(((uint32_t)rgb) * 0xff / 0xf); /* g */ + dst[2] = (uint8_t)(((uint32_t)rgb) * 0xff / 0xf); /* b */ + dst[3] = (uint8_t)(((uint32_t)a) * 0xff / 0xf); /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l4a4_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= ((uint8_t)(src[0] >> 4)) & 0xf; + value |= ((uint8_t)(src[3] >> 4)) << 4; + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_l8a8_unorm { + uint16_t value; + struct { + uint8_t rgb; + uint8_t a; + } chan; +}; + +static INLINE void +util_format_l8a8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t rgb; + uint16_t a; + rgb = (value) & 0xff; + a = value >> 8; + dst[0] = ubyte_to_float(rgb); /* r */ + dst[1] = ubyte_to_float(rgb); /* g */ + dst[2] = ubyte_to_float(rgb); /* b */ + dst[3] = ubyte_to_float(a); /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l8a8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (float_to_ubyte(src[0])) & 0xff; + value |= (float_to_ubyte(src[3])) << 8; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_l8a8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + uint16_t rgb; + uint16_t a; + rgb = (value) & 0xff; + a = value >> 8; + dst[0] = ubyte_to_float(rgb); /* r */ + dst[1] = ubyte_to_float(rgb); /* g */ + dst[2] = ubyte_to_float(rgb); /* b */ + dst[3] = ubyte_to_float(a); /* a */ +} + +static INLINE void +util_format_l8a8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t rgb; + uint16_t a; + rgb = (value) & 0xff; + a = value >> 8; + dst[0] = rgb; /* r */ + dst[1] = rgb; /* g */ + dst[2] = rgb; /* b */ + dst[3] = a; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l8a8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (src[0]) & 0xff; + value |= (src[3]) << 8; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_l16_unorm { + uint16_t value; + struct { + uint16_t rgb; + } chan; +}; + +static INLINE void +util_format_l16_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t rgb; + rgb = value; + dst[0] = (float)(rgb * (1.0f/0xffff)); /* r */ + dst[1] = (float)(rgb * (1.0f/0xffff)); /* g */ + dst[2] = (float)(rgb * (1.0f/0xffff)); /* b */ + dst[3] = 1; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l16_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)util_iround(CLAMP(src[0], 0, 1) * 0xffff); + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_l16_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + uint16_t rgb; + rgb = value; + dst[0] = (float)(rgb * (1.0f/0xffff)); /* r */ + dst[1] = (float)(rgb * (1.0f/0xffff)); /* g */ + dst[2] = (float)(rgb * (1.0f/0xffff)); /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_l16_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t rgb; + rgb = value; + dst[0] = (uint8_t)(rgb >> 8); /* r */ + dst[1] = (uint8_t)(rgb >> 8); /* g */ + dst[2] = (uint8_t)(rgb >> 8); /* b */ + dst[3] = 255; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l16_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)(((uint32_t)src[0]) * 0xffff / 0xff); + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_a16_unorm { + uint16_t value; + struct { + uint16_t a; + } chan; +}; + +static INLINE void +util_format_a16_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t a; + a = value; + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (float)(a * (1.0f/0xffff)); /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a16_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)util_iround(CLAMP(src[3], 0, 1) * 0xffff); + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_a16_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + uint16_t a; + a = value; + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (float)(a * (1.0f/0xffff)); /* a */ +} + +static INLINE void +util_format_a16_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t a; + a = value; + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (uint8_t)(a >> 8); /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a16_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)(((uint32_t)src[3]) * 0xffff / 0xff); + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_i16_unorm { + uint16_t value; + struct { + uint16_t rgba; + } chan; +}; + +static INLINE void +util_format_i16_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t rgba; + rgba = value; + dst[0] = (float)(rgba * (1.0f/0xffff)); /* r */ + dst[1] = (float)(rgba * (1.0f/0xffff)); /* g */ + dst[2] = (float)(rgba * (1.0f/0xffff)); /* b */ + dst[3] = (float)(rgba * (1.0f/0xffff)); /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_i16_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)util_iround(CLAMP(src[0], 0, 1) * 0xffff); + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_i16_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + uint16_t rgba; + rgba = value; + dst[0] = (float)(rgba * (1.0f/0xffff)); /* r */ + dst[1] = (float)(rgba * (1.0f/0xffff)); /* g */ + dst[2] = (float)(rgba * (1.0f/0xffff)); /* b */ + dst[3] = (float)(rgba * (1.0f/0xffff)); /* a */ +} + +static INLINE void +util_format_i16_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t rgba; + rgba = value; + dst[0] = (uint8_t)(rgba >> 8); /* r */ + dst[1] = (uint8_t)(rgba >> 8); /* g */ + dst[2] = (uint8_t)(rgba >> 8); /* b */ + dst[3] = (uint8_t)(rgba >> 8); /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_i16_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)(((uint32_t)src[0]) * 0xffff / 0xff); + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_l16a16_unorm { + uint32_t value; + struct { + uint16_t rgb; + uint16_t a; + } chan; +}; + +static INLINE void +util_format_l16a16_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t rgb; + uint32_t a; + rgb = (value) & 0xffff; + a = value >> 16; + dst[0] = (float)(rgb * (1.0f/0xffff)); /* r */ + dst[1] = (float)(rgb * (1.0f/0xffff)); /* g */ + dst[2] = (float)(rgb * (1.0f/0xffff)); /* b */ + dst[3] = (float)(a * (1.0f/0xffff)); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l16a16_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint16_t)util_iround(CLAMP(src[0], 0, 1) * 0xffff)) & 0xffff; + value |= ((uint16_t)util_iround(CLAMP(src[3], 0, 1) * 0xffff)) << 16; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_l16a16_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t rgb; + uint32_t a; + rgb = (value) & 0xffff; + a = value >> 16; + dst[0] = (float)(rgb * (1.0f/0xffff)); /* r */ + dst[1] = (float)(rgb * (1.0f/0xffff)); /* g */ + dst[2] = (float)(rgb * (1.0f/0xffff)); /* b */ + dst[3] = (float)(a * (1.0f/0xffff)); /* a */ +} + +static INLINE void +util_format_l16a16_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t rgb; + uint32_t a; + rgb = (value) & 0xffff; + a = value >> 16; + dst[0] = (uint8_t)(rgb >> 8); /* r */ + dst[1] = (uint8_t)(rgb >> 8); /* g */ + dst[2] = (uint8_t)(rgb >> 8); /* b */ + dst[3] = (uint8_t)(a >> 8); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l16a16_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint16_t)(((uint32_t)src[0]) * 0xffff / 0xff)) & 0xffff; + value |= ((uint16_t)(((uint32_t)src[3]) * 0xffff / 0xff)) << 16; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_a8_snorm { + uint8_t value; + struct { + int8_t a; + } chan; +}; + +static INLINE void +util_format_a8_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + int8_t a; + a = (int8_t)(value) ; + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (float)(a * (1.0f/0x7f)); /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a8_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= (uint8_t)((int8_t)util_iround(CLAMP(src[3], -1, 1) * 0x7f)) ; + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_a8_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint8_t value = *(const uint8_t *)src; + int8_t a; + a = (int8_t)(value) ; + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (float)(a * (1.0f/0x7f)); /* a */ +} + +static INLINE void +util_format_a8_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + int8_t a; + a = (int8_t)(value) ; + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (uint8_t)(((uint32_t)MAX2(a, 0)) * 0xff / 0x7f); /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a8_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= (uint8_t)((int8_t)(src[3] >> 1)) ; + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_l8_snorm { + uint8_t value; + struct { + int8_t rgb; + } chan; +}; + +static INLINE void +util_format_l8_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + int8_t rgb; + rgb = (int8_t)(value) ; + dst[0] = (float)(rgb * (1.0f/0x7f)); /* r */ + dst[1] = (float)(rgb * (1.0f/0x7f)); /* g */ + dst[2] = (float)(rgb * (1.0f/0x7f)); /* b */ + dst[3] = 1; /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l8_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= (uint8_t)((int8_t)util_iround(CLAMP(src[0], -1, 1) * 0x7f)) ; + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_l8_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint8_t value = *(const uint8_t *)src; + int8_t rgb; + rgb = (int8_t)(value) ; + dst[0] = (float)(rgb * (1.0f/0x7f)); /* r */ + dst[1] = (float)(rgb * (1.0f/0x7f)); /* g */ + dst[2] = (float)(rgb * (1.0f/0x7f)); /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_l8_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + int8_t rgb; + rgb = (int8_t)(value) ; + dst[0] = (uint8_t)(((uint32_t)MAX2(rgb, 0)) * 0xff / 0x7f); /* r */ + dst[1] = (uint8_t)(((uint32_t)MAX2(rgb, 0)) * 0xff / 0x7f); /* g */ + dst[2] = (uint8_t)(((uint32_t)MAX2(rgb, 0)) * 0xff / 0x7f); /* b */ + dst[3] = 255; /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l8_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= (uint8_t)((int8_t)(src[0] >> 1)) ; + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_l8a8_snorm { + uint16_t value; + struct { + int8_t rgb; + int8_t a; + } chan; +}; + +static INLINE void +util_format_l8a8_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + int16_t rgb; + int16_t a; + rgb = ((int16_t)(value << 8) ) >> 8; + a = ((int16_t)(value) ) >> 8; + dst[0] = (float)(rgb * (1.0f/0x7f)); /* r */ + dst[1] = (float)(rgb * (1.0f/0x7f)); /* g */ + dst[2] = (float)(rgb * (1.0f/0x7f)); /* b */ + dst[3] = (float)(a * (1.0f/0x7f)); /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l8a8_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)(((int8_t)util_iround(CLAMP(src[0], -1, 1) * 0x7f)) & 0xff) ; + value |= (uint16_t)(((int8_t)util_iround(CLAMP(src[3], -1, 1) * 0x7f)) << 8) ; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_l8a8_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + int16_t rgb; + int16_t a; + rgb = ((int16_t)(value << 8) ) >> 8; + a = ((int16_t)(value) ) >> 8; + dst[0] = (float)(rgb * (1.0f/0x7f)); /* r */ + dst[1] = (float)(rgb * (1.0f/0x7f)); /* g */ + dst[2] = (float)(rgb * (1.0f/0x7f)); /* b */ + dst[3] = (float)(a * (1.0f/0x7f)); /* a */ +} + +static INLINE void +util_format_l8a8_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + int16_t rgb; + int16_t a; + rgb = ((int16_t)(value << 8) ) >> 8; + a = ((int16_t)(value) ) >> 8; + dst[0] = (uint8_t)(((uint32_t)MAX2(rgb, 0)) * 0xff / 0x7f); /* r */ + dst[1] = (uint8_t)(((uint32_t)MAX2(rgb, 0)) * 0xff / 0x7f); /* g */ + dst[2] = (uint8_t)(((uint32_t)MAX2(rgb, 0)) * 0xff / 0x7f); /* b */ + dst[3] = (uint8_t)(((uint32_t)MAX2(a, 0)) * 0xff / 0x7f); /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l8a8_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)(((int8_t)(src[0] >> 1)) & 0xff) ; + value |= (uint16_t)(((int8_t)(src[3] >> 1)) << 8) ; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_i8_snorm { + uint8_t value; + struct { + int8_t rgba; + } chan; +}; + +static INLINE void +util_format_i8_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + int8_t rgba; + rgba = (int8_t)(value) ; + dst[0] = (float)(rgba * (1.0f/0x7f)); /* r */ + dst[1] = (float)(rgba * (1.0f/0x7f)); /* g */ + dst[2] = (float)(rgba * (1.0f/0x7f)); /* b */ + dst[3] = (float)(rgba * (1.0f/0x7f)); /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_i8_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= (uint8_t)((int8_t)util_iround(CLAMP(src[0], -1, 1) * 0x7f)) ; + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_i8_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint8_t value = *(const uint8_t *)src; + int8_t rgba; + rgba = (int8_t)(value) ; + dst[0] = (float)(rgba * (1.0f/0x7f)); /* r */ + dst[1] = (float)(rgba * (1.0f/0x7f)); /* g */ + dst[2] = (float)(rgba * (1.0f/0x7f)); /* b */ + dst[3] = (float)(rgba * (1.0f/0x7f)); /* a */ +} + +static INLINE void +util_format_i8_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + int8_t rgba; + rgba = (int8_t)(value) ; + dst[0] = (uint8_t)(((uint32_t)MAX2(rgba, 0)) * 0xff / 0x7f); /* r */ + dst[1] = (uint8_t)(((uint32_t)MAX2(rgba, 0)) * 0xff / 0x7f); /* g */ + dst[2] = (uint8_t)(((uint32_t)MAX2(rgba, 0)) * 0xff / 0x7f); /* b */ + dst[3] = (uint8_t)(((uint32_t)MAX2(rgba, 0)) * 0xff / 0x7f); /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_i8_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= (uint8_t)((int8_t)(src[0] >> 1)) ; + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_a16_snorm { + uint16_t value; + struct { + int16_t a; + } chan; +}; + +static INLINE void +util_format_a16_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + int16_t a; + a = (int16_t)(value) ; + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (float)(a * (1.0f/0x7fff)); /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a16_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)((int16_t)util_iround(CLAMP(src[3], -1, 1) * 0x7fff)) ; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_a16_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + int16_t a; + a = (int16_t)(value) ; + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (float)(a * (1.0f/0x7fff)); /* a */ +} + +static INLINE void +util_format_a16_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + int16_t a; + a = (int16_t)(value) ; + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (uint8_t)(MAX2(a, 0) >> 7); /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a16_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)((int16_t)(((uint32_t)src[3]) * 0x7fff / 0xff)) ; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_l16_snorm { + uint16_t value; + struct { + int16_t rgb; + } chan; +}; + +static INLINE void +util_format_l16_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + int16_t rgb; + rgb = (int16_t)(value) ; + dst[0] = (float)(rgb * (1.0f/0x7fff)); /* r */ + dst[1] = (float)(rgb * (1.0f/0x7fff)); /* g */ + dst[2] = (float)(rgb * (1.0f/0x7fff)); /* b */ + dst[3] = 1; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l16_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)((int16_t)util_iround(CLAMP(src[0], -1, 1) * 0x7fff)) ; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_l16_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + int16_t rgb; + rgb = (int16_t)(value) ; + dst[0] = (float)(rgb * (1.0f/0x7fff)); /* r */ + dst[1] = (float)(rgb * (1.0f/0x7fff)); /* g */ + dst[2] = (float)(rgb * (1.0f/0x7fff)); /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_l16_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + int16_t rgb; + rgb = (int16_t)(value) ; + dst[0] = (uint8_t)(MAX2(rgb, 0) >> 7); /* r */ + dst[1] = (uint8_t)(MAX2(rgb, 0) >> 7); /* g */ + dst[2] = (uint8_t)(MAX2(rgb, 0) >> 7); /* b */ + dst[3] = 255; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l16_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)((int16_t)(((uint32_t)src[0]) * 0x7fff / 0xff)) ; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_l16a16_snorm { + uint32_t value; + struct { + int16_t rgb; + int16_t a; + } chan; +}; + +static INLINE void +util_format_l16a16_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t rgb; + int32_t a; + rgb = ((int32_t)(value << 16) ) >> 16; + a = ((int32_t)(value) ) >> 16; + dst[0] = (float)(rgb * (1.0f/0x7fff)); /* r */ + dst[1] = (float)(rgb * (1.0f/0x7fff)); /* g */ + dst[2] = (float)(rgb * (1.0f/0x7fff)); /* b */ + dst[3] = (float)(a * (1.0f/0x7fff)); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l16a16_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((int16_t)util_iround(CLAMP(src[0], -1, 1) * 0x7fff)) & 0xffff) ; + value |= (uint32_t)(((int16_t)util_iround(CLAMP(src[3], -1, 1) * 0x7fff)) << 16) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_l16a16_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + int32_t rgb; + int32_t a; + rgb = ((int32_t)(value << 16) ) >> 16; + a = ((int32_t)(value) ) >> 16; + dst[0] = (float)(rgb * (1.0f/0x7fff)); /* r */ + dst[1] = (float)(rgb * (1.0f/0x7fff)); /* g */ + dst[2] = (float)(rgb * (1.0f/0x7fff)); /* b */ + dst[3] = (float)(a * (1.0f/0x7fff)); /* a */ +} + +static INLINE void +util_format_l16a16_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t rgb; + int32_t a; + rgb = ((int32_t)(value << 16) ) >> 16; + a = ((int32_t)(value) ) >> 16; + dst[0] = (uint8_t)(MAX2(rgb, 0) >> 7); /* r */ + dst[1] = (uint8_t)(MAX2(rgb, 0) >> 7); /* g */ + dst[2] = (uint8_t)(MAX2(rgb, 0) >> 7); /* b */ + dst[3] = (uint8_t)(MAX2(a, 0) >> 7); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l16a16_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((int16_t)(((uint32_t)src[0]) * 0x7fff / 0xff)) & 0xffff) ; + value |= (uint32_t)(((int16_t)(((uint32_t)src[3]) * 0x7fff / 0xff)) << 16) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_i16_snorm { + uint16_t value; + struct { + int16_t rgba; + } chan; +}; + +static INLINE void +util_format_i16_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + int16_t rgba; + rgba = (int16_t)(value) ; + dst[0] = (float)(rgba * (1.0f/0x7fff)); /* r */ + dst[1] = (float)(rgba * (1.0f/0x7fff)); /* g */ + dst[2] = (float)(rgba * (1.0f/0x7fff)); /* b */ + dst[3] = (float)(rgba * (1.0f/0x7fff)); /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_i16_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)((int16_t)util_iround(CLAMP(src[0], -1, 1) * 0x7fff)) ; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_i16_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + int16_t rgba; + rgba = (int16_t)(value) ; + dst[0] = (float)(rgba * (1.0f/0x7fff)); /* r */ + dst[1] = (float)(rgba * (1.0f/0x7fff)); /* g */ + dst[2] = (float)(rgba * (1.0f/0x7fff)); /* b */ + dst[3] = (float)(rgba * (1.0f/0x7fff)); /* a */ +} + +static INLINE void +util_format_i16_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + int16_t rgba; + rgba = (int16_t)(value) ; + dst[0] = (uint8_t)(MAX2(rgba, 0) >> 7); /* r */ + dst[1] = (uint8_t)(MAX2(rgba, 0) >> 7); /* g */ + dst[2] = (uint8_t)(MAX2(rgba, 0) >> 7); /* b */ + dst[3] = (uint8_t)(MAX2(rgba, 0) >> 7); /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_i16_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)((int16_t)(((uint32_t)src[0]) * 0x7fff / 0xff)) ; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_a16_float { + uint16_t value; + struct { + uint16_t a; + } chan; +}; + +static INLINE void +util_format_a16_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_a16_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = util_half_to_float(pixel.chan.a); /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a16_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_a16_float pixel; + pixel.chan.a = util_float_to_half(src[3]); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_a16_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_a16_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = util_half_to_float(pixel.chan.a); /* a */ +} + +static INLINE void +util_format_a16_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_a16_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = float_to_ubyte(util_half_to_float(pixel.chan.a)); /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a16_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_a16_float pixel; + pixel.chan.a = util_float_to_half((float)(src[3] * (1.0f/0xff))); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_l16_float { + uint16_t value; + struct { + uint16_t rgb; + } chan; +}; + +static INLINE void +util_format_l16_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_l16_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = util_half_to_float(pixel.chan.rgb); /* r */ + dst[1] = util_half_to_float(pixel.chan.rgb); /* g */ + dst[2] = util_half_to_float(pixel.chan.rgb); /* b */ + dst[3] = 1; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l16_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_l16_float pixel; + pixel.chan.rgb = util_float_to_half(src[0]); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_l16_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_l16_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = util_half_to_float(pixel.chan.rgb); /* r */ + dst[1] = util_half_to_float(pixel.chan.rgb); /* g */ + dst[2] = util_half_to_float(pixel.chan.rgb); /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_l16_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_l16_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = float_to_ubyte(util_half_to_float(pixel.chan.rgb)); /* r */ + dst[1] = float_to_ubyte(util_half_to_float(pixel.chan.rgb)); /* g */ + dst[2] = float_to_ubyte(util_half_to_float(pixel.chan.rgb)); /* b */ + dst[3] = 255; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l16_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_l16_float pixel; + pixel.chan.rgb = util_float_to_half((float)(src[0] * (1.0f/0xff))); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_l16a16_float { + uint32_t value; + struct { + uint16_t rgb; + uint16_t a; + } chan; +}; + +static INLINE void +util_format_l16a16_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_l16a16_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = util_half_to_float(pixel.chan.rgb); /* r */ + dst[1] = util_half_to_float(pixel.chan.rgb); /* g */ + dst[2] = util_half_to_float(pixel.chan.rgb); /* b */ + dst[3] = util_half_to_float(pixel.chan.a); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l16a16_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_l16a16_float pixel; + pixel.chan.rgb = util_float_to_half(src[0]); + pixel.chan.a = util_float_to_half(src[3]); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_l16a16_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_l16a16_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = util_half_to_float(pixel.chan.rgb); /* r */ + dst[1] = util_half_to_float(pixel.chan.rgb); /* g */ + dst[2] = util_half_to_float(pixel.chan.rgb); /* b */ + dst[3] = util_half_to_float(pixel.chan.a); /* a */ +} + +static INLINE void +util_format_l16a16_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_l16a16_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = float_to_ubyte(util_half_to_float(pixel.chan.rgb)); /* r */ + dst[1] = float_to_ubyte(util_half_to_float(pixel.chan.rgb)); /* g */ + dst[2] = float_to_ubyte(util_half_to_float(pixel.chan.rgb)); /* b */ + dst[3] = float_to_ubyte(util_half_to_float(pixel.chan.a)); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l16a16_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_l16a16_float pixel; + pixel.chan.rgb = util_float_to_half((float)(src[0] * (1.0f/0xff))); + pixel.chan.a = util_float_to_half((float)(src[3] * (1.0f/0xff))); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_i16_float { + uint16_t value; + struct { + uint16_t rgba; + } chan; +}; + +static INLINE void +util_format_i16_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_i16_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = util_half_to_float(pixel.chan.rgba); /* r */ + dst[1] = util_half_to_float(pixel.chan.rgba); /* g */ + dst[2] = util_half_to_float(pixel.chan.rgba); /* b */ + dst[3] = util_half_to_float(pixel.chan.rgba); /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_i16_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_i16_float pixel; + pixel.chan.rgba = util_float_to_half(src[0]); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_i16_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_i16_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = util_half_to_float(pixel.chan.rgba); /* r */ + dst[1] = util_half_to_float(pixel.chan.rgba); /* g */ + dst[2] = util_half_to_float(pixel.chan.rgba); /* b */ + dst[3] = util_half_to_float(pixel.chan.rgba); /* a */ +} + +static INLINE void +util_format_i16_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_i16_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = float_to_ubyte(util_half_to_float(pixel.chan.rgba)); /* r */ + dst[1] = float_to_ubyte(util_half_to_float(pixel.chan.rgba)); /* g */ + dst[2] = float_to_ubyte(util_half_to_float(pixel.chan.rgba)); /* b */ + dst[3] = float_to_ubyte(util_half_to_float(pixel.chan.rgba)); /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_i16_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_i16_float pixel; + pixel.chan.rgba = util_float_to_half((float)(src[0] * (1.0f/0xff))); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_a32_float { + uint32_t value; + struct { + float a; + } chan; +}; + +static INLINE void +util_format_a32_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_a32_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = pixel.chan.a; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a32_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_a32_float pixel; + pixel.chan.a = src[3]; + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_a32_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_a32_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = pixel.chan.a; /* a */ +} + +static INLINE void +util_format_a32_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_a32_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = float_to_ubyte(pixel.chan.a); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a32_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_a32_float pixel; + pixel.chan.a = ubyte_to_float(src[3]); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_l32_float { + uint32_t value; + struct { + float rgb; + } chan; +}; + +static INLINE void +util_format_l32_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_l32_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.rgb; /* r */ + dst[1] = pixel.chan.rgb; /* g */ + dst[2] = pixel.chan.rgb; /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l32_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_l32_float pixel; + pixel.chan.rgb = src[0]; + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_l32_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_l32_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.rgb; /* r */ + dst[1] = pixel.chan.rgb; /* g */ + dst[2] = pixel.chan.rgb; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_l32_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_l32_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = float_to_ubyte(pixel.chan.rgb); /* r */ + dst[1] = float_to_ubyte(pixel.chan.rgb); /* g */ + dst[2] = float_to_ubyte(pixel.chan.rgb); /* b */ + dst[3] = 255; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l32_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_l32_float pixel; + pixel.chan.rgb = ubyte_to_float(src[0]); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_l32a32_float { + uint64_t value; + struct { + float rgb; + float a; + } chan; +}; + +static INLINE void +util_format_l32a32_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_l32a32_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.rgb; /* r */ + dst[1] = pixel.chan.rgb; /* g */ + dst[2] = pixel.chan.rgb; /* b */ + dst[3] = pixel.chan.a; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l32a32_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_l32a32_float pixel; + pixel.chan.rgb = src[0]; + pixel.chan.a = src[3]; + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_l32a32_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_l32a32_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.rgb; /* r */ + dst[1] = pixel.chan.rgb; /* g */ + dst[2] = pixel.chan.rgb; /* b */ + dst[3] = pixel.chan.a; /* a */ +} + +static INLINE void +util_format_l32a32_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_l32a32_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = float_to_ubyte(pixel.chan.rgb); /* r */ + dst[1] = float_to_ubyte(pixel.chan.rgb); /* g */ + dst[2] = float_to_ubyte(pixel.chan.rgb); /* b */ + dst[3] = float_to_ubyte(pixel.chan.a); /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l32a32_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_l32a32_float pixel; + pixel.chan.rgb = ubyte_to_float(src[0]); + pixel.chan.a = ubyte_to_float(src[3]); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_i32_float { + uint32_t value; + struct { + float rgba; + } chan; +}; + +static INLINE void +util_format_i32_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_i32_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.rgba; /* r */ + dst[1] = pixel.chan.rgba; /* g */ + dst[2] = pixel.chan.rgba; /* b */ + dst[3] = pixel.chan.rgba; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_i32_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_i32_float pixel; + pixel.chan.rgba = src[0]; + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_i32_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_i32_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.rgba; /* r */ + dst[1] = pixel.chan.rgba; /* g */ + dst[2] = pixel.chan.rgba; /* b */ + dst[3] = pixel.chan.rgba; /* a */ +} + +static INLINE void +util_format_i32_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_i32_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = float_to_ubyte(pixel.chan.rgba); /* r */ + dst[1] = float_to_ubyte(pixel.chan.rgba); /* g */ + dst[2] = float_to_ubyte(pixel.chan.rgba); /* b */ + dst[3] = float_to_ubyte(pixel.chan.rgba); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_i32_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_i32_float pixel; + pixel.chan.rgba = ubyte_to_float(src[0]); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_l8_srgb { + uint8_t value; + struct { + uint8_t rgb; + } chan; +}; + +static INLINE void +util_format_l8_srgb_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + uint8_t rgb; + rgb = value; + dst[0] = util_format_srgb_8unorm_to_linear_float(rgb); /* r */ + dst[1] = util_format_srgb_8unorm_to_linear_float(rgb); /* g */ + dst[2] = util_format_srgb_8unorm_to_linear_float(rgb); /* b */ + dst[3] = 1; /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l8_srgb_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= util_format_linear_float_to_srgb_8unorm(src[0]); + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_l8_srgb_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint8_t value = *(const uint8_t *)src; + uint8_t rgb; + rgb = value; + dst[0] = util_format_srgb_8unorm_to_linear_float(rgb); /* r */ + dst[1] = util_format_srgb_8unorm_to_linear_float(rgb); /* g */ + dst[2] = util_format_srgb_8unorm_to_linear_float(rgb); /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_l8_srgb_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + uint8_t rgb; + rgb = value; + dst[0] = util_format_srgb_to_linear_8unorm(rgb); /* r */ + dst[1] = util_format_srgb_to_linear_8unorm(rgb); /* g */ + dst[2] = util_format_srgb_to_linear_8unorm(rgb); /* b */ + dst[3] = 255; /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l8_srgb_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= util_format_linear_to_srgb_8unorm(src[0]); + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_l8a8_srgb { + uint16_t value; + struct { + uint8_t rgb; + uint8_t a; + } chan; +}; + +static INLINE void +util_format_l8a8_srgb_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t rgb; + uint16_t a; + rgb = (value) & 0xff; + a = value >> 8; + dst[0] = util_format_srgb_8unorm_to_linear_float(rgb); /* r */ + dst[1] = util_format_srgb_8unorm_to_linear_float(rgb); /* g */ + dst[2] = util_format_srgb_8unorm_to_linear_float(rgb); /* b */ + dst[3] = ubyte_to_float(a); /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l8a8_srgb_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (util_format_linear_float_to_srgb_8unorm(src[0])) & 0xff; + value |= (float_to_ubyte(src[3])) << 8; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_l8a8_srgb_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + uint16_t rgb; + uint16_t a; + rgb = (value) & 0xff; + a = value >> 8; + dst[0] = util_format_srgb_8unorm_to_linear_float(rgb); /* r */ + dst[1] = util_format_srgb_8unorm_to_linear_float(rgb); /* g */ + dst[2] = util_format_srgb_8unorm_to_linear_float(rgb); /* b */ + dst[3] = ubyte_to_float(a); /* a */ +} + +static INLINE void +util_format_l8a8_srgb_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t rgb; + uint16_t a; + rgb = (value) & 0xff; + a = value >> 8; + dst[0] = util_format_srgb_to_linear_8unorm(rgb); /* r */ + dst[1] = util_format_srgb_to_linear_8unorm(rgb); /* g */ + dst[2] = util_format_srgb_to_linear_8unorm(rgb); /* b */ + dst[3] = a; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l8a8_srgb_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (util_format_linear_to_srgb_8unorm(src[0])) & 0xff; + value |= (src[3]) << 8; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8g8b8_srgb { + struct { + uint8_t r; + uint8_t g; + uint8_t b; + } chan; +}; + +static INLINE void +util_format_r8g8b8_srgb_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r8g8b8_srgb pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = util_format_srgb_8unorm_to_linear_float(pixel.chan.r); /* r */ + dst[1] = util_format_srgb_8unorm_to_linear_float(pixel.chan.g); /* g */ + dst[2] = util_format_srgb_8unorm_to_linear_float(pixel.chan.b); /* b */ + dst[3] = 1; /* a */ + src += 3; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8_srgb_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r8g8b8_srgb pixel; + pixel.chan.r = util_format_linear_float_to_srgb_8unorm(src[0]); + pixel.chan.g = util_format_linear_float_to_srgb_8unorm(src[1]); + pixel.chan.b = util_format_linear_float_to_srgb_8unorm(src[2]); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 3; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8g8b8_srgb_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r8g8b8_srgb pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = util_format_srgb_8unorm_to_linear_float(pixel.chan.r); /* r */ + dst[1] = util_format_srgb_8unorm_to_linear_float(pixel.chan.g); /* g */ + dst[2] = util_format_srgb_8unorm_to_linear_float(pixel.chan.b); /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r8g8b8_srgb_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r8g8b8_srgb pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = util_format_srgb_to_linear_8unorm(pixel.chan.r); /* r */ + dst[1] = util_format_srgb_to_linear_8unorm(pixel.chan.g); /* g */ + dst[2] = util_format_srgb_to_linear_8unorm(pixel.chan.b); /* b */ + dst[3] = 255; /* a */ + src += 3; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8_srgb_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r8g8b8_srgb pixel; + pixel.chan.r = util_format_linear_to_srgb_8unorm(src[0]); + pixel.chan.g = util_format_linear_to_srgb_8unorm(src[1]); + pixel.chan.b = util_format_linear_to_srgb_8unorm(src[2]); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 3; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8g8b8a8_srgb { + uint32_t value; + struct { + uint8_t r; + uint8_t g; + uint8_t b; + uint8_t a; + } chan; +}; + +static INLINE void +util_format_r8g8b8a8_srgb_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + uint32_t a; + r = (value) & 0xff; + g = (value >> 8) & 0xff; + b = (value >> 16) & 0xff; + a = value >> 24; + dst[0] = util_format_srgb_8unorm_to_linear_float(r); /* r */ + dst[1] = util_format_srgb_8unorm_to_linear_float(g); /* g */ + dst[2] = util_format_srgb_8unorm_to_linear_float(b); /* b */ + dst[3] = ubyte_to_float(a); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8a8_srgb_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (util_format_linear_float_to_srgb_8unorm(src[0])) & 0xff; + value |= ((util_format_linear_float_to_srgb_8unorm(src[1])) & 0xff) << 8; + value |= ((util_format_linear_float_to_srgb_8unorm(src[2])) & 0xff) << 16; + value |= (float_to_ubyte(src[3])) << 24; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8g8b8a8_srgb_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + uint32_t a; + r = (value) & 0xff; + g = (value >> 8) & 0xff; + b = (value >> 16) & 0xff; + a = value >> 24; + dst[0] = util_format_srgb_8unorm_to_linear_float(r); /* r */ + dst[1] = util_format_srgb_8unorm_to_linear_float(g); /* g */ + dst[2] = util_format_srgb_8unorm_to_linear_float(b); /* b */ + dst[3] = ubyte_to_float(a); /* a */ +} + +static INLINE void +util_format_r8g8b8a8_srgb_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + uint32_t a; + r = (value) & 0xff; + g = (value >> 8) & 0xff; + b = (value >> 16) & 0xff; + a = value >> 24; + dst[0] = util_format_srgb_to_linear_8unorm(r); /* r */ + dst[1] = util_format_srgb_to_linear_8unorm(g); /* g */ + dst[2] = util_format_srgb_to_linear_8unorm(b); /* b */ + dst[3] = a; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8a8_srgb_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (util_format_linear_to_srgb_8unorm(src[0])) & 0xff; + value |= ((util_format_linear_to_srgb_8unorm(src[1])) & 0xff) << 8; + value |= ((util_format_linear_to_srgb_8unorm(src[2])) & 0xff) << 16; + value |= (src[3]) << 24; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_a8b8g8r8_srgb { + uint32_t value; + struct { + uint8_t a; + uint8_t b; + uint8_t g; + uint8_t r; + } chan; +}; + +static INLINE void +util_format_a8b8g8r8_srgb_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t a; + uint32_t b; + uint32_t g; + uint32_t r; + a = (value) & 0xff; + b = (value >> 8) & 0xff; + g = (value >> 16) & 0xff; + r = value >> 24; + dst[0] = util_format_srgb_8unorm_to_linear_float(r); /* r */ + dst[1] = util_format_srgb_8unorm_to_linear_float(g); /* g */ + dst[2] = util_format_srgb_8unorm_to_linear_float(b); /* b */ + dst[3] = ubyte_to_float(a); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a8b8g8r8_srgb_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (float_to_ubyte(src[3])) & 0xff; + value |= ((util_format_linear_float_to_srgb_8unorm(src[2])) & 0xff) << 8; + value |= ((util_format_linear_float_to_srgb_8unorm(src[1])) & 0xff) << 16; + value |= (util_format_linear_float_to_srgb_8unorm(src[0])) << 24; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_a8b8g8r8_srgb_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t a; + uint32_t b; + uint32_t g; + uint32_t r; + a = (value) & 0xff; + b = (value >> 8) & 0xff; + g = (value >> 16) & 0xff; + r = value >> 24; + dst[0] = util_format_srgb_8unorm_to_linear_float(r); /* r */ + dst[1] = util_format_srgb_8unorm_to_linear_float(g); /* g */ + dst[2] = util_format_srgb_8unorm_to_linear_float(b); /* b */ + dst[3] = ubyte_to_float(a); /* a */ +} + +static INLINE void +util_format_a8b8g8r8_srgb_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t a; + uint32_t b; + uint32_t g; + uint32_t r; + a = (value) & 0xff; + b = (value >> 8) & 0xff; + g = (value >> 16) & 0xff; + r = value >> 24; + dst[0] = util_format_srgb_to_linear_8unorm(r); /* r */ + dst[1] = util_format_srgb_to_linear_8unorm(g); /* g */ + dst[2] = util_format_srgb_to_linear_8unorm(b); /* b */ + dst[3] = a; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a8b8g8r8_srgb_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (src[3]) & 0xff; + value |= ((util_format_linear_to_srgb_8unorm(src[2])) & 0xff) << 8; + value |= ((util_format_linear_to_srgb_8unorm(src[1])) & 0xff) << 16; + value |= (util_format_linear_to_srgb_8unorm(src[0])) << 24; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_x8b8g8r8_srgb { + uint32_t value; + struct { + uint8_t x; + uint8_t b; + uint8_t g; + uint8_t r; + } chan; +}; + +static INLINE void +util_format_x8b8g8r8_srgb_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t b; + uint32_t g; + uint32_t r; + b = (value >> 8) & 0xff; + g = (value >> 16) & 0xff; + r = value >> 24; + dst[0] = util_format_srgb_8unorm_to_linear_float(r); /* r */ + dst[1] = util_format_srgb_8unorm_to_linear_float(g); /* g */ + dst[2] = util_format_srgb_8unorm_to_linear_float(b); /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_x8b8g8r8_srgb_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((util_format_linear_float_to_srgb_8unorm(src[2])) & 0xff) << 8; + value |= ((util_format_linear_float_to_srgb_8unorm(src[1])) & 0xff) << 16; + value |= (util_format_linear_float_to_srgb_8unorm(src[0])) << 24; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_x8b8g8r8_srgb_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t b; + uint32_t g; + uint32_t r; + b = (value >> 8) & 0xff; + g = (value >> 16) & 0xff; + r = value >> 24; + dst[0] = util_format_srgb_8unorm_to_linear_float(r); /* r */ + dst[1] = util_format_srgb_8unorm_to_linear_float(g); /* g */ + dst[2] = util_format_srgb_8unorm_to_linear_float(b); /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_x8b8g8r8_srgb_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t b; + uint32_t g; + uint32_t r; + b = (value >> 8) & 0xff; + g = (value >> 16) & 0xff; + r = value >> 24; + dst[0] = util_format_srgb_to_linear_8unorm(r); /* r */ + dst[1] = util_format_srgb_to_linear_8unorm(g); /* g */ + dst[2] = util_format_srgb_to_linear_8unorm(b); /* b */ + dst[3] = 255; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_x8b8g8r8_srgb_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((util_format_linear_to_srgb_8unorm(src[2])) & 0xff) << 8; + value |= ((util_format_linear_to_srgb_8unorm(src[1])) & 0xff) << 16; + value |= (util_format_linear_to_srgb_8unorm(src[0])) << 24; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_b8g8r8a8_srgb { + uint32_t value; + struct { + uint8_t b; + uint8_t g; + uint8_t r; + uint8_t a; + } chan; +}; + +static INLINE void +util_format_b8g8r8a8_srgb_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t b; + uint32_t g; + uint32_t r; + uint32_t a; + b = (value) & 0xff; + g = (value >> 8) & 0xff; + r = (value >> 16) & 0xff; + a = value >> 24; + dst[0] = util_format_srgb_8unorm_to_linear_float(r); /* r */ + dst[1] = util_format_srgb_8unorm_to_linear_float(g); /* g */ + dst[2] = util_format_srgb_8unorm_to_linear_float(b); /* b */ + dst[3] = ubyte_to_float(a); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_b8g8r8a8_srgb_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (util_format_linear_float_to_srgb_8unorm(src[2])) & 0xff; + value |= ((util_format_linear_float_to_srgb_8unorm(src[1])) & 0xff) << 8; + value |= ((util_format_linear_float_to_srgb_8unorm(src[0])) & 0xff) << 16; + value |= (float_to_ubyte(src[3])) << 24; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_b8g8r8a8_srgb_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t b; + uint32_t g; + uint32_t r; + uint32_t a; + b = (value) & 0xff; + g = (value >> 8) & 0xff; + r = (value >> 16) & 0xff; + a = value >> 24; + dst[0] = util_format_srgb_8unorm_to_linear_float(r); /* r */ + dst[1] = util_format_srgb_8unorm_to_linear_float(g); /* g */ + dst[2] = util_format_srgb_8unorm_to_linear_float(b); /* b */ + dst[3] = ubyte_to_float(a); /* a */ +} + +static INLINE void +util_format_b8g8r8a8_srgb_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t b; + uint32_t g; + uint32_t r; + uint32_t a; + b = (value) & 0xff; + g = (value >> 8) & 0xff; + r = (value >> 16) & 0xff; + a = value >> 24; + dst[0] = util_format_srgb_to_linear_8unorm(r); /* r */ + dst[1] = util_format_srgb_to_linear_8unorm(g); /* g */ + dst[2] = util_format_srgb_to_linear_8unorm(b); /* b */ + dst[3] = a; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_b8g8r8a8_srgb_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (util_format_linear_to_srgb_8unorm(src[2])) & 0xff; + value |= ((util_format_linear_to_srgb_8unorm(src[1])) & 0xff) << 8; + value |= ((util_format_linear_to_srgb_8unorm(src[0])) & 0xff) << 16; + value |= (src[3]) << 24; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_b8g8r8x8_srgb { + uint32_t value; + struct { + uint8_t b; + uint8_t g; + uint8_t r; + uint8_t x; + } chan; +}; + +static INLINE void +util_format_b8g8r8x8_srgb_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t b; + uint32_t g; + uint32_t r; + b = (value) & 0xff; + g = (value >> 8) & 0xff; + r = (value >> 16) & 0xff; + dst[0] = util_format_srgb_8unorm_to_linear_float(r); /* r */ + dst[1] = util_format_srgb_8unorm_to_linear_float(g); /* g */ + dst[2] = util_format_srgb_8unorm_to_linear_float(b); /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_b8g8r8x8_srgb_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (util_format_linear_float_to_srgb_8unorm(src[2])) & 0xff; + value |= ((util_format_linear_float_to_srgb_8unorm(src[1])) & 0xff) << 8; + value |= ((util_format_linear_float_to_srgb_8unorm(src[0])) & 0xff) << 16; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_b8g8r8x8_srgb_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t b; + uint32_t g; + uint32_t r; + b = (value) & 0xff; + g = (value >> 8) & 0xff; + r = (value >> 16) & 0xff; + dst[0] = util_format_srgb_8unorm_to_linear_float(r); /* r */ + dst[1] = util_format_srgb_8unorm_to_linear_float(g); /* g */ + dst[2] = util_format_srgb_8unorm_to_linear_float(b); /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_b8g8r8x8_srgb_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t b; + uint32_t g; + uint32_t r; + b = (value) & 0xff; + g = (value >> 8) & 0xff; + r = (value >> 16) & 0xff; + dst[0] = util_format_srgb_to_linear_8unorm(r); /* r */ + dst[1] = util_format_srgb_to_linear_8unorm(g); /* g */ + dst[2] = util_format_srgb_to_linear_8unorm(b); /* b */ + dst[3] = 255; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_b8g8r8x8_srgb_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (util_format_linear_to_srgb_8unorm(src[2])) & 0xff; + value |= ((util_format_linear_to_srgb_8unorm(src[1])) & 0xff) << 8; + value |= ((util_format_linear_to_srgb_8unorm(src[0])) & 0xff) << 16; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_a8r8g8b8_srgb { + uint32_t value; + struct { + uint8_t a; + uint8_t r; + uint8_t g; + uint8_t b; + } chan; +}; + +static INLINE void +util_format_a8r8g8b8_srgb_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t a; + uint32_t r; + uint32_t g; + uint32_t b; + a = (value) & 0xff; + r = (value >> 8) & 0xff; + g = (value >> 16) & 0xff; + b = value >> 24; + dst[0] = util_format_srgb_8unorm_to_linear_float(r); /* r */ + dst[1] = util_format_srgb_8unorm_to_linear_float(g); /* g */ + dst[2] = util_format_srgb_8unorm_to_linear_float(b); /* b */ + dst[3] = ubyte_to_float(a); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a8r8g8b8_srgb_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (float_to_ubyte(src[3])) & 0xff; + value |= ((util_format_linear_float_to_srgb_8unorm(src[0])) & 0xff) << 8; + value |= ((util_format_linear_float_to_srgb_8unorm(src[1])) & 0xff) << 16; + value |= (util_format_linear_float_to_srgb_8unorm(src[2])) << 24; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_a8r8g8b8_srgb_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t a; + uint32_t r; + uint32_t g; + uint32_t b; + a = (value) & 0xff; + r = (value >> 8) & 0xff; + g = (value >> 16) & 0xff; + b = value >> 24; + dst[0] = util_format_srgb_8unorm_to_linear_float(r); /* r */ + dst[1] = util_format_srgb_8unorm_to_linear_float(g); /* g */ + dst[2] = util_format_srgb_8unorm_to_linear_float(b); /* b */ + dst[3] = ubyte_to_float(a); /* a */ +} + +static INLINE void +util_format_a8r8g8b8_srgb_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t a; + uint32_t r; + uint32_t g; + uint32_t b; + a = (value) & 0xff; + r = (value >> 8) & 0xff; + g = (value >> 16) & 0xff; + b = value >> 24; + dst[0] = util_format_srgb_to_linear_8unorm(r); /* r */ + dst[1] = util_format_srgb_to_linear_8unorm(g); /* g */ + dst[2] = util_format_srgb_to_linear_8unorm(b); /* b */ + dst[3] = a; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a8r8g8b8_srgb_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (src[3]) & 0xff; + value |= ((util_format_linear_to_srgb_8unorm(src[0])) & 0xff) << 8; + value |= ((util_format_linear_to_srgb_8unorm(src[1])) & 0xff) << 16; + value |= (util_format_linear_to_srgb_8unorm(src[2])) << 24; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_x8r8g8b8_srgb { + uint32_t value; + struct { + uint8_t x; + uint8_t r; + uint8_t g; + uint8_t b; + } chan; +}; + +static INLINE void +util_format_x8r8g8b8_srgb_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + r = (value >> 8) & 0xff; + g = (value >> 16) & 0xff; + b = value >> 24; + dst[0] = util_format_srgb_8unorm_to_linear_float(r); /* r */ + dst[1] = util_format_srgb_8unorm_to_linear_float(g); /* g */ + dst[2] = util_format_srgb_8unorm_to_linear_float(b); /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_x8r8g8b8_srgb_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((util_format_linear_float_to_srgb_8unorm(src[0])) & 0xff) << 8; + value |= ((util_format_linear_float_to_srgb_8unorm(src[1])) & 0xff) << 16; + value |= (util_format_linear_float_to_srgb_8unorm(src[2])) << 24; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_x8r8g8b8_srgb_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + r = (value >> 8) & 0xff; + g = (value >> 16) & 0xff; + b = value >> 24; + dst[0] = util_format_srgb_8unorm_to_linear_float(r); /* r */ + dst[1] = util_format_srgb_8unorm_to_linear_float(g); /* g */ + dst[2] = util_format_srgb_8unorm_to_linear_float(b); /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_x8r8g8b8_srgb_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + r = (value >> 8) & 0xff; + g = (value >> 16) & 0xff; + b = value >> 24; + dst[0] = util_format_srgb_to_linear_8unorm(r); /* r */ + dst[1] = util_format_srgb_to_linear_8unorm(g); /* g */ + dst[2] = util_format_srgb_to_linear_8unorm(b); /* b */ + dst[3] = 255; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_x8r8g8b8_srgb_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((util_format_linear_to_srgb_8unorm(src[0])) & 0xff) << 8; + value |= ((util_format_linear_to_srgb_8unorm(src[1])) & 0xff) << 16; + value |= (util_format_linear_to_srgb_8unorm(src[2])) << 24; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8sg8sb8ux8u_norm { + uint32_t value; + struct { + int8_t r; + int8_t g; + uint8_t b; + uint8_t x; + } chan; +}; + +static INLINE void +util_format_r8sg8sb8ux8u_norm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + uint32_t b; + r = ((int32_t)(value << 24) ) >> 24; + g = ((int32_t)(value << 16) ) >> 24; + b = (value >> 16) & 0xff; + dst[0] = (float)(r * (1.0f/0x7f)); /* r */ + dst[1] = (float)(g * (1.0f/0x7f)); /* g */ + dst[2] = ubyte_to_float(b); /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8sg8sb8ux8u_norm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((uint32_t)util_iround(CLAMP(src[0], -1, 1) * 0x7f)) & 0xff) ; + value |= (uint32_t)((((uint32_t)util_iround(CLAMP(src[1], -1, 1) * 0x7f)) & 0xff) << 8) ; + value |= ((float_to_ubyte(src[2])) & 0xff) << 16; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8sg8sb8ux8u_norm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + uint32_t b; + r = ((int32_t)(value << 24) ) >> 24; + g = ((int32_t)(value << 16) ) >> 24; + b = (value >> 16) & 0xff; + dst[0] = (float)(r * (1.0f/0x7f)); /* r */ + dst[1] = (float)(g * (1.0f/0x7f)); /* g */ + dst[2] = ubyte_to_float(b); /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r8sg8sb8ux8u_norm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + uint32_t b; + r = ((int32_t)(value << 24) ) >> 24; + g = ((int32_t)(value << 16) ) >> 24; + b = (value >> 16) & 0xff; + dst[0] = (uint8_t)(((uint32_t)MAX2(r, 0)) * 0xff / 0x7f); /* r */ + dst[1] = (uint8_t)(((uint32_t)MAX2(g, 0)) * 0xff / 0x7f); /* g */ + dst[2] = b; /* b */ + dst[3] = 255; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8sg8sb8ux8u_norm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((uint32_t)(src[0] >> 1)) & 0xff) ; + value |= (uint32_t)((((uint32_t)(src[1] >> 1)) & 0xff) << 8) ; + value |= ((src[2]) & 0xff) << 16; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r10sg10sb10sa2u_norm { + uint32_t value; + struct { + int r:10; + int g:10; + int b:10; + unsigned a:2; + } chan; +}; + +static INLINE void +util_format_r10sg10sb10sa2u_norm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + int32_t b; + uint32_t a; + r = ((int32_t)(value << 22) ) >> 22; + g = ((int32_t)(value << 12) ) >> 22; + b = ((int32_t)(value << 2) ) >> 22; + a = value >> 30; + dst[0] = (float)(r * (1.0f/0x1ff)); /* r */ + dst[1] = (float)(g * (1.0f/0x1ff)); /* g */ + dst[2] = (float)(b * (1.0f/0x1ff)); /* b */ + dst[3] = (float)(a * (1.0f/0x3)); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r10sg10sb10sa2u_norm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((uint32_t)util_iround(CLAMP(src[0], -1, 1) * 0x1ff)) & 0x3ff) ; + value |= (uint32_t)((((uint32_t)util_iround(CLAMP(src[1], -1, 1) * 0x1ff)) & 0x3ff) << 10) ; + value |= (uint32_t)((((uint32_t)util_iround(CLAMP(src[2], -1, 1) * 0x1ff)) & 0x3ff) << 20) ; + value |= ((uint32_t)util_iround(CLAMP(src[3], 0, 1) * 0x3)) << 30; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r10sg10sb10sa2u_norm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + int32_t b; + uint32_t a; + r = ((int32_t)(value << 22) ) >> 22; + g = ((int32_t)(value << 12) ) >> 22; + b = ((int32_t)(value << 2) ) >> 22; + a = value >> 30; + dst[0] = (float)(r * (1.0f/0x1ff)); /* r */ + dst[1] = (float)(g * (1.0f/0x1ff)); /* g */ + dst[2] = (float)(b * (1.0f/0x1ff)); /* b */ + dst[3] = (float)(a * (1.0f/0x3)); /* a */ +} + +static INLINE void +util_format_r10sg10sb10sa2u_norm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + int32_t b; + uint32_t a; + r = ((int32_t)(value << 22) ) >> 22; + g = ((int32_t)(value << 12) ) >> 22; + b = ((int32_t)(value << 2) ) >> 22; + a = value >> 30; + dst[0] = (uint8_t)(MAX2(r, 0) >> 1); /* r */ + dst[1] = (uint8_t)(MAX2(g, 0) >> 1); /* g */ + dst[2] = (uint8_t)(MAX2(b, 0) >> 1); /* b */ + dst[3] = (uint8_t)(((uint32_t)a) * 0xff / 0x3); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r10sg10sb10sa2u_norm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((uint32_t)(((uint32_t)src[0]) * 0x1ff / 0xff)) & 0x3ff) ; + value |= (uint32_t)((((uint32_t)(((uint32_t)src[1]) * 0x1ff / 0xff)) & 0x3ff) << 10) ; + value |= (uint32_t)((((uint32_t)(((uint32_t)src[2]) * 0x1ff / 0xff)) & 0x3ff) << 20) ; + value |= ((uint32_t)(src[3] >> 6)) << 30; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r5sg5sb6u_norm { + uint16_t value; + struct { + int r:5; + int g:5; + unsigned b:6; + } chan; +}; + +static INLINE void +util_format_r5sg5sb6u_norm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + int16_t r; + int16_t g; + uint16_t b; + r = ((int16_t)(value << 11) ) >> 11; + g = ((int16_t)(value << 6) ) >> 11; + b = value >> 10; + dst[0] = (float)(r * (1.0f/0xf)); /* r */ + dst[1] = (float)(g * (1.0f/0xf)); /* g */ + dst[2] = (float)(b * (1.0f/0x3f)); /* b */ + dst[3] = 1; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r5sg5sb6u_norm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)(((uint16_t)util_iround(CLAMP(src[0], -1, 1) * 0xf)) & 0x1f) ; + value |= (uint16_t)((((uint16_t)util_iround(CLAMP(src[1], -1, 1) * 0xf)) & 0x1f) << 5) ; + value |= ((uint16_t)util_iround(CLAMP(src[2], 0, 1) * 0x3f)) << 10; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r5sg5sb6u_norm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + int16_t r; + int16_t g; + uint16_t b; + r = ((int16_t)(value << 11) ) >> 11; + g = ((int16_t)(value << 6) ) >> 11; + b = value >> 10; + dst[0] = (float)(r * (1.0f/0xf)); /* r */ + dst[1] = (float)(g * (1.0f/0xf)); /* g */ + dst[2] = (float)(b * (1.0f/0x3f)); /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r5sg5sb6u_norm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + int16_t r; + int16_t g; + uint16_t b; + r = ((int16_t)(value << 11) ) >> 11; + g = ((int16_t)(value << 6) ) >> 11; + b = value >> 10; + dst[0] = (uint8_t)(((uint32_t)MAX2(r, 0)) * 0xff / 0xf); /* r */ + dst[1] = (uint8_t)(((uint32_t)MAX2(g, 0)) * 0xff / 0xf); /* g */ + dst[2] = (uint8_t)(((uint32_t)b) * 0xff / 0x3f); /* b */ + dst[3] = 255; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r5sg5sb6u_norm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)(((uint16_t)(src[0] >> 4)) & 0x1f) ; + value |= (uint16_t)((((uint16_t)(src[1] >> 4)) & 0x1f) << 5) ; + value |= ((uint16_t)(src[2] >> 2)) << 10; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r64_float { + uint64_t value; + struct { + double r; + } chan; +}; + +static INLINE void +util_format_r64_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r64_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)pixel.chan.r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r64_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r64_float pixel; + pixel.chan.r = (double)src[0]; + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r64_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r64_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)pixel.chan.r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r64_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r64_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (uint8_t)util_iround(CLAMP(pixel.chan.r, 0, 1) * 0xff); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 255; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r64_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r64_float pixel; + pixel.chan.r = (double)(src[0] * (1.0f/0xff)); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r64g64_float { + struct { + double r; + double g; + } chan; +}; + +static INLINE void +util_format_r64g64_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r64g64_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)pixel.chan.r; /* r */ + dst[1] = (float)pixel.chan.g; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 16; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r64g64_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r64g64_float pixel; + pixel.chan.r = (double)src[0]; + pixel.chan.g = (double)src[1]; + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 16; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r64g64_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r64g64_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)pixel.chan.r; /* r */ + dst[1] = (float)pixel.chan.g; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r64g64_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r64g64_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (uint8_t)util_iround(CLAMP(pixel.chan.r, 0, 1) * 0xff); /* r */ + dst[1] = (uint8_t)util_iround(CLAMP(pixel.chan.g, 0, 1) * 0xff); /* g */ + dst[2] = 0; /* b */ + dst[3] = 255; /* a */ + src += 16; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r64g64_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r64g64_float pixel; + pixel.chan.r = (double)(src[0] * (1.0f/0xff)); + pixel.chan.g = (double)(src[1] * (1.0f/0xff)); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 16; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r64g64b64_float { + struct { + double r; + double g; + double b; + } chan; +}; + +static INLINE void +util_format_r64g64b64_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r64g64b64_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)pixel.chan.r; /* r */ + dst[1] = (float)pixel.chan.g; /* g */ + dst[2] = (float)pixel.chan.b; /* b */ + dst[3] = 1; /* a */ + src += 24; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r64g64b64_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r64g64b64_float pixel; + pixel.chan.r = (double)src[0]; + pixel.chan.g = (double)src[1]; + pixel.chan.b = (double)src[2]; + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 24; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r64g64b64_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r64g64b64_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)pixel.chan.r; /* r */ + dst[1] = (float)pixel.chan.g; /* g */ + dst[2] = (float)pixel.chan.b; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r64g64b64_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r64g64b64_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (uint8_t)util_iround(CLAMP(pixel.chan.r, 0, 1) * 0xff); /* r */ + dst[1] = (uint8_t)util_iround(CLAMP(pixel.chan.g, 0, 1) * 0xff); /* g */ + dst[2] = (uint8_t)util_iround(CLAMP(pixel.chan.b, 0, 1) * 0xff); /* b */ + dst[3] = 255; /* a */ + src += 24; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r64g64b64_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r64g64b64_float pixel; + pixel.chan.r = (double)(src[0] * (1.0f/0xff)); + pixel.chan.g = (double)(src[1] * (1.0f/0xff)); + pixel.chan.b = (double)(src[2] * (1.0f/0xff)); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 24; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r64g64b64a64_float { + struct { + double r; + double g; + double b; + double a; + } chan; +}; + +static INLINE void +util_format_r64g64b64a64_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r64g64b64a64_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)pixel.chan.r; /* r */ + dst[1] = (float)pixel.chan.g; /* g */ + dst[2] = (float)pixel.chan.b; /* b */ + dst[3] = (float)pixel.chan.a; /* a */ + src += 32; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r64g64b64a64_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r64g64b64a64_float pixel; + pixel.chan.r = (double)src[0]; + pixel.chan.g = (double)src[1]; + pixel.chan.b = (double)src[2]; + pixel.chan.a = (double)src[3]; + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 32; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r64g64b64a64_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r64g64b64a64_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)pixel.chan.r; /* r */ + dst[1] = (float)pixel.chan.g; /* g */ + dst[2] = (float)pixel.chan.b; /* b */ + dst[3] = (float)pixel.chan.a; /* a */ +} + +static INLINE void +util_format_r64g64b64a64_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r64g64b64a64_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (uint8_t)util_iround(CLAMP(pixel.chan.r, 0, 1) * 0xff); /* r */ + dst[1] = (uint8_t)util_iround(CLAMP(pixel.chan.g, 0, 1) * 0xff); /* g */ + dst[2] = (uint8_t)util_iround(CLAMP(pixel.chan.b, 0, 1) * 0xff); /* b */ + dst[3] = (uint8_t)util_iround(CLAMP(pixel.chan.a, 0, 1) * 0xff); /* a */ + src += 32; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r64g64b64a64_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r64g64b64a64_float pixel; + pixel.chan.r = (double)(src[0] * (1.0f/0xff)); + pixel.chan.g = (double)(src[1] * (1.0f/0xff)); + pixel.chan.b = (double)(src[2] * (1.0f/0xff)); + pixel.chan.a = (double)(src[3] * (1.0f/0xff)); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 32; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32_float { + uint32_t value; + struct { + float r; + } chan; +}; + +static INLINE void +util_format_r32_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32_float pixel; + pixel.chan.r = src[0]; + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r32_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r32_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = float_to_ubyte(pixel.chan.r); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 255; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32_float pixel; + pixel.chan.r = ubyte_to_float(src[0]); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32g32_float { + uint64_t value; + struct { + float r; + float g; + } chan; +}; + +static INLINE void +util_format_r32g32_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.r; /* r */ + dst[1] = pixel.chan.g; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32_float pixel; + pixel.chan.r = src[0]; + pixel.chan.g = src[1]; + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32g32_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r32g32_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.r; /* r */ + dst[1] = pixel.chan.g; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r32g32_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = float_to_ubyte(pixel.chan.r); /* r */ + dst[1] = float_to_ubyte(pixel.chan.g); /* g */ + dst[2] = 0; /* b */ + dst[3] = 255; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32_float pixel; + pixel.chan.r = ubyte_to_float(src[0]); + pixel.chan.g = ubyte_to_float(src[1]); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32g32b32_float { + struct { + float r; + float g; + float b; + } chan; +}; + +static INLINE void +util_format_r32g32b32_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.r; /* r */ + dst[1] = pixel.chan.g; /* g */ + dst[2] = pixel.chan.b; /* b */ + dst[3] = 1; /* a */ + src += 12; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32_float pixel; + pixel.chan.r = src[0]; + pixel.chan.g = src[1]; + pixel.chan.b = src[2]; + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 12; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32g32b32_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r32g32b32_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.r; /* r */ + dst[1] = pixel.chan.g; /* g */ + dst[2] = pixel.chan.b; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r32g32b32_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = float_to_ubyte(pixel.chan.r); /* r */ + dst[1] = float_to_ubyte(pixel.chan.g); /* g */ + dst[2] = float_to_ubyte(pixel.chan.b); /* b */ + dst[3] = 255; /* a */ + src += 12; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32_float pixel; + pixel.chan.r = ubyte_to_float(src[0]); + pixel.chan.g = ubyte_to_float(src[1]); + pixel.chan.b = ubyte_to_float(src[2]); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 12; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32g32b32a32_float { + struct { + float r; + float g; + float b; + float a; + } chan; +}; + +static INLINE void +util_format_r32g32b32a32_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32a32_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.r; /* r */ + dst[1] = pixel.chan.g; /* g */ + dst[2] = pixel.chan.b; /* b */ + dst[3] = pixel.chan.a; /* a */ + src += 16; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32a32_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32a32_float pixel; + pixel.chan.r = src[0]; + pixel.chan.g = src[1]; + pixel.chan.b = src[2]; + pixel.chan.a = src[3]; + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 16; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32g32b32a32_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r32g32b32a32_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.r; /* r */ + dst[1] = pixel.chan.g; /* g */ + dst[2] = pixel.chan.b; /* b */ + dst[3] = pixel.chan.a; /* a */ +} + +static INLINE void +util_format_r32g32b32a32_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32a32_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = float_to_ubyte(pixel.chan.r); /* r */ + dst[1] = float_to_ubyte(pixel.chan.g); /* g */ + dst[2] = float_to_ubyte(pixel.chan.b); /* b */ + dst[3] = float_to_ubyte(pixel.chan.a); /* a */ + src += 16; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32a32_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32a32_float pixel; + pixel.chan.r = ubyte_to_float(src[0]); + pixel.chan.g = ubyte_to_float(src[1]); + pixel.chan.b = ubyte_to_float(src[2]); + pixel.chan.a = ubyte_to_float(src[3]); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 16; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32_unorm { + uint32_t value; + struct { + uint32_t r; + } chan; +}; + +static INLINE void +util_format_r32_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + r = value; + dst[0] = (float)(r * (1.0/0xffffffff)); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(CLAMP(src[0], 0, 1) * (double)0xffffffff); + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t r; + r = value; + dst[0] = (float)(r * (1.0/0xffffffff)); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r32_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + r = value; + dst[0] = (uint8_t)(r >> 24); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 255; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((uint64_t)src[0]) * 0xffffffff / 0xff); + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32g32_unorm { + uint64_t value; + struct { + uint32_t r; + uint32_t g; + } chan; +}; + +static INLINE void +util_format_r32g32_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32_unorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)(pixel.chan.r * (1.0/0xffffffff)); /* r */ + dst[1] = (float)(pixel.chan.g * (1.0/0xffffffff)); /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32_unorm pixel; + pixel.chan.r = (uint32_t)(CLAMP(src[0], 0, 1) * (double)0xffffffff); + pixel.chan.g = (uint32_t)(CLAMP(src[1], 0, 1) * (double)0xffffffff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32g32_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r32g32_unorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)(pixel.chan.r * (1.0/0xffffffff)); /* r */ + dst[1] = (float)(pixel.chan.g * (1.0/0xffffffff)); /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r32g32_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32_unorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (uint8_t)(pixel.chan.r >> 24); /* r */ + dst[1] = (uint8_t)(pixel.chan.g >> 24); /* g */ + dst[2] = 0; /* b */ + dst[3] = 255; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32_unorm pixel; + pixel.chan.r = (uint32_t)(((uint64_t)src[0]) * 0xffffffff / 0xff); + pixel.chan.g = (uint32_t)(((uint64_t)src[1]) * 0xffffffff / 0xff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32g32b32_unorm { + struct { + uint32_t r; + uint32_t g; + uint32_t b; + } chan; +}; + +static INLINE void +util_format_r32g32b32_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32_unorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)(pixel.chan.r * (1.0/0xffffffff)); /* r */ + dst[1] = (float)(pixel.chan.g * (1.0/0xffffffff)); /* g */ + dst[2] = (float)(pixel.chan.b * (1.0/0xffffffff)); /* b */ + dst[3] = 1; /* a */ + src += 12; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32_unorm pixel; + pixel.chan.r = (uint32_t)(CLAMP(src[0], 0, 1) * (double)0xffffffff); + pixel.chan.g = (uint32_t)(CLAMP(src[1], 0, 1) * (double)0xffffffff); + pixel.chan.b = (uint32_t)(CLAMP(src[2], 0, 1) * (double)0xffffffff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 12; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32g32b32_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r32g32b32_unorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)(pixel.chan.r * (1.0/0xffffffff)); /* r */ + dst[1] = (float)(pixel.chan.g * (1.0/0xffffffff)); /* g */ + dst[2] = (float)(pixel.chan.b * (1.0/0xffffffff)); /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r32g32b32_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32_unorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (uint8_t)(pixel.chan.r >> 24); /* r */ + dst[1] = (uint8_t)(pixel.chan.g >> 24); /* g */ + dst[2] = (uint8_t)(pixel.chan.b >> 24); /* b */ + dst[3] = 255; /* a */ + src += 12; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32_unorm pixel; + pixel.chan.r = (uint32_t)(((uint64_t)src[0]) * 0xffffffff / 0xff); + pixel.chan.g = (uint32_t)(((uint64_t)src[1]) * 0xffffffff / 0xff); + pixel.chan.b = (uint32_t)(((uint64_t)src[2]) * 0xffffffff / 0xff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 12; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32g32b32a32_unorm { + struct { + uint32_t r; + uint32_t g; + uint32_t b; + uint32_t a; + } chan; +}; + +static INLINE void +util_format_r32g32b32a32_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32a32_unorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)(pixel.chan.r * (1.0/0xffffffff)); /* r */ + dst[1] = (float)(pixel.chan.g * (1.0/0xffffffff)); /* g */ + dst[2] = (float)(pixel.chan.b * (1.0/0xffffffff)); /* b */ + dst[3] = (float)(pixel.chan.a * (1.0/0xffffffff)); /* a */ + src += 16; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32a32_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32a32_unorm pixel; + pixel.chan.r = (uint32_t)(CLAMP(src[0], 0, 1) * (double)0xffffffff); + pixel.chan.g = (uint32_t)(CLAMP(src[1], 0, 1) * (double)0xffffffff); + pixel.chan.b = (uint32_t)(CLAMP(src[2], 0, 1) * (double)0xffffffff); + pixel.chan.a = (uint32_t)(CLAMP(src[3], 0, 1) * (double)0xffffffff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 16; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32g32b32a32_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r32g32b32a32_unorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)(pixel.chan.r * (1.0/0xffffffff)); /* r */ + dst[1] = (float)(pixel.chan.g * (1.0/0xffffffff)); /* g */ + dst[2] = (float)(pixel.chan.b * (1.0/0xffffffff)); /* b */ + dst[3] = (float)(pixel.chan.a * (1.0/0xffffffff)); /* a */ +} + +static INLINE void +util_format_r32g32b32a32_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32a32_unorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (uint8_t)(pixel.chan.r >> 24); /* r */ + dst[1] = (uint8_t)(pixel.chan.g >> 24); /* g */ + dst[2] = (uint8_t)(pixel.chan.b >> 24); /* b */ + dst[3] = (uint8_t)(pixel.chan.a >> 24); /* a */ + src += 16; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32a32_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32a32_unorm pixel; + pixel.chan.r = (uint32_t)(((uint64_t)src[0]) * 0xffffffff / 0xff); + pixel.chan.g = (uint32_t)(((uint64_t)src[1]) * 0xffffffff / 0xff); + pixel.chan.b = (uint32_t)(((uint64_t)src[2]) * 0xffffffff / 0xff); + pixel.chan.a = (uint32_t)(((uint64_t)src[3]) * 0xffffffff / 0xff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 16; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32_uscaled { + uint32_t value; + struct { + uint32_t r; + } chan; +}; + +static INLINE void +util_format_r32_uscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + r = value; + dst[0] = (float)r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32_uscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)CLAMP(src[0], 0, 4294967295); + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32_uscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t r; + r = value; + dst[0] = (float)r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r32_uscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + r = value; + dst[0] = (uint8_t)(((uint64_t)MIN2(r, 1)) * 0xff / 0x1); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 255; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32_uscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((uint64_t)src[0]) * 0x1 / 0xff); + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32g32_uscaled { + uint64_t value; + struct { + uint32_t r; + uint32_t g; + } chan; +}; + +static INLINE void +util_format_r32g32_uscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32_uscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)pixel.chan.r; /* r */ + dst[1] = (float)pixel.chan.g; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32_uscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32_uscaled pixel; + pixel.chan.r = (uint32_t)CLAMP(src[0], 0, 4294967295); + pixel.chan.g = (uint32_t)CLAMP(src[1], 0, 4294967295); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32g32_uscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r32g32_uscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)pixel.chan.r; /* r */ + dst[1] = (float)pixel.chan.g; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r32g32_uscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32_uscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (uint8_t)(((uint64_t)MIN2(pixel.chan.r, 1)) * 0xff / 0x1); /* r */ + dst[1] = (uint8_t)(((uint64_t)MIN2(pixel.chan.g, 1)) * 0xff / 0x1); /* g */ + dst[2] = 0; /* b */ + dst[3] = 255; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32_uscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32_uscaled pixel; + pixel.chan.r = (uint32_t)(((uint64_t)src[0]) * 0x1 / 0xff); + pixel.chan.g = (uint32_t)(((uint64_t)src[1]) * 0x1 / 0xff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32g32b32_uscaled { + struct { + uint32_t r; + uint32_t g; + uint32_t b; + } chan; +}; + +static INLINE void +util_format_r32g32b32_uscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32_uscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)pixel.chan.r; /* r */ + dst[1] = (float)pixel.chan.g; /* g */ + dst[2] = (float)pixel.chan.b; /* b */ + dst[3] = 1; /* a */ + src += 12; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32_uscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32_uscaled pixel; + pixel.chan.r = (uint32_t)CLAMP(src[0], 0, 4294967295); + pixel.chan.g = (uint32_t)CLAMP(src[1], 0, 4294967295); + pixel.chan.b = (uint32_t)CLAMP(src[2], 0, 4294967295); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 12; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32g32b32_uscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r32g32b32_uscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)pixel.chan.r; /* r */ + dst[1] = (float)pixel.chan.g; /* g */ + dst[2] = (float)pixel.chan.b; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r32g32b32_uscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32_uscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (uint8_t)(((uint64_t)MIN2(pixel.chan.r, 1)) * 0xff / 0x1); /* r */ + dst[1] = (uint8_t)(((uint64_t)MIN2(pixel.chan.g, 1)) * 0xff / 0x1); /* g */ + dst[2] = (uint8_t)(((uint64_t)MIN2(pixel.chan.b, 1)) * 0xff / 0x1); /* b */ + dst[3] = 255; /* a */ + src += 12; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32_uscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32_uscaled pixel; + pixel.chan.r = (uint32_t)(((uint64_t)src[0]) * 0x1 / 0xff); + pixel.chan.g = (uint32_t)(((uint64_t)src[1]) * 0x1 / 0xff); + pixel.chan.b = (uint32_t)(((uint64_t)src[2]) * 0x1 / 0xff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 12; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32g32b32a32_uscaled { + struct { + uint32_t r; + uint32_t g; + uint32_t b; + uint32_t a; + } chan; +}; + +static INLINE void +util_format_r32g32b32a32_uscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32a32_uscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)pixel.chan.r; /* r */ + dst[1] = (float)pixel.chan.g; /* g */ + dst[2] = (float)pixel.chan.b; /* b */ + dst[3] = (float)pixel.chan.a; /* a */ + src += 16; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32a32_uscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32a32_uscaled pixel; + pixel.chan.r = (uint32_t)CLAMP(src[0], 0, 4294967295); + pixel.chan.g = (uint32_t)CLAMP(src[1], 0, 4294967295); + pixel.chan.b = (uint32_t)CLAMP(src[2], 0, 4294967295); + pixel.chan.a = (uint32_t)CLAMP(src[3], 0, 4294967295); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 16; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32g32b32a32_uscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r32g32b32a32_uscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)pixel.chan.r; /* r */ + dst[1] = (float)pixel.chan.g; /* g */ + dst[2] = (float)pixel.chan.b; /* b */ + dst[3] = (float)pixel.chan.a; /* a */ +} + +static INLINE void +util_format_r32g32b32a32_uscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32a32_uscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (uint8_t)(((uint64_t)MIN2(pixel.chan.r, 1)) * 0xff / 0x1); /* r */ + dst[1] = (uint8_t)(((uint64_t)MIN2(pixel.chan.g, 1)) * 0xff / 0x1); /* g */ + dst[2] = (uint8_t)(((uint64_t)MIN2(pixel.chan.b, 1)) * 0xff / 0x1); /* b */ + dst[3] = (uint8_t)(((uint64_t)MIN2(pixel.chan.a, 1)) * 0xff / 0x1); /* a */ + src += 16; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32a32_uscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32a32_uscaled pixel; + pixel.chan.r = (uint32_t)(((uint64_t)src[0]) * 0x1 / 0xff); + pixel.chan.g = (uint32_t)(((uint64_t)src[1]) * 0x1 / 0xff); + pixel.chan.b = (uint32_t)(((uint64_t)src[2]) * 0x1 / 0xff); + pixel.chan.a = (uint32_t)(((uint64_t)src[3]) * 0x1 / 0xff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 16; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32_snorm { + uint32_t value; + struct { + int32_t r; + } chan; +}; + +static INLINE void +util_format_r32_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + r = (int32_t)(value) ; + dst[0] = (float)(r * (1.0/0x7fffffff)); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)((int32_t)(CLAMP(src[0], -1, 1) * (double)0x7fffffff)) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + int32_t r; + r = (int32_t)(value) ; + dst[0] = (float)(r * (1.0/0x7fffffff)); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r32_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + r = (int32_t)(value) ; + dst[0] = (uint8_t)(MAX2(r, 0) >> 23); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 255; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)((int32_t)(((uint64_t)src[0]) * 0x7fffffff / 0xff)) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32g32_snorm { + uint64_t value; + struct { + int32_t r; + int32_t g; + } chan; +}; + +static INLINE void +util_format_r32g32_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32_snorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)(pixel.chan.r * (1.0/0x7fffffff)); /* r */ + dst[1] = (float)(pixel.chan.g * (1.0/0x7fffffff)); /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32_snorm pixel; + pixel.chan.r = (int32_t)(CLAMP(src[0], -1, 1) * (double)0x7fffffff); + pixel.chan.g = (int32_t)(CLAMP(src[1], -1, 1) * (double)0x7fffffff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32g32_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r32g32_snorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)(pixel.chan.r * (1.0/0x7fffffff)); /* r */ + dst[1] = (float)(pixel.chan.g * (1.0/0x7fffffff)); /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r32g32_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32_snorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (uint8_t)(MAX2(pixel.chan.r, 0) >> 23); /* r */ + dst[1] = (uint8_t)(MAX2(pixel.chan.g, 0) >> 23); /* g */ + dst[2] = 0; /* b */ + dst[3] = 255; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32_snorm pixel; + pixel.chan.r = (int32_t)(((uint64_t)src[0]) * 0x7fffffff / 0xff); + pixel.chan.g = (int32_t)(((uint64_t)src[1]) * 0x7fffffff / 0xff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32g32b32_snorm { + struct { + int32_t r; + int32_t g; + int32_t b; + } chan; +}; + +static INLINE void +util_format_r32g32b32_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32_snorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)(pixel.chan.r * (1.0/0x7fffffff)); /* r */ + dst[1] = (float)(pixel.chan.g * (1.0/0x7fffffff)); /* g */ + dst[2] = (float)(pixel.chan.b * (1.0/0x7fffffff)); /* b */ + dst[3] = 1; /* a */ + src += 12; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32_snorm pixel; + pixel.chan.r = (int32_t)(CLAMP(src[0], -1, 1) * (double)0x7fffffff); + pixel.chan.g = (int32_t)(CLAMP(src[1], -1, 1) * (double)0x7fffffff); + pixel.chan.b = (int32_t)(CLAMP(src[2], -1, 1) * (double)0x7fffffff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 12; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32g32b32_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r32g32b32_snorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)(pixel.chan.r * (1.0/0x7fffffff)); /* r */ + dst[1] = (float)(pixel.chan.g * (1.0/0x7fffffff)); /* g */ + dst[2] = (float)(pixel.chan.b * (1.0/0x7fffffff)); /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r32g32b32_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32_snorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (uint8_t)(MAX2(pixel.chan.r, 0) >> 23); /* r */ + dst[1] = (uint8_t)(MAX2(pixel.chan.g, 0) >> 23); /* g */ + dst[2] = (uint8_t)(MAX2(pixel.chan.b, 0) >> 23); /* b */ + dst[3] = 255; /* a */ + src += 12; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32_snorm pixel; + pixel.chan.r = (int32_t)(((uint64_t)src[0]) * 0x7fffffff / 0xff); + pixel.chan.g = (int32_t)(((uint64_t)src[1]) * 0x7fffffff / 0xff); + pixel.chan.b = (int32_t)(((uint64_t)src[2]) * 0x7fffffff / 0xff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 12; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32g32b32a32_snorm { + struct { + int32_t r; + int32_t g; + int32_t b; + int32_t a; + } chan; +}; + +static INLINE void +util_format_r32g32b32a32_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32a32_snorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)(pixel.chan.r * (1.0/0x7fffffff)); /* r */ + dst[1] = (float)(pixel.chan.g * (1.0/0x7fffffff)); /* g */ + dst[2] = (float)(pixel.chan.b * (1.0/0x7fffffff)); /* b */ + dst[3] = (float)(pixel.chan.a * (1.0/0x7fffffff)); /* a */ + src += 16; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32a32_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32a32_snorm pixel; + pixel.chan.r = (int32_t)(CLAMP(src[0], -1, 1) * (double)0x7fffffff); + pixel.chan.g = (int32_t)(CLAMP(src[1], -1, 1) * (double)0x7fffffff); + pixel.chan.b = (int32_t)(CLAMP(src[2], -1, 1) * (double)0x7fffffff); + pixel.chan.a = (int32_t)(CLAMP(src[3], -1, 1) * (double)0x7fffffff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 16; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32g32b32a32_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r32g32b32a32_snorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)(pixel.chan.r * (1.0/0x7fffffff)); /* r */ + dst[1] = (float)(pixel.chan.g * (1.0/0x7fffffff)); /* g */ + dst[2] = (float)(pixel.chan.b * (1.0/0x7fffffff)); /* b */ + dst[3] = (float)(pixel.chan.a * (1.0/0x7fffffff)); /* a */ +} + +static INLINE void +util_format_r32g32b32a32_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32a32_snorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (uint8_t)(MAX2(pixel.chan.r, 0) >> 23); /* r */ + dst[1] = (uint8_t)(MAX2(pixel.chan.g, 0) >> 23); /* g */ + dst[2] = (uint8_t)(MAX2(pixel.chan.b, 0) >> 23); /* b */ + dst[3] = (uint8_t)(MAX2(pixel.chan.a, 0) >> 23); /* a */ + src += 16; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32a32_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32a32_snorm pixel; + pixel.chan.r = (int32_t)(((uint64_t)src[0]) * 0x7fffffff / 0xff); + pixel.chan.g = (int32_t)(((uint64_t)src[1]) * 0x7fffffff / 0xff); + pixel.chan.b = (int32_t)(((uint64_t)src[2]) * 0x7fffffff / 0xff); + pixel.chan.a = (int32_t)(((uint64_t)src[3]) * 0x7fffffff / 0xff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 16; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32_sscaled { + uint32_t value; + struct { + int32_t r; + } chan; +}; + +static INLINE void +util_format_r32_sscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + r = (int32_t)(value) ; + dst[0] = (float)r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32_sscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)((int32_t)CLAMP(src[0], -2147483648, 2147483647)) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32_sscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + int32_t r; + r = (int32_t)(value) ; + dst[0] = (float)r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r32_sscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + r = (int32_t)(value) ; + dst[0] = (uint8_t)(((uint64_t)CLAMP(r, 0, 1)) * 0xff / 0x1); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 255; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32_sscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)((int32_t)(((uint64_t)src[0]) * 0x1 / 0xff)) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32g32_sscaled { + uint64_t value; + struct { + int32_t r; + int32_t g; + } chan; +}; + +static INLINE void +util_format_r32g32_sscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32_sscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)pixel.chan.r; /* r */ + dst[1] = (float)pixel.chan.g; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32_sscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32_sscaled pixel; + pixel.chan.r = (int32_t)CLAMP(src[0], -2147483648, 2147483647); + pixel.chan.g = (int32_t)CLAMP(src[1], -2147483648, 2147483647); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32g32_sscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r32g32_sscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)pixel.chan.r; /* r */ + dst[1] = (float)pixel.chan.g; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r32g32_sscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32_sscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (uint8_t)(((uint64_t)CLAMP(pixel.chan.r, 0, 1)) * 0xff / 0x1); /* r */ + dst[1] = (uint8_t)(((uint64_t)CLAMP(pixel.chan.g, 0, 1)) * 0xff / 0x1); /* g */ + dst[2] = 0; /* b */ + dst[3] = 255; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32_sscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32_sscaled pixel; + pixel.chan.r = (int32_t)(((uint64_t)src[0]) * 0x1 / 0xff); + pixel.chan.g = (int32_t)(((uint64_t)src[1]) * 0x1 / 0xff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32g32b32_sscaled { + struct { + int32_t r; + int32_t g; + int32_t b; + } chan; +}; + +static INLINE void +util_format_r32g32b32_sscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32_sscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)pixel.chan.r; /* r */ + dst[1] = (float)pixel.chan.g; /* g */ + dst[2] = (float)pixel.chan.b; /* b */ + dst[3] = 1; /* a */ + src += 12; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32_sscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32_sscaled pixel; + pixel.chan.r = (int32_t)CLAMP(src[0], -2147483648, 2147483647); + pixel.chan.g = (int32_t)CLAMP(src[1], -2147483648, 2147483647); + pixel.chan.b = (int32_t)CLAMP(src[2], -2147483648, 2147483647); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 12; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32g32b32_sscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r32g32b32_sscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)pixel.chan.r; /* r */ + dst[1] = (float)pixel.chan.g; /* g */ + dst[2] = (float)pixel.chan.b; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r32g32b32_sscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32_sscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (uint8_t)(((uint64_t)CLAMP(pixel.chan.r, 0, 1)) * 0xff / 0x1); /* r */ + dst[1] = (uint8_t)(((uint64_t)CLAMP(pixel.chan.g, 0, 1)) * 0xff / 0x1); /* g */ + dst[2] = (uint8_t)(((uint64_t)CLAMP(pixel.chan.b, 0, 1)) * 0xff / 0x1); /* b */ + dst[3] = 255; /* a */ + src += 12; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32_sscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32_sscaled pixel; + pixel.chan.r = (int32_t)(((uint64_t)src[0]) * 0x1 / 0xff); + pixel.chan.g = (int32_t)(((uint64_t)src[1]) * 0x1 / 0xff); + pixel.chan.b = (int32_t)(((uint64_t)src[2]) * 0x1 / 0xff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 12; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32g32b32a32_sscaled { + struct { + int32_t r; + int32_t g; + int32_t b; + int32_t a; + } chan; +}; + +static INLINE void +util_format_r32g32b32a32_sscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32a32_sscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)pixel.chan.r; /* r */ + dst[1] = (float)pixel.chan.g; /* g */ + dst[2] = (float)pixel.chan.b; /* b */ + dst[3] = (float)pixel.chan.a; /* a */ + src += 16; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32a32_sscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32a32_sscaled pixel; + pixel.chan.r = (int32_t)CLAMP(src[0], -2147483648, 2147483647); + pixel.chan.g = (int32_t)CLAMP(src[1], -2147483648, 2147483647); + pixel.chan.b = (int32_t)CLAMP(src[2], -2147483648, 2147483647); + pixel.chan.a = (int32_t)CLAMP(src[3], -2147483648, 2147483647); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 16; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32g32b32a32_sscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r32g32b32a32_sscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)pixel.chan.r; /* r */ + dst[1] = (float)pixel.chan.g; /* g */ + dst[2] = (float)pixel.chan.b; /* b */ + dst[3] = (float)pixel.chan.a; /* a */ +} + +static INLINE void +util_format_r32g32b32a32_sscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32a32_sscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (uint8_t)(((uint64_t)CLAMP(pixel.chan.r, 0, 1)) * 0xff / 0x1); /* r */ + dst[1] = (uint8_t)(((uint64_t)CLAMP(pixel.chan.g, 0, 1)) * 0xff / 0x1); /* g */ + dst[2] = (uint8_t)(((uint64_t)CLAMP(pixel.chan.b, 0, 1)) * 0xff / 0x1); /* b */ + dst[3] = (uint8_t)(((uint64_t)CLAMP(pixel.chan.a, 0, 1)) * 0xff / 0x1); /* a */ + src += 16; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32a32_sscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32a32_sscaled pixel; + pixel.chan.r = (int32_t)(((uint64_t)src[0]) * 0x1 / 0xff); + pixel.chan.g = (int32_t)(((uint64_t)src[1]) * 0x1 / 0xff); + pixel.chan.b = (int32_t)(((uint64_t)src[2]) * 0x1 / 0xff); + pixel.chan.a = (int32_t)(((uint64_t)src[3]) * 0x1 / 0xff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 16; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16_float { + uint16_t value; + struct { + uint16_t r; + } chan; +}; + +static INLINE void +util_format_r16_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = util_half_to_float(pixel.chan.r); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16_float pixel; + pixel.chan.r = util_float_to_half(src[0]); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r16_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = util_half_to_float(pixel.chan.r); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r16_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = float_to_ubyte(util_half_to_float(pixel.chan.r)); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 255; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16_float pixel; + pixel.chan.r = util_float_to_half((float)(src[0] * (1.0f/0xff))); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16g16_float { + uint32_t value; + struct { + uint16_t r; + uint16_t g; + } chan; +}; + +static INLINE void +util_format_r16g16_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = util_half_to_float(pixel.chan.r); /* r */ + dst[1] = util_half_to_float(pixel.chan.g); /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16_float pixel; + pixel.chan.r = util_float_to_half(src[0]); + pixel.chan.g = util_float_to_half(src[1]); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16g16_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r16g16_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = util_half_to_float(pixel.chan.r); /* r */ + dst[1] = util_half_to_float(pixel.chan.g); /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r16g16_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = float_to_ubyte(util_half_to_float(pixel.chan.r)); /* r */ + dst[1] = float_to_ubyte(util_half_to_float(pixel.chan.g)); /* g */ + dst[2] = 0; /* b */ + dst[3] = 255; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16_float pixel; + pixel.chan.r = util_float_to_half((float)(src[0] * (1.0f/0xff))); + pixel.chan.g = util_float_to_half((float)(src[1] * (1.0f/0xff))); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16g16b16_float { + struct { + uint16_t r; + uint16_t g; + uint16_t b; + } chan; +}; + +static INLINE void +util_format_r16g16b16_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = util_half_to_float(pixel.chan.r); /* r */ + dst[1] = util_half_to_float(pixel.chan.g); /* g */ + dst[2] = util_half_to_float(pixel.chan.b); /* b */ + dst[3] = 1; /* a */ + src += 6; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16_float pixel; + pixel.chan.r = util_float_to_half(src[0]); + pixel.chan.g = util_float_to_half(src[1]); + pixel.chan.b = util_float_to_half(src[2]); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 6; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16g16b16_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r16g16b16_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = util_half_to_float(pixel.chan.r); /* r */ + dst[1] = util_half_to_float(pixel.chan.g); /* g */ + dst[2] = util_half_to_float(pixel.chan.b); /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r16g16b16_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = float_to_ubyte(util_half_to_float(pixel.chan.r)); /* r */ + dst[1] = float_to_ubyte(util_half_to_float(pixel.chan.g)); /* g */ + dst[2] = float_to_ubyte(util_half_to_float(pixel.chan.b)); /* b */ + dst[3] = 255; /* a */ + src += 6; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16_float pixel; + pixel.chan.r = util_float_to_half((float)(src[0] * (1.0f/0xff))); + pixel.chan.g = util_float_to_half((float)(src[1] * (1.0f/0xff))); + pixel.chan.b = util_float_to_half((float)(src[2] * (1.0f/0xff))); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 6; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16g16b16a16_float { + uint64_t value; + struct { + uint16_t r; + uint16_t g; + uint16_t b; + uint16_t a; + } chan; +}; + +static INLINE void +util_format_r16g16b16a16_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16a16_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = util_half_to_float(pixel.chan.r); /* r */ + dst[1] = util_half_to_float(pixel.chan.g); /* g */ + dst[2] = util_half_to_float(pixel.chan.b); /* b */ + dst[3] = util_half_to_float(pixel.chan.a); /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16a16_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16a16_float pixel; + pixel.chan.r = util_float_to_half(src[0]); + pixel.chan.g = util_float_to_half(src[1]); + pixel.chan.b = util_float_to_half(src[2]); + pixel.chan.a = util_float_to_half(src[3]); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16g16b16a16_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r16g16b16a16_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = util_half_to_float(pixel.chan.r); /* r */ + dst[1] = util_half_to_float(pixel.chan.g); /* g */ + dst[2] = util_half_to_float(pixel.chan.b); /* b */ + dst[3] = util_half_to_float(pixel.chan.a); /* a */ +} + +static INLINE void +util_format_r16g16b16a16_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16a16_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = float_to_ubyte(util_half_to_float(pixel.chan.r)); /* r */ + dst[1] = float_to_ubyte(util_half_to_float(pixel.chan.g)); /* g */ + dst[2] = float_to_ubyte(util_half_to_float(pixel.chan.b)); /* b */ + dst[3] = float_to_ubyte(util_half_to_float(pixel.chan.a)); /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16a16_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16a16_float pixel; + pixel.chan.r = util_float_to_half((float)(src[0] * (1.0f/0xff))); + pixel.chan.g = util_float_to_half((float)(src[1] * (1.0f/0xff))); + pixel.chan.b = util_float_to_half((float)(src[2] * (1.0f/0xff))); + pixel.chan.a = util_float_to_half((float)(src[3] * (1.0f/0xff))); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16_unorm { + uint16_t value; + struct { + uint16_t r; + } chan; +}; + +static INLINE void +util_format_r16_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t r; + r = value; + dst[0] = (float)(r * (1.0f/0xffff)); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)util_iround(CLAMP(src[0], 0, 1) * 0xffff); + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + uint16_t r; + r = value; + dst[0] = (float)(r * (1.0f/0xffff)); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r16_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t r; + r = value; + dst[0] = (uint8_t)(r >> 8); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 255; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)(((uint32_t)src[0]) * 0xffff / 0xff); + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16g16_unorm { + uint32_t value; + struct { + uint16_t r; + uint16_t g; + } chan; +}; + +static INLINE void +util_format_r16g16_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + r = (value) & 0xffff; + g = value >> 16; + dst[0] = (float)(r * (1.0f/0xffff)); /* r */ + dst[1] = (float)(g * (1.0f/0xffff)); /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint16_t)util_iround(CLAMP(src[0], 0, 1) * 0xffff)) & 0xffff; + value |= ((uint16_t)util_iround(CLAMP(src[1], 0, 1) * 0xffff)) << 16; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16g16_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + r = (value) & 0xffff; + g = value >> 16; + dst[0] = (float)(r * (1.0f/0xffff)); /* r */ + dst[1] = (float)(g * (1.0f/0xffff)); /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r16g16_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + r = (value) & 0xffff; + g = value >> 16; + dst[0] = (uint8_t)(r >> 8); /* r */ + dst[1] = (uint8_t)(g >> 8); /* g */ + dst[2] = 0; /* b */ + dst[3] = 255; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint16_t)(((uint32_t)src[0]) * 0xffff / 0xff)) & 0xffff; + value |= ((uint16_t)(((uint32_t)src[1]) * 0xffff / 0xff)) << 16; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16g16b16_unorm { + struct { + uint16_t r; + uint16_t g; + uint16_t b; + } chan; +}; + +static INLINE void +util_format_r16g16b16_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16_unorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)(pixel.chan.r * (1.0f/0xffff)); /* r */ + dst[1] = (float)(pixel.chan.g * (1.0f/0xffff)); /* g */ + dst[2] = (float)(pixel.chan.b * (1.0f/0xffff)); /* b */ + dst[3] = 1; /* a */ + src += 6; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16_unorm pixel; + pixel.chan.r = (uint16_t)util_iround(CLAMP(src[0], 0, 1) * 0xffff); + pixel.chan.g = (uint16_t)util_iround(CLAMP(src[1], 0, 1) * 0xffff); + pixel.chan.b = (uint16_t)util_iround(CLAMP(src[2], 0, 1) * 0xffff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 6; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16g16b16_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r16g16b16_unorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)(pixel.chan.r * (1.0f/0xffff)); /* r */ + dst[1] = (float)(pixel.chan.g * (1.0f/0xffff)); /* g */ + dst[2] = (float)(pixel.chan.b * (1.0f/0xffff)); /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r16g16b16_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16_unorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (uint8_t)(pixel.chan.r >> 8); /* r */ + dst[1] = (uint8_t)(pixel.chan.g >> 8); /* g */ + dst[2] = (uint8_t)(pixel.chan.b >> 8); /* b */ + dst[3] = 255; /* a */ + src += 6; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16_unorm pixel; + pixel.chan.r = (uint16_t)(((uint32_t)src[0]) * 0xffff / 0xff); + pixel.chan.g = (uint16_t)(((uint32_t)src[1]) * 0xffff / 0xff); + pixel.chan.b = (uint16_t)(((uint32_t)src[2]) * 0xffff / 0xff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 6; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16g16b16a16_unorm { + uint64_t value; + struct { + uint16_t r; + uint16_t g; + uint16_t b; + uint16_t a; + } chan; +}; + +static INLINE void +util_format_r16g16b16a16_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16a16_unorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)(pixel.chan.r * (1.0f/0xffff)); /* r */ + dst[1] = (float)(pixel.chan.g * (1.0f/0xffff)); /* g */ + dst[2] = (float)(pixel.chan.b * (1.0f/0xffff)); /* b */ + dst[3] = (float)(pixel.chan.a * (1.0f/0xffff)); /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16a16_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16a16_unorm pixel; + pixel.chan.r = (uint16_t)util_iround(CLAMP(src[0], 0, 1) * 0xffff); + pixel.chan.g = (uint16_t)util_iround(CLAMP(src[1], 0, 1) * 0xffff); + pixel.chan.b = (uint16_t)util_iround(CLAMP(src[2], 0, 1) * 0xffff); + pixel.chan.a = (uint16_t)util_iround(CLAMP(src[3], 0, 1) * 0xffff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16g16b16a16_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r16g16b16a16_unorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)(pixel.chan.r * (1.0f/0xffff)); /* r */ + dst[1] = (float)(pixel.chan.g * (1.0f/0xffff)); /* g */ + dst[2] = (float)(pixel.chan.b * (1.0f/0xffff)); /* b */ + dst[3] = (float)(pixel.chan.a * (1.0f/0xffff)); /* a */ +} + +static INLINE void +util_format_r16g16b16a16_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16a16_unorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (uint8_t)(pixel.chan.r >> 8); /* r */ + dst[1] = (uint8_t)(pixel.chan.g >> 8); /* g */ + dst[2] = (uint8_t)(pixel.chan.b >> 8); /* b */ + dst[3] = (uint8_t)(pixel.chan.a >> 8); /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16a16_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16a16_unorm pixel; + pixel.chan.r = (uint16_t)(((uint32_t)src[0]) * 0xffff / 0xff); + pixel.chan.g = (uint16_t)(((uint32_t)src[1]) * 0xffff / 0xff); + pixel.chan.b = (uint16_t)(((uint32_t)src[2]) * 0xffff / 0xff); + pixel.chan.a = (uint16_t)(((uint32_t)src[3]) * 0xffff / 0xff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16_uscaled { + uint16_t value; + struct { + uint16_t r; + } chan; +}; + +static INLINE void +util_format_r16_uscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t r; + r = value; + dst[0] = (float)r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16_uscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)CLAMP(src[0], 0, 65535); + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16_uscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + uint16_t r; + r = value; + dst[0] = (float)r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r16_uscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t r; + r = value; + dst[0] = (uint8_t)(((uint32_t)MIN2(r, 1)) * 0xff / 0x1); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 255; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16_uscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)(((uint32_t)src[0]) * 0x1 / 0xff); + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16g16_uscaled { + uint32_t value; + struct { + uint16_t r; + uint16_t g; + } chan; +}; + +static INLINE void +util_format_r16g16_uscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + r = (value) & 0xffff; + g = value >> 16; + dst[0] = (float)r; /* r */ + dst[1] = (float)g; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16_uscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint16_t)CLAMP(src[0], 0, 65535)) & 0xffff; + value |= ((uint16_t)CLAMP(src[1], 0, 65535)) << 16; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16g16_uscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + r = (value) & 0xffff; + g = value >> 16; + dst[0] = (float)r; /* r */ + dst[1] = (float)g; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r16g16_uscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + r = (value) & 0xffff; + g = value >> 16; + dst[0] = (uint8_t)(((uint32_t)MIN2(r, 1)) * 0xff / 0x1); /* r */ + dst[1] = (uint8_t)(((uint32_t)MIN2(g, 1)) * 0xff / 0x1); /* g */ + dst[2] = 0; /* b */ + dst[3] = 255; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16_uscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint16_t)(((uint32_t)src[0]) * 0x1 / 0xff)) & 0xffff; + value |= ((uint16_t)(((uint32_t)src[1]) * 0x1 / 0xff)) << 16; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16g16b16_uscaled { + struct { + uint16_t r; + uint16_t g; + uint16_t b; + } chan; +}; + +static INLINE void +util_format_r16g16b16_uscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16_uscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)pixel.chan.r; /* r */ + dst[1] = (float)pixel.chan.g; /* g */ + dst[2] = (float)pixel.chan.b; /* b */ + dst[3] = 1; /* a */ + src += 6; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16_uscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16_uscaled pixel; + pixel.chan.r = (uint16_t)CLAMP(src[0], 0, 65535); + pixel.chan.g = (uint16_t)CLAMP(src[1], 0, 65535); + pixel.chan.b = (uint16_t)CLAMP(src[2], 0, 65535); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 6; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16g16b16_uscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r16g16b16_uscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)pixel.chan.r; /* r */ + dst[1] = (float)pixel.chan.g; /* g */ + dst[2] = (float)pixel.chan.b; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r16g16b16_uscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16_uscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (uint8_t)(((uint32_t)MIN2(pixel.chan.r, 1)) * 0xff / 0x1); /* r */ + dst[1] = (uint8_t)(((uint32_t)MIN2(pixel.chan.g, 1)) * 0xff / 0x1); /* g */ + dst[2] = (uint8_t)(((uint32_t)MIN2(pixel.chan.b, 1)) * 0xff / 0x1); /* b */ + dst[3] = 255; /* a */ + src += 6; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16_uscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16_uscaled pixel; + pixel.chan.r = (uint16_t)(((uint32_t)src[0]) * 0x1 / 0xff); + pixel.chan.g = (uint16_t)(((uint32_t)src[1]) * 0x1 / 0xff); + pixel.chan.b = (uint16_t)(((uint32_t)src[2]) * 0x1 / 0xff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 6; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16g16b16a16_uscaled { + uint64_t value; + struct { + uint16_t r; + uint16_t g; + uint16_t b; + uint16_t a; + } chan; +}; + +static INLINE void +util_format_r16g16b16a16_uscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16a16_uscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)pixel.chan.r; /* r */ + dst[1] = (float)pixel.chan.g; /* g */ + dst[2] = (float)pixel.chan.b; /* b */ + dst[3] = (float)pixel.chan.a; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16a16_uscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16a16_uscaled pixel; + pixel.chan.r = (uint16_t)CLAMP(src[0], 0, 65535); + pixel.chan.g = (uint16_t)CLAMP(src[1], 0, 65535); + pixel.chan.b = (uint16_t)CLAMP(src[2], 0, 65535); + pixel.chan.a = (uint16_t)CLAMP(src[3], 0, 65535); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16g16b16a16_uscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r16g16b16a16_uscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)pixel.chan.r; /* r */ + dst[1] = (float)pixel.chan.g; /* g */ + dst[2] = (float)pixel.chan.b; /* b */ + dst[3] = (float)pixel.chan.a; /* a */ +} + +static INLINE void +util_format_r16g16b16a16_uscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16a16_uscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (uint8_t)(((uint32_t)MIN2(pixel.chan.r, 1)) * 0xff / 0x1); /* r */ + dst[1] = (uint8_t)(((uint32_t)MIN2(pixel.chan.g, 1)) * 0xff / 0x1); /* g */ + dst[2] = (uint8_t)(((uint32_t)MIN2(pixel.chan.b, 1)) * 0xff / 0x1); /* b */ + dst[3] = (uint8_t)(((uint32_t)MIN2(pixel.chan.a, 1)) * 0xff / 0x1); /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16a16_uscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16a16_uscaled pixel; + pixel.chan.r = (uint16_t)(((uint32_t)src[0]) * 0x1 / 0xff); + pixel.chan.g = (uint16_t)(((uint32_t)src[1]) * 0x1 / 0xff); + pixel.chan.b = (uint16_t)(((uint32_t)src[2]) * 0x1 / 0xff); + pixel.chan.a = (uint16_t)(((uint32_t)src[3]) * 0x1 / 0xff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16_snorm { + uint16_t value; + struct { + int16_t r; + } chan; +}; + +static INLINE void +util_format_r16_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + int16_t r; + r = (int16_t)(value) ; + dst[0] = (float)(r * (1.0f/0x7fff)); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)((int16_t)util_iround(CLAMP(src[0], -1, 1) * 0x7fff)) ; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + int16_t r; + r = (int16_t)(value) ; + dst[0] = (float)(r * (1.0f/0x7fff)); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r16_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + int16_t r; + r = (int16_t)(value) ; + dst[0] = (uint8_t)(MAX2(r, 0) >> 7); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 255; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)((int16_t)(((uint32_t)src[0]) * 0x7fff / 0xff)) ; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16g16_snorm { + uint32_t value; + struct { + int16_t r; + int16_t g; + } chan; +}; + +static INLINE void +util_format_r16g16_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + r = ((int32_t)(value << 16) ) >> 16; + g = ((int32_t)(value) ) >> 16; + dst[0] = (float)(r * (1.0f/0x7fff)); /* r */ + dst[1] = (float)(g * (1.0f/0x7fff)); /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((int16_t)util_iround(CLAMP(src[0], -1, 1) * 0x7fff)) & 0xffff) ; + value |= (uint32_t)(((int16_t)util_iround(CLAMP(src[1], -1, 1) * 0x7fff)) << 16) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16g16_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + r = ((int32_t)(value << 16) ) >> 16; + g = ((int32_t)(value) ) >> 16; + dst[0] = (float)(r * (1.0f/0x7fff)); /* r */ + dst[1] = (float)(g * (1.0f/0x7fff)); /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r16g16_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + r = ((int32_t)(value << 16) ) >> 16; + g = ((int32_t)(value) ) >> 16; + dst[0] = (uint8_t)(MAX2(r, 0) >> 7); /* r */ + dst[1] = (uint8_t)(MAX2(g, 0) >> 7); /* g */ + dst[2] = 0; /* b */ + dst[3] = 255; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((int16_t)(((uint32_t)src[0]) * 0x7fff / 0xff)) & 0xffff) ; + value |= (uint32_t)(((int16_t)(((uint32_t)src[1]) * 0x7fff / 0xff)) << 16) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16g16b16_snorm { + struct { + int16_t r; + int16_t g; + int16_t b; + } chan; +}; + +static INLINE void +util_format_r16g16b16_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16_snorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)(pixel.chan.r * (1.0f/0x7fff)); /* r */ + dst[1] = (float)(pixel.chan.g * (1.0f/0x7fff)); /* g */ + dst[2] = (float)(pixel.chan.b * (1.0f/0x7fff)); /* b */ + dst[3] = 1; /* a */ + src += 6; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16_snorm pixel; + pixel.chan.r = (int16_t)util_iround(CLAMP(src[0], -1, 1) * 0x7fff); + pixel.chan.g = (int16_t)util_iround(CLAMP(src[1], -1, 1) * 0x7fff); + pixel.chan.b = (int16_t)util_iround(CLAMP(src[2], -1, 1) * 0x7fff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 6; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16g16b16_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r16g16b16_snorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)(pixel.chan.r * (1.0f/0x7fff)); /* r */ + dst[1] = (float)(pixel.chan.g * (1.0f/0x7fff)); /* g */ + dst[2] = (float)(pixel.chan.b * (1.0f/0x7fff)); /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r16g16b16_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16_snorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (uint8_t)(MAX2(pixel.chan.r, 0) >> 7); /* r */ + dst[1] = (uint8_t)(MAX2(pixel.chan.g, 0) >> 7); /* g */ + dst[2] = (uint8_t)(MAX2(pixel.chan.b, 0) >> 7); /* b */ + dst[3] = 255; /* a */ + src += 6; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16_snorm pixel; + pixel.chan.r = (int16_t)(((uint32_t)src[0]) * 0x7fff / 0xff); + pixel.chan.g = (int16_t)(((uint32_t)src[1]) * 0x7fff / 0xff); + pixel.chan.b = (int16_t)(((uint32_t)src[2]) * 0x7fff / 0xff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 6; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16g16b16a16_snorm { + uint64_t value; + struct { + int16_t r; + int16_t g; + int16_t b; + int16_t a; + } chan; +}; + +static INLINE void +util_format_r16g16b16a16_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16a16_snorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)(pixel.chan.r * (1.0f/0x7fff)); /* r */ + dst[1] = (float)(pixel.chan.g * (1.0f/0x7fff)); /* g */ + dst[2] = (float)(pixel.chan.b * (1.0f/0x7fff)); /* b */ + dst[3] = (float)(pixel.chan.a * (1.0f/0x7fff)); /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16a16_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16a16_snorm pixel; + pixel.chan.r = (int16_t)util_iround(CLAMP(src[0], -1, 1) * 0x7fff); + pixel.chan.g = (int16_t)util_iround(CLAMP(src[1], -1, 1) * 0x7fff); + pixel.chan.b = (int16_t)util_iround(CLAMP(src[2], -1, 1) * 0x7fff); + pixel.chan.a = (int16_t)util_iround(CLAMP(src[3], -1, 1) * 0x7fff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16g16b16a16_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r16g16b16a16_snorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)(pixel.chan.r * (1.0f/0x7fff)); /* r */ + dst[1] = (float)(pixel.chan.g * (1.0f/0x7fff)); /* g */ + dst[2] = (float)(pixel.chan.b * (1.0f/0x7fff)); /* b */ + dst[3] = (float)(pixel.chan.a * (1.0f/0x7fff)); /* a */ +} + +static INLINE void +util_format_r16g16b16a16_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16a16_snorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (uint8_t)(MAX2(pixel.chan.r, 0) >> 7); /* r */ + dst[1] = (uint8_t)(MAX2(pixel.chan.g, 0) >> 7); /* g */ + dst[2] = (uint8_t)(MAX2(pixel.chan.b, 0) >> 7); /* b */ + dst[3] = (uint8_t)(MAX2(pixel.chan.a, 0) >> 7); /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16a16_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16a16_snorm pixel; + pixel.chan.r = (int16_t)(((uint32_t)src[0]) * 0x7fff / 0xff); + pixel.chan.g = (int16_t)(((uint32_t)src[1]) * 0x7fff / 0xff); + pixel.chan.b = (int16_t)(((uint32_t)src[2]) * 0x7fff / 0xff); + pixel.chan.a = (int16_t)(((uint32_t)src[3]) * 0x7fff / 0xff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16_sscaled { + uint16_t value; + struct { + int16_t r; + } chan; +}; + +static INLINE void +util_format_r16_sscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + int16_t r; + r = (int16_t)(value) ; + dst[0] = (float)r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16_sscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)((int16_t)CLAMP(src[0], -32768, 32767)) ; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16_sscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + int16_t r; + r = (int16_t)(value) ; + dst[0] = (float)r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r16_sscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + int16_t r; + r = (int16_t)(value) ; + dst[0] = (uint8_t)(((uint32_t)CLAMP(r, 0, 1)) * 0xff / 0x1); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 255; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16_sscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)((int16_t)(((uint32_t)src[0]) * 0x1 / 0xff)) ; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16g16_sscaled { + uint32_t value; + struct { + int16_t r; + int16_t g; + } chan; +}; + +static INLINE void +util_format_r16g16_sscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + r = ((int32_t)(value << 16) ) >> 16; + g = ((int32_t)(value) ) >> 16; + dst[0] = (float)r; /* r */ + dst[1] = (float)g; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16_sscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((int16_t)CLAMP(src[0], -32768, 32767)) & 0xffff) ; + value |= (uint32_t)(((int16_t)CLAMP(src[1], -32768, 32767)) << 16) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16g16_sscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + r = ((int32_t)(value << 16) ) >> 16; + g = ((int32_t)(value) ) >> 16; + dst[0] = (float)r; /* r */ + dst[1] = (float)g; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r16g16_sscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + r = ((int32_t)(value << 16) ) >> 16; + g = ((int32_t)(value) ) >> 16; + dst[0] = (uint8_t)(((uint32_t)CLAMP(r, 0, 1)) * 0xff / 0x1); /* r */ + dst[1] = (uint8_t)(((uint32_t)CLAMP(g, 0, 1)) * 0xff / 0x1); /* g */ + dst[2] = 0; /* b */ + dst[3] = 255; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16_sscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((int16_t)(((uint32_t)src[0]) * 0x1 / 0xff)) & 0xffff) ; + value |= (uint32_t)(((int16_t)(((uint32_t)src[1]) * 0x1 / 0xff)) << 16) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16g16b16_sscaled { + struct { + int16_t r; + int16_t g; + int16_t b; + } chan; +}; + +static INLINE void +util_format_r16g16b16_sscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16_sscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)pixel.chan.r; /* r */ + dst[1] = (float)pixel.chan.g; /* g */ + dst[2] = (float)pixel.chan.b; /* b */ + dst[3] = 1; /* a */ + src += 6; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16_sscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16_sscaled pixel; + pixel.chan.r = (int16_t)CLAMP(src[0], -32768, 32767); + pixel.chan.g = (int16_t)CLAMP(src[1], -32768, 32767); + pixel.chan.b = (int16_t)CLAMP(src[2], -32768, 32767); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 6; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16g16b16_sscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r16g16b16_sscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)pixel.chan.r; /* r */ + dst[1] = (float)pixel.chan.g; /* g */ + dst[2] = (float)pixel.chan.b; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r16g16b16_sscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16_sscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (uint8_t)(((uint32_t)CLAMP(pixel.chan.r, 0, 1)) * 0xff / 0x1); /* r */ + dst[1] = (uint8_t)(((uint32_t)CLAMP(pixel.chan.g, 0, 1)) * 0xff / 0x1); /* g */ + dst[2] = (uint8_t)(((uint32_t)CLAMP(pixel.chan.b, 0, 1)) * 0xff / 0x1); /* b */ + dst[3] = 255; /* a */ + src += 6; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16_sscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16_sscaled pixel; + pixel.chan.r = (int16_t)(((uint32_t)src[0]) * 0x1 / 0xff); + pixel.chan.g = (int16_t)(((uint32_t)src[1]) * 0x1 / 0xff); + pixel.chan.b = (int16_t)(((uint32_t)src[2]) * 0x1 / 0xff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 6; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16g16b16a16_sscaled { + uint64_t value; + struct { + int16_t r; + int16_t g; + int16_t b; + int16_t a; + } chan; +}; + +static INLINE void +util_format_r16g16b16a16_sscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16a16_sscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)pixel.chan.r; /* r */ + dst[1] = (float)pixel.chan.g; /* g */ + dst[2] = (float)pixel.chan.b; /* b */ + dst[3] = (float)pixel.chan.a; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16a16_sscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16a16_sscaled pixel; + pixel.chan.r = (int16_t)CLAMP(src[0], -32768, 32767); + pixel.chan.g = (int16_t)CLAMP(src[1], -32768, 32767); + pixel.chan.b = (int16_t)CLAMP(src[2], -32768, 32767); + pixel.chan.a = (int16_t)CLAMP(src[3], -32768, 32767); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16g16b16a16_sscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r16g16b16a16_sscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)pixel.chan.r; /* r */ + dst[1] = (float)pixel.chan.g; /* g */ + dst[2] = (float)pixel.chan.b; /* b */ + dst[3] = (float)pixel.chan.a; /* a */ +} + +static INLINE void +util_format_r16g16b16a16_sscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16a16_sscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (uint8_t)(((uint32_t)CLAMP(pixel.chan.r, 0, 1)) * 0xff / 0x1); /* r */ + dst[1] = (uint8_t)(((uint32_t)CLAMP(pixel.chan.g, 0, 1)) * 0xff / 0x1); /* g */ + dst[2] = (uint8_t)(((uint32_t)CLAMP(pixel.chan.b, 0, 1)) * 0xff / 0x1); /* b */ + dst[3] = (uint8_t)(((uint32_t)CLAMP(pixel.chan.a, 0, 1)) * 0xff / 0x1); /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16a16_sscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16a16_sscaled pixel; + pixel.chan.r = (int16_t)(((uint32_t)src[0]) * 0x1 / 0xff); + pixel.chan.g = (int16_t)(((uint32_t)src[1]) * 0x1 / 0xff); + pixel.chan.b = (int16_t)(((uint32_t)src[2]) * 0x1 / 0xff); + pixel.chan.a = (int16_t)(((uint32_t)src[3]) * 0x1 / 0xff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8_unorm { + uint8_t value; + struct { + uint8_t r; + } chan; +}; + +static INLINE void +util_format_r8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + uint8_t r; + r = value; + dst[0] = ubyte_to_float(r); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= float_to_ubyte(src[0]); + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint8_t value = *(const uint8_t *)src; + uint8_t r; + r = value; + dst[0] = ubyte_to_float(r); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + uint8_t r; + r = value; + dst[0] = r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 255; /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= src[0]; + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8g8_unorm { + uint16_t value; + struct { + uint8_t r; + uint8_t g; + } chan; +}; + +static INLINE void +util_format_r8g8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t r; + uint16_t g; + r = (value) & 0xff; + g = value >> 8; + dst[0] = ubyte_to_float(r); /* r */ + dst[1] = ubyte_to_float(g); /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (float_to_ubyte(src[0])) & 0xff; + value |= (float_to_ubyte(src[1])) << 8; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8g8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + uint16_t r; + uint16_t g; + r = (value) & 0xff; + g = value >> 8; + dst[0] = ubyte_to_float(r); /* r */ + dst[1] = ubyte_to_float(g); /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r8g8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t r; + uint16_t g; + r = (value) & 0xff; + g = value >> 8; + dst[0] = r; /* r */ + dst[1] = g; /* g */ + dst[2] = 0; /* b */ + dst[3] = 255; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (src[0]) & 0xff; + value |= (src[1]) << 8; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8g8b8_unorm { + struct { + uint8_t r; + uint8_t g; + uint8_t b; + } chan; +}; + +static INLINE void +util_format_r8g8b8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r8g8b8_unorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = ubyte_to_float(pixel.chan.r); /* r */ + dst[1] = ubyte_to_float(pixel.chan.g); /* g */ + dst[2] = ubyte_to_float(pixel.chan.b); /* b */ + dst[3] = 1; /* a */ + src += 3; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r8g8b8_unorm pixel; + pixel.chan.r = float_to_ubyte(src[0]); + pixel.chan.g = float_to_ubyte(src[1]); + pixel.chan.b = float_to_ubyte(src[2]); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 3; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8g8b8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r8g8b8_unorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = ubyte_to_float(pixel.chan.r); /* r */ + dst[1] = ubyte_to_float(pixel.chan.g); /* g */ + dst[2] = ubyte_to_float(pixel.chan.b); /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r8g8b8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r8g8b8_unorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.r; /* r */ + dst[1] = pixel.chan.g; /* g */ + dst[2] = pixel.chan.b; /* b */ + dst[3] = 255; /* a */ + src += 3; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r8g8b8_unorm pixel; + pixel.chan.r = src[0]; + pixel.chan.g = src[1]; + pixel.chan.b = src[2]; + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 3; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8g8b8a8_unorm { + uint32_t value; + struct { + uint8_t r; + uint8_t g; + uint8_t b; + uint8_t a; + } chan; +}; + +static INLINE void +util_format_r8g8b8a8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + uint32_t a; + r = (value) & 0xff; + g = (value >> 8) & 0xff; + b = (value >> 16) & 0xff; + a = value >> 24; + dst[0] = ubyte_to_float(r); /* r */ + dst[1] = ubyte_to_float(g); /* g */ + dst[2] = ubyte_to_float(b); /* b */ + dst[3] = ubyte_to_float(a); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8a8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (float_to_ubyte(src[0])) & 0xff; + value |= ((float_to_ubyte(src[1])) & 0xff) << 8; + value |= ((float_to_ubyte(src[2])) & 0xff) << 16; + value |= (float_to_ubyte(src[3])) << 24; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8g8b8a8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + uint32_t a; + r = (value) & 0xff; + g = (value >> 8) & 0xff; + b = (value >> 16) & 0xff; + a = value >> 24; + dst[0] = ubyte_to_float(r); /* r */ + dst[1] = ubyte_to_float(g); /* g */ + dst[2] = ubyte_to_float(b); /* b */ + dst[3] = ubyte_to_float(a); /* a */ +} + +static INLINE void +util_format_r8g8b8a8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + uint32_t a; + r = (value) & 0xff; + g = (value >> 8) & 0xff; + b = (value >> 16) & 0xff; + a = value >> 24; + dst[0] = r; /* r */ + dst[1] = g; /* g */ + dst[2] = b; /* b */ + dst[3] = a; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8a8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (src[0]) & 0xff; + value |= ((src[1]) & 0xff) << 8; + value |= ((src[2]) & 0xff) << 16; + value |= (src[3]) << 24; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8_uscaled { + uint8_t value; + struct { + uint8_t r; + } chan; +}; + +static INLINE void +util_format_r8_uscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + uint8_t r; + r = value; + dst[0] = (float)r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8_uscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= (uint8_t)CLAMP(src[0], 0, 255); + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8_uscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint8_t value = *(const uint8_t *)src; + uint8_t r; + r = value; + dst[0] = (float)r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r8_uscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + uint8_t r; + r = value; + dst[0] = (uint8_t)(((uint32_t)MIN2(r, 1)) * 0xff / 0x1); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 255; /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8_uscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= (uint8_t)(((uint32_t)src[0]) * 0x1 / 0xff); + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8g8_uscaled { + uint16_t value; + struct { + uint8_t r; + uint8_t g; + } chan; +}; + +static INLINE void +util_format_r8g8_uscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t r; + uint16_t g; + r = (value) & 0xff; + g = value >> 8; + dst[0] = (float)r; /* r */ + dst[1] = (float)g; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8_uscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= ((uint8_t)CLAMP(src[0], 0, 255)) & 0xff; + value |= ((uint8_t)CLAMP(src[1], 0, 255)) << 8; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8g8_uscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + uint16_t r; + uint16_t g; + r = (value) & 0xff; + g = value >> 8; + dst[0] = (float)r; /* r */ + dst[1] = (float)g; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r8g8_uscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t r; + uint16_t g; + r = (value) & 0xff; + g = value >> 8; + dst[0] = (uint8_t)(((uint32_t)MIN2(r, 1)) * 0xff / 0x1); /* r */ + dst[1] = (uint8_t)(((uint32_t)MIN2(g, 1)) * 0xff / 0x1); /* g */ + dst[2] = 0; /* b */ + dst[3] = 255; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8_uscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= ((uint8_t)(((uint32_t)src[0]) * 0x1 / 0xff)) & 0xff; + value |= ((uint8_t)(((uint32_t)src[1]) * 0x1 / 0xff)) << 8; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8g8b8_uscaled { + struct { + uint8_t r; + uint8_t g; + uint8_t b; + } chan; +}; + +static INLINE void +util_format_r8g8b8_uscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r8g8b8_uscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)pixel.chan.r; /* r */ + dst[1] = (float)pixel.chan.g; /* g */ + dst[2] = (float)pixel.chan.b; /* b */ + dst[3] = 1; /* a */ + src += 3; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8_uscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r8g8b8_uscaled pixel; + pixel.chan.r = (uint8_t)CLAMP(src[0], 0, 255); + pixel.chan.g = (uint8_t)CLAMP(src[1], 0, 255); + pixel.chan.b = (uint8_t)CLAMP(src[2], 0, 255); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 3; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8g8b8_uscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r8g8b8_uscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)pixel.chan.r; /* r */ + dst[1] = (float)pixel.chan.g; /* g */ + dst[2] = (float)pixel.chan.b; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r8g8b8_uscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r8g8b8_uscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (uint8_t)(((uint32_t)MIN2(pixel.chan.r, 1)) * 0xff / 0x1); /* r */ + dst[1] = (uint8_t)(((uint32_t)MIN2(pixel.chan.g, 1)) * 0xff / 0x1); /* g */ + dst[2] = (uint8_t)(((uint32_t)MIN2(pixel.chan.b, 1)) * 0xff / 0x1); /* b */ + dst[3] = 255; /* a */ + src += 3; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8_uscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r8g8b8_uscaled pixel; + pixel.chan.r = (uint8_t)(((uint32_t)src[0]) * 0x1 / 0xff); + pixel.chan.g = (uint8_t)(((uint32_t)src[1]) * 0x1 / 0xff); + pixel.chan.b = (uint8_t)(((uint32_t)src[2]) * 0x1 / 0xff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 3; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8g8b8a8_uscaled { + uint32_t value; + struct { + uint8_t r; + uint8_t g; + uint8_t b; + uint8_t a; + } chan; +}; + +static INLINE void +util_format_r8g8b8a8_uscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + uint32_t a; + r = (value) & 0xff; + g = (value >> 8) & 0xff; + b = (value >> 16) & 0xff; + a = value >> 24; + dst[0] = (float)r; /* r */ + dst[1] = (float)g; /* g */ + dst[2] = (float)b; /* b */ + dst[3] = (float)a; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8a8_uscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint8_t)CLAMP(src[0], 0, 255)) & 0xff; + value |= (((uint8_t)CLAMP(src[1], 0, 255)) & 0xff) << 8; + value |= (((uint8_t)CLAMP(src[2], 0, 255)) & 0xff) << 16; + value |= ((uint8_t)CLAMP(src[3], 0, 255)) << 24; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8g8b8a8_uscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + uint32_t a; + r = (value) & 0xff; + g = (value >> 8) & 0xff; + b = (value >> 16) & 0xff; + a = value >> 24; + dst[0] = (float)r; /* r */ + dst[1] = (float)g; /* g */ + dst[2] = (float)b; /* b */ + dst[3] = (float)a; /* a */ +} + +static INLINE void +util_format_r8g8b8a8_uscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + uint32_t a; + r = (value) & 0xff; + g = (value >> 8) & 0xff; + b = (value >> 16) & 0xff; + a = value >> 24; + dst[0] = (uint8_t)(((uint32_t)MIN2(r, 1)) * 0xff / 0x1); /* r */ + dst[1] = (uint8_t)(((uint32_t)MIN2(g, 1)) * 0xff / 0x1); /* g */ + dst[2] = (uint8_t)(((uint32_t)MIN2(b, 1)) * 0xff / 0x1); /* b */ + dst[3] = (uint8_t)(((uint32_t)MIN2(a, 1)) * 0xff / 0x1); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8a8_uscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint8_t)(((uint32_t)src[0]) * 0x1 / 0xff)) & 0xff; + value |= (((uint8_t)(((uint32_t)src[1]) * 0x1 / 0xff)) & 0xff) << 8; + value |= (((uint8_t)(((uint32_t)src[2]) * 0x1 / 0xff)) & 0xff) << 16; + value |= ((uint8_t)(((uint32_t)src[3]) * 0x1 / 0xff)) << 24; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8_snorm { + uint8_t value; + struct { + int8_t r; + } chan; +}; + +static INLINE void +util_format_r8_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + int8_t r; + r = (int8_t)(value) ; + dst[0] = (float)(r * (1.0f/0x7f)); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= (uint8_t)((int8_t)util_iround(CLAMP(src[0], -1, 1) * 0x7f)) ; + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint8_t value = *(const uint8_t *)src; + int8_t r; + r = (int8_t)(value) ; + dst[0] = (float)(r * (1.0f/0x7f)); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r8_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + int8_t r; + r = (int8_t)(value) ; + dst[0] = (uint8_t)(((uint32_t)MAX2(r, 0)) * 0xff / 0x7f); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 255; /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= (uint8_t)((int8_t)(src[0] >> 1)) ; + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8g8_snorm { + uint16_t value; + struct { + int8_t r; + int8_t g; + } chan; +}; + +static INLINE void +util_format_r8g8_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + int16_t r; + int16_t g; + r = ((int16_t)(value << 8) ) >> 8; + g = ((int16_t)(value) ) >> 8; + dst[0] = (float)(r * (1.0f/0x7f)); /* r */ + dst[1] = (float)(g * (1.0f/0x7f)); /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)(((int8_t)util_iround(CLAMP(src[0], -1, 1) * 0x7f)) & 0xff) ; + value |= (uint16_t)(((int8_t)util_iround(CLAMP(src[1], -1, 1) * 0x7f)) << 8) ; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8g8_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + int16_t r; + int16_t g; + r = ((int16_t)(value << 8) ) >> 8; + g = ((int16_t)(value) ) >> 8; + dst[0] = (float)(r * (1.0f/0x7f)); /* r */ + dst[1] = (float)(g * (1.0f/0x7f)); /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r8g8_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + int16_t r; + int16_t g; + r = ((int16_t)(value << 8) ) >> 8; + g = ((int16_t)(value) ) >> 8; + dst[0] = (uint8_t)(((uint32_t)MAX2(r, 0)) * 0xff / 0x7f); /* r */ + dst[1] = (uint8_t)(((uint32_t)MAX2(g, 0)) * 0xff / 0x7f); /* g */ + dst[2] = 0; /* b */ + dst[3] = 255; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)(((int8_t)(src[0] >> 1)) & 0xff) ; + value |= (uint16_t)(((int8_t)(src[1] >> 1)) << 8) ; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8g8b8_snorm { + struct { + int8_t r; + int8_t g; + int8_t b; + } chan; +}; + +static INLINE void +util_format_r8g8b8_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r8g8b8_snorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)(pixel.chan.r * (1.0f/0x7f)); /* r */ + dst[1] = (float)(pixel.chan.g * (1.0f/0x7f)); /* g */ + dst[2] = (float)(pixel.chan.b * (1.0f/0x7f)); /* b */ + dst[3] = 1; /* a */ + src += 3; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r8g8b8_snorm pixel; + pixel.chan.r = (int8_t)util_iround(CLAMP(src[0], -1, 1) * 0x7f); + pixel.chan.g = (int8_t)util_iround(CLAMP(src[1], -1, 1) * 0x7f); + pixel.chan.b = (int8_t)util_iround(CLAMP(src[2], -1, 1) * 0x7f); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 3; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8g8b8_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r8g8b8_snorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)(pixel.chan.r * (1.0f/0x7f)); /* r */ + dst[1] = (float)(pixel.chan.g * (1.0f/0x7f)); /* g */ + dst[2] = (float)(pixel.chan.b * (1.0f/0x7f)); /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r8g8b8_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r8g8b8_snorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (uint8_t)(((uint32_t)MAX2(pixel.chan.r, 0)) * 0xff / 0x7f); /* r */ + dst[1] = (uint8_t)(((uint32_t)MAX2(pixel.chan.g, 0)) * 0xff / 0x7f); /* g */ + dst[2] = (uint8_t)(((uint32_t)MAX2(pixel.chan.b, 0)) * 0xff / 0x7f); /* b */ + dst[3] = 255; /* a */ + src += 3; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r8g8b8_snorm pixel; + pixel.chan.r = (int8_t)(src[0] >> 1); + pixel.chan.g = (int8_t)(src[1] >> 1); + pixel.chan.b = (int8_t)(src[2] >> 1); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 3; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8g8b8a8_snorm { + uint32_t value; + struct { + int8_t r; + int8_t g; + int8_t b; + int8_t a; + } chan; +}; + +static INLINE void +util_format_r8g8b8a8_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + int32_t b; + int32_t a; + r = ((int32_t)(value << 24) ) >> 24; + g = ((int32_t)(value << 16) ) >> 24; + b = ((int32_t)(value << 8) ) >> 24; + a = ((int32_t)(value) ) >> 24; + dst[0] = (float)(r * (1.0f/0x7f)); /* r */ + dst[1] = (float)(g * (1.0f/0x7f)); /* g */ + dst[2] = (float)(b * (1.0f/0x7f)); /* b */ + dst[3] = (float)(a * (1.0f/0x7f)); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8a8_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((int8_t)util_iround(CLAMP(src[0], -1, 1) * 0x7f)) & 0xff) ; + value |= (uint32_t)((((int8_t)util_iround(CLAMP(src[1], -1, 1) * 0x7f)) & 0xff) << 8) ; + value |= (uint32_t)((((int8_t)util_iround(CLAMP(src[2], -1, 1) * 0x7f)) & 0xff) << 16) ; + value |= (uint32_t)(((int8_t)util_iround(CLAMP(src[3], -1, 1) * 0x7f)) << 24) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8g8b8a8_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + int32_t b; + int32_t a; + r = ((int32_t)(value << 24) ) >> 24; + g = ((int32_t)(value << 16) ) >> 24; + b = ((int32_t)(value << 8) ) >> 24; + a = ((int32_t)(value) ) >> 24; + dst[0] = (float)(r * (1.0f/0x7f)); /* r */ + dst[1] = (float)(g * (1.0f/0x7f)); /* g */ + dst[2] = (float)(b * (1.0f/0x7f)); /* b */ + dst[3] = (float)(a * (1.0f/0x7f)); /* a */ +} + +static INLINE void +util_format_r8g8b8a8_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + int32_t b; + int32_t a; + r = ((int32_t)(value << 24) ) >> 24; + g = ((int32_t)(value << 16) ) >> 24; + b = ((int32_t)(value << 8) ) >> 24; + a = ((int32_t)(value) ) >> 24; + dst[0] = (uint8_t)(((uint32_t)MAX2(r, 0)) * 0xff / 0x7f); /* r */ + dst[1] = (uint8_t)(((uint32_t)MAX2(g, 0)) * 0xff / 0x7f); /* g */ + dst[2] = (uint8_t)(((uint32_t)MAX2(b, 0)) * 0xff / 0x7f); /* b */ + dst[3] = (uint8_t)(((uint32_t)MAX2(a, 0)) * 0xff / 0x7f); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8a8_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((int8_t)(src[0] >> 1)) & 0xff) ; + value |= (uint32_t)((((int8_t)(src[1] >> 1)) & 0xff) << 8) ; + value |= (uint32_t)((((int8_t)(src[2] >> 1)) & 0xff) << 16) ; + value |= (uint32_t)(((int8_t)(src[3] >> 1)) << 24) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8_sscaled { + uint8_t value; + struct { + int8_t r; + } chan; +}; + +static INLINE void +util_format_r8_sscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + int8_t r; + r = (int8_t)(value) ; + dst[0] = (float)r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8_sscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= (uint8_t)((int8_t)CLAMP(src[0], -128, 127)) ; + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8_sscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint8_t value = *(const uint8_t *)src; + int8_t r; + r = (int8_t)(value) ; + dst[0] = (float)r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r8_sscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + int8_t r; + r = (int8_t)(value) ; + dst[0] = (uint8_t)(((uint32_t)CLAMP(r, 0, 1)) * 0xff / 0x1); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 255; /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8_sscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= (uint8_t)((int8_t)(((uint32_t)src[0]) * 0x1 / 0xff)) ; + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8g8_sscaled { + uint16_t value; + struct { + int8_t r; + int8_t g; + } chan; +}; + +static INLINE void +util_format_r8g8_sscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + int16_t r; + int16_t g; + r = ((int16_t)(value << 8) ) >> 8; + g = ((int16_t)(value) ) >> 8; + dst[0] = (float)r; /* r */ + dst[1] = (float)g; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8_sscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)(((int8_t)CLAMP(src[0], -128, 127)) & 0xff) ; + value |= (uint16_t)(((int8_t)CLAMP(src[1], -128, 127)) << 8) ; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8g8_sscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + int16_t r; + int16_t g; + r = ((int16_t)(value << 8) ) >> 8; + g = ((int16_t)(value) ) >> 8; + dst[0] = (float)r; /* r */ + dst[1] = (float)g; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r8g8_sscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + int16_t r; + int16_t g; + r = ((int16_t)(value << 8) ) >> 8; + g = ((int16_t)(value) ) >> 8; + dst[0] = (uint8_t)(((uint32_t)CLAMP(r, 0, 1)) * 0xff / 0x1); /* r */ + dst[1] = (uint8_t)(((uint32_t)CLAMP(g, 0, 1)) * 0xff / 0x1); /* g */ + dst[2] = 0; /* b */ + dst[3] = 255; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8_sscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)(((int8_t)(((uint32_t)src[0]) * 0x1 / 0xff)) & 0xff) ; + value |= (uint16_t)(((int8_t)(((uint32_t)src[1]) * 0x1 / 0xff)) << 8) ; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8g8b8_sscaled { + struct { + int8_t r; + int8_t g; + int8_t b; + } chan; +}; + +static INLINE void +util_format_r8g8b8_sscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r8g8b8_sscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)pixel.chan.r; /* r */ + dst[1] = (float)pixel.chan.g; /* g */ + dst[2] = (float)pixel.chan.b; /* b */ + dst[3] = 1; /* a */ + src += 3; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8_sscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r8g8b8_sscaled pixel; + pixel.chan.r = (int8_t)CLAMP(src[0], -128, 127); + pixel.chan.g = (int8_t)CLAMP(src[1], -128, 127); + pixel.chan.b = (int8_t)CLAMP(src[2], -128, 127); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 3; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8g8b8_sscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r8g8b8_sscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)pixel.chan.r; /* r */ + dst[1] = (float)pixel.chan.g; /* g */ + dst[2] = (float)pixel.chan.b; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r8g8b8_sscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r8g8b8_sscaled pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (uint8_t)(((uint32_t)CLAMP(pixel.chan.r, 0, 1)) * 0xff / 0x1); /* r */ + dst[1] = (uint8_t)(((uint32_t)CLAMP(pixel.chan.g, 0, 1)) * 0xff / 0x1); /* g */ + dst[2] = (uint8_t)(((uint32_t)CLAMP(pixel.chan.b, 0, 1)) * 0xff / 0x1); /* b */ + dst[3] = 255; /* a */ + src += 3; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8_sscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r8g8b8_sscaled pixel; + pixel.chan.r = (int8_t)(((uint32_t)src[0]) * 0x1 / 0xff); + pixel.chan.g = (int8_t)(((uint32_t)src[1]) * 0x1 / 0xff); + pixel.chan.b = (int8_t)(((uint32_t)src[2]) * 0x1 / 0xff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 3; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8g8b8a8_sscaled { + uint32_t value; + struct { + int8_t r; + int8_t g; + int8_t b; + int8_t a; + } chan; +}; + +static INLINE void +util_format_r8g8b8a8_sscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + int32_t b; + int32_t a; + r = ((int32_t)(value << 24) ) >> 24; + g = ((int32_t)(value << 16) ) >> 24; + b = ((int32_t)(value << 8) ) >> 24; + a = ((int32_t)(value) ) >> 24; + dst[0] = (float)r; /* r */ + dst[1] = (float)g; /* g */ + dst[2] = (float)b; /* b */ + dst[3] = (float)a; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8a8_sscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((int8_t)CLAMP(src[0], -128, 127)) & 0xff) ; + value |= (uint32_t)((((int8_t)CLAMP(src[1], -128, 127)) & 0xff) << 8) ; + value |= (uint32_t)((((int8_t)CLAMP(src[2], -128, 127)) & 0xff) << 16) ; + value |= (uint32_t)(((int8_t)CLAMP(src[3], -128, 127)) << 24) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8g8b8a8_sscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + int32_t b; + int32_t a; + r = ((int32_t)(value << 24) ) >> 24; + g = ((int32_t)(value << 16) ) >> 24; + b = ((int32_t)(value << 8) ) >> 24; + a = ((int32_t)(value) ) >> 24; + dst[0] = (float)r; /* r */ + dst[1] = (float)g; /* g */ + dst[2] = (float)b; /* b */ + dst[3] = (float)a; /* a */ +} + +static INLINE void +util_format_r8g8b8a8_sscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + int32_t b; + int32_t a; + r = ((int32_t)(value << 24) ) >> 24; + g = ((int32_t)(value << 16) ) >> 24; + b = ((int32_t)(value << 8) ) >> 24; + a = ((int32_t)(value) ) >> 24; + dst[0] = (uint8_t)(((uint32_t)CLAMP(r, 0, 1)) * 0xff / 0x1); /* r */ + dst[1] = (uint8_t)(((uint32_t)CLAMP(g, 0, 1)) * 0xff / 0x1); /* g */ + dst[2] = (uint8_t)(((uint32_t)CLAMP(b, 0, 1)) * 0xff / 0x1); /* b */ + dst[3] = (uint8_t)(((uint32_t)CLAMP(a, 0, 1)) * 0xff / 0x1); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8a8_sscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((int8_t)(((uint32_t)src[0]) * 0x1 / 0xff)) & 0xff) ; + value |= (uint32_t)((((int8_t)(((uint32_t)src[1]) * 0x1 / 0xff)) & 0xff) << 8) ; + value |= (uint32_t)((((int8_t)(((uint32_t)src[2]) * 0x1 / 0xff)) & 0xff) << 16) ; + value |= (uint32_t)(((int8_t)(((uint32_t)src[3]) * 0x1 / 0xff)) << 24) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32_fixed { + uint32_t value; + struct { + int32_t r; + } chan; +}; + +static INLINE void +util_format_r32_fixed_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32_fixed pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)(pixel.chan.r * (1.0/0x10000)); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32_fixed_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32_fixed pixel; + pixel.chan.r = (int32_t)(CLAMP(src[0], -65536, 65535) * (double)0x10000); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32_fixed_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r32_fixed pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)(pixel.chan.r * (1.0/0x10000)); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r32_fixed_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32_fixed pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (uint8_t)util_iround((CLAMP(pixel.chan.r, 0, 65536) * (1.0/0x10000)) * 0xff); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 255; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32_fixed_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32_fixed pixel; + pixel.chan.r = (int32_t)((float)(src[0] * (1.0f/0xff)) * (double)0x10000); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32g32_fixed { + uint64_t value; + struct { + int32_t r; + int32_t g; + } chan; +}; + +static INLINE void +util_format_r32g32_fixed_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32_fixed pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)(pixel.chan.r * (1.0/0x10000)); /* r */ + dst[1] = (float)(pixel.chan.g * (1.0/0x10000)); /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32_fixed_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32_fixed pixel; + pixel.chan.r = (int32_t)(CLAMP(src[0], -65536, 65535) * (double)0x10000); + pixel.chan.g = (int32_t)(CLAMP(src[1], -65536, 65535) * (double)0x10000); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32g32_fixed_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r32g32_fixed pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)(pixel.chan.r * (1.0/0x10000)); /* r */ + dst[1] = (float)(pixel.chan.g * (1.0/0x10000)); /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r32g32_fixed_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32_fixed pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (uint8_t)util_iround((CLAMP(pixel.chan.r, 0, 65536) * (1.0/0x10000)) * 0xff); /* r */ + dst[1] = (uint8_t)util_iround((CLAMP(pixel.chan.g, 0, 65536) * (1.0/0x10000)) * 0xff); /* g */ + dst[2] = 0; /* b */ + dst[3] = 255; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32_fixed_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32_fixed pixel; + pixel.chan.r = (int32_t)((float)(src[0] * (1.0f/0xff)) * (double)0x10000); + pixel.chan.g = (int32_t)((float)(src[1] * (1.0f/0xff)) * (double)0x10000); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32g32b32_fixed { + struct { + int32_t r; + int32_t g; + int32_t b; + } chan; +}; + +static INLINE void +util_format_r32g32b32_fixed_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32_fixed pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)(pixel.chan.r * (1.0/0x10000)); /* r */ + dst[1] = (float)(pixel.chan.g * (1.0/0x10000)); /* g */ + dst[2] = (float)(pixel.chan.b * (1.0/0x10000)); /* b */ + dst[3] = 1; /* a */ + src += 12; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32_fixed_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32_fixed pixel; + pixel.chan.r = (int32_t)(CLAMP(src[0], -65536, 65535) * (double)0x10000); + pixel.chan.g = (int32_t)(CLAMP(src[1], -65536, 65535) * (double)0x10000); + pixel.chan.b = (int32_t)(CLAMP(src[2], -65536, 65535) * (double)0x10000); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 12; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32g32b32_fixed_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r32g32b32_fixed pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)(pixel.chan.r * (1.0/0x10000)); /* r */ + dst[1] = (float)(pixel.chan.g * (1.0/0x10000)); /* g */ + dst[2] = (float)(pixel.chan.b * (1.0/0x10000)); /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r32g32b32_fixed_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32_fixed pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (uint8_t)util_iround((CLAMP(pixel.chan.r, 0, 65536) * (1.0/0x10000)) * 0xff); /* r */ + dst[1] = (uint8_t)util_iround((CLAMP(pixel.chan.g, 0, 65536) * (1.0/0x10000)) * 0xff); /* g */ + dst[2] = (uint8_t)util_iround((CLAMP(pixel.chan.b, 0, 65536) * (1.0/0x10000)) * 0xff); /* b */ + dst[3] = 255; /* a */ + src += 12; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32_fixed_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32_fixed pixel; + pixel.chan.r = (int32_t)((float)(src[0] * (1.0f/0xff)) * (double)0x10000); + pixel.chan.g = (int32_t)((float)(src[1] * (1.0f/0xff)) * (double)0x10000); + pixel.chan.b = (int32_t)((float)(src[2] * (1.0f/0xff)) * (double)0x10000); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 12; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32g32b32a32_fixed { + struct { + int32_t r; + int32_t g; + int32_t b; + int32_t a; + } chan; +}; + +static INLINE void +util_format_r32g32b32a32_fixed_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32a32_fixed pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)(pixel.chan.r * (1.0/0x10000)); /* r */ + dst[1] = (float)(pixel.chan.g * (1.0/0x10000)); /* g */ + dst[2] = (float)(pixel.chan.b * (1.0/0x10000)); /* b */ + dst[3] = (float)(pixel.chan.a * (1.0/0x10000)); /* a */ + src += 16; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32a32_fixed_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32a32_fixed pixel; + pixel.chan.r = (int32_t)(CLAMP(src[0], -65536, 65535) * (double)0x10000); + pixel.chan.g = (int32_t)(CLAMP(src[1], -65536, 65535) * (double)0x10000); + pixel.chan.b = (int32_t)(CLAMP(src[2], -65536, 65535) * (double)0x10000); + pixel.chan.a = (int32_t)(CLAMP(src[3], -65536, 65535) * (double)0x10000); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 16; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32g32b32a32_fixed_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r32g32b32a32_fixed pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)(pixel.chan.r * (1.0/0x10000)); /* r */ + dst[1] = (float)(pixel.chan.g * (1.0/0x10000)); /* g */ + dst[2] = (float)(pixel.chan.b * (1.0/0x10000)); /* b */ + dst[3] = (float)(pixel.chan.a * (1.0/0x10000)); /* a */ +} + +static INLINE void +util_format_r32g32b32a32_fixed_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32a32_fixed pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (uint8_t)util_iround((CLAMP(pixel.chan.r, 0, 65536) * (1.0/0x10000)) * 0xff); /* r */ + dst[1] = (uint8_t)util_iround((CLAMP(pixel.chan.g, 0, 65536) * (1.0/0x10000)) * 0xff); /* g */ + dst[2] = (uint8_t)util_iround((CLAMP(pixel.chan.b, 0, 65536) * (1.0/0x10000)) * 0xff); /* b */ + dst[3] = (uint8_t)util_iround((CLAMP(pixel.chan.a, 0, 65536) * (1.0/0x10000)) * 0xff); /* a */ + src += 16; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32a32_fixed_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32a32_fixed pixel; + pixel.chan.r = (int32_t)((float)(src[0] * (1.0f/0xff)) * (double)0x10000); + pixel.chan.g = (int32_t)((float)(src[1] * (1.0f/0xff)) * (double)0x10000); + pixel.chan.b = (int32_t)((float)(src[2] * (1.0f/0xff)) * (double)0x10000); + pixel.chan.a = (int32_t)((float)(src[3] * (1.0f/0xff)) * (double)0x10000); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 16; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r10g10b10x2_uscaled { + uint32_t value; + struct { + unsigned r:10; + unsigned g:10; + unsigned b:10; + unsigned x:2; + } chan; +}; + +static INLINE void +util_format_r10g10b10x2_uscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + r = (value) & 0x3ff; + g = (value >> 10) & 0x3ff; + b = (value >> 20) & 0x3ff; + dst[0] = (float)r; /* r */ + dst[1] = (float)g; /* g */ + dst[2] = (float)b; /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r10g10b10x2_uscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint32_t)CLAMP(src[0], 0, 1023)) & 0x3ff; + value |= (((uint32_t)CLAMP(src[1], 0, 1023)) & 0x3ff) << 10; + value |= (((uint32_t)CLAMP(src[2], 0, 1023)) & 0x3ff) << 20; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r10g10b10x2_uscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + r = (value) & 0x3ff; + g = (value >> 10) & 0x3ff; + b = (value >> 20) & 0x3ff; + dst[0] = (float)r; /* r */ + dst[1] = (float)g; /* g */ + dst[2] = (float)b; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r10g10b10x2_uscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + r = (value) & 0x3ff; + g = (value >> 10) & 0x3ff; + b = (value >> 20) & 0x3ff; + dst[0] = (uint8_t)(((uint32_t)MIN2(r, 1)) * 0xff / 0x1); /* r */ + dst[1] = (uint8_t)(((uint32_t)MIN2(g, 1)) * 0xff / 0x1); /* g */ + dst[2] = (uint8_t)(((uint32_t)MIN2(b, 1)) * 0xff / 0x1); /* b */ + dst[3] = 255; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r10g10b10x2_uscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint32_t)(((uint32_t)src[0]) * 0x1 / 0xff)) & 0x3ff; + value |= (((uint32_t)(((uint32_t)src[1]) * 0x1 / 0xff)) & 0x3ff) << 10; + value |= (((uint32_t)(((uint32_t)src[2]) * 0x1 / 0xff)) & 0x3ff) << 20; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r10g10b10x2_snorm { + uint32_t value; + struct { + int r:10; + int g:10; + int b:10; + unsigned x:2; + } chan; +}; + +static INLINE void +util_format_r10g10b10x2_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + int32_t b; + r = ((int32_t)(value << 22) ) >> 22; + g = ((int32_t)(value << 12) ) >> 22; + b = ((int32_t)(value << 2) ) >> 22; + dst[0] = (float)(r * (1.0f/0x1ff)); /* r */ + dst[1] = (float)(g * (1.0f/0x1ff)); /* g */ + dst[2] = (float)(b * (1.0f/0x1ff)); /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r10g10b10x2_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((uint32_t)util_iround(CLAMP(src[0], -1, 1) * 0x1ff)) & 0x3ff) ; + value |= (uint32_t)((((uint32_t)util_iround(CLAMP(src[1], -1, 1) * 0x1ff)) & 0x3ff) << 10) ; + value |= (uint32_t)((((uint32_t)util_iround(CLAMP(src[2], -1, 1) * 0x1ff)) & 0x3ff) << 20) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r10g10b10x2_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + int32_t b; + r = ((int32_t)(value << 22) ) >> 22; + g = ((int32_t)(value << 12) ) >> 22; + b = ((int32_t)(value << 2) ) >> 22; + dst[0] = (float)(r * (1.0f/0x1ff)); /* r */ + dst[1] = (float)(g * (1.0f/0x1ff)); /* g */ + dst[2] = (float)(b * (1.0f/0x1ff)); /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r10g10b10x2_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + int32_t b; + r = ((int32_t)(value << 22) ) >> 22; + g = ((int32_t)(value << 12) ) >> 22; + b = ((int32_t)(value << 2) ) >> 22; + dst[0] = (uint8_t)(MAX2(r, 0) >> 1); /* r */ + dst[1] = (uint8_t)(MAX2(g, 0) >> 1); /* g */ + dst[2] = (uint8_t)(MAX2(b, 0) >> 1); /* b */ + dst[3] = 255; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r10g10b10x2_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((uint32_t)(((uint32_t)src[0]) * 0x1ff / 0xff)) & 0x3ff) ; + value |= (uint32_t)((((uint32_t)(((uint32_t)src[1]) * 0x1ff / 0xff)) & 0x3ff) << 10) ; + value |= (uint32_t)((((uint32_t)(((uint32_t)src[2]) * 0x1ff / 0xff)) & 0x3ff) << 20) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r4a4_unorm { + uint8_t value; + struct { + unsigned a:4; + unsigned r:4; + } chan; +}; + +static INLINE void +util_format_r4a4_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + uint8_t a; + uint8_t r; + a = (value) & 0xf; + r = value >> 4; + dst[0] = (float)(r * (1.0f/0xf)); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (float)(a * (1.0f/0xf)); /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r4a4_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= ((uint8_t)util_iround(CLAMP(src[3], 0, 1) * 0xf)) & 0xf; + value |= ((uint8_t)util_iround(CLAMP(src[0], 0, 1) * 0xf)) << 4; + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r4a4_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint8_t value = *(const uint8_t *)src; + uint8_t a; + uint8_t r; + a = (value) & 0xf; + r = value >> 4; + dst[0] = (float)(r * (1.0f/0xf)); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (float)(a * (1.0f/0xf)); /* a */ +} + +static INLINE void +util_format_r4a4_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + uint8_t a; + uint8_t r; + a = (value) & 0xf; + r = value >> 4; + dst[0] = (uint8_t)(((uint32_t)r) * 0xff / 0xf); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (uint8_t)(((uint32_t)a) * 0xff / 0xf); /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r4a4_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= ((uint8_t)(src[3] >> 4)) & 0xf; + value |= ((uint8_t)(src[0] >> 4)) << 4; + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_a4r4_unorm { + uint8_t value; + struct { + unsigned r:4; + unsigned a:4; + } chan; +}; + +static INLINE void +util_format_a4r4_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + uint8_t r; + uint8_t a; + r = (value) & 0xf; + a = value >> 4; + dst[0] = (float)(r * (1.0f/0xf)); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (float)(a * (1.0f/0xf)); /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a4r4_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= ((uint8_t)util_iround(CLAMP(src[0], 0, 1) * 0xf)) & 0xf; + value |= ((uint8_t)util_iround(CLAMP(src[3], 0, 1) * 0xf)) << 4; + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_a4r4_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint8_t value = *(const uint8_t *)src; + uint8_t r; + uint8_t a; + r = (value) & 0xf; + a = value >> 4; + dst[0] = (float)(r * (1.0f/0xf)); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (float)(a * (1.0f/0xf)); /* a */ +} + +static INLINE void +util_format_a4r4_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + uint8_t r; + uint8_t a; + r = (value) & 0xf; + a = value >> 4; + dst[0] = (uint8_t)(((uint32_t)r) * 0xff / 0xf); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (uint8_t)(((uint32_t)a) * 0xff / 0xf); /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a4r4_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= ((uint8_t)(src[0] >> 4)) & 0xf; + value |= ((uint8_t)(src[3] >> 4)) << 4; + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8a8_unorm { + uint16_t value; + struct { + uint8_t r; + uint8_t a; + } chan; +}; + +static INLINE void +util_format_r8a8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t r; + uint16_t a; + r = (value) & 0xff; + a = value >> 8; + dst[0] = ubyte_to_float(r); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = ubyte_to_float(a); /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8a8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (float_to_ubyte(src[0])) & 0xff; + value |= (float_to_ubyte(src[3])) << 8; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8a8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + uint16_t r; + uint16_t a; + r = (value) & 0xff; + a = value >> 8; + dst[0] = ubyte_to_float(r); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = ubyte_to_float(a); /* a */ +} + +static INLINE void +util_format_r8a8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t r; + uint16_t a; + r = (value) & 0xff; + a = value >> 8; + dst[0] = r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = a; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8a8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (src[0]) & 0xff; + value |= (src[3]) << 8; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_a8r8_unorm { + uint16_t value; + struct { + uint8_t a; + uint8_t r; + } chan; +}; + +static INLINE void +util_format_a8r8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t a; + uint16_t r; + a = (value) & 0xff; + r = value >> 8; + dst[0] = ubyte_to_float(r); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = ubyte_to_float(a); /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a8r8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (float_to_ubyte(src[3])) & 0xff; + value |= (float_to_ubyte(src[0])) << 8; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_a8r8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + uint16_t a; + uint16_t r; + a = (value) & 0xff; + r = value >> 8; + dst[0] = ubyte_to_float(r); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = ubyte_to_float(a); /* a */ +} + +static INLINE void +util_format_a8r8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t a; + uint16_t r; + a = (value) & 0xff; + r = value >> 8; + dst[0] = r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = a; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a8r8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (src[3]) & 0xff; + value |= (src[0]) << 8; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r10g10b10a2_uscaled { + uint32_t value; + struct { + unsigned r:10; + unsigned g:10; + unsigned b:10; + unsigned a:2; + } chan; +}; + +static INLINE void +util_format_r10g10b10a2_uscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + uint32_t a; + r = (value) & 0x3ff; + g = (value >> 10) & 0x3ff; + b = (value >> 20) & 0x3ff; + a = value >> 30; + dst[0] = (float)r; /* r */ + dst[1] = (float)g; /* g */ + dst[2] = (float)b; /* b */ + dst[3] = (float)a; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r10g10b10a2_uscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint32_t)CLAMP(src[0], 0, 1023)) & 0x3ff; + value |= (((uint32_t)CLAMP(src[1], 0, 1023)) & 0x3ff) << 10; + value |= (((uint32_t)CLAMP(src[2], 0, 1023)) & 0x3ff) << 20; + value |= ((uint32_t)CLAMP(src[3], 0, 3)) << 30; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r10g10b10a2_uscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + uint32_t a; + r = (value) & 0x3ff; + g = (value >> 10) & 0x3ff; + b = (value >> 20) & 0x3ff; + a = value >> 30; + dst[0] = (float)r; /* r */ + dst[1] = (float)g; /* g */ + dst[2] = (float)b; /* b */ + dst[3] = (float)a; /* a */ +} + +static INLINE void +util_format_r10g10b10a2_uscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + uint32_t a; + r = (value) & 0x3ff; + g = (value >> 10) & 0x3ff; + b = (value >> 20) & 0x3ff; + a = value >> 30; + dst[0] = (uint8_t)(((uint32_t)MIN2(r, 1)) * 0xff / 0x1); /* r */ + dst[1] = (uint8_t)(((uint32_t)MIN2(g, 1)) * 0xff / 0x1); /* g */ + dst[2] = (uint8_t)(((uint32_t)MIN2(b, 1)) * 0xff / 0x1); /* b */ + dst[3] = (uint8_t)(((uint32_t)MIN2(a, 1)) * 0xff / 0x1); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r10g10b10a2_uscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint32_t)(((uint32_t)src[0]) * 0x1 / 0xff)) & 0x3ff; + value |= (((uint32_t)(((uint32_t)src[1]) * 0x1 / 0xff)) & 0x3ff) << 10; + value |= (((uint32_t)(((uint32_t)src[2]) * 0x1 / 0xff)) & 0x3ff) << 20; + value |= ((uint32_t)(((uint32_t)src[3]) * 0x1 / 0xff)) << 30; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r10g10b10a2_sscaled { + uint32_t value; + struct { + int r:10; + int g:10; + int b:10; + int a:2; + } chan; +}; + +static INLINE void +util_format_r10g10b10a2_sscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + int32_t b; + int32_t a; + r = ((int32_t)(value << 22) ) >> 22; + g = ((int32_t)(value << 12) ) >> 22; + b = ((int32_t)(value << 2) ) >> 22; + a = ((int32_t)(value) ) >> 30; + dst[0] = (float)r; /* r */ + dst[1] = (float)g; /* g */ + dst[2] = (float)b; /* b */ + dst[3] = (float)a; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r10g10b10a2_sscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((uint32_t)CLAMP(src[0], -512, 511)) & 0x3ff) ; + value |= (uint32_t)((((uint32_t)CLAMP(src[1], -512, 511)) & 0x3ff) << 10) ; + value |= (uint32_t)((((uint32_t)CLAMP(src[2], -512, 511)) & 0x3ff) << 20) ; + value |= (uint32_t)(((uint32_t)CLAMP(src[3], -2, 1)) << 30) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r10g10b10a2_sscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + int32_t b; + int32_t a; + r = ((int32_t)(value << 22) ) >> 22; + g = ((int32_t)(value << 12) ) >> 22; + b = ((int32_t)(value << 2) ) >> 22; + a = ((int32_t)(value) ) >> 30; + dst[0] = (float)r; /* r */ + dst[1] = (float)g; /* g */ + dst[2] = (float)b; /* b */ + dst[3] = (float)a; /* a */ +} + +static INLINE void +util_format_r10g10b10a2_sscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + int32_t b; + int32_t a; + r = ((int32_t)(value << 22) ) >> 22; + g = ((int32_t)(value << 12) ) >> 22; + b = ((int32_t)(value << 2) ) >> 22; + a = ((int32_t)(value) ) >> 30; + dst[0] = (uint8_t)(((uint32_t)CLAMP(r, 0, 1)) * 0xff / 0x1); /* r */ + dst[1] = (uint8_t)(((uint32_t)CLAMP(g, 0, 1)) * 0xff / 0x1); /* g */ + dst[2] = (uint8_t)(((uint32_t)CLAMP(b, 0, 1)) * 0xff / 0x1); /* b */ + dst[3] = (uint8_t)(((uint32_t)MAX2(a, 0)) * 0xff / 0x1); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r10g10b10a2_sscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((uint32_t)(((uint32_t)src[0]) * 0x1 / 0xff)) & 0x3ff) ; + value |= (uint32_t)((((uint32_t)(((uint32_t)src[1]) * 0x1 / 0xff)) & 0x3ff) << 10) ; + value |= (uint32_t)((((uint32_t)(((uint32_t)src[2]) * 0x1 / 0xff)) & 0x3ff) << 20) ; + value |= (uint32_t)(((uint32_t)(((uint32_t)src[3]) * 0x1 / 0xff)) << 30) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r10g10b10a2_snorm { + uint32_t value; + struct { + int r:10; + int g:10; + int b:10; + int a:2; + } chan; +}; + +static INLINE void +util_format_r10g10b10a2_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + int32_t b; + int32_t a; + r = ((int32_t)(value << 22) ) >> 22; + g = ((int32_t)(value << 12) ) >> 22; + b = ((int32_t)(value << 2) ) >> 22; + a = ((int32_t)(value) ) >> 30; + dst[0] = (float)(r * (1.0f/0x1ff)); /* r */ + dst[1] = (float)(g * (1.0f/0x1ff)); /* g */ + dst[2] = (float)(b * (1.0f/0x1ff)); /* b */ + dst[3] = (float)(a * (1.0f/0x1)); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r10g10b10a2_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((uint32_t)util_iround(CLAMP(src[0], -1, 1) * 0x1ff)) & 0x3ff) ; + value |= (uint32_t)((((uint32_t)util_iround(CLAMP(src[1], -1, 1) * 0x1ff)) & 0x3ff) << 10) ; + value |= (uint32_t)((((uint32_t)util_iround(CLAMP(src[2], -1, 1) * 0x1ff)) & 0x3ff) << 20) ; + value |= (uint32_t)(((uint32_t)util_iround(CLAMP(src[3], -1, 1) * 0x1)) << 30) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r10g10b10a2_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + int32_t b; + int32_t a; + r = ((int32_t)(value << 22) ) >> 22; + g = ((int32_t)(value << 12) ) >> 22; + b = ((int32_t)(value << 2) ) >> 22; + a = ((int32_t)(value) ) >> 30; + dst[0] = (float)(r * (1.0f/0x1ff)); /* r */ + dst[1] = (float)(g * (1.0f/0x1ff)); /* g */ + dst[2] = (float)(b * (1.0f/0x1ff)); /* b */ + dst[3] = (float)(a * (1.0f/0x1)); /* a */ +} + +static INLINE void +util_format_r10g10b10a2_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + int32_t b; + int32_t a; + r = ((int32_t)(value << 22) ) >> 22; + g = ((int32_t)(value << 12) ) >> 22; + b = ((int32_t)(value << 2) ) >> 22; + a = ((int32_t)(value) ) >> 30; + dst[0] = (uint8_t)(MAX2(r, 0) >> 1); /* r */ + dst[1] = (uint8_t)(MAX2(g, 0) >> 1); /* g */ + dst[2] = (uint8_t)(MAX2(b, 0) >> 1); /* b */ + dst[3] = (uint8_t)(((uint32_t)MAX2(a, 0)) * 0xff / 0x1); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r10g10b10a2_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((uint32_t)(((uint32_t)src[0]) * 0x1ff / 0xff)) & 0x3ff) ; + value |= (uint32_t)((((uint32_t)(((uint32_t)src[1]) * 0x1ff / 0xff)) & 0x3ff) << 10) ; + value |= (uint32_t)((((uint32_t)(((uint32_t)src[2]) * 0x1ff / 0xff)) & 0x3ff) << 20) ; + value |= (uint32_t)(((uint32_t)(src[3] >> 7)) << 30) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_b10g10r10a2_uscaled { + uint32_t value; + struct { + unsigned b:10; + unsigned g:10; + unsigned r:10; + unsigned a:2; + } chan; +}; + +static INLINE void +util_format_b10g10r10a2_uscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t b; + uint32_t g; + uint32_t r; + uint32_t a; + b = (value) & 0x3ff; + g = (value >> 10) & 0x3ff; + r = (value >> 20) & 0x3ff; + a = value >> 30; + dst[0] = (float)r; /* r */ + dst[1] = (float)g; /* g */ + dst[2] = (float)b; /* b */ + dst[3] = (float)a; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_b10g10r10a2_uscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint32_t)CLAMP(src[2], 0, 1023)) & 0x3ff; + value |= (((uint32_t)CLAMP(src[1], 0, 1023)) & 0x3ff) << 10; + value |= (((uint32_t)CLAMP(src[0], 0, 1023)) & 0x3ff) << 20; + value |= ((uint32_t)CLAMP(src[3], 0, 3)) << 30; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_b10g10r10a2_uscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t b; + uint32_t g; + uint32_t r; + uint32_t a; + b = (value) & 0x3ff; + g = (value >> 10) & 0x3ff; + r = (value >> 20) & 0x3ff; + a = value >> 30; + dst[0] = (float)r; /* r */ + dst[1] = (float)g; /* g */ + dst[2] = (float)b; /* b */ + dst[3] = (float)a; /* a */ +} + +static INLINE void +util_format_b10g10r10a2_uscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t b; + uint32_t g; + uint32_t r; + uint32_t a; + b = (value) & 0x3ff; + g = (value >> 10) & 0x3ff; + r = (value >> 20) & 0x3ff; + a = value >> 30; + dst[0] = (uint8_t)(((uint32_t)MIN2(r, 1)) * 0xff / 0x1); /* r */ + dst[1] = (uint8_t)(((uint32_t)MIN2(g, 1)) * 0xff / 0x1); /* g */ + dst[2] = (uint8_t)(((uint32_t)MIN2(b, 1)) * 0xff / 0x1); /* b */ + dst[3] = (uint8_t)(((uint32_t)MIN2(a, 1)) * 0xff / 0x1); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_b10g10r10a2_uscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint32_t)(((uint32_t)src[2]) * 0x1 / 0xff)) & 0x3ff; + value |= (((uint32_t)(((uint32_t)src[1]) * 0x1 / 0xff)) & 0x3ff) << 10; + value |= (((uint32_t)(((uint32_t)src[0]) * 0x1 / 0xff)) & 0x3ff) << 20; + value |= ((uint32_t)(((uint32_t)src[3]) * 0x1 / 0xff)) << 30; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_b10g10r10a2_sscaled { + uint32_t value; + struct { + int b:10; + int g:10; + int r:10; + int a:2; + } chan; +}; + +static INLINE void +util_format_b10g10r10a2_sscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t b; + int32_t g; + int32_t r; + int32_t a; + b = ((int32_t)(value << 22) ) >> 22; + g = ((int32_t)(value << 12) ) >> 22; + r = ((int32_t)(value << 2) ) >> 22; + a = ((int32_t)(value) ) >> 30; + dst[0] = (float)r; /* r */ + dst[1] = (float)g; /* g */ + dst[2] = (float)b; /* b */ + dst[3] = (float)a; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_b10g10r10a2_sscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((uint32_t)CLAMP(src[2], -512, 511)) & 0x3ff) ; + value |= (uint32_t)((((uint32_t)CLAMP(src[1], -512, 511)) & 0x3ff) << 10) ; + value |= (uint32_t)((((uint32_t)CLAMP(src[0], -512, 511)) & 0x3ff) << 20) ; + value |= (uint32_t)(((uint32_t)CLAMP(src[3], -2, 1)) << 30) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_b10g10r10a2_sscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + int32_t b; + int32_t g; + int32_t r; + int32_t a; + b = ((int32_t)(value << 22) ) >> 22; + g = ((int32_t)(value << 12) ) >> 22; + r = ((int32_t)(value << 2) ) >> 22; + a = ((int32_t)(value) ) >> 30; + dst[0] = (float)r; /* r */ + dst[1] = (float)g; /* g */ + dst[2] = (float)b; /* b */ + dst[3] = (float)a; /* a */ +} + +static INLINE void +util_format_b10g10r10a2_sscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t b; + int32_t g; + int32_t r; + int32_t a; + b = ((int32_t)(value << 22) ) >> 22; + g = ((int32_t)(value << 12) ) >> 22; + r = ((int32_t)(value << 2) ) >> 22; + a = ((int32_t)(value) ) >> 30; + dst[0] = (uint8_t)(((uint32_t)CLAMP(r, 0, 1)) * 0xff / 0x1); /* r */ + dst[1] = (uint8_t)(((uint32_t)CLAMP(g, 0, 1)) * 0xff / 0x1); /* g */ + dst[2] = (uint8_t)(((uint32_t)CLAMP(b, 0, 1)) * 0xff / 0x1); /* b */ + dst[3] = (uint8_t)(((uint32_t)MAX2(a, 0)) * 0xff / 0x1); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_b10g10r10a2_sscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((uint32_t)(((uint32_t)src[2]) * 0x1 / 0xff)) & 0x3ff) ; + value |= (uint32_t)((((uint32_t)(((uint32_t)src[1]) * 0x1 / 0xff)) & 0x3ff) << 10) ; + value |= (uint32_t)((((uint32_t)(((uint32_t)src[0]) * 0x1 / 0xff)) & 0x3ff) << 20) ; + value |= (uint32_t)(((uint32_t)(((uint32_t)src[3]) * 0x1 / 0xff)) << 30) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_b10g10r10a2_snorm { + uint32_t value; + struct { + int b:10; + int g:10; + int r:10; + int a:2; + } chan; +}; + +static INLINE void +util_format_b10g10r10a2_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t b; + int32_t g; + int32_t r; + int32_t a; + b = ((int32_t)(value << 22) ) >> 22; + g = ((int32_t)(value << 12) ) >> 22; + r = ((int32_t)(value << 2) ) >> 22; + a = ((int32_t)(value) ) >> 30; + dst[0] = (float)(r * (1.0f/0x1ff)); /* r */ + dst[1] = (float)(g * (1.0f/0x1ff)); /* g */ + dst[2] = (float)(b * (1.0f/0x1ff)); /* b */ + dst[3] = (float)(a * (1.0f/0x1)); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_b10g10r10a2_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((uint32_t)util_iround(CLAMP(src[2], -1, 1) * 0x1ff)) & 0x3ff) ; + value |= (uint32_t)((((uint32_t)util_iround(CLAMP(src[1], -1, 1) * 0x1ff)) & 0x3ff) << 10) ; + value |= (uint32_t)((((uint32_t)util_iround(CLAMP(src[0], -1, 1) * 0x1ff)) & 0x3ff) << 20) ; + value |= (uint32_t)(((uint32_t)util_iround(CLAMP(src[3], -1, 1) * 0x1)) << 30) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_b10g10r10a2_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + int32_t b; + int32_t g; + int32_t r; + int32_t a; + b = ((int32_t)(value << 22) ) >> 22; + g = ((int32_t)(value << 12) ) >> 22; + r = ((int32_t)(value << 2) ) >> 22; + a = ((int32_t)(value) ) >> 30; + dst[0] = (float)(r * (1.0f/0x1ff)); /* r */ + dst[1] = (float)(g * (1.0f/0x1ff)); /* g */ + dst[2] = (float)(b * (1.0f/0x1ff)); /* b */ + dst[3] = (float)(a * (1.0f/0x1)); /* a */ +} + +static INLINE void +util_format_b10g10r10a2_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t b; + int32_t g; + int32_t r; + int32_t a; + b = ((int32_t)(value << 22) ) >> 22; + g = ((int32_t)(value << 12) ) >> 22; + r = ((int32_t)(value << 2) ) >> 22; + a = ((int32_t)(value) ) >> 30; + dst[0] = (uint8_t)(MAX2(r, 0) >> 1); /* r */ + dst[1] = (uint8_t)(MAX2(g, 0) >> 1); /* g */ + dst[2] = (uint8_t)(MAX2(b, 0) >> 1); /* b */ + dst[3] = (uint8_t)(((uint32_t)MAX2(a, 0)) * 0xff / 0x1); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_b10g10r10a2_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((uint32_t)(((uint32_t)src[2]) * 0x1ff / 0xff)) & 0x3ff) ; + value |= (uint32_t)((((uint32_t)(((uint32_t)src[1]) * 0x1ff / 0xff)) & 0x3ff) << 10) ; + value |= (uint32_t)((((uint32_t)(((uint32_t)src[0]) * 0x1ff / 0xff)) & 0x3ff) << 20) ; + value |= (uint32_t)(((uint32_t)(src[3] >> 7)) << 30) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8_uint { + uint8_t value; + struct { + uint8_t r; + } chan; +}; + +static INLINE void +util_format_r8_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + uint8_t r; + r = value; + dst[0] = (unsigned)r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= (uint8_t)MIN2(src[0], 255); + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint8_t value = *(const uint8_t *)src; + uint8_t r; + r = value; + dst[0] = (unsigned)r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r8_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + uint8_t r; + r = value; + dst[0] = (int)r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= (uint8_t)CLAMP(src[0], 0, 255); + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8g8_uint { + uint16_t value; + struct { + uint8_t r; + uint8_t g; + } chan; +}; + +static INLINE void +util_format_r8g8_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t r; + uint16_t g; + r = (value) & 0xff; + g = value >> 8; + dst[0] = (unsigned)r; /* r */ + dst[1] = (unsigned)g; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= ((uint8_t)MIN2(src[0], 255)) & 0xff; + value |= ((uint8_t)MIN2(src[1], 255)) << 8; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8g8_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + uint16_t r; + uint16_t g; + r = (value) & 0xff; + g = value >> 8; + dst[0] = (unsigned)r; /* r */ + dst[1] = (unsigned)g; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r8g8_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t r; + uint16_t g; + r = (value) & 0xff; + g = value >> 8; + dst[0] = (int)r; /* r */ + dst[1] = (int)g; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= ((uint8_t)CLAMP(src[0], 0, 255)) & 0xff; + value |= ((uint8_t)CLAMP(src[1], 0, 255)) << 8; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8g8b8_uint { + struct { + uint8_t r; + uint8_t g; + uint8_t b; + } chan; +}; + +static INLINE void +util_format_r8g8b8_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r8g8b8_uint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (unsigned)pixel.chan.r; /* r */ + dst[1] = (unsigned)pixel.chan.g; /* g */ + dst[2] = (unsigned)pixel.chan.b; /* b */ + dst[3] = 1; /* a */ + src += 3; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r8g8b8_uint pixel; + pixel.chan.r = (uint8_t)MIN2(src[0], 255); + pixel.chan.g = (uint8_t)MIN2(src[1], 255); + pixel.chan.b = (uint8_t)MIN2(src[2], 255); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 3; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8g8b8_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r8g8b8_uint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (unsigned)pixel.chan.r; /* r */ + dst[1] = (unsigned)pixel.chan.g; /* g */ + dst[2] = (unsigned)pixel.chan.b; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r8g8b8_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r8g8b8_uint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (int)pixel.chan.r; /* r */ + dst[1] = (int)pixel.chan.g; /* g */ + dst[2] = (int)pixel.chan.b; /* b */ + dst[3] = 1; /* a */ + src += 3; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r8g8b8_uint pixel; + pixel.chan.r = (uint8_t)CLAMP(src[0], 0, 255); + pixel.chan.g = (uint8_t)CLAMP(src[1], 0, 255); + pixel.chan.b = (uint8_t)CLAMP(src[2], 0, 255); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 3; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8g8b8a8_uint { + uint32_t value; + struct { + uint8_t r; + uint8_t g; + uint8_t b; + uint8_t a; + } chan; +}; + +static INLINE void +util_format_r8g8b8a8_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + uint32_t a; + r = (value) & 0xff; + g = (value >> 8) & 0xff; + b = (value >> 16) & 0xff; + a = value >> 24; + dst[0] = (unsigned)r; /* r */ + dst[1] = (unsigned)g; /* g */ + dst[2] = (unsigned)b; /* b */ + dst[3] = (unsigned)a; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8a8_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint8_t)MIN2(src[0], 255)) & 0xff; + value |= (((uint8_t)MIN2(src[1], 255)) & 0xff) << 8; + value |= (((uint8_t)MIN2(src[2], 255)) & 0xff) << 16; + value |= ((uint8_t)MIN2(src[3], 255)) << 24; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8g8b8a8_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + uint32_t a; + r = (value) & 0xff; + g = (value >> 8) & 0xff; + b = (value >> 16) & 0xff; + a = value >> 24; + dst[0] = (unsigned)r; /* r */ + dst[1] = (unsigned)g; /* g */ + dst[2] = (unsigned)b; /* b */ + dst[3] = (unsigned)a; /* a */ +} + +static INLINE void +util_format_r8g8b8a8_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + uint32_t a; + r = (value) & 0xff; + g = (value >> 8) & 0xff; + b = (value >> 16) & 0xff; + a = value >> 24; + dst[0] = (int)r; /* r */ + dst[1] = (int)g; /* g */ + dst[2] = (int)b; /* b */ + dst[3] = (int)a; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8a8_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint8_t)CLAMP(src[0], 0, 255)) & 0xff; + value |= (((uint8_t)CLAMP(src[1], 0, 255)) & 0xff) << 8; + value |= (((uint8_t)CLAMP(src[2], 0, 255)) & 0xff) << 16; + value |= ((uint8_t)CLAMP(src[3], 0, 255)) << 24; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8_sint { + uint8_t value; + struct { + int8_t r; + } chan; +}; + +static INLINE void +util_format_r8_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + int8_t r; + r = (int8_t)(value) ; + dst[0] = (int)r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= (uint8_t)((int8_t)CLAMP(src[0], -128, 127)) ; + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint8_t value = *(const uint8_t *)src; + int8_t r; + r = (int8_t)(value) ; + dst[0] = (int)r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r8_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + int8_t r; + r = (int8_t)(value) ; + dst[0] = (unsigned)MAX2(r, 0); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= (uint8_t)((int8_t)MIN2(src[0], 127)) ; + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8g8_sint { + uint16_t value; + struct { + int8_t r; + int8_t g; + } chan; +}; + +static INLINE void +util_format_r8g8_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + int16_t r; + int16_t g; + r = ((int16_t)(value << 8) ) >> 8; + g = ((int16_t)(value) ) >> 8; + dst[0] = (int)r; /* r */ + dst[1] = (int)g; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)(((int8_t)CLAMP(src[0], -128, 127)) & 0xff) ; + value |= (uint16_t)(((int8_t)CLAMP(src[1], -128, 127)) << 8) ; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8g8_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + int16_t r; + int16_t g; + r = ((int16_t)(value << 8) ) >> 8; + g = ((int16_t)(value) ) >> 8; + dst[0] = (int)r; /* r */ + dst[1] = (int)g; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r8g8_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + int16_t r; + int16_t g; + r = ((int16_t)(value << 8) ) >> 8; + g = ((int16_t)(value) ) >> 8; + dst[0] = (unsigned)MAX2(r, 0); /* r */ + dst[1] = (unsigned)MAX2(g, 0); /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)(((int8_t)MIN2(src[0], 127)) & 0xff) ; + value |= (uint16_t)(((int8_t)MIN2(src[1], 127)) << 8) ; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8g8b8_sint { + struct { + int8_t r; + int8_t g; + int8_t b; + } chan; +}; + +static INLINE void +util_format_r8g8b8_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r8g8b8_sint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (int)pixel.chan.r; /* r */ + dst[1] = (int)pixel.chan.g; /* g */ + dst[2] = (int)pixel.chan.b; /* b */ + dst[3] = 1; /* a */ + src += 3; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r8g8b8_sint pixel; + pixel.chan.r = (int8_t)CLAMP(src[0], -128, 127); + pixel.chan.g = (int8_t)CLAMP(src[1], -128, 127); + pixel.chan.b = (int8_t)CLAMP(src[2], -128, 127); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 3; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8g8b8_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r8g8b8_sint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (int)pixel.chan.r; /* r */ + dst[1] = (int)pixel.chan.g; /* g */ + dst[2] = (int)pixel.chan.b; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r8g8b8_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r8g8b8_sint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (unsigned)MAX2(pixel.chan.r, 0); /* r */ + dst[1] = (unsigned)MAX2(pixel.chan.g, 0); /* g */ + dst[2] = (unsigned)MAX2(pixel.chan.b, 0); /* b */ + dst[3] = 1; /* a */ + src += 3; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r8g8b8_sint pixel; + pixel.chan.r = (int8_t)MIN2(src[0], 127); + pixel.chan.g = (int8_t)MIN2(src[1], 127); + pixel.chan.b = (int8_t)MIN2(src[2], 127); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 3; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8g8b8a8_sint { + uint32_t value; + struct { + int8_t r; + int8_t g; + int8_t b; + int8_t a; + } chan; +}; + +static INLINE void +util_format_r8g8b8a8_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + int32_t b; + int32_t a; + r = ((int32_t)(value << 24) ) >> 24; + g = ((int32_t)(value << 16) ) >> 24; + b = ((int32_t)(value << 8) ) >> 24; + a = ((int32_t)(value) ) >> 24; + dst[0] = (int)r; /* r */ + dst[1] = (int)g; /* g */ + dst[2] = (int)b; /* b */ + dst[3] = (int)a; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8a8_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((int8_t)CLAMP(src[0], -128, 127)) & 0xff) ; + value |= (uint32_t)((((int8_t)CLAMP(src[1], -128, 127)) & 0xff) << 8) ; + value |= (uint32_t)((((int8_t)CLAMP(src[2], -128, 127)) & 0xff) << 16) ; + value |= (uint32_t)(((int8_t)CLAMP(src[3], -128, 127)) << 24) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8g8b8a8_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + int32_t b; + int32_t a; + r = ((int32_t)(value << 24) ) >> 24; + g = ((int32_t)(value << 16) ) >> 24; + b = ((int32_t)(value << 8) ) >> 24; + a = ((int32_t)(value) ) >> 24; + dst[0] = (int)r; /* r */ + dst[1] = (int)g; /* g */ + dst[2] = (int)b; /* b */ + dst[3] = (int)a; /* a */ +} + +static INLINE void +util_format_r8g8b8a8_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + int32_t b; + int32_t a; + r = ((int32_t)(value << 24) ) >> 24; + g = ((int32_t)(value << 16) ) >> 24; + b = ((int32_t)(value << 8) ) >> 24; + a = ((int32_t)(value) ) >> 24; + dst[0] = (unsigned)MAX2(r, 0); /* r */ + dst[1] = (unsigned)MAX2(g, 0); /* g */ + dst[2] = (unsigned)MAX2(b, 0); /* b */ + dst[3] = (unsigned)MAX2(a, 0); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8a8_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((int8_t)MIN2(src[0], 127)) & 0xff) ; + value |= (uint32_t)((((int8_t)MIN2(src[1], 127)) & 0xff) << 8) ; + value |= (uint32_t)((((int8_t)MIN2(src[2], 127)) & 0xff) << 16) ; + value |= (uint32_t)(((int8_t)MIN2(src[3], 127)) << 24) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16_uint { + uint16_t value; + struct { + uint16_t r; + } chan; +}; + +static INLINE void +util_format_r16_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t r; + r = value; + dst[0] = (unsigned)r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)MIN2(src[0], 65535); + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + uint16_t r; + r = value; + dst[0] = (unsigned)r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r16_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t r; + r = value; + dst[0] = (int)r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)CLAMP(src[0], 0, 65535); + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16g16_uint { + uint32_t value; + struct { + uint16_t r; + uint16_t g; + } chan; +}; + +static INLINE void +util_format_r16g16_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + r = (value) & 0xffff; + g = value >> 16; + dst[0] = (unsigned)r; /* r */ + dst[1] = (unsigned)g; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint16_t)MIN2(src[0], 65535)) & 0xffff; + value |= ((uint16_t)MIN2(src[1], 65535)) << 16; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16g16_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + r = (value) & 0xffff; + g = value >> 16; + dst[0] = (unsigned)r; /* r */ + dst[1] = (unsigned)g; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r16g16_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + r = (value) & 0xffff; + g = value >> 16; + dst[0] = (int)r; /* r */ + dst[1] = (int)g; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint16_t)CLAMP(src[0], 0, 65535)) & 0xffff; + value |= ((uint16_t)CLAMP(src[1], 0, 65535)) << 16; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16g16b16_uint { + struct { + uint16_t r; + uint16_t g; + uint16_t b; + } chan; +}; + +static INLINE void +util_format_r16g16b16_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16_uint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (unsigned)pixel.chan.r; /* r */ + dst[1] = (unsigned)pixel.chan.g; /* g */ + dst[2] = (unsigned)pixel.chan.b; /* b */ + dst[3] = 1; /* a */ + src += 6; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16_uint pixel; + pixel.chan.r = (uint16_t)MIN2(src[0], 65535); + pixel.chan.g = (uint16_t)MIN2(src[1], 65535); + pixel.chan.b = (uint16_t)MIN2(src[2], 65535); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 6; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16g16b16_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r16g16b16_uint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (unsigned)pixel.chan.r; /* r */ + dst[1] = (unsigned)pixel.chan.g; /* g */ + dst[2] = (unsigned)pixel.chan.b; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r16g16b16_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16_uint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (int)pixel.chan.r; /* r */ + dst[1] = (int)pixel.chan.g; /* g */ + dst[2] = (int)pixel.chan.b; /* b */ + dst[3] = 1; /* a */ + src += 6; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16_uint pixel; + pixel.chan.r = (uint16_t)CLAMP(src[0], 0, 65535); + pixel.chan.g = (uint16_t)CLAMP(src[1], 0, 65535); + pixel.chan.b = (uint16_t)CLAMP(src[2], 0, 65535); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 6; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16g16b16a16_uint { + uint64_t value; + struct { + uint16_t r; + uint16_t g; + uint16_t b; + uint16_t a; + } chan; +}; + +static INLINE void +util_format_r16g16b16a16_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16a16_uint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (unsigned)pixel.chan.r; /* r */ + dst[1] = (unsigned)pixel.chan.g; /* g */ + dst[2] = (unsigned)pixel.chan.b; /* b */ + dst[3] = (unsigned)pixel.chan.a; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16a16_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16a16_uint pixel; + pixel.chan.r = (uint16_t)MIN2(src[0], 65535); + pixel.chan.g = (uint16_t)MIN2(src[1], 65535); + pixel.chan.b = (uint16_t)MIN2(src[2], 65535); + pixel.chan.a = (uint16_t)MIN2(src[3], 65535); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16g16b16a16_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r16g16b16a16_uint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (unsigned)pixel.chan.r; /* r */ + dst[1] = (unsigned)pixel.chan.g; /* g */ + dst[2] = (unsigned)pixel.chan.b; /* b */ + dst[3] = (unsigned)pixel.chan.a; /* a */ +} + +static INLINE void +util_format_r16g16b16a16_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16a16_uint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (int)pixel.chan.r; /* r */ + dst[1] = (int)pixel.chan.g; /* g */ + dst[2] = (int)pixel.chan.b; /* b */ + dst[3] = (int)pixel.chan.a; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16a16_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16a16_uint pixel; + pixel.chan.r = (uint16_t)CLAMP(src[0], 0, 65535); + pixel.chan.g = (uint16_t)CLAMP(src[1], 0, 65535); + pixel.chan.b = (uint16_t)CLAMP(src[2], 0, 65535); + pixel.chan.a = (uint16_t)CLAMP(src[3], 0, 65535); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16_sint { + uint16_t value; + struct { + int16_t r; + } chan; +}; + +static INLINE void +util_format_r16_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + int16_t r; + r = (int16_t)(value) ; + dst[0] = (int)r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)((int16_t)CLAMP(src[0], -32768, 32767)) ; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + int16_t r; + r = (int16_t)(value) ; + dst[0] = (int)r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r16_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + int16_t r; + r = (int16_t)(value) ; + dst[0] = (unsigned)MAX2(r, 0); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)((int16_t)MIN2(src[0], 32767)) ; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16g16_sint { + uint32_t value; + struct { + int16_t r; + int16_t g; + } chan; +}; + +static INLINE void +util_format_r16g16_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + r = ((int32_t)(value << 16) ) >> 16; + g = ((int32_t)(value) ) >> 16; + dst[0] = (int)r; /* r */ + dst[1] = (int)g; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((int16_t)CLAMP(src[0], -32768, 32767)) & 0xffff) ; + value |= (uint32_t)(((int16_t)CLAMP(src[1], -32768, 32767)) << 16) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16g16_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + r = ((int32_t)(value << 16) ) >> 16; + g = ((int32_t)(value) ) >> 16; + dst[0] = (int)r; /* r */ + dst[1] = (int)g; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r16g16_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + r = ((int32_t)(value << 16) ) >> 16; + g = ((int32_t)(value) ) >> 16; + dst[0] = (unsigned)MAX2(r, 0); /* r */ + dst[1] = (unsigned)MAX2(g, 0); /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((int16_t)MIN2(src[0], 32767)) & 0xffff) ; + value |= (uint32_t)(((int16_t)MIN2(src[1], 32767)) << 16) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16g16b16_sint { + struct { + int16_t r; + int16_t g; + int16_t b; + } chan; +}; + +static INLINE void +util_format_r16g16b16_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16_sint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (int)pixel.chan.r; /* r */ + dst[1] = (int)pixel.chan.g; /* g */ + dst[2] = (int)pixel.chan.b; /* b */ + dst[3] = 1; /* a */ + src += 6; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16_sint pixel; + pixel.chan.r = (int16_t)CLAMP(src[0], -32768, 32767); + pixel.chan.g = (int16_t)CLAMP(src[1], -32768, 32767); + pixel.chan.b = (int16_t)CLAMP(src[2], -32768, 32767); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 6; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16g16b16_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r16g16b16_sint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (int)pixel.chan.r; /* r */ + dst[1] = (int)pixel.chan.g; /* g */ + dst[2] = (int)pixel.chan.b; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r16g16b16_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16_sint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (unsigned)MAX2(pixel.chan.r, 0); /* r */ + dst[1] = (unsigned)MAX2(pixel.chan.g, 0); /* g */ + dst[2] = (unsigned)MAX2(pixel.chan.b, 0); /* b */ + dst[3] = 1; /* a */ + src += 6; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16_sint pixel; + pixel.chan.r = (int16_t)MIN2(src[0], 32767); + pixel.chan.g = (int16_t)MIN2(src[1], 32767); + pixel.chan.b = (int16_t)MIN2(src[2], 32767); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 6; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16g16b16a16_sint { + uint64_t value; + struct { + int16_t r; + int16_t g; + int16_t b; + int16_t a; + } chan; +}; + +static INLINE void +util_format_r16g16b16a16_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16a16_sint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (int)pixel.chan.r; /* r */ + dst[1] = (int)pixel.chan.g; /* g */ + dst[2] = (int)pixel.chan.b; /* b */ + dst[3] = (int)pixel.chan.a; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16a16_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16a16_sint pixel; + pixel.chan.r = (int16_t)CLAMP(src[0], -32768, 32767); + pixel.chan.g = (int16_t)CLAMP(src[1], -32768, 32767); + pixel.chan.b = (int16_t)CLAMP(src[2], -32768, 32767); + pixel.chan.a = (int16_t)CLAMP(src[3], -32768, 32767); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16g16b16a16_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r16g16b16a16_sint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (int)pixel.chan.r; /* r */ + dst[1] = (int)pixel.chan.g; /* g */ + dst[2] = (int)pixel.chan.b; /* b */ + dst[3] = (int)pixel.chan.a; /* a */ +} + +static INLINE void +util_format_r16g16b16a16_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16a16_sint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (unsigned)MAX2(pixel.chan.r, 0); /* r */ + dst[1] = (unsigned)MAX2(pixel.chan.g, 0); /* g */ + dst[2] = (unsigned)MAX2(pixel.chan.b, 0); /* b */ + dst[3] = (unsigned)MAX2(pixel.chan.a, 0); /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16a16_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16a16_sint pixel; + pixel.chan.r = (int16_t)MIN2(src[0], 32767); + pixel.chan.g = (int16_t)MIN2(src[1], 32767); + pixel.chan.b = (int16_t)MIN2(src[2], 32767); + pixel.chan.a = (int16_t)MIN2(src[3], 32767); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32_uint { + uint32_t value; + struct { + uint32_t r; + } chan; +}; + +static INLINE void +util_format_r32_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + r = value; + dst[0] = r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= src[0]; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t r; + r = value; + dst[0] = r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r32_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + r = value; + dst[0] = (int)MIN2(r, 2147483647); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)MAX2(src[0], 0); + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32g32_uint { + uint64_t value; + struct { + uint32_t r; + uint32_t g; + } chan; +}; + +static INLINE void +util_format_r32g32_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32_uint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.r; /* r */ + dst[1] = pixel.chan.g; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32_uint pixel; + pixel.chan.r = src[0]; + pixel.chan.g = src[1]; + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32g32_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r32g32_uint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.r; /* r */ + dst[1] = pixel.chan.g; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r32g32_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32_uint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (int)MIN2(pixel.chan.r, 2147483647); /* r */ + dst[1] = (int)MIN2(pixel.chan.g, 2147483647); /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32_uint pixel; + pixel.chan.r = (uint32_t)MAX2(src[0], 0); + pixel.chan.g = (uint32_t)MAX2(src[1], 0); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32g32b32_uint { + struct { + uint32_t r; + uint32_t g; + uint32_t b; + } chan; +}; + +static INLINE void +util_format_r32g32b32_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32_uint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.r; /* r */ + dst[1] = pixel.chan.g; /* g */ + dst[2] = pixel.chan.b; /* b */ + dst[3] = 1; /* a */ + src += 12; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32_uint pixel; + pixel.chan.r = src[0]; + pixel.chan.g = src[1]; + pixel.chan.b = src[2]; + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 12; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32g32b32_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r32g32b32_uint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.r; /* r */ + dst[1] = pixel.chan.g; /* g */ + dst[2] = pixel.chan.b; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r32g32b32_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32_uint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (int)MIN2(pixel.chan.r, 2147483647); /* r */ + dst[1] = (int)MIN2(pixel.chan.g, 2147483647); /* g */ + dst[2] = (int)MIN2(pixel.chan.b, 2147483647); /* b */ + dst[3] = 1; /* a */ + src += 12; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32_uint pixel; + pixel.chan.r = (uint32_t)MAX2(src[0], 0); + pixel.chan.g = (uint32_t)MAX2(src[1], 0); + pixel.chan.b = (uint32_t)MAX2(src[2], 0); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 12; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32g32b32a32_uint { + struct { + uint32_t r; + uint32_t g; + uint32_t b; + uint32_t a; + } chan; +}; + +static INLINE void +util_format_r32g32b32a32_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32a32_uint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.r; /* r */ + dst[1] = pixel.chan.g; /* g */ + dst[2] = pixel.chan.b; /* b */ + dst[3] = pixel.chan.a; /* a */ + src += 16; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32a32_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32a32_uint pixel; + pixel.chan.r = src[0]; + pixel.chan.g = src[1]; + pixel.chan.b = src[2]; + pixel.chan.a = src[3]; + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 16; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32g32b32a32_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r32g32b32a32_uint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.r; /* r */ + dst[1] = pixel.chan.g; /* g */ + dst[2] = pixel.chan.b; /* b */ + dst[3] = pixel.chan.a; /* a */ +} + +static INLINE void +util_format_r32g32b32a32_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32a32_uint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (int)MIN2(pixel.chan.r, 2147483647); /* r */ + dst[1] = (int)MIN2(pixel.chan.g, 2147483647); /* g */ + dst[2] = (int)MIN2(pixel.chan.b, 2147483647); /* b */ + dst[3] = (int)MIN2(pixel.chan.a, 2147483647); /* a */ + src += 16; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32a32_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32a32_uint pixel; + pixel.chan.r = (uint32_t)MAX2(src[0], 0); + pixel.chan.g = (uint32_t)MAX2(src[1], 0); + pixel.chan.b = (uint32_t)MAX2(src[2], 0); + pixel.chan.a = (uint32_t)MAX2(src[3], 0); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 16; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32_sint { + uint32_t value; + struct { + int32_t r; + } chan; +}; + +static INLINE void +util_format_r32_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + r = (int32_t)(value) ; + dst[0] = r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(src[0]) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + int32_t r; + r = (int32_t)(value) ; + dst[0] = r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r32_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + r = (int32_t)(value) ; + dst[0] = (unsigned)MAX2(r, 0); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)((int32_t)MIN2(src[0], 2147483647)) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32g32_sint { + uint64_t value; + struct { + int32_t r; + int32_t g; + } chan; +}; + +static INLINE void +util_format_r32g32_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32_sint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.r; /* r */ + dst[1] = pixel.chan.g; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32_sint pixel; + pixel.chan.r = src[0]; + pixel.chan.g = src[1]; + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32g32_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r32g32_sint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.r; /* r */ + dst[1] = pixel.chan.g; /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r32g32_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32_sint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (unsigned)MAX2(pixel.chan.r, 0); /* r */ + dst[1] = (unsigned)MAX2(pixel.chan.g, 0); /* g */ + dst[2] = 0; /* b */ + dst[3] = 1; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32_sint pixel; + pixel.chan.r = (int32_t)MIN2(src[0], 2147483647); + pixel.chan.g = (int32_t)MIN2(src[1], 2147483647); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32g32b32_sint { + struct { + int32_t r; + int32_t g; + int32_t b; + } chan; +}; + +static INLINE void +util_format_r32g32b32_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32_sint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.r; /* r */ + dst[1] = pixel.chan.g; /* g */ + dst[2] = pixel.chan.b; /* b */ + dst[3] = 1; /* a */ + src += 12; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32_sint pixel; + pixel.chan.r = src[0]; + pixel.chan.g = src[1]; + pixel.chan.b = src[2]; + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 12; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32g32b32_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r32g32b32_sint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.r; /* r */ + dst[1] = pixel.chan.g; /* g */ + dst[2] = pixel.chan.b; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r32g32b32_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32_sint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (unsigned)MAX2(pixel.chan.r, 0); /* r */ + dst[1] = (unsigned)MAX2(pixel.chan.g, 0); /* g */ + dst[2] = (unsigned)MAX2(pixel.chan.b, 0); /* b */ + dst[3] = 1; /* a */ + src += 12; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32_sint pixel; + pixel.chan.r = (int32_t)MIN2(src[0], 2147483647); + pixel.chan.g = (int32_t)MIN2(src[1], 2147483647); + pixel.chan.b = (int32_t)MIN2(src[2], 2147483647); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 12; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32g32b32a32_sint { + struct { + int32_t r; + int32_t g; + int32_t b; + int32_t a; + } chan; +}; + +static INLINE void +util_format_r32g32b32a32_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32a32_sint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.r; /* r */ + dst[1] = pixel.chan.g; /* g */ + dst[2] = pixel.chan.b; /* b */ + dst[3] = pixel.chan.a; /* a */ + src += 16; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32a32_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32a32_sint pixel; + pixel.chan.r = src[0]; + pixel.chan.g = src[1]; + pixel.chan.b = src[2]; + pixel.chan.a = src[3]; + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 16; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32g32b32a32_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r32g32b32a32_sint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.r; /* r */ + dst[1] = pixel.chan.g; /* g */ + dst[2] = pixel.chan.b; /* b */ + dst[3] = pixel.chan.a; /* a */ +} + +static INLINE void +util_format_r32g32b32a32_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32a32_sint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (unsigned)MAX2(pixel.chan.r, 0); /* r */ + dst[1] = (unsigned)MAX2(pixel.chan.g, 0); /* g */ + dst[2] = (unsigned)MAX2(pixel.chan.b, 0); /* b */ + dst[3] = (unsigned)MAX2(pixel.chan.a, 0); /* a */ + src += 16; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32a32_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32a32_sint pixel; + pixel.chan.r = (int32_t)MIN2(src[0], 2147483647); + pixel.chan.g = (int32_t)MIN2(src[1], 2147483647); + pixel.chan.b = (int32_t)MIN2(src[2], 2147483647); + pixel.chan.a = (int32_t)MIN2(src[3], 2147483647); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 16; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_a8_uint { + uint8_t value; + struct { + uint8_t a; + } chan; +}; + +static INLINE void +util_format_a8_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + uint8_t a; + a = value; + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (unsigned)a; /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a8_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= (uint8_t)MIN2(src[3], 255); + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_a8_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint8_t value = *(const uint8_t *)src; + uint8_t a; + a = value; + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (unsigned)a; /* a */ +} + +static INLINE void +util_format_a8_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + uint8_t a; + a = value; + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (int)a; /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a8_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= (uint8_t)CLAMP(src[3], 0, 255); + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_i8_uint { + uint8_t value; + struct { + uint8_t rgba; + } chan; +}; + +static INLINE void +util_format_i8_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + uint8_t rgba; + rgba = value; + dst[0] = (unsigned)rgba; /* r */ + dst[1] = (unsigned)rgba; /* g */ + dst[2] = (unsigned)rgba; /* b */ + dst[3] = (unsigned)rgba; /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_i8_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= (uint8_t)MIN2(src[0], 255); + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_i8_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint8_t value = *(const uint8_t *)src; + uint8_t rgba; + rgba = value; + dst[0] = (unsigned)rgba; /* r */ + dst[1] = (unsigned)rgba; /* g */ + dst[2] = (unsigned)rgba; /* b */ + dst[3] = (unsigned)rgba; /* a */ +} + +static INLINE void +util_format_i8_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + uint8_t rgba; + rgba = value; + dst[0] = (int)rgba; /* r */ + dst[1] = (int)rgba; /* g */ + dst[2] = (int)rgba; /* b */ + dst[3] = (int)rgba; /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_i8_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= (uint8_t)CLAMP(src[0], 0, 255); + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_l8_uint { + uint8_t value; + struct { + uint8_t rgb; + } chan; +}; + +static INLINE void +util_format_l8_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + uint8_t rgb; + rgb = value; + dst[0] = (unsigned)rgb; /* r */ + dst[1] = (unsigned)rgb; /* g */ + dst[2] = (unsigned)rgb; /* b */ + dst[3] = 1; /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l8_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= (uint8_t)MIN2(src[0], 255); + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_l8_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint8_t value = *(const uint8_t *)src; + uint8_t rgb; + rgb = value; + dst[0] = (unsigned)rgb; /* r */ + dst[1] = (unsigned)rgb; /* g */ + dst[2] = (unsigned)rgb; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_l8_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + uint8_t rgb; + rgb = value; + dst[0] = (int)rgb; /* r */ + dst[1] = (int)rgb; /* g */ + dst[2] = (int)rgb; /* b */ + dst[3] = 1; /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l8_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= (uint8_t)CLAMP(src[0], 0, 255); + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_l8a8_uint { + uint16_t value; + struct { + uint8_t rgb; + uint8_t a; + } chan; +}; + +static INLINE void +util_format_l8a8_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t rgb; + uint16_t a; + rgb = (value) & 0xff; + a = value >> 8; + dst[0] = (unsigned)rgb; /* r */ + dst[1] = (unsigned)rgb; /* g */ + dst[2] = (unsigned)rgb; /* b */ + dst[3] = (unsigned)a; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l8a8_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= ((uint8_t)MIN2(src[0], 255)) & 0xff; + value |= ((uint8_t)MIN2(src[3], 255)) << 8; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_l8a8_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + uint16_t rgb; + uint16_t a; + rgb = (value) & 0xff; + a = value >> 8; + dst[0] = (unsigned)rgb; /* r */ + dst[1] = (unsigned)rgb; /* g */ + dst[2] = (unsigned)rgb; /* b */ + dst[3] = (unsigned)a; /* a */ +} + +static INLINE void +util_format_l8a8_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t rgb; + uint16_t a; + rgb = (value) & 0xff; + a = value >> 8; + dst[0] = (int)rgb; /* r */ + dst[1] = (int)rgb; /* g */ + dst[2] = (int)rgb; /* b */ + dst[3] = (int)a; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l8a8_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= ((uint8_t)CLAMP(src[0], 0, 255)) & 0xff; + value |= ((uint8_t)CLAMP(src[3], 0, 255)) << 8; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_a8_sint { + uint8_t value; + struct { + int8_t a; + } chan; +}; + +static INLINE void +util_format_a8_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + int8_t a; + a = (int8_t)(value) ; + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (int)a; /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a8_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= (uint8_t)((int8_t)CLAMP(src[3], -128, 127)) ; + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_a8_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint8_t value = *(const uint8_t *)src; + int8_t a; + a = (int8_t)(value) ; + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (int)a; /* a */ +} + +static INLINE void +util_format_a8_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + int8_t a; + a = (int8_t)(value) ; + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (unsigned)MAX2(a, 0); /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a8_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= (uint8_t)((int8_t)MIN2(src[3], 127)) ; + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_i8_sint { + uint8_t value; + struct { + int8_t rgba; + } chan; +}; + +static INLINE void +util_format_i8_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + int8_t rgba; + rgba = (int8_t)(value) ; + dst[0] = (int)rgba; /* r */ + dst[1] = (int)rgba; /* g */ + dst[2] = (int)rgba; /* b */ + dst[3] = (int)rgba; /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_i8_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= (uint8_t)((int8_t)CLAMP(src[0], -128, 127)) ; + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_i8_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint8_t value = *(const uint8_t *)src; + int8_t rgba; + rgba = (int8_t)(value) ; + dst[0] = (int)rgba; /* r */ + dst[1] = (int)rgba; /* g */ + dst[2] = (int)rgba; /* b */ + dst[3] = (int)rgba; /* a */ +} + +static INLINE void +util_format_i8_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + int8_t rgba; + rgba = (int8_t)(value) ; + dst[0] = (unsigned)MAX2(rgba, 0); /* r */ + dst[1] = (unsigned)MAX2(rgba, 0); /* g */ + dst[2] = (unsigned)MAX2(rgba, 0); /* b */ + dst[3] = (unsigned)MAX2(rgba, 0); /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_i8_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= (uint8_t)((int8_t)MIN2(src[0], 127)) ; + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_l8_sint { + uint8_t value; + struct { + int8_t rgb; + } chan; +}; + +static INLINE void +util_format_l8_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + int8_t rgb; + rgb = (int8_t)(value) ; + dst[0] = (int)rgb; /* r */ + dst[1] = (int)rgb; /* g */ + dst[2] = (int)rgb; /* b */ + dst[3] = 1; /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l8_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= (uint8_t)((int8_t)CLAMP(src[0], -128, 127)) ; + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_l8_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint8_t value = *(const uint8_t *)src; + int8_t rgb; + rgb = (int8_t)(value) ; + dst[0] = (int)rgb; /* r */ + dst[1] = (int)rgb; /* g */ + dst[2] = (int)rgb; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_l8_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint8_t value = *(const uint8_t *)src; + int8_t rgb; + rgb = (int8_t)(value) ; + dst[0] = (unsigned)MAX2(rgb, 0); /* r */ + dst[1] = (unsigned)MAX2(rgb, 0); /* g */ + dst[2] = (unsigned)MAX2(rgb, 0); /* b */ + dst[3] = 1; /* a */ + src += 1; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l8_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint8_t value = 0; + value |= (uint8_t)((int8_t)MIN2(src[0], 127)) ; + *(uint8_t *)dst = value; + src += 4; + dst += 1; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_l8a8_sint { + uint16_t value; + struct { + int8_t rgb; + int8_t a; + } chan; +}; + +static INLINE void +util_format_l8a8_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + int16_t rgb; + int16_t a; + rgb = ((int16_t)(value << 8) ) >> 8; + a = ((int16_t)(value) ) >> 8; + dst[0] = (int)rgb; /* r */ + dst[1] = (int)rgb; /* g */ + dst[2] = (int)rgb; /* b */ + dst[3] = (int)a; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l8a8_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)(((int8_t)CLAMP(src[0], -128, 127)) & 0xff) ; + value |= (uint16_t)(((int8_t)CLAMP(src[3], -128, 127)) << 8) ; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_l8a8_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + int16_t rgb; + int16_t a; + rgb = ((int16_t)(value << 8) ) >> 8; + a = ((int16_t)(value) ) >> 8; + dst[0] = (int)rgb; /* r */ + dst[1] = (int)rgb; /* g */ + dst[2] = (int)rgb; /* b */ + dst[3] = (int)a; /* a */ +} + +static INLINE void +util_format_l8a8_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + int16_t rgb; + int16_t a; + rgb = ((int16_t)(value << 8) ) >> 8; + a = ((int16_t)(value) ) >> 8; + dst[0] = (unsigned)MAX2(rgb, 0); /* r */ + dst[1] = (unsigned)MAX2(rgb, 0); /* g */ + dst[2] = (unsigned)MAX2(rgb, 0); /* b */ + dst[3] = (unsigned)MAX2(a, 0); /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l8a8_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)(((int8_t)MIN2(src[0], 127)) & 0xff) ; + value |= (uint16_t)(((int8_t)MIN2(src[3], 127)) << 8) ; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_a16_uint { + uint16_t value; + struct { + uint16_t a; + } chan; +}; + +static INLINE void +util_format_a16_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t a; + a = value; + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (unsigned)a; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a16_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)MIN2(src[3], 65535); + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_a16_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + uint16_t a; + a = value; + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (unsigned)a; /* a */ +} + +static INLINE void +util_format_a16_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t a; + a = value; + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (int)a; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a16_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)CLAMP(src[3], 0, 65535); + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_i16_uint { + uint16_t value; + struct { + uint16_t rgba; + } chan; +}; + +static INLINE void +util_format_i16_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t rgba; + rgba = value; + dst[0] = (unsigned)rgba; /* r */ + dst[1] = (unsigned)rgba; /* g */ + dst[2] = (unsigned)rgba; /* b */ + dst[3] = (unsigned)rgba; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_i16_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)MIN2(src[0], 65535); + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_i16_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + uint16_t rgba; + rgba = value; + dst[0] = (unsigned)rgba; /* r */ + dst[1] = (unsigned)rgba; /* g */ + dst[2] = (unsigned)rgba; /* b */ + dst[3] = (unsigned)rgba; /* a */ +} + +static INLINE void +util_format_i16_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t rgba; + rgba = value; + dst[0] = (int)rgba; /* r */ + dst[1] = (int)rgba; /* g */ + dst[2] = (int)rgba; /* b */ + dst[3] = (int)rgba; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_i16_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)CLAMP(src[0], 0, 65535); + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_l16_uint { + uint16_t value; + struct { + uint16_t rgb; + } chan; +}; + +static INLINE void +util_format_l16_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t rgb; + rgb = value; + dst[0] = (unsigned)rgb; /* r */ + dst[1] = (unsigned)rgb; /* g */ + dst[2] = (unsigned)rgb; /* b */ + dst[3] = 1; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l16_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)MIN2(src[0], 65535); + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_l16_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + uint16_t rgb; + rgb = value; + dst[0] = (unsigned)rgb; /* r */ + dst[1] = (unsigned)rgb; /* g */ + dst[2] = (unsigned)rgb; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_l16_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t rgb; + rgb = value; + dst[0] = (int)rgb; /* r */ + dst[1] = (int)rgb; /* g */ + dst[2] = (int)rgb; /* b */ + dst[3] = 1; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l16_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)CLAMP(src[0], 0, 65535); + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_l16a16_uint { + uint32_t value; + struct { + uint16_t rgb; + uint16_t a; + } chan; +}; + +static INLINE void +util_format_l16a16_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t rgb; + uint32_t a; + rgb = (value) & 0xffff; + a = value >> 16; + dst[0] = (unsigned)rgb; /* r */ + dst[1] = (unsigned)rgb; /* g */ + dst[2] = (unsigned)rgb; /* b */ + dst[3] = (unsigned)a; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l16a16_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint16_t)MIN2(src[0], 65535)) & 0xffff; + value |= ((uint16_t)MIN2(src[3], 65535)) << 16; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_l16a16_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t rgb; + uint32_t a; + rgb = (value) & 0xffff; + a = value >> 16; + dst[0] = (unsigned)rgb; /* r */ + dst[1] = (unsigned)rgb; /* g */ + dst[2] = (unsigned)rgb; /* b */ + dst[3] = (unsigned)a; /* a */ +} + +static INLINE void +util_format_l16a16_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t rgb; + uint32_t a; + rgb = (value) & 0xffff; + a = value >> 16; + dst[0] = (int)rgb; /* r */ + dst[1] = (int)rgb; /* g */ + dst[2] = (int)rgb; /* b */ + dst[3] = (int)a; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l16a16_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint16_t)CLAMP(src[0], 0, 65535)) & 0xffff; + value |= ((uint16_t)CLAMP(src[3], 0, 65535)) << 16; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_a16_sint { + uint16_t value; + struct { + int16_t a; + } chan; +}; + +static INLINE void +util_format_a16_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + int16_t a; + a = (int16_t)(value) ; + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (int)a; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a16_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)((int16_t)CLAMP(src[3], -32768, 32767)) ; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_a16_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + int16_t a; + a = (int16_t)(value) ; + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (int)a; /* a */ +} + +static INLINE void +util_format_a16_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + int16_t a; + a = (int16_t)(value) ; + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (unsigned)MAX2(a, 0); /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a16_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)((int16_t)MIN2(src[3], 32767)) ; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_i16_sint { + uint16_t value; + struct { + int16_t rgba; + } chan; +}; + +static INLINE void +util_format_i16_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + int16_t rgba; + rgba = (int16_t)(value) ; + dst[0] = (int)rgba; /* r */ + dst[1] = (int)rgba; /* g */ + dst[2] = (int)rgba; /* b */ + dst[3] = (int)rgba; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_i16_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)((int16_t)CLAMP(src[0], -32768, 32767)) ; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_i16_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + int16_t rgba; + rgba = (int16_t)(value) ; + dst[0] = (int)rgba; /* r */ + dst[1] = (int)rgba; /* g */ + dst[2] = (int)rgba; /* b */ + dst[3] = (int)rgba; /* a */ +} + +static INLINE void +util_format_i16_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + int16_t rgba; + rgba = (int16_t)(value) ; + dst[0] = (unsigned)MAX2(rgba, 0); /* r */ + dst[1] = (unsigned)MAX2(rgba, 0); /* g */ + dst[2] = (unsigned)MAX2(rgba, 0); /* b */ + dst[3] = (unsigned)MAX2(rgba, 0); /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_i16_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)((int16_t)MIN2(src[0], 32767)) ; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_l16_sint { + uint16_t value; + struct { + int16_t rgb; + } chan; +}; + +static INLINE void +util_format_l16_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + int16_t rgb; + rgb = (int16_t)(value) ; + dst[0] = (int)rgb; /* r */ + dst[1] = (int)rgb; /* g */ + dst[2] = (int)rgb; /* b */ + dst[3] = 1; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l16_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)((int16_t)CLAMP(src[0], -32768, 32767)) ; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_l16_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + int16_t rgb; + rgb = (int16_t)(value) ; + dst[0] = (int)rgb; /* r */ + dst[1] = (int)rgb; /* g */ + dst[2] = (int)rgb; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_l16_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + int16_t rgb; + rgb = (int16_t)(value) ; + dst[0] = (unsigned)MAX2(rgb, 0); /* r */ + dst[1] = (unsigned)MAX2(rgb, 0); /* g */ + dst[2] = (unsigned)MAX2(rgb, 0); /* b */ + dst[3] = 1; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l16_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)((int16_t)MIN2(src[0], 32767)) ; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_l16a16_sint { + uint32_t value; + struct { + int16_t rgb; + int16_t a; + } chan; +}; + +static INLINE void +util_format_l16a16_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t rgb; + int32_t a; + rgb = ((int32_t)(value << 16) ) >> 16; + a = ((int32_t)(value) ) >> 16; + dst[0] = (int)rgb; /* r */ + dst[1] = (int)rgb; /* g */ + dst[2] = (int)rgb; /* b */ + dst[3] = (int)a; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l16a16_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((int16_t)CLAMP(src[0], -32768, 32767)) & 0xffff) ; + value |= (uint32_t)(((int16_t)CLAMP(src[3], -32768, 32767)) << 16) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_l16a16_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + int32_t rgb; + int32_t a; + rgb = ((int32_t)(value << 16) ) >> 16; + a = ((int32_t)(value) ) >> 16; + dst[0] = (int)rgb; /* r */ + dst[1] = (int)rgb; /* g */ + dst[2] = (int)rgb; /* b */ + dst[3] = (int)a; /* a */ +} + +static INLINE void +util_format_l16a16_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t rgb; + int32_t a; + rgb = ((int32_t)(value << 16) ) >> 16; + a = ((int32_t)(value) ) >> 16; + dst[0] = (unsigned)MAX2(rgb, 0); /* r */ + dst[1] = (unsigned)MAX2(rgb, 0); /* g */ + dst[2] = (unsigned)MAX2(rgb, 0); /* b */ + dst[3] = (unsigned)MAX2(a, 0); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l16a16_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((int16_t)MIN2(src[0], 32767)) & 0xffff) ; + value |= (uint32_t)(((int16_t)MIN2(src[3], 32767)) << 16) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_a32_uint { + uint32_t value; + struct { + uint32_t a; + } chan; +}; + +static INLINE void +util_format_a32_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t a; + a = value; + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = a; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a32_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= src[3]; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_a32_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t a; + a = value; + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = a; /* a */ +} + +static INLINE void +util_format_a32_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t a; + a = value; + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (int)MIN2(a, 2147483647); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a32_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)MAX2(src[3], 0); + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_i32_uint { + uint32_t value; + struct { + uint32_t rgba; + } chan; +}; + +static INLINE void +util_format_i32_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t rgba; + rgba = value; + dst[0] = rgba; /* r */ + dst[1] = rgba; /* g */ + dst[2] = rgba; /* b */ + dst[3] = rgba; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_i32_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= src[0]; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_i32_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t rgba; + rgba = value; + dst[0] = rgba; /* r */ + dst[1] = rgba; /* g */ + dst[2] = rgba; /* b */ + dst[3] = rgba; /* a */ +} + +static INLINE void +util_format_i32_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t rgba; + rgba = value; + dst[0] = (int)MIN2(rgba, 2147483647); /* r */ + dst[1] = (int)MIN2(rgba, 2147483647); /* g */ + dst[2] = (int)MIN2(rgba, 2147483647); /* b */ + dst[3] = (int)MIN2(rgba, 2147483647); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_i32_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)MAX2(src[0], 0); + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_l32_uint { + uint32_t value; + struct { + uint32_t rgb; + } chan; +}; + +static INLINE void +util_format_l32_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t rgb; + rgb = value; + dst[0] = rgb; /* r */ + dst[1] = rgb; /* g */ + dst[2] = rgb; /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l32_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= src[0]; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_l32_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t rgb; + rgb = value; + dst[0] = rgb; /* r */ + dst[1] = rgb; /* g */ + dst[2] = rgb; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_l32_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t rgb; + rgb = value; + dst[0] = (int)MIN2(rgb, 2147483647); /* r */ + dst[1] = (int)MIN2(rgb, 2147483647); /* g */ + dst[2] = (int)MIN2(rgb, 2147483647); /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l32_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)MAX2(src[0], 0); + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_l32a32_uint { + uint64_t value; + struct { + uint32_t rgb; + uint32_t a; + } chan; +}; + +static INLINE void +util_format_l32a32_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_l32a32_uint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.rgb; /* r */ + dst[1] = pixel.chan.rgb; /* g */ + dst[2] = pixel.chan.rgb; /* b */ + dst[3] = pixel.chan.a; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l32a32_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_l32a32_uint pixel; + pixel.chan.rgb = src[0]; + pixel.chan.a = src[3]; + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_l32a32_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_l32a32_uint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.rgb; /* r */ + dst[1] = pixel.chan.rgb; /* g */ + dst[2] = pixel.chan.rgb; /* b */ + dst[3] = pixel.chan.a; /* a */ +} + +static INLINE void +util_format_l32a32_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_l32a32_uint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (int)MIN2(pixel.chan.rgb, 2147483647); /* r */ + dst[1] = (int)MIN2(pixel.chan.rgb, 2147483647); /* g */ + dst[2] = (int)MIN2(pixel.chan.rgb, 2147483647); /* b */ + dst[3] = (int)MIN2(pixel.chan.a, 2147483647); /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l32a32_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_l32a32_uint pixel; + pixel.chan.rgb = (uint32_t)MAX2(src[0], 0); + pixel.chan.a = (uint32_t)MAX2(src[3], 0); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_a32_sint { + uint32_t value; + struct { + int32_t a; + } chan; +}; + +static INLINE void +util_format_a32_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t a; + a = (int32_t)(value) ; + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = a; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a32_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(src[3]) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_a32_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + int32_t a; + a = (int32_t)(value) ; + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = a; /* a */ +} + +static INLINE void +util_format_a32_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t a; + a = (int32_t)(value) ; + dst[0] = 0; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (unsigned)MAX2(a, 0); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_a32_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)((int32_t)MIN2(src[3], 2147483647)) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_i32_sint { + uint32_t value; + struct { + int32_t rgba; + } chan; +}; + +static INLINE void +util_format_i32_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t rgba; + rgba = (int32_t)(value) ; + dst[0] = rgba; /* r */ + dst[1] = rgba; /* g */ + dst[2] = rgba; /* b */ + dst[3] = rgba; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_i32_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(src[0]) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_i32_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + int32_t rgba; + rgba = (int32_t)(value) ; + dst[0] = rgba; /* r */ + dst[1] = rgba; /* g */ + dst[2] = rgba; /* b */ + dst[3] = rgba; /* a */ +} + +static INLINE void +util_format_i32_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t rgba; + rgba = (int32_t)(value) ; + dst[0] = (unsigned)MAX2(rgba, 0); /* r */ + dst[1] = (unsigned)MAX2(rgba, 0); /* g */ + dst[2] = (unsigned)MAX2(rgba, 0); /* b */ + dst[3] = (unsigned)MAX2(rgba, 0); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_i32_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)((int32_t)MIN2(src[0], 2147483647)) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_l32_sint { + uint32_t value; + struct { + int32_t rgb; + } chan; +}; + +static INLINE void +util_format_l32_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t rgb; + rgb = (int32_t)(value) ; + dst[0] = rgb; /* r */ + dst[1] = rgb; /* g */ + dst[2] = rgb; /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l32_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(src[0]) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_l32_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + int32_t rgb; + rgb = (int32_t)(value) ; + dst[0] = rgb; /* r */ + dst[1] = rgb; /* g */ + dst[2] = rgb; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_l32_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t rgb; + rgb = (int32_t)(value) ; + dst[0] = (unsigned)MAX2(rgb, 0); /* r */ + dst[1] = (unsigned)MAX2(rgb, 0); /* g */ + dst[2] = (unsigned)MAX2(rgb, 0); /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l32_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)((int32_t)MIN2(src[0], 2147483647)) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_l32a32_sint { + uint64_t value; + struct { + int32_t rgb; + int32_t a; + } chan; +}; + +static INLINE void +util_format_l32a32_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_l32a32_sint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.rgb; /* r */ + dst[1] = pixel.chan.rgb; /* g */ + dst[2] = pixel.chan.rgb; /* b */ + dst[3] = pixel.chan.a; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l32a32_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_l32a32_sint pixel; + pixel.chan.rgb = src[0]; + pixel.chan.a = src[3]; + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_l32a32_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_l32a32_sint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.rgb; /* r */ + dst[1] = pixel.chan.rgb; /* g */ + dst[2] = pixel.chan.rgb; /* b */ + dst[3] = pixel.chan.a; /* a */ +} + +static INLINE void +util_format_l32a32_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_l32a32_sint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (unsigned)MAX2(pixel.chan.rgb, 0); /* r */ + dst[1] = (unsigned)MAX2(pixel.chan.rgb, 0); /* g */ + dst[2] = (unsigned)MAX2(pixel.chan.rgb, 0); /* b */ + dst[3] = (unsigned)MAX2(pixel.chan.a, 0); /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_l32a32_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_l32a32_sint pixel; + pixel.chan.rgb = (int32_t)MIN2(src[0], 2147483647); + pixel.chan.a = (int32_t)MIN2(src[3], 2147483647); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_b10g10r10a2_uint { + uint32_t value; + struct { + unsigned b:10; + unsigned g:10; + unsigned r:10; + unsigned a:2; + } chan; +}; + +static INLINE void +util_format_b10g10r10a2_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t b; + uint32_t g; + uint32_t r; + uint32_t a; + b = (value) & 0x3ff; + g = (value >> 10) & 0x3ff; + r = (value >> 20) & 0x3ff; + a = value >> 30; + dst[0] = (unsigned)r; /* r */ + dst[1] = (unsigned)g; /* g */ + dst[2] = (unsigned)b; /* b */ + dst[3] = (unsigned)a; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_b10g10r10a2_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint32_t)MIN2(src[2], 1023)) & 0x3ff; + value |= (((uint32_t)MIN2(src[1], 1023)) & 0x3ff) << 10; + value |= (((uint32_t)MIN2(src[0], 1023)) & 0x3ff) << 20; + value |= ((uint32_t)MIN2(src[3], 3)) << 30; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_b10g10r10a2_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t b; + uint32_t g; + uint32_t r; + uint32_t a; + b = (value) & 0x3ff; + g = (value >> 10) & 0x3ff; + r = (value >> 20) & 0x3ff; + a = value >> 30; + dst[0] = (unsigned)r; /* r */ + dst[1] = (unsigned)g; /* g */ + dst[2] = (unsigned)b; /* b */ + dst[3] = (unsigned)a; /* a */ +} + +static INLINE void +util_format_b10g10r10a2_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t b; + uint32_t g; + uint32_t r; + uint32_t a; + b = (value) & 0x3ff; + g = (value >> 10) & 0x3ff; + r = (value >> 20) & 0x3ff; + a = value >> 30; + dst[0] = (int)r; /* r */ + dst[1] = (int)g; /* g */ + dst[2] = (int)b; /* b */ + dst[3] = (int)a; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_b10g10r10a2_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint32_t)CLAMP(src[2], 0, 1023)) & 0x3ff; + value |= (((uint32_t)CLAMP(src[1], 0, 1023)) & 0x3ff) << 10; + value |= (((uint32_t)CLAMP(src[0], 0, 1023)) & 0x3ff) << 20; + value |= ((uint32_t)CLAMP(src[3], 0, 3)) << 30; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8g8b8x8_snorm { + uint32_t value; + struct { + int8_t r; + int8_t g; + int8_t b; + uint8_t x; + } chan; +}; + +static INLINE void +util_format_r8g8b8x8_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + int32_t b; + r = ((int32_t)(value << 24) ) >> 24; + g = ((int32_t)(value << 16) ) >> 24; + b = ((int32_t)(value << 8) ) >> 24; + dst[0] = (float)(r * (1.0f/0x7f)); /* r */ + dst[1] = (float)(g * (1.0f/0x7f)); /* g */ + dst[2] = (float)(b * (1.0f/0x7f)); /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8x8_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((int8_t)util_iround(CLAMP(src[0], -1, 1) * 0x7f)) & 0xff) ; + value |= (uint32_t)((((int8_t)util_iround(CLAMP(src[1], -1, 1) * 0x7f)) & 0xff) << 8) ; + value |= (uint32_t)((((int8_t)util_iround(CLAMP(src[2], -1, 1) * 0x7f)) & 0xff) << 16) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8g8b8x8_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + int32_t b; + r = ((int32_t)(value << 24) ) >> 24; + g = ((int32_t)(value << 16) ) >> 24; + b = ((int32_t)(value << 8) ) >> 24; + dst[0] = (float)(r * (1.0f/0x7f)); /* r */ + dst[1] = (float)(g * (1.0f/0x7f)); /* g */ + dst[2] = (float)(b * (1.0f/0x7f)); /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r8g8b8x8_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + int32_t b; + r = ((int32_t)(value << 24) ) >> 24; + g = ((int32_t)(value << 16) ) >> 24; + b = ((int32_t)(value << 8) ) >> 24; + dst[0] = (uint8_t)(((uint32_t)MAX2(r, 0)) * 0xff / 0x7f); /* r */ + dst[1] = (uint8_t)(((uint32_t)MAX2(g, 0)) * 0xff / 0x7f); /* g */ + dst[2] = (uint8_t)(((uint32_t)MAX2(b, 0)) * 0xff / 0x7f); /* b */ + dst[3] = 255; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8x8_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((int8_t)(src[0] >> 1)) & 0xff) ; + value |= (uint32_t)((((int8_t)(src[1] >> 1)) & 0xff) << 8) ; + value |= (uint32_t)((((int8_t)(src[2] >> 1)) & 0xff) << 16) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8g8b8x8_srgb { + uint32_t value; + struct { + uint8_t r; + uint8_t g; + uint8_t b; + uint8_t x; + } chan; +}; + +static INLINE void +util_format_r8g8b8x8_srgb_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + r = (value) & 0xff; + g = (value >> 8) & 0xff; + b = (value >> 16) & 0xff; + dst[0] = util_format_srgb_8unorm_to_linear_float(r); /* r */ + dst[1] = util_format_srgb_8unorm_to_linear_float(g); /* g */ + dst[2] = util_format_srgb_8unorm_to_linear_float(b); /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8x8_srgb_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (util_format_linear_float_to_srgb_8unorm(src[0])) & 0xff; + value |= ((util_format_linear_float_to_srgb_8unorm(src[1])) & 0xff) << 8; + value |= ((util_format_linear_float_to_srgb_8unorm(src[2])) & 0xff) << 16; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8g8b8x8_srgb_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + r = (value) & 0xff; + g = (value >> 8) & 0xff; + b = (value >> 16) & 0xff; + dst[0] = util_format_srgb_8unorm_to_linear_float(r); /* r */ + dst[1] = util_format_srgb_8unorm_to_linear_float(g); /* g */ + dst[2] = util_format_srgb_8unorm_to_linear_float(b); /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r8g8b8x8_srgb_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + r = (value) & 0xff; + g = (value >> 8) & 0xff; + b = (value >> 16) & 0xff; + dst[0] = util_format_srgb_to_linear_8unorm(r); /* r */ + dst[1] = util_format_srgb_to_linear_8unorm(g); /* g */ + dst[2] = util_format_srgb_to_linear_8unorm(b); /* b */ + dst[3] = 255; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8x8_srgb_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (util_format_linear_to_srgb_8unorm(src[0])) & 0xff; + value |= ((util_format_linear_to_srgb_8unorm(src[1])) & 0xff) << 8; + value |= ((util_format_linear_to_srgb_8unorm(src[2])) & 0xff) << 16; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8g8b8x8_uint { + uint32_t value; + struct { + uint8_t r; + uint8_t g; + uint8_t b; + uint8_t x; + } chan; +}; + +static INLINE void +util_format_r8g8b8x8_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + r = (value) & 0xff; + g = (value >> 8) & 0xff; + b = (value >> 16) & 0xff; + dst[0] = (unsigned)r; /* r */ + dst[1] = (unsigned)g; /* g */ + dst[2] = (unsigned)b; /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8x8_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint8_t)MIN2(src[0], 255)) & 0xff; + value |= (((uint8_t)MIN2(src[1], 255)) & 0xff) << 8; + value |= (((uint8_t)MIN2(src[2], 255)) & 0xff) << 16; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8g8b8x8_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + r = (value) & 0xff; + g = (value >> 8) & 0xff; + b = (value >> 16) & 0xff; + dst[0] = (unsigned)r; /* r */ + dst[1] = (unsigned)g; /* g */ + dst[2] = (unsigned)b; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r8g8b8x8_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + r = (value) & 0xff; + g = (value >> 8) & 0xff; + b = (value >> 16) & 0xff; + dst[0] = (int)r; /* r */ + dst[1] = (int)g; /* g */ + dst[2] = (int)b; /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8x8_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint8_t)CLAMP(src[0], 0, 255)) & 0xff; + value |= (((uint8_t)CLAMP(src[1], 0, 255)) & 0xff) << 8; + value |= (((uint8_t)CLAMP(src[2], 0, 255)) & 0xff) << 16; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8g8b8x8_sint { + uint32_t value; + struct { + int8_t r; + int8_t g; + int8_t b; + uint8_t x; + } chan; +}; + +static INLINE void +util_format_r8g8b8x8_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + int32_t b; + r = ((int32_t)(value << 24) ) >> 24; + g = ((int32_t)(value << 16) ) >> 24; + b = ((int32_t)(value << 8) ) >> 24; + dst[0] = (int)r; /* r */ + dst[1] = (int)g; /* g */ + dst[2] = (int)b; /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8x8_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((int8_t)CLAMP(src[0], -128, 127)) & 0xff) ; + value |= (uint32_t)((((int8_t)CLAMP(src[1], -128, 127)) & 0xff) << 8) ; + value |= (uint32_t)((((int8_t)CLAMP(src[2], -128, 127)) & 0xff) << 16) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8g8b8x8_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + int32_t b; + r = ((int32_t)(value << 24) ) >> 24; + g = ((int32_t)(value << 16) ) >> 24; + b = ((int32_t)(value << 8) ) >> 24; + dst[0] = (int)r; /* r */ + dst[1] = (int)g; /* g */ + dst[2] = (int)b; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r8g8b8x8_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t g; + int32_t b; + r = ((int32_t)(value << 24) ) >> 24; + g = ((int32_t)(value << 16) ) >> 24; + b = ((int32_t)(value << 8) ) >> 24; + dst[0] = (unsigned)MAX2(r, 0); /* r */ + dst[1] = (unsigned)MAX2(g, 0); /* g */ + dst[2] = (unsigned)MAX2(b, 0); /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8g8b8x8_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((int8_t)MIN2(src[0], 127)) & 0xff) ; + value |= (uint32_t)((((int8_t)MIN2(src[1], 127)) & 0xff) << 8) ; + value |= (uint32_t)((((int8_t)MIN2(src[2], 127)) & 0xff) << 16) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_b10g10r10x2_unorm { + uint32_t value; + struct { + unsigned b:10; + unsigned g:10; + unsigned r:10; + unsigned x:2; + } chan; +}; + +static INLINE void +util_format_b10g10r10x2_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t b; + uint32_t g; + uint32_t r; + b = (value) & 0x3ff; + g = (value >> 10) & 0x3ff; + r = (value >> 20) & 0x3ff; + dst[0] = (float)(r * (1.0f/0x3ff)); /* r */ + dst[1] = (float)(g * (1.0f/0x3ff)); /* g */ + dst[2] = (float)(b * (1.0f/0x3ff)); /* b */ + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_b10g10r10x2_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint32_t)util_iround(CLAMP(src[2], 0, 1) * 0x3ff)) & 0x3ff; + value |= (((uint32_t)util_iround(CLAMP(src[1], 0, 1) * 0x3ff)) & 0x3ff) << 10; + value |= (((uint32_t)util_iround(CLAMP(src[0], 0, 1) * 0x3ff)) & 0x3ff) << 20; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_b10g10r10x2_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t b; + uint32_t g; + uint32_t r; + b = (value) & 0x3ff; + g = (value >> 10) & 0x3ff; + r = (value >> 20) & 0x3ff; + dst[0] = (float)(r * (1.0f/0x3ff)); /* r */ + dst[1] = (float)(g * (1.0f/0x3ff)); /* g */ + dst[2] = (float)(b * (1.0f/0x3ff)); /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_b10g10r10x2_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t b; + uint32_t g; + uint32_t r; + b = (value) & 0x3ff; + g = (value >> 10) & 0x3ff; + r = (value >> 20) & 0x3ff; + dst[0] = (uint8_t)(r >> 2); /* r */ + dst[1] = (uint8_t)(g >> 2); /* g */ + dst[2] = (uint8_t)(b >> 2); /* b */ + dst[3] = 255; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_b10g10r10x2_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint32_t)(((uint32_t)src[2]) * 0x3ff / 0xff)) & 0x3ff; + value |= (((uint32_t)(((uint32_t)src[1]) * 0x3ff / 0xff)) & 0x3ff) << 10; + value |= (((uint32_t)(((uint32_t)src[0]) * 0x3ff / 0xff)) & 0x3ff) << 20; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16g16b16x16_unorm { + uint64_t value; + struct { + uint16_t r; + uint16_t g; + uint16_t b; + uint16_t x; + } chan; +}; + +static INLINE void +util_format_r16g16b16x16_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16x16_unorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)(pixel.chan.r * (1.0f/0xffff)); /* r */ + dst[1] = (float)(pixel.chan.g * (1.0f/0xffff)); /* g */ + dst[2] = (float)(pixel.chan.b * (1.0f/0xffff)); /* b */ + dst[3] = 1; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16x16_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16x16_unorm pixel; + pixel.chan.r = (uint16_t)util_iround(CLAMP(src[0], 0, 1) * 0xffff); + pixel.chan.g = (uint16_t)util_iround(CLAMP(src[1], 0, 1) * 0xffff); + pixel.chan.b = (uint16_t)util_iround(CLAMP(src[2], 0, 1) * 0xffff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16g16b16x16_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r16g16b16x16_unorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)(pixel.chan.r * (1.0f/0xffff)); /* r */ + dst[1] = (float)(pixel.chan.g * (1.0f/0xffff)); /* g */ + dst[2] = (float)(pixel.chan.b * (1.0f/0xffff)); /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r16g16b16x16_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16x16_unorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (uint8_t)(pixel.chan.r >> 8); /* r */ + dst[1] = (uint8_t)(pixel.chan.g >> 8); /* g */ + dst[2] = (uint8_t)(pixel.chan.b >> 8); /* b */ + dst[3] = 255; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16x16_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16x16_unorm pixel; + pixel.chan.r = (uint16_t)(((uint32_t)src[0]) * 0xffff / 0xff); + pixel.chan.g = (uint16_t)(((uint32_t)src[1]) * 0xffff / 0xff); + pixel.chan.b = (uint16_t)(((uint32_t)src[2]) * 0xffff / 0xff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16g16b16x16_snorm { + uint64_t value; + struct { + int16_t r; + int16_t g; + int16_t b; + uint16_t x; + } chan; +}; + +static INLINE void +util_format_r16g16b16x16_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16x16_snorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)(pixel.chan.r * (1.0f/0x7fff)); /* r */ + dst[1] = (float)(pixel.chan.g * (1.0f/0x7fff)); /* g */ + dst[2] = (float)(pixel.chan.b * (1.0f/0x7fff)); /* b */ + dst[3] = 1; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16x16_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16x16_snorm pixel; + pixel.chan.r = (int16_t)util_iround(CLAMP(src[0], -1, 1) * 0x7fff); + pixel.chan.g = (int16_t)util_iround(CLAMP(src[1], -1, 1) * 0x7fff); + pixel.chan.b = (int16_t)util_iround(CLAMP(src[2], -1, 1) * 0x7fff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16g16b16x16_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r16g16b16x16_snorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (float)(pixel.chan.r * (1.0f/0x7fff)); /* r */ + dst[1] = (float)(pixel.chan.g * (1.0f/0x7fff)); /* g */ + dst[2] = (float)(pixel.chan.b * (1.0f/0x7fff)); /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r16g16b16x16_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16x16_snorm pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (uint8_t)(MAX2(pixel.chan.r, 0) >> 7); /* r */ + dst[1] = (uint8_t)(MAX2(pixel.chan.g, 0) >> 7); /* g */ + dst[2] = (uint8_t)(MAX2(pixel.chan.b, 0) >> 7); /* b */ + dst[3] = 255; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16x16_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16x16_snorm pixel; + pixel.chan.r = (int16_t)(((uint32_t)src[0]) * 0x7fff / 0xff); + pixel.chan.g = (int16_t)(((uint32_t)src[1]) * 0x7fff / 0xff); + pixel.chan.b = (int16_t)(((uint32_t)src[2]) * 0x7fff / 0xff); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16g16b16x16_float { + uint64_t value; + struct { + uint16_t r; + uint16_t g; + uint16_t b; + uint16_t x; + } chan; +}; + +static INLINE void +util_format_r16g16b16x16_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16x16_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = util_half_to_float(pixel.chan.r); /* r */ + dst[1] = util_half_to_float(pixel.chan.g); /* g */ + dst[2] = util_half_to_float(pixel.chan.b); /* b */ + dst[3] = 1; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16x16_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16x16_float pixel; + pixel.chan.r = util_float_to_half(src[0]); + pixel.chan.g = util_float_to_half(src[1]); + pixel.chan.b = util_float_to_half(src[2]); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16g16b16x16_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r16g16b16x16_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = util_half_to_float(pixel.chan.r); /* r */ + dst[1] = util_half_to_float(pixel.chan.g); /* g */ + dst[2] = util_half_to_float(pixel.chan.b); /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r16g16b16x16_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16x16_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = float_to_ubyte(util_half_to_float(pixel.chan.r)); /* r */ + dst[1] = float_to_ubyte(util_half_to_float(pixel.chan.g)); /* g */ + dst[2] = float_to_ubyte(util_half_to_float(pixel.chan.b)); /* b */ + dst[3] = 255; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16x16_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16x16_float pixel; + pixel.chan.r = util_float_to_half((float)(src[0] * (1.0f/0xff))); + pixel.chan.g = util_float_to_half((float)(src[1] * (1.0f/0xff))); + pixel.chan.b = util_float_to_half((float)(src[2] * (1.0f/0xff))); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16g16b16x16_uint { + uint64_t value; + struct { + uint16_t r; + uint16_t g; + uint16_t b; + uint16_t x; + } chan; +}; + +static INLINE void +util_format_r16g16b16x16_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16x16_uint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (unsigned)pixel.chan.r; /* r */ + dst[1] = (unsigned)pixel.chan.g; /* g */ + dst[2] = (unsigned)pixel.chan.b; /* b */ + dst[3] = 1; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16x16_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16x16_uint pixel; + pixel.chan.r = (uint16_t)MIN2(src[0], 65535); + pixel.chan.g = (uint16_t)MIN2(src[1], 65535); + pixel.chan.b = (uint16_t)MIN2(src[2], 65535); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16g16b16x16_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r16g16b16x16_uint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (unsigned)pixel.chan.r; /* r */ + dst[1] = (unsigned)pixel.chan.g; /* g */ + dst[2] = (unsigned)pixel.chan.b; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r16g16b16x16_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16x16_uint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (int)pixel.chan.r; /* r */ + dst[1] = (int)pixel.chan.g; /* g */ + dst[2] = (int)pixel.chan.b; /* b */ + dst[3] = 1; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16x16_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16x16_uint pixel; + pixel.chan.r = (uint16_t)CLAMP(src[0], 0, 65535); + pixel.chan.g = (uint16_t)CLAMP(src[1], 0, 65535); + pixel.chan.b = (uint16_t)CLAMP(src[2], 0, 65535); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16g16b16x16_sint { + uint64_t value; + struct { + int16_t r; + int16_t g; + int16_t b; + uint16_t x; + } chan; +}; + +static INLINE void +util_format_r16g16b16x16_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16x16_sint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (int)pixel.chan.r; /* r */ + dst[1] = (int)pixel.chan.g; /* g */ + dst[2] = (int)pixel.chan.b; /* b */ + dst[3] = 1; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16x16_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16x16_sint pixel; + pixel.chan.r = (int16_t)CLAMP(src[0], -32768, 32767); + pixel.chan.g = (int16_t)CLAMP(src[1], -32768, 32767); + pixel.chan.b = (int16_t)CLAMP(src[2], -32768, 32767); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16g16b16x16_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r16g16b16x16_sint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (int)pixel.chan.r; /* r */ + dst[1] = (int)pixel.chan.g; /* g */ + dst[2] = (int)pixel.chan.b; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r16g16b16x16_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16x16_sint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (unsigned)MAX2(pixel.chan.r, 0); /* r */ + dst[1] = (unsigned)MAX2(pixel.chan.g, 0); /* g */ + dst[2] = (unsigned)MAX2(pixel.chan.b, 0); /* b */ + dst[3] = 1; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16g16b16x16_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16g16b16x16_sint pixel; + pixel.chan.r = (int16_t)MIN2(src[0], 32767); + pixel.chan.g = (int16_t)MIN2(src[1], 32767); + pixel.chan.b = (int16_t)MIN2(src[2], 32767); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32g32b32x32_float { + struct { + float r; + float g; + float b; + uint32_t x; + } chan; +}; + +static INLINE void +util_format_r32g32b32x32_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32x32_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.r; /* r */ + dst[1] = pixel.chan.g; /* g */ + dst[2] = pixel.chan.b; /* b */ + dst[3] = 1; /* a */ + src += 16; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32x32_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32x32_float pixel; + pixel.chan.r = src[0]; + pixel.chan.g = src[1]; + pixel.chan.b = src[2]; + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 16; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32g32b32x32_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r32g32b32x32_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.r; /* r */ + dst[1] = pixel.chan.g; /* g */ + dst[2] = pixel.chan.b; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r32g32b32x32_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32x32_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = float_to_ubyte(pixel.chan.r); /* r */ + dst[1] = float_to_ubyte(pixel.chan.g); /* g */ + dst[2] = float_to_ubyte(pixel.chan.b); /* b */ + dst[3] = 255; /* a */ + src += 16; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32x32_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32x32_float pixel; + pixel.chan.r = ubyte_to_float(src[0]); + pixel.chan.g = ubyte_to_float(src[1]); + pixel.chan.b = ubyte_to_float(src[2]); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 16; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32g32b32x32_uint { + struct { + uint32_t r; + uint32_t g; + uint32_t b; + uint32_t x; + } chan; +}; + +static INLINE void +util_format_r32g32b32x32_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32x32_uint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.r; /* r */ + dst[1] = pixel.chan.g; /* g */ + dst[2] = pixel.chan.b; /* b */ + dst[3] = 1; /* a */ + src += 16; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32x32_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32x32_uint pixel; + pixel.chan.r = src[0]; + pixel.chan.g = src[1]; + pixel.chan.b = src[2]; + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 16; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32g32b32x32_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r32g32b32x32_uint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.r; /* r */ + dst[1] = pixel.chan.g; /* g */ + dst[2] = pixel.chan.b; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r32g32b32x32_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32x32_uint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (int)MIN2(pixel.chan.r, 2147483647); /* r */ + dst[1] = (int)MIN2(pixel.chan.g, 2147483647); /* g */ + dst[2] = (int)MIN2(pixel.chan.b, 2147483647); /* b */ + dst[3] = 1; /* a */ + src += 16; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32x32_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32x32_uint pixel; + pixel.chan.r = (uint32_t)MAX2(src[0], 0); + pixel.chan.g = (uint32_t)MAX2(src[1], 0); + pixel.chan.b = (uint32_t)MAX2(src[2], 0); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 16; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32g32b32x32_sint { + struct { + int32_t r; + int32_t g; + int32_t b; + uint32_t x; + } chan; +}; + +static INLINE void +util_format_r32g32b32x32_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32x32_sint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.r; /* r */ + dst[1] = pixel.chan.g; /* g */ + dst[2] = pixel.chan.b; /* b */ + dst[3] = 1; /* a */ + src += 16; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32x32_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32x32_sint pixel; + pixel.chan.r = src[0]; + pixel.chan.g = src[1]; + pixel.chan.b = src[2]; + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 16; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32g32b32x32_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r32g32b32x32_sint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.r; /* r */ + dst[1] = pixel.chan.g; /* g */ + dst[2] = pixel.chan.b; /* b */ + dst[3] = 1; /* a */ +} + +static INLINE void +util_format_r32g32b32x32_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32x32_sint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (unsigned)MAX2(pixel.chan.r, 0); /* r */ + dst[1] = (unsigned)MAX2(pixel.chan.g, 0); /* g */ + dst[2] = (unsigned)MAX2(pixel.chan.b, 0); /* b */ + dst[3] = 1; /* a */ + src += 16; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32g32b32x32_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32g32b32x32_sint pixel; + pixel.chan.r = (int32_t)MIN2(src[0], 2147483647); + pixel.chan.g = (int32_t)MIN2(src[1], 2147483647); + pixel.chan.b = (int32_t)MIN2(src[2], 2147483647); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 16; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8a8_snorm { + uint16_t value; + struct { + int8_t r; + int8_t a; + } chan; +}; + +static INLINE void +util_format_r8a8_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + int16_t r; + int16_t a; + r = ((int16_t)(value << 8) ) >> 8; + a = ((int16_t)(value) ) >> 8; + dst[0] = (float)(r * (1.0f/0x7f)); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (float)(a * (1.0f/0x7f)); /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8a8_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)(((int8_t)util_iround(CLAMP(src[0], -1, 1) * 0x7f)) & 0xff) ; + value |= (uint16_t)(((int8_t)util_iround(CLAMP(src[3], -1, 1) * 0x7f)) << 8) ; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8a8_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + int16_t r; + int16_t a; + r = ((int16_t)(value << 8) ) >> 8; + a = ((int16_t)(value) ) >> 8; + dst[0] = (float)(r * (1.0f/0x7f)); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (float)(a * (1.0f/0x7f)); /* a */ +} + +static INLINE void +util_format_r8a8_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + int16_t r; + int16_t a; + r = ((int16_t)(value << 8) ) >> 8; + a = ((int16_t)(value) ) >> 8; + dst[0] = (uint8_t)(((uint32_t)MAX2(r, 0)) * 0xff / 0x7f); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (uint8_t)(((uint32_t)MAX2(a, 0)) * 0xff / 0x7f); /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8a8_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)(((int8_t)(src[0] >> 1)) & 0xff) ; + value |= (uint16_t)(((int8_t)(src[3] >> 1)) << 8) ; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16a16_unorm { + uint32_t value; + struct { + uint16_t r; + uint16_t a; + } chan; +}; + +static INLINE void +util_format_r16a16_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t a; + r = (value) & 0xffff; + a = value >> 16; + dst[0] = (float)(r * (1.0f/0xffff)); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (float)(a * (1.0f/0xffff)); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16a16_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint16_t)util_iround(CLAMP(src[0], 0, 1) * 0xffff)) & 0xffff; + value |= ((uint16_t)util_iround(CLAMP(src[3], 0, 1) * 0xffff)) << 16; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16a16_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t a; + r = (value) & 0xffff; + a = value >> 16; + dst[0] = (float)(r * (1.0f/0xffff)); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (float)(a * (1.0f/0xffff)); /* a */ +} + +static INLINE void +util_format_r16a16_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t a; + r = (value) & 0xffff; + a = value >> 16; + dst[0] = (uint8_t)(r >> 8); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (uint8_t)(a >> 8); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16a16_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint16_t)(((uint32_t)src[0]) * 0xffff / 0xff)) & 0xffff; + value |= ((uint16_t)(((uint32_t)src[3]) * 0xffff / 0xff)) << 16; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16a16_snorm { + uint32_t value; + struct { + int16_t r; + int16_t a; + } chan; +}; + +static INLINE void +util_format_r16a16_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t a; + r = ((int32_t)(value << 16) ) >> 16; + a = ((int32_t)(value) ) >> 16; + dst[0] = (float)(r * (1.0f/0x7fff)); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (float)(a * (1.0f/0x7fff)); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16a16_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((int16_t)util_iround(CLAMP(src[0], -1, 1) * 0x7fff)) & 0xffff) ; + value |= (uint32_t)(((int16_t)util_iround(CLAMP(src[3], -1, 1) * 0x7fff)) << 16) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16a16_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t a; + r = ((int32_t)(value << 16) ) >> 16; + a = ((int32_t)(value) ) >> 16; + dst[0] = (float)(r * (1.0f/0x7fff)); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (float)(a * (1.0f/0x7fff)); /* a */ +} + +static INLINE void +util_format_r16a16_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t a; + r = ((int32_t)(value << 16) ) >> 16; + a = ((int32_t)(value) ) >> 16; + dst[0] = (uint8_t)(MAX2(r, 0) >> 7); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (uint8_t)(MAX2(a, 0) >> 7); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16a16_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((int16_t)(((uint32_t)src[0]) * 0x7fff / 0xff)) & 0xffff) ; + value |= (uint32_t)(((int16_t)(((uint32_t)src[3]) * 0x7fff / 0xff)) << 16) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16a16_float { + uint32_t value; + struct { + uint16_t r; + uint16_t a; + } chan; +}; + +static INLINE void +util_format_r16a16_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16a16_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = util_half_to_float(pixel.chan.r); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = util_half_to_float(pixel.chan.a); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16a16_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16a16_float pixel; + pixel.chan.r = util_float_to_half(src[0]); + pixel.chan.a = util_float_to_half(src[3]); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16a16_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r16a16_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = util_half_to_float(pixel.chan.r); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = util_half_to_float(pixel.chan.a); /* a */ +} + +static INLINE void +util_format_r16a16_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r16a16_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = float_to_ubyte(util_half_to_float(pixel.chan.r)); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = float_to_ubyte(util_half_to_float(pixel.chan.a)); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16a16_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r16a16_float pixel; + pixel.chan.r = util_float_to_half((float)(src[0] * (1.0f/0xff))); + pixel.chan.a = util_float_to_half((float)(src[3] * (1.0f/0xff))); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32a32_float { + uint64_t value; + struct { + float r; + float a; + } chan; +}; + +static INLINE void +util_format_r32a32_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32a32_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = pixel.chan.a; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32a32_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32a32_float pixel; + pixel.chan.r = src[0]; + pixel.chan.a = src[3]; + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32a32_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r32a32_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = pixel.chan.a; /* a */ +} + +static INLINE void +util_format_r32a32_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32a32_float pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = float_to_ubyte(pixel.chan.r); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = float_to_ubyte(pixel.chan.a); /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32a32_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32a32_float pixel; + pixel.chan.r = ubyte_to_float(src[0]); + pixel.chan.a = ubyte_to_float(src[3]); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8a8_uint { + uint16_t value; + struct { + uint8_t r; + uint8_t a; + } chan; +}; + +static INLINE void +util_format_r8a8_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t r; + uint16_t a; + r = (value) & 0xff; + a = value >> 8; + dst[0] = (unsigned)r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (unsigned)a; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8a8_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= ((uint8_t)MIN2(src[0], 255)) & 0xff; + value |= ((uint8_t)MIN2(src[3], 255)) << 8; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8a8_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + uint16_t r; + uint16_t a; + r = (value) & 0xff; + a = value >> 8; + dst[0] = (unsigned)r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (unsigned)a; /* a */ +} + +static INLINE void +util_format_r8a8_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + uint16_t r; + uint16_t a; + r = (value) & 0xff; + a = value >> 8; + dst[0] = (int)r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (int)a; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8a8_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= ((uint8_t)CLAMP(src[0], 0, 255)) & 0xff; + value |= ((uint8_t)CLAMP(src[3], 0, 255)) << 8; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r8a8_sint { + uint16_t value; + struct { + int8_t r; + int8_t a; + } chan; +}; + +static INLINE void +util_format_r8a8_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + int16_t r; + int16_t a; + r = ((int16_t)(value << 8) ) >> 8; + a = ((int16_t)(value) ) >> 8; + dst[0] = (int)r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (int)a; /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8a8_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)(((int8_t)CLAMP(src[0], -128, 127)) & 0xff) ; + value |= (uint16_t)(((int8_t)CLAMP(src[3], -128, 127)) << 8) ; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r8a8_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + int16_t r; + int16_t a; + r = ((int16_t)(value << 8) ) >> 8; + a = ((int16_t)(value) ) >> 8; + dst[0] = (int)r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (int)a; /* a */ +} + +static INLINE void +util_format_r8a8_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *(const uint16_t *)src; + int16_t r; + int16_t a; + r = ((int16_t)(value << 8) ) >> 8; + a = ((int16_t)(value) ) >> 8; + dst[0] = (unsigned)MAX2(r, 0); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (unsigned)MAX2(a, 0); /* a */ + src += 2; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r8a8_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + value |= (uint16_t)(((int8_t)MIN2(src[0], 127)) & 0xff) ; + value |= (uint16_t)(((int8_t)MIN2(src[3], 127)) << 8) ; + *(uint16_t *)dst = value; + src += 4; + dst += 2; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16a16_uint { + uint32_t value; + struct { + uint16_t r; + uint16_t a; + } chan; +}; + +static INLINE void +util_format_r16a16_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t a; + r = (value) & 0xffff; + a = value >> 16; + dst[0] = (unsigned)r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (unsigned)a; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16a16_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint16_t)MIN2(src[0], 65535)) & 0xffff; + value |= ((uint16_t)MIN2(src[3], 65535)) << 16; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16a16_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t a; + r = (value) & 0xffff; + a = value >> 16; + dst[0] = (unsigned)r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (unsigned)a; /* a */ +} + +static INLINE void +util_format_r16a16_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t a; + r = (value) & 0xffff; + a = value >> 16; + dst[0] = (int)r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (int)a; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16a16_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint16_t)CLAMP(src[0], 0, 65535)) & 0xffff; + value |= ((uint16_t)CLAMP(src[3], 0, 65535)) << 16; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r16a16_sint { + uint32_t value; + struct { + int16_t r; + int16_t a; + } chan; +}; + +static INLINE void +util_format_r16a16_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t a; + r = ((int32_t)(value << 16) ) >> 16; + a = ((int32_t)(value) ) >> 16; + dst[0] = (int)r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (int)a; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16a16_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((int16_t)CLAMP(src[0], -32768, 32767)) & 0xffff) ; + value |= (uint32_t)(((int16_t)CLAMP(src[3], -32768, 32767)) << 16) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r16a16_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t a; + r = ((int32_t)(value << 16) ) >> 16; + a = ((int32_t)(value) ) >> 16; + dst[0] = (int)r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (int)a; /* a */ +} + +static INLINE void +util_format_r16a16_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + int32_t r; + int32_t a; + r = ((int32_t)(value << 16) ) >> 16; + a = ((int32_t)(value) ) >> 16; + dst[0] = (unsigned)MAX2(r, 0); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (unsigned)MAX2(a, 0); /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r16a16_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= (uint32_t)(((int16_t)MIN2(src[0], 32767)) & 0xffff) ; + value |= (uint32_t)(((int16_t)MIN2(src[3], 32767)) << 16) ; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32a32_uint { + uint64_t value; + struct { + uint32_t r; + uint32_t a; + } chan; +}; + +static INLINE void +util_format_r32a32_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32a32_uint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = pixel.chan.a; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32a32_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32a32_uint pixel; + pixel.chan.r = src[0]; + pixel.chan.a = src[3]; + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32a32_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r32a32_uint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = pixel.chan.a; /* a */ +} + +static INLINE void +util_format_r32a32_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32a32_uint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (int)MIN2(pixel.chan.r, 2147483647); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (int)MIN2(pixel.chan.a, 2147483647); /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32a32_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32a32_uint pixel; + pixel.chan.r = (uint32_t)MAX2(src[0], 0); + pixel.chan.a = (uint32_t)MAX2(src[3], 0); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r32a32_sint { + uint64_t value; + struct { + int32_t r; + int32_t a; + } chan; +}; + +static INLINE void +util_format_r32a32_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32a32_sint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = pixel.chan.a; /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32a32_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32a32_sint pixel; + pixel.chan.r = src[0]; + pixel.chan.a = src[3]; + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r32a32_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j) +{ + union util_format_r32a32_sint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = pixel.chan.r; /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = pixel.chan.a; /* a */ +} + +static INLINE void +util_format_r32a32_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + union util_format_r32a32_sint pixel; + memcpy(&pixel, src, sizeof pixel); + dst[0] = (unsigned)MAX2(pixel.chan.r, 0); /* r */ + dst[1] = 0; /* g */ + dst[2] = 0; /* b */ + dst[3] = (unsigned)MAX2(pixel.chan.a, 0); /* a */ + src += 8; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r32a32_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + union util_format_r32a32_sint pixel; + pixel.chan.r = (int32_t)MIN2(src[0], 2147483647); + pixel.chan.a = (int32_t)MIN2(src[3], 2147483647); + memcpy(dst, &pixel, sizeof pixel); + src += 4; + dst += 8; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +union util_format_r10g10b10a2_uint { + uint32_t value; + struct { + unsigned r:10; + unsigned g:10; + unsigned b:10; + unsigned a:2; + } chan; +}; + +static INLINE void +util_format_r10g10b10a2_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + unsigned *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + uint32_t a; + r = (value) & 0x3ff; + g = (value >> 10) & 0x3ff; + b = (value >> 20) & 0x3ff; + a = value >> 30; + dst[0] = (unsigned)r; /* r */ + dst[1] = (unsigned)g; /* g */ + dst[2] = (unsigned)b; /* b */ + dst[3] = (unsigned)a; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r10g10b10a2_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const unsigned *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint32_t)MIN2(src[0], 1023)) & 0x3ff; + value |= (((uint32_t)MIN2(src[1], 1023)) & 0x3ff) << 10; + value |= (((uint32_t)MIN2(src[2], 1023)) & 0x3ff) << 20; + value |= ((uint32_t)MIN2(src[3], 3)) << 30; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +static INLINE void +util_format_r10g10b10a2_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + uint32_t a; + r = (value) & 0x3ff; + g = (value >> 10) & 0x3ff; + b = (value >> 20) & 0x3ff; + a = value >> 30; + dst[0] = (unsigned)r; /* r */ + dst[1] = (unsigned)g; /* g */ + dst[2] = (unsigned)b; /* b */ + dst[3] = (unsigned)a; /* a */ +} + +static INLINE void +util_format_r10g10b10a2_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + int *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; + uint32_t r; + uint32_t g; + uint32_t b; + uint32_t a; + r = (value) & 0x3ff; + g = (value >> 10) & 0x3ff; + b = (value >> 20) & 0x3ff; + a = value >> 30; + dst[0] = (int)r; /* r */ + dst[1] = (int)g; /* g */ + dst[2] = (int)b; /* b */ + dst[3] = (int)a; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +static INLINE void +util_format_r10g10b10a2_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const int *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = 0; + value |= ((uint32_t)CLAMP(src[0], 0, 1023)) & 0x3ff; + value |= (((uint32_t)CLAMP(src[1], 0, 1023)) & 0x3ff) << 10; + value |= (((uint32_t)CLAMP(src[2], 0, 1023)) & 0x3ff) << 20; + value |= ((uint32_t)CLAMP(src[3], 0, 3)) << 30; + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +const struct util_format_description +util_format_none_description = { + PIPE_FORMAT_NONE, + "PIPE_FORMAT_NONE", + "none", + {1, 1, 8}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 8, 0}, /* x = r */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_none_unpack_rgba_8unorm, + &util_format_none_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_none_unpack_rgba_float, + &util_format_none_pack_rgba_float, + &util_format_none_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_b8g8r8a8_unorm_description = { + PIPE_FORMAT_B8G8R8A8_UNORM, + "PIPE_FORMAT_B8G8R8A8_UNORM", + "b8g8r8a8_unorm", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = b */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 16}, /* z = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 24} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_Z, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_b8g8r8a8_unorm_unpack_rgba_8unorm, + &util_format_b8g8r8a8_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_b8g8r8a8_unorm_unpack_rgba_float, + &util_format_b8g8r8a8_unorm_pack_rgba_float, + &util_format_b8g8r8a8_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_b8g8r8x8_unorm_description = { + PIPE_FORMAT_B8G8R8X8_UNORM, + "PIPE_FORMAT_B8G8R8X8_UNORM", + "b8g8r8x8_unorm", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = b */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 16}, /* z = r */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 24} /* w = x */ + }, + { + UTIL_FORMAT_SWIZZLE_Z, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_b8g8r8x8_unorm_unpack_rgba_8unorm, + &util_format_b8g8r8x8_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_b8g8r8x8_unorm_unpack_rgba_float, + &util_format_b8g8r8x8_unorm_pack_rgba_float, + &util_format_b8g8r8x8_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_a8r8g8b8_unorm_description = { + PIPE_FORMAT_A8R8G8B8_UNORM, + "PIPE_FORMAT_A8R8G8B8_UNORM", + "a8r8g8b8_unorm", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = a */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 16}, /* z = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 24} /* w = b */ + }, + { + UTIL_FORMAT_SWIZZLE_Y, /* r */ + UTIL_FORMAT_SWIZZLE_Z, /* g */ + UTIL_FORMAT_SWIZZLE_W, /* b */ + UTIL_FORMAT_SWIZZLE_X /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_a8r8g8b8_unorm_unpack_rgba_8unorm, + &util_format_a8r8g8b8_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_a8r8g8b8_unorm_unpack_rgba_float, + &util_format_a8r8g8b8_unorm_pack_rgba_float, + &util_format_a8r8g8b8_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_x8r8g8b8_unorm_description = { + PIPE_FORMAT_X8R8G8B8_UNORM, + "PIPE_FORMAT_X8R8G8B8_UNORM", + "x8r8g8b8_unorm", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 0}, /* x = x */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 16}, /* z = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 24} /* w = b */ + }, + { + UTIL_FORMAT_SWIZZLE_Y, /* r */ + UTIL_FORMAT_SWIZZLE_Z, /* g */ + UTIL_FORMAT_SWIZZLE_W, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_x8r8g8b8_unorm_unpack_rgba_8unorm, + &util_format_x8r8g8b8_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_x8r8g8b8_unorm_unpack_rgba_float, + &util_format_x8r8g8b8_unorm_pack_rgba_float, + &util_format_x8r8g8b8_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_a8b8g8r8_unorm_description = { + PIPE_FORMAT_A8B8G8R8_UNORM, + "PIPE_FORMAT_A8B8G8R8_UNORM", + "a8b8g8r8_unorm", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = a */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = b */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 16}, /* z = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 24} /* w = r */ + }, + { + UTIL_FORMAT_SWIZZLE_W, /* r */ + UTIL_FORMAT_SWIZZLE_Z, /* g */ + UTIL_FORMAT_SWIZZLE_Y, /* b */ + UTIL_FORMAT_SWIZZLE_X /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_a8b8g8r8_unorm_unpack_rgba_8unorm, + &util_format_a8b8g8r8_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_a8b8g8r8_unorm_unpack_rgba_float, + &util_format_a8b8g8r8_unorm_pack_rgba_float, + &util_format_a8b8g8r8_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_x8b8g8r8_unorm_description = { + PIPE_FORMAT_X8B8G8R8_UNORM, + "PIPE_FORMAT_X8B8G8R8_UNORM", + "x8b8g8r8_unorm", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 0}, /* x = x */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = b */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 16}, /* z = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 24} /* w = r */ + }, + { + UTIL_FORMAT_SWIZZLE_W, /* r */ + UTIL_FORMAT_SWIZZLE_Z, /* g */ + UTIL_FORMAT_SWIZZLE_Y, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_x8b8g8r8_unorm_unpack_rgba_8unorm, + &util_format_x8b8g8r8_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_x8b8g8r8_unorm_unpack_rgba_float, + &util_format_x8b8g8r8_unorm_pack_rgba_float, + &util_format_x8b8g8r8_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8g8b8x8_unorm_description = { + PIPE_FORMAT_R8G8B8X8_UNORM, + "PIPE_FORMAT_R8G8B8X8_UNORM", + "r8g8b8x8_unorm", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 16}, /* z = b */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 24} /* w = x */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r8g8b8x8_unorm_unpack_rgba_8unorm, + &util_format_r8g8b8x8_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r8g8b8x8_unorm_unpack_rgba_float, + &util_format_r8g8b8x8_unorm_pack_rgba_float, + &util_format_r8g8b8x8_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_b5g5r5x1_unorm_description = { + PIPE_FORMAT_B5G5R5X1_UNORM, + "PIPE_FORMAT_B5G5R5X1_UNORM", + "b5g5r5x1_unorm", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + FALSE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 5, 0}, /* x = b */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 5, 5}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 5, 10}, /* z = r */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 1, 15} /* w = x */ + }, + { + UTIL_FORMAT_SWIZZLE_Z, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_b5g5r5x1_unorm_unpack_rgba_8unorm, + &util_format_b5g5r5x1_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_b5g5r5x1_unorm_unpack_rgba_float, + &util_format_b5g5r5x1_unorm_pack_rgba_float, + &util_format_b5g5r5x1_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_b5g5r5a1_unorm_description = { + PIPE_FORMAT_B5G5R5A1_UNORM, + "PIPE_FORMAT_B5G5R5A1_UNORM", + "b5g5r5a1_unorm", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + FALSE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 5, 0}, /* x = b */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 5, 5}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 5, 10}, /* z = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 1, 15} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_Z, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_b5g5r5a1_unorm_unpack_rgba_8unorm, + &util_format_b5g5r5a1_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_b5g5r5a1_unorm_unpack_rgba_float, + &util_format_b5g5r5a1_unorm_pack_rgba_float, + &util_format_b5g5r5a1_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_b4g4r4a4_unorm_description = { + PIPE_FORMAT_B4G4R4A4_UNORM, + "PIPE_FORMAT_B4G4R4A4_UNORM", + "b4g4r4a4_unorm", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + FALSE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 4, 0}, /* x = b */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 4, 4}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 4, 8}, /* z = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 4, 12} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_Z, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_b4g4r4a4_unorm_unpack_rgba_8unorm, + &util_format_b4g4r4a4_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_b4g4r4a4_unorm_unpack_rgba_float, + &util_format_b4g4r4a4_unorm_pack_rgba_float, + &util_format_b4g4r4a4_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_b4g4r4x4_unorm_description = { + PIPE_FORMAT_B4G4R4X4_UNORM, + "PIPE_FORMAT_B4G4R4X4_UNORM", + "b4g4r4x4_unorm", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + FALSE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 4, 0}, /* x = b */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 4, 4}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 4, 8}, /* z = r */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 4, 12} /* w = x */ + }, + { + UTIL_FORMAT_SWIZZLE_Z, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_b4g4r4x4_unorm_unpack_rgba_8unorm, + &util_format_b4g4r4x4_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_b4g4r4x4_unorm_unpack_rgba_float, + &util_format_b4g4r4x4_unorm_pack_rgba_float, + &util_format_b4g4r4x4_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_b5g6r5_unorm_description = { + PIPE_FORMAT_B5G6R5_UNORM, + "PIPE_FORMAT_B5G6R5_UNORM", + "b5g6r5_unorm", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 3, /* nr_channels */ + FALSE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 5, 0}, /* x = b */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 6, 5}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 5, 11}, /* z = r */ + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_Z, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_b5g6r5_unorm_unpack_rgba_8unorm, + &util_format_b5g6r5_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_b5g6r5_unorm_unpack_rgba_float, + &util_format_b5g6r5_unorm_pack_rgba_float, + &util_format_b5g6r5_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r10g10b10a2_unorm_description = { + PIPE_FORMAT_R10G10B10A2_UNORM, + "PIPE_FORMAT_R10G10B10A2_UNORM", + "r10g10b10a2_unorm", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + FALSE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 10, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 10, 10}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 10, 20}, /* z = b */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 2, 30} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r10g10b10a2_unorm_unpack_rgba_8unorm, + &util_format_r10g10b10a2_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r10g10b10a2_unorm_unpack_rgba_float, + &util_format_r10g10b10a2_unorm_pack_rgba_float, + &util_format_r10g10b10a2_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_b10g10r10a2_unorm_description = { + PIPE_FORMAT_B10G10R10A2_UNORM, + "PIPE_FORMAT_B10G10R10A2_UNORM", + "b10g10r10a2_unorm", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + FALSE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 10, 0}, /* x = b */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 10, 10}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 10, 20}, /* z = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 2, 30} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_Z, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_b10g10r10a2_unorm_unpack_rgba_8unorm, + &util_format_b10g10r10a2_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_b10g10r10a2_unorm_unpack_rgba_float, + &util_format_b10g10r10a2_unorm_pack_rgba_float, + &util_format_b10g10r10a2_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_b2g3r3_unorm_description = { + PIPE_FORMAT_B2G3R3_UNORM, + "PIPE_FORMAT_B2G3R3_UNORM", + "b2g3r3_unorm", + {1, 1, 8}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 3, /* nr_channels */ + FALSE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 2, 0}, /* x = b */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 3, 2}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 3, 5}, /* z = r */ + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_Z, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_b2g3r3_unorm_unpack_rgba_8unorm, + &util_format_b2g3r3_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_b2g3r3_unorm_unpack_rgba_float, + &util_format_b2g3r3_unorm_pack_rgba_float, + &util_format_b2g3r3_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_l8_unorm_description = { + PIPE_FORMAT_L8_UNORM, + "PIPE_FORMAT_L8_UNORM", + "l8_unorm", + {1, 1, 8}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = rgb */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_l8_unorm_unpack_rgba_8unorm, + &util_format_l8_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_l8_unorm_unpack_rgba_float, + &util_format_l8_unorm_pack_rgba_float, + &util_format_l8_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_a8_unorm_description = { + PIPE_FORMAT_A8_UNORM, + "PIPE_FORMAT_A8_UNORM", + "a8_unorm", + {1, 1, 8}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_0, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_X /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_a8_unorm_unpack_rgba_8unorm, + &util_format_a8_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_a8_unorm_unpack_rgba_float, + &util_format_a8_unorm_pack_rgba_float, + &util_format_a8_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_i8_unorm_description = { + PIPE_FORMAT_I8_UNORM, + "PIPE_FORMAT_I8_UNORM", + "i8_unorm", + {1, 1, 8}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = rgba */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_X /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_i8_unorm_unpack_rgba_8unorm, + &util_format_i8_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_i8_unorm_unpack_rgba_float, + &util_format_i8_unorm_pack_rgba_float, + &util_format_i8_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_l4a4_unorm_description = { + PIPE_FORMAT_L4A4_UNORM, + "PIPE_FORMAT_L4A4_UNORM", + "l4a4_unorm", + {1, 1, 8}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + FALSE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 4, 0}, /* x = rgb */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 4, 4}, /* y = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_Y /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_l4a4_unorm_unpack_rgba_8unorm, + &util_format_l4a4_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_l4a4_unorm_unpack_rgba_float, + &util_format_l4a4_unorm_pack_rgba_float, + &util_format_l4a4_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_l8a8_unorm_description = { + PIPE_FORMAT_L8A8_UNORM, + "PIPE_FORMAT_L8A8_UNORM", + "l8a8_unorm", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = rgb */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_Y /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_l8a8_unorm_unpack_rgba_8unorm, + &util_format_l8a8_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_l8a8_unorm_unpack_rgba_float, + &util_format_l8a8_unorm_pack_rgba_float, + &util_format_l8a8_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_l16_unorm_description = { + PIPE_FORMAT_L16_UNORM, + "PIPE_FORMAT_L16_UNORM", + "l16_unorm", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 0}, /* x = rgb */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_l16_unorm_unpack_rgba_8unorm, + &util_format_l16_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_l16_unorm_unpack_rgba_float, + &util_format_l16_unorm_pack_rgba_float, + &util_format_l16_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_a16_unorm_description = { + PIPE_FORMAT_A16_UNORM, + "PIPE_FORMAT_A16_UNORM", + "a16_unorm", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 0}, /* x = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_0, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_X /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_a16_unorm_unpack_rgba_8unorm, + &util_format_a16_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_a16_unorm_unpack_rgba_float, + &util_format_a16_unorm_pack_rgba_float, + &util_format_a16_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_i16_unorm_description = { + PIPE_FORMAT_I16_UNORM, + "PIPE_FORMAT_I16_UNORM", + "i16_unorm", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 0}, /* x = rgba */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_X /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_i16_unorm_unpack_rgba_8unorm, + &util_format_i16_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_i16_unorm_unpack_rgba_float, + &util_format_i16_unorm_pack_rgba_float, + &util_format_i16_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_l16a16_unorm_description = { + PIPE_FORMAT_L16A16_UNORM, + "PIPE_FORMAT_L16A16_UNORM", + "l16a16_unorm", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 0}, /* x = rgb */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 16}, /* y = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_Y /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_l16a16_unorm_unpack_rgba_8unorm, + &util_format_l16a16_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_l16a16_unorm_unpack_rgba_float, + &util_format_l16a16_unorm_pack_rgba_float, + &util_format_l16a16_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_a8_snorm_description = { + PIPE_FORMAT_A8_SNORM, + "PIPE_FORMAT_A8_SNORM", + "a8_snorm", + {1, 1, 8}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 0}, /* x = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_0, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_X /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_a8_snorm_unpack_rgba_8unorm, + &util_format_a8_snorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_a8_snorm_unpack_rgba_float, + &util_format_a8_snorm_pack_rgba_float, + &util_format_a8_snorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_l8_snorm_description = { + PIPE_FORMAT_L8_SNORM, + "PIPE_FORMAT_L8_SNORM", + "l8_snorm", + {1, 1, 8}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 0}, /* x = rgb */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_l8_snorm_unpack_rgba_8unorm, + &util_format_l8_snorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_l8_snorm_unpack_rgba_float, + &util_format_l8_snorm_pack_rgba_float, + &util_format_l8_snorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_l8a8_snorm_description = { + PIPE_FORMAT_L8A8_SNORM, + "PIPE_FORMAT_L8A8_SNORM", + "l8a8_snorm", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 0}, /* x = rgb */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 8}, /* y = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_Y /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_l8a8_snorm_unpack_rgba_8unorm, + &util_format_l8a8_snorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_l8a8_snorm_unpack_rgba_float, + &util_format_l8a8_snorm_pack_rgba_float, + &util_format_l8a8_snorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_i8_snorm_description = { + PIPE_FORMAT_I8_SNORM, + "PIPE_FORMAT_I8_SNORM", + "i8_snorm", + {1, 1, 8}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 0}, /* x = rgba */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_X /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_i8_snorm_unpack_rgba_8unorm, + &util_format_i8_snorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_i8_snorm_unpack_rgba_float, + &util_format_i8_snorm_pack_rgba_float, + &util_format_i8_snorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_a16_snorm_description = { + PIPE_FORMAT_A16_SNORM, + "PIPE_FORMAT_A16_SNORM", + "a16_snorm", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 0}, /* x = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_0, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_X /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_a16_snorm_unpack_rgba_8unorm, + &util_format_a16_snorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_a16_snorm_unpack_rgba_float, + &util_format_a16_snorm_pack_rgba_float, + &util_format_a16_snorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_l16_snorm_description = { + PIPE_FORMAT_L16_SNORM, + "PIPE_FORMAT_L16_SNORM", + "l16_snorm", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 0}, /* x = rgb */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_l16_snorm_unpack_rgba_8unorm, + &util_format_l16_snorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_l16_snorm_unpack_rgba_float, + &util_format_l16_snorm_pack_rgba_float, + &util_format_l16_snorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_l16a16_snorm_description = { + PIPE_FORMAT_L16A16_SNORM, + "PIPE_FORMAT_L16A16_SNORM", + "l16a16_snorm", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 0}, /* x = rgb */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 16}, /* y = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_Y /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_l16a16_snorm_unpack_rgba_8unorm, + &util_format_l16a16_snorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_l16a16_snorm_unpack_rgba_float, + &util_format_l16a16_snorm_pack_rgba_float, + &util_format_l16a16_snorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_i16_snorm_description = { + PIPE_FORMAT_I16_SNORM, + "PIPE_FORMAT_I16_SNORM", + "i16_snorm", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 0}, /* x = rgba */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_X /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_i16_snorm_unpack_rgba_8unorm, + &util_format_i16_snorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_i16_snorm_unpack_rgba_float, + &util_format_i16_snorm_pack_rgba_float, + &util_format_i16_snorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_a16_float_description = { + PIPE_FORMAT_A16_FLOAT, + "PIPE_FORMAT_A16_FLOAT", + "a16_float", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 0}, /* x = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_0, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_X /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_a16_float_unpack_rgba_8unorm, + &util_format_a16_float_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_a16_float_unpack_rgba_float, + &util_format_a16_float_pack_rgba_float, + &util_format_a16_float_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_l16_float_description = { + PIPE_FORMAT_L16_FLOAT, + "PIPE_FORMAT_L16_FLOAT", + "l16_float", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 0}, /* x = rgb */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_l16_float_unpack_rgba_8unorm, + &util_format_l16_float_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_l16_float_unpack_rgba_float, + &util_format_l16_float_pack_rgba_float, + &util_format_l16_float_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_l16a16_float_description = { + PIPE_FORMAT_L16A16_FLOAT, + "PIPE_FORMAT_L16A16_FLOAT", + "l16a16_float", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 0}, /* x = rgb */ + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 16}, /* y = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_Y /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_l16a16_float_unpack_rgba_8unorm, + &util_format_l16a16_float_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_l16a16_float_unpack_rgba_float, + &util_format_l16a16_float_pack_rgba_float, + &util_format_l16a16_float_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_i16_float_description = { + PIPE_FORMAT_I16_FLOAT, + "PIPE_FORMAT_I16_FLOAT", + "i16_float", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 0}, /* x = rgba */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_X /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_i16_float_unpack_rgba_8unorm, + &util_format_i16_float_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_i16_float_unpack_rgba_float, + &util_format_i16_float_pack_rgba_float, + &util_format_i16_float_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_a32_float_description = { + PIPE_FORMAT_A32_FLOAT, + "PIPE_FORMAT_A32_FLOAT", + "a32_float", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 0}, /* x = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_0, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_X /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_a32_float_unpack_rgba_8unorm, + &util_format_a32_float_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_a32_float_unpack_rgba_float, + &util_format_a32_float_pack_rgba_float, + &util_format_a32_float_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_l32_float_description = { + PIPE_FORMAT_L32_FLOAT, + "PIPE_FORMAT_L32_FLOAT", + "l32_float", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 0}, /* x = rgb */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_l32_float_unpack_rgba_8unorm, + &util_format_l32_float_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_l32_float_unpack_rgba_float, + &util_format_l32_float_pack_rgba_float, + &util_format_l32_float_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_l32a32_float_description = { + PIPE_FORMAT_L32A32_FLOAT, + "PIPE_FORMAT_L32A32_FLOAT", + "l32a32_float", + {1, 1, 64}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 0}, /* x = rgb */ + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 32}, /* y = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_Y /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_l32a32_float_unpack_rgba_8unorm, + &util_format_l32a32_float_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_l32a32_float_unpack_rgba_float, + &util_format_l32a32_float_pack_rgba_float, + &util_format_l32a32_float_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_i32_float_description = { + PIPE_FORMAT_I32_FLOAT, + "PIPE_FORMAT_I32_FLOAT", + "i32_float", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 0}, /* x = rgba */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_X /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_i32_float_unpack_rgba_8unorm, + &util_format_i32_float_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_i32_float_unpack_rgba_float, + &util_format_i32_float_pack_rgba_float, + &util_format_i32_float_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_l8_srgb_description = { + PIPE_FORMAT_L8_SRGB, + "PIPE_FORMAT_L8_SRGB", + "l8_srgb", + {1, 1, 8}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = rgb */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* sr */ + UTIL_FORMAT_SWIZZLE_X, /* sg */ + UTIL_FORMAT_SWIZZLE_X, /* sb */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_SRGB, + &util_format_l8_srgb_unpack_rgba_8unorm, + &util_format_l8_srgb_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_l8_srgb_unpack_rgba_float, + &util_format_l8_srgb_pack_rgba_float, + &util_format_l8_srgb_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_l8a8_srgb_description = { + PIPE_FORMAT_L8A8_SRGB, + "PIPE_FORMAT_L8A8_SRGB", + "l8a8_srgb", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = rgb */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* sr */ + UTIL_FORMAT_SWIZZLE_X, /* sg */ + UTIL_FORMAT_SWIZZLE_X, /* sb */ + UTIL_FORMAT_SWIZZLE_Y /* a */ + }, + UTIL_FORMAT_COLORSPACE_SRGB, + &util_format_l8a8_srgb_unpack_rgba_8unorm, + &util_format_l8a8_srgb_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_l8a8_srgb_unpack_rgba_float, + &util_format_l8a8_srgb_pack_rgba_float, + &util_format_l8a8_srgb_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8g8b8_srgb_description = { + PIPE_FORMAT_R8G8B8_SRGB, + "PIPE_FORMAT_R8G8B8_SRGB", + "r8g8b8_srgb", + {1, 1, 24}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 3, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 16}, /* z = b */ + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* sr */ + UTIL_FORMAT_SWIZZLE_Y, /* sg */ + UTIL_FORMAT_SWIZZLE_Z, /* sb */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_SRGB, + &util_format_r8g8b8_srgb_unpack_rgba_8unorm, + &util_format_r8g8b8_srgb_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r8g8b8_srgb_unpack_rgba_float, + &util_format_r8g8b8_srgb_pack_rgba_float, + &util_format_r8g8b8_srgb_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8g8b8a8_srgb_description = { + PIPE_FORMAT_R8G8B8A8_SRGB, + "PIPE_FORMAT_R8G8B8A8_SRGB", + "r8g8b8a8_srgb", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 16}, /* z = b */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 24} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* sr */ + UTIL_FORMAT_SWIZZLE_Y, /* sg */ + UTIL_FORMAT_SWIZZLE_Z, /* sb */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_SRGB, + &util_format_r8g8b8a8_srgb_unpack_rgba_8unorm, + &util_format_r8g8b8a8_srgb_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r8g8b8a8_srgb_unpack_rgba_float, + &util_format_r8g8b8a8_srgb_pack_rgba_float, + &util_format_r8g8b8a8_srgb_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_a8b8g8r8_srgb_description = { + PIPE_FORMAT_A8B8G8R8_SRGB, + "PIPE_FORMAT_A8B8G8R8_SRGB", + "a8b8g8r8_srgb", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = a */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = b */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 16}, /* z = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 24} /* w = r */ + }, + { + UTIL_FORMAT_SWIZZLE_W, /* sr */ + UTIL_FORMAT_SWIZZLE_Z, /* sg */ + UTIL_FORMAT_SWIZZLE_Y, /* sb */ + UTIL_FORMAT_SWIZZLE_X /* a */ + }, + UTIL_FORMAT_COLORSPACE_SRGB, + &util_format_a8b8g8r8_srgb_unpack_rgba_8unorm, + &util_format_a8b8g8r8_srgb_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_a8b8g8r8_srgb_unpack_rgba_float, + &util_format_a8b8g8r8_srgb_pack_rgba_float, + &util_format_a8b8g8r8_srgb_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_x8b8g8r8_srgb_description = { + PIPE_FORMAT_X8B8G8R8_SRGB, + "PIPE_FORMAT_X8B8G8R8_SRGB", + "x8b8g8r8_srgb", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 0}, /* x = x */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = b */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 16}, /* z = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 24} /* w = r */ + }, + { + UTIL_FORMAT_SWIZZLE_W, /* sr */ + UTIL_FORMAT_SWIZZLE_Z, /* sg */ + UTIL_FORMAT_SWIZZLE_Y, /* sb */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_SRGB, + &util_format_x8b8g8r8_srgb_unpack_rgba_8unorm, + &util_format_x8b8g8r8_srgb_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_x8b8g8r8_srgb_unpack_rgba_float, + &util_format_x8b8g8r8_srgb_pack_rgba_float, + &util_format_x8b8g8r8_srgb_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_b8g8r8a8_srgb_description = { + PIPE_FORMAT_B8G8R8A8_SRGB, + "PIPE_FORMAT_B8G8R8A8_SRGB", + "b8g8r8a8_srgb", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = b */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 16}, /* z = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 24} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_Z, /* sr */ + UTIL_FORMAT_SWIZZLE_Y, /* sg */ + UTIL_FORMAT_SWIZZLE_X, /* sb */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_SRGB, + &util_format_b8g8r8a8_srgb_unpack_rgba_8unorm, + &util_format_b8g8r8a8_srgb_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_b8g8r8a8_srgb_unpack_rgba_float, + &util_format_b8g8r8a8_srgb_pack_rgba_float, + &util_format_b8g8r8a8_srgb_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_b8g8r8x8_srgb_description = { + PIPE_FORMAT_B8G8R8X8_SRGB, + "PIPE_FORMAT_B8G8R8X8_SRGB", + "b8g8r8x8_srgb", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = b */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 16}, /* z = r */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 24} /* w = x */ + }, + { + UTIL_FORMAT_SWIZZLE_Z, /* sr */ + UTIL_FORMAT_SWIZZLE_Y, /* sg */ + UTIL_FORMAT_SWIZZLE_X, /* sb */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_SRGB, + &util_format_b8g8r8x8_srgb_unpack_rgba_8unorm, + &util_format_b8g8r8x8_srgb_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_b8g8r8x8_srgb_unpack_rgba_float, + &util_format_b8g8r8x8_srgb_pack_rgba_float, + &util_format_b8g8r8x8_srgb_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_a8r8g8b8_srgb_description = { + PIPE_FORMAT_A8R8G8B8_SRGB, + "PIPE_FORMAT_A8R8G8B8_SRGB", + "a8r8g8b8_srgb", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = a */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 16}, /* z = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 24} /* w = b */ + }, + { + UTIL_FORMAT_SWIZZLE_Y, /* sr */ + UTIL_FORMAT_SWIZZLE_Z, /* sg */ + UTIL_FORMAT_SWIZZLE_W, /* sb */ + UTIL_FORMAT_SWIZZLE_X /* a */ + }, + UTIL_FORMAT_COLORSPACE_SRGB, + &util_format_a8r8g8b8_srgb_unpack_rgba_8unorm, + &util_format_a8r8g8b8_srgb_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_a8r8g8b8_srgb_unpack_rgba_float, + &util_format_a8r8g8b8_srgb_pack_rgba_float, + &util_format_a8r8g8b8_srgb_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_x8r8g8b8_srgb_description = { + PIPE_FORMAT_X8R8G8B8_SRGB, + "PIPE_FORMAT_X8R8G8B8_SRGB", + "x8r8g8b8_srgb", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 0}, /* x = x */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 16}, /* z = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 24} /* w = b */ + }, + { + UTIL_FORMAT_SWIZZLE_Y, /* sr */ + UTIL_FORMAT_SWIZZLE_Z, /* sg */ + UTIL_FORMAT_SWIZZLE_W, /* sb */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_SRGB, + &util_format_x8r8g8b8_srgb_unpack_rgba_8unorm, + &util_format_x8r8g8b8_srgb_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_x8r8g8b8_srgb_unpack_rgba_float, + &util_format_x8r8g8b8_srgb_pack_rgba_float, + &util_format_x8r8g8b8_srgb_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8sg8sb8ux8u_norm_description = { + PIPE_FORMAT_R8SG8SB8UX8U_NORM, + "PIPE_FORMAT_R8SG8SB8UX8U_NORM", + "r8sg8sb8ux8u_norm", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + FALSE, /* is_array */ + TRUE, /* is_bitmask */ + TRUE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 8}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 16}, /* z = b */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 24} /* w = x */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r8sg8sb8ux8u_norm_unpack_rgba_8unorm, + &util_format_r8sg8sb8ux8u_norm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r8sg8sb8ux8u_norm_unpack_rgba_float, + &util_format_r8sg8sb8ux8u_norm_pack_rgba_float, + &util_format_r8sg8sb8ux8u_norm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r10sg10sb10sa2u_norm_description = { + PIPE_FORMAT_R10SG10SB10SA2U_NORM, + "PIPE_FORMAT_R10SG10SB10SA2U_NORM", + "r10sg10sb10sa2u_norm", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + FALSE, /* is_array */ + TRUE, /* is_bitmask */ + TRUE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 10, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 10, 10}, /* y = g */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 10, 20}, /* z = b */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 2, 30} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r10sg10sb10sa2u_norm_unpack_rgba_8unorm, + &util_format_r10sg10sb10sa2u_norm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r10sg10sb10sa2u_norm_unpack_rgba_float, + &util_format_r10sg10sb10sa2u_norm_pack_rgba_float, + &util_format_r10sg10sb10sa2u_norm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r5sg5sb6u_norm_description = { + PIPE_FORMAT_R5SG5SB6U_NORM, + "PIPE_FORMAT_R5SG5SB6U_NORM", + "r5sg5sb6u_norm", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 3, /* nr_channels */ + FALSE, /* is_array */ + TRUE, /* is_bitmask */ + TRUE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 5, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 5, 5}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 6, 10}, /* z = b */ + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r5sg5sb6u_norm_unpack_rgba_8unorm, + &util_format_r5sg5sb6u_norm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r5sg5sb6u_norm_unpack_rgba_float, + &util_format_r5sg5sb6u_norm_pack_rgba_float, + &util_format_r5sg5sb6u_norm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_s8_uint_description = { + PIPE_FORMAT_S8_UINT, + "PIPE_FORMAT_S8_UINT", + "s8_uint", + {1, 1, 8}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 0}, /* x = s */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_NONE, /* z */ + UTIL_FORMAT_SWIZZLE_X, /* s */ + UTIL_FORMAT_SWIZZLE_NONE, /* ignored */ + UTIL_FORMAT_SWIZZLE_NONE /* ignored */ + }, + UTIL_FORMAT_COLORSPACE_ZS, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + &util_format_s8_uint_unpack_s_8uint, + &util_format_s8_uint_pack_s_8uint, + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_z16_unorm_description = { + PIPE_FORMAT_Z16_UNORM, + "PIPE_FORMAT_Z16_UNORM", + "z16_unorm", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 0}, /* x = z */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* z */ + UTIL_FORMAT_SWIZZLE_NONE, /* s */ + UTIL_FORMAT_SWIZZLE_NONE, /* ignored */ + UTIL_FORMAT_SWIZZLE_NONE /* ignored */ + }, + UTIL_FORMAT_COLORSPACE_ZS, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + &util_format_z16_unorm_unpack_z_32unorm, + &util_format_z16_unorm_pack_z_32unorm, + &util_format_z16_unorm_unpack_z_float, + &util_format_z16_unorm_pack_z_float, + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_z32_unorm_description = { + PIPE_FORMAT_Z32_UNORM, + "PIPE_FORMAT_Z32_UNORM", + "z32_unorm", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 32, 0}, /* x = z */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* z */ + UTIL_FORMAT_SWIZZLE_NONE, /* s */ + UTIL_FORMAT_SWIZZLE_NONE, /* ignored */ + UTIL_FORMAT_SWIZZLE_NONE /* ignored */ + }, + UTIL_FORMAT_COLORSPACE_ZS, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + &util_format_z32_unorm_unpack_z_32unorm, + &util_format_z32_unorm_pack_z_32unorm, + &util_format_z32_unorm_unpack_z_float, + &util_format_z32_unorm_pack_z_float, + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_z32_float_description = { + PIPE_FORMAT_Z32_FLOAT, + "PIPE_FORMAT_Z32_FLOAT", + "z32_float", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 0}, /* x = z */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* z */ + UTIL_FORMAT_SWIZZLE_NONE, /* s */ + UTIL_FORMAT_SWIZZLE_NONE, /* ignored */ + UTIL_FORMAT_SWIZZLE_NONE /* ignored */ + }, + UTIL_FORMAT_COLORSPACE_ZS, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + &util_format_z32_float_unpack_z_32unorm, + &util_format_z32_float_pack_z_32unorm, + &util_format_z32_float_unpack_z_float, + &util_format_z32_float_pack_z_float, + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_z24_unorm_s8_uint_description = { + PIPE_FORMAT_Z24_UNORM_S8_UINT, + "PIPE_FORMAT_Z24_UNORM_S8_UINT", + "z24_unorm_s8_uint", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + FALSE, /* is_array */ + TRUE, /* is_bitmask */ + TRUE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 24, 0}, /* x = z */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 24}, /* y = s */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* z */ + UTIL_FORMAT_SWIZZLE_Y, /* s */ + UTIL_FORMAT_SWIZZLE_NONE, /* ignored */ + UTIL_FORMAT_SWIZZLE_NONE /* ignored */ + }, + UTIL_FORMAT_COLORSPACE_ZS, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + &util_format_z24_unorm_s8_uint_unpack_z_32unorm, + &util_format_z24_unorm_s8_uint_pack_z_32unorm, + &util_format_z24_unorm_s8_uint_unpack_z_float, + &util_format_z24_unorm_s8_uint_pack_z_float, + &util_format_z24_unorm_s8_uint_unpack_s_8uint, + &util_format_z24_unorm_s8_uint_pack_s_8uint, + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_s8_uint_z24_unorm_description = { + PIPE_FORMAT_S8_UINT_Z24_UNORM, + "PIPE_FORMAT_S8_UINT_Z24_UNORM", + "s8_uint_z24_unorm", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + FALSE, /* is_array */ + TRUE, /* is_bitmask */ + TRUE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 0}, /* x = s */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 24, 8}, /* y = z */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_Y, /* z */ + UTIL_FORMAT_SWIZZLE_X, /* s */ + UTIL_FORMAT_SWIZZLE_NONE, /* ignored */ + UTIL_FORMAT_SWIZZLE_NONE /* ignored */ + }, + UTIL_FORMAT_COLORSPACE_ZS, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + &util_format_s8_uint_z24_unorm_unpack_z_32unorm, + &util_format_s8_uint_z24_unorm_pack_z_32unorm, + &util_format_s8_uint_z24_unorm_unpack_z_float, + &util_format_s8_uint_z24_unorm_pack_z_float, + &util_format_s8_uint_z24_unorm_unpack_s_8uint, + &util_format_s8_uint_z24_unorm_pack_s_8uint, + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_x24s8_uint_description = { + PIPE_FORMAT_X24S8_UINT, + "PIPE_FORMAT_X24S8_UINT", + "x24s8_uint", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + FALSE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 24, 0}, /* x = x */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 24}, /* y = s */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_NONE, /* z */ + UTIL_FORMAT_SWIZZLE_Y, /* s */ + UTIL_FORMAT_SWIZZLE_NONE, /* ignored */ + UTIL_FORMAT_SWIZZLE_NONE /* ignored */ + }, + UTIL_FORMAT_COLORSPACE_ZS, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + &util_format_x24s8_uint_unpack_s_8uint, + &util_format_x24s8_uint_pack_s_8uint, + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_s8x24_uint_description = { + PIPE_FORMAT_S8X24_UINT, + "PIPE_FORMAT_S8X24_UINT", + "s8x24_uint", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + FALSE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 0}, /* x = s */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 24, 8}, /* y = x */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_NONE, /* z */ + UTIL_FORMAT_SWIZZLE_X, /* s */ + UTIL_FORMAT_SWIZZLE_NONE, /* ignored */ + UTIL_FORMAT_SWIZZLE_NONE /* ignored */ + }, + UTIL_FORMAT_COLORSPACE_ZS, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + &util_format_s8x24_uint_unpack_s_8uint, + &util_format_s8x24_uint_pack_s_8uint, + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_z24x8_unorm_description = { + PIPE_FORMAT_Z24X8_UNORM, + "PIPE_FORMAT_Z24X8_UNORM", + "z24x8_unorm", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + FALSE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 24, 0}, /* x = z */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 24}, /* y = x */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* z */ + UTIL_FORMAT_SWIZZLE_NONE, /* s */ + UTIL_FORMAT_SWIZZLE_NONE, /* ignored */ + UTIL_FORMAT_SWIZZLE_NONE /* ignored */ + }, + UTIL_FORMAT_COLORSPACE_ZS, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + &util_format_z24x8_unorm_unpack_z_32unorm, + &util_format_z24x8_unorm_pack_z_32unorm, + &util_format_z24x8_unorm_unpack_z_float, + &util_format_z24x8_unorm_pack_z_float, + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_x8z24_unorm_description = { + PIPE_FORMAT_X8Z24_UNORM, + "PIPE_FORMAT_X8Z24_UNORM", + "x8z24_unorm", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + FALSE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 0}, /* x = x */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 24, 8}, /* y = z */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_Y, /* z */ + UTIL_FORMAT_SWIZZLE_NONE, /* s */ + UTIL_FORMAT_SWIZZLE_NONE, /* ignored */ + UTIL_FORMAT_SWIZZLE_NONE /* ignored */ + }, + UTIL_FORMAT_COLORSPACE_ZS, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + &util_format_x8z24_unorm_unpack_z_32unorm, + &util_format_x8z24_unorm_pack_z_32unorm, + &util_format_x8z24_unorm_unpack_z_float, + &util_format_x8z24_unorm_pack_z_float, + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_z32_float_s8x24_uint_description = { + PIPE_FORMAT_Z32_FLOAT_S8X24_UINT, + "PIPE_FORMAT_Z32_FLOAT_S8X24_UINT", + "z32_float_s8x24_uint", + {1, 1, 64}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 3, /* nr_channels */ + FALSE, /* is_array */ + FALSE, /* is_bitmask */ + TRUE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 0}, /* x = z */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 32}, /* y = s */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 24, 40}, /* z = x */ + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* z */ + UTIL_FORMAT_SWIZZLE_Y, /* s */ + UTIL_FORMAT_SWIZZLE_NONE, /* ignored */ + UTIL_FORMAT_SWIZZLE_NONE /* ignored */ + }, + UTIL_FORMAT_COLORSPACE_ZS, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + &util_format_z32_float_s8x24_uint_unpack_z_32unorm, + &util_format_z32_float_s8x24_uint_pack_z_32unorm, + &util_format_z32_float_s8x24_uint_unpack_z_float, + &util_format_z32_float_s8x24_uint_pack_z_float, + &util_format_z32_float_s8x24_uint_unpack_s_8uint, + &util_format_z32_float_s8x24_uint_pack_s_8uint, + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_x32_s8x24_uint_description = { + PIPE_FORMAT_X32_S8X24_UINT, + "PIPE_FORMAT_X32_S8X24_UINT", + "x32_s8x24_uint", + {1, 1, 64}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 3, /* nr_channels */ + FALSE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 32, 0}, /* x = x */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 32}, /* y = s */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 24, 40}, /* z = x */ + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_NONE, /* z */ + UTIL_FORMAT_SWIZZLE_Y, /* s */ + UTIL_FORMAT_SWIZZLE_NONE, /* ignored */ + UTIL_FORMAT_SWIZZLE_NONE /* ignored */ + }, + UTIL_FORMAT_COLORSPACE_ZS, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + &util_format_x32_s8x24_uint_unpack_s_8uint, + &util_format_x32_s8x24_uint_pack_s_8uint, + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_uyvy_description = { + PIPE_FORMAT_UYVY, + "PIPE_FORMAT_UYVY", + "uyvy", + {2, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_SUBSAMPLED, + 1, /* nr_channels */ + FALSE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 32, 0}, /* x = x */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* y */ + UTIL_FORMAT_SWIZZLE_Y, /* u */ + UTIL_FORMAT_SWIZZLE_Z, /* v */ + UTIL_FORMAT_SWIZZLE_1 /* ignored */ + }, + UTIL_FORMAT_COLORSPACE_YUV, + &util_format_uyvy_unpack_rgba_8unorm, + &util_format_uyvy_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_uyvy_unpack_rgba_float, + &util_format_uyvy_pack_rgba_float, + &util_format_uyvy_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_yuyv_description = { + PIPE_FORMAT_YUYV, + "PIPE_FORMAT_YUYV", + "yuyv", + {2, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_SUBSAMPLED, + 1, /* nr_channels */ + FALSE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 32, 0}, /* x = x */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* y */ + UTIL_FORMAT_SWIZZLE_Y, /* u */ + UTIL_FORMAT_SWIZZLE_Z, /* v */ + UTIL_FORMAT_SWIZZLE_1 /* ignored */ + }, + UTIL_FORMAT_COLORSPACE_YUV, + &util_format_yuyv_unpack_rgba_8unorm, + &util_format_yuyv_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_yuyv_unpack_rgba_float, + &util_format_yuyv_pack_rgba_float, + &util_format_yuyv_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8g8_b8g8_unorm_description = { + PIPE_FORMAT_R8G8_B8G8_UNORM, + "PIPE_FORMAT_R8G8_B8G8_UNORM", + "r8g8_b8g8_unorm", + {2, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_SUBSAMPLED, + 1, /* nr_channels */ + FALSE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 32, 0}, /* x = x */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r8g8_b8g8_unorm_unpack_rgba_8unorm, + &util_format_r8g8_b8g8_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r8g8_b8g8_unorm_unpack_rgba_float, + &util_format_r8g8_b8g8_unorm_pack_rgba_float, + &util_format_r8g8_b8g8_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_g8r8_g8b8_unorm_description = { + PIPE_FORMAT_G8R8_G8B8_UNORM, + "PIPE_FORMAT_G8R8_G8B8_UNORM", + "g8r8_g8b8_unorm", + {2, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_SUBSAMPLED, + 1, /* nr_channels */ + FALSE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 32, 0}, /* x = x */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_g8r8_g8b8_unorm_unpack_rgba_8unorm, + &util_format_g8r8_g8b8_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_g8r8_g8b8_unorm_unpack_rgba_float, + &util_format_g8r8_g8b8_unorm_pack_rgba_float, + &util_format_g8r8_g8b8_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_g8r8_b8r8_unorm_description = { + PIPE_FORMAT_G8R8_B8R8_UNORM, + "PIPE_FORMAT_G8R8_B8R8_UNORM", + "g8r8_b8r8_unorm", + {2, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_SUBSAMPLED, + 1, /* nr_channels */ + FALSE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 32, 0}, /* x = x */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_Y, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_g8r8_b8r8_unorm_unpack_rgba_8unorm, + &util_format_g8r8_b8r8_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_g8r8_b8r8_unorm_unpack_rgba_float, + &util_format_g8r8_b8r8_unorm_pack_rgba_float, + &util_format_g8r8_b8r8_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8g8_r8b8_unorm_description = { + PIPE_FORMAT_R8G8_R8B8_UNORM, + "PIPE_FORMAT_R8G8_R8B8_UNORM", + "r8g8_r8b8_unorm", + {2, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_SUBSAMPLED, + 1, /* nr_channels */ + FALSE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 32, 0}, /* x = x */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_Y, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r8g8_r8b8_unorm_unpack_rgba_8unorm, + &util_format_r8g8_r8b8_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r8g8_r8b8_unorm_unpack_rgba_float, + &util_format_r8g8_r8b8_unorm_pack_rgba_float, + &util_format_r8g8_r8b8_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r11g11b10_float_description = { + PIPE_FORMAT_R11G11B10_FLOAT, + "PIPE_FORMAT_R11G11B10_FLOAT", + "r11g11b10_float", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_OTHER, + 1, /* nr_channels */ + FALSE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 32, 0}, /* x = x */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r11g11b10_float_unpack_rgba_8unorm, + &util_format_r11g11b10_float_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r11g11b10_float_unpack_rgba_float, + &util_format_r11g11b10_float_pack_rgba_float, + &util_format_r11g11b10_float_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r9g9b9e5_float_description = { + PIPE_FORMAT_R9G9B9E5_FLOAT, + "PIPE_FORMAT_R9G9B9E5_FLOAT", + "r9g9b9e5_float", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_OTHER, + 1, /* nr_channels */ + FALSE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 32, 0}, /* x = x */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r9g9b9e5_float_unpack_rgba_8unorm, + &util_format_r9g9b9e5_float_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r9g9b9e5_float_unpack_rgba_float, + &util_format_r9g9b9e5_float_pack_rgba_float, + &util_format_r9g9b9e5_float_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r1_unorm_description = { + PIPE_FORMAT_R1_UNORM, + "PIPE_FORMAT_R1_UNORM", + "r1_unorm", + {8, 1, 8}, /* block */ + UTIL_FORMAT_LAYOUT_OTHER, + 1, /* nr_channels */ + FALSE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 0}, /* x = x */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r1_unorm_unpack_rgba_8unorm, + &util_format_r1_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r1_unorm_unpack_rgba_float, + &util_format_r1_unorm_pack_rgba_float, + &util_format_r1_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8g8bx_snorm_description = { + PIPE_FORMAT_R8G8Bx_SNORM, + "PIPE_FORMAT_R8G8Bx_SNORM", + "r8g8bx_snorm", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_OTHER, + 2, /* nr_channels */ + FALSE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 0}, /* x = x */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 8}, /* y = y */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r8g8bx_snorm_unpack_rgba_8unorm, + &util_format_r8g8bx_snorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r8g8bx_snorm_unpack_rgba_float, + &util_format_r8g8bx_snorm_pack_rgba_float, + &util_format_r8g8bx_snorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_dxt1_rgb_description = { + PIPE_FORMAT_DXT1_RGB, + "PIPE_FORMAT_DXT1_RGB", + "dxt1_rgb", + {4, 4, 64}, /* block */ + UTIL_FORMAT_LAYOUT_S3TC, + 1, /* nr_channels */ + FALSE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 64, 0}, /* x = x */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_dxt1_rgb_unpack_rgba_8unorm, + &util_format_dxt1_rgb_pack_rgba_8unorm, + &util_format_dxt1_rgb_fetch_rgba_8unorm, + &util_format_dxt1_rgb_unpack_rgba_float, + &util_format_dxt1_rgb_pack_rgba_float, + &util_format_dxt1_rgb_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_dxt1_rgba_description = { + PIPE_FORMAT_DXT1_RGBA, + "PIPE_FORMAT_DXT1_RGBA", + "dxt1_rgba", + {4, 4, 64}, /* block */ + UTIL_FORMAT_LAYOUT_S3TC, + 1, /* nr_channels */ + FALSE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 64, 0}, /* x = x */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_dxt1_rgba_unpack_rgba_8unorm, + &util_format_dxt1_rgba_pack_rgba_8unorm, + &util_format_dxt1_rgba_fetch_rgba_8unorm, + &util_format_dxt1_rgba_unpack_rgba_float, + &util_format_dxt1_rgba_pack_rgba_float, + &util_format_dxt1_rgba_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_dxt3_rgba_description = { + PIPE_FORMAT_DXT3_RGBA, + "PIPE_FORMAT_DXT3_RGBA", + "dxt3_rgba", + {4, 4, 128}, /* block */ + UTIL_FORMAT_LAYOUT_S3TC, + 1, /* nr_channels */ + FALSE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 128, 0}, /* x = x */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_dxt3_rgba_unpack_rgba_8unorm, + &util_format_dxt3_rgba_pack_rgba_8unorm, + &util_format_dxt3_rgba_fetch_rgba_8unorm, + &util_format_dxt3_rgba_unpack_rgba_float, + &util_format_dxt3_rgba_pack_rgba_float, + &util_format_dxt3_rgba_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_dxt5_rgba_description = { + PIPE_FORMAT_DXT5_RGBA, + "PIPE_FORMAT_DXT5_RGBA", + "dxt5_rgba", + {4, 4, 128}, /* block */ + UTIL_FORMAT_LAYOUT_S3TC, + 1, /* nr_channels */ + FALSE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 128, 0}, /* x = x */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_dxt5_rgba_unpack_rgba_8unorm, + &util_format_dxt5_rgba_pack_rgba_8unorm, + &util_format_dxt5_rgba_fetch_rgba_8unorm, + &util_format_dxt5_rgba_unpack_rgba_float, + &util_format_dxt5_rgba_pack_rgba_float, + &util_format_dxt5_rgba_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_dxt1_srgb_description = { + PIPE_FORMAT_DXT1_SRGB, + "PIPE_FORMAT_DXT1_SRGB", + "dxt1_srgb", + {4, 4, 64}, /* block */ + UTIL_FORMAT_LAYOUT_S3TC, + 1, /* nr_channels */ + FALSE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 64, 0}, /* x = x */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* sr */ + UTIL_FORMAT_SWIZZLE_Y, /* sg */ + UTIL_FORMAT_SWIZZLE_Z, /* sb */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_SRGB, + &util_format_dxt1_srgb_unpack_rgba_8unorm, + &util_format_dxt1_srgb_pack_rgba_8unorm, + &util_format_dxt1_srgb_fetch_rgba_8unorm, + &util_format_dxt1_srgb_unpack_rgba_float, + &util_format_dxt1_srgb_pack_rgba_float, + &util_format_dxt1_srgb_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_dxt1_srgba_description = { + PIPE_FORMAT_DXT1_SRGBA, + "PIPE_FORMAT_DXT1_SRGBA", + "dxt1_srgba", + {4, 4, 64}, /* block */ + UTIL_FORMAT_LAYOUT_S3TC, + 1, /* nr_channels */ + FALSE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 64, 0}, /* x = x */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* sr */ + UTIL_FORMAT_SWIZZLE_Y, /* sg */ + UTIL_FORMAT_SWIZZLE_Z, /* sb */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_SRGB, + &util_format_dxt1_srgba_unpack_rgba_8unorm, + &util_format_dxt1_srgba_pack_rgba_8unorm, + &util_format_dxt1_srgba_fetch_rgba_8unorm, + &util_format_dxt1_srgba_unpack_rgba_float, + &util_format_dxt1_srgba_pack_rgba_float, + &util_format_dxt1_srgba_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_dxt3_srgba_description = { + PIPE_FORMAT_DXT3_SRGBA, + "PIPE_FORMAT_DXT3_SRGBA", + "dxt3_srgba", + {4, 4, 128}, /* block */ + UTIL_FORMAT_LAYOUT_S3TC, + 1, /* nr_channels */ + FALSE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 128, 0}, /* x = x */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* sr */ + UTIL_FORMAT_SWIZZLE_Y, /* sg */ + UTIL_FORMAT_SWIZZLE_Z, /* sb */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_SRGB, + &util_format_dxt3_srgba_unpack_rgba_8unorm, + &util_format_dxt3_srgba_pack_rgba_8unorm, + &util_format_dxt3_srgba_fetch_rgba_8unorm, + &util_format_dxt3_srgba_unpack_rgba_float, + &util_format_dxt3_srgba_pack_rgba_float, + &util_format_dxt3_srgba_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_dxt5_srgba_description = { + PIPE_FORMAT_DXT5_SRGBA, + "PIPE_FORMAT_DXT5_SRGBA", + "dxt5_srgba", + {4, 4, 128}, /* block */ + UTIL_FORMAT_LAYOUT_S3TC, + 1, /* nr_channels */ + FALSE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 128, 0}, /* x = x */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* sr */ + UTIL_FORMAT_SWIZZLE_Y, /* sg */ + UTIL_FORMAT_SWIZZLE_Z, /* sb */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_SRGB, + &util_format_dxt5_srgba_unpack_rgba_8unorm, + &util_format_dxt5_srgba_pack_rgba_8unorm, + &util_format_dxt5_srgba_fetch_rgba_8unorm, + &util_format_dxt5_srgba_unpack_rgba_float, + &util_format_dxt5_srgba_pack_rgba_float, + &util_format_dxt5_srgba_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_rgtc1_unorm_description = { + PIPE_FORMAT_RGTC1_UNORM, + "PIPE_FORMAT_RGTC1_UNORM", + "rgtc1_unorm", + {4, 4, 64}, /* block */ + UTIL_FORMAT_LAYOUT_RGTC, + 1, /* nr_channels */ + FALSE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 64, 0}, /* x = x */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_rgtc1_unorm_unpack_rgba_8unorm, + &util_format_rgtc1_unorm_pack_rgba_8unorm, + &util_format_rgtc1_unorm_fetch_rgba_8unorm, + &util_format_rgtc1_unorm_unpack_rgba_float, + &util_format_rgtc1_unorm_pack_rgba_float, + &util_format_rgtc1_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_rgtc1_snorm_description = { + PIPE_FORMAT_RGTC1_SNORM, + "PIPE_FORMAT_RGTC1_SNORM", + "rgtc1_snorm", + {4, 4, 64}, /* block */ + UTIL_FORMAT_LAYOUT_RGTC, + 1, /* nr_channels */ + FALSE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 64, 0}, /* x = x */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_rgtc1_snorm_unpack_rgba_8unorm, + &util_format_rgtc1_snorm_pack_rgba_8unorm, + &util_format_rgtc1_snorm_fetch_rgba_8unorm, + &util_format_rgtc1_snorm_unpack_rgba_float, + &util_format_rgtc1_snorm_pack_rgba_float, + &util_format_rgtc1_snorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_rgtc2_unorm_description = { + PIPE_FORMAT_RGTC2_UNORM, + "PIPE_FORMAT_RGTC2_UNORM", + "rgtc2_unorm", + {4, 4, 128}, /* block */ + UTIL_FORMAT_LAYOUT_RGTC, + 1, /* nr_channels */ + FALSE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 128, 0}, /* x = x */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_rgtc2_unorm_unpack_rgba_8unorm, + &util_format_rgtc2_unorm_pack_rgba_8unorm, + &util_format_rgtc2_unorm_fetch_rgba_8unorm, + &util_format_rgtc2_unorm_unpack_rgba_float, + &util_format_rgtc2_unorm_pack_rgba_float, + &util_format_rgtc2_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_rgtc2_snorm_description = { + PIPE_FORMAT_RGTC2_SNORM, + "PIPE_FORMAT_RGTC2_SNORM", + "rgtc2_snorm", + {4, 4, 128}, /* block */ + UTIL_FORMAT_LAYOUT_RGTC, + 1, /* nr_channels */ + FALSE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 128, 0}, /* x = x */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_rgtc2_snorm_unpack_rgba_8unorm, + &util_format_rgtc2_snorm_pack_rgba_8unorm, + &util_format_rgtc2_snorm_fetch_rgba_8unorm, + &util_format_rgtc2_snorm_unpack_rgba_float, + &util_format_rgtc2_snorm_pack_rgba_float, + &util_format_rgtc2_snorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_latc1_unorm_description = { + PIPE_FORMAT_LATC1_UNORM, + "PIPE_FORMAT_LATC1_UNORM", + "latc1_unorm", + {4, 4, 64}, /* block */ + UTIL_FORMAT_LAYOUT_RGTC, + 1, /* nr_channels */ + FALSE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 64, 0}, /* x = x */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_latc1_unorm_unpack_rgba_8unorm, + &util_format_latc1_unorm_pack_rgba_8unorm, + &util_format_latc1_unorm_fetch_rgba_8unorm, + &util_format_latc1_unorm_unpack_rgba_float, + &util_format_latc1_unorm_pack_rgba_float, + &util_format_latc1_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_latc1_snorm_description = { + PIPE_FORMAT_LATC1_SNORM, + "PIPE_FORMAT_LATC1_SNORM", + "latc1_snorm", + {4, 4, 64}, /* block */ + UTIL_FORMAT_LAYOUT_RGTC, + 1, /* nr_channels */ + FALSE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 64, 0}, /* x = x */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_latc1_snorm_unpack_rgba_8unorm, + &util_format_latc1_snorm_pack_rgba_8unorm, + &util_format_latc1_snorm_fetch_rgba_8unorm, + &util_format_latc1_snorm_unpack_rgba_float, + &util_format_latc1_snorm_pack_rgba_float, + &util_format_latc1_snorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_latc2_unorm_description = { + PIPE_FORMAT_LATC2_UNORM, + "PIPE_FORMAT_LATC2_UNORM", + "latc2_unorm", + {4, 4, 128}, /* block */ + UTIL_FORMAT_LAYOUT_RGTC, + 1, /* nr_channels */ + FALSE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 128, 0}, /* x = x */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_Y /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_latc2_unorm_unpack_rgba_8unorm, + &util_format_latc2_unorm_pack_rgba_8unorm, + &util_format_latc2_unorm_fetch_rgba_8unorm, + &util_format_latc2_unorm_unpack_rgba_float, + &util_format_latc2_unorm_pack_rgba_float, + &util_format_latc2_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_latc2_snorm_description = { + PIPE_FORMAT_LATC2_SNORM, + "PIPE_FORMAT_LATC2_SNORM", + "latc2_snorm", + {4, 4, 128}, /* block */ + UTIL_FORMAT_LAYOUT_RGTC, + 1, /* nr_channels */ + FALSE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 128, 0}, /* x = x */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_Y /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_latc2_snorm_unpack_rgba_8unorm, + &util_format_latc2_snorm_pack_rgba_8unorm, + &util_format_latc2_snorm_fetch_rgba_8unorm, + &util_format_latc2_snorm_unpack_rgba_float, + &util_format_latc2_snorm_pack_rgba_float, + &util_format_latc2_snorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_etc1_rgb8_description = { + PIPE_FORMAT_ETC1_RGB8, + "PIPE_FORMAT_ETC1_RGB8", + "etc1_rgb8", + {4, 4, 64}, /* block */ + UTIL_FORMAT_LAYOUT_ETC, + 1, /* nr_channels */ + FALSE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 64, 0}, /* x = x */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_etc1_rgb8_unpack_rgba_8unorm, + &util_format_etc1_rgb8_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_etc1_rgb8_unpack_rgba_float, + &util_format_etc1_rgb8_pack_rgba_float, + &util_format_etc1_rgb8_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r64_float_description = { + PIPE_FORMAT_R64_FLOAT, + "PIPE_FORMAT_R64_FLOAT", + "r64_float", + {1, 1, 64}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 64, 0}, /* x = r */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r64_float_unpack_rgba_8unorm, + &util_format_r64_float_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r64_float_unpack_rgba_float, + &util_format_r64_float_pack_rgba_float, + &util_format_r64_float_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r64g64_float_description = { + PIPE_FORMAT_R64G64_FLOAT, + "PIPE_FORMAT_R64G64_FLOAT", + "r64g64_float", + {1, 1, 128}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 64, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 64, 64}, /* y = g */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r64g64_float_unpack_rgba_8unorm, + &util_format_r64g64_float_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r64g64_float_unpack_rgba_float, + &util_format_r64g64_float_pack_rgba_float, + &util_format_r64g64_float_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r64g64b64_float_description = { + PIPE_FORMAT_R64G64B64_FLOAT, + "PIPE_FORMAT_R64G64B64_FLOAT", + "r64g64b64_float", + {1, 1, 192}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 3, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 64, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 64, 64}, /* y = g */ + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 64, 128}, /* z = b */ + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r64g64b64_float_unpack_rgba_8unorm, + &util_format_r64g64b64_float_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r64g64b64_float_unpack_rgba_float, + &util_format_r64g64b64_float_pack_rgba_float, + &util_format_r64g64b64_float_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r64g64b64a64_float_description = { + PIPE_FORMAT_R64G64B64A64_FLOAT, + "PIPE_FORMAT_R64G64B64A64_FLOAT", + "r64g64b64a64_float", + {1, 1, 256}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 64, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 64, 64}, /* y = g */ + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 64, 128}, /* z = b */ + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 64, 192} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r64g64b64a64_float_unpack_rgba_8unorm, + &util_format_r64g64b64a64_float_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r64g64b64a64_float_unpack_rgba_float, + &util_format_r64g64b64a64_float_pack_rgba_float, + &util_format_r64g64b64a64_float_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32_float_description = { + PIPE_FORMAT_R32_FLOAT, + "PIPE_FORMAT_R32_FLOAT", + "r32_float", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 0}, /* x = r */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r32_float_unpack_rgba_8unorm, + &util_format_r32_float_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r32_float_unpack_rgba_float, + &util_format_r32_float_pack_rgba_float, + &util_format_r32_float_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32g32_float_description = { + PIPE_FORMAT_R32G32_FLOAT, + "PIPE_FORMAT_R32G32_FLOAT", + "r32g32_float", + {1, 1, 64}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 32}, /* y = g */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r32g32_float_unpack_rgba_8unorm, + &util_format_r32g32_float_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r32g32_float_unpack_rgba_float, + &util_format_r32g32_float_pack_rgba_float, + &util_format_r32g32_float_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32g32b32_float_description = { + PIPE_FORMAT_R32G32B32_FLOAT, + "PIPE_FORMAT_R32G32B32_FLOAT", + "r32g32b32_float", + {1, 1, 96}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 3, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 32}, /* y = g */ + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 64}, /* z = b */ + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r32g32b32_float_unpack_rgba_8unorm, + &util_format_r32g32b32_float_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r32g32b32_float_unpack_rgba_float, + &util_format_r32g32b32_float_pack_rgba_float, + &util_format_r32g32b32_float_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32g32b32a32_float_description = { + PIPE_FORMAT_R32G32B32A32_FLOAT, + "PIPE_FORMAT_R32G32B32A32_FLOAT", + "r32g32b32a32_float", + {1, 1, 128}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 32}, /* y = g */ + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 64}, /* z = b */ + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 96} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r32g32b32a32_float_unpack_rgba_8unorm, + &util_format_r32g32b32a32_float_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r32g32b32a32_float_unpack_rgba_float, + &util_format_r32g32b32a32_float_pack_rgba_float, + &util_format_r32g32b32a32_float_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32_unorm_description = { + PIPE_FORMAT_R32_UNORM, + "PIPE_FORMAT_R32_UNORM", + "r32_unorm", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 32, 0}, /* x = r */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r32_unorm_unpack_rgba_8unorm, + &util_format_r32_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r32_unorm_unpack_rgba_float, + &util_format_r32_unorm_pack_rgba_float, + &util_format_r32_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32g32_unorm_description = { + PIPE_FORMAT_R32G32_UNORM, + "PIPE_FORMAT_R32G32_UNORM", + "r32g32_unorm", + {1, 1, 64}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 32, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 32, 32}, /* y = g */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r32g32_unorm_unpack_rgba_8unorm, + &util_format_r32g32_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r32g32_unorm_unpack_rgba_float, + &util_format_r32g32_unorm_pack_rgba_float, + &util_format_r32g32_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32g32b32_unorm_description = { + PIPE_FORMAT_R32G32B32_UNORM, + "PIPE_FORMAT_R32G32B32_UNORM", + "r32g32b32_unorm", + {1, 1, 96}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 3, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 32, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 32, 32}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 32, 64}, /* z = b */ + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r32g32b32_unorm_unpack_rgba_8unorm, + &util_format_r32g32b32_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r32g32b32_unorm_unpack_rgba_float, + &util_format_r32g32b32_unorm_pack_rgba_float, + &util_format_r32g32b32_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32g32b32a32_unorm_description = { + PIPE_FORMAT_R32G32B32A32_UNORM, + "PIPE_FORMAT_R32G32B32A32_UNORM", + "r32g32b32a32_unorm", + {1, 1, 128}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 32, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 32, 32}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 32, 64}, /* z = b */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 32, 96} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r32g32b32a32_unorm_unpack_rgba_8unorm, + &util_format_r32g32b32a32_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r32g32b32a32_unorm_unpack_rgba_float, + &util_format_r32g32b32a32_unorm_pack_rgba_float, + &util_format_r32g32b32a32_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32_uscaled_description = { + PIPE_FORMAT_R32_USCALED, + "PIPE_FORMAT_R32_USCALED", + "r32_uscaled", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 32, 0}, /* x = r */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r32_uscaled_unpack_rgba_8unorm, + &util_format_r32_uscaled_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r32_uscaled_unpack_rgba_float, + &util_format_r32_uscaled_pack_rgba_float, + &util_format_r32_uscaled_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32g32_uscaled_description = { + PIPE_FORMAT_R32G32_USCALED, + "PIPE_FORMAT_R32G32_USCALED", + "r32g32_uscaled", + {1, 1, 64}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 32, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 32, 32}, /* y = g */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r32g32_uscaled_unpack_rgba_8unorm, + &util_format_r32g32_uscaled_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r32g32_uscaled_unpack_rgba_float, + &util_format_r32g32_uscaled_pack_rgba_float, + &util_format_r32g32_uscaled_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32g32b32_uscaled_description = { + PIPE_FORMAT_R32G32B32_USCALED, + "PIPE_FORMAT_R32G32B32_USCALED", + "r32g32b32_uscaled", + {1, 1, 96}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 3, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 32, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 32, 32}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 32, 64}, /* z = b */ + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r32g32b32_uscaled_unpack_rgba_8unorm, + &util_format_r32g32b32_uscaled_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r32g32b32_uscaled_unpack_rgba_float, + &util_format_r32g32b32_uscaled_pack_rgba_float, + &util_format_r32g32b32_uscaled_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32g32b32a32_uscaled_description = { + PIPE_FORMAT_R32G32B32A32_USCALED, + "PIPE_FORMAT_R32G32B32A32_USCALED", + "r32g32b32a32_uscaled", + {1, 1, 128}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 32, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 32, 32}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 32, 64}, /* z = b */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 32, 96} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r32g32b32a32_uscaled_unpack_rgba_8unorm, + &util_format_r32g32b32a32_uscaled_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r32g32b32a32_uscaled_unpack_rgba_float, + &util_format_r32g32b32a32_uscaled_pack_rgba_float, + &util_format_r32g32b32a32_uscaled_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32_snorm_description = { + PIPE_FORMAT_R32_SNORM, + "PIPE_FORMAT_R32_SNORM", + "r32_snorm", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 32, 0}, /* x = r */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r32_snorm_unpack_rgba_8unorm, + &util_format_r32_snorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r32_snorm_unpack_rgba_float, + &util_format_r32_snorm_pack_rgba_float, + &util_format_r32_snorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32g32_snorm_description = { + PIPE_FORMAT_R32G32_SNORM, + "PIPE_FORMAT_R32G32_SNORM", + "r32g32_snorm", + {1, 1, 64}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 32, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 32, 32}, /* y = g */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r32g32_snorm_unpack_rgba_8unorm, + &util_format_r32g32_snorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r32g32_snorm_unpack_rgba_float, + &util_format_r32g32_snorm_pack_rgba_float, + &util_format_r32g32_snorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32g32b32_snorm_description = { + PIPE_FORMAT_R32G32B32_SNORM, + "PIPE_FORMAT_R32G32B32_SNORM", + "r32g32b32_snorm", + {1, 1, 96}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 3, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 32, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 32, 32}, /* y = g */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 32, 64}, /* z = b */ + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r32g32b32_snorm_unpack_rgba_8unorm, + &util_format_r32g32b32_snorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r32g32b32_snorm_unpack_rgba_float, + &util_format_r32g32b32_snorm_pack_rgba_float, + &util_format_r32g32b32_snorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32g32b32a32_snorm_description = { + PIPE_FORMAT_R32G32B32A32_SNORM, + "PIPE_FORMAT_R32G32B32A32_SNORM", + "r32g32b32a32_snorm", + {1, 1, 128}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 32, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 32, 32}, /* y = g */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 32, 64}, /* z = b */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 32, 96} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r32g32b32a32_snorm_unpack_rgba_8unorm, + &util_format_r32g32b32a32_snorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r32g32b32a32_snorm_unpack_rgba_float, + &util_format_r32g32b32a32_snorm_pack_rgba_float, + &util_format_r32g32b32a32_snorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32_sscaled_description = { + PIPE_FORMAT_R32_SSCALED, + "PIPE_FORMAT_R32_SSCALED", + "r32_sscaled", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 32, 0}, /* x = r */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r32_sscaled_unpack_rgba_8unorm, + &util_format_r32_sscaled_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r32_sscaled_unpack_rgba_float, + &util_format_r32_sscaled_pack_rgba_float, + &util_format_r32_sscaled_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32g32_sscaled_description = { + PIPE_FORMAT_R32G32_SSCALED, + "PIPE_FORMAT_R32G32_SSCALED", + "r32g32_sscaled", + {1, 1, 64}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 32, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 32, 32}, /* y = g */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r32g32_sscaled_unpack_rgba_8unorm, + &util_format_r32g32_sscaled_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r32g32_sscaled_unpack_rgba_float, + &util_format_r32g32_sscaled_pack_rgba_float, + &util_format_r32g32_sscaled_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32g32b32_sscaled_description = { + PIPE_FORMAT_R32G32B32_SSCALED, + "PIPE_FORMAT_R32G32B32_SSCALED", + "r32g32b32_sscaled", + {1, 1, 96}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 3, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 32, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 32, 32}, /* y = g */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 32, 64}, /* z = b */ + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r32g32b32_sscaled_unpack_rgba_8unorm, + &util_format_r32g32b32_sscaled_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r32g32b32_sscaled_unpack_rgba_float, + &util_format_r32g32b32_sscaled_pack_rgba_float, + &util_format_r32g32b32_sscaled_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32g32b32a32_sscaled_description = { + PIPE_FORMAT_R32G32B32A32_SSCALED, + "PIPE_FORMAT_R32G32B32A32_SSCALED", + "r32g32b32a32_sscaled", + {1, 1, 128}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 32, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 32, 32}, /* y = g */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 32, 64}, /* z = b */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 32, 96} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r32g32b32a32_sscaled_unpack_rgba_8unorm, + &util_format_r32g32b32a32_sscaled_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r32g32b32a32_sscaled_unpack_rgba_float, + &util_format_r32g32b32a32_sscaled_pack_rgba_float, + &util_format_r32g32b32a32_sscaled_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16_float_description = { + PIPE_FORMAT_R16_FLOAT, + "PIPE_FORMAT_R16_FLOAT", + "r16_float", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 0}, /* x = r */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r16_float_unpack_rgba_8unorm, + &util_format_r16_float_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r16_float_unpack_rgba_float, + &util_format_r16_float_pack_rgba_float, + &util_format_r16_float_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16g16_float_description = { + PIPE_FORMAT_R16G16_FLOAT, + "PIPE_FORMAT_R16G16_FLOAT", + "r16g16_float", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 16}, /* y = g */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r16g16_float_unpack_rgba_8unorm, + &util_format_r16g16_float_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r16g16_float_unpack_rgba_float, + &util_format_r16g16_float_pack_rgba_float, + &util_format_r16g16_float_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16g16b16_float_description = { + PIPE_FORMAT_R16G16B16_FLOAT, + "PIPE_FORMAT_R16G16B16_FLOAT", + "r16g16b16_float", + {1, 1, 48}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 3, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 16}, /* y = g */ + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 32}, /* z = b */ + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r16g16b16_float_unpack_rgba_8unorm, + &util_format_r16g16b16_float_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r16g16b16_float_unpack_rgba_float, + &util_format_r16g16b16_float_pack_rgba_float, + &util_format_r16g16b16_float_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16g16b16a16_float_description = { + PIPE_FORMAT_R16G16B16A16_FLOAT, + "PIPE_FORMAT_R16G16B16A16_FLOAT", + "r16g16b16a16_float", + {1, 1, 64}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 16}, /* y = g */ + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 32}, /* z = b */ + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 48} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r16g16b16a16_float_unpack_rgba_8unorm, + &util_format_r16g16b16a16_float_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r16g16b16a16_float_unpack_rgba_float, + &util_format_r16g16b16a16_float_pack_rgba_float, + &util_format_r16g16b16a16_float_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16_unorm_description = { + PIPE_FORMAT_R16_UNORM, + "PIPE_FORMAT_R16_UNORM", + "r16_unorm", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 0}, /* x = r */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r16_unorm_unpack_rgba_8unorm, + &util_format_r16_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r16_unorm_unpack_rgba_float, + &util_format_r16_unorm_pack_rgba_float, + &util_format_r16_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16g16_unorm_description = { + PIPE_FORMAT_R16G16_UNORM, + "PIPE_FORMAT_R16G16_UNORM", + "r16g16_unorm", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 16}, /* y = g */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r16g16_unorm_unpack_rgba_8unorm, + &util_format_r16g16_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r16g16_unorm_unpack_rgba_float, + &util_format_r16g16_unorm_pack_rgba_float, + &util_format_r16g16_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16g16b16_unorm_description = { + PIPE_FORMAT_R16G16B16_UNORM, + "PIPE_FORMAT_R16G16B16_UNORM", + "r16g16b16_unorm", + {1, 1, 48}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 3, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 16}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 32}, /* z = b */ + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r16g16b16_unorm_unpack_rgba_8unorm, + &util_format_r16g16b16_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r16g16b16_unorm_unpack_rgba_float, + &util_format_r16g16b16_unorm_pack_rgba_float, + &util_format_r16g16b16_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16g16b16a16_unorm_description = { + PIPE_FORMAT_R16G16B16A16_UNORM, + "PIPE_FORMAT_R16G16B16A16_UNORM", + "r16g16b16a16_unorm", + {1, 1, 64}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 16}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 32}, /* z = b */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 48} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r16g16b16a16_unorm_unpack_rgba_8unorm, + &util_format_r16g16b16a16_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r16g16b16a16_unorm_unpack_rgba_float, + &util_format_r16g16b16a16_unorm_pack_rgba_float, + &util_format_r16g16b16a16_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16_uscaled_description = { + PIPE_FORMAT_R16_USCALED, + "PIPE_FORMAT_R16_USCALED", + "r16_uscaled", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 16, 0}, /* x = r */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r16_uscaled_unpack_rgba_8unorm, + &util_format_r16_uscaled_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r16_uscaled_unpack_rgba_float, + &util_format_r16_uscaled_pack_rgba_float, + &util_format_r16_uscaled_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16g16_uscaled_description = { + PIPE_FORMAT_R16G16_USCALED, + "PIPE_FORMAT_R16G16_USCALED", + "r16g16_uscaled", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 16, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 16, 16}, /* y = g */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r16g16_uscaled_unpack_rgba_8unorm, + &util_format_r16g16_uscaled_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r16g16_uscaled_unpack_rgba_float, + &util_format_r16g16_uscaled_pack_rgba_float, + &util_format_r16g16_uscaled_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16g16b16_uscaled_description = { + PIPE_FORMAT_R16G16B16_USCALED, + "PIPE_FORMAT_R16G16B16_USCALED", + "r16g16b16_uscaled", + {1, 1, 48}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 3, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 16, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 16, 16}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 16, 32}, /* z = b */ + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r16g16b16_uscaled_unpack_rgba_8unorm, + &util_format_r16g16b16_uscaled_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r16g16b16_uscaled_unpack_rgba_float, + &util_format_r16g16b16_uscaled_pack_rgba_float, + &util_format_r16g16b16_uscaled_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16g16b16a16_uscaled_description = { + PIPE_FORMAT_R16G16B16A16_USCALED, + "PIPE_FORMAT_R16G16B16A16_USCALED", + "r16g16b16a16_uscaled", + {1, 1, 64}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 16, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 16, 16}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 16, 32}, /* z = b */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 16, 48} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r16g16b16a16_uscaled_unpack_rgba_8unorm, + &util_format_r16g16b16a16_uscaled_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r16g16b16a16_uscaled_unpack_rgba_float, + &util_format_r16g16b16a16_uscaled_pack_rgba_float, + &util_format_r16g16b16a16_uscaled_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16_snorm_description = { + PIPE_FORMAT_R16_SNORM, + "PIPE_FORMAT_R16_SNORM", + "r16_snorm", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 0}, /* x = r */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r16_snorm_unpack_rgba_8unorm, + &util_format_r16_snorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r16_snorm_unpack_rgba_float, + &util_format_r16_snorm_pack_rgba_float, + &util_format_r16_snorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16g16_snorm_description = { + PIPE_FORMAT_R16G16_SNORM, + "PIPE_FORMAT_R16G16_SNORM", + "r16g16_snorm", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 16}, /* y = g */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r16g16_snorm_unpack_rgba_8unorm, + &util_format_r16g16_snorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r16g16_snorm_unpack_rgba_float, + &util_format_r16g16_snorm_pack_rgba_float, + &util_format_r16g16_snorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16g16b16_snorm_description = { + PIPE_FORMAT_R16G16B16_SNORM, + "PIPE_FORMAT_R16G16B16_SNORM", + "r16g16b16_snorm", + {1, 1, 48}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 3, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 16}, /* y = g */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 32}, /* z = b */ + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r16g16b16_snorm_unpack_rgba_8unorm, + &util_format_r16g16b16_snorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r16g16b16_snorm_unpack_rgba_float, + &util_format_r16g16b16_snorm_pack_rgba_float, + &util_format_r16g16b16_snorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16g16b16a16_snorm_description = { + PIPE_FORMAT_R16G16B16A16_SNORM, + "PIPE_FORMAT_R16G16B16A16_SNORM", + "r16g16b16a16_snorm", + {1, 1, 64}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 16}, /* y = g */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 32}, /* z = b */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 48} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r16g16b16a16_snorm_unpack_rgba_8unorm, + &util_format_r16g16b16a16_snorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r16g16b16a16_snorm_unpack_rgba_float, + &util_format_r16g16b16a16_snorm_pack_rgba_float, + &util_format_r16g16b16a16_snorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16_sscaled_description = { + PIPE_FORMAT_R16_SSCALED, + "PIPE_FORMAT_R16_SSCALED", + "r16_sscaled", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 16, 0}, /* x = r */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r16_sscaled_unpack_rgba_8unorm, + &util_format_r16_sscaled_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r16_sscaled_unpack_rgba_float, + &util_format_r16_sscaled_pack_rgba_float, + &util_format_r16_sscaled_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16g16_sscaled_description = { + PIPE_FORMAT_R16G16_SSCALED, + "PIPE_FORMAT_R16G16_SSCALED", + "r16g16_sscaled", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 16, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 16, 16}, /* y = g */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r16g16_sscaled_unpack_rgba_8unorm, + &util_format_r16g16_sscaled_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r16g16_sscaled_unpack_rgba_float, + &util_format_r16g16_sscaled_pack_rgba_float, + &util_format_r16g16_sscaled_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16g16b16_sscaled_description = { + PIPE_FORMAT_R16G16B16_SSCALED, + "PIPE_FORMAT_R16G16B16_SSCALED", + "r16g16b16_sscaled", + {1, 1, 48}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 3, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 16, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 16, 16}, /* y = g */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 16, 32}, /* z = b */ + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r16g16b16_sscaled_unpack_rgba_8unorm, + &util_format_r16g16b16_sscaled_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r16g16b16_sscaled_unpack_rgba_float, + &util_format_r16g16b16_sscaled_pack_rgba_float, + &util_format_r16g16b16_sscaled_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16g16b16a16_sscaled_description = { + PIPE_FORMAT_R16G16B16A16_SSCALED, + "PIPE_FORMAT_R16G16B16A16_SSCALED", + "r16g16b16a16_sscaled", + {1, 1, 64}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 16, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 16, 16}, /* y = g */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 16, 32}, /* z = b */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 16, 48} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r16g16b16a16_sscaled_unpack_rgba_8unorm, + &util_format_r16g16b16a16_sscaled_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r16g16b16a16_sscaled_unpack_rgba_float, + &util_format_r16g16b16a16_sscaled_pack_rgba_float, + &util_format_r16g16b16a16_sscaled_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8_unorm_description = { + PIPE_FORMAT_R8_UNORM, + "PIPE_FORMAT_R8_UNORM", + "r8_unorm", + {1, 1, 8}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = r */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r8_unorm_unpack_rgba_8unorm, + &util_format_r8_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r8_unorm_unpack_rgba_float, + &util_format_r8_unorm_pack_rgba_float, + &util_format_r8_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8g8_unorm_description = { + PIPE_FORMAT_R8G8_UNORM, + "PIPE_FORMAT_R8G8_UNORM", + "r8g8_unorm", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = g */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r8g8_unorm_unpack_rgba_8unorm, + &util_format_r8g8_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r8g8_unorm_unpack_rgba_float, + &util_format_r8g8_unorm_pack_rgba_float, + &util_format_r8g8_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8g8b8_unorm_description = { + PIPE_FORMAT_R8G8B8_UNORM, + "PIPE_FORMAT_R8G8B8_UNORM", + "r8g8b8_unorm", + {1, 1, 24}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 3, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 16}, /* z = b */ + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r8g8b8_unorm_unpack_rgba_8unorm, + &util_format_r8g8b8_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r8g8b8_unorm_unpack_rgba_float, + &util_format_r8g8b8_unorm_pack_rgba_float, + &util_format_r8g8b8_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8g8b8a8_unorm_description = { + PIPE_FORMAT_R8G8B8A8_UNORM, + "PIPE_FORMAT_R8G8B8A8_UNORM", + "r8g8b8a8_unorm", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 16}, /* z = b */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 24} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r8g8b8a8_unorm_unpack_rgba_8unorm, + &util_format_r8g8b8a8_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r8g8b8a8_unorm_unpack_rgba_float, + &util_format_r8g8b8a8_unorm_pack_rgba_float, + &util_format_r8g8b8a8_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8_uscaled_description = { + PIPE_FORMAT_R8_USCALED, + "PIPE_FORMAT_R8_USCALED", + "r8_uscaled", + {1, 1, 8}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 8, 0}, /* x = r */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r8_uscaled_unpack_rgba_8unorm, + &util_format_r8_uscaled_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r8_uscaled_unpack_rgba_float, + &util_format_r8_uscaled_pack_rgba_float, + &util_format_r8_uscaled_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8g8_uscaled_description = { + PIPE_FORMAT_R8G8_USCALED, + "PIPE_FORMAT_R8G8_USCALED", + "r8g8_uscaled", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 8, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 8, 8}, /* y = g */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r8g8_uscaled_unpack_rgba_8unorm, + &util_format_r8g8_uscaled_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r8g8_uscaled_unpack_rgba_float, + &util_format_r8g8_uscaled_pack_rgba_float, + &util_format_r8g8_uscaled_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8g8b8_uscaled_description = { + PIPE_FORMAT_R8G8B8_USCALED, + "PIPE_FORMAT_R8G8B8_USCALED", + "r8g8b8_uscaled", + {1, 1, 24}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 3, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 8, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 8, 8}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 8, 16}, /* z = b */ + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r8g8b8_uscaled_unpack_rgba_8unorm, + &util_format_r8g8b8_uscaled_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r8g8b8_uscaled_unpack_rgba_float, + &util_format_r8g8b8_uscaled_pack_rgba_float, + &util_format_r8g8b8_uscaled_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8g8b8a8_uscaled_description = { + PIPE_FORMAT_R8G8B8A8_USCALED, + "PIPE_FORMAT_R8G8B8A8_USCALED", + "r8g8b8a8_uscaled", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 8, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 8, 8}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 8, 16}, /* z = b */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 8, 24} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r8g8b8a8_uscaled_unpack_rgba_8unorm, + &util_format_r8g8b8a8_uscaled_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r8g8b8a8_uscaled_unpack_rgba_float, + &util_format_r8g8b8a8_uscaled_pack_rgba_float, + &util_format_r8g8b8a8_uscaled_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8_snorm_description = { + PIPE_FORMAT_R8_SNORM, + "PIPE_FORMAT_R8_SNORM", + "r8_snorm", + {1, 1, 8}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 0}, /* x = r */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r8_snorm_unpack_rgba_8unorm, + &util_format_r8_snorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r8_snorm_unpack_rgba_float, + &util_format_r8_snorm_pack_rgba_float, + &util_format_r8_snorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8g8_snorm_description = { + PIPE_FORMAT_R8G8_SNORM, + "PIPE_FORMAT_R8G8_SNORM", + "r8g8_snorm", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 8}, /* y = g */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r8g8_snorm_unpack_rgba_8unorm, + &util_format_r8g8_snorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r8g8_snorm_unpack_rgba_float, + &util_format_r8g8_snorm_pack_rgba_float, + &util_format_r8g8_snorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8g8b8_snorm_description = { + PIPE_FORMAT_R8G8B8_SNORM, + "PIPE_FORMAT_R8G8B8_SNORM", + "r8g8b8_snorm", + {1, 1, 24}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 3, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 8}, /* y = g */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 16}, /* z = b */ + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r8g8b8_snorm_unpack_rgba_8unorm, + &util_format_r8g8b8_snorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r8g8b8_snorm_unpack_rgba_float, + &util_format_r8g8b8_snorm_pack_rgba_float, + &util_format_r8g8b8_snorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8g8b8a8_snorm_description = { + PIPE_FORMAT_R8G8B8A8_SNORM, + "PIPE_FORMAT_R8G8B8A8_SNORM", + "r8g8b8a8_snorm", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 8}, /* y = g */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 16}, /* z = b */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 24} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r8g8b8a8_snorm_unpack_rgba_8unorm, + &util_format_r8g8b8a8_snorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r8g8b8a8_snorm_unpack_rgba_float, + &util_format_r8g8b8a8_snorm_pack_rgba_float, + &util_format_r8g8b8a8_snorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8_sscaled_description = { + PIPE_FORMAT_R8_SSCALED, + "PIPE_FORMAT_R8_SSCALED", + "r8_sscaled", + {1, 1, 8}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 8, 0}, /* x = r */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r8_sscaled_unpack_rgba_8unorm, + &util_format_r8_sscaled_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r8_sscaled_unpack_rgba_float, + &util_format_r8_sscaled_pack_rgba_float, + &util_format_r8_sscaled_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8g8_sscaled_description = { + PIPE_FORMAT_R8G8_SSCALED, + "PIPE_FORMAT_R8G8_SSCALED", + "r8g8_sscaled", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 8, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 8, 8}, /* y = g */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r8g8_sscaled_unpack_rgba_8unorm, + &util_format_r8g8_sscaled_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r8g8_sscaled_unpack_rgba_float, + &util_format_r8g8_sscaled_pack_rgba_float, + &util_format_r8g8_sscaled_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8g8b8_sscaled_description = { + PIPE_FORMAT_R8G8B8_SSCALED, + "PIPE_FORMAT_R8G8B8_SSCALED", + "r8g8b8_sscaled", + {1, 1, 24}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 3, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 8, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 8, 8}, /* y = g */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 8, 16}, /* z = b */ + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r8g8b8_sscaled_unpack_rgba_8unorm, + &util_format_r8g8b8_sscaled_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r8g8b8_sscaled_unpack_rgba_float, + &util_format_r8g8b8_sscaled_pack_rgba_float, + &util_format_r8g8b8_sscaled_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8g8b8a8_sscaled_description = { + PIPE_FORMAT_R8G8B8A8_SSCALED, + "PIPE_FORMAT_R8G8B8A8_SSCALED", + "r8g8b8a8_sscaled", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 8, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 8, 8}, /* y = g */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 8, 16}, /* z = b */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 8, 24} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r8g8b8a8_sscaled_unpack_rgba_8unorm, + &util_format_r8g8b8a8_sscaled_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r8g8b8a8_sscaled_unpack_rgba_float, + &util_format_r8g8b8a8_sscaled_pack_rgba_float, + &util_format_r8g8b8a8_sscaled_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32_fixed_description = { + PIPE_FORMAT_R32_FIXED, + "PIPE_FORMAT_R32_FIXED", + "r32_fixed", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_FIXED, FALSE, FALSE, 32, 0}, /* x = r */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r32_fixed_unpack_rgba_8unorm, + &util_format_r32_fixed_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r32_fixed_unpack_rgba_float, + &util_format_r32_fixed_pack_rgba_float, + &util_format_r32_fixed_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32g32_fixed_description = { + PIPE_FORMAT_R32G32_FIXED, + "PIPE_FORMAT_R32G32_FIXED", + "r32g32_fixed", + {1, 1, 64}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_FIXED, FALSE, FALSE, 32, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_FIXED, FALSE, FALSE, 32, 32}, /* y = g */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r32g32_fixed_unpack_rgba_8unorm, + &util_format_r32g32_fixed_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r32g32_fixed_unpack_rgba_float, + &util_format_r32g32_fixed_pack_rgba_float, + &util_format_r32g32_fixed_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32g32b32_fixed_description = { + PIPE_FORMAT_R32G32B32_FIXED, + "PIPE_FORMAT_R32G32B32_FIXED", + "r32g32b32_fixed", + {1, 1, 96}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 3, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_FIXED, FALSE, FALSE, 32, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_FIXED, FALSE, FALSE, 32, 32}, /* y = g */ + {UTIL_FORMAT_TYPE_FIXED, FALSE, FALSE, 32, 64}, /* z = b */ + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r32g32b32_fixed_unpack_rgba_8unorm, + &util_format_r32g32b32_fixed_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r32g32b32_fixed_unpack_rgba_float, + &util_format_r32g32b32_fixed_pack_rgba_float, + &util_format_r32g32b32_fixed_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32g32b32a32_fixed_description = { + PIPE_FORMAT_R32G32B32A32_FIXED, + "PIPE_FORMAT_R32G32B32A32_FIXED", + "r32g32b32a32_fixed", + {1, 1, 128}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_FIXED, FALSE, FALSE, 32, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_FIXED, FALSE, FALSE, 32, 32}, /* y = g */ + {UTIL_FORMAT_TYPE_FIXED, FALSE, FALSE, 32, 64}, /* z = b */ + {UTIL_FORMAT_TYPE_FIXED, FALSE, FALSE, 32, 96} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r32g32b32a32_fixed_unpack_rgba_8unorm, + &util_format_r32g32b32a32_fixed_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r32g32b32a32_fixed_unpack_rgba_float, + &util_format_r32g32b32a32_fixed_pack_rgba_float, + &util_format_r32g32b32a32_fixed_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r10g10b10x2_uscaled_description = { + PIPE_FORMAT_R10G10B10X2_USCALED, + "PIPE_FORMAT_R10G10B10X2_USCALED", + "r10g10b10x2_uscaled", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + FALSE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 10, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 10, 10}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 10, 20}, /* z = b */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 2, 30} /* w = x */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r10g10b10x2_uscaled_unpack_rgba_8unorm, + &util_format_r10g10b10x2_uscaled_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r10g10b10x2_uscaled_unpack_rgba_float, + &util_format_r10g10b10x2_uscaled_pack_rgba_float, + &util_format_r10g10b10x2_uscaled_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r10g10b10x2_snorm_description = { + PIPE_FORMAT_R10G10B10X2_SNORM, + "PIPE_FORMAT_R10G10B10X2_SNORM", + "r10g10b10x2_snorm", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + FALSE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 10, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 10, 10}, /* y = g */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 10, 20}, /* z = b */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 2, 30} /* w = x */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r10g10b10x2_snorm_unpack_rgba_8unorm, + &util_format_r10g10b10x2_snorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r10g10b10x2_snorm_unpack_rgba_float, + &util_format_r10g10b10x2_snorm_pack_rgba_float, + &util_format_r10g10b10x2_snorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_yv12_description = { + PIPE_FORMAT_YV12, + "PIPE_FORMAT_YV12", + "yv12", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_OTHER, + 4, /* nr_channels */ + FALSE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 0}, /* x = x */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 8}, /* y = y */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 16}, /* z = z */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 24} /* w = w */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* y */ + UTIL_FORMAT_SWIZZLE_Y, /* u */ + UTIL_FORMAT_SWIZZLE_Z, /* v */ + UTIL_FORMAT_SWIZZLE_W /* ignored */ + }, + UTIL_FORMAT_COLORSPACE_YUV, + &util_format_yv12_unpack_rgba_8unorm, + &util_format_yv12_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_yv12_unpack_rgba_float, + &util_format_yv12_pack_rgba_float, + &util_format_yv12_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_yv16_description = { + PIPE_FORMAT_YV16, + "PIPE_FORMAT_YV16", + "yv16", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_OTHER, + 4, /* nr_channels */ + FALSE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 0}, /* x = x */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 8}, /* y = y */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 16}, /* z = z */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 24} /* w = w */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* y */ + UTIL_FORMAT_SWIZZLE_Y, /* u */ + UTIL_FORMAT_SWIZZLE_Z, /* v */ + UTIL_FORMAT_SWIZZLE_W /* ignored */ + }, + UTIL_FORMAT_COLORSPACE_YUV, + &util_format_yv16_unpack_rgba_8unorm, + &util_format_yv16_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_yv16_unpack_rgba_float, + &util_format_yv16_pack_rgba_float, + &util_format_yv16_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_iyuv_description = { + PIPE_FORMAT_IYUV, + "PIPE_FORMAT_IYUV", + "iyuv", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_OTHER, + 4, /* nr_channels */ + FALSE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 0}, /* x = x */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 8}, /* y = y */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 16}, /* z = z */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 24} /* w = w */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* y */ + UTIL_FORMAT_SWIZZLE_Y, /* u */ + UTIL_FORMAT_SWIZZLE_Z, /* v */ + UTIL_FORMAT_SWIZZLE_W /* ignored */ + }, + UTIL_FORMAT_COLORSPACE_YUV, + &util_format_iyuv_unpack_rgba_8unorm, + &util_format_iyuv_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_iyuv_unpack_rgba_float, + &util_format_iyuv_pack_rgba_float, + &util_format_iyuv_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_nv12_description = { + PIPE_FORMAT_NV12, + "PIPE_FORMAT_NV12", + "nv12", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_OTHER, + 4, /* nr_channels */ + FALSE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 0}, /* x = x */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 8}, /* y = y */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 16}, /* z = z */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 24} /* w = w */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* y */ + UTIL_FORMAT_SWIZZLE_Y, /* u */ + UTIL_FORMAT_SWIZZLE_Z, /* v */ + UTIL_FORMAT_SWIZZLE_W /* ignored */ + }, + UTIL_FORMAT_COLORSPACE_YUV, + &util_format_nv12_unpack_rgba_8unorm, + &util_format_nv12_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_nv12_unpack_rgba_float, + &util_format_nv12_pack_rgba_float, + &util_format_nv12_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_nv21_description = { + PIPE_FORMAT_NV21, + "PIPE_FORMAT_NV21", + "nv21", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_OTHER, + 4, /* nr_channels */ + FALSE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 0}, /* x = x */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 8}, /* y = y */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 16}, /* z = z */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 24} /* w = w */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* y */ + UTIL_FORMAT_SWIZZLE_Y, /* u */ + UTIL_FORMAT_SWIZZLE_Z, /* v */ + UTIL_FORMAT_SWIZZLE_W /* ignored */ + }, + UTIL_FORMAT_COLORSPACE_YUV, + &util_format_nv21_unpack_rgba_8unorm, + &util_format_nv21_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_nv21_unpack_rgba_float, + &util_format_nv21_pack_rgba_float, + &util_format_nv21_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r4a4_unorm_description = { + PIPE_FORMAT_R4A4_UNORM, + "PIPE_FORMAT_R4A4_UNORM", + "r4a4_unorm", + {1, 1, 8}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + FALSE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 4, 0}, /* x = a */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 4, 4}, /* y = r */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_Y, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_X /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r4a4_unorm_unpack_rgba_8unorm, + &util_format_r4a4_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r4a4_unorm_unpack_rgba_float, + &util_format_r4a4_unorm_pack_rgba_float, + &util_format_r4a4_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_a4r4_unorm_description = { + PIPE_FORMAT_A4R4_UNORM, + "PIPE_FORMAT_A4R4_UNORM", + "a4r4_unorm", + {1, 1, 8}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + FALSE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 4, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 4, 4}, /* y = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_Y /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_a4r4_unorm_unpack_rgba_8unorm, + &util_format_a4r4_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_a4r4_unorm_unpack_rgba_float, + &util_format_a4r4_unorm_pack_rgba_float, + &util_format_a4r4_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8a8_unorm_description = { + PIPE_FORMAT_R8A8_UNORM, + "PIPE_FORMAT_R8A8_UNORM", + "r8a8_unorm", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_Y /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r8a8_unorm_unpack_rgba_8unorm, + &util_format_r8a8_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r8a8_unorm_unpack_rgba_float, + &util_format_r8a8_unorm_pack_rgba_float, + &util_format_r8a8_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_a8r8_unorm_description = { + PIPE_FORMAT_A8R8_UNORM, + "PIPE_FORMAT_A8R8_UNORM", + "a8r8_unorm", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = a */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = r */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_Y, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_X /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_a8r8_unorm_unpack_rgba_8unorm, + &util_format_a8r8_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_a8r8_unorm_unpack_rgba_float, + &util_format_a8r8_unorm_pack_rgba_float, + &util_format_a8r8_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r10g10b10a2_uscaled_description = { + PIPE_FORMAT_R10G10B10A2_USCALED, + "PIPE_FORMAT_R10G10B10A2_USCALED", + "r10g10b10a2_uscaled", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + FALSE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 10, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 10, 10}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 10, 20}, /* z = b */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 2, 30} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r10g10b10a2_uscaled_unpack_rgba_8unorm, + &util_format_r10g10b10a2_uscaled_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r10g10b10a2_uscaled_unpack_rgba_float, + &util_format_r10g10b10a2_uscaled_pack_rgba_float, + &util_format_r10g10b10a2_uscaled_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r10g10b10a2_sscaled_description = { + PIPE_FORMAT_R10G10B10A2_SSCALED, + "PIPE_FORMAT_R10G10B10A2_SSCALED", + "r10g10b10a2_sscaled", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + FALSE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 10, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 10, 10}, /* y = g */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 10, 20}, /* z = b */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 2, 30} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r10g10b10a2_sscaled_unpack_rgba_8unorm, + &util_format_r10g10b10a2_sscaled_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r10g10b10a2_sscaled_unpack_rgba_float, + &util_format_r10g10b10a2_sscaled_pack_rgba_float, + &util_format_r10g10b10a2_sscaled_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r10g10b10a2_snorm_description = { + PIPE_FORMAT_R10G10B10A2_SNORM, + "PIPE_FORMAT_R10G10B10A2_SNORM", + "r10g10b10a2_snorm", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + FALSE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 10, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 10, 10}, /* y = g */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 10, 20}, /* z = b */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 2, 30} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r10g10b10a2_snorm_unpack_rgba_8unorm, + &util_format_r10g10b10a2_snorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r10g10b10a2_snorm_unpack_rgba_float, + &util_format_r10g10b10a2_snorm_pack_rgba_float, + &util_format_r10g10b10a2_snorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_b10g10r10a2_uscaled_description = { + PIPE_FORMAT_B10G10R10A2_USCALED, + "PIPE_FORMAT_B10G10R10A2_USCALED", + "b10g10r10a2_uscaled", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + FALSE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 10, 0}, /* x = b */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 10, 10}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 10, 20}, /* z = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 2, 30} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_Z, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_b10g10r10a2_uscaled_unpack_rgba_8unorm, + &util_format_b10g10r10a2_uscaled_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_b10g10r10a2_uscaled_unpack_rgba_float, + &util_format_b10g10r10a2_uscaled_pack_rgba_float, + &util_format_b10g10r10a2_uscaled_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_b10g10r10a2_sscaled_description = { + PIPE_FORMAT_B10G10R10A2_SSCALED, + "PIPE_FORMAT_B10G10R10A2_SSCALED", + "b10g10r10a2_sscaled", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + FALSE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 10, 0}, /* x = b */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 10, 10}, /* y = g */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 10, 20}, /* z = r */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 2, 30} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_Z, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_b10g10r10a2_sscaled_unpack_rgba_8unorm, + &util_format_b10g10r10a2_sscaled_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_b10g10r10a2_sscaled_unpack_rgba_float, + &util_format_b10g10r10a2_sscaled_pack_rgba_float, + &util_format_b10g10r10a2_sscaled_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_b10g10r10a2_snorm_description = { + PIPE_FORMAT_B10G10R10A2_SNORM, + "PIPE_FORMAT_B10G10R10A2_SNORM", + "b10g10r10a2_snorm", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + FALSE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 10, 0}, /* x = b */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 10, 10}, /* y = g */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 10, 20}, /* z = r */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 2, 30} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_Z, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_b10g10r10a2_snorm_unpack_rgba_8unorm, + &util_format_b10g10r10a2_snorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_b10g10r10a2_snorm_unpack_rgba_float, + &util_format_b10g10r10a2_snorm_pack_rgba_float, + &util_format_b10g10r10a2_snorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8_uint_description = { + PIPE_FORMAT_R8_UINT, + "PIPE_FORMAT_R8_UINT", + "r8_uint", + {1, 1, 8}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 0}, /* x = r */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r8_uint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r8_uint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r8_uint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r8_uint_pack_signed, /* pack_rgba_sint */ + &util_format_r8_uint_fetch_unsigned, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8g8_uint_description = { + PIPE_FORMAT_R8G8_UINT, + "PIPE_FORMAT_R8G8_UINT", + "r8g8_uint", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 8}, /* y = g */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r8g8_uint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r8g8_uint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r8g8_uint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r8g8_uint_pack_signed, /* pack_rgba_sint */ + &util_format_r8g8_uint_fetch_unsigned, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8g8b8_uint_description = { + PIPE_FORMAT_R8G8B8_UINT, + "PIPE_FORMAT_R8G8B8_UINT", + "r8g8b8_uint", + {1, 1, 24}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 3, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 8}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 16}, /* z = b */ + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r8g8b8_uint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r8g8b8_uint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r8g8b8_uint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r8g8b8_uint_pack_signed, /* pack_rgba_sint */ + &util_format_r8g8b8_uint_fetch_unsigned, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8g8b8a8_uint_description = { + PIPE_FORMAT_R8G8B8A8_UINT, + "PIPE_FORMAT_R8G8B8A8_UINT", + "r8g8b8a8_uint", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 8}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 16}, /* z = b */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 24} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r8g8b8a8_uint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r8g8b8a8_uint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r8g8b8a8_uint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r8g8b8a8_uint_pack_signed, /* pack_rgba_sint */ + &util_format_r8g8b8a8_uint_fetch_unsigned, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8_sint_description = { + PIPE_FORMAT_R8_SINT, + "PIPE_FORMAT_R8_SINT", + "r8_sint", + {1, 1, 8}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 0}, /* x = r */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r8_sint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r8_sint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r8_sint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r8_sint_pack_signed, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + &util_format_r8_sint_fetch_signed /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8g8_sint_description = { + PIPE_FORMAT_R8G8_SINT, + "PIPE_FORMAT_R8G8_SINT", + "r8g8_sint", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 8}, /* y = g */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r8g8_sint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r8g8_sint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r8g8_sint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r8g8_sint_pack_signed, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + &util_format_r8g8_sint_fetch_signed /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8g8b8_sint_description = { + PIPE_FORMAT_R8G8B8_SINT, + "PIPE_FORMAT_R8G8B8_SINT", + "r8g8b8_sint", + {1, 1, 24}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 3, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 8}, /* y = g */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 16}, /* z = b */ + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r8g8b8_sint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r8g8b8_sint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r8g8b8_sint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r8g8b8_sint_pack_signed, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + &util_format_r8g8b8_sint_fetch_signed /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8g8b8a8_sint_description = { + PIPE_FORMAT_R8G8B8A8_SINT, + "PIPE_FORMAT_R8G8B8A8_SINT", + "r8g8b8a8_sint", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 8}, /* y = g */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 16}, /* z = b */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 24} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r8g8b8a8_sint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r8g8b8a8_sint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r8g8b8a8_sint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r8g8b8a8_sint_pack_signed, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + &util_format_r8g8b8a8_sint_fetch_signed /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16_uint_description = { + PIPE_FORMAT_R16_UINT, + "PIPE_FORMAT_R16_UINT", + "r16_uint", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 0}, /* x = r */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r16_uint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r16_uint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r16_uint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r16_uint_pack_signed, /* pack_rgba_sint */ + &util_format_r16_uint_fetch_unsigned, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16g16_uint_description = { + PIPE_FORMAT_R16G16_UINT, + "PIPE_FORMAT_R16G16_UINT", + "r16g16_uint", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 16}, /* y = g */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r16g16_uint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r16g16_uint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r16g16_uint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r16g16_uint_pack_signed, /* pack_rgba_sint */ + &util_format_r16g16_uint_fetch_unsigned, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16g16b16_uint_description = { + PIPE_FORMAT_R16G16B16_UINT, + "PIPE_FORMAT_R16G16B16_UINT", + "r16g16b16_uint", + {1, 1, 48}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 3, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 16}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 32}, /* z = b */ + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r16g16b16_uint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r16g16b16_uint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r16g16b16_uint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r16g16b16_uint_pack_signed, /* pack_rgba_sint */ + &util_format_r16g16b16_uint_fetch_unsigned, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16g16b16a16_uint_description = { + PIPE_FORMAT_R16G16B16A16_UINT, + "PIPE_FORMAT_R16G16B16A16_UINT", + "r16g16b16a16_uint", + {1, 1, 64}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 16}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 32}, /* z = b */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 48} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r16g16b16a16_uint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r16g16b16a16_uint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r16g16b16a16_uint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r16g16b16a16_uint_pack_signed, /* pack_rgba_sint */ + &util_format_r16g16b16a16_uint_fetch_unsigned, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16_sint_description = { + PIPE_FORMAT_R16_SINT, + "PIPE_FORMAT_R16_SINT", + "r16_sint", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 0}, /* x = r */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r16_sint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r16_sint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r16_sint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r16_sint_pack_signed, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + &util_format_r16_sint_fetch_signed /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16g16_sint_description = { + PIPE_FORMAT_R16G16_SINT, + "PIPE_FORMAT_R16G16_SINT", + "r16g16_sint", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 16}, /* y = g */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r16g16_sint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r16g16_sint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r16g16_sint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r16g16_sint_pack_signed, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + &util_format_r16g16_sint_fetch_signed /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16g16b16_sint_description = { + PIPE_FORMAT_R16G16B16_SINT, + "PIPE_FORMAT_R16G16B16_SINT", + "r16g16b16_sint", + {1, 1, 48}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 3, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 16}, /* y = g */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 32}, /* z = b */ + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r16g16b16_sint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r16g16b16_sint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r16g16b16_sint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r16g16b16_sint_pack_signed, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + &util_format_r16g16b16_sint_fetch_signed /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16g16b16a16_sint_description = { + PIPE_FORMAT_R16G16B16A16_SINT, + "PIPE_FORMAT_R16G16B16A16_SINT", + "r16g16b16a16_sint", + {1, 1, 64}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 16}, /* y = g */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 32}, /* z = b */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 48} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r16g16b16a16_sint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r16g16b16a16_sint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r16g16b16a16_sint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r16g16b16a16_sint_pack_signed, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + &util_format_r16g16b16a16_sint_fetch_signed /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32_uint_description = { + PIPE_FORMAT_R32_UINT, + "PIPE_FORMAT_R32_UINT", + "r32_uint", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 0}, /* x = r */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r32_uint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r32_uint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r32_uint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r32_uint_pack_signed, /* pack_rgba_sint */ + &util_format_r32_uint_fetch_unsigned, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32g32_uint_description = { + PIPE_FORMAT_R32G32_UINT, + "PIPE_FORMAT_R32G32_UINT", + "r32g32_uint", + {1, 1, 64}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 32}, /* y = g */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r32g32_uint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r32g32_uint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r32g32_uint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r32g32_uint_pack_signed, /* pack_rgba_sint */ + &util_format_r32g32_uint_fetch_unsigned, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32g32b32_uint_description = { + PIPE_FORMAT_R32G32B32_UINT, + "PIPE_FORMAT_R32G32B32_UINT", + "r32g32b32_uint", + {1, 1, 96}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 3, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 32}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 64}, /* z = b */ + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r32g32b32_uint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r32g32b32_uint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r32g32b32_uint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r32g32b32_uint_pack_signed, /* pack_rgba_sint */ + &util_format_r32g32b32_uint_fetch_unsigned, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32g32b32a32_uint_description = { + PIPE_FORMAT_R32G32B32A32_UINT, + "PIPE_FORMAT_R32G32B32A32_UINT", + "r32g32b32a32_uint", + {1, 1, 128}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 32}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 64}, /* z = b */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 96} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r32g32b32a32_uint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r32g32b32a32_uint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r32g32b32a32_uint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r32g32b32a32_uint_pack_signed, /* pack_rgba_sint */ + &util_format_r32g32b32a32_uint_fetch_unsigned, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32_sint_description = { + PIPE_FORMAT_R32_SINT, + "PIPE_FORMAT_R32_SINT", + "r32_sint", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 0}, /* x = r */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r32_sint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r32_sint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r32_sint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r32_sint_pack_signed, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + &util_format_r32_sint_fetch_signed /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32g32_sint_description = { + PIPE_FORMAT_R32G32_SINT, + "PIPE_FORMAT_R32G32_SINT", + "r32g32_sint", + {1, 1, 64}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 32}, /* y = g */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r32g32_sint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r32g32_sint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r32g32_sint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r32g32_sint_pack_signed, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + &util_format_r32g32_sint_fetch_signed /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32g32b32_sint_description = { + PIPE_FORMAT_R32G32B32_SINT, + "PIPE_FORMAT_R32G32B32_SINT", + "r32g32b32_sint", + {1, 1, 96}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 3, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 32}, /* y = g */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 64}, /* z = b */ + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r32g32b32_sint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r32g32b32_sint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r32g32b32_sint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r32g32b32_sint_pack_signed, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + &util_format_r32g32b32_sint_fetch_signed /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32g32b32a32_sint_description = { + PIPE_FORMAT_R32G32B32A32_SINT, + "PIPE_FORMAT_R32G32B32A32_SINT", + "r32g32b32a32_sint", + {1, 1, 128}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 32}, /* y = g */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 64}, /* z = b */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 96} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r32g32b32a32_sint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r32g32b32a32_sint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r32g32b32a32_sint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r32g32b32a32_sint_pack_signed, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + &util_format_r32g32b32a32_sint_fetch_signed /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_a8_uint_description = { + PIPE_FORMAT_A8_UINT, + "PIPE_FORMAT_A8_UINT", + "a8_uint", + {1, 1, 8}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 0}, /* x = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_0, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_X /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_a8_uint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_a8_uint_pack_unsigned, /* pack_rgba_uint */ + &util_format_a8_uint_unpack_signed, /* unpack_rgba_sint */ + &util_format_a8_uint_pack_signed, /* pack_rgba_sint */ + &util_format_a8_uint_fetch_unsigned, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_i8_uint_description = { + PIPE_FORMAT_I8_UINT, + "PIPE_FORMAT_I8_UINT", + "i8_uint", + {1, 1, 8}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 0}, /* x = rgba */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_X /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_i8_uint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_i8_uint_pack_unsigned, /* pack_rgba_uint */ + &util_format_i8_uint_unpack_signed, /* unpack_rgba_sint */ + &util_format_i8_uint_pack_signed, /* pack_rgba_sint */ + &util_format_i8_uint_fetch_unsigned, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_l8_uint_description = { + PIPE_FORMAT_L8_UINT, + "PIPE_FORMAT_L8_UINT", + "l8_uint", + {1, 1, 8}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 0}, /* x = rgb */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_l8_uint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_l8_uint_pack_unsigned, /* pack_rgba_uint */ + &util_format_l8_uint_unpack_signed, /* unpack_rgba_sint */ + &util_format_l8_uint_pack_signed, /* pack_rgba_sint */ + &util_format_l8_uint_fetch_unsigned, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_l8a8_uint_description = { + PIPE_FORMAT_L8A8_UINT, + "PIPE_FORMAT_L8A8_UINT", + "l8a8_uint", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 0}, /* x = rgb */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 8}, /* y = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_Y /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_l8a8_uint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_l8a8_uint_pack_unsigned, /* pack_rgba_uint */ + &util_format_l8a8_uint_unpack_signed, /* unpack_rgba_sint */ + &util_format_l8a8_uint_pack_signed, /* pack_rgba_sint */ + &util_format_l8a8_uint_fetch_unsigned, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_a8_sint_description = { + PIPE_FORMAT_A8_SINT, + "PIPE_FORMAT_A8_SINT", + "a8_sint", + {1, 1, 8}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 0}, /* x = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_0, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_X /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_a8_sint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_a8_sint_pack_unsigned, /* pack_rgba_uint */ + &util_format_a8_sint_unpack_signed, /* unpack_rgba_sint */ + &util_format_a8_sint_pack_signed, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + &util_format_a8_sint_fetch_signed /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_i8_sint_description = { + PIPE_FORMAT_I8_SINT, + "PIPE_FORMAT_I8_SINT", + "i8_sint", + {1, 1, 8}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 0}, /* x = rgba */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_X /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_i8_sint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_i8_sint_pack_unsigned, /* pack_rgba_uint */ + &util_format_i8_sint_unpack_signed, /* unpack_rgba_sint */ + &util_format_i8_sint_pack_signed, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + &util_format_i8_sint_fetch_signed /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_l8_sint_description = { + PIPE_FORMAT_L8_SINT, + "PIPE_FORMAT_L8_SINT", + "l8_sint", + {1, 1, 8}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 0}, /* x = rgb */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_l8_sint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_l8_sint_pack_unsigned, /* pack_rgba_uint */ + &util_format_l8_sint_unpack_signed, /* unpack_rgba_sint */ + &util_format_l8_sint_pack_signed, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + &util_format_l8_sint_fetch_signed /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_l8a8_sint_description = { + PIPE_FORMAT_L8A8_SINT, + "PIPE_FORMAT_L8A8_SINT", + "l8a8_sint", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 0}, /* x = rgb */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 8}, /* y = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_Y /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_l8a8_sint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_l8a8_sint_pack_unsigned, /* pack_rgba_uint */ + &util_format_l8a8_sint_unpack_signed, /* unpack_rgba_sint */ + &util_format_l8a8_sint_pack_signed, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + &util_format_l8a8_sint_fetch_signed /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_a16_uint_description = { + PIPE_FORMAT_A16_UINT, + "PIPE_FORMAT_A16_UINT", + "a16_uint", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 0}, /* x = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_0, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_X /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_a16_uint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_a16_uint_pack_unsigned, /* pack_rgba_uint */ + &util_format_a16_uint_unpack_signed, /* unpack_rgba_sint */ + &util_format_a16_uint_pack_signed, /* pack_rgba_sint */ + &util_format_a16_uint_fetch_unsigned, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_i16_uint_description = { + PIPE_FORMAT_I16_UINT, + "PIPE_FORMAT_I16_UINT", + "i16_uint", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 0}, /* x = rgba */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_X /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_i16_uint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_i16_uint_pack_unsigned, /* pack_rgba_uint */ + &util_format_i16_uint_unpack_signed, /* unpack_rgba_sint */ + &util_format_i16_uint_pack_signed, /* pack_rgba_sint */ + &util_format_i16_uint_fetch_unsigned, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_l16_uint_description = { + PIPE_FORMAT_L16_UINT, + "PIPE_FORMAT_L16_UINT", + "l16_uint", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 0}, /* x = rgb */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_l16_uint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_l16_uint_pack_unsigned, /* pack_rgba_uint */ + &util_format_l16_uint_unpack_signed, /* unpack_rgba_sint */ + &util_format_l16_uint_pack_signed, /* pack_rgba_sint */ + &util_format_l16_uint_fetch_unsigned, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_l16a16_uint_description = { + PIPE_FORMAT_L16A16_UINT, + "PIPE_FORMAT_L16A16_UINT", + "l16a16_uint", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 0}, /* x = rgb */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 16}, /* y = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_Y /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_l16a16_uint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_l16a16_uint_pack_unsigned, /* pack_rgba_uint */ + &util_format_l16a16_uint_unpack_signed, /* unpack_rgba_sint */ + &util_format_l16a16_uint_pack_signed, /* pack_rgba_sint */ + &util_format_l16a16_uint_fetch_unsigned, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_a16_sint_description = { + PIPE_FORMAT_A16_SINT, + "PIPE_FORMAT_A16_SINT", + "a16_sint", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 0}, /* x = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_0, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_X /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_a16_sint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_a16_sint_pack_unsigned, /* pack_rgba_uint */ + &util_format_a16_sint_unpack_signed, /* unpack_rgba_sint */ + &util_format_a16_sint_pack_signed, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + &util_format_a16_sint_fetch_signed /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_i16_sint_description = { + PIPE_FORMAT_I16_SINT, + "PIPE_FORMAT_I16_SINT", + "i16_sint", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 0}, /* x = rgba */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_X /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_i16_sint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_i16_sint_pack_unsigned, /* pack_rgba_uint */ + &util_format_i16_sint_unpack_signed, /* unpack_rgba_sint */ + &util_format_i16_sint_pack_signed, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + &util_format_i16_sint_fetch_signed /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_l16_sint_description = { + PIPE_FORMAT_L16_SINT, + "PIPE_FORMAT_L16_SINT", + "l16_sint", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 0}, /* x = rgb */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_l16_sint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_l16_sint_pack_unsigned, /* pack_rgba_uint */ + &util_format_l16_sint_unpack_signed, /* unpack_rgba_sint */ + &util_format_l16_sint_pack_signed, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + &util_format_l16_sint_fetch_signed /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_l16a16_sint_description = { + PIPE_FORMAT_L16A16_SINT, + "PIPE_FORMAT_L16A16_SINT", + "l16a16_sint", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 0}, /* x = rgb */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 16}, /* y = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_Y /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_l16a16_sint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_l16a16_sint_pack_unsigned, /* pack_rgba_uint */ + &util_format_l16a16_sint_unpack_signed, /* unpack_rgba_sint */ + &util_format_l16a16_sint_pack_signed, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + &util_format_l16a16_sint_fetch_signed /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_a32_uint_description = { + PIPE_FORMAT_A32_UINT, + "PIPE_FORMAT_A32_UINT", + "a32_uint", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 0}, /* x = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_0, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_X /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_a32_uint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_a32_uint_pack_unsigned, /* pack_rgba_uint */ + &util_format_a32_uint_unpack_signed, /* unpack_rgba_sint */ + &util_format_a32_uint_pack_signed, /* pack_rgba_sint */ + &util_format_a32_uint_fetch_unsigned, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_i32_uint_description = { + PIPE_FORMAT_I32_UINT, + "PIPE_FORMAT_I32_UINT", + "i32_uint", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 0}, /* x = rgba */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_X /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_i32_uint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_i32_uint_pack_unsigned, /* pack_rgba_uint */ + &util_format_i32_uint_unpack_signed, /* unpack_rgba_sint */ + &util_format_i32_uint_pack_signed, /* pack_rgba_sint */ + &util_format_i32_uint_fetch_unsigned, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_l32_uint_description = { + PIPE_FORMAT_L32_UINT, + "PIPE_FORMAT_L32_UINT", + "l32_uint", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 0}, /* x = rgb */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_l32_uint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_l32_uint_pack_unsigned, /* pack_rgba_uint */ + &util_format_l32_uint_unpack_signed, /* unpack_rgba_sint */ + &util_format_l32_uint_pack_signed, /* pack_rgba_sint */ + &util_format_l32_uint_fetch_unsigned, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_l32a32_uint_description = { + PIPE_FORMAT_L32A32_UINT, + "PIPE_FORMAT_L32A32_UINT", + "l32a32_uint", + {1, 1, 64}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 0}, /* x = rgb */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 32}, /* y = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_Y /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_l32a32_uint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_l32a32_uint_pack_unsigned, /* pack_rgba_uint */ + &util_format_l32a32_uint_unpack_signed, /* unpack_rgba_sint */ + &util_format_l32a32_uint_pack_signed, /* pack_rgba_sint */ + &util_format_l32a32_uint_fetch_unsigned, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_a32_sint_description = { + PIPE_FORMAT_A32_SINT, + "PIPE_FORMAT_A32_SINT", + "a32_sint", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 0}, /* x = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_0, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_X /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_a32_sint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_a32_sint_pack_unsigned, /* pack_rgba_uint */ + &util_format_a32_sint_unpack_signed, /* unpack_rgba_sint */ + &util_format_a32_sint_pack_signed, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + &util_format_a32_sint_fetch_signed /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_i32_sint_description = { + PIPE_FORMAT_I32_SINT, + "PIPE_FORMAT_I32_SINT", + "i32_sint", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 0}, /* x = rgba */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_X /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_i32_sint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_i32_sint_pack_unsigned, /* pack_rgba_uint */ + &util_format_i32_sint_unpack_signed, /* unpack_rgba_sint */ + &util_format_i32_sint_pack_signed, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + &util_format_i32_sint_fetch_signed /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_l32_sint_description = { + PIPE_FORMAT_L32_SINT, + "PIPE_FORMAT_L32_SINT", + "l32_sint", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 1, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 0}, /* x = rgb */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_l32_sint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_l32_sint_pack_unsigned, /* pack_rgba_uint */ + &util_format_l32_sint_unpack_signed, /* unpack_rgba_sint */ + &util_format_l32_sint_pack_signed, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + &util_format_l32_sint_fetch_signed /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_l32a32_sint_description = { + PIPE_FORMAT_L32A32_SINT, + "PIPE_FORMAT_L32A32_SINT", + "l32a32_sint", + {1, 1, 64}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 0}, /* x = rgb */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 32}, /* y = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_X, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_Y /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_l32a32_sint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_l32a32_sint_pack_unsigned, /* pack_rgba_uint */ + &util_format_l32a32_sint_unpack_signed, /* unpack_rgba_sint */ + &util_format_l32a32_sint_pack_signed, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + &util_format_l32a32_sint_fetch_signed /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_b10g10r10a2_uint_description = { + PIPE_FORMAT_B10G10R10A2_UINT, + "PIPE_FORMAT_B10G10R10A2_UINT", + "b10g10r10a2_uint", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + FALSE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 10, 0}, /* x = b */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 10, 10}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 10, 20}, /* z = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 2, 30} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_Z, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_b10g10r10a2_uint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_b10g10r10a2_uint_pack_unsigned, /* pack_rgba_uint */ + &util_format_b10g10r10a2_uint_unpack_signed, /* unpack_rgba_sint */ + &util_format_b10g10r10a2_uint_pack_signed, /* pack_rgba_sint */ + &util_format_b10g10r10a2_uint_fetch_unsigned, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8g8b8x8_snorm_description = { + PIPE_FORMAT_R8G8B8X8_SNORM, + "PIPE_FORMAT_R8G8B8X8_SNORM", + "r8g8b8x8_snorm", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 8}, /* y = g */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 16}, /* z = b */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 24} /* w = x */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r8g8b8x8_snorm_unpack_rgba_8unorm, + &util_format_r8g8b8x8_snorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r8g8b8x8_snorm_unpack_rgba_float, + &util_format_r8g8b8x8_snorm_pack_rgba_float, + &util_format_r8g8b8x8_snorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8g8b8x8_srgb_description = { + PIPE_FORMAT_R8G8B8X8_SRGB, + "PIPE_FORMAT_R8G8B8X8_SRGB", + "r8g8b8x8_srgb", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 16}, /* z = b */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 24} /* w = x */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* sr */ + UTIL_FORMAT_SWIZZLE_Y, /* sg */ + UTIL_FORMAT_SWIZZLE_Z, /* sb */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_SRGB, + &util_format_r8g8b8x8_srgb_unpack_rgba_8unorm, + &util_format_r8g8b8x8_srgb_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r8g8b8x8_srgb_unpack_rgba_float, + &util_format_r8g8b8x8_srgb_pack_rgba_float, + &util_format_r8g8b8x8_srgb_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8g8b8x8_uint_description = { + PIPE_FORMAT_R8G8B8X8_UINT, + "PIPE_FORMAT_R8G8B8X8_UINT", + "r8g8b8x8_uint", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 8}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 16}, /* z = b */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 24} /* w = x */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r8g8b8x8_uint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r8g8b8x8_uint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r8g8b8x8_uint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r8g8b8x8_uint_pack_signed, /* pack_rgba_sint */ + &util_format_r8g8b8x8_uint_fetch_unsigned, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8g8b8x8_sint_description = { + PIPE_FORMAT_R8G8B8X8_SINT, + "PIPE_FORMAT_R8G8B8X8_SINT", + "r8g8b8x8_sint", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 8}, /* y = g */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 16}, /* z = b */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 24} /* w = x */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r8g8b8x8_sint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r8g8b8x8_sint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r8g8b8x8_sint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r8g8b8x8_sint_pack_signed, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + &util_format_r8g8b8x8_sint_fetch_signed /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_b10g10r10x2_unorm_description = { + PIPE_FORMAT_B10G10R10X2_UNORM, + "PIPE_FORMAT_B10G10R10X2_UNORM", + "b10g10r10x2_unorm", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + FALSE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 10, 0}, /* x = b */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 10, 10}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 10, 20}, /* z = r */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 2, 30} /* w = x */ + }, + { + UTIL_FORMAT_SWIZZLE_Z, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_X, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_b10g10r10x2_unorm_unpack_rgba_8unorm, + &util_format_b10g10r10x2_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_b10g10r10x2_unorm_unpack_rgba_float, + &util_format_b10g10r10x2_unorm_pack_rgba_float, + &util_format_b10g10r10x2_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16g16b16x16_unorm_description = { + PIPE_FORMAT_R16G16B16X16_UNORM, + "PIPE_FORMAT_R16G16B16X16_UNORM", + "r16g16b16x16_unorm", + {1, 1, 64}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 16}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 32}, /* z = b */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 16, 48} /* w = x */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r16g16b16x16_unorm_unpack_rgba_8unorm, + &util_format_r16g16b16x16_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r16g16b16x16_unorm_unpack_rgba_float, + &util_format_r16g16b16x16_unorm_pack_rgba_float, + &util_format_r16g16b16x16_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16g16b16x16_snorm_description = { + PIPE_FORMAT_R16G16B16X16_SNORM, + "PIPE_FORMAT_R16G16B16X16_SNORM", + "r16g16b16x16_snorm", + {1, 1, 64}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 16}, /* y = g */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 32}, /* z = b */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 16, 48} /* w = x */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r16g16b16x16_snorm_unpack_rgba_8unorm, + &util_format_r16g16b16x16_snorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r16g16b16x16_snorm_unpack_rgba_float, + &util_format_r16g16b16x16_snorm_pack_rgba_float, + &util_format_r16g16b16x16_snorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16g16b16x16_float_description = { + PIPE_FORMAT_R16G16B16X16_FLOAT, + "PIPE_FORMAT_R16G16B16X16_FLOAT", + "r16g16b16x16_float", + {1, 1, 64}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 16}, /* y = g */ + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 32}, /* z = b */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 16, 48} /* w = x */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r16g16b16x16_float_unpack_rgba_8unorm, + &util_format_r16g16b16x16_float_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r16g16b16x16_float_unpack_rgba_float, + &util_format_r16g16b16x16_float_pack_rgba_float, + &util_format_r16g16b16x16_float_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16g16b16x16_uint_description = { + PIPE_FORMAT_R16G16B16X16_UINT, + "PIPE_FORMAT_R16G16B16X16_UINT", + "r16g16b16x16_uint", + {1, 1, 64}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 16}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 32}, /* z = b */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 16, 48} /* w = x */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r16g16b16x16_uint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r16g16b16x16_uint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r16g16b16x16_uint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r16g16b16x16_uint_pack_signed, /* pack_rgba_sint */ + &util_format_r16g16b16x16_uint_fetch_unsigned, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16g16b16x16_sint_description = { + PIPE_FORMAT_R16G16B16X16_SINT, + "PIPE_FORMAT_R16G16B16X16_SINT", + "r16g16b16x16_sint", + {1, 1, 64}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 16}, /* y = g */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 32}, /* z = b */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 16, 48} /* w = x */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r16g16b16x16_sint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r16g16b16x16_sint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r16g16b16x16_sint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r16g16b16x16_sint_pack_signed, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + &util_format_r16g16b16x16_sint_fetch_signed /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32g32b32x32_float_description = { + PIPE_FORMAT_R32G32B32X32_FLOAT, + "PIPE_FORMAT_R32G32B32X32_FLOAT", + "r32g32b32x32_float", + {1, 1, 128}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 32}, /* y = g */ + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 64}, /* z = b */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 32, 96} /* w = x */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r32g32b32x32_float_unpack_rgba_8unorm, + &util_format_r32g32b32x32_float_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r32g32b32x32_float_unpack_rgba_float, + &util_format_r32g32b32x32_float_pack_rgba_float, + &util_format_r32g32b32x32_float_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32g32b32x32_uint_description = { + PIPE_FORMAT_R32G32B32X32_UINT, + "PIPE_FORMAT_R32G32B32X32_UINT", + "r32g32b32x32_uint", + {1, 1, 128}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 32}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 64}, /* z = b */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 32, 96} /* w = x */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r32g32b32x32_uint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r32g32b32x32_uint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r32g32b32x32_uint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r32g32b32x32_uint_pack_signed, /* pack_rgba_sint */ + &util_format_r32g32b32x32_uint_fetch_unsigned, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32g32b32x32_sint_description = { + PIPE_FORMAT_R32G32B32X32_SINT, + "PIPE_FORMAT_R32G32B32X32_SINT", + "r32g32b32x32_sint", + {1, 1, 128}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 32}, /* y = g */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 64}, /* z = b */ + {UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 32, 96} /* w = x */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_1 /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r32g32b32x32_sint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r32g32b32x32_sint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r32g32b32x32_sint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r32g32b32x32_sint_pack_signed, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + &util_format_r32g32b32x32_sint_fetch_signed /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8a8_snorm_description = { + PIPE_FORMAT_R8A8_SNORM, + "PIPE_FORMAT_R8A8_SNORM", + "r8a8_snorm", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 8}, /* y = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_Y /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r8a8_snorm_unpack_rgba_8unorm, + &util_format_r8a8_snorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r8a8_snorm_unpack_rgba_float, + &util_format_r8a8_snorm_pack_rgba_float, + &util_format_r8a8_snorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16a16_unorm_description = { + PIPE_FORMAT_R16A16_UNORM, + "PIPE_FORMAT_R16A16_UNORM", + "r16a16_unorm", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 16}, /* y = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_Y /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r16a16_unorm_unpack_rgba_8unorm, + &util_format_r16a16_unorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r16a16_unorm_unpack_rgba_float, + &util_format_r16a16_unorm_pack_rgba_float, + &util_format_r16a16_unorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16a16_snorm_description = { + PIPE_FORMAT_R16A16_SNORM, + "PIPE_FORMAT_R16A16_SNORM", + "r16a16_snorm", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 16}, /* y = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_Y /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r16a16_snorm_unpack_rgba_8unorm, + &util_format_r16a16_snorm_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r16a16_snorm_unpack_rgba_float, + &util_format_r16a16_snorm_pack_rgba_float, + &util_format_r16a16_snorm_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16a16_float_description = { + PIPE_FORMAT_R16A16_FLOAT, + "PIPE_FORMAT_R16A16_FLOAT", + "r16a16_float", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 16}, /* y = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_Y /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r16a16_float_unpack_rgba_8unorm, + &util_format_r16a16_float_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r16a16_float_unpack_rgba_float, + &util_format_r16a16_float_pack_rgba_float, + &util_format_r16a16_float_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32a32_float_description = { + PIPE_FORMAT_R32A32_FLOAT, + "PIPE_FORMAT_R32A32_FLOAT", + "r32a32_float", + {1, 1, 64}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 32}, /* y = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_Y /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + &util_format_r32a32_float_unpack_rgba_8unorm, + &util_format_r32a32_float_pack_rgba_8unorm, + NULL, /* fetch_rgba_8unorm */ + &util_format_r32a32_float_unpack_rgba_float, + &util_format_r32a32_float_pack_rgba_float, + &util_format_r32a32_float_fetch_rgba_float, + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + NULL, /* unpack_rgba_uint */ + NULL, /* pack_rgba_uint */ + NULL, /* unpack_rgba_sint */ + NULL, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8a8_uint_description = { + PIPE_FORMAT_R8A8_UINT, + "PIPE_FORMAT_R8A8_UINT", + "r8a8_uint", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 8}, /* y = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_Y /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r8a8_uint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r8a8_uint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r8a8_uint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r8a8_uint_pack_signed, /* pack_rgba_sint */ + &util_format_r8a8_uint_fetch_unsigned, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r8a8_sint_description = { + PIPE_FORMAT_R8A8_SINT, + "PIPE_FORMAT_R8A8_SINT", + "r8a8_sint", + {1, 1, 16}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 8}, /* y = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_Y /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r8a8_sint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r8a8_sint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r8a8_sint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r8a8_sint_pack_signed, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + &util_format_r8a8_sint_fetch_signed /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16a16_uint_description = { + PIPE_FORMAT_R16A16_UINT, + "PIPE_FORMAT_R16A16_UINT", + "r16a16_uint", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 16}, /* y = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_Y /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r16a16_uint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r16a16_uint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r16a16_uint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r16a16_uint_pack_signed, /* pack_rgba_sint */ + &util_format_r16a16_uint_fetch_unsigned, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r16a16_sint_description = { + PIPE_FORMAT_R16A16_SINT, + "PIPE_FORMAT_R16A16_SINT", + "r16a16_sint", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 16}, /* y = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_Y /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r16a16_sint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r16a16_sint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r16a16_sint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r16a16_sint_pack_signed, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + &util_format_r16a16_sint_fetch_signed /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32a32_uint_description = { + PIPE_FORMAT_R32A32_UINT, + "PIPE_FORMAT_R32A32_UINT", + "r32a32_uint", + {1, 1, 64}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 32}, /* y = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_Y /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r32a32_uint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r32a32_uint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r32a32_uint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r32a32_uint_pack_signed, /* pack_rgba_sint */ + &util_format_r32a32_uint_fetch_unsigned, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r32a32_sint_description = { + PIPE_FORMAT_R32A32_SINT, + "PIPE_FORMAT_R32A32_SINT", + "r32a32_sint", + {1, 1, 64}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 2, /* nr_channels */ + TRUE, /* is_array */ + FALSE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 32}, /* y = a */ + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_0, /* g */ + UTIL_FORMAT_SWIZZLE_0, /* b */ + UTIL_FORMAT_SWIZZLE_Y /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r32a32_sint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r32a32_sint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r32a32_sint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r32a32_sint_pack_signed, /* pack_rgba_sint */ + NULL, /* fetch_rgba_uint */ + &util_format_r32a32_sint_fetch_signed /* fetch_rgba_sint */ +}; + +const struct util_format_description +util_format_r10g10b10a2_uint_description = { + PIPE_FORMAT_R10G10B10A2_UINT, + "PIPE_FORMAT_R10G10B10A2_UINT", + "r10g10b10a2_uint", + {1, 1, 32}, /* block */ + UTIL_FORMAT_LAYOUT_PLAIN, + 4, /* nr_channels */ + FALSE, /* is_array */ + TRUE, /* is_bitmask */ + FALSE, /* is_mixed */ + { + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 10, 0}, /* x = r */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 10, 10}, /* y = g */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 10, 20}, /* z = b */ + {UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 2, 30} /* w = a */ + }, + { + UTIL_FORMAT_SWIZZLE_X, /* r */ + UTIL_FORMAT_SWIZZLE_Y, /* g */ + UTIL_FORMAT_SWIZZLE_Z, /* b */ + UTIL_FORMAT_SWIZZLE_W /* a */ + }, + UTIL_FORMAT_COLORSPACE_RGB, + NULL, /* unpack_rgba_8unorm */ + NULL, /* pack_rgba_8unorm */ + NULL, /* fetch_rgba_8unorm */ + NULL, /* unpack_rgba_float */ + NULL, /* pack_rgba_float */ + NULL, /* fetch_rgba_float */ + NULL, /* unpack_z_32unorm */ + NULL, /* pack_z_32unorm */ + NULL, /* unpack_z_float */ + NULL, /* pack_z_float */ + NULL, /* unpack_s_8uint */ + NULL, /* pack_s_8uint */ + &util_format_r10g10b10a2_uint_unpack_unsigned, /* unpack_rgba_uint */ + &util_format_r10g10b10a2_uint_pack_unsigned, /* pack_rgba_uint */ + &util_format_r10g10b10a2_uint_unpack_signed, /* unpack_rgba_sint */ + &util_format_r10g10b10a2_uint_pack_signed, /* pack_rgba_sint */ + &util_format_r10g10b10a2_uint_fetch_unsigned, /* fetch_rgba_uint */ + NULL /* fetch_rgba_sint */ +}; + +const struct util_format_description * +util_format_description(enum pipe_format format) +{ + if (format >= PIPE_FORMAT_COUNT) { + return NULL; + } + + switch (format) { + case PIPE_FORMAT_NONE: + return &util_format_none_description; + case PIPE_FORMAT_B8G8R8A8_UNORM: + return &util_format_b8g8r8a8_unorm_description; + case PIPE_FORMAT_B8G8R8X8_UNORM: + return &util_format_b8g8r8x8_unorm_description; + case PIPE_FORMAT_A8R8G8B8_UNORM: + return &util_format_a8r8g8b8_unorm_description; + case PIPE_FORMAT_X8R8G8B8_UNORM: + return &util_format_x8r8g8b8_unorm_description; + case PIPE_FORMAT_A8B8G8R8_UNORM: + return &util_format_a8b8g8r8_unorm_description; + case PIPE_FORMAT_X8B8G8R8_UNORM: + return &util_format_x8b8g8r8_unorm_description; + case PIPE_FORMAT_R8G8B8X8_UNORM: + return &util_format_r8g8b8x8_unorm_description; + case PIPE_FORMAT_B5G5R5X1_UNORM: + return &util_format_b5g5r5x1_unorm_description; + case PIPE_FORMAT_B5G5R5A1_UNORM: + return &util_format_b5g5r5a1_unorm_description; + case PIPE_FORMAT_B4G4R4A4_UNORM: + return &util_format_b4g4r4a4_unorm_description; + case PIPE_FORMAT_B4G4R4X4_UNORM: + return &util_format_b4g4r4x4_unorm_description; + case PIPE_FORMAT_B5G6R5_UNORM: + return &util_format_b5g6r5_unorm_description; + case PIPE_FORMAT_R10G10B10A2_UNORM: + return &util_format_r10g10b10a2_unorm_description; + case PIPE_FORMAT_B10G10R10A2_UNORM: + return &util_format_b10g10r10a2_unorm_description; + case PIPE_FORMAT_B2G3R3_UNORM: + return &util_format_b2g3r3_unorm_description; + case PIPE_FORMAT_L8_UNORM: + return &util_format_l8_unorm_description; + case PIPE_FORMAT_A8_UNORM: + return &util_format_a8_unorm_description; + case PIPE_FORMAT_I8_UNORM: + return &util_format_i8_unorm_description; + case PIPE_FORMAT_L4A4_UNORM: + return &util_format_l4a4_unorm_description; + case PIPE_FORMAT_L8A8_UNORM: + return &util_format_l8a8_unorm_description; + case PIPE_FORMAT_L16_UNORM: + return &util_format_l16_unorm_description; + case PIPE_FORMAT_A16_UNORM: + return &util_format_a16_unorm_description; + case PIPE_FORMAT_I16_UNORM: + return &util_format_i16_unorm_description; + case PIPE_FORMAT_L16A16_UNORM: + return &util_format_l16a16_unorm_description; + case PIPE_FORMAT_A8_SNORM: + return &util_format_a8_snorm_description; + case PIPE_FORMAT_L8_SNORM: + return &util_format_l8_snorm_description; + case PIPE_FORMAT_L8A8_SNORM: + return &util_format_l8a8_snorm_description; + case PIPE_FORMAT_I8_SNORM: + return &util_format_i8_snorm_description; + case PIPE_FORMAT_A16_SNORM: + return &util_format_a16_snorm_description; + case PIPE_FORMAT_L16_SNORM: + return &util_format_l16_snorm_description; + case PIPE_FORMAT_L16A16_SNORM: + return &util_format_l16a16_snorm_description; + case PIPE_FORMAT_I16_SNORM: + return &util_format_i16_snorm_description; + case PIPE_FORMAT_A16_FLOAT: + return &util_format_a16_float_description; + case PIPE_FORMAT_L16_FLOAT: + return &util_format_l16_float_description; + case PIPE_FORMAT_L16A16_FLOAT: + return &util_format_l16a16_float_description; + case PIPE_FORMAT_I16_FLOAT: + return &util_format_i16_float_description; + case PIPE_FORMAT_A32_FLOAT: + return &util_format_a32_float_description; + case PIPE_FORMAT_L32_FLOAT: + return &util_format_l32_float_description; + case PIPE_FORMAT_L32A32_FLOAT: + return &util_format_l32a32_float_description; + case PIPE_FORMAT_I32_FLOAT: + return &util_format_i32_float_description; + case PIPE_FORMAT_L8_SRGB: + return &util_format_l8_srgb_description; + case PIPE_FORMAT_L8A8_SRGB: + return &util_format_l8a8_srgb_description; + case PIPE_FORMAT_R8G8B8_SRGB: + return &util_format_r8g8b8_srgb_description; + case PIPE_FORMAT_R8G8B8A8_SRGB: + return &util_format_r8g8b8a8_srgb_description; + case PIPE_FORMAT_A8B8G8R8_SRGB: + return &util_format_a8b8g8r8_srgb_description; + case PIPE_FORMAT_X8B8G8R8_SRGB: + return &util_format_x8b8g8r8_srgb_description; + case PIPE_FORMAT_B8G8R8A8_SRGB: + return &util_format_b8g8r8a8_srgb_description; + case PIPE_FORMAT_B8G8R8X8_SRGB: + return &util_format_b8g8r8x8_srgb_description; + case PIPE_FORMAT_A8R8G8B8_SRGB: + return &util_format_a8r8g8b8_srgb_description; + case PIPE_FORMAT_X8R8G8B8_SRGB: + return &util_format_x8r8g8b8_srgb_description; + case PIPE_FORMAT_R8SG8SB8UX8U_NORM: + return &util_format_r8sg8sb8ux8u_norm_description; + case PIPE_FORMAT_R10SG10SB10SA2U_NORM: + return &util_format_r10sg10sb10sa2u_norm_description; + case PIPE_FORMAT_R5SG5SB6U_NORM: + return &util_format_r5sg5sb6u_norm_description; + case PIPE_FORMAT_S8_UINT: + return &util_format_s8_uint_description; + case PIPE_FORMAT_Z16_UNORM: + return &util_format_z16_unorm_description; + case PIPE_FORMAT_Z32_UNORM: + return &util_format_z32_unorm_description; + case PIPE_FORMAT_Z32_FLOAT: + return &util_format_z32_float_description; + case PIPE_FORMAT_Z24_UNORM_S8_UINT: + return &util_format_z24_unorm_s8_uint_description; + case PIPE_FORMAT_S8_UINT_Z24_UNORM: + return &util_format_s8_uint_z24_unorm_description; + case PIPE_FORMAT_X24S8_UINT: + return &util_format_x24s8_uint_description; + case PIPE_FORMAT_S8X24_UINT: + return &util_format_s8x24_uint_description; + case PIPE_FORMAT_Z24X8_UNORM: + return &util_format_z24x8_unorm_description; + case PIPE_FORMAT_X8Z24_UNORM: + return &util_format_x8z24_unorm_description; + case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: + return &util_format_z32_float_s8x24_uint_description; + case PIPE_FORMAT_X32_S8X24_UINT: + return &util_format_x32_s8x24_uint_description; + case PIPE_FORMAT_UYVY: + return &util_format_uyvy_description; + case PIPE_FORMAT_YUYV: + return &util_format_yuyv_description; + case PIPE_FORMAT_R8G8_B8G8_UNORM: + return &util_format_r8g8_b8g8_unorm_description; + case PIPE_FORMAT_G8R8_G8B8_UNORM: + return &util_format_g8r8_g8b8_unorm_description; + case PIPE_FORMAT_G8R8_B8R8_UNORM: + return &util_format_g8r8_b8r8_unorm_description; + case PIPE_FORMAT_R8G8_R8B8_UNORM: + return &util_format_r8g8_r8b8_unorm_description; + case PIPE_FORMAT_R11G11B10_FLOAT: + return &util_format_r11g11b10_float_description; + case PIPE_FORMAT_R9G9B9E5_FLOAT: + return &util_format_r9g9b9e5_float_description; + case PIPE_FORMAT_R1_UNORM: + return &util_format_r1_unorm_description; + case PIPE_FORMAT_R8G8Bx_SNORM: + return &util_format_r8g8bx_snorm_description; + case PIPE_FORMAT_DXT1_RGB: + return &util_format_dxt1_rgb_description; + case PIPE_FORMAT_DXT1_RGBA: + return &util_format_dxt1_rgba_description; + case PIPE_FORMAT_DXT3_RGBA: + return &util_format_dxt3_rgba_description; + case PIPE_FORMAT_DXT5_RGBA: + return &util_format_dxt5_rgba_description; + case PIPE_FORMAT_DXT1_SRGB: + return &util_format_dxt1_srgb_description; + case PIPE_FORMAT_DXT1_SRGBA: + return &util_format_dxt1_srgba_description; + case PIPE_FORMAT_DXT3_SRGBA: + return &util_format_dxt3_srgba_description; + case PIPE_FORMAT_DXT5_SRGBA: + return &util_format_dxt5_srgba_description; + case PIPE_FORMAT_RGTC1_UNORM: + return &util_format_rgtc1_unorm_description; + case PIPE_FORMAT_RGTC1_SNORM: + return &util_format_rgtc1_snorm_description; + case PIPE_FORMAT_RGTC2_UNORM: + return &util_format_rgtc2_unorm_description; + case PIPE_FORMAT_RGTC2_SNORM: + return &util_format_rgtc2_snorm_description; + case PIPE_FORMAT_LATC1_UNORM: + return &util_format_latc1_unorm_description; + case PIPE_FORMAT_LATC1_SNORM: + return &util_format_latc1_snorm_description; + case PIPE_FORMAT_LATC2_UNORM: + return &util_format_latc2_unorm_description; + case PIPE_FORMAT_LATC2_SNORM: + return &util_format_latc2_snorm_description; + case PIPE_FORMAT_ETC1_RGB8: + return &util_format_etc1_rgb8_description; + case PIPE_FORMAT_R64_FLOAT: + return &util_format_r64_float_description; + case PIPE_FORMAT_R64G64_FLOAT: + return &util_format_r64g64_float_description; + case PIPE_FORMAT_R64G64B64_FLOAT: + return &util_format_r64g64b64_float_description; + case PIPE_FORMAT_R64G64B64A64_FLOAT: + return &util_format_r64g64b64a64_float_description; + case PIPE_FORMAT_R32_FLOAT: + return &util_format_r32_float_description; + case PIPE_FORMAT_R32G32_FLOAT: + return &util_format_r32g32_float_description; + case PIPE_FORMAT_R32G32B32_FLOAT: + return &util_format_r32g32b32_float_description; + case PIPE_FORMAT_R32G32B32A32_FLOAT: + return &util_format_r32g32b32a32_float_description; + case PIPE_FORMAT_R32_UNORM: + return &util_format_r32_unorm_description; + case PIPE_FORMAT_R32G32_UNORM: + return &util_format_r32g32_unorm_description; + case PIPE_FORMAT_R32G32B32_UNORM: + return &util_format_r32g32b32_unorm_description; + case PIPE_FORMAT_R32G32B32A32_UNORM: + return &util_format_r32g32b32a32_unorm_description; + case PIPE_FORMAT_R32_USCALED: + return &util_format_r32_uscaled_description; + case PIPE_FORMAT_R32G32_USCALED: + return &util_format_r32g32_uscaled_description; + case PIPE_FORMAT_R32G32B32_USCALED: + return &util_format_r32g32b32_uscaled_description; + case PIPE_FORMAT_R32G32B32A32_USCALED: + return &util_format_r32g32b32a32_uscaled_description; + case PIPE_FORMAT_R32_SNORM: + return &util_format_r32_snorm_description; + case PIPE_FORMAT_R32G32_SNORM: + return &util_format_r32g32_snorm_description; + case PIPE_FORMAT_R32G32B32_SNORM: + return &util_format_r32g32b32_snorm_description; + case PIPE_FORMAT_R32G32B32A32_SNORM: + return &util_format_r32g32b32a32_snorm_description; + case PIPE_FORMAT_R32_SSCALED: + return &util_format_r32_sscaled_description; + case PIPE_FORMAT_R32G32_SSCALED: + return &util_format_r32g32_sscaled_description; + case PIPE_FORMAT_R32G32B32_SSCALED: + return &util_format_r32g32b32_sscaled_description; + case PIPE_FORMAT_R32G32B32A32_SSCALED: + return &util_format_r32g32b32a32_sscaled_description; + case PIPE_FORMAT_R16_FLOAT: + return &util_format_r16_float_description; + case PIPE_FORMAT_R16G16_FLOAT: + return &util_format_r16g16_float_description; + case PIPE_FORMAT_R16G16B16_FLOAT: + return &util_format_r16g16b16_float_description; + case PIPE_FORMAT_R16G16B16A16_FLOAT: + return &util_format_r16g16b16a16_float_description; + case PIPE_FORMAT_R16_UNORM: + return &util_format_r16_unorm_description; + case PIPE_FORMAT_R16G16_UNORM: + return &util_format_r16g16_unorm_description; + case PIPE_FORMAT_R16G16B16_UNORM: + return &util_format_r16g16b16_unorm_description; + case PIPE_FORMAT_R16G16B16A16_UNORM: + return &util_format_r16g16b16a16_unorm_description; + case PIPE_FORMAT_R16_USCALED: + return &util_format_r16_uscaled_description; + case PIPE_FORMAT_R16G16_USCALED: + return &util_format_r16g16_uscaled_description; + case PIPE_FORMAT_R16G16B16_USCALED: + return &util_format_r16g16b16_uscaled_description; + case PIPE_FORMAT_R16G16B16A16_USCALED: + return &util_format_r16g16b16a16_uscaled_description; + case PIPE_FORMAT_R16_SNORM: + return &util_format_r16_snorm_description; + case PIPE_FORMAT_R16G16_SNORM: + return &util_format_r16g16_snorm_description; + case PIPE_FORMAT_R16G16B16_SNORM: + return &util_format_r16g16b16_snorm_description; + case PIPE_FORMAT_R16G16B16A16_SNORM: + return &util_format_r16g16b16a16_snorm_description; + case PIPE_FORMAT_R16_SSCALED: + return &util_format_r16_sscaled_description; + case PIPE_FORMAT_R16G16_SSCALED: + return &util_format_r16g16_sscaled_description; + case PIPE_FORMAT_R16G16B16_SSCALED: + return &util_format_r16g16b16_sscaled_description; + case PIPE_FORMAT_R16G16B16A16_SSCALED: + return &util_format_r16g16b16a16_sscaled_description; + case PIPE_FORMAT_R8_UNORM: + return &util_format_r8_unorm_description; + case PIPE_FORMAT_R8G8_UNORM: + return &util_format_r8g8_unorm_description; + case PIPE_FORMAT_R8G8B8_UNORM: + return &util_format_r8g8b8_unorm_description; + case PIPE_FORMAT_R8G8B8A8_UNORM: + return &util_format_r8g8b8a8_unorm_description; + case PIPE_FORMAT_R8_USCALED: + return &util_format_r8_uscaled_description; + case PIPE_FORMAT_R8G8_USCALED: + return &util_format_r8g8_uscaled_description; + case PIPE_FORMAT_R8G8B8_USCALED: + return &util_format_r8g8b8_uscaled_description; + case PIPE_FORMAT_R8G8B8A8_USCALED: + return &util_format_r8g8b8a8_uscaled_description; + case PIPE_FORMAT_R8_SNORM: + return &util_format_r8_snorm_description; + case PIPE_FORMAT_R8G8_SNORM: + return &util_format_r8g8_snorm_description; + case PIPE_FORMAT_R8G8B8_SNORM: + return &util_format_r8g8b8_snorm_description; + case PIPE_FORMAT_R8G8B8A8_SNORM: + return &util_format_r8g8b8a8_snorm_description; + case PIPE_FORMAT_R8_SSCALED: + return &util_format_r8_sscaled_description; + case PIPE_FORMAT_R8G8_SSCALED: + return &util_format_r8g8_sscaled_description; + case PIPE_FORMAT_R8G8B8_SSCALED: + return &util_format_r8g8b8_sscaled_description; + case PIPE_FORMAT_R8G8B8A8_SSCALED: + return &util_format_r8g8b8a8_sscaled_description; + case PIPE_FORMAT_R32_FIXED: + return &util_format_r32_fixed_description; + case PIPE_FORMAT_R32G32_FIXED: + return &util_format_r32g32_fixed_description; + case PIPE_FORMAT_R32G32B32_FIXED: + return &util_format_r32g32b32_fixed_description; + case PIPE_FORMAT_R32G32B32A32_FIXED: + return &util_format_r32g32b32a32_fixed_description; + case PIPE_FORMAT_R10G10B10X2_USCALED: + return &util_format_r10g10b10x2_uscaled_description; + case PIPE_FORMAT_R10G10B10X2_SNORM: + return &util_format_r10g10b10x2_snorm_description; + case PIPE_FORMAT_YV12: + return &util_format_yv12_description; + case PIPE_FORMAT_YV16: + return &util_format_yv16_description; + case PIPE_FORMAT_IYUV: + return &util_format_iyuv_description; + case PIPE_FORMAT_NV12: + return &util_format_nv12_description; + case PIPE_FORMAT_NV21: + return &util_format_nv21_description; + case PIPE_FORMAT_R4A4_UNORM: + return &util_format_r4a4_unorm_description; + case PIPE_FORMAT_A4R4_UNORM: + return &util_format_a4r4_unorm_description; + case PIPE_FORMAT_R8A8_UNORM: + return &util_format_r8a8_unorm_description; + case PIPE_FORMAT_A8R8_UNORM: + return &util_format_a8r8_unorm_description; + case PIPE_FORMAT_R10G10B10A2_USCALED: + return &util_format_r10g10b10a2_uscaled_description; + case PIPE_FORMAT_R10G10B10A2_SSCALED: + return &util_format_r10g10b10a2_sscaled_description; + case PIPE_FORMAT_R10G10B10A2_SNORM: + return &util_format_r10g10b10a2_snorm_description; + case PIPE_FORMAT_B10G10R10A2_USCALED: + return &util_format_b10g10r10a2_uscaled_description; + case PIPE_FORMAT_B10G10R10A2_SSCALED: + return &util_format_b10g10r10a2_sscaled_description; + case PIPE_FORMAT_B10G10R10A2_SNORM: + return &util_format_b10g10r10a2_snorm_description; + case PIPE_FORMAT_R8_UINT: + return &util_format_r8_uint_description; + case PIPE_FORMAT_R8G8_UINT: + return &util_format_r8g8_uint_description; + case PIPE_FORMAT_R8G8B8_UINT: + return &util_format_r8g8b8_uint_description; + case PIPE_FORMAT_R8G8B8A8_UINT: + return &util_format_r8g8b8a8_uint_description; + case PIPE_FORMAT_R8_SINT: + return &util_format_r8_sint_description; + case PIPE_FORMAT_R8G8_SINT: + return &util_format_r8g8_sint_description; + case PIPE_FORMAT_R8G8B8_SINT: + return &util_format_r8g8b8_sint_description; + case PIPE_FORMAT_R8G8B8A8_SINT: + return &util_format_r8g8b8a8_sint_description; + case PIPE_FORMAT_R16_UINT: + return &util_format_r16_uint_description; + case PIPE_FORMAT_R16G16_UINT: + return &util_format_r16g16_uint_description; + case PIPE_FORMAT_R16G16B16_UINT: + return &util_format_r16g16b16_uint_description; + case PIPE_FORMAT_R16G16B16A16_UINT: + return &util_format_r16g16b16a16_uint_description; + case PIPE_FORMAT_R16_SINT: + return &util_format_r16_sint_description; + case PIPE_FORMAT_R16G16_SINT: + return &util_format_r16g16_sint_description; + case PIPE_FORMAT_R16G16B16_SINT: + return &util_format_r16g16b16_sint_description; + case PIPE_FORMAT_R16G16B16A16_SINT: + return &util_format_r16g16b16a16_sint_description; + case PIPE_FORMAT_R32_UINT: + return &util_format_r32_uint_description; + case PIPE_FORMAT_R32G32_UINT: + return &util_format_r32g32_uint_description; + case PIPE_FORMAT_R32G32B32_UINT: + return &util_format_r32g32b32_uint_description; + case PIPE_FORMAT_R32G32B32A32_UINT: + return &util_format_r32g32b32a32_uint_description; + case PIPE_FORMAT_R32_SINT: + return &util_format_r32_sint_description; + case PIPE_FORMAT_R32G32_SINT: + return &util_format_r32g32_sint_description; + case PIPE_FORMAT_R32G32B32_SINT: + return &util_format_r32g32b32_sint_description; + case PIPE_FORMAT_R32G32B32A32_SINT: + return &util_format_r32g32b32a32_sint_description; + case PIPE_FORMAT_A8_UINT: + return &util_format_a8_uint_description; + case PIPE_FORMAT_I8_UINT: + return &util_format_i8_uint_description; + case PIPE_FORMAT_L8_UINT: + return &util_format_l8_uint_description; + case PIPE_FORMAT_L8A8_UINT: + return &util_format_l8a8_uint_description; + case PIPE_FORMAT_A8_SINT: + return &util_format_a8_sint_description; + case PIPE_FORMAT_I8_SINT: + return &util_format_i8_sint_description; + case PIPE_FORMAT_L8_SINT: + return &util_format_l8_sint_description; + case PIPE_FORMAT_L8A8_SINT: + return &util_format_l8a8_sint_description; + case PIPE_FORMAT_A16_UINT: + return &util_format_a16_uint_description; + case PIPE_FORMAT_I16_UINT: + return &util_format_i16_uint_description; + case PIPE_FORMAT_L16_UINT: + return &util_format_l16_uint_description; + case PIPE_FORMAT_L16A16_UINT: + return &util_format_l16a16_uint_description; + case PIPE_FORMAT_A16_SINT: + return &util_format_a16_sint_description; + case PIPE_FORMAT_I16_SINT: + return &util_format_i16_sint_description; + case PIPE_FORMAT_L16_SINT: + return &util_format_l16_sint_description; + case PIPE_FORMAT_L16A16_SINT: + return &util_format_l16a16_sint_description; + case PIPE_FORMAT_A32_UINT: + return &util_format_a32_uint_description; + case PIPE_FORMAT_I32_UINT: + return &util_format_i32_uint_description; + case PIPE_FORMAT_L32_UINT: + return &util_format_l32_uint_description; + case PIPE_FORMAT_L32A32_UINT: + return &util_format_l32a32_uint_description; + case PIPE_FORMAT_A32_SINT: + return &util_format_a32_sint_description; + case PIPE_FORMAT_I32_SINT: + return &util_format_i32_sint_description; + case PIPE_FORMAT_L32_SINT: + return &util_format_l32_sint_description; + case PIPE_FORMAT_L32A32_SINT: + return &util_format_l32a32_sint_description; + case PIPE_FORMAT_B10G10R10A2_UINT: + return &util_format_b10g10r10a2_uint_description; + case PIPE_FORMAT_R8G8B8X8_SNORM: + return &util_format_r8g8b8x8_snorm_description; + case PIPE_FORMAT_R8G8B8X8_SRGB: + return &util_format_r8g8b8x8_srgb_description; + case PIPE_FORMAT_R8G8B8X8_UINT: + return &util_format_r8g8b8x8_uint_description; + case PIPE_FORMAT_R8G8B8X8_SINT: + return &util_format_r8g8b8x8_sint_description; + case PIPE_FORMAT_B10G10R10X2_UNORM: + return &util_format_b10g10r10x2_unorm_description; + case PIPE_FORMAT_R16G16B16X16_UNORM: + return &util_format_r16g16b16x16_unorm_description; + case PIPE_FORMAT_R16G16B16X16_SNORM: + return &util_format_r16g16b16x16_snorm_description; + case PIPE_FORMAT_R16G16B16X16_FLOAT: + return &util_format_r16g16b16x16_float_description; + case PIPE_FORMAT_R16G16B16X16_UINT: + return &util_format_r16g16b16x16_uint_description; + case PIPE_FORMAT_R16G16B16X16_SINT: + return &util_format_r16g16b16x16_sint_description; + case PIPE_FORMAT_R32G32B32X32_FLOAT: + return &util_format_r32g32b32x32_float_description; + case PIPE_FORMAT_R32G32B32X32_UINT: + return &util_format_r32g32b32x32_uint_description; + case PIPE_FORMAT_R32G32B32X32_SINT: + return &util_format_r32g32b32x32_sint_description; + case PIPE_FORMAT_R8A8_SNORM: + return &util_format_r8a8_snorm_description; + case PIPE_FORMAT_R16A16_UNORM: + return &util_format_r16a16_unorm_description; + case PIPE_FORMAT_R16A16_SNORM: + return &util_format_r16a16_snorm_description; + case PIPE_FORMAT_R16A16_FLOAT: + return &util_format_r16a16_float_description; + case PIPE_FORMAT_R32A32_FLOAT: + return &util_format_r32a32_float_description; + case PIPE_FORMAT_R8A8_UINT: + return &util_format_r8a8_uint_description; + case PIPE_FORMAT_R8A8_SINT: + return &util_format_r8a8_sint_description; + case PIPE_FORMAT_R16A16_UINT: + return &util_format_r16a16_uint_description; + case PIPE_FORMAT_R16A16_SINT: + return &util_format_r16a16_sint_description; + case PIPE_FORMAT_R32A32_UINT: + return &util_format_r32a32_uint_description; + case PIPE_FORMAT_R32A32_SINT: + return &util_format_r32a32_sint_description; + case PIPE_FORMAT_R10G10B10A2_UINT: + return &util_format_r10g10b10a2_uint_description; + default: + return NULL; + } +} + diff --git a/src/gallium/auxiliary/util/u_format_yuv.h b/src/gallium/auxiliary/util/u_format_yuv.h new file mode 100644 index 0000000..4ec3981 --- /dev/null +++ b/src/gallium/auxiliary/util/u_format_yuv.h @@ -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 + * @author Michal Krol + * @author Jose Fonseca + * + * 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_ */ diff --git a/src/gallium/auxiliary/util/u_format_zs.h b/src/gallium/auxiliary/util/u_format_zs.h new file mode 100644 index 0000000..adddfaf --- /dev/null +++ b/src/gallium/auxiliary/util/u_format_zs.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_ */ diff --git a/src/gallium/auxiliary/util/u_half.h b/src/gallium/auxiliary/util/u_half.h new file mode 100644 index 0000000..d340b9a --- /dev/null +++ b/src/gallium/auxiliary/util/u_half.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 */ + diff --git a/src/gallium/auxiliary/util/u_hash_table.h b/src/gallium/auxiliary/util/u_hash_table.h new file mode 100644 index 0000000..9431761 --- /dev/null +++ b/src/gallium/auxiliary/util/u_hash_table.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 + */ + +#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_ */ diff --git a/src/gallium/auxiliary/util/u_inlines.h b/src/gallium/auxiliary/util/u_inlines.h new file mode 100644 index 0000000..e952615 --- /dev/null +++ b/src/gallium/auxiliary/util/u_inlines.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 */ diff --git a/src/gallium/auxiliary/util/u_math.h b/src/gallium/auxiliary/util/u_math.h new file mode 100644 index 0000000..ffbcc4c --- /dev/null +++ b/src/gallium/auxiliary/util/u_math.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 +#include +#include + +#ifdef PIPE_OS_UNIX +#include /* 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<MEMBER)) + + + +#ifdef __cplusplus +} +#endif + + +#endif /* U_MEMORY_H */ diff --git a/src/gallium/auxiliary/util/u_pack_color.h b/src/gallium/auxiliary/util/u_pack_color.h new file mode 100644 index 0000000..166c68b --- /dev/null +++ b/src/gallium/auxiliary/util/u_pack_color.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 */ diff --git a/src/gallium/auxiliary/util/u_pointer.h b/src/gallium/auxiliary/util/u_pointer.h new file mode 100644 index 0000000..30c23b7 --- /dev/null +++ b/src/gallium/auxiliary/util/u_pointer.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 */ diff --git a/src/gallium/auxiliary/util/u_prim.h b/src/gallium/auxiliary/util/u_prim.h new file mode 100644 index 0000000..fd95c0b --- /dev/null +++ b/src/gallium/auxiliary/util/u_prim.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 diff --git a/src/gallium/auxiliary/util/u_string.h b/src/gallium/auxiliary/util/u_string.h new file mode 100644 index 0000000..dc89c44 --- /dev/null +++ b/src/gallium/auxiliary/util/u_string.h @@ -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 + */ + +#ifndef U_STRING_H_ +#define U_STRING_H_ + +#if !defined(_MSC_VER) && !defined(XF86_LIBC_H) +#include +#endif +#include +#include + +#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_ */ diff --git a/src/gallium/auxiliary/util/u_surface.h b/src/gallium/auxiliary/util/u_surface.h new file mode 100644 index 0000000..bfd8f40 --- /dev/null +++ b/src/gallium/auxiliary/util/u_surface.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 */ diff --git a/src/gallium/auxiliary/util/u_tile.h b/src/gallium/auxiliary/util/u_tile.h new file mode 100644 index 0000000..a33d7f7 --- /dev/null +++ b/src/gallium/auxiliary/util/u_tile.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 diff --git a/src/gallium/auxiliary/util/u_transfer.h b/src/gallium/auxiliary/util/u_transfer.h new file mode 100644 index 0000000..6c25ee0 --- /dev/null +++ b/src/gallium/auxiliary/util/u_transfer.h @@ -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 diff --git a/src/graw_cursor.c b/src/graw_cursor.c new file mode 100644 index 0000000..98165f4 --- /dev/null +++ b/src/graw_cursor.c @@ -0,0 +1,162 @@ +#include +#include +#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; +} diff --git a/src/graw_cursor.h b/src/graw_cursor.h new file mode 100644 index 0000000..bba1301 --- /dev/null +++ b/src/graw_cursor.h @@ -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 diff --git a/src/graw_decode.c b/src/graw_decode.c new file mode 100644 index 0000000..9c47235 --- /dev/null +++ b/src/graw_decode.c @@ -0,0 +1,911 @@ +#include +#include +#include +#include + +#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); + +} + diff --git a/src/graw_decode.h b/src/graw_decode.h new file mode 100644 index 0000000..e89cdea --- /dev/null +++ b/src/graw_decode.h @@ -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 diff --git a/src/graw_formats.c b/src/graw_formats.c new file mode 100644 index 0000000..30c7465 --- /dev/null +++ b/src/graw_formats.c @@ -0,0 +1,307 @@ +#include + +#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); + +} diff --git a/src/graw_iov.h b/src/graw_iov.h new file mode 100644 index 0000000..c6ab870 --- /dev/null +++ b/src/graw_iov.h @@ -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 diff --git a/src/graw_renderer.c b/src/graw_renderer.c new file mode 100644 index 0000000..259a5bc --- /dev/null +++ b/src/graw_renderer.c @@ -0,0 +1,4486 @@ +#include + +#include +#include "pipe/p_shader_tokens.h" + +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_screen.h" +#include "pipe/p_state.h" +#include "util/u_inlines.h" +#include "util/u_memory.h" +#include "util/u_transfer.h" +#include "util/u_double_list.h" +#include "util/u_format.h" +#include "tgsi/tgsi_text.h" +#include "tgsi/tgsi_info.h" +#include "tgsi/tgsi_parse.h" + +#include "vrend_object.h" +#include "graw_shader.h" + +#include "graw_renderer.h" +#include "graw_decode.h" +#include "graw_cursor.h" + +#include "virgl_hw.h" +/* transfer boxes from the guest POV are in y = 0 = top orientation */ +/* blit/copy operations from the guest POV are in y = 0 = top orientation */ + +/* since we are storing things in OpenGL FBOs we need to flip transfer operations by default */ +static void grend_update_viewport_state(struct grend_context *ctx); +static void grend_update_scissor_state(struct grend_context *ctx); +static void grend_ctx_restart_queries(struct grend_context *ctx); +static void grend_destroy_query_object(void *obj_ptr); +static void grend_finish_context_switch(struct grend_context *ctx); +static void grend_patch_blend_func(struct grend_context *ctx); +static void grend_update_frontface_state(struct grend_context *ctx); + +extern int graw_shader_use_explicit; +int localrender; +static int have_invert_mesa = 0; +static int draw_cursor = 0; +int vrend_dump_shaders; + +static struct grend_if_cbs *clicbs; + +struct grend_fence { + uint32_t fence_id; + uint32_t ctx_id; + GLsync syncobj; + struct list_head fences; +}; + +struct grend_nontimer_hw_query { + struct list_head query_list; + GLuint id; + uint64_t result; +}; + +struct grend_query { + struct list_head waiting_queries; + struct list_head ctx_queries; + + struct list_head hw_queries; + GLuint timer_query_id; + GLuint type; + GLuint gltype; + int ctx_id; + struct grend_resource *res; + uint64_t current_total; + boolean active_hw; +}; + +#define VIRGL_INVALID_RESOURCE 1 +struct global_error_state { + enum virgl_errors last_error; +}; + +struct global_renderer_state { + bool viewport_dirty; + bool scissor_dirty; + GLboolean blend_enabled; + GLboolean depth_test_enabled; + GLboolean alpha_test_enabled; + GLboolean stencil_test_enabled; + GLuint program_id; + struct list_head fence_list; + struct grend_context *current_ctx; + struct grend_context *current_hw_ctx; + struct list_head waiting_query_list; + + struct graw_cursor_info cursor_info; + boolean have_robustness; + boolean have_multisample; + GLuint vaoid; + + struct pipe_rasterizer_state hw_rs_state; + struct pipe_depth_stencil_alpha_state hw_dsa_state; + struct pipe_blend_state hw_blend_state; + + boolean have_nv_prim_restart, have_gl_prim_restart, have_bit_encoding; +}; + +static struct global_renderer_state grend_state; + +struct grend_linked_shader_program { + struct list_head head; + GLuint id; + + struct grend_shader *ss[PIPE_SHADER_TYPES]; + + uint32_t samplers_used_mask[PIPE_SHADER_TYPES]; + GLuint *samp_locs[PIPE_SHADER_TYPES]; + + GLuint *shadow_samp_mask_locs[PIPE_SHADER_TYPES]; + GLuint *shadow_samp_add_locs[PIPE_SHADER_TYPES]; + + GLuint *const_locs[PIPE_SHADER_TYPES]; + + GLuint *attrib_locs; + uint32_t shadow_samp_mask[PIPE_SHADER_TYPES]; + + GLuint vs_ws_adjust_loc; +}; + +struct grend_shader { + struct grend_shader *next_variant; + struct grend_shader_selector *sel; + + GLchar *glsl_prog; + GLuint id; + GLuint compiled_fs_id; + struct vrend_shader_key key; +}; + +struct grend_shader_selector { + struct pipe_reference reference; + struct grend_shader *current; + struct tgsi_token *tokens; + + struct vrend_shader_info sinfo; + + unsigned num_shaders; + unsigned type; +}; + +struct grend_buffer { + struct grend_resource base; +}; + +struct grend_texture { + struct grend_resource base; + struct pipe_sampler_state state; + GLenum cur_swizzle_r; + GLenum cur_swizzle_g; + GLenum cur_swizzle_b; + GLenum cur_swizzle_a; + GLuint srgb_decode; +}; + +struct grend_surface { + struct pipe_reference reference; + GLuint id; + GLuint res_handle; + GLuint format; + GLuint val0, val1; + struct grend_resource *texture; +}; + +struct grend_sampler { + +}; + +struct grend_so_target { + struct pipe_reference reference; + GLuint res_handle; + unsigned buffer_offset; + unsigned buffer_size; + struct grend_resource *buffer; +}; + +struct grend_sampler_view { + struct pipe_reference reference; + GLuint id; + GLuint res_handle; + GLuint format; + GLuint val0, val1; + GLuint swizzle_r:3; + GLuint swizzle_g:3; + GLuint swizzle_b:3; + GLuint swizzle_a:3; + GLuint gl_swizzle_r; + GLuint gl_swizzle_g; + GLuint gl_swizzle_b; + GLuint gl_swizzle_a; + GLuint cur_base, cur_max; + struct grend_resource *texture; + GLenum depth_texture_mode; + GLuint srgb_decode; +}; + +struct grend_vertex_element { + struct pipe_vertex_element base; + GLenum type; + GLboolean norm; + GLuint nr_chan; +}; + +struct grend_vertex_element_array { + unsigned count; + struct grend_vertex_element elements[PIPE_MAX_ATTRIBS]; +}; + +struct grend_constants { + float *consts; + uint32_t num_consts; +}; + +struct grend_shader_view { + int num_views; + struct grend_sampler_view *views[PIPE_MAX_SHADER_SAMPLER_VIEWS]; + uint32_t res_id[PIPE_MAX_SHADER_SAMPLER_VIEWS]; + uint32_t old_ids[PIPE_MAX_SHADER_SAMPLER_VIEWS]; +}; + +struct grend_context { + char debug_name[64]; + + virgl_gl_context gl_context; + + int ctx_id; + GLuint vaoid; + + uint32_t enabled_attribs_bitmask; + + struct util_hash_table *object_hash; + struct grend_vertex_element_array *ve; + int num_vbos; + struct pipe_vertex_buffer vbo[PIPE_MAX_ATTRIBS]; + uint32_t vbo_res_ids[PIPE_MAX_ATTRIBS]; + struct grend_shader_selector *vs; + struct grend_shader_selector *fs; + + bool shader_dirty; + struct grend_linked_shader_program *prog; + + struct grend_shader_view views[PIPE_SHADER_TYPES]; + + struct pipe_index_buffer ib; + uint32_t index_buffer_res_id; + + struct grend_constants consts[PIPE_SHADER_TYPES]; + bool const_dirty[PIPE_SHADER_TYPES]; + struct pipe_sampler_state *sampler_state[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS]; + + int num_sampler_states[PIPE_SHADER_TYPES]; + boolean sampler_state_dirty; + + uint8_t stencil_refs[2]; + + struct pipe_depth_stencil_alpha_state *dsa; + boolean stencil_state_dirty; + struct list_head programs; + + GLint view_cur_x, view_cur_y; + GLsizei view_width, view_height; + GLclampd view_near_val, view_far_val; + float depth_transform, depth_scale; + /* viewport is negative */ + GLboolean viewport_is_negative; + /* this is set if the contents of the FBO look upside down when viewed + with 0,0 as the bottom corner */ + GLboolean inverted_fbo_content; + boolean scissor_state_dirty; + boolean viewport_state_dirty; + uint32_t fb_height; + + uint32_t fb_id; + int nr_cbufs, old_nr_cbufs; + struct grend_surface *zsurf; + struct grend_surface *surf[8]; + + struct pipe_scissor_state ss; + + struct pipe_blend_state blend_state; + struct pipe_depth_stencil_alpha_state dsa_state; + struct pipe_rasterizer_state rs_state; + + struct pipe_blend_color blend_color; + + int num_so_targets; + struct grend_so_target *so_targets[16]; + + struct list_head active_nontimer_query_list; + boolean query_on_hw; + + /* has this ctx gotten an error? */ + boolean in_error; + enum virgl_ctx_errors last_error; + + boolean ctx_switch_pending; + GLuint blit_fb_ids[2]; +}; + +static struct grend_nontimer_hw_query *grend_create_hw_query(struct grend_query *query); + +#define MAX_SCANOUT 4 +static struct grend_resource *frontbuffer[MAX_SCANOUT]; +static struct pipe_box front_box[MAX_SCANOUT]; +static struct grend_format_table tex_conv_table[VIRGL_FORMAT_MAX]; + +static INLINE boolean vrend_format_can_render(enum virgl_formats format) +{ + return tex_conv_table[format].bindings & VREND_BIND_RENDER; +} + +static INLINE boolean vrend_format_is_ds(enum virgl_formats format) +{ + return tex_conv_table[format].bindings & VREND_BIND_DEPTHSTENCIL; +} + +static const char *vrend_ctx_error_strings[] = { "None", "Unknown", "Illegal shader", "Illegal handle", "Illegal resource", "Illegal surface", "Illegal vertex format" }; + +static void __report_context_error(const char *fname, struct grend_context *ctx, enum virgl_ctx_errors error, uint32_t value) +{ + ctx->in_error = TRUE; + ctx->last_error = error; + fprintf(stderr,"%s: context error reported %d \"%s\" %s %d\n", fname, ctx->ctx_id, ctx->debug_name, vrend_ctx_error_strings[error], value); +} +#define report_context_error(ctx, error, value) __report_context_error(__func__, ctx, error, value) + +static INLINE boolean should_invert_viewport(struct grend_context *ctx) +{ + /* if we have a negative viewport then gallium wanted to invert it, + however since we are rendering to GL FBOs we need to invert it + again unless we are rendering upside down already + - confused? + so if gallium asks for a negative viewport */ + return !(ctx->viewport_is_negative ^ ctx->inverted_fbo_content); +} + +static void grend_destroy_surface(struct grend_surface *surf) +{ + grend_resource_reference(&surf->texture, NULL); + free(surf); +} + +static INLINE void +grend_surface_reference(struct grend_surface **ptr, struct grend_surface *surf) +{ + struct grend_surface *old_surf = *ptr; + + if (pipe_reference(&(*ptr)->reference, &surf->reference)) + grend_destroy_surface(old_surf); + *ptr = surf; +} + +static void grend_destroy_sampler_view(struct grend_sampler_view *samp) +{ + grend_resource_reference(&samp->texture, NULL); + free(samp); +} + +static INLINE void +grend_sampler_view_reference(struct grend_sampler_view **ptr, struct grend_sampler_view *view) +{ + struct grend_sampler_view *old_view = *ptr; + + if (pipe_reference(&(*ptr)->reference, &view->reference)) + grend_destroy_sampler_view(old_view); + *ptr = view; +} + +static void grend_destroy_so_target(struct grend_so_target *target) +{ + grend_resource_reference(&target->buffer, NULL); + free(target); +} + +static INLINE void +grend_so_target_reference(struct grend_so_target **ptr, struct grend_so_target *target) +{ + struct grend_so_target *old_target = *ptr; + + if (pipe_reference(&(*ptr)->reference, &target->reference)) + grend_destroy_so_target(old_target); + *ptr = target; +} + +static void grend_shader_destroy(struct grend_shader *shader) +{ + glDeleteShader(shader->id); + free(shader->glsl_prog); + free(shader); +} + +static void grend_destroy_shader_selector(struct grend_shader_selector *sel) +{ + struct grend_shader *p = sel->current, *c; + + while (p) { + c = p->next_variant; + grend_shader_destroy(p); + p = c; + } + free(sel->sinfo.interpinfo); + free(sel->tokens); + free(sel); +} + +static boolean grend_compile_shader(struct grend_context *ctx, + struct grend_shader *shader) +{ + GLint param; + glShaderSource(shader->id, 1, (const char **)&shader->glsl_prog, NULL); + glCompileShader(shader->id); + glGetShaderiv(shader->id, GL_COMPILE_STATUS, ¶m); + if (param == GL_FALSE) { + char infolog[65536]; + int len; + glGetShaderInfoLog(shader->id, 65536, &len, infolog); + report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_SHADER, 0); + fprintf(stderr,"shader failed to compile\n%s\n", infolog); + fprintf(stderr,"GLSL:\n%s\n", shader->glsl_prog); + return FALSE; + } + return TRUE; +} + +static INLINE void +grend_shader_state_reference(struct grend_shader_selector **ptr, struct grend_shader_selector *shader) +{ + struct grend_shader_selector *old_shader = *ptr; + + if (pipe_reference(&(*ptr)->reference, &shader->reference)) + grend_destroy_shader_selector(old_shader); + *ptr = shader; +} + +void +grend_insert_format(struct grend_format_table *entry, uint32_t bindings) +{ + tex_conv_table[entry->format] = *entry; + tex_conv_table[entry->format].bindings = bindings; +} + +static boolean grend_is_timer_query(GLenum gltype) +{ + return gltype == GL_TIMESTAMP || + gltype == GL_TIME_ELAPSED; +} + +void grend_use_program(GLuint program_id) +{ + if (grend_state.program_id != program_id) { + glUseProgram(program_id); + grend_state.program_id = program_id; + } +} + +void grend_bind_va(GLuint vaoid) +{ + glBindVertexArray(vaoid); +} + +void grend_blend_enable(GLboolean blend_enable) +{ + if (grend_state.blend_enabled != blend_enable) { + grend_state.blend_enabled = blend_enable; + if (blend_enable) + glEnable(GL_BLEND); + else + glDisable(GL_BLEND); + } +} + +void grend_depth_test_enable(GLboolean depth_test_enable) +{ + if (grend_state.depth_test_enabled != depth_test_enable) { + grend_state.depth_test_enabled = depth_test_enable; + if (depth_test_enable) + glEnable(GL_DEPTH_TEST); + else + glDisable(GL_DEPTH_TEST); + } +} + +static void grend_alpha_test_enable(GLboolean alpha_test_enable) +{ + if (grend_state.alpha_test_enabled != alpha_test_enable) { + grend_state.alpha_test_enabled = alpha_test_enable; + if (alpha_test_enable) + glEnable(GL_ALPHA_TEST); + else + glDisable(GL_ALPHA_TEST); + } +} +static void grend_stencil_test_enable(GLboolean stencil_test_enable) +{ + if (grend_state.stencil_test_enabled != stencil_test_enable) { + grend_state.stencil_test_enabled = stencil_test_enable; + if (stencil_test_enable) + glEnable(GL_STENCIL_TEST); + else + glDisable(GL_STENCIL_TEST); + } +} + +static void set_stream_out_varyings(int prog_id, struct pipe_stream_output_info *vs_so) +{ + char *varyings[PIPE_MAX_SHADER_OUTPUTS]; + char tmp[64]; + int i; + if (!vs_so->num_outputs) + return; + + for (i = 0; i < vs_so->num_outputs; i++) { + snprintf(tmp, 64, "tfout%d", i); + + varyings[i] = strdup(tmp); + } + + glTransformFeedbackVaryings(prog_id, vs_so->num_outputs, + (const GLchar **)varyings, GL_INTERLEAVED_ATTRIBS_EXT); + + for (i = 0; i < vs_so->num_outputs; i++) + if (varyings[i]) + free(varyings[i]); +} + +static struct grend_linked_shader_program *add_shader_program(struct grend_context *ctx, + struct grend_shader *vs, + struct grend_shader *fs) +{ + struct grend_linked_shader_program *sprog = malloc(sizeof(struct grend_linked_shader_program)); + char name[16]; + int i; + GLuint prog_id; + GLint lret; + int id; + + /* need to rewrite VS code to add interpolation params */ + if (!vs->compiled_fs_id != fs->id) { + vrend_patch_vertex_shader_interpolants(vs->glsl_prog, + &vs->sel->sinfo, + &fs->sel->sinfo); + boolean ret; + ret = grend_compile_shader(ctx, vs); + if (ret == FALSE) { + glDeleteShader(vs->id); + free(sprog); + return NULL; + } + vs->compiled_fs_id = fs->id; + } + + prog_id = glCreateProgram(); + glAttachShader(prog_id, vs->id); + set_stream_out_varyings(prog_id, &vs->sel->sinfo.so_info); + glAttachShader(prog_id, fs->id); + glLinkProgram(prog_id); + + glGetProgramiv(prog_id, GL_LINK_STATUS, &lret); + if (lret == GL_FALSE) { + char infolog[65536]; + int len; + glGetProgramInfoLog(prog_id, 65536, &len, infolog); + fprintf(stderr,"got error linking\n%s\n", infolog); + /* dump shaders */ + report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_SHADER, 0); + fprintf(stderr,"vert shader: GLSL\n%s\n", vs->glsl_prog); + fprintf(stderr,"frag shader: GLSL\n%s\n", fs->glsl_prog); + glDeleteProgram(prog_id); + return NULL; + } + + sprog->ss[0] = vs; + sprog->ss[1] = fs; + + sprog->id = prog_id; + + list_add(&sprog->head, &ctx->programs); + + sprog->vs_ws_adjust_loc = glGetUniformLocation(prog_id, "winsys_adjust"); + for (id = PIPE_SHADER_VERTEX; id <= PIPE_SHADER_FRAGMENT; id++) { + if (sprog->ss[id]->sel->sinfo.samplers_used_mask) { + uint32_t mask = sprog->ss[id]->sel->sinfo.samplers_used_mask; + int nsamp = util_bitcount(sprog->ss[id]->sel->sinfo.samplers_used_mask); + int index; + sprog->shadow_samp_mask[id] = sprog->ss[id]->sel->sinfo.shadow_samp_mask; + if (sprog->ss[id]->sel->sinfo.shadow_samp_mask) { + sprog->shadow_samp_mask_locs[id] = calloc(nsamp, sizeof(uint32_t)); + sprog->shadow_samp_add_locs[id] = calloc(nsamp, sizeof(uint32_t)); + } else { + sprog->shadow_samp_mask_locs[id] = sprog->shadow_samp_add_locs[id] = NULL; + } + sprog->samp_locs[id] = calloc(nsamp, sizeof(uint32_t)); + if (sprog->samp_locs[id]) { + const char *prefix = (id == PIPE_SHADER_VERTEX) ? "vs" : "fs"; + index = 0; + while(mask) { + i = u_bit_scan(&mask); + snprintf(name, 10, "%ssamp%d", prefix, i); + sprog->samp_locs[id][index] = glGetUniformLocation(prog_id, name); + if (sprog->ss[id]->sel->sinfo.shadow_samp_mask & (1 << i)) { + snprintf(name, 14, "%sshadmask%d", prefix, i); + sprog->shadow_samp_mask_locs[id][index] = glGetUniformLocation(prog_id, name); + snprintf(name, 14, "%sshadadd%d", prefix, i); + sprog->shadow_samp_add_locs[id][index] = glGetUniformLocation(prog_id, name); + } + index++; + } + } + } else { + sprog->samp_locs[id] = NULL; + sprog->shadow_samp_mask_locs[id] = NULL; + sprog->shadow_samp_add_locs[id] = NULL; + sprog->shadow_samp_mask[id] = 0; + } + sprog->samplers_used_mask[id] = sprog->ss[id]->sel->sinfo.samplers_used_mask; + } + + for (id = PIPE_SHADER_VERTEX; id <= PIPE_SHADER_FRAGMENT; id++) { + if (sprog->ss[id]->sel->sinfo.num_consts) { + sprog->const_locs[id] = calloc(sprog->ss[id]->sel->sinfo.num_consts, sizeof(uint32_t)); + if (sprog->const_locs[id]) { + const char *prefix = (id == PIPE_SHADER_VERTEX) ? "vs" : "fs"; + for (i = 0; i < sprog->ss[id]->sel->sinfo.num_consts; i++) { + snprintf(name, 16, "%sconst[%d]", prefix, i); + sprog->const_locs[id][i] = glGetUniformLocation(prog_id, name); + } + } + } else + sprog->const_locs[id] = NULL; + } + + if (vs->sel->sinfo.num_inputs) { + sprog->attrib_locs = calloc(vs->sel->sinfo.num_inputs, sizeof(uint32_t)); + if (sprog->attrib_locs) { + for (i = 0; i < vs->sel->sinfo.num_inputs; i++) { + snprintf(name, 10, "in_%d", i); + sprog->attrib_locs[i] = glGetAttribLocation(prog_id, name); + } + } + } else + sprog->attrib_locs = NULL; + + if (fs->sel->sinfo.num_outputs > 1) { + glBindFragDataLocationIndexed(prog_id, 0, 0, "out_c0"); + glBindFragDataLocationIndexed(prog_id, 0, 1, "out_c1"); + } + return sprog; +} + +static struct grend_linked_shader_program *lookup_shader_program(struct grend_context *ctx, + GLuint vs_id, GLuint fs_id) +{ + struct grend_linked_shader_program *ent; + LIST_FOR_EACH_ENTRY(ent, &ctx->programs, head) { + if (ent->ss[PIPE_SHADER_VERTEX]->id == vs_id && ent->ss[PIPE_SHADER_FRAGMENT]->id == fs_id) + return ent; + } + return 0; +} + +static void grend_free_programs(struct grend_context *ctx) +{ + struct grend_linked_shader_program *ent, *tmp; + int i; + LIST_FOR_EACH_ENTRY_SAFE(ent, tmp, &ctx->programs, head) { + glDeleteProgram(ent->id); + list_del(&ent->head); + + for (i = PIPE_SHADER_VERTEX; i <= PIPE_SHADER_FRAGMENT; i++) { +// grend_shader_state_reference(&ent->ss[i], NULL); + free(ent->shadow_samp_mask_locs[i]); + free(ent->shadow_samp_add_locs[i]); + free(ent->samp_locs[i]); + free(ent->const_locs[i]); + } + free(ent->attrib_locs); + free(ent); + } +} + +static void grend_apply_sampler_state(struct grend_context *ctx, + struct grend_resource *res, + uint32_t shader_type, + int id); + +void grend_update_stencil_state(struct grend_context *ctx); + +void grend_create_surface(struct grend_context *ctx, + uint32_t handle, + uint32_t res_handle, uint32_t format, + uint32_t val0, uint32_t val1) + +{ + struct grend_surface *surf; + struct grend_resource *res; + + res = vrend_resource_lookup(res_handle, ctx->ctx_id); + if (!res) { + report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, res_handle); + return; + } + + surf = CALLOC_STRUCT(grend_surface); + surf->res_handle = res_handle; + surf->format = format; + surf->val0 = val0; + surf->val1 = val1; + pipe_reference_init(&surf->reference, 1); + + grend_resource_reference(&surf->texture, res); + + vrend_object_insert(ctx->object_hash, surf, sizeof(*surf), handle, VIRGL_OBJECT_SURFACE); +} + +static void grend_destroy_surface_object(void *obj_ptr) +{ + struct grend_surface *surface = obj_ptr; + + grend_surface_reference(&surface, NULL); +} + +static void grend_destroy_sampler_view_object(void *obj_ptr) +{ + struct grend_sampler_view *samp = obj_ptr; + + grend_sampler_view_reference(&samp, NULL); +} + +static void grend_destroy_so_target_object(void *obj_ptr) +{ + struct grend_so_target *target = obj_ptr; + + grend_so_target_reference(&target, NULL); +} + +static inline GLenum to_gl_swizzle(int swizzle) +{ + switch (swizzle) { + case PIPE_SWIZZLE_RED: return GL_RED; + case PIPE_SWIZZLE_GREEN: return GL_GREEN; + case PIPE_SWIZZLE_BLUE: return GL_BLUE; + case PIPE_SWIZZLE_ALPHA: return GL_ALPHA; + case PIPE_SWIZZLE_ZERO: return GL_ZERO; + case PIPE_SWIZZLE_ONE: return GL_ONE; + } + assert(0); + return 0; +} +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) +{ + struct grend_sampler_view *view; + struct grend_resource *res; + + res = vrend_resource_lookup(res_handle, ctx->ctx_id); + if (!res) { + report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, res_handle); + return; + } + + view = CALLOC_STRUCT(grend_sampler_view); + pipe_reference_init(&view->reference, 1); + view->res_handle = res_handle; + view->format = format; + view->val0 = val0; + view->val1 = val1; + view->swizzle_r = swizzle_packed & 0x7; + view->swizzle_g = (swizzle_packed >> 3) & 0x7; + view->swizzle_b = (swizzle_packed >> 6) & 0x7; + view->swizzle_a = (swizzle_packed >> 9) & 0x7; + view->cur_base = -1; + view->cur_max = 10000; + + grend_resource_reference(&view->texture, res); + + if (view->swizzle_r != 0 && view->swizzle_g != 1 && view->swizzle_b != 2 && view->swizzle_a != 3) + fprintf(stderr,"%d %d swizzles %d %d %d %d\n", view->format, view->texture->base.format, view->swizzle_r, view->swizzle_g, view->swizzle_b, view->swizzle_a); + + view->srgb_decode = GL_DECODE_EXT; + if (view->format != view->texture->base.format) { + if (util_format_is_srgb(view->texture->base.format) && + !util_format_is_srgb(view->format)) + view->srgb_decode = GL_SKIP_DECODE_EXT; + } + if (util_format_has_alpha(format) || util_format_is_depth_or_stencil(format)) + view->gl_swizzle_a = to_gl_swizzle(view->swizzle_a); + else + view->gl_swizzle_a = GL_ONE; + view->gl_swizzle_r = to_gl_swizzle(view->swizzle_r); + view->gl_swizzle_g = to_gl_swizzle(view->swizzle_g); + view->gl_swizzle_b = to_gl_swizzle(view->swizzle_b); + + vrend_object_insert(ctx->object_hash, view, sizeof(*view), handle, VIRGL_OBJECT_SAMPLER_VIEW); +} + +static void grend_fb_bind_texture(struct grend_resource *res, + int idx, + uint32_t level, uint32_t layer) +{ + const struct util_format_description *desc = util_format_description(res->base.format); + GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + idx; + + if (vrend_format_is_ds(res->base.format)) { { + if (util_format_has_stencil(desc)) { + if (util_format_has_depth(desc)) + attachment = GL_DEPTH_STENCIL_ATTACHMENT; + else + attachment = GL_STENCIL_ATTACHMENT; + } else + attachment = GL_DEPTH_ATTACHMENT; + } + } + + switch (res->target) { + case GL_TEXTURE_1D_ARRAY: + case GL_TEXTURE_2D_ARRAY: + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: + case GL_TEXTURE_CUBE_MAP_ARRAY: + glFramebufferTextureLayer(GL_FRAMEBUFFER_EXT, attachment, + res->id, level, layer); + break; + case GL_TEXTURE_3D: + glFramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT, attachment, + res->target, res->id, level, layer); + break; + case GL_TEXTURE_CUBE_MAP: + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, + GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer, res->id, level); + break; + case GL_TEXTURE_1D: + glFramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT, attachment, + res->target, res->id, level); + break; + case GL_TEXTURE_2D: + default: + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, + res->target, res->id, level); + break; + } + + if (attachment == GL_DEPTH_ATTACHMENT) + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT, + 0, 0, 0); +} + +static void grend_hw_set_zsurf_texture(struct grend_context *ctx) +{ + struct grend_resource *tex; + + if (!ctx->zsurf) { + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, + GL_TEXTURE_2D, 0, 0); + return; + + } + tex = ctx->zsurf->texture; + if (!tex) + return; + + grend_fb_bind_texture(tex, 0, ctx->zsurf->val0, ctx->zsurf->val1 & 0xffff); +} + +static void grend_hw_set_color_surface(struct grend_context *ctx, int index) +{ + struct grend_resource *tex; + + if (!ctx->surf[index]) { + GLenum attachment = GL_COLOR_ATTACHMENT0 + index; + + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, + GL_TEXTURE_2D, 0, 0); + } else { + tex = ctx->surf[index]->texture; + grend_fb_bind_texture(tex, index, ctx->surf[index]->val0, + ctx->surf[index]->val1 & 0xffff); + + } + + +} + +static void grend_hw_emit_framebuffer_state(struct grend_context *ctx) +{ + static const GLenum buffers[8] = { + GL_COLOR_ATTACHMENT0_EXT, + GL_COLOR_ATTACHMENT1_EXT, + GL_COLOR_ATTACHMENT2_EXT, + GL_COLOR_ATTACHMENT3_EXT, + GL_COLOR_ATTACHMENT4_EXT, + GL_COLOR_ATTACHMENT5_EXT, + GL_COLOR_ATTACHMENT6_EXT, + GL_COLOR_ATTACHMENT7_EXT, + }; + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ctx->fb_id); + + if (ctx->nr_cbufs == 0) + glReadBuffer(GL_NONE); + glDrawBuffers(ctx->nr_cbufs, buffers); +} + +void grend_set_framebuffer_state(struct grend_context *ctx, + uint32_t nr_cbufs, uint32_t surf_handle[8], + uint32_t zsurf_handle) +{ + struct grend_surface *surf, *zsurf; + int i; + int old_num; + GLenum status; + GLint new_height = -1; + boolean new_ibf = GL_FALSE; + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ctx->fb_id); + + if (zsurf_handle) { + zsurf = vrend_object_lookup(ctx->object_hash, zsurf_handle, VIRGL_OBJECT_SURFACE); + if (!zsurf) { + report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_SURFACE, zsurf_handle); + return; + } + } else + zsurf = NULL; + + if (ctx->zsurf != zsurf) { + grend_surface_reference(&ctx->zsurf, zsurf); + grend_hw_set_zsurf_texture(ctx); + } + + old_num = ctx->nr_cbufs; + ctx->nr_cbufs = nr_cbufs; + ctx->old_nr_cbufs = old_num; + + for (i = 0; i < nr_cbufs; i++) { + surf = vrend_object_lookup(ctx->object_hash, surf_handle[i], VIRGL_OBJECT_SURFACE); + if (!surf) { + report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_SURFACE, surf_handle[i]); + return; + } + if (ctx->surf[i] != surf) { + grend_surface_reference(&ctx->surf[i], surf); + grend_hw_set_color_surface(ctx, i); + } + } + + if (old_num > ctx->nr_cbufs) { + for (i = ctx->nr_cbufs; i < old_num; i++) { + grend_surface_reference(&ctx->surf[i], NULL); + grend_hw_set_color_surface(ctx, i); + } + } + + /* find a buffer to set fb_height from */ + if (ctx->nr_cbufs == 0 && !ctx->zsurf) { + new_height = 0; + new_ibf = FALSE; + } else if (ctx->nr_cbufs == 0) { + new_height = u_minify(ctx->zsurf->texture->base.height0, ctx->zsurf->val0); + new_ibf = ctx->zsurf->texture->y_0_top ? TRUE : FALSE; + } + else { + new_height = u_minify(ctx->surf[0]->texture->base.height0, ctx->surf[0]->val0); + new_ibf = ctx->surf[0]->texture->y_0_top ? TRUE : FALSE; + } + + if (new_height != -1) { + if (ctx->fb_height != new_height || ctx->inverted_fbo_content != new_ibf) { + ctx->fb_height = new_height; + ctx->inverted_fbo_content = new_ibf; + ctx->scissor_state_dirty = TRUE; + ctx->viewport_state_dirty = TRUE; + } + } + + grend_hw_emit_framebuffer_state(ctx); + + if (ctx->nr_cbufs > 0 || ctx->zsurf) { + status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) + fprintf(stderr,"failed to complete framebuffer 0x%x %s\n", status, ctx->debug_name); + } +} + +static void grend_hw_emit_depth_range(struct grend_context *ctx) +{ + glDepthRange(ctx->view_near_val, ctx->view_far_val); +} + +/* + * if the viewport Y scale factor is > 0 then we are rendering to + * an FBO already so don't need to invert rendering? + */ +void grend_set_viewport_state(struct grend_context *ctx, + const struct pipe_viewport_state *state) +{ + /* convert back to glViewport */ + GLint x, y; + GLsizei width, height; + GLclampd near_val, far_val; + GLboolean viewport_is_negative = (state->scale[1] < 0) ? GL_TRUE : GL_FALSE; + GLfloat abs_s1 = fabsf(state->scale[1]); + + width = state->scale[0] * 2.0f; + height = abs_s1 * 2.0f; + x = state->translate[0] - state->scale[0]; + y = state->translate[1] - state->scale[1]; + + near_val = state->translate[2] - state->scale[2]; + far_val = near_val + (state->scale[2] * 2.0); + + if (ctx->view_cur_x != x || + ctx->view_cur_y != y || + ctx->view_width != width || + ctx->view_height != height) { + ctx->viewport_state_dirty = TRUE; + ctx->view_cur_x = x; + ctx->view_cur_y = y; + ctx->view_width = width; + ctx->view_height = height; + } + + if (ctx->viewport_is_negative != viewport_is_negative) + ctx->viewport_is_negative = viewport_is_negative; + + ctx->depth_scale = fabsf(far_val - near_val); + ctx->depth_transform = near_val; + + if (ctx->view_near_val != near_val || + ctx->view_far_val != far_val) { + ctx->view_near_val = near_val; + ctx->view_far_val = far_val; + grend_hw_emit_depth_range(ctx); + } +} + +void grend_create_vertex_elements_state(struct grend_context *ctx, + uint32_t handle, + unsigned num_elements, + const struct pipe_vertex_element *elements) +{ + struct grend_vertex_element_array *v = CALLOC_STRUCT(grend_vertex_element_array); + const struct util_format_description *desc; + GLenum type; + int i; + + v->count = num_elements; + for (i = 0; i < num_elements; i++) { + memcpy(&v->elements[i].base, &elements[i], sizeof(struct pipe_vertex_element)); + + desc = util_format_description(elements[i].src_format); + + type = GL_FALSE; + if (desc->channel[0].type == UTIL_FORMAT_TYPE_FLOAT) { + if (desc->channel[0].size == 32) + type = GL_FLOAT; + else if (desc->channel[0].size == 64) + type = GL_DOUBLE; + else if (desc->channel[0].size == 16) + type = GL_HALF_FLOAT; + } else if (desc->channel[0].type == UTIL_FORMAT_TYPE_UNSIGNED && + desc->channel[0].size == 8) + type = GL_UNSIGNED_BYTE; + else if (desc->channel[0].type == UTIL_FORMAT_TYPE_SIGNED && + desc->channel[0].size == 8) + type = GL_BYTE; + else if (desc->channel[0].type == UTIL_FORMAT_TYPE_UNSIGNED && + desc->channel[0].size == 16) + type = GL_UNSIGNED_SHORT; + else if (desc->channel[0].type == UTIL_FORMAT_TYPE_SIGNED && + desc->channel[0].size == 16) + type = GL_SHORT; + else if (desc->channel[0].type == UTIL_FORMAT_TYPE_UNSIGNED && + desc->channel[0].size == 32) + type = GL_UNSIGNED_INT; + else if (desc->channel[0].type == UTIL_FORMAT_TYPE_SIGNED && + desc->channel[0].size == 32) + type = GL_INT; + else if (elements[i].src_format == PIPE_FORMAT_R10G10B10A2_SSCALED || + elements[i].src_format == PIPE_FORMAT_R10G10B10A2_SNORM || + elements[i].src_format == PIPE_FORMAT_B10G10R10A2_SNORM) + type = GL_INT_2_10_10_10_REV; + else if (elements[i].src_format == PIPE_FORMAT_R10G10B10A2_USCALED || + elements[i].src_format == PIPE_FORMAT_R10G10B10A2_UNORM || + elements[i].src_format == PIPE_FORMAT_B10G10R10A2_UNORM) + type = GL_UNSIGNED_INT_2_10_10_10_REV; + + if (type == GL_FALSE) { + report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_VERTEX_FORMAT, elements[i].src_format); + FREE(v); + return; + } + + v->elements[i].type = type; + if (desc->channel[0].normalized) + v->elements[i].norm = GL_TRUE; + if (desc->nr_channels == 4 && desc->swizzle[0] == UTIL_FORMAT_SWIZZLE_Z) + v->elements[i].nr_chan = GL_BGRA; + else + v->elements[i].nr_chan = desc->nr_channels; + } + + vrend_object_insert(ctx->object_hash, v, sizeof(struct grend_vertex_element), handle, + VIRGL_OBJECT_VERTEX_ELEMENTS); +} + +void grend_bind_vertex_elements_state(struct grend_context *ctx, + uint32_t handle) +{ + struct grend_vertex_element_array *v; + + if (!handle) { + ctx->ve = NULL; + return; + } + v = vrend_object_lookup(ctx->object_hash, handle, VIRGL_OBJECT_VERTEX_ELEMENTS); + if (!v) { + report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_HANDLE, handle); + return; + } + ctx->ve = v; +} + +void grend_set_constants(struct grend_context *ctx, + uint32_t shader, + uint32_t index, + uint32_t num_constant, + float *data) +{ + struct grend_constants *consts; + int i; + + consts = &ctx->consts[shader]; + ctx->const_dirty[shader] = TRUE; + + consts->consts = realloc(consts->consts, num_constant * sizeof(float)); + if (!consts->consts) + return; + + consts->num_consts = num_constant; + for (i = 0; i < num_constant; i++) + consts->consts[i] = data[i]; +} + +void grend_set_index_buffer(struct grend_context *ctx, + uint32_t res_handle, + uint32_t index_size, + uint32_t offset) +{ + struct grend_resource *res; + + ctx->ib.index_size = index_size; + ctx->ib.offset = offset; + if (res_handle) { + if (ctx->index_buffer_res_id != res_handle) { + res = vrend_resource_lookup(res_handle, ctx->ctx_id); + if (!res) { + grend_resource_reference((struct grend_resource **)&ctx->ib.buffer, NULL); + ctx->index_buffer_res_id = 0; + report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, res_handle); + return; + } + grend_resource_reference((struct grend_resource **)&ctx->ib.buffer, res); + ctx->index_buffer_res_id = res_handle; + } + } else { + grend_resource_reference((struct grend_resource **)&ctx->ib.buffer, NULL); + ctx->index_buffer_res_id = 0; + } +} + +void grend_set_single_vbo(struct grend_context *ctx, + int index, + uint32_t stride, + uint32_t buffer_offset, + uint32_t res_handle) +{ + struct grend_resource *res; + ctx->vbo[index].stride = stride; + ctx->vbo[index].buffer_offset = buffer_offset; + + if (res_handle == 0) { + grend_resource_reference((struct grend_resource **)&ctx->vbo[index].buffer, NULL); + ctx->vbo_res_ids[index] = 0; + } else if (ctx->vbo_res_ids[index] != res_handle) { + res = vrend_resource_lookup(res_handle, ctx->ctx_id); + if (!res) { + report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, res_handle); + ctx->vbo_res_ids[index] = 0; + return; + } + grend_resource_reference((struct grend_resource **)&ctx->vbo[index].buffer, res); + ctx->vbo_res_ids[index] = res_handle; + } +} + +void grend_set_num_vbo(struct grend_context *ctx, + int num_vbo) +{ + int old_num = ctx->num_vbos; + int i; + ctx->num_vbos = num_vbo; + + for (i = num_vbo; i < old_num; i++) { + grend_resource_reference((struct grend_resource **)&ctx->vbo[i].buffer, NULL); + ctx->vbo_res_ids[i] = 0; + } + +} + +void grend_set_single_sampler_view(struct grend_context *ctx, + uint32_t shader_type, + int index, + uint32_t handle) +{ + struct grend_sampler_view *view = NULL; + struct grend_texture *tex; + + if (handle) { + view = vrend_object_lookup(ctx->object_hash, handle, VIRGL_OBJECT_SAMPLER_VIEW); + if (!view) { + ctx->views[shader_type].views[index] = NULL; + report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_HANDLE, handle); + return; + } + tex = vrend_resource_lookup(view->res_handle, ctx->ctx_id); + if (!tex) { + fprintf(stderr,"cannot find texture to back resource view %d %d\n", handle, view->res_handle); + return; + } + glBindTexture(view->texture->target, view->texture->id); + if (view->texture->target != PIPE_BUFFER) { + tex = (struct grend_texture *)view->texture; + if (util_format_is_depth_or_stencil(view->format)) { + if (view->depth_texture_mode != GL_RED) { + glTexParameteri(view->texture->target, GL_DEPTH_TEXTURE_MODE, GL_RED); + view->depth_texture_mode = GL_RED; + } + } + + if (view->cur_base != (view->val1 & 0xff)) { + view->cur_base = view->val1 & 0xff; + glTexParameteri(view->texture->target, GL_TEXTURE_BASE_LEVEL, view->cur_base); + } + if (view->cur_max != ((view->val1 >> 8) & 0xff)) { + view->cur_max = (view->val1 >> 8) & 0xff; + glTexParameteri(view->texture->target, GL_TEXTURE_MAX_LEVEL, view->cur_max); + } + if (tex->cur_swizzle_r != view->gl_swizzle_r) { + glTexParameteri(view->texture->target, GL_TEXTURE_SWIZZLE_R, view->gl_swizzle_r); + tex->cur_swizzle_r = view->gl_swizzle_r; + } + if (tex->cur_swizzle_g != view->gl_swizzle_g) { + glTexParameteri(view->texture->target, GL_TEXTURE_SWIZZLE_G, view->gl_swizzle_g); + tex->cur_swizzle_g = view->gl_swizzle_g; + } + if (tex->cur_swizzle_b != view->gl_swizzle_b) { + glTexParameteri(view->texture->target, GL_TEXTURE_SWIZZLE_B, view->gl_swizzle_b); + tex->cur_swizzle_b = view->gl_swizzle_b; + } + if (tex->cur_swizzle_a != view->gl_swizzle_a) { + glTexParameteri(view->texture->target, GL_TEXTURE_SWIZZLE_A, view->gl_swizzle_a); + tex->cur_swizzle_a = view->gl_swizzle_a; + } + if (tex->srgb_decode != view->srgb_decode && util_format_is_srgb(tex->base.base.format)) { + glTexParameteri(view->texture->target, GL_TEXTURE_SRGB_DECODE_EXT, + view->srgb_decode); + tex->srgb_decode = view->srgb_decode; + } + } + } + + grend_sampler_view_reference(&ctx->views[shader_type].views[index], view); +} + +void grend_set_num_sampler_views(struct grend_context *ctx, + uint32_t shader_type, + uint32_t start_slot, + int num_sampler_views) +{ + if (start_slot + num_sampler_views < ctx->views[shader_type].num_views) { + int i; + for (i = start_slot + num_sampler_views; i < ctx->views[shader_type].num_views; i++) + grend_sampler_view_reference(&ctx->views[shader_type].views[i], NULL); + } + ctx->views[shader_type].num_views = start_slot + num_sampler_views; +} + +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) +{ + struct grend_resource *res; + + res = vrend_resource_lookup(res_handle, ctx->ctx_id); + if (!res) { + report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, res_handle); + return; + } + if (res->ptr) { + memcpy(res->ptr + box->x, data, box->width); + } else if (res->target == GL_ELEMENT_ARRAY_BUFFER_ARB || + res->target == GL_ARRAY_BUFFER_ARB || + res->target == GL_TRANSFORM_FEEDBACK_BUFFER) { + glBindBufferARB(res->target, res->id); + glBufferSubData(res->target, box->x, box->width, data); + } else { + GLenum glformat, gltype; + glBindTexture(res->target, res->id); + glformat = tex_conv_table[res->base.format].glformat; + gltype = tex_conv_table[res->base.format].gltype; + + glTexSubImage2D(res->target, level, box->x, box->y, box->width, box->height, + glformat, gltype, data); + } +} + + +static void grend_destroy_shader_object(void *obj_ptr) +{ + struct grend_shader_selector *state = obj_ptr; + + grend_shader_state_reference(&state, NULL); +} + +static INLINE void vrend_fill_shader_key(struct grend_context *ctx, + struct vrend_shader_key *key) +{ + key->invert_fs_origin = !ctx->inverted_fbo_content; + key->coord_replace = ctx->rs_state.point_quad_rasterization ? ctx->rs_state.sprite_coord_enable : 0; +} + +static int grend_shader_create(struct grend_context *ctx, + struct grend_shader *shader, + struct vrend_shader_key key) +{ + shader->id = glCreateShader(shader->sel->type == PIPE_SHADER_VERTEX ? GL_VERTEX_SHADER : GL_FRAGMENT_SHADER); + shader->compiled_fs_id = 0; + shader->glsl_prog = tgsi_convert(shader->sel->tokens, &key, &shader->sel->sinfo); + + if (shader->sel->type == PIPE_SHADER_FRAGMENT) { + boolean ret; + + ret = grend_compile_shader(ctx, shader); + if (ret == FALSE) { + glDeleteShader(shader->id); + free(shader->glsl_prog); + return -1; + } + } + return 0; +} + +static int grend_shader_select(struct grend_context *ctx, + struct grend_shader_selector *sel, + boolean *dirty) +{ + struct vrend_shader_key key; + struct grend_shader *shader = NULL; + int r; + + memset(&key, 0, sizeof(key)); + vrend_fill_shader_key(ctx, &key); + + if (sel->current && memcmp(&sel->current->key, &key, sizeof(key))) + return 0; + + if (sel->num_shaders > 1) { + struct grend_shader *p = sel->current, *c = p->next_variant; + while (c && memcmp(&c->key, &key, sizeof(key)) != 0) { + p = c; + c = c->next_variant; + } + if (c) { + p->next_variant = c->next_variant; + shader = c; + } + } + + if (!shader) { + shader = CALLOC_STRUCT(grend_shader); + shader->sel = sel; + + r = grend_shader_create(ctx, shader, key); + if (r) { + sel->current = NULL; + FREE(shader); + return r; + } + sel->num_shaders++; + } + if (dirty) + *dirty = true; + + shader->next_variant = sel->current; + sel->current = shader; + return 0; +} + +static void *grend_create_shader_state(struct grend_context *ctx, + const struct pipe_shader_state *state, + unsigned pipe_shader_type) +{ + struct grend_shader_selector *sel = CALLOC_STRUCT(grend_shader_selector); + int r; + + sel->type = pipe_shader_type; + sel->sinfo.so_info = state->stream_output; + sel->tokens = tgsi_dup_tokens(state->tokens); + pipe_reference_init(&sel->reference, 1); + + r = grend_shader_select(ctx, sel, NULL); + if (r) + return NULL; + return sel; +} + +void grend_create_vs(struct grend_context *ctx, + uint32_t handle, + const struct pipe_shader_state *vs) +{ + struct grend_shader_selector *sel; + + sel = grend_create_shader_state(ctx, vs, PIPE_SHADER_VERTEX); + + vrend_object_insert(ctx->object_hash, sel, sizeof(*sel), handle, VIRGL_OBJECT_VS); + + return; +} + +void grend_create_fs(struct grend_context *ctx, + uint32_t handle, + const struct pipe_shader_state *fs) +{ + struct grend_shader_selector *sel; + + sel = grend_create_shader_state(ctx, fs, PIPE_SHADER_FRAGMENT); + + vrend_object_insert(ctx->object_hash, sel, sizeof(*sel), handle, VIRGL_OBJECT_FS); + + return; +} + +void grend_bind_vs(struct grend_context *ctx, + uint32_t handle) +{ + struct grend_shader_selector *sel; + + sel = vrend_object_lookup(ctx->object_hash, handle, VIRGL_OBJECT_VS); + + if (ctx->vs != sel) + ctx->shader_dirty = true; + grend_shader_state_reference(&ctx->vs, sel); +} + +void grend_bind_fs(struct grend_context *ctx, + uint32_t handle) +{ + struct grend_shader_selector *sel; + + sel = vrend_object_lookup(ctx->object_hash, handle, VIRGL_OBJECT_FS); + + if (ctx->fs != sel) + ctx->shader_dirty = true; + grend_shader_state_reference(&ctx->fs, sel); +} + +void grend_clear(struct grend_context *ctx, + unsigned buffers, + const union pipe_color_union *color, + double depth, unsigned stencil) +{ + GLbitfield bits = 0; + + if (ctx->in_error) + return; + + if (ctx->ctx_switch_pending) + grend_finish_context_switch(ctx); + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ctx->fb_id); + + grend_update_frontface_state(ctx); + if (ctx->stencil_state_dirty) + grend_update_stencil_state(ctx); + if (ctx->scissor_state_dirty || grend_state.scissor_dirty) + grend_update_scissor_state(ctx); + if (ctx->viewport_state_dirty || grend_state.viewport_dirty) + grend_update_viewport_state(ctx); + + grend_use_program(0); + + if (buffers & PIPE_CLEAR_COLOR) + glClearColor(color->f[0], color->f[1], color->f[2], color->f[3]); + + if (buffers & PIPE_CLEAR_DEPTH) { + /* gallium clears don't respect depth mask */ + glDepthMask(GL_TRUE); + glClearDepth(depth); + } + + if (buffers & PIPE_CLEAR_STENCIL) + glClearStencil(stencil); + + if (buffers & PIPE_CLEAR_COLOR) + bits |= GL_COLOR_BUFFER_BIT; + if (buffers & PIPE_CLEAR_DEPTH) + bits |= GL_DEPTH_BUFFER_BIT; + if (buffers & PIPE_CLEAR_STENCIL) + bits |= GL_STENCIL_BUFFER_BIT; + glClear(bits); + + if (buffers & PIPE_CLEAR_DEPTH) + if (!ctx->dsa_state.depth.writemask) + glDepthMask(GL_FALSE); +} + +static void grend_update_scissor_state(struct grend_context *ctx) +{ + struct pipe_scissor_state *ss = &ctx->ss; + struct pipe_rasterizer_state *state = &ctx->rs_state; + GLint y; + + if (ctx->viewport_is_negative) + y = ss->miny; + else + y = ss->maxy; + if (state->scissor) + glEnable(GL_SCISSOR_TEST); + else + glDisable(GL_SCISSOR_TEST); + + glScissor(ss->minx, y, ss->maxx - ss->minx, ss->maxy - ss->miny); + ctx->scissor_state_dirty = FALSE; + grend_state.scissor_dirty = FALSE; +} + +static void grend_update_viewport_state(struct grend_context *ctx) +{ + GLint cy; + if (ctx->viewport_is_negative) + cy = ctx->view_cur_y - ctx->view_height; + else + cy = ctx->view_cur_y; + glViewport(ctx->view_cur_x, cy, ctx->view_width, ctx->view_height); + + ctx->viewport_state_dirty = FALSE; + grend_state.viewport_dirty = FALSE; +} + +static GLenum get_xfb_mode(GLenum mode) +{ + switch (mode) { + case GL_POINTS: + return GL_POINTS; + case GL_TRIANGLES: + case GL_TRIANGLE_STRIP: + case GL_TRIANGLE_FAN: + case GL_QUADS: + case GL_QUAD_STRIP: + case GL_POLYGON: + return GL_TRIANGLES; + case GL_LINES: + case GL_LINE_LOOP: + case GL_LINE_STRIP: + return GL_LINES; + } + fprintf(stderr, "failed to translate TFB %d\n", mode); + return GL_POINTS; +} + +void grend_draw_vbo(struct grend_context *ctx, + const struct pipe_draw_info *info) +{ + int i; + int sampler_id; + bool new_program = FALSE; + uint32_t shader_type; + uint32_t num_enable; + uint32_t enable_bitmask; + uint32_t disable_bitmask; + + if (ctx->in_error) + return; + + if (ctx->ctx_switch_pending) + grend_finish_context_switch(ctx); + + grend_update_frontface_state(ctx); + if (ctx->stencil_state_dirty) + grend_update_stencil_state(ctx); + if (ctx->scissor_state_dirty || grend_state.scissor_dirty) + grend_update_scissor_state(ctx); + + if (ctx->viewport_state_dirty || grend_state.viewport_dirty) + grend_update_viewport_state(ctx); + + grend_patch_blend_func(ctx); + + if (ctx->shader_dirty) { + struct grend_linked_shader_program *prog; + boolean fs_dirty, vs_dirty; + + if (!ctx->vs || !ctx->fs) { + fprintf(stderr,"dropping rendering due to missing shaders\n"); + return; + } + + grend_shader_select(ctx, ctx->fs, &fs_dirty); + grend_shader_select(ctx, ctx->vs, &vs_dirty); + + prog = lookup_shader_program(ctx, ctx->vs->current->id, ctx->fs->current->id); + if (!prog) { + prog = add_shader_program(ctx, ctx->vs->current, ctx->fs->current); + if (!prog) + return; + } + if (ctx->prog != prog) { + new_program = TRUE; + ctx->prog = prog; + } + } + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ctx->fb_id); + + grend_use_program(ctx->prog->id); + + for (shader_type = PIPE_SHADER_VERTEX; shader_type <= PIPE_SHADER_FRAGMENT; shader_type++) { + if (ctx->prog->const_locs[shader_type] && (ctx->const_dirty[shader_type] || new_program)) { + int nc; + if (shader_type == PIPE_SHADER_VERTEX) { + nc = ctx->vs->sinfo.num_consts; + } else if (shader_type == PIPE_SHADER_FRAGMENT) { + nc = ctx->fs->sinfo.num_consts; + } + for (i = 0; i < nc; i++) { + if (ctx->prog->const_locs[shader_type][i] != -1 && ctx->consts[shader_type].consts) + glUniform4fv(ctx->prog->const_locs[shader_type][i], 1, &ctx->consts[shader_type].consts[i * 4]); + } + ctx->const_dirty[shader_type] = FALSE; + } + } + + sampler_id = 0; + for (shader_type = PIPE_SHADER_VERTEX; shader_type <= PIPE_SHADER_FRAGMENT; shader_type++) { + int index = 0; + for (i = 0; i < ctx->views[shader_type].num_views; i++) { + struct grend_resource *texture = NULL; + + if (ctx->views[shader_type].views[i]) { + texture = ctx->views[shader_type].views[i]->texture; + } + + if (!(ctx->prog->samplers_used_mask[shader_type] & (1 << i))) + continue; + + if (ctx->prog->samp_locs[shader_type]) + glUniform1i(ctx->prog->samp_locs[shader_type][index], sampler_id); + + if (ctx->prog->shadow_samp_mask[shader_type] & (1 << i)) { + struct grend_sampler_view *tview = ctx->views[shader_type].views[i]; + glUniform4f(ctx->prog->shadow_samp_mask_locs[shader_type][index], + tview->gl_swizzle_r == GL_ZERO ? 0.0 : 1.0, + tview->gl_swizzle_g == GL_ZERO ? 0.0 : 1.0, + tview->gl_swizzle_b == GL_ZERO ? 0.0 : 1.0, + tview->gl_swizzle_a == GL_ZERO ? 0.0 : 1.0); + glUniform4f(ctx->prog->shadow_samp_add_locs[shader_type][index], + tview->gl_swizzle_r == GL_ONE ? 1.0 : 0.0, + tview->gl_swizzle_g == GL_ONE ? 1.0 : 0.0, + tview->gl_swizzle_b == GL_ONE ? 1.0 : 0.0, + tview->gl_swizzle_a == GL_ONE ? 1.0 : 0.0); + } + + glActiveTexture(GL_TEXTURE0 + sampler_id); + if (texture) { + glBindTexture(texture->target, texture->id); + if (ctx->views[shader_type].old_ids[i] != texture->id || ctx->sampler_state_dirty) { + grend_apply_sampler_state(ctx, texture, shader_type, i); + ctx->views[shader_type].old_ids[i] = texture->id; + } + if (ctx->rs_state.point_quad_rasterization) { + if (ctx->rs_state.sprite_coord_enable & (1 << i)) + glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE); + else + glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_FALSE); + } + sampler_id++; + } + index++; + } + } + ctx->sampler_state_dirty = FALSE; + + if (!ctx->ve) { + fprintf(stderr,"illegal VE setup - skipping renderering\n"); + return; + } + glUniform4f(ctx->prog->vs_ws_adjust_loc, 0.0, ctx->viewport_is_negative ? -1.0 : 1.0, ctx->depth_scale, ctx->depth_transform); + + num_enable = ctx->ve->count; + enable_bitmask = 0; + disable_bitmask = ~((1ull << num_enable) - 1); + for (i = 0; i < ctx->ve->count; i++) { + struct grend_vertex_element *ve = &ctx->ve->elements[i]; + int vbo_index = ctx->ve->elements[i].base.vertex_buffer_index; + struct grend_buffer *buf; + GLint loc; + + if (i >= ctx->prog->ss[PIPE_SHADER_VERTEX]->sel->sinfo.num_inputs) { + /* XYZZY: debug this? */ + num_enable = ctx->prog->ss[PIPE_SHADER_VERTEX]->sel->sinfo.num_inputs; + break; + } + buf = (struct grend_buffer *)ctx->vbo[vbo_index].buffer; + + if (!buf) { + fprintf(stderr,"cannot find vbo buf %d %d %d\n", i, ctx->ve->count, ctx->prog->ss[PIPE_SHADER_VERTEX]->sel->sinfo.num_inputs); + continue; + } + + if (graw_shader_use_explicit) { + loc = i; + } else { + if (ctx->prog->attrib_locs) { + loc = ctx->prog->attrib_locs[i]; + } else loc = -1; + + if (loc == -1) { + fprintf(stderr,"cannot find loc %d %d %d\n", i, ctx->ve->count, ctx->prog->ss[PIPE_SHADER_VERTEX]->sel->sinfo.num_inputs); + num_enable--; + if (i == 0) { + fprintf(stderr,"shader probably didn't compile - skipping rendering\n"); + return; + } + continue; + } + } + + if (ve->type == GL_FALSE) { + fprintf(stderr,"failed to translate vertex type - skipping render\n"); + return; + } + + glBindBuffer(GL_ARRAY_BUFFER, buf->base.id); + + if (ctx->vbo[vbo_index].stride == 0) { + void *data; + /* for 0 stride we are kinda screwed */ + data = glMapBufferRange(GL_ARRAY_BUFFER, ctx->vbo[vbo_index].buffer_offset, ve->nr_chan * sizeof(GLfloat), GL_MAP_READ_BIT); + + switch (ve->nr_chan) { + case 1: + glVertexAttrib1fv(loc, data); + break; + case 2: + glVertexAttrib2fv(loc, data); + break; + case 3: + glVertexAttrib3fv(loc, data); + break; + case 4: + default: + glVertexAttrib4fv(loc, data); + break; + } + glUnmapBuffer(GL_ARRAY_BUFFER); + disable_bitmask |= (1 << loc); + } else { + enable_bitmask |= (1 << loc); + if (util_format_is_pure_integer(ve->base.src_format)) { + glVertexAttribIPointer(loc, ve->nr_chan, ve->type, ctx->vbo[vbo_index].stride, (void *)(unsigned long)(ve->base.src_offset + ctx->vbo[vbo_index].buffer_offset)); + } else { + glVertexAttribPointer(loc, ve->nr_chan, ve->type, ve->norm, ctx->vbo[vbo_index].stride, (void *)(unsigned long)(ve->base.src_offset + ctx->vbo[vbo_index].buffer_offset)); + } + glVertexAttribDivisorARB(loc, ve->base.instance_divisor); + } + } + + if (ctx->enabled_attribs_bitmask != enable_bitmask) { + uint32_t mask = ctx->enabled_attribs_bitmask & disable_bitmask; + + while (mask) { + i = u_bit_scan(&mask); + glDisableVertexAttribArray(i); + } + ctx->enabled_attribs_bitmask &= ~disable_bitmask; + + mask = ctx->enabled_attribs_bitmask ^ enable_bitmask; + while (mask) { + i = u_bit_scan(&mask); + glEnableVertexAttribArray(i); + } + + ctx->enabled_attribs_bitmask = enable_bitmask; + } + + if (info->indexed) { + struct grend_resource *res = (struct grend_resource *)ctx->ib.buffer; + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, res->id); + } else + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + +// grend_ctx_restart_queries(ctx); + + if (ctx->num_so_targets) { + glBeginTransformFeedback(get_xfb_mode(info->mode)); + } + + if (info->primitive_restart) { + if (grend_state.have_nv_prim_restart) { + glEnableClientState(GL_PRIMITIVE_RESTART_NV); + glPrimitiveRestartIndexNV(info->restart_index); + } else { + glEnable(GL_PRIMITIVE_RESTART); + glPrimitiveRestartIndex(info->restart_index); + } + } + /* set the vertex state up now on a delay */ + if (!info->indexed) { + GLenum mode = info->mode; + if (info->instance_count <= 1) + glDrawArrays(mode, info->start, info->count); + else + glDrawArraysInstancedARB(mode, info->start, info->count, info->instance_count); + } else { + GLenum elsz; + GLenum mode = info->mode; + switch (ctx->ib.index_size) { + case 1: + elsz = GL_UNSIGNED_BYTE; + break; + case 2: + elsz = GL_UNSIGNED_SHORT; + break; + case 4: + elsz = GL_UNSIGNED_INT; + break; + } + + if (info->index_bias) { + if (info->min_index != 0 || info->max_index != -1) + glDrawRangeElementsBaseVertex(mode, info->min_index, info->max_index, info->count, elsz, (void *)(unsigned long)ctx->ib.offset, info->index_bias); + else + glDrawElementsBaseVertex(mode, info->count, elsz, (void *)(unsigned long)ctx->ib.offset, info->index_bias); + } else if (info->min_index != 0 || info->max_index != -1) + glDrawRangeElements(mode, info->min_index, info->max_index, info->count, elsz, (void *)(unsigned long)ctx->ib.offset); + else if (info->instance_count > 1) + glDrawElementsInstancedARB(mode, info->count, elsz, (void *)(unsigned long)ctx->ib.offset, info->instance_count); + else + glDrawElements(mode, info->count, elsz, (void *)(unsigned long)ctx->ib.offset); + } + + if (ctx->num_so_targets) + glEndTransformFeedback(); + + if (info->primitive_restart) { + if (grend_state.have_nv_prim_restart) + glDisableClientState(GL_PRIMITIVE_RESTART_NV); + else if (grend_state.have_gl_prim_restart) + glDisable(GL_PRIMITIVE_RESTART); + } +} + +static GLenum translate_blend_func(uint32_t pipe_blend) +{ + switch(pipe_blend){ + case PIPE_BLEND_ADD: return GL_FUNC_ADD; + case PIPE_BLEND_SUBTRACT: return GL_FUNC_SUBTRACT; + case PIPE_BLEND_REVERSE_SUBTRACT: return GL_FUNC_REVERSE_SUBTRACT; + case PIPE_BLEND_MIN: return GL_MIN; + case PIPE_BLEND_MAX: return GL_MAX; + default: + assert("invalid blend token()" == NULL); + return 0; + } +} + +static GLenum translate_blend_factor(uint32_t pipe_factor) +{ + switch (pipe_factor) { + case PIPE_BLENDFACTOR_ONE: return GL_ONE; + case PIPE_BLENDFACTOR_SRC_COLOR: return GL_SRC_COLOR; + case PIPE_BLENDFACTOR_SRC_ALPHA: return GL_SRC_ALPHA; + + case PIPE_BLENDFACTOR_DST_COLOR: return GL_DST_COLOR; + case PIPE_BLENDFACTOR_DST_ALPHA: return GL_DST_ALPHA; + + case PIPE_BLENDFACTOR_CONST_COLOR: return GL_CONSTANT_COLOR; + case PIPE_BLENDFACTOR_CONST_ALPHA: return GL_CONSTANT_ALPHA; + + case PIPE_BLENDFACTOR_SRC1_COLOR: return GL_SRC1_COLOR; + case PIPE_BLENDFACTOR_SRC1_ALPHA: return GL_SRC1_ALPHA; + case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: return GL_SRC_ALPHA_SATURATE; + case PIPE_BLENDFACTOR_ZERO: return GL_ZERO; + + + case PIPE_BLENDFACTOR_INV_SRC_COLOR: return GL_ONE_MINUS_SRC_COLOR; + case PIPE_BLENDFACTOR_INV_SRC_ALPHA: return GL_ONE_MINUS_SRC_ALPHA; + + case PIPE_BLENDFACTOR_INV_DST_COLOR: return GL_ONE_MINUS_DST_COLOR; + case PIPE_BLENDFACTOR_INV_DST_ALPHA: return GL_ONE_MINUS_DST_ALPHA; + + case PIPE_BLENDFACTOR_INV_CONST_COLOR: return GL_ONE_MINUS_CONSTANT_COLOR; + case PIPE_BLENDFACTOR_INV_CONST_ALPHA: return GL_ONE_MINUS_CONSTANT_ALPHA; + + case PIPE_BLENDFACTOR_INV_SRC1_COLOR: return GL_ONE_MINUS_SRC1_COLOR; + case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: return GL_ONE_MINUS_SRC1_ALPHA; + + default: + assert("invalid blend token()" == NULL); + return 0; + } +} + +static GLenum +translate_logicop(GLuint pipe_logicop) +{ + switch (pipe_logicop) { +#define CASE(x) case PIPE_LOGICOP_##x: return GL_##x + CASE(CLEAR); + CASE(NOR); + CASE(AND_INVERTED); + CASE(COPY_INVERTED); + CASE(AND_REVERSE); + CASE(INVERT); + CASE(XOR); + CASE(NAND); + CASE(AND); + CASE(EQUIV); + CASE(NOOP); + CASE(OR_INVERTED); + CASE(COPY); + CASE(OR_REVERSE); + CASE(OR); + CASE(SET); + default: + assert("invalid logicop token()" == NULL); + return 0; + } +#undef CASE +} + +static GLenum +translate_stencil_op(GLuint op) +{ + switch (op) { +#define CASE(x) case PIPE_STENCIL_OP_##x: return GL_##x + CASE(KEEP); + CASE(ZERO); + CASE(REPLACE); + CASE(INCR); + CASE(DECR); + CASE(INCR_WRAP); + CASE(DECR_WRAP); + CASE(INVERT); + default: + assert("invalid stencilop token()" == NULL); + return 0; + } +#undef CASE +} + +static INLINE boolean is_dst_blend(int blend_factor) +{ + return (blend_factor == PIPE_BLENDFACTOR_DST_ALPHA || + blend_factor == PIPE_BLENDFACTOR_INV_DST_ALPHA); +} + +static INLINE int conv_dst_blend(int blend_factor) +{ + if (blend_factor == PIPE_BLENDFACTOR_DST_ALPHA) + return PIPE_BLENDFACTOR_ONE; + if (blend_factor == PIPE_BLENDFACTOR_INV_DST_ALPHA) + return PIPE_BLENDFACTOR_ZERO; + return blend_factor; +} + +static void grend_patch_blend_func(struct grend_context *ctx) +{ + struct pipe_blend_state *state = &ctx->blend_state; + int i; + int rsf, rdf, asf, adf; + if (ctx->nr_cbufs == 0) + return; + + for (i = 0; i < ctx->nr_cbufs; i++) { + if (!util_format_has_alpha(ctx->surf[i]->format)) + break; + } + + if (i == ctx->nr_cbufs) + return; + + if (state->independent_blend_enable) { + /* ARB_draw_buffers_blend is required for this */ + for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { + if (state->rt[i].blend_enable) { + if (!(is_dst_blend(state->rt[i].rgb_src_factor) || + is_dst_blend(state->rt[i].rgb_dst_factor) || + is_dst_blend(state->rt[i].alpha_src_factor) || + is_dst_blend(state->rt[i].alpha_dst_factor))) + continue; + + rsf = translate_blend_factor(conv_dst_blend(state->rt[i].rgb_src_factor)); + rdf = translate_blend_factor(conv_dst_blend(state->rt[i].rgb_dst_factor)); + asf = translate_blend_factor(conv_dst_blend(state->rt[i].alpha_src_factor)); + adf = translate_blend_factor(conv_dst_blend(state->rt[i].alpha_dst_factor)); + + glBlendFuncSeparateiARB(i, rsf, rdf, asf, adf); + } + } + } else { + if (state->rt[0].blend_enable) { + if (!(is_dst_blend(state->rt[0].rgb_src_factor) || + is_dst_blend(state->rt[0].rgb_dst_factor) || + is_dst_blend(state->rt[0].alpha_src_factor) || + is_dst_blend(state->rt[0].alpha_dst_factor))) + return; + + rsf = translate_blend_factor(conv_dst_blend(state->rt[i].rgb_src_factor)); + rdf = translate_blend_factor(conv_dst_blend(state->rt[i].rgb_dst_factor)); + asf = translate_blend_factor(conv_dst_blend(state->rt[i].alpha_src_factor)); + adf = translate_blend_factor(conv_dst_blend(state->rt[i].alpha_dst_factor)); + + glBlendFuncSeparate(rsf, rdf, asf, adf); + } + } +} + +static void grend_hw_emit_blend(struct grend_context *ctx) +{ + struct pipe_blend_state *state = &ctx->blend_state; + + if (state->logicop_enable != grend_state.hw_blend_state.logicop_enable) { + grend_state.hw_blend_state.logicop_enable = state->logicop_enable; + if (state->logicop_enable) { + glEnable(GL_COLOR_LOGIC_OP); + glLogicOp(translate_logicop(state->logicop_func)); + } else + glDisable(GL_COLOR_LOGIC_OP); + } + + if (state->independent_blend_enable) { + /* ARB_draw_buffers_blend is required for this */ + int i; + + for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { + if (state->rt[i].blend_enable) { + glBlendFuncSeparateiARB(i, translate_blend_factor(state->rt[i].rgb_src_factor), + translate_blend_factor(state->rt[i].rgb_dst_factor), + translate_blend_factor(state->rt[i].alpha_src_factor), + translate_blend_factor(state->rt[i].alpha_dst_factor)); + glBlendEquationSeparateiARB(i, translate_blend_func(state->rt[0].rgb_func), + translate_blend_func(state->rt[0].alpha_func)); + glEnableIndexedEXT(GL_BLEND, i); + } else + glDisableIndexedEXT(GL_BLEND, i); + + if (state->rt[i].colormask != grend_state.hw_blend_state.rt[i].colormask) { + grend_state.hw_blend_state.rt[i].colormask = state->rt[i].colormask; + glColorMaskIndexedEXT(i, state->rt[i].colormask & PIPE_MASK_R ? GL_TRUE : GL_FALSE, + state->rt[i].colormask & PIPE_MASK_G ? GL_TRUE : GL_FALSE, + state->rt[i].colormask & PIPE_MASK_B ? GL_TRUE : GL_FALSE, + state->rt[i].colormask & PIPE_MASK_A ? GL_TRUE : GL_FALSE); + } + } + } else { + if (state->rt[0].blend_enable) { + glBlendFuncSeparate(translate_blend_factor(state->rt[0].rgb_src_factor), + translate_blend_factor(state->rt[0].rgb_dst_factor), + translate_blend_factor(state->rt[0].alpha_src_factor), + translate_blend_factor(state->rt[0].alpha_dst_factor)); + glBlendEquationSeparate(translate_blend_func(state->rt[0].rgb_func), + translate_blend_func(state->rt[0].alpha_func)); + grend_blend_enable(GL_TRUE); + } + else + grend_blend_enable(GL_FALSE); + + if (state->rt[0].colormask != grend_state.hw_blend_state.rt[0].colormask) { + int i; + for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) + grend_state.hw_blend_state.rt[i].colormask = state->rt[i].colormask; + glColorMask(state->rt[0].colormask & PIPE_MASK_R ? GL_TRUE : GL_FALSE, + state->rt[0].colormask & PIPE_MASK_G ? GL_TRUE : GL_FALSE, + state->rt[0].colormask & PIPE_MASK_B ? GL_TRUE : GL_FALSE, + state->rt[0].colormask & PIPE_MASK_A ? GL_TRUE : GL_FALSE); + } + } + + if (grend_state.have_multisample) { + if (state->alpha_to_coverage) + glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE); + else + glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); + + if (state->alpha_to_one) + glEnable(GL_SAMPLE_ALPHA_TO_ONE); + else + glDisable(GL_SAMPLE_ALPHA_TO_ONE); + } +} + +void grend_object_bind_blend(struct grend_context *ctx, + uint32_t handle) +{ + struct pipe_blend_state *state; + + if (handle == 0) { + memset(&ctx->blend_state, 0, sizeof(ctx->blend_state)); + grend_blend_enable(GL_FALSE); + return; + } + state = vrend_object_lookup(ctx->object_hash, handle, VIRGL_OBJECT_BLEND); + if (!state) { + report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_HANDLE, handle); + return; + } + + ctx->blend_state = *state; + + grend_hw_emit_blend(ctx); +} + +static void grend_hw_emit_dsa(struct grend_context *ctx) +{ + struct pipe_depth_stencil_alpha_state *state = &ctx->dsa_state; + + if (state->depth.enabled) { + grend_depth_test_enable(GL_TRUE); + glDepthFunc(GL_NEVER + state->depth.func); + if (state->depth.writemask) + glDepthMask(GL_TRUE); + else + glDepthMask(GL_FALSE); + } else + grend_depth_test_enable(GL_FALSE); + + if (state->alpha.enabled) { + grend_alpha_test_enable(GL_TRUE); + glAlphaFunc(GL_NEVER + state->alpha.func, state->alpha.ref_value); + } else + grend_alpha_test_enable(GL_FALSE); + + +} +void grend_object_bind_dsa(struct grend_context *ctx, + uint32_t handle) +{ + struct pipe_depth_stencil_alpha_state *state; + + if (handle == 0) { + memset(&ctx->dsa_state, 0, sizeof(ctx->dsa_state)); + ctx->dsa = NULL; + ctx->stencil_state_dirty = TRUE; + grend_hw_emit_dsa(ctx); + return; + } + + state = vrend_object_lookup(ctx->object_hash, handle, VIRGL_OBJECT_DSA); + if (!state) { + report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_HANDLE, handle); + return; + } + + if (ctx->dsa != state) + ctx->stencil_state_dirty = TRUE; + ctx->dsa_state = *state; + ctx->dsa = state; + grend_hw_emit_dsa(ctx); +} + +static void grend_update_frontface_state(struct grend_context *ctx) +{ + struct pipe_rasterizer_state *state = &ctx->rs_state; + int front_ccw = state->front_ccw; + + front_ccw ^= (ctx->viewport_is_negative ? 1 : 0); +// if (front_ccw != grend_state.hw_rs_state.front_ccw) { +// grend_state.hw_rs_state.front_ccw = front_ccw; + if (front_ccw) + glFrontFace(GL_CCW); + else + glFrontFace(GL_CW); +// } +} + +void grend_update_stencil_state(struct grend_context *ctx) +{ + struct pipe_depth_stencil_alpha_state *state = ctx->dsa; + int i; + if (!state) + return; + + if (!state->stencil[1].enabled) { + if (state->stencil[0].enabled) { + grend_stencil_test_enable(GL_TRUE); + + glStencilOp(translate_stencil_op(state->stencil[0].fail_op), + translate_stencil_op(state->stencil[0].zfail_op), + translate_stencil_op(state->stencil[0].zpass_op)); + + glStencilFunc(GL_NEVER + state->stencil[0].func, + ctx->stencil_refs[0], + state->stencil[0].valuemask); + glStencilMask(state->stencil[0].writemask); + } else + grend_stencil_test_enable(GL_FALSE); + } else { + grend_stencil_test_enable(GL_TRUE); + + for (i = 0; i < 2; i++) { + GLenum face = (i == 1) ? GL_BACK : GL_FRONT; + glStencilOpSeparate(face, + translate_stencil_op(state->stencil[i].fail_op), + translate_stencil_op(state->stencil[i].zfail_op), + translate_stencil_op(state->stencil[i].zpass_op)); + + glStencilFuncSeparate(face, GL_NEVER + state->stencil[i].func, + ctx->stencil_refs[i], + state->stencil[i].valuemask); + glStencilMaskSeparate(face, state->stencil[i].writemask); + } + } + ctx->stencil_state_dirty = FALSE; +} + +static inline GLenum translate_fill(uint32_t mode) +{ + switch (mode) { + case PIPE_POLYGON_MODE_POINT: + return GL_POINT; + case PIPE_POLYGON_MODE_LINE: + return GL_LINE; + case PIPE_POLYGON_MODE_FILL: + return GL_FILL; + } + assert(0); + return 0; +} + +static void grend_hw_emit_rs(struct grend_context *ctx) +{ + struct pipe_rasterizer_state *state = &ctx->rs_state; + int i; +#if 0 + if (state->depth_clip) { + glEnable(GL_DEPTH_CLAMP); + } else { + glDisable(GL_DEPTH_CLAMP); + } +#endif + + if (state->point_size_per_vertex) { + glEnable(GL_PROGRAM_POINT_SIZE); + } else { + glDisable(GL_PROGRAM_POINT_SIZE); + if (state->point_size) + glPointSize(state->point_size); + } + + if (state->rasterizer_discard != grend_state.hw_rs_state.rasterizer_discard) { + grend_state.hw_rs_state.rasterizer_discard = state->rasterizer_discard; + if (state->rasterizer_discard) + glEnable(GL_RASTERIZER_DISCARD); + else + glDisable(GL_RASTERIZER_DISCARD); + } + + glPolygonMode(GL_FRONT, translate_fill(state->fill_front)); + glPolygonMode(GL_BACK, translate_fill(state->fill_back)); + + if (state->offset_tri) + glEnable(GL_POLYGON_OFFSET_FILL); + else + glDisable(GL_POLYGON_OFFSET_FILL); + + if (state->offset_line) + glEnable(GL_POLYGON_OFFSET_LINE); + else + glDisable(GL_POLYGON_OFFSET_LINE); + + if (state->offset_point) + glEnable(GL_POLYGON_OFFSET_POINT); + else + glDisable(GL_POLYGON_OFFSET_POINT); + + if (state->flatshade != grend_state.hw_rs_state.flatshade) { + grend_state.hw_rs_state.flatshade = state->flatshade; + if (state->flatshade) { + glShadeModel(GL_FLAT); + } else { + glShadeModel(GL_SMOOTH); + } + } + + if (state->flatshade_first != grend_state.hw_rs_state.flatshade_first) { + grend_state.hw_rs_state.flatshade_first = state->flatshade_first; + if (state->flatshade_first) + glProvokingVertexEXT(GL_FIRST_VERTEX_CONVENTION_EXT); + else + glProvokingVertexEXT(GL_LAST_VERTEX_CONVENTION_EXT); + } + glPolygonOffset(state->offset_scale, state->offset_units); + + if (state->poly_stipple_enable) + glEnable(GL_POLYGON_STIPPLE); + else + glDisable(GL_POLYGON_STIPPLE); + + if (state->point_quad_rasterization) { + glEnable(GL_POINT_SPRITE); + + glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, state->sprite_coord_mode ? GL_UPPER_LEFT : GL_LOWER_LEFT); + } else + glDisable(GL_POINT_SPRITE); + + if (state->cull_face != PIPE_FACE_NONE) { + switch (state->cull_face) { + case PIPE_FACE_FRONT: + glCullFace(GL_FRONT); + break; + case PIPE_FACE_BACK: + glCullFace(GL_BACK); + break; + case PIPE_FACE_FRONT_AND_BACK: + glCullFace(GL_FRONT_AND_BACK); + break; + } + glEnable(GL_CULL_FACE); + } else + glDisable(GL_CULL_FACE); + + if (state->light_twoside) + glEnable(GL_VERTEX_PROGRAM_TWO_SIDE); + else + glDisable(GL_VERTEX_PROGRAM_TWO_SIDE); + + if (state->clip_plane_enable != grend_state.hw_rs_state.clip_plane_enable) { + grend_state.hw_rs_state.clip_plane_enable = state->clip_plane_enable; + for (i = 0; i < 8; i++) { + if (state->clip_plane_enable & (1 << i)) + glEnable(GL_CLIP_PLANE0 + i); + else + glDisable(GL_CLIP_PLANE0 + i); + } + } + + glLineStipple(state->line_stipple_factor, state->line_stipple_pattern); + if (state->line_stipple_enable) + glEnable(GL_LINE_STIPPLE); + else + glDisable(GL_LINE_STIPPLE); + + if (state->line_smooth) + glEnable(GL_LINE_SMOOTH); + else + glDisable(GL_LINE_SMOOTH); + + if (state->poly_smooth) + glEnable(GL_POLYGON_SMOOTH); + else + glDisable(GL_POLYGON_SMOOTH); + + if (state->clamp_vertex_color) + glClampColor(GL_CLAMP_VERTEX_COLOR_ARB, GL_TRUE); + else + glClampColor(GL_CLAMP_VERTEX_COLOR_ARB, GL_FALSE); + + if (state->clamp_fragment_color) + glClampColor(GL_CLAMP_FRAGMENT_COLOR_ARB, GL_TRUE); + else + glClampColor(GL_CLAMP_FRAGMENT_COLOR_ARB, GL_FALSE); + + if (grend_state.have_multisample) { + if (state->multisample) { + glEnable(GL_MULTISAMPLE); + glEnable(GL_SAMPLE_MASK); + } else { + glDisable(GL_MULTISAMPLE); + glDisable(GL_SAMPLE_MASK); + } + } +} + +void grend_object_bind_rasterizer(struct grend_context *ctx, + uint32_t handle) +{ + struct pipe_rasterizer_state *state; + + if (handle == 0) { + memset(&ctx->rs_state, 0, sizeof(ctx->rs_state)); + return; + } + + state = vrend_object_lookup(ctx->object_hash, handle, VIRGL_OBJECT_RASTERIZER); + + if (!state) { + report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_HANDLE, handle); + return; + } + + ctx->rs_state = *state; + ctx->scissor_state_dirty = TRUE; + grend_hw_emit_rs(ctx); +} + +static GLuint convert_wrap(int wrap) +{ + switch(wrap){ + case PIPE_TEX_WRAP_REPEAT: return GL_REPEAT; + case PIPE_TEX_WRAP_CLAMP: return GL_CLAMP; + + case PIPE_TEX_WRAP_CLAMP_TO_EDGE: return GL_CLAMP_TO_EDGE; + case PIPE_TEX_WRAP_CLAMP_TO_BORDER: return GL_CLAMP_TO_BORDER; + + case PIPE_TEX_WRAP_MIRROR_REPEAT: return GL_MIRRORED_REPEAT; + case PIPE_TEX_WRAP_MIRROR_CLAMP: return GL_MIRROR_CLAMP_EXT; + case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: return GL_MIRROR_CLAMP_TO_EDGE_EXT; + case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: return GL_MIRROR_CLAMP_TO_BORDER_EXT; + default: + assert(0); + return -1; + } +} + +void grend_bind_sampler_states(struct grend_context *ctx, + uint32_t shader_type, + uint32_t start_slot, + uint32_t num_states, + uint32_t *handles) +{ + int i; + struct pipe_sampler_state *state; + + ctx->num_sampler_states[shader_type] = num_states; + + for (i = 0; i < num_states; i++) { + if (handles[i] == 0) + state = NULL; + else + state = vrend_object_lookup(ctx->object_hash, handles[i], VIRGL_OBJECT_SAMPLER_STATE); + + ctx->sampler_state[shader_type][i + start_slot] = state; + } + ctx->sampler_state_dirty = TRUE; +} + +static inline GLenum convert_mag_filter(unsigned int filter) +{ + if (filter == PIPE_TEX_FILTER_NEAREST) + return GL_NEAREST; + return GL_LINEAR; +} + +static inline GLenum convert_min_filter(unsigned int filter, unsigned int mip_filter) +{ + if (mip_filter == PIPE_TEX_MIPFILTER_NONE) + return convert_mag_filter(filter); + else if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) { + if (filter == PIPE_TEX_FILTER_NEAREST) + return GL_NEAREST_MIPMAP_LINEAR; + else + return GL_LINEAR_MIPMAP_LINEAR; + } else if (mip_filter == PIPE_TEX_MIPFILTER_NEAREST) { + if (filter == PIPE_TEX_FILTER_NEAREST) + return GL_NEAREST_MIPMAP_NEAREST; + else + return GL_LINEAR_MIPMAP_NEAREST; + } + assert(0); + return 0; +} + +static void grend_apply_sampler_state(struct grend_context *ctx, + struct grend_resource *res, + uint32_t shader_type, + int id) +{ + struct grend_texture *tex = (struct grend_texture *)res; + struct pipe_sampler_state *state = ctx->sampler_state[shader_type][id]; + bool set_all = FALSE; + GLenum target = tex->base.target; + + if (!state) { + fprintf(stderr, "cannot find sampler state for %d %d\n", shader_type, id); + return; + } + if (res->base.nr_samples > 1) { + tex->state = *state; + return; + } + + if (tex->state.max_lod == -1) + set_all = TRUE; + + if (tex->state.wrap_s != state->wrap_s || set_all) + glTexParameteri(target, GL_TEXTURE_WRAP_S, convert_wrap(state->wrap_s)); + if (tex->state.wrap_t != state->wrap_t || set_all) + glTexParameteri(target, GL_TEXTURE_WRAP_T, convert_wrap(state->wrap_t)); + if (tex->state.wrap_r != state->wrap_r || set_all) + glTexParameteri(target, GL_TEXTURE_WRAP_R, convert_wrap(state->wrap_r)); + if (tex->state.min_img_filter != state->min_img_filter || + tex->state.min_mip_filter != state->min_mip_filter || set_all) + glTexParameterf(target, GL_TEXTURE_MIN_FILTER, convert_min_filter(state->min_img_filter, state->min_mip_filter)); + if (tex->state.mag_img_filter != state->mag_img_filter || set_all) + glTexParameterf(target, GL_TEXTURE_MAG_FILTER, convert_mag_filter(state->mag_img_filter)); + if (res->target != GL_TEXTURE_RECTANGLE) { + if (tex->state.min_lod != state->min_lod || set_all) + glTexParameterf(target, GL_TEXTURE_MIN_LOD, state->min_lod); + if (tex->state.max_lod != state->max_lod || set_all) + glTexParameterf(target, GL_TEXTURE_MAX_LOD, state->max_lod); + if (tex->state.lod_bias != state->lod_bias || set_all) + glTexParameterf(target, GL_TEXTURE_LOD_BIAS, state->lod_bias); + } + + if (tex->state.compare_mode != state->compare_mode || set_all) + glTexParameteri(target, GL_TEXTURE_COMPARE_MODE, state->compare_mode ? GL_COMPARE_R_TO_TEXTURE : GL_NONE); + if (tex->state.compare_func != state->compare_func || set_all) + glTexParameteri(target, GL_TEXTURE_COMPARE_FUNC, GL_NEVER + state->compare_func); + + if (memcmp(&tex->state.border_color, &state->border_color, 16) || set_all) + glTexParameterIuiv(target, GL_TEXTURE_BORDER_COLOR, state->border_color.ui); + tex->state = *state; +} + +void grend_flush(struct grend_context *ctx) +{ + glFlush(); +} + +void grend_flush_frontbuffer(uint32_t res_handle) +{ +} + +static GLenum tgsitargettogltarget(const enum pipe_texture_target target, int nr_samples) +{ + switch(target) { + case PIPE_TEXTURE_1D: + return GL_TEXTURE_1D; + case PIPE_TEXTURE_2D: + return (nr_samples > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D; + case PIPE_TEXTURE_3D: + return GL_TEXTURE_3D; + case PIPE_TEXTURE_RECT: + return GL_TEXTURE_RECTANGLE_NV; + case PIPE_TEXTURE_CUBE: + return GL_TEXTURE_CUBE_MAP; + + case PIPE_TEXTURE_1D_ARRAY: + return GL_TEXTURE_1D_ARRAY; + case PIPE_TEXTURE_2D_ARRAY: + return (nr_samples > 1) ? GL_TEXTURE_2D_MULTISAMPLE_ARRAY : GL_TEXTURE_2D_ARRAY; + case PIPE_TEXTURE_CUBE_ARRAY: + return GL_TEXTURE_CUBE_MAP_ARRAY; + case PIPE_BUFFER: + default: + return PIPE_BUFFER; + } + return PIPE_BUFFER; +} + +static int inited; + +void graw_renderer_init(struct grend_if_cbs *cbs) +{ + if (!inited) { + inited = 1; + vrend_object_init_resource_table(); + clicbs = cbs; + } + int gl_ver = epoxy_gl_version(); +#define glewIsSupported epoxy_has_gl_extension + if (glewIsSupported("GL_ARB_robustness")) + grend_state.have_robustness = TRUE; + else + fprintf(stderr,"WARNING: running without ARB robustness in place may crash\n"); + + if (gl_ver >= 33 || glewIsSupported("GL_ARB_shader_bit_encoding")) + grend_state.have_bit_encoding = TRUE; + if (gl_ver >= 31) + grend_state.have_gl_prim_restart = TRUE; + else if (glewIsSupported("GL_NV_primitive_restart")) + grend_state.have_nv_prim_restart = TRUE; + + if (glewIsSupported("GL_EXT_framebuffer_multisample") && glewIsSupported("GL_ARB_texture_multisample")) { + grend_state.have_multisample = true; + } + + /* callbacks for when we are cleaning up the object table */ + vrend_object_set_destroy_callback(VIRGL_OBJECT_QUERY, grend_destroy_query_object); + vrend_object_set_destroy_callback(VIRGL_OBJECT_SURFACE, grend_destroy_surface_object); + vrend_object_set_destroy_callback(VIRGL_OBJECT_VS, grend_destroy_shader_object); + vrend_object_set_destroy_callback(VIRGL_OBJECT_FS, grend_destroy_shader_object); + vrend_object_set_destroy_callback(VIRGL_OBJECT_SAMPLER_VIEW, grend_destroy_sampler_view_object); + vrend_object_set_destroy_callback(VIRGL_OBJECT_STREAMOUT_TARGET, grend_destroy_so_target_object); + + vrend_build_format_list(); + grend_state.viewport_dirty = grend_state.scissor_dirty = TRUE; + grend_state.program_id = (GLuint)-1; + list_inithead(&grend_state.fence_list); + list_inithead(&grend_state.waiting_query_list); + + graw_cursor_init(&grend_state.cursor_info); + /* create 0 context */ + graw_renderer_context_create_internal(0, 0, NULL); +} + +void +graw_renderer_fini(void) +{ + if (!inited) + return; + + vrend_object_fini_resource_table(); + inited = 0; +} + +bool grend_destroy_context(struct grend_context *ctx) +{ + bool switch_0 = (ctx == grend_state.current_ctx); + int i; + + if (switch_0) { + grend_state.current_ctx = NULL; + grend_state.current_hw_ctx = NULL; + } + + /* reset references on framebuffers */ + grend_set_framebuffer_state(ctx, 0, NULL, 0); + + grend_set_num_sampler_views(ctx, PIPE_SHADER_VERTEX, 0, 0); + grend_set_num_sampler_views(ctx, PIPE_SHADER_FRAGMENT, 0, 0); + + grend_set_streamout_targets(ctx, 0, 0, NULL); + grend_set_num_vbo(ctx, 0); + + grend_set_index_buffer(ctx, 0, 0, 0); + + if (ctx->fb_id) + glDeleteFramebuffers(1, &ctx->fb_id); + + if (ctx->blit_fb_ids[0]) + glDeleteFramebuffers(2, ctx->blit_fb_ids); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + while (ctx->enabled_attribs_bitmask) { + i = u_bit_scan(&ctx->enabled_attribs_bitmask); + + glDisableVertexAttribArray(i); + } + + grend_bind_va(0); + + glDeleteVertexArrays(1, &ctx->vaoid); + + grend_free_programs(ctx); + + /* need to free any objects still in hash table - TODO */ + vrend_object_fini_ctx_table(ctx->object_hash); + + if (ctx->ctx_id != 0) + clicbs->destroy_gl_context(ctx->gl_context); + + FREE(ctx); + + return switch_0; +} + +struct grend_context *grend_create_context(int id, uint32_t nlen, const char *debug_name) +{ + struct grend_context *grctx = CALLOC_STRUCT(grend_context); + + if (nlen) { + strncpy(grctx->debug_name, debug_name, 64); + } + + grctx->gl_context = clicbs->create_gl_context(0); + clicbs->make_current(0, grctx->gl_context); + + grctx->ctx_id = id; + list_inithead(&grctx->programs); + list_inithead(&grctx->active_nontimer_query_list); + glGenVertexArrays(1, &grctx->vaoid); + glGenFramebuffers(1, &grctx->fb_id); + glGenFramebuffers(2, grctx->blit_fb_ids); + grctx->object_hash = vrend_object_init_ctx_table(); + + grend_bind_va(grctx->vaoid); + return grctx; +} + +int graw_renderer_resource_attach_iov(int res_handle, struct virgl_iovec *iov, + int num_iovs) +{ + struct grend_resource *res; + + res = vrend_resource_lookup(res_handle, 0); + if (!res) + return; + + /* work out size and max resource size */ + res->iov = iov; + res->num_iovs = num_iovs; + return 0; +} + +void graw_renderer_resource_invalid_iov(int res_handle) +{ + struct grend_resource *res; + res = vrend_resource_lookup(res_handle, 0); + if (!res) { + return; + } + + (*clicbs->inval_backing)(res->iov, res->num_iovs); + res->num_iovs = 0; + res->iov = 0; +} + +void graw_renderer_resource_create(struct graw_renderer_resource_create_args *args, struct virgl_iovec *iov, uint32_t num_iovs) +{ + struct grend_resource *gr = (struct grend_resource *)CALLOC_STRUCT(grend_texture); + int level; + + gr->handle = args->handle; + gr->iov = iov; + gr->num_iovs = num_iovs; + gr->base.width0 = args->width; + gr->base.height0 = args->height; + gr->base.depth0 = args->depth; + gr->base.format = args->format; + gr->base.target = args->target; + gr->base.last_level = args->last_level; + gr->base.nr_samples = args->nr_samples; + gr->base.array_size = args->array_size; + + if (args->flags & VIRGL_RESOURCE_Y_0_TOP) + gr->y_0_top = TRUE; + + pipe_reference_init(&gr->base.reference, 1); + + if (args->bind == PIPE_BIND_CUSTOM) { + /* custom shuold only be for buffers */ + gr->ptr = malloc(args->width); + } else if (args->bind == PIPE_BIND_INDEX_BUFFER) { + gr->target = GL_ELEMENT_ARRAY_BUFFER_ARB; + glGenBuffersARB(1, &gr->id); + glBindBufferARB(gr->target, gr->id); + glBufferData(gr->target, args->width, NULL, GL_STREAM_DRAW); + } else if (args->bind == PIPE_BIND_STREAM_OUTPUT) { + gr->target = GL_TRANSFORM_FEEDBACK_BUFFER; + glGenBuffersARB(1, &gr->id); + glBindBuffer(gr->target, gr->id); + glBufferData(gr->target, args->width, NULL, GL_STREAM_DRAW); + } else if (args->target == PIPE_BUFFER) { + gr->target = GL_ARRAY_BUFFER_ARB; + glGenBuffersARB(1, &gr->id); + glBindBufferARB(gr->target, gr->id); + glBufferData(gr->target, args->width, NULL, GL_STREAM_DRAW); + } else { + struct grend_texture *gt = (struct grend_texture *)gr; + GLenum internalformat, glformat, gltype; + gr->target = tgsitargettogltarget(args->target, args->nr_samples); + glGenTextures(1, &gr->id); + glBindTexture(gr->target, gr->id); + + internalformat = tex_conv_table[args->format].internalformat; + glformat = tex_conv_table[args->format].glformat; + gltype = tex_conv_table[args->format].gltype; + if (internalformat == 0) { + fprintf(stderr,"unknown format is %d\n", args->format); + return; + } + + if (args->nr_samples > 1) { + if (gr->target == GL_TEXTURE_2D_MULTISAMPLE) { + glTexImage2DMultisample(gr->target, args->nr_samples, + internalformat, args->width, args->height, + TRUE); + } else { + glTexImage3DMultisample(gr->target, args->nr_samples, + internalformat, args->width, args->height, args->array_size, + TRUE); + } + + } else if (gr->target == GL_TEXTURE_CUBE_MAP) { + int i; + for (i = 0; i < 6; i++) { + GLenum ctarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i; + for (level = 0; level <= args->last_level; level++) { + unsigned mwidth = u_minify(args->width, level); + unsigned mheight = u_minify(args->height, level); + glTexImage2D(ctarget, level, internalformat, mwidth, mheight, 0, glformat, + gltype, NULL); + } + } + } else if (gr->target == GL_TEXTURE_3D || gr->target == GL_TEXTURE_2D_ARRAY || gr->target == GL_TEXTURE_CUBE_MAP_ARRAY) { + for (level = 0; level <= args->last_level; level++) { + unsigned depth_param = (gr->target == GL_TEXTURE_2D_ARRAY || gr->target == GL_TEXTURE_CUBE_MAP_ARRAY) ? args->array_size : u_minify(args->depth, level); + unsigned mwidth = u_minify(args->width, level); + unsigned mheight = u_minify(args->height, level); + glTexImage3D(gr->target, level, internalformat, mwidth, mheight, depth_param, 0, + glformat, + gltype, NULL); + } + } else if (gr->target == GL_TEXTURE_1D) { + for (level = 0; level <= args->last_level; level++) { + unsigned mwidth = u_minify(args->width, level); + glTexImage1D(gr->target, level, internalformat, mwidth, 0, + glformat, + gltype, NULL); + } + } else { + for (level = 0; level <= args->last_level; level++) { + unsigned mwidth = u_minify(args->width, level); + unsigned mheight = u_minify(args->height, level); + glTexImage2D(gr->target, level, internalformat, mwidth, gr->target == GL_TEXTURE_1D_ARRAY ? args->array_size : mheight, 0, glformat, + gltype, NULL); + } + } + + gt->state.max_lod = -1; + gt->cur_swizzle_r = gt->cur_swizzle_g = gt->cur_swizzle_b = gt->cur_swizzle_a = -1; + } + + vrend_resource_insert(gr, sizeof(*gr), args->handle); +} + +void graw_renderer_resource_destroy(struct grend_resource *res) +{ + if (res->scannedout) + (*clicbs->scanout_resource_info)(0, res->id, 0, 0, 0, 0, 0); + + if (res->readback_fb_id) + glDeleteFramebuffers(1, &res->readback_fb_id); + + if (res->ptr) + free(res->ptr); + if (res->id) { + if (res->target == GL_ELEMENT_ARRAY_BUFFER_ARB || + res->target == GL_ARRAY_BUFFER_ARB || + res->target == GL_TRANSFORM_FEEDBACK_BUFFER) { + glDeleteBuffers(1, &res->id); + } else + glDeleteTextures(1, &res->id); + } + + if (res->handle) + vrend_resource_remove(res->handle); + free(res); +} + + +void graw_renderer_resource_unref(uint32_t res_handle) +{ + struct grend_resource *res; + + res = vrend_resource_lookup(res_handle, 0); + if (!res) + return; + + if (res->iov) { + (*clicbs->inval_backing)(res->iov, res->num_iovs); + } + vrend_resource_remove(res->handle); + res->handle = 0; + + grend_resource_reference(&res, NULL); +} + +static int use_sub_data = 0; +struct virgl_sub_upload_data { + GLenum target; + struct pipe_box *box; +}; + +static void iov_buffer_upload(void *cookie, uint32_t doff, void *src, int len) +{ + struct virgl_sub_upload_data *d = cookie; + glBufferSubData(d->target, d->box->x + doff, len, src); +} + +static void copy_transfer_data(struct pipe_resource *res, + struct virgl_iovec *iov, + unsigned int num_iovs, + void *data, + uint32_t src_stride, + struct pipe_box *box, + uint64_t offset) +{ + int blsize = util_format_get_blocksize(res->format); + GLuint size = graw_iov_size(iov, num_iovs); + GLuint send_size = util_format_get_nblocks(res->format, box->width, + box->height) * blsize * box->depth; + GLuint bwx = util_format_get_nblocksx(res->format, box->width) * blsize; + GLuint bh = util_format_get_nblocksy(res->format, box->height); + int h; + uint32_t myoffset = offset; + + if (send_size == size || bh == 1) + graw_iov_to_buf(iov, num_iovs, offset, data, send_size); + else { + for (h = 0; h < bh; h++) { + void *ptr = data + (h * bwx); + graw_iov_to_buf(iov, num_iovs, myoffset, ptr, bwx); + myoffset += src_stride; + } + } +} + +void graw_renderer_transfer_write_iov(uint32_t res_handle, + uint32_t ctx_id, + int level, + uint32_t stride, + uint32_t layer_stride, + struct pipe_box *box, + uint64_t offset, + struct virgl_iovec *iov, + unsigned int num_iovs) +{ + struct grend_resource *res; + + void *data; + + res = vrend_resource_lookup(res_handle, ctx_id); + if (res == NULL) { + struct grend_context *ctx = vrend_lookup_renderer_ctx(ctx_id); + report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, res_handle); + return; + } + + if ((res->iov && !iov) || num_iovs == 0) { + iov = res->iov; + num_iovs = res->num_iovs; + } + + if (!iov) { + struct grend_context *ctx = vrend_lookup_renderer_ctx(ctx_id); + report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, res_handle); + return; + } + + grend_hw_switch_context(vrend_lookup_renderer_ctx(0), TRUE); + + if (res->target == 0 && res->ptr) { + graw_iov_to_buf(iov, num_iovs, offset, res->ptr + box->x, box->width); + return; + } + if (res->target == GL_TRANSFORM_FEEDBACK_BUFFER || + res->target == GL_ELEMENT_ARRAY_BUFFER_ARB || + res->target == GL_ARRAY_BUFFER_ARB) { + struct virgl_sub_upload_data d; + d.box = box; + d.target = res->target; + + glBindBufferARB(res->target, res->id); + if (use_sub_data == 1) { + graw_iov_to_buf_cb(iov, num_iovs, offset, box->width, &iov_buffer_upload, &d); + } else { + data = glMapBufferRange(res->target, box->x, box->width, GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_WRITE_BIT); + if (data == NULL) { + fprintf(stderr,"map failed for element buffer\n"); + graw_iov_to_buf_cb(iov, num_iovs, offset, box->width, &iov_buffer_upload, &d); + } else { + graw_iov_to_buf(iov, num_iovs, offset, data, box->width); + glUnmapBuffer(res->target); + } + } + } else { + GLenum glformat; + GLenum gltype; + int need_temp = 0; + int elsize = util_format_get_blocksize(res->base.format); + int x = 0, y = 0; + boolean compressed; + grend_use_program(0); + + if (!stride) + stride = util_format_get_nblocksx(res->base.format, u_minify(res->base.width0, level)) * elsize; + + compressed = util_format_is_compressed(res->base.format); + if (num_iovs > 1 || compressed) { + need_temp = 1; + } + + if (need_temp) { + GLuint send_size = util_format_get_nblocks(res->base.format, box->width, + box->height) * util_format_get_blocksize(res->base.format) * box->depth; + data = malloc(send_size); + copy_transfer_data(&res->base, iov, num_iovs, data, stride, + box, offset); + } else { + data = iov[0].iov_base + offset; + } + + if (stride && !need_temp) { + glPixelStorei(GL_UNPACK_ROW_LENGTH, stride / elsize); + } else + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + + switch (elsize) { + case 1: + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + break; + case 2: + glPixelStorei(GL_UNPACK_ALIGNMENT, 2); + break; + case 4: + default: + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + break; + case 8: + glPixelStorei(GL_UNPACK_ALIGNMENT, 8); + break; + } + + glformat = tex_conv_table[res->base.format].glformat; + gltype = tex_conv_table[res->base.format].gltype; + + if (res->is_front || res->y_0_top) { + if (!res->is_front) { + if (res->readback_fb_id == 0 || res->readback_fb_level != level) { + GLuint fb_id; + if (res->readback_fb_id) + glDeleteFramebuffers(1, &res->readback_fb_id); + + glGenFramebuffers(1, &fb_id); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb_id); + grend_fb_bind_texture(res, 0, level, 0); + + res->readback_fb_id = fb_id; + res->readback_fb_level = level; + } else { + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, res->readback_fb_id); + } + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + } else { + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glDrawBuffer(GL_BACK); + } + grend_blend_enable(GL_FALSE); + grend_depth_test_enable(GL_FALSE); + grend_alpha_test_enable(GL_FALSE); + grend_stencil_test_enable(GL_FALSE); + glPixelZoom(1.0f, res->y_0_top ? -1.0f : 1.0f); + glWindowPos2i(box->x, res->y_0_top ? res->base.height0 - box->y : box->y); + glDrawPixels(box->width, box->height, glformat, gltype, + data); + } else { + uint32_t comp_size; + glBindTexture(res->target, res->id); + + if (compressed) { + glformat = tex_conv_table[res->base.format].internalformat; + comp_size = util_format_get_nblocks(res->base.format, box->width, + box->height) * util_format_get_blocksize(res->base.format); + } + + if (glformat == 0) { + glformat = GL_BGRA; + gltype = GL_UNSIGNED_BYTE; + } + + x = box->x; + y = box->y; + + if (res->base.format == (enum pipe_format)VIRGL_FORMAT_Z24X8_UNORM) { + /* we get values from the guest as 24-bit scaled integers + but we give them to the host GL and it interprets them + as 32-bit scaled integers, so we need to scale them here */ + glPixelTransferf(GL_DEPTH_SCALE, 256.0); + } + if (res->target == GL_TEXTURE_CUBE_MAP) { + GLenum ctarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + box->z; + if (compressed) { + glCompressedTexSubImage2D(ctarget, level, x, y, + box->width, box->height, + glformat, comp_size, data); + } else { + glTexSubImage2D(ctarget, level, x, y, box->width, box->height, + glformat, gltype, data); + } + } else if (res->target == GL_TEXTURE_3D || res->target == GL_TEXTURE_2D_ARRAY || res->target == GL_TEXTURE_CUBE_MAP_ARRAY) { + if (compressed) { + glCompressedTexSubImage3D(res->target, level, x, y, box->z, + box->width, box->height, box->depth, + glformat, comp_size, data); + } else { + glTexSubImage3D(res->target, level, x, y, box->z, + box->width, box->height, box->depth, + glformat, gltype, data); + } + } else if (res->target == GL_TEXTURE_1D) { + if (compressed) { + glCompressedTexSubImage1D(res->target, level, box->x, + box->width, + glformat, comp_size, data); + } else { + glTexSubImage1D(res->target, level, box->x, box->width, + glformat, gltype, data); + } + } else { + if (compressed) { + glCompressedTexSubImage2D(res->target, level, x, res->target == GL_TEXTURE_1D_ARRAY ? box->z : y, + box->width, box->height, + glformat, comp_size, data); + } else { + glTexSubImage2D(res->target, level, x, res->target == GL_TEXTURE_1D_ARRAY ? box->z : y, + box->width, box->height, + glformat, gltype, data); + } + } + if (res->base.format == (enum pipe_format)VIRGL_FORMAT_Z24X8_UNORM) { + glPixelTransferf(GL_DEPTH_SCALE, 1.0); + } + } + if (stride && !need_temp) + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + + if (need_temp) + free(data); + } + +} + +static void vrend_transfer_send_getteximage(struct grend_resource *res, + uint32_t level, uint32_t stride, + struct pipe_box *box, uint64_t offset, + struct virgl_iovec *iov, int num_iovs) +{ + GLenum format, type; + uint32_t send_size, tex_size; + void *data; + int elsize = util_format_get_blocksize(res->base.format); + int compressed = util_format_is_compressed(res->base.format); + GLenum target; + uint32_t depth = 1; + uint32_t send_offset = 0; + format = tex_conv_table[res->base.format].glformat; + type = tex_conv_table[res->base.format].gltype; + + if (compressed) + format = tex_conv_table[res->base.format].internalformat; + + if (res->target == GL_TEXTURE_3D) + depth = u_minify(res->base.depth0, level); + else if (res->target == GL_TEXTURE_2D_ARRAY || res->target == GL_TEXTURE_1D_ARRAY || res->target == GL_TEXTURE_CUBE_MAP_ARRAY) + depth = res->base.array_size; + + tex_size = util_format_get_nblocks(res->base.format, u_minify(res->base.width0, level), u_minify(res->base.height0, level)) * util_format_get_blocksize(res->base.format) * depth; + + send_size = util_format_get_nblocks(res->base.format, box->width, box->height) * util_format_get_blocksize(res->base.format) * box->depth; + + if (box->z && res->target != GL_TEXTURE_CUBE_MAP) { + send_offset = util_format_get_nblocks(res->base.format, u_minify(res->base.width0, level), u_minify(res->base.height0, level)) * util_format_get_blocksize(res->base.format) * box->z; + } + + data = malloc(tex_size); + if (!data) + return; + + switch (elsize) { + case 1: + glPixelStorei(GL_PACK_ALIGNMENT, 1); + break; + case 2: + glPixelStorei(GL_PACK_ALIGNMENT, 2); + break; + case 4: + default: + glPixelStorei(GL_PACK_ALIGNMENT, 4); + break; + case 8: + glPixelStorei(GL_PACK_ALIGNMENT, 8); + break; + } + + glBindTexture(res->target, res->id); + if (res->target == GL_TEXTURE_CUBE_MAP) { + target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + box->z; + } else + target = res->target; + + if (compressed) { + if (grend_state.have_robustness) + glGetnCompressedTexImageARB(target, level, tex_size, data); + else + glGetCompressedTexImage(target, level, data); + } else { + if (grend_state.have_robustness) + glGetnTexImageARB(target, level, format, type, tex_size, data); + else + glGetTexImage(target, level, format, type, data); + } + + glPixelStorei(GL_PACK_ALIGNMENT, 4); + + graw_transfer_write_tex_return(&res->base, box, level, stride, offset, iov, num_iovs, data + send_offset, send_size, FALSE); + free(data); +} + +static void vrend_transfer_send_readpixels(struct grend_resource *res, + uint32_t level, uint32_t stride, + struct pipe_box *box, uint64_t offset, + struct virgl_iovec *iov, int num_iovs) +{ + void *myptr = iov[0].iov_base + offset; + int need_temp = 0; + GLuint fb_id; + void *data; + boolean actually_invert, separate_invert = FALSE; + GLenum format, type; + GLint y1; + uint32_t send_size = 0; + uint32_t h = u_minify(res->base.height0, level); + int elsize = util_format_get_blocksize(res->base.format); + + grend_use_program(0); + + format = tex_conv_table[res->base.format].glformat; + type = tex_conv_table[res->base.format].gltype; + /* if we are asked to invert and reading from a front then don't */ + + if (res->is_front) + actually_invert = FALSE; + else + actually_invert = res->y_0_top; + + if (actually_invert && !have_invert_mesa) + separate_invert = TRUE; + + if (num_iovs > 1 || separate_invert) + need_temp = 1; + + send_size = box->width * box->height * box->depth * util_format_get_blocksize(res->base.format); + + if (need_temp) { + data = malloc(send_size); + if (!data) + fprintf(stderr,"malloc failed %d\n", send_size); + } else + data = myptr; +// fprintf(stderr,"TEXTURE TRANSFER %d %d %d %d %d, temp:%d\n", res_handle, res->readback_fb_id, box->width, box->height, level, need_temp); + + if (!res->is_front) { + if (res->readback_fb_id == 0 || res->readback_fb_level != level || res->readback_fb_z != box->z) { + + if (res->readback_fb_id) + glDeleteFramebuffers(1, &res->readback_fb_id); + + glGenFramebuffers(1, &fb_id); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb_id); + + grend_fb_bind_texture(res, 0, level, box->z); + + res->readback_fb_id = fb_id; + res->readback_fb_level = level; + res->readback_fb_z = box->z; + } else { + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, res->readback_fb_id); + } + if (actually_invert) + y1 = h - box->y - box->height; + else + y1 = box->y; + + if (have_invert_mesa && actually_invert) + glPixelStorei(GL_PACK_INVERT_MESA, 1); + if (!vrend_format_is_ds(res->base.format)) + glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); + if (!need_temp && stride) + glPixelStorei(GL_PACK_ROW_LENGTH, stride); + } else { + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + y1 = box->y; + glReadBuffer(GL_BACK); + } + + switch (elsize) { + case 1: + glPixelStorei(GL_PACK_ALIGNMENT, 1); + break; + case 2: + glPixelStorei(GL_PACK_ALIGNMENT, 2); + break; + case 4: + default: + glPixelStorei(GL_PACK_ALIGNMENT, 4); + break; + case 8: + glPixelStorei(GL_PACK_ALIGNMENT, 8); + break; + } + + if (res->base.format == (enum pipe_format)VIRGL_FORMAT_Z24X8_UNORM) { + /* we get values from the guest as 24-bit scaled integers + but we give them to the host GL and it interprets them + as 32-bit scaled integers, so we need to scale them here */ + glPixelTransferf(GL_DEPTH_SCALE, 1.0/256.0); + } + if (grend_state.have_robustness) + glReadnPixelsARB(box->x, y1, box->width, box->height, format, type, send_size, data); + else + glReadPixels(box->x, y1, box->width, box->height, format, type, data); + + if (res->base.format == (enum pipe_format)VIRGL_FORMAT_Z24X8_UNORM) + glPixelTransferf(GL_DEPTH_SCALE, 1.0); + if (have_invert_mesa && actually_invert) + glPixelStorei(GL_PACK_INVERT_MESA, 0); + if (!need_temp && stride) + glPixelStorei(GL_PACK_ROW_LENGTH, 0); + glPixelStorei(GL_PACK_ALIGNMENT, 4); + if (need_temp) { + graw_transfer_write_tex_return(&res->base, box, level, stride, offset, iov, num_iovs, data, send_size, separate_invert); + free(data); + } +} + +void graw_renderer_transfer_send_iov(uint32_t res_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 num_iovs) +{ + struct grend_resource *res; + struct grend_context *ctx = vrend_lookup_renderer_ctx(ctx_id); + + res = vrend_resource_lookup(res_handle, ctx_id); + if (!res) { + report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, res_handle); + return; + } + + if (box->width + box->x > u_minify(res->base.width0, level) || + box->height + box->y > u_minify(res->base.height0, level)) + return; + + grend_hw_switch_context(vrend_lookup_renderer_ctx(0), TRUE); + + if (res->iov && (!iov || num_iovs == 0)) { + iov = res->iov; + num_iovs = res->num_iovs; + } + + if (!iov) { + report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, res_handle); + return; + } + + if (res->target == 0 && res->ptr) { + uint32_t send_size = box->width * util_format_get_blocksize(res->base.format); + graw_transfer_write_return(res->ptr + box->x, send_size, offset, iov, num_iovs); + } else if (res->target == GL_ELEMENT_ARRAY_BUFFER_ARB || + res->target == GL_ARRAY_BUFFER_ARB || + res->target == GL_TRANSFORM_FEEDBACK_BUFFER) { + uint32_t send_size = box->width * util_format_get_blocksize(res->base.format); + void *data; + glBindBufferARB(res->target, res->id); + data = glMapBufferRange(res->target, box->x, box->width, GL_MAP_READ_BIT); + if (!data) + fprintf(stderr,"unable to open buffer for reading %d\n", res->target); + else + graw_transfer_write_return(data, send_size, offset, iov, num_iovs); + glUnmapBuffer(res->target); + } else { + boolean can_readpixels = TRUE; + + can_readpixels = vrend_format_can_render(res->base.format) || vrend_format_is_ds(res->base.format); + + if (can_readpixels) { + vrend_transfer_send_readpixels(res, level, stride, box, offset, + iov, num_iovs); + return; + } + + vrend_transfer_send_getteximage(res, level, stride, box, offset, + iov, num_iovs); + + } +} + +void grend_set_stencil_ref(struct grend_context *ctx, + struct pipe_stencil_ref *ref) +{ + if (ctx->stencil_refs[0] != ref->ref_value[0] || + ctx->stencil_refs[1] != ref->ref_value[1]) { + ctx->stencil_refs[0] = ref->ref_value[0]; + ctx->stencil_refs[1] = ref->ref_value[1]; + ctx->stencil_state_dirty = TRUE; + } + +} + +static void grend_hw_emit_blend_color(struct grend_context *ctx) +{ + struct pipe_blend_color *color = &ctx->blend_color; + glBlendColor(color->color[0], color->color[1], color->color[2], + color->color[3]); +} + +void grend_set_blend_color(struct grend_context *ctx, + struct pipe_blend_color *color) +{ + ctx->blend_color = *color; + grend_hw_emit_blend_color(ctx); +} + +void grend_set_scissor_state(struct grend_context *ctx, + struct pipe_scissor_state *ss) +{ + ctx->ss = *ss; + ctx->scissor_state_dirty = TRUE; +} + +void grend_set_polygon_stipple(struct grend_context *ctx, + struct pipe_poly_stipple *ps) +{ + glPolygonStipple((const GLubyte *)ps->stipple); +} + +void grend_set_clip_state(struct grend_context *ctx, struct pipe_clip_state *ucp) +{ + int i, j; + GLdouble val[4]; + + for (i = 0; i < 8; i++) { + for (j = 0; j < 4; j++) + val[j] = ucp->ucp[i][j]; + glClipPlane(GL_CLIP_PLANE0 + i, val); + } +} + +void grend_set_sample_mask(struct grend_context *ctx, unsigned sample_mask) +{ + glSampleMaski(0, sample_mask); +} + + +static void grend_hw_emit_streamout_targets(struct grend_context *ctx) +{ + int i; + + for (i = 0; i < ctx->num_so_targets; i++) { + if (ctx->so_targets[i]->buffer_offset) + glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, i, ctx->so_targets[i]->buffer->id, ctx->so_targets[i]->buffer_offset, ctx->so_targets[i]->buffer_size); + else + glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, i, ctx->so_targets[i]->buffer->id); + } +} + +void grend_set_streamout_targets(struct grend_context *ctx, + uint32_t append_bitmask, + uint32_t num_targets, + uint32_t *handles) +{ + struct grend_so_target *target; + int i; + int old_num = ctx->num_so_targets; + + ctx->num_so_targets = num_targets; + for (i = 0; i < num_targets; i++) { + target = vrend_object_lookup(ctx->object_hash, handles[i], VIRGL_OBJECT_STREAMOUT_TARGET); + if (!target) { + report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_HANDLE, handles[i]); + return; + } + grend_so_target_reference(&ctx->so_targets[i], target); + } + + for (i = num_targets; i < old_num; i++) + grend_so_target_reference(&ctx->so_targets[i], NULL); + + grend_hw_emit_streamout_targets(ctx); +} + +static void vrend_resource_buffer_copy(struct grend_context *ctx, + struct grend_resource *src_res, + struct grend_resource *dst_res, + uint32_t dstx, uint32_t srcx, + uint32_t width) +{ + + glBindBuffer(GL_COPY_READ_BUFFER, src_res->id); + glBindBuffer(GL_COPY_WRITE_BUFFER, dst_res->id); + + glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, srcx, dstx, width); + glBindBuffer(GL_COPY_READ_BUFFER, 0); + glBindBuffer(GL_COPY_WRITE_BUFFER, 0); +} + +static void vrend_resource_copy_fallback(struct grend_context *ctx, + struct grend_resource *src_res, + struct grend_resource *dst_res, + uint32_t dst_level, + uint32_t dstx, uint32_t dsty, + uint32_t dstz, uint32_t src_level, + const struct pipe_box *src_box) +{ + void *tptr; + uint32_t transfer_size; + GLenum glformat, gltype; + int elsize = util_format_get_blocksize(dst_res->base.format); + int compressed = util_format_is_compressed(dst_res->base.format); + + if (src_res->base.format != dst_res->base.format) { + fprintf(stderr, "copy fallback failed due to mismatched formats %d %d\n", src_res->base.format, dst_res->base.format); + return; + } + + /* this is ugly need to do a full GetTexImage */ + transfer_size = util_format_get_nblocks(src_res->base.format, u_minify(src_res->base.width0, src_level), u_minify(src_res->base.height0, src_level)) * + u_minify(src_res->base.depth0, src_level) * util_format_get_blocksize(src_res->base.format); + + tptr = malloc(transfer_size); + if (!tptr) + return; + + glformat = tex_conv_table[src_res->base.format].glformat; + gltype = tex_conv_table[src_res->base.format].gltype; + + if (compressed) + glformat = tex_conv_table[src_res->base.format].internalformat; + + switch (elsize) { + case 1: + glPixelStorei(GL_PACK_ALIGNMENT, 1); + break; + case 2: + glPixelStorei(GL_PACK_ALIGNMENT, 2); + break; + case 4: + default: + glPixelStorei(GL_PACK_ALIGNMENT, 4); + break; + case 8: + glPixelStorei(GL_PACK_ALIGNMENT, 8); + break; + } + glBindTexture(src_res->target, src_res->id); + if (compressed) { + if (grend_state.have_robustness) + glGetnCompressedTexImageARB(src_res->target, src_level, transfer_size, tptr); + else + glGetCompressedTexImage(src_res->target, src_level, tptr); + } else { + if (grend_state.have_robustness) + glGetnTexImageARB(src_res->target, src_level, glformat, gltype, transfer_size, tptr); + else + glGetTexImage(src_res->target, src_level, glformat, gltype, tptr); + } + + glPixelStorei(GL_PACK_ALIGNMENT, 4); + switch (elsize) { + case 1: + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + break; + case 2: + glPixelStorei(GL_UNPACK_ALIGNMENT, 2); + break; + case 4: + default: + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + break; + case 8: + glPixelStorei(GL_UNPACK_ALIGNMENT, 8); + break; + } + + glBindTexture(dst_res->target, dst_res->id); + if (compressed) { + glCompressedTexSubImage2D(dst_res->target, dst_level, dstx, dsty, + src_box->width, src_box->height, + glformat, transfer_size, tptr); + } else { + glTexSubImage2D(dst_res->target, dst_level, dstx, dsty, src_box->width, src_box->height, glformat, gltype, tptr); + } + + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + free(tptr); +} + +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) +{ + struct grend_resource *src_res, *dst_res; + GLbitfield glmask = 0; + GLint sy1, sy2, dy1, dy2; + + if (ctx->in_error) + return; + + src_res = vrend_resource_lookup(src_handle, ctx->ctx_id); + dst_res = vrend_resource_lookup(dst_handle, ctx->ctx_id); + + if (!src_res) { + report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, src_handle); + return; + } + if (!dst_res) { + report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, dst_handle); + return; + } + + if (src_res->base.target == PIPE_BUFFER && dst_res->base.target == PIPE_BUFFER) { + /* do a buffer copy */ + vrend_resource_buffer_copy(ctx, src_res, dst_res, dstx, + src_box->x, src_box->width); + return; + } + + if (!vrend_format_can_render(src_res->base.format) || + !vrend_format_can_render(dst_res->base.format)) { + vrend_resource_copy_fallback(ctx, src_res, dst_res, dst_level, dstx, + dsty, dstz, src_level, src_box); + + return; + } + + glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->blit_fb_ids[0]); + grend_fb_bind_texture(src_res, 0, src_level, src_box->z); + + if (!dst_res->is_front) { + glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->blit_fb_ids[1]); + grend_fb_bind_texture(dst_res, 0, dst_level, dstz); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, ctx->blit_fb_ids[1]); + } else + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, ctx->blit_fb_ids[0]); + + glmask = GL_COLOR_BUFFER_BIT; + glDisable(GL_SCISSOR_TEST); + + if (!src_res->is_front && !src_res->y_0_top) { + sy1 = src_box->y; + sy2 = src_box->y + src_box->height; + } else { + sy1 = src_res->base.height0 - src_box->y - src_box->height; + sy2 = src_res->base.height0 - src_box->y; + } + + if (!dst_res->is_front && !dst_res->y_0_top) { + dy1 = dsty; + dy2 = dsty + src_box->height; + } else { + dy1 = dst_res->base.height0 - dsty - src_box->height; + dy2 = dst_res->base.height0 - dsty; + } + + glBlitFramebuffer(src_box->x, sy1, + src_box->x + src_box->width, + sy2, + dstx, dy1, + dstx + src_box->width, + dy2, + glmask, GL_NEAREST); + +} + +static void graw_renderer_blit_int(struct grend_context *ctx, + uint32_t dst_handle, uint32_t src_handle, + const struct pipe_blit_info *info) +{ + struct grend_resource *src_res, *dst_res; + GLbitfield glmask = 0; + int src_y1, src_y2, dst_y1, dst_y2; + + if (ctx->in_error) + return; + + src_res = vrend_resource_lookup(src_handle, ctx->ctx_id); + dst_res = vrend_resource_lookup(dst_handle, ctx->ctx_id); + + if (!src_res) { + report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, src_handle); + return; + } + if (!dst_res) { + report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, dst_handle); + return; + } + + glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->blit_fb_ids[0]); + + grend_fb_bind_texture(src_res, 0, info->src.level, info->src.box.z); + + if (!dst_res->is_front) { + glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->blit_fb_ids[1]); + + grend_fb_bind_texture(dst_res, 0, info->dst.level, info->dst.box.z); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, ctx->blit_fb_ids[1]); + } else + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, ctx->blit_fb_ids[0]); + + if (info->mask & PIPE_MASK_Z) + glmask |= GL_DEPTH_BUFFER_BIT; + if (info->mask & PIPE_MASK_S) + glmask |= GL_STENCIL_BUFFER_BIT; + if (info->mask & PIPE_MASK_RGBA) + glmask |= GL_COLOR_BUFFER_BIT; + + if (!dst_res->is_front && !dst_res->y_0_top) { + dst_y1 = info->dst.box.y + info->dst.box.height; + dst_y2 = info->dst.box.y; + } else { + dst_y1 = dst_res->base.height0 - info->dst.box.y - info->dst.box.height; + dst_y2 = dst_res->base.height0 - info->dst.box.y; + } + + if ((!src_res->is_front && !src_res->y_0_top)) { + src_y1 = info->src.box.y + info->src.box.height; + src_y2 = info->src.box.y; + } else { + src_y1 = src_res->base.height0 - info->src.box.y - info->src.box.height; + src_y2 = src_res->base.height0 - info->src.box.y; + } + + if (info->scissor_enable) { + glScissor(info->scissor.minx, info->scissor.miny, info->scissor.maxx - info->scissor.minx, info->scissor.maxy - info->scissor.miny); + ctx->scissor_state_dirty = TRUE; + glEnable(GL_SCISSOR_TEST); + } else + glDisable(GL_SCISSOR_TEST); + + glBlitFramebuffer(info->src.box.x, + src_y1, + info->src.box.x + info->src.box.width, + src_y2, + info->dst.box.x, + dst_y1, + info->dst.box.x + info->dst.box.width, + dst_y2, + glmask, convert_mag_filter(info->filter)); + +} + +void graw_renderer_blit(struct grend_context *ctx, + uint32_t dst_handle, uint32_t src_handle, + const struct pipe_blit_info *info) +{ + graw_renderer_blit_int(ctx, dst_handle, src_handle, info); +} + +int graw_renderer_set_scanout(uint32_t res_handle, uint32_t scanout_id, uint32_t ctx_id, + struct pipe_box *box) +{ + struct grend_resource *res; + res = vrend_resource_lookup(res_handle, ctx_id); + if (!res) + return 0; + + grend_resource_reference(&frontbuffer[scanout_id], res); + front_box[scanout_id] = *box; + + { + int elsize = util_format_get_blocksize(res->base.format); + uint32_t stride; + stride = util_format_get_nblocksx(res->base.format, u_minify(res->base.width0, 0)) * elsize; + (*clicbs->scanout_resource_info)(scanout_id, res->id, res->y_0_top ? 1 : 0, stride, res->base.width0, res->base.height0, res->base.format); + res->scannedout = 1; + } + (*clicbs->scanout_rect_info)(scanout_id, res->id, box->x, box->y, box->width, box->height); + fprintf(stderr,"setting frontbuffer %d to %d\n", scanout_id, res_handle); + return 0; +} + +int graw_renderer_flush_buffer_res(struct grend_resource *res, + struct pipe_box *box) +{ + if (1 && !res->is_front) { + int i; + grend_hw_switch_context(vrend_lookup_renderer_ctx(0), TRUE); + + for (i = 0; i < MAX_SCANOUT; i++) { + if (clicbs->flush_scanout) + clicbs->flush_scanout(i, box->x, box->y, box->width, box->height); + } + } + + return 0; +} + +int graw_renderer_flush_buffer(uint32_t res_handle, + uint32_t ctx_id, + struct pipe_box *box) +{ + struct grend_resource *res; + int i; + bool found = false; + if (!localrender) + return 0; + + res = vrend_resource_lookup(res_handle, ctx_id); + if (!res) + return 0; + + for (i = 0; i < MAX_SCANOUT; i++) { + if (res == frontbuffer[i]) { + found = true; + } + } + + if (found == false) { + fprintf(stderr,"not the frontbuffer %d\n", res_handle); + return 0; + } + + return graw_renderer_flush_buffer_res(res, box); +} + +int graw_renderer_create_fence(int client_fence_id, uint32_t ctx_id) +{ + struct grend_fence *fence; + + fence = malloc(sizeof(struct grend_fence)); + if (!fence) + return -1; + + fence->ctx_id = ctx_id; + fence->fence_id = client_fence_id; + fence->syncobj = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + list_addtail(&fence->fences, &grend_state.fence_list); + return 0; +} + +void graw_renderer_check_fences(void) +{ + struct grend_fence *fence, *stor; + uint32_t latest_id = 0; + GLenum glret; + + if (!inited) + return; + + LIST_FOR_EACH_ENTRY_SAFE(fence, stor, &grend_state.fence_list, fences) { + glret = glClientWaitSync(fence->syncobj, 0, 0); + if (glret == GL_ALREADY_SIGNALED){ + latest_id = fence->fence_id; + list_del(&fence->fences); + glDeleteSync(fence->syncobj); + free(fence); + } + /* don't bother checking any subsequent ones */ + else if (glret == GL_TIMEOUT_EXPIRED) { + break; + } + } + + if (latest_id == 0) + return; + clicbs->write_fence(latest_id); +} + +static boolean graw_get_one_query_result(GLuint query_id, bool use_64, uint64_t *result) +{ + GLint ready; + GLuint passed; + GLuint64 pass64; + + glGetQueryObjectiv(query_id, GL_QUERY_RESULT_AVAILABLE_ARB, &ready); + + if (!ready) + return FALSE; + + if (use_64) { + glGetQueryObjectui64v(query_id, GL_QUERY_RESULT_ARB, &pass64); + *result = pass64; + } else { + glGetQueryObjectuiv(query_id, GL_QUERY_RESULT_ARB, &passed); + *result = passed; + } + return TRUE; +} + +static boolean graw_check_query(struct grend_query *query) +{ + uint64_t result; + struct virgl_host_query_state *state; + struct grend_nontimer_hw_query *hwq, *stor; + boolean ret; + + if (grend_is_timer_query(query->gltype)) { + ret = graw_get_one_query_result(query->timer_query_id, TRUE, &result); + if (ret == FALSE) + return FALSE; + goto out_write_val; + } + + /* for non-timer queries we have to iterate over all hw queries and remove and total them */ + LIST_FOR_EACH_ENTRY_SAFE(hwq, stor, &query->hw_queries, query_list) { + ret = graw_get_one_query_result(hwq->id, FALSE, &result); + if (ret == FALSE) + return FALSE; + + /* if this query is done drop it from the list */ + list_del(&hwq->query_list); + glDeleteQueries(1, &hwq->id); + FREE(hwq); + + query->current_total += result; + } + result = query->current_total; + +out_write_val: + state = query->res->ptr; + + state->result = result; + state->query_state = VIRGL_QUERY_STATE_DONE; + + query->current_total = 0; + return TRUE; +} + +void graw_renderer_check_queries(void) +{ + struct grend_query *query, *stor; + if (!inited) + return; + + LIST_FOR_EACH_ENTRY_SAFE(query, stor, &grend_state.waiting_query_list, waiting_queries) { + grend_hw_switch_context(vrend_lookup_renderer_ctx(query->ctx_id), TRUE); + if (graw_check_query(query) == TRUE) + list_delinit(&query->waiting_queries); + } +} + +static void grend_do_end_query(struct grend_query *q) +{ + glEndQuery(q->gltype); + q->active_hw = FALSE; +} + +static void grend_ctx_finish_queries(struct grend_context *ctx) +{ + struct grend_query *query; + + LIST_FOR_EACH_ENTRY(query, &ctx->active_nontimer_query_list, ctx_queries) { + if (query->active_hw == TRUE) + grend_do_end_query(query); + } +} + +static void grend_ctx_restart_queries(struct grend_context *ctx) +{ + struct grend_query *query; + struct grend_nontimer_hw_query *hwq; + + if (ctx->query_on_hw == TRUE) + return; + + ctx->query_on_hw = TRUE; + LIST_FOR_EACH_ENTRY(query, &ctx->active_nontimer_query_list, ctx_queries) { + if (query->active_hw == FALSE) { + hwq = grend_create_hw_query(query); + glBeginQuery(query->gltype, hwq->id); + query->active_hw = TRUE; + } + } +} + +/* stop all the nontimer queries running in the current context */ +void grend_stop_current_queries(void) +{ + if (grend_state.current_ctx && grend_state.current_ctx->query_on_hw) { + grend_ctx_finish_queries(grend_state.current_ctx); + grend_state.current_ctx->query_on_hw = FALSE; + } +} + +boolean grend_hw_switch_context(struct grend_context *ctx, boolean now) +{ + if (ctx == grend_state.current_ctx && ctx->ctx_switch_pending == FALSE) + return TRUE; + + if (ctx->ctx_id != 0 && ctx->in_error) { + return FALSE; + } + + ctx->ctx_switch_pending = TRUE; + if (now == TRUE) { + grend_finish_context_switch(ctx); + } + grend_state.current_ctx = ctx; + return TRUE; +} + +static void grend_finish_context_switch(struct grend_context *ctx) +{ + if (ctx->ctx_switch_pending == FALSE) + return; + ctx->ctx_switch_pending = FALSE; + + if (grend_state.current_hw_ctx == ctx) + return; + + grend_state.current_hw_ctx = ctx; + + clicbs->make_current(0, ctx->gl_context); + +#if 0 + /* re-emit all the state */ + grend_hw_emit_framebuffer_state(ctx); + grend_hw_emit_depth_range(ctx); + grend_hw_emit_blend(ctx); + grend_hw_emit_dsa(ctx); + grend_hw_emit_rs(ctx); + grend_hw_emit_blend_color(ctx); + grend_hw_emit_streamout_targets(ctx); + + ctx->stencil_state_dirty = TRUE; + ctx->scissor_state_dirty = TRUE; + ctx->viewport_state_dirty = TRUE; + ctx->shader_dirty = TRUE; +#endif +} + + +void +graw_renderer_object_destroy(struct grend_context *ctx, uint32_t handle) +{ + vrend_object_remove(ctx->object_hash, handle, 0); +} + +void graw_renderer_object_insert(struct grend_context *ctx, void *data, + uint32_t size, uint32_t handle, enum virgl_object_type type) +{ + vrend_object_insert(ctx->object_hash, data, size, handle, type); +} + +static struct grend_nontimer_hw_query *grend_create_hw_query(struct grend_query *query) +{ + struct grend_nontimer_hw_query *hwq; + + hwq = CALLOC_STRUCT(grend_nontimer_hw_query); + if (!hwq) + return NULL; + + glGenQueries(1, &hwq->id); + + list_add(&hwq->query_list, &query->hw_queries); + return hwq; +} + + +void grend_create_query(struct grend_context *ctx, uint32_t handle, + uint32_t query_type, uint32_t res_handle, + uint32_t offset) +{ + struct grend_query *q; + struct grend_resource *res; + + res = vrend_resource_lookup(res_handle, ctx->ctx_id); + if (!res) { + report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, res_handle); + return; + } + + q = CALLOC_STRUCT(grend_query); + if (!q) + return; + + list_inithead(&q->waiting_queries); + list_inithead(&q->ctx_queries); + list_inithead(&q->hw_queries); + q->type = query_type; + q->ctx_id = ctx->ctx_id; + + grend_resource_reference(&q->res, res); + + switch (q->type) { + case PIPE_QUERY_OCCLUSION_COUNTER: + q->gltype = GL_SAMPLES_PASSED_ARB; + break; + case PIPE_QUERY_OCCLUSION_PREDICATE: + q->gltype = GL_ANY_SAMPLES_PASSED; + break; + case PIPE_QUERY_TIMESTAMP: + q->gltype = GL_TIMESTAMP; + break; + case PIPE_QUERY_TIME_ELAPSED: + q->gltype = GL_TIME_ELAPSED; + break; + case PIPE_QUERY_PRIMITIVES_GENERATED: + q->gltype = GL_PRIMITIVES_GENERATED; + break; + case PIPE_QUERY_PRIMITIVES_EMITTED: + q->gltype = GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN; + break; + default: + fprintf(stderr,"unknown query object received %d\n", q->type); + break; + } + + if (grend_is_timer_query(q->gltype)) + glGenQueries(1, &q->timer_query_id); + + graw_renderer_object_insert(ctx, q, sizeof(struct grend_query), handle, + VIRGL_OBJECT_QUERY); +} + +static void grend_destroy_query(struct grend_query *query) +{ + struct grend_nontimer_hw_query *hwq, *stor; + + grend_resource_reference(&query->res, NULL); + list_del(&query->ctx_queries); + list_del(&query->waiting_queries); + if (grend_is_timer_query(query->gltype)) { + glDeleteQueries(1, &query->timer_query_id); + return; + } + LIST_FOR_EACH_ENTRY_SAFE(hwq, stor, &query->hw_queries, query_list) { + glDeleteQueries(1, &hwq->id); + FREE(hwq); + } + free(query); +} + +static void grend_destroy_query_object(void *obj_ptr) +{ + struct grend_query *query = obj_ptr; + grend_destroy_query(query); +} + +void grend_begin_query(struct grend_context *ctx, uint32_t handle) +{ + struct grend_query *q; + struct grend_nontimer_hw_query *hwq; + + q = vrend_object_lookup(ctx->object_hash, handle, VIRGL_OBJECT_QUERY); + if (!q) + return; + + if (q->gltype == GL_TIMESTAMP) + return; + + if (grend_is_timer_query(q->gltype)) { + glBeginQuery(q->gltype, q->timer_query_id); + return; + } + hwq = grend_create_hw_query(q); + + /* add to active query list for this context */ + glBeginQuery(q->gltype, hwq->id); + + q->active_hw = TRUE; + list_addtail(&q->ctx_queries, &ctx->active_nontimer_query_list); +} + +void grend_end_query(struct grend_context *ctx, uint32_t handle) +{ + struct grend_query *q; + q = vrend_object_lookup(ctx->object_hash, handle, VIRGL_OBJECT_QUERY); + if (!q) + return; + + if (grend_is_timer_query(q->gltype)) { + if (q->gltype == GL_TIMESTAMP) + glQueryCounter(q->timer_query_id, q->gltype); + /* remove from active query list for this context */ + else + glEndQuery(q->gltype); + return; + } + + if (q->active_hw) + grend_do_end_query(q); + + list_delinit(&q->ctx_queries); +} + +void grend_get_query_result(struct grend_context *ctx, uint32_t handle, + uint32_t wait) +{ + struct grend_query *q; + boolean ret; + + q = vrend_object_lookup(ctx->object_hash, handle, VIRGL_OBJECT_QUERY); + if (!q) + return; + + ret = graw_check_query(q); + if (ret == FALSE) + list_addtail(&q->waiting_queries, &grend_state.waiting_query_list); +} + +void grend_render_condition(struct grend_context *ctx, + uint32_t handle, + boolean condtion, + uint mode) +{ + struct grend_query *q; + GLenum glmode; + struct grend_nontimer_hw_query *hwq, *last; + + if (handle == 0) { + glEndConditionalRenderNV(); + return; + } + + q = vrend_object_lookup(ctx->object_hash, handle, VIRGL_OBJECT_QUERY); + if (!q) + return; + + switch (mode) { + case PIPE_RENDER_COND_WAIT: + glmode = GL_QUERY_WAIT; + break; + case PIPE_RENDER_COND_NO_WAIT: + glmode = GL_QUERY_NO_WAIT; + break; + case PIPE_RENDER_COND_BY_REGION_WAIT: + glmode = GL_QUERY_BY_REGION_WAIT; + break; + case PIPE_RENDER_COND_BY_REGION_NO_WAIT: + glmode = GL_QUERY_BY_REGION_NO_WAIT; + break; + } + + LIST_FOR_EACH_ENTRY(hwq, &q->hw_queries, query_list) + last = hwq; + + glBeginConditionalRender(last->id, glmode); + +} + +void grend_set_query_state(struct grend_context *ctx, + boolean enabled) +{ + +} + +void grend_set_cursor_info(uint32_t cursor_handle, int x, int y) +{ + grend_state.cursor_info.res_handle = cursor_handle; + grend_state.cursor_info.x = x; + grend_state.cursor_info.y = y; + +// if (frontbuffer && draw_cursor) +// graw_renderer_remove_cursor(&grend_state.cursor_info, frontbuffer); +} + +void grend_create_so_target(struct grend_context *ctx, + uint32_t handle, + uint32_t res_handle, + uint32_t buffer_offset, + uint32_t buffer_size) +{ + struct grend_so_target *target; + struct grend_resource *res; + + res = vrend_resource_lookup(res_handle, ctx->ctx_id); + if (!res) { + report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, res_handle); + return; + } + + target = CALLOC_STRUCT(grend_so_target); + if (!target) + return; + + pipe_reference_init(&target->reference, 1); + target->res_handle = res_handle; + target->buffer_offset = buffer_offset; + target->buffer_size = buffer_size; + + grend_resource_reference(&target->buffer, res); + + vrend_object_insert(ctx->object_hash, target, sizeof(*target), handle, + VIRGL_OBJECT_STREAMOUT_TARGET); +} + +static void vrender_get_glsl_version(int *major, int *minor) +{ + int major_local, minor_local; + const GLubyte *version_str; + int c; + + version_str = glGetString(GL_SHADING_LANGUAGE_VERSION); + c = sscanf((const char *)version_str, "%i.%i", + &major_local, &minor_local); + assert(c == 2); + + if (major) + *major = major_local; + if (minor) + *minor = minor_local; +} + +void graw_renderer_fill_caps(uint32_t set, uint32_t version, + union virgl_caps *caps) +{ + int i; + GLint max; + int glsl_major, glsl_minor; + int gl_ver = epoxy_gl_version(); + memset(caps, 0, sizeof(*caps)); + + if (set != 0) { + caps->max_version = 0; + return; + } + vrender_get_glsl_version(&glsl_major, &glsl_minor); + caps->max_version = 1; + + caps->v1.bset.occlusion_query = 1; + if (gl_ver >= 30) { + caps->v1.bset.indep_blend_enable = 1; + caps->v1.bset.conditional_render = 1; + } else { + if (glewIsSupported("GL_EXT_draw_buffers2")) + caps->v1.bset.indep_blend_enable = 1; + if (glewIsSupported("GL_NV_conditional_render")) + caps->v1.bset.conditional_render = 1; + } + + if (gl_ver >= 31) { + caps->v1.bset.instanceid = 1; + } else { + if (glewIsSupported("GL_ARB_draw_instanced")) + caps->v1.bset.instanceid = 1; + } + + if (grend_state.have_nv_prim_restart || grend_state.have_gl_prim_restart) + caps->v1.bset.primitive_restart = 1; + + if (gl_ver >= 32) { + caps->v1.bset.fragment_coord_conventions = 1; + } else { + if (glewIsSupported("GL_ARB_fragment_coord_conventions")) + caps->v1.bset.fragment_coord_conventions = 1; + } + + if (glewIsSupported("GL_ARB_texture_multisample")) { + /* disable multisample until developed */ + caps->v1.bset.texture_multisample = 1; + } + if (gl_ver >= 40) { + caps->v1.bset.indep_blend_func = 1; + caps->v1.bset.cube_map_array = 1; + } else { + if (glewIsSupported("GL_ARB_draw_buffers_blend")) + caps->v1.bset.indep_blend_func = 1; + if (glewIsSupported("GL_ARB_texture_cube_map_array")) + caps->v1.bset.cube_map_array = 1; + } + + if (gl_ver >= 42) { + caps->v1.bset.start_instance = 1; + } else { + if (glewIsSupported("GL_ARB_base_instance")) + caps->v1.bset.start_instance = 1; + } + if (glewIsSupported("GL_ARB_shader_stencil_export")) + caps->v1.bset.shader_stencil_export = 1; + + caps->v1.glsl_level = 130; + if (glewIsSupported("GL_EXT_texture_array")) + caps->v1.max_texture_array_layers = 256; + caps->v1.max_streamout_buffers = 4; + if (glewIsSupported("GL_ARB_blend_func_extended")) { + glGetIntegerv(GL_MAX_DUAL_SOURCE_DRAW_BUFFERS, &max); + caps->v1.max_dual_source_render_targets = max; + } else + caps->v1.max_dual_source_render_targets = 0; + + glGetIntegerv(GL_MAX_DRAW_BUFFERS, &max); + caps->v1.max_render_targets = max; + + glGetIntegerv(GL_MAX_SAMPLES, &max); + caps->v1.max_samples = max; + + for (i = 0; i < VIRGL_FORMAT_MAX; i++) { + uint32_t offset = i / 32; + uint32_t index = i % 32; + + if (tex_conv_table[i].internalformat != 0) { + caps->v1.sampler.bitmask[offset] |= (1 << index); + if (vrend_format_can_render(i)) + caps->v1.render.bitmask[offset] |= (1 << index); + } + } + +} + +GLint64 graw_renderer_get_timestamp(void) +{ + GLint64 v; + glGetInteger64v(GL_TIMESTAMP, &v); + return v; +} + +void *graw_renderer_get_cursor_contents(uint32_t res_handle, uint32_t *width, uint32_t *height) +{ + GLenum format, type; + struct grend_resource *res; + int blsize; + void *data, *data2; + int size; + int h; + + res = vrend_resource_lookup(res_handle, 0); + if (!res) + return NULL; + + if (res->base.width0 > 128 || res->base.height0 > 128) + return NULL; + + if (res->target != GL_TEXTURE_2D) + return NULL; + + *width = res->base.width0; + *height = res->base.height0; + format = tex_conv_table[res->base.format].glformat; + type = tex_conv_table[res->base.format].gltype; + blsize = util_format_get_blocksize(res->base.format); + size = util_format_get_nblocks(res->base.format, res->base.width0, res->base.height0) * blsize; + data = malloc(size); + data2 = malloc(size); + + glBindTexture(res->target, res->id); + glGetnTexImageARB(res->target, 0, format, type, size, data); + + for (h = 0; h < res->base.height0; h++) { + uint32_t doff = (res->base.height0 - h - 1) * res->base.width0 * blsize; + uint32_t soff = h * res->base.width0 * blsize; + + memcpy(data2 + doff, data + soff, res->base.width0 * blsize); + } + free(data); + + return data2; +} + +void graw_renderer_force_ctx_0(void) +{ + grend_state.current_ctx = NULL; + grend_state.current_hw_ctx = NULL; + grend_hw_switch_context(vrend_lookup_renderer_ctx(0), TRUE); +} + +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) +{ + struct grend_resource *res = frontbuffer[idx]; + struct pipe_box box; + int elsize = util_format_get_blocksize(res->base.format); + int stride; + box.x = x; + box.y = y; + box.z = 0; + box.width = width; + box.height = height; + box.depth = 1; + + stride = util_format_get_nblocksx(res->base.format, res->base.width0) * elsize; + graw_renderer_transfer_send_iov(res->handle, 0, + 0, stride, 0, &box, offset, iov, num_iovs); +} + +void graw_renderer_dump_resource(void *data) +{ + struct grend_resource *res = data; + + fprintf(stderr, "target %d, width, height %dx%d\n", res->target, res->base.width0, res->base.height0); + +} diff --git a/src/graw_renderer.h b/src/graw_renderer.h new file mode 100644 index 0000000..14f3367 --- /dev/null +++ b/src/graw_renderer.h @@ -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 diff --git a/src/graw_renderer_helper.c b/src/graw_renderer_helper.c new file mode 100644 index 0000000..099f62e --- /dev/null +++ b/src/graw_renderer_helper.c @@ -0,0 +1,72 @@ +/* helper library for qemu local renderers like SDL / GTK + flushes the given texture to the frontbuffer */ +#include +#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); +} diff --git a/src/graw_shader.c b/src/graw_shader.c new file mode 100644 index 0000000..55bd893 --- /dev/null +++ b/src/graw_shader.c @@ -0,0 +1,1612 @@ + +#include "tgsi/tgsi_info.h" +#include "tgsi/tgsi_iterate.h" +#include +#include +#include +#include "graw_shader.h" +extern int vrend_dump_shaders; +/* + * TODO list + * loops + * DDX/DDY/TXD + * missing opcodes + */ + +/* start convert of tgsi to glsl */ + +#define INTERP_PREFIX " " + +int graw_shader_use_explicit = 0; + +struct graw_shader_io { + unsigned name; + unsigned gpr; + unsigned done; + int sid; + unsigned interpolate; + boolean centroid; + unsigned first; + boolean glsl_predefined_no_emit; + boolean glsl_no_index; + boolean override_no_wm; + char glsl_name[64]; +}; + +struct graw_shader_sampler { + int tgsi_sampler_type; +}; + +struct immed { + int type; + union imm { + uint32_t ui; + int32_t i; + float f; + } val[4]; +}; + +struct dump_ctx { + struct tgsi_iterate_context iter; + int prog_type; + char *glsl_main; + int size; + uint instno; + + int num_interps; + int num_inputs; + struct graw_shader_io inputs[32]; + int num_outputs; + struct graw_shader_io outputs[32]; + int num_system_values; + struct graw_shader_io system_values[32]; + + int num_temps; + struct graw_shader_sampler samplers[32]; + uint32_t samplers_used; + int num_consts; + + int num_imm; + struct immed imm[32]; + unsigned fragcoord_input; + + int num_address; + + struct pipe_stream_output_info *so; + boolean uses_cube_array; + boolean uses_sampler_ms; + /* create a shader with lower left if upper left is primary variant + or vice versa */ + uint32_t shadow_samp_mask; + boolean write_all_cbufs; + int fs_coord_origin, fs_pixel_center; + + struct vrend_shader_key *key; + boolean has_ints; + boolean has_instanceid; + int indent_level; + int num_clip_dist; + +}; + +static inline boolean fs_emit_layout(struct dump_ctx *ctx) +{ + if (ctx->fs_pixel_center) + return TRUE; + /* if coord origin is 0 and invert is 0 - emit origin_upper_left, + if coord_origin is 0 and invert is 1 - emit nothing (lower) + if coord origin is 1 and invert is 0 - emit nothing (lower) + if coord_origin is 1 and invert is 1 - emit origin upper left */ + if (!(ctx->fs_coord_origin ^ ctx->key->invert_fs_origin)) + return TRUE; + return FALSE; +} + +static boolean +iter_declaration(struct tgsi_iterate_context *iter, + struct tgsi_full_declaration *decl ) +{ + struct dump_ctx *ctx = (struct dump_ctx *)iter; + int i; + int color_offset = 0; + char *name_prefix = ""; + + ctx->prog_type = iter->processor.Processor; + switch (decl->Declaration.File) { + case TGSI_FILE_INPUT: + i = ctx->num_inputs++; + ctx->inputs[i].name = decl->Semantic.Name; + ctx->inputs[i].sid = decl->Semantic.Index; + ctx->inputs[i].interpolate = decl->Interp.Interpolate; + ctx->inputs[i].centroid = decl->Interp.Centroid; + ctx->inputs[i].first = decl->Range.First; + ctx->inputs[i].glsl_predefined_no_emit = FALSE; + ctx->inputs[i].glsl_no_index = FALSE; + ctx->inputs[i].override_no_wm = FALSE; + + switch (ctx->inputs[i].name) { + case TGSI_SEMANTIC_COLOR: + if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT) { + if (decl->Semantic.Index == 0) + name_prefix = "gl_Color"; + else if (decl->Semantic.Index == 1) + name_prefix = "gl_SecondaryColor"; + else + fprintf(stderr, "got illegal color semantic index %d\n", decl->Semantic.Index); + ctx->inputs[i].glsl_no_index = TRUE; + break; + } + /* fallthrough */ + case TGSI_SEMANTIC_POSITION: + if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT) { + name_prefix = "gl_FragCoord"; + ctx->inputs[i].glsl_predefined_no_emit = TRUE; + ctx->inputs[i].glsl_no_index = TRUE; + break; + } + /* fallthrough for vertex shader */ + case TGSI_SEMANTIC_FACE: + if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT) { + name_prefix = "gl_FrontFacing"; + ctx->inputs[i].glsl_predefined_no_emit = TRUE; + ctx->inputs[i].glsl_no_index = TRUE; + break; + } + case TGSI_SEMANTIC_GENERIC: + if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT) { + if (ctx->key->coord_replace & (1 << ctx->inputs[i].sid)) { + fprintf(stderr,"replacing generic %d with coord\n", ctx->inputs[i].sid); + name_prefix = "vec4(gl_PointCoord, 0.0, 1.0)"; + ctx->inputs[i].glsl_predefined_no_emit = TRUE; + ctx->inputs[i].glsl_no_index = TRUE; + break; + } + } + default: + if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT) + name_prefix = "ex"; + else + name_prefix = "in"; + break; + } + + if (ctx->inputs[i].glsl_no_index) + snprintf(ctx->inputs[i].glsl_name, 64, "%s", name_prefix); + else { + if (ctx->inputs[i].name == TGSI_SEMANTIC_FOG) + snprintf(ctx->inputs[i].glsl_name, 64, "%s_f%d", name_prefix, ctx->inputs[i].sid); + else if (ctx->inputs[i].name == TGSI_SEMANTIC_COLOR) + snprintf(ctx->inputs[i].glsl_name, 64, "%s_c%d", name_prefix, ctx->inputs[i].sid); + else if (ctx->inputs[i].name == TGSI_SEMANTIC_GENERIC) + snprintf(ctx->inputs[i].glsl_name, 64, "%s_g%d", name_prefix, ctx->inputs[i].sid); + else + snprintf(ctx->inputs[i].glsl_name, 64, "%s_%d", name_prefix, ctx->inputs[i].first); + } + break; + case TGSI_FILE_OUTPUT: + i = ctx->num_outputs++; + ctx->outputs[i].name = decl->Semantic.Name; + ctx->outputs[i].sid = decl->Semantic.Index; + ctx->outputs[i].interpolate = decl->Interp.Interpolate; + ctx->outputs[i].first = decl->Range.First; + ctx->outputs[i].glsl_predefined_no_emit = FALSE; + ctx->outputs[i].glsl_no_index = FALSE; + ctx->outputs[i].override_no_wm = FALSE; + switch (ctx->outputs[i].name) { + case TGSI_SEMANTIC_POSITION: + if (iter->processor.Processor == TGSI_PROCESSOR_VERTEX) { + if (ctx->outputs[i].first > 0) + fprintf(stderr,"Illegal position input\n"); + name_prefix = "gl_Position"; + ctx->outputs[i].glsl_predefined_no_emit = TRUE; + ctx->outputs[i].glsl_no_index = TRUE; + } else if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT) { + if (ctx->outputs[i].first > 0) + fprintf(stderr,"Illegal position input\n"); + name_prefix = "gl_FragDepth"; + ctx->outputs[i].glsl_predefined_no_emit = TRUE; + ctx->outputs[i].glsl_no_index = TRUE; + ctx->outputs[i].override_no_wm = TRUE; + } + break; + case TGSI_SEMANTIC_CLIPDIST: + name_prefix = "gl_ClipDistance"; + ctx->outputs[i].glsl_predefined_no_emit = TRUE; + ctx->outputs[i].glsl_no_index = TRUE; + ctx->num_clip_dist += 4; + break; + case TGSI_SEMANTIC_CLIPVERTEX: + name_prefix = "gl_ClipVertex"; + ctx->outputs[i].glsl_predefined_no_emit = TRUE; + ctx->outputs[i].glsl_no_index = TRUE; + ctx->outputs[i].override_no_wm = TRUE; + break; + + case TGSI_SEMANTIC_COLOR: + if (iter->processor.Processor == TGSI_PROCESSOR_VERTEX) { + ctx->outputs[i].glsl_no_index = TRUE; + if (ctx->outputs[i].sid == 0) + name_prefix = "gl_FrontColor"; + else if (ctx->outputs[i].sid == 1) + name_prefix = "gl_FrontSecondaryColor"; + break; + } + case TGSI_SEMANTIC_BCOLOR: + if (iter->processor.Processor == TGSI_PROCESSOR_VERTEX) { + ctx->outputs[i].glsl_no_index = TRUE; + if (ctx->outputs[i].sid == 0) + name_prefix = "gl_BackColor"; + else if (ctx->outputs[i].sid == 1) + name_prefix = "gl_BackSecondaryColor"; + break; + } + case TGSI_SEMANTIC_PSIZE: + if (iter->processor.Processor == TGSI_PROCESSOR_VERTEX) { + ctx->outputs[i].glsl_predefined_no_emit = TRUE; + ctx->outputs[i].glsl_no_index = TRUE; + ctx->outputs[i].override_no_wm = TRUE; + name_prefix = "gl_PointSize"; + break; + } + case TGSI_SEMANTIC_GENERIC: + if (iter->processor.Processor == TGSI_PROCESSOR_VERTEX) + if (ctx->outputs[i].name == TGSI_SEMANTIC_GENERIC) + color_offset = -1; + default: + if (iter->processor.Processor == TGSI_PROCESSOR_VERTEX) + name_prefix = "ex"; + else + name_prefix = "out"; + break; + } + + if (ctx->outputs[i].glsl_no_index) + snprintf(ctx->outputs[i].glsl_name, 64, "%s", name_prefix); + else { + if (ctx->outputs[i].name == TGSI_SEMANTIC_FOG) + snprintf(ctx->outputs[i].glsl_name, 64, "%s_f%d", name_prefix, ctx->outputs[i].sid); + else if (ctx->outputs[i].name == TGSI_SEMANTIC_COLOR) + snprintf(ctx->outputs[i].glsl_name, 64, "%s_c%d", name_prefix, ctx->outputs[i].sid); + else if (ctx->outputs[i].name == TGSI_SEMANTIC_GENERIC) + snprintf(ctx->outputs[i].glsl_name, 64, "%s_g%d", name_prefix, ctx->outputs[i].sid); + else + snprintf(ctx->outputs[i].glsl_name, 64, "%s_%d", name_prefix, ctx->outputs[i].first + color_offset); + + } + break; + case TGSI_FILE_TEMPORARY: + if (decl->Range.Last) { + if (decl->Range.Last + 1 > ctx->num_temps) + ctx->num_temps = decl->Range.Last + 1; + } else + ctx->num_temps++; + + break; + case TGSI_FILE_SAMPLER: + ctx->samplers_used |= (1 << decl->Range.Last); + break; + case TGSI_FILE_CONSTANT: + if (decl->Range.Last) { + if (decl->Range.Last + 1 > ctx->num_consts) + ctx->num_consts = decl->Range.Last + 1; + } else + ctx->num_consts++; + + break; + case TGSI_FILE_ADDRESS: + ctx->num_address = 1; + break; + case TGSI_FILE_SYSTEM_VALUE: + i = ctx->num_system_values++; + ctx->system_values[i].name = decl->Semantic.Name; + ctx->system_values[i].sid = decl->Semantic.Index; + ctx->system_values[i].glsl_predefined_no_emit = TRUE; + ctx->system_values[i].glsl_no_index = TRUE; + ctx->system_values[i].first = decl->Range.First; + if (decl->Semantic.Name == TGSI_SEMANTIC_INSTANCEID) { + name_prefix = "gl_InstanceID"; + ctx->has_instanceid = TRUE; + } else if (decl->Semantic.Name == TGSI_SEMANTIC_VERTEXID) { + name_prefix = "gl_VertexID"; + } else { + fprintf(stderr, "unsupported system value %d\n", decl->Semantic.Name); + name_prefix = "unknown"; + } + snprintf(ctx->system_values[i].glsl_name, 64, "%s", name_prefix); + break; + default: + fprintf(stderr,"unsupported file %d declaration\n", decl->Declaration.File); + break; + } + + + return TRUE; +} + +static boolean +iter_property(struct tgsi_iterate_context *iter, + struct tgsi_full_property *prop) +{ + struct dump_ctx *ctx = (struct dump_ctx *) iter; + + if (prop->Property.PropertyName == TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS) { + if (prop->u[0].Data == 1) + ctx->write_all_cbufs = TRUE; + } + + if (prop->Property.PropertyName == TGSI_PROPERTY_FS_COORD_ORIGIN) { + ctx->fs_coord_origin = prop->u[0].Data; + } + + if (prop->Property.PropertyName == TGSI_PROPERTY_FS_COORD_PIXEL_CENTER) { + ctx->fs_pixel_center = prop->u[0].Data; + } + + return TRUE; +} + +static boolean +iter_immediate( + struct tgsi_iterate_context *iter, + struct tgsi_full_immediate *imm ) +{ + struct dump_ctx *ctx = (struct dump_ctx *) iter; + int i; + int first = ctx->num_imm; + ctx->imm[first].type = imm->Immediate.DataType; + for (i = 0; i < 4; i++) { + if (imm->Immediate.DataType == TGSI_IMM_FLOAT32) { + ctx->imm[first].val[i].f = imm->u[i].Float; + } else if (imm->Immediate.DataType == TGSI_IMM_UINT32) { + ctx->has_ints = TRUE; + ctx->imm[first].val[i].ui = imm->u[i].Uint; + } else if (imm->Immediate.DataType == TGSI_IMM_INT32) { + ctx->has_ints = TRUE; + ctx->imm[first].val[i].i = imm->u[i].Int; + } + } + ctx->num_imm++; + return TRUE; +} + +static char get_swiz_char(int swiz) +{ + switch(swiz){ + case TGSI_SWIZZLE_X: return 'x'; + case TGSI_SWIZZLE_Y: return 'y'; + case TGSI_SWIZZLE_Z: return 'z'; + case TGSI_SWIZZLE_W: return 'w'; + } + return 0; +} + +static void emit_cbuf_writes(struct dump_ctx *ctx) +{ + char buf[255]; + int i; + + for (i = 1; i < 8; i++) { + snprintf(buf, 255, "out_c%d = out_c0;\n", i); + strcat(ctx->glsl_main, buf); + } +} + +static void emit_prescale(struct dump_ctx *ctx) +{ + char buf[255]; + + snprintf(buf, 255, "gl_Position.y = gl_Position.y * winsys_adjust.y;\n"); + strcat(ctx->glsl_main, buf); + snprintf(buf, 255, "gl_Position.z = dot(gl_Position, vec4(0.0, 0.0, winsys_adjust.zw));\n"); + strcat(ctx->glsl_main, buf); +} + +static void emit_so_movs(struct dump_ctx *ctx) +{ + char buf[255]; + int i, j; + char outtype[6] = {0}; + char writemask[6]; + for (i = 0; i < ctx->so->num_outputs; i++) { + if (ctx->so->output[i].start_component != 0) { + int wm_idx = 0; + writemask[wm_idx++] = '.'; + for (j = 0; j < ctx->so->output[i].num_components; j++) { + unsigned idx = ctx->so->output[i].start_component + j; + if (idx >= 4) + break; + if (idx <= 2) + writemask[wm_idx++] = 'x' + idx; + else + writemask[wm_idx++] = 'w'; + } + writemask[wm_idx] = '\0'; + } else + writemask[0] = 0; + + if (ctx->so->output[i].num_components == 1) + snprintf(outtype, 6, "float"); + else + snprintf(outtype, 6, "vec%d", ctx->so->output[i].num_components); + + if (ctx->outputs[ctx->so->output[i].register_index].name == TGSI_SEMANTIC_CLIPDIST) { + snprintf(buf, 255, "tfout%d = %s(clip_dist_temp[%d]%s);\n", i, outtype, ctx->outputs[ctx->so->output[i].register_index].sid, + writemask); + } else { + snprintf(buf, 255, "tfout%d = %s(%s%s);\n", i, outtype, ctx->outputs[ctx->so->output[i].register_index].glsl_name, writemask); + } + strcat(ctx->glsl_main, buf); + } + +} + +static void emit_clip_dist_movs(struct dump_ctx *ctx) +{ + char buf[255]; + int i; + for (i = 0; i < ctx->num_clip_dist; i++) { + int clipidx = i < 4 ? 0 : 1; + char swiz = i & 3; + char wm = 0; + switch (swiz) { + case 0: wm = 'x'; break; + case 1: wm = 'y'; break; + case 2: wm = 'z'; break; + case 3: wm = 'w'; break; + } + snprintf(buf, 255, "gl_ClipDistance[%d] = clip_dist_temp[%d].%c;\n", + i, clipidx, wm); + strcat(ctx->glsl_main, buf); + } +} + + + +#define emit_arit_op2(op) snprintf(buf, 255, "%s = %s(%s((%s %s %s))%s);\n", dsts[0], dstconv, dtypeprefix, srcs[0], op, srcs[1], writemask) +#define emit_op1(op) snprintf(buf, 255, "%s = %s(%s(%s(%s)));\n", dsts[0], dstconv, dtypeprefix, op, srcs[0]) +#define emit_compare(op) snprintf(buf, 255, "%s = %s(%s((%s(%s, %s)))%s);\n", dsts[0], dstconv, dtypeprefix, op, srcs[0], srcs[1], writemask) + +#define emit_ucompare(op) snprintf(buf, 255, "%s = %s(uintBitsToFloat(%s(%s(%s, %s)%s) * %s(0xffffffff)));\n", dsts[0], dstconv, udstconv, op, srcs[0], srcs[1], writemask, udstconv) + +static void emit_buf(struct dump_ctx *ctx, char *buf) +{ + int i; + for (i = 0; i < ctx->indent_level; i++) + strcat(ctx->glsl_main, "\t"); + + strcat(ctx->glsl_main, buf); +} + +static boolean +iter_instruction(struct tgsi_iterate_context *iter, + struct tgsi_full_instruction *inst) +{ + struct dump_ctx *ctx = (struct dump_ctx *)iter; + char srcs[4][255], dsts[3][255], buf[512]; + uint instno = ctx->instno++; + int i; + int j; + int sreg_index = 0; + char dstconv[32] = {0}; + char udstconv[32] = {0}; + char writemask[6] = {0}; + char offbuf[64] = {0}; + char *twm, *gwm, *txfi; + char bias[64] = {0}; + char *tex_ext; + boolean is_shad = FALSE; + int sampler_index; + enum tgsi_opcode_type dtype = tgsi_opcode_infer_dst_type(inst->Instruction.Opcode); + enum tgsi_opcode_type stype = tgsi_opcode_infer_src_type(inst->Instruction.Opcode); + char *dtypeprefix="", *stypeprefix = ""; + bool stprefix = false; + + if (dtype == TGSI_TYPE_SIGNED || dtype == TGSI_TYPE_UNSIGNED || + stype == TGSI_TYPE_SIGNED || stype == TGSI_TYPE_UNSIGNED) + ctx->has_ints = TRUE; + + if (inst->Instruction.Opcode == TGSI_OPCODE_TXQ) { + dtypeprefix = "intBitsToFloat"; + } else { + switch (dtype) { + case TGSI_TYPE_UNSIGNED: + dtypeprefix = "uintBitsToFloat"; + break; + case TGSI_TYPE_SIGNED: + dtypeprefix = "intBitsToFloat"; + break; + default: + break; + } + } + + switch (stype) { + case TGSI_TYPE_UNSIGNED: + stypeprefix = "floatBitsToUint"; + stprefix = true; + break; + case TGSI_TYPE_SIGNED: + stypeprefix = "floatBitsToInt"; + stprefix = true; + break; + default: + break; + } + + if (instno == 0) + strcat(ctx->glsl_main, "void main(void)\n{\n"); + for (i = 0; i < inst->Instruction.NumDstRegs; i++) { + const struct tgsi_full_dst_register *dst = &inst->Dst[i]; + if (dst->Register.WriteMask != TGSI_WRITEMASK_XYZW) { + int wm_idx = 0; + writemask[wm_idx++] = '.'; + if (dst->Register.WriteMask & 0x1) + writemask[wm_idx++] = 'x'; + if (dst->Register.WriteMask & 0x2) + writemask[wm_idx++] = 'y'; + if (dst->Register.WriteMask & 0x4) + writemask[wm_idx++] = 'z'; + if (dst->Register.WriteMask & 0x8) + writemask[wm_idx++] = 'w'; + if (wm_idx == 2) { + snprintf(dstconv, 6, "float"); + snprintf(udstconv, 6, "uint"); + } else { + snprintf(dstconv, 6, "vec%d", wm_idx-1); + snprintf(udstconv, 6, "uvec%d", wm_idx-1); + } + } else { + snprintf(dstconv, 6, "vec4"); + snprintf(udstconv, 6, "uvec4"); + } + if (dst->Register.File == TGSI_FILE_OUTPUT) { + for (j = 0; j < ctx->num_outputs; j++) { + if (ctx->outputs[j].first == dst->Register.Index) { + if (ctx->outputs[j].name == TGSI_SEMANTIC_CLIPDIST) { + snprintf(dsts[i], 255, "clip_dist_temp[%d]", ctx->outputs[j].sid); + } else { + snprintf(dsts[i], 255, "%s%s", ctx->outputs[j].glsl_name, ctx->outputs[j].override_no_wm ? "" : writemask); + if (ctx->outputs[j].name == TGSI_SEMANTIC_PSIZE) { + snprintf(dstconv, 6, "float"); + break; + } + } + } + } + } + else if (dst->Register.File == TGSI_FILE_TEMPORARY) { + if (dst->Register.Indirect) { + snprintf(dsts[i], 255, "temps[addr0 + %d]%s", dst->Register.Index, writemask); + } else + snprintf(dsts[i], 255, "temps[%d]%s", dst->Register.Index, writemask); + } + } + + for (i = 0; i < inst->Instruction.NumSrcRegs; i++) { + const struct tgsi_full_src_register *src = &inst->Src[i]; + char swizzle[8] = {0}; + char prefix[6] = {0}; + int swz_idx = 0, pre_idx = 0; + boolean isabsolute = src->Register.Absolute; + + if (isabsolute) + swizzle[swz_idx++] = ')'; + + if (src->Register.Negate) + prefix[pre_idx++] = '-'; + if (isabsolute) + strcpy(&prefix[pre_idx++], "abs("); + + 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) { + swizzle[swz_idx++] = '.'; + swizzle[swz_idx++] = get_swiz_char(src->Register.SwizzleX); + swizzle[swz_idx++] = get_swiz_char(src->Register.SwizzleY); + swizzle[swz_idx++] = get_swiz_char(src->Register.SwizzleZ); + swizzle[swz_idx++] = get_swiz_char(src->Register.SwizzleW); + } + if (src->Register.File == TGSI_FILE_INPUT) { + for (j = 0; j < ctx->num_inputs; j++) + if (ctx->inputs[j].first == src->Register.Index) { + snprintf(srcs[i], 255, "%s(%s%s%s)", stypeprefix, prefix, ctx->inputs[j].glsl_name, swizzle); + break; + } + } + else if (src->Register.File == TGSI_FILE_TEMPORARY) { + if (src->Register.Indirect) { + snprintf(srcs[i], 255, "%s%c%stemps[addr0 + %d]%s%c", stypeprefix, stprefix ? '(' : ' ', prefix, src->Register.Index, swizzle, stprefix ? ')' : ' '); + } else + snprintf(srcs[i], 255, "%s%c%stemps[%d]%s%c", stypeprefix, stprefix ? '(' : ' ', prefix, src->Register.Index, swizzle, stprefix ? ')' : ' '); + } else if (src->Register.File == TGSI_FILE_CONSTANT) { + const char *cname = ctx->prog_type == TGSI_PROCESSOR_VERTEX ? "vsconst" : "fsconst"; + if (src->Register.Indirect) { + snprintf(srcs[i], 255, "%s(%s%s[addr0 + %d]%s)", stypeprefix, prefix, cname, src->Register.Index, swizzle); + } else + snprintf(srcs[i], 255, "%s(%s%s[%d]%s)", stypeprefix, prefix, cname, src->Register.Index, swizzle); + } else if (src->Register.File == TGSI_FILE_SAMPLER) { + const char *cname = ctx->prog_type == TGSI_PROCESSOR_VERTEX ? "vssamp" : "fssamp"; + snprintf(srcs[i], 255, "%s%d%s", cname, src->Register.Index, swizzle); + sreg_index = src->Register.Index; + } else if (src->Register.File == TGSI_FILE_IMMEDIATE) { + struct immed *imd = &ctx->imm[(src->Register.Index)]; + int idx = src->Register.SwizzleX; + char temp[48]; + const char *vtype = "vec4"; + const char *imm_stypeprefix = stypeprefix; + + if (imd->type == TGSI_IMM_UINT32 || imd->type == TGSI_IMM_INT32) { + if (imd->type == TGSI_IMM_UINT32) + vtype = "uvec4"; + else + vtype = "ivec4"; + + if (stype == TGSI_TYPE_UNSIGNED && imd->type == TGSI_IMM_INT32) + imm_stypeprefix = "uvec4"; + else if (stype == TGSI_TYPE_SIGNED && imd->type == TGSI_IMM_UINT32) + imm_stypeprefix = "ivec4"; + else if (stype == TGSI_TYPE_FLOAT || stype == TGSI_TYPE_UNTYPED) { + if (imd->type == TGSI_IMM_INT32) + imm_stypeprefix = "intBitsToFloat"; + else + imm_stypeprefix = "uintBitsToFloat"; + } else if (stype == TGSI_TYPE_UNSIGNED || stype == TGSI_TYPE_SIGNED) + imm_stypeprefix = ""; + + } + + /* build up a vec4 of immediates */ + snprintf(srcs[i], 255, "%s(%s%s(", imm_stypeprefix, prefix, vtype); + for (j = 0; j < 4; j++) { + if (j == 0) + idx = src->Register.SwizzleX; + else if (j == 1) + idx = src->Register.SwizzleY; + else if (j == 2) + idx = src->Register.SwizzleZ; + else if (j == 3) + idx = src->Register.SwizzleW; + switch (imd->type) { + case TGSI_IMM_FLOAT32: + if (isinf(imd->val[idx].f) || isnan(imd->val[idx].f)) { + ctx->has_ints = TRUE; + snprintf(temp, 48, "uintBitsToFloat(%uU)", imd->val[idx].ui); + } else + snprintf(temp, 25, "%.8g", imd->val[idx].f); + break; + case TGSI_IMM_UINT32: + snprintf(temp, 25, "%uU", imd->val[idx].ui); + break; + case TGSI_IMM_INT32: + snprintf(temp, 25, "%d", imd->val[idx].i); + break; + } + strncat(srcs[i], temp, 255); + if (j < 3) + strcat(srcs[i], ","); + else { + snprintf(temp, 4, "))%c", isabsolute ? ')' : 0); + strncat(srcs[i], temp, 255); + } + } + } else if (src->Register.File == TGSI_FILE_SYSTEM_VALUE) { + for (j = 0; j < ctx->num_system_values; j++) + if (ctx->system_values[j].first == src->Register.Index) { + snprintf(srcs[i], 255, "%s%s", prefix, ctx->system_values[j].glsl_name); + } + } + } + switch (inst->Instruction.Opcode) { + case TGSI_OPCODE_SQRT: + snprintf(buf, 255, "%s = sqrt(vec4(%s))%s;\n", dsts[0], srcs[0], writemask); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_LRP: + snprintf(buf, 255, "%s = mix(vec4(%s), vec4(%s), vec4(%s))%s;\n", dsts[0], srcs[2], srcs[1], srcs[0], writemask); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_DP2: + snprintf(buf, 255, "%s = %s(dot(vec2(%s), vec2(%s)));\n", dsts[0], dstconv, srcs[0], srcs[1]); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_DP3: + snprintf(buf, 255, "%s = %s(dot(vec3(%s), vec3(%s)));\n", dsts[0], dstconv, srcs[0], srcs[1]); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_DP4: + snprintf(buf, 255, "%s = %s(dot(vec4(%s), vec4(%s)));\n", dsts[0], dstconv, srcs[0], srcs[1]); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_DPH: + snprintf(buf, 255, "%s = %s(dot(vec4(vec3(%s), 1.0), vec4(%s)));\n", dsts[0], dstconv, srcs[0], srcs[1]); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_MAX: + case TGSI_OPCODE_IMAX: + case TGSI_OPCODE_UMAX: + snprintf(buf, 255, "%s = %s(%s(max(%s, %s)));\n", dsts[0], dstconv, dtypeprefix, srcs[0], srcs[1]); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_MIN: + case TGSI_OPCODE_IMIN: + case TGSI_OPCODE_UMIN: + snprintf(buf, 255, "%s = %s(%s(min(%s, %s)));\n", dsts[0], dstconv, dtypeprefix, srcs[0], srcs[1]); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_ABS: + case TGSI_OPCODE_IABS: + emit_op1("abs"); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_KILL_IF: + snprintf(buf, 255, "if (any(lessThan(%s, vec4(0.0))))\ndiscard;\n", srcs[0]); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_IF: + case TGSI_OPCODE_UIF: + snprintf(buf, 255, "if (any(bvec4(%s))) {\n", srcs[0]); + emit_buf(ctx, buf); + ctx->indent_level++; + break; + case TGSI_OPCODE_ELSE: + snprintf(buf, 255, "} else {\n"); + ctx->indent_level--; + emit_buf(ctx, buf); + ctx->indent_level++; + break; + case TGSI_OPCODE_ENDIF: + snprintf(buf, 255, "}\n"); + ctx->indent_level--; + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_KILL: + snprintf(buf, 255, "discard;\n"); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_DST: + snprintf(buf, 512, "%s = vec4(1.0, %s.y * %s.y, %s.z, %s.w);\n", dsts[0], + srcs[0], srcs[1], srcs[0], srcs[1]); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_LIT: + snprintf(buf, 512, "%s = %s(vec4(1.0, max(%s.x, 0.0), step(0.0, %s.x) * pow(max(0.0, %s.y), clamp(%s.w, -128.0, 128.0)), 1.0)%s);\n", dsts[0], dstconv, srcs[0], srcs[0], srcs[0], srcs[0], writemask); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_EX2: + emit_op1("exp2"); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_LG2: + emit_op1("log2"); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_EXP: + snprintf(buf, 512, "%s = %s(vec4(pow(2.0, floor(%s.x)), %s.x - floor(%s.x), exp2(%s.x), 1.0)%s);\n", dsts[0], dstconv, srcs[0], srcs[0], srcs[0], srcs[0], writemask); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_LOG: + snprintf(buf, 512, "%s = %s(vec4(floor(log2(%s.x)), %s.x / pow(2.0, floor(log2(%s.x))), log2(%s.x), 1.0)%s);\n", dsts[0], dstconv, srcs[0], srcs[0], srcs[0], srcs[0], writemask); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_COS: + emit_op1("cos"); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_SIN: + emit_op1("sin"); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_SCS: + snprintf(buf, 255, "%s = %s(vec4(cos(%s.x), sin(%s.x), 0, 1)%s);\n", dsts[0], dstconv, + srcs[0], srcs[0], writemask); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_DDX: + emit_op1("dFdx"); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_DDY: + emit_op1("dFdy"); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_RCP: + snprintf(buf, 255, "%s = %s(1.0/(%s));\n", dsts[0], dstconv, srcs[0]); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_FLR: + emit_op1("floor"); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_ROUND: + emit_op1("round"); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_ISSG: + emit_op1("sign"); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_CEIL: + emit_op1("ceil"); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_FRC: + emit_op1("fract"); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_TRUNC: + emit_op1("trunc"); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_SSG: + emit_op1("sign"); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_RSQ: + snprintf(buf, 255, "%s = %s(inversesqrt(%s.x));\n", dsts[0], dstconv, srcs[0]); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_MOV: + snprintf(buf, 255, "%s = %s(%s(%s%s));\n", dsts[0], dstconv, dtypeprefix, srcs[0], writemask); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_ADD: + emit_arit_op2("+"); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_UADD: + snprintf(buf, 255, "%s = %s(%s(ivec4((uvec4(%s) + uvec4(%s))))%s);\n", dsts[0], dstconv, dtypeprefix, srcs[0], srcs[1], writemask); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_SUB: + emit_arit_op2("-"); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_MUL: + emit_arit_op2("*"); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_DIV: + emit_arit_op2("/"); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_UMUL: + snprintf(buf, 255, "%s = %s(%s((uvec4(%s) * uvec4(%s)))%s);\n", dsts[0], dstconv, dtypeprefix, srcs[0], srcs[1], writemask); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_UMOD: + snprintf(buf, 255, "%s = %s(%s((uvec4(%s) %% uvec4(%s)))%s);\n", dsts[0], dstconv, dtypeprefix, srcs[0], srcs[1], writemask); + strcat(ctx->glsl_main, buf); + break; + case TGSI_OPCODE_IDIV: + snprintf(buf, 255, "%s = %s(%s((ivec4(%s) / ivec4(%s)))%s);\n", dsts[0], dstconv, dtypeprefix, srcs[0], srcs[1], writemask); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_UDIV: + snprintf(buf, 255, "%s = %s(%s((uvec4(%s) / uvec4(%s)))%s);\n", dsts[0], dstconv, dtypeprefix, srcs[0], srcs[1], writemask); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_ISHR: + case TGSI_OPCODE_USHR: + emit_arit_op2(">>"); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_SHL: + emit_arit_op2("<<"); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_MAD: + snprintf(buf, 255, "%s = %s((%s * %s + %s)%s);\n", dsts[0], dstconv, srcs[0], srcs[1], srcs[2], writemask); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_UMAD: + snprintf(buf, 255, "%s = %s(%s((%s * %s + %s)%s));\n", dsts[0], dstconv, dtypeprefix, srcs[0], srcs[1], srcs[2], writemask); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_OR: + emit_arit_op2("|"); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_AND: + emit_arit_op2("&"); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_XOR: + emit_arit_op2("^"); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_MOD: + emit_arit_op2("%"); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_TEX: + case TGSI_OPCODE_TEX2: + case TGSI_OPCODE_TXB: + case TGSI_OPCODE_TXL: + case TGSI_OPCODE_TXB2: + case TGSI_OPCODE_TXL2: + case TGSI_OPCODE_TXD: + case TGSI_OPCODE_TXF: + ctx->samplers[sreg_index].tgsi_sampler_type = inst->Texture.Texture; + + if (inst->Texture.Texture == TGSI_TEXTURE_CUBE_ARRAY || inst->Texture.Texture == TGSI_TEXTURE_SHADOWCUBE_ARRAY) + ctx->uses_cube_array = TRUE; + if (inst->Texture.Texture == TGSI_TEXTURE_2D_MSAA || inst->Texture.Texture == TGSI_TEXTURE_2D_ARRAY_MSAA) + ctx->uses_sampler_ms = TRUE; + + switch (inst->Texture.Texture) { + case TGSI_TEXTURE_1D: + twm = ".x"; + txfi = "int"; + break; + case TGSI_TEXTURE_2D: + case TGSI_TEXTURE_1D_ARRAY: + twm = ".xy"; + txfi = "ivec2"; + break; + case TGSI_TEXTURE_SHADOW1D: + case TGSI_TEXTURE_SHADOW2D: + case TGSI_TEXTURE_SHADOW1D_ARRAY: + is_shad = TRUE; + case TGSI_TEXTURE_3D: + case TGSI_TEXTURE_CUBE: + case TGSI_TEXTURE_2D_ARRAY: + twm = ".xyz"; + txfi = "ivec3"; + break; + case TGSI_TEXTURE_2D_MSAA: + twm = ".xy"; + txfi = "ivec2"; + break; + case TGSI_TEXTURE_2D_ARRAY_MSAA: + twm = ".xyz"; + txfi = "ivec3"; + break; + + case TGSI_TEXTURE_SHADOWCUBE: + case TGSI_TEXTURE_SHADOW2D_ARRAY: + is_shad = TRUE; + case TGSI_TEXTURE_CUBE_ARRAY: + case TGSI_TEXTURE_SHADOWCUBE_ARRAY: + default: + twm = ""; + txfi = ""; + break; + } + + if (inst->Instruction.Opcode == TGSI_OPCODE_TXD) { + switch (inst->Texture.Texture) { + case TGSI_TEXTURE_1D: + case TGSI_TEXTURE_SHADOW1D: + case TGSI_TEXTURE_1D_ARRAY: + case TGSI_TEXTURE_SHADOW1D_ARRAY: + gwm = ".x"; + break; + case TGSI_TEXTURE_2D: + case TGSI_TEXTURE_SHADOW2D: + case TGSI_TEXTURE_2D_ARRAY: + case TGSI_TEXTURE_SHADOW2D_ARRAY: + gwm = ".xy"; + break; + case TGSI_TEXTURE_3D: + case TGSI_TEXTURE_CUBE: + case TGSI_TEXTURE_SHADOWCUBE: + gwm = ".xyz"; + break; + default: + gwm = ""; + break; + } + } + + + sampler_index = 1; + + if (inst->Instruction.Opcode == TGSI_OPCODE_TXB2 || inst->Instruction.Opcode == TGSI_OPCODE_TXL2 || inst->Instruction.Opcode == TGSI_OPCODE_TEX2) { + sampler_index = 2; + if (inst->Instruction.Opcode != TGSI_OPCODE_TEX2) + snprintf(bias, 64, ", %s.x", srcs[1]); + } else if (inst->Instruction.Opcode == TGSI_OPCODE_TXB || inst->Instruction.Opcode == TGSI_OPCODE_TXL) + snprintf(bias, 64, ", %s.w", srcs[0]); + else if (inst->Instruction.Opcode == TGSI_OPCODE_TXF) { + snprintf(bias, 64, ", int(%s.w)", srcs[0]); + } else if (inst->Instruction.Opcode == TGSI_OPCODE_TXD) { + snprintf(bias, 64, ", %s%s, %s%s", srcs[1], gwm, srcs[2], gwm); + sampler_index = 3; + } + else + bias[0] = 0; + + if (inst->Instruction.Opcode == TGSI_OPCODE_TXL || inst->Instruction.Opcode == TGSI_OPCODE_TXL2) { + if (inst->Texture.NumOffsets == 1) + tex_ext = "LodOffset"; + else + tex_ext = "Lod"; + } else if (inst->Instruction.Opcode == TGSI_OPCODE_TXD) { + if (inst->Texture.NumOffsets == 1) + tex_ext = "GradOffset"; + else + tex_ext = "Grad"; + } else { + if (inst->Texture.NumOffsets == 1) + tex_ext = "Offset"; + else + tex_ext = ""; + } + + if (inst->Texture.NumOffsets == 1) { + struct immed *imd = &ctx->imm[(inst->TexOffsets[0].Index)]; + switch (inst->Texture.Texture) { + case TGSI_TEXTURE_1D: + case TGSI_TEXTURE_1D_ARRAY: + case TGSI_TEXTURE_SHADOW1D: + case TGSI_TEXTURE_SHADOW1D_ARRAY: + snprintf(offbuf, 25, ", int(%d)", imd->val[inst->TexOffsets[0].SwizzleX].i); + break; + case TGSI_TEXTURE_2D: + case TGSI_TEXTURE_2D_ARRAY: + case TGSI_TEXTURE_SHADOW2D: + case TGSI_TEXTURE_SHADOW2D_ARRAY: + snprintf(offbuf, 25, ", ivec2(%d, %d)", imd->val[inst->TexOffsets[0].SwizzleX].i, imd->val[inst->TexOffsets[0].SwizzleY].i); + break; + case TGSI_TEXTURE_3D: + snprintf(offbuf, 25, ", ivec3(%d, %d, %d)", imd->val[inst->TexOffsets[0].SwizzleX].i, imd->val[inst->TexOffsets[0].SwizzleY].i, + imd->val[inst->TexOffsets[0].SwizzleZ].i); + break; + } + + if (inst->Instruction.Opcode == TGSI_OPCODE_TXL || inst->Instruction.Opcode == TGSI_OPCODE_TXL2 || inst->Instruction.Opcode == TGSI_OPCODE_TXD) { + char tmp[64]; + strcpy(tmp, offbuf); + strcpy(offbuf, bias); + strcpy(bias, tmp); + + } + } + if (inst->Instruction.Opcode == TGSI_OPCODE_TXF) { + snprintf(buf, 255, "%s = %s(texelFetch%s(%s, %s(%s%s)%s%s)%s);\n", dsts[0], dstconv, tex_ext, srcs[sampler_index], txfi, srcs[0], twm, bias, offbuf, ctx->outputs[0].override_no_wm ? "" : writemask); + } + /* rect is special in GLSL 1.30 */ + else if (inst->Texture.Texture == TGSI_TEXTURE_RECT) + snprintf(buf, 255, "%s = texture2DRect(%s, %s.xy)%s;\n", dsts[0], srcs[sampler_index], srcs[0], writemask); + else if (inst->Texture.Texture == TGSI_TEXTURE_SHADOWRECT) + snprintf(buf, 255, "%s = shadow2DRect(%s, %s.xyz)%s;\n", dsts[0], srcs[sampler_index], srcs[0], writemask); + else if (is_shad) { /* TGSI returns 1.0 in alpha */ + const char *mname = ctx->prog_type == TGSI_PROCESSOR_VERTEX ? "vsshadmask" : "fsshadmask"; + const char *cname = ctx->prog_type == TGSI_PROCESSOR_VERTEX ? "vsshadadd" : "fsshadadd"; + const struct tgsi_full_src_register *src = &inst->Src[sampler_index]; + snprintf(buf, 255, "%s = %s(vec4(vec4(texture%s(%s, %s%s%s)) * %s%d + %s%d)%s);\n", dsts[0], dstconv, tex_ext, srcs[sampler_index], srcs[0], twm, bias, mname, src->Register.Index, cname, src->Register.Index, writemask); + } else + snprintf(buf, 255, "%s = %s(texture%s(%s, %s%s%s%s)%s);\n", dsts[0], dstconv, tex_ext, srcs[sampler_index], srcs[0], twm, offbuf, bias, ctx->outputs[0].override_no_wm ? "" : writemask); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_TXP: + + sampler_index = 1; + ctx->samplers[sreg_index].tgsi_sampler_type = inst->Texture.Texture; + + switch (inst->Texture.Texture) { + case TGSI_TEXTURE_1D: + twm = ".xy"; + break; + case TGSI_TEXTURE_RECT: + case TGSI_TEXTURE_CUBE: + case TGSI_TEXTURE_2D: + case TGSI_TEXTURE_SHADOWRECT: + case TGSI_TEXTURE_1D_ARRAY: + case TGSI_TEXTURE_2D_ARRAY: + twm = ".xyz"; + break; + case TGSI_TEXTURE_SHADOW1D: + case TGSI_TEXTURE_SHADOW2D: + is_shad = TRUE; + case TGSI_TEXTURE_3D: + twm = ""; + break; + + case TGSI_TEXTURE_SHADOW1D_ARRAY: + case TGSI_TEXTURE_SHADOWCUBE: + case TGSI_TEXTURE_SHADOW2D_ARRAY: + case TGSI_TEXTURE_CUBE_ARRAY: + case TGSI_TEXTURE_SHADOWCUBE_ARRAY: + + default: + fprintf(stderr,"failed to convert TXP opcode %d, invalid texture %d\n", inst->Instruction.Opcode, inst->Texture.Texture); + return FALSE; + break; + } + tex_ext = ""; + + if (inst->Texture.Texture == TGSI_TEXTURE_RECT) + snprintf(buf, 255, "%s = texture2DRectProj(%s, %s)%s;\n", dsts[0], srcs[1], srcs[0], writemask); + else if (inst->Texture.Texture == TGSI_TEXTURE_SHADOWRECT) + snprintf(buf, 255, "%s = shadow2DRectProj(%s, %s)%s;\n", dsts[0], srcs[1], srcs[0], writemask); + else if (inst->Texture.Texture == TGSI_TEXTURE_CUBE || inst->Texture.Texture == TGSI_TEXTURE_2D_ARRAY) + snprintf(buf, 255, "%s = texture(%s, %s.xyz)%s;\n", dsts[0], srcs[1], srcs[0], writemask); + else if (inst->Texture.Texture == TGSI_TEXTURE_1D_ARRAY) + snprintf(buf, 255, "%s = texture(%s, %s.xy)%s;\n", dsts[0], srcs[1], srcs[0], writemask); + else if (is_shad) { /* TGSI returns 1.0 in alpha */ + const char *mname = ctx->prog_type == TGSI_PROCESSOR_VERTEX ? "vsshadmask" : "fsshadmask"; + const char *cname = ctx->prog_type == TGSI_PROCESSOR_VERTEX ? "vsshadadd" : "fsshadadd"; + const struct tgsi_full_src_register *src = &inst->Src[sampler_index]; + snprintf(buf, 255, "%s = %s(vec4(vec4(textureProj%s(%s, %s%s%s)) * %s%d + %s%d)%s);\n", dsts[0], dstconv, tex_ext, srcs[sampler_index], srcs[0], twm, bias, mname, src->Register.Index, cname, src->Register.Index, writemask); + } else + snprintf(buf, 255, "%s = %s(textureProj(%s, %s)%s);\n", dsts[0], dstconv, srcs[1], srcs[0], writemask); + + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_TXQ: { + ctx->samplers[sreg_index].tgsi_sampler_type = inst->Texture.Texture; + if (inst->Texture.Texture == TGSI_TEXTURE_CUBE_ARRAY || inst->Texture.Texture == TGSI_TEXTURE_SHADOWCUBE_ARRAY) + ctx->uses_cube_array = TRUE; + if (inst->Texture.Texture == TGSI_TEXTURE_2D_MSAA || inst->Texture.Texture == TGSI_TEXTURE_2D_ARRAY_MSAA) { + ctx->uses_sampler_ms = TRUE; + } else + snprintf(bias, 64, ", int(%s.w)", srcs[0]); + sampler_index = 1; + snprintf(buf, 255, "%s = %s(%s(textureSize(%s%s)));\n", dsts[0], dstconv, dtypeprefix, srcs[sampler_index], bias); + emit_buf(ctx, buf); + break; + } + case TGSI_OPCODE_I2F: + snprintf(buf, 255, "%s = %s(ivec4(%s));\n", dsts[0], dstconv, srcs[0]); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_U2F: + snprintf(buf, 255, "%s = %s(uvec4(%s));\n", dsts[0], dstconv, srcs[0]); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_F2I: + snprintf(buf, 255, "%s = %s(%s(ivec4(%s)));\n", dsts[0], dstconv, dtypeprefix, srcs[0]); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_F2U: + snprintf(buf, 255, "%s = %s(%s(uvec4(%s)));\n", dsts[0], dstconv, dtypeprefix, srcs[0]); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_NOT: + snprintf(buf, 255, "%s = %s(uintBitsToFloat(~(uvec4(%s))));\n", dsts[0], dstconv, srcs[0]); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_INEG: + snprintf(buf, 255, "%s = %s(intBitsToFloat(-(ivec4(%s))));\n", dsts[0], dstconv, srcs[0]); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_SEQ: + emit_compare("equal"); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_USEQ: + case TGSI_OPCODE_FSEQ: + emit_ucompare("equal"); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_SLT: + emit_compare("lessThan"); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_ISLT: + case TGSI_OPCODE_USLT: + case TGSI_OPCODE_FSLT: + emit_ucompare("lessThan"); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_SNE: + emit_compare("notEqual"); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_USNE: + case TGSI_OPCODE_FSNE: + emit_ucompare("notEqual"); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_SGE: + emit_compare("greaterThanEqual"); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_ISGE: + case TGSI_OPCODE_USGE: + case TGSI_OPCODE_FSGE: + emit_ucompare("greaterThanEqual"); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_POW: + snprintf(buf, 255, "%s = %s(pow(%s, %s));\n", dsts[0], dstconv, srcs[0], srcs[1]); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_CMP: + snprintf(buf, 255, "%s = mix(%s, %s, greaterThanEqual(%s, vec4(0.0)))%s;\n", dsts[0], srcs[1], srcs[2], srcs[0], writemask); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_END: + if (iter->processor.Processor == TGSI_PROCESSOR_VERTEX) { + emit_prescale(ctx); + if (ctx->so) + emit_so_movs(ctx); + if (ctx->num_clip_dist) + emit_clip_dist_movs(ctx); + } else if (ctx->write_all_cbufs) + emit_cbuf_writes(ctx); + strcat(ctx->glsl_main, "}\n"); + break; + case TGSI_OPCODE_RET: + strcat(ctx->glsl_main, "return;\n"); + break; + case TGSI_OPCODE_ARL: + snprintf(buf, 255, "addr0 = int(floor(%s)%s);\n", srcs[0], writemask); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_UARL: + snprintf(buf, 255, "addr0 = int(%s);\n", srcs[0]); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_XPD: + snprintf(buf, 255, "%s = %s(cross(vec3(%s), vec3(%s)));\n", dsts[0], dstconv, srcs[0], srcs[1]); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_BGNLOOP: + snprintf(buf, 255, "do {\n"); + emit_buf(ctx, buf); + ctx->indent_level++; + break; + case TGSI_OPCODE_ENDLOOP: + ctx->indent_level--; + snprintf(buf, 255, "} while(true);\n"); + emit_buf(ctx, buf); + break; + case TGSI_OPCODE_BRK: + snprintf(buf, 255, "break;\n"); + emit_buf(ctx, buf); + break; + default: + fprintf(stderr,"failed to convert opcode %d\n", inst->Instruction.Opcode); + break; + } + + if (inst->Instruction.Saturate == TGSI_SAT_ZERO_ONE) { + snprintf(buf, 255, "%s = clamp(%s, 0.0, 1.0);\n", dsts[0], dsts[0]); + emit_buf(ctx, buf); + } + + return TRUE; +} + +static boolean +prolog(struct tgsi_iterate_context *iter) +{ + return TRUE; +} + +static void emit_header(struct dump_ctx *ctx, char *glsl_final) +{ + strcat(glsl_final, "#version 130\n"); + if (ctx->prog_type == TGSI_PROCESSOR_VERTEX && graw_shader_use_explicit) + strcat(glsl_final, "#extension GL_ARB_explicit_attrib_location : enable\n"); + if (ctx->prog_type == TGSI_PROCESSOR_FRAGMENT && fs_emit_layout(ctx)) + strcat(glsl_final, "#extension GL_ARB_fragment_coord_conventions : enable\n"); + strcat(glsl_final, "#extension GL_ARB_texture_rectangle : require\n"); + if (ctx->uses_cube_array) + strcat(glsl_final, "#extension GL_ARB_texture_cube_map_array : require\n"); + if (ctx->has_ints) + strcat(glsl_final, "#extension GL_ARB_shader_bit_encoding : require\n"); + if (ctx->uses_sampler_ms) + strcat(glsl_final, "#extension GL_ARB_texture_multisample : require\n"); + if (ctx->has_instanceid) + strcat(glsl_final, "#extension GL_ARB_draw_instanced : require\n"); +} + +static const char *samplertypeconv(int sampler_type, int *is_shad) +{ + switch (sampler_type) { + case TGSI_TEXTURE_1D: return "1D"; + case TGSI_TEXTURE_2D: return "2D"; + case TGSI_TEXTURE_3D: return "3D"; + case TGSI_TEXTURE_CUBE: return "Cube"; + case TGSI_TEXTURE_RECT: return "2DRect"; + case TGSI_TEXTURE_SHADOW1D: *is_shad = 1; return "1DShadow"; + case TGSI_TEXTURE_SHADOW2D: *is_shad = 1; return "2DShadow"; + case TGSI_TEXTURE_SHADOWRECT: *is_shad = 1; return "2DRectShadow"; + case TGSI_TEXTURE_1D_ARRAY: return "1DArray"; + case TGSI_TEXTURE_2D_ARRAY: return "2DArray"; + case TGSI_TEXTURE_SHADOW1D_ARRAY: *is_shad = 1; return "1DArrayShadow"; + case TGSI_TEXTURE_SHADOW2D_ARRAY: *is_shad = 1; return "2DArrayShadow"; + case TGSI_TEXTURE_SHADOWCUBE: *is_shad = 1; return "CubeShadow"; + case TGSI_TEXTURE_CUBE_ARRAY: return "CubeArray"; + case TGSI_TEXTURE_SHADOWCUBE_ARRAY: *is_shad = 1; return "CubeArrayShadow"; + case TGSI_TEXTURE_2D_MSAA: return "2DMS"; + case TGSI_TEXTURE_2D_ARRAY_MSAA: return "2DMSArray"; + default: return NULL; + } +} + +static const char *get_interp_string(int interpolate) +{ + switch (interpolate) { + case TGSI_INTERPOLATE_LINEAR: + return "noperspective "; + case TGSI_INTERPOLATE_PERSPECTIVE: + return "smooth "; + case TGSI_INTERPOLATE_CONSTANT: + return "flat "; + } + return NULL; +} + +static void emit_ios(struct dump_ctx *ctx, char *glsl_final) +{ + int i; + char buf[255]; + const char *prefix = ""; + + ctx->num_interps = 0; + + if (ctx->prog_type == TGSI_PROCESSOR_FRAGMENT) { + if (fs_emit_layout(ctx)) { + boolean upper_left = !(ctx->fs_coord_origin ^ ctx->key->invert_fs_origin); + char comma = (upper_left && ctx->fs_pixel_center) ? ',' : ' '; + + snprintf(buf, 255, "layout(%s%c%s) in vec4 gl_FragCoord;\n", + upper_left ? "origin_upper_left" : "", + comma, + ctx->fs_pixel_center ? "pixel_center_integer" : ""); + strcat(glsl_final, buf); + } + } + for (i = 0; i < ctx->num_inputs; i++) { + if (!ctx->inputs[i].glsl_predefined_no_emit) { + if (ctx->prog_type == TGSI_PROCESSOR_VERTEX && graw_shader_use_explicit) { + snprintf(buf, 255, "layout(location=%d) ", ctx->inputs[i].first); + strcat(glsl_final, buf); + } + if (ctx->prog_type == TGSI_PROCESSOR_FRAGMENT && + (ctx->inputs[i].name == TGSI_SEMANTIC_GENERIC || + ctx->inputs[i].name == TGSI_SEMANTIC_COLOR)) { + prefix = get_interp_string(ctx->inputs[i].interpolate); + if (!prefix) + prefix = ""; + else + ctx->num_interps++; + } + + snprintf(buf, 255, "%sin vec4 %s;\n", prefix, ctx->inputs[i].glsl_name); + strcat(glsl_final, buf); + } + } + if (ctx->write_all_cbufs) { + for (i = 0; i < 8; i++) { + snprintf(buf, 255, "out vec4 out_c%d;\n", i); + strcat(glsl_final, buf); + } + } else { + for (i = 0; i < ctx->num_outputs; i++) { + if (!ctx->outputs[i].glsl_predefined_no_emit) { + if (ctx->prog_type == TGSI_PROCESSOR_VERTEX && (ctx->outputs[i].name == TGSI_SEMANTIC_GENERIC || ctx->outputs[i].name == TGSI_SEMANTIC_COLOR || ctx->outputs[i].name == TGSI_SEMANTIC_BCOLOR)) { + ctx->num_interps++; + prefix = INTERP_PREFIX; + } else + prefix = ""; + /* ugly leave spaces to patch interp in later */ + snprintf(buf, 255, "%sout vec4 %s;\n", prefix, ctx->outputs[i].glsl_name); + strcat(glsl_final, buf); + } + } + } + + if (ctx->prog_type == TGSI_PROCESSOR_VERTEX) { + snprintf(buf, 255, "uniform vec4 winsys_adjust;\n"); + strcat(glsl_final, buf); + + if (ctx->num_clip_dist) { + snprintf(buf, 255, "out float gl_ClipDistance[%d];\n", ctx->num_clip_dist); + strcat(glsl_final, buf); + snprintf(buf, 255, "vec4 clip_dist_temp[2];\n"); + strcat(glsl_final, buf); + } + } + + if (ctx->so) { + char outtype[6] = {0}; + for (i = 0; i < ctx->so->num_outputs; i++) { + if (ctx->so->output[i].num_components == 1) + snprintf(outtype, 6, "float"); + else + snprintf(outtype, 6, "vec%d", ctx->so->output[i].num_components); + snprintf(buf, 255, "out %s tfout%d;\n", outtype, i); + strcat(glsl_final, buf); + } + } + if (ctx->num_temps) { + snprintf(buf, 255, "vec4 temps[%d];\n", ctx->num_temps); + strcat(glsl_final, buf); + } + + for (i = 0; i < ctx->num_address; i++) { + snprintf(buf, 255, "int addr%d;\n", i); + strcat(glsl_final, buf); + } + if (ctx->num_consts) { + const char *cname = ctx->prog_type == TGSI_PROCESSOR_VERTEX ? "vsconst" : "fsconst"; + snprintf(buf, 255, "uniform vec4 %s[%d];\n", cname, ctx->num_consts); + strcat(glsl_final, buf); + } + for (i = 0; i < 32; i++) { + int is_shad = 0; + const char *stc; + + if ((ctx->samplers_used & (1 << i)) == 0) + continue; + + stc = samplertypeconv(ctx->samplers[i].tgsi_sampler_type, &is_shad); + + if (stc) { + char *sname = "fs"; + + if (ctx->prog_type == TGSI_PROCESSOR_VERTEX) + sname = "vs"; + + snprintf(buf, 255, "uniform sampler%s %ssamp%d;\n", stc, sname, i); + strcat(glsl_final, buf); + if (is_shad) { + snprintf(buf, 255, "uniform vec4 %sshadmask%d;\n", sname, i); + strcat(glsl_final, buf); + snprintf(buf, 255, "uniform vec4 %sshadadd%d;\n", sname, i); + strcat(glsl_final, buf); + ctx->shadow_samp_mask |= (1 << i); + } + } + + } +} + +static boolean fill_fragment_interpolants(struct dump_ctx *ctx, struct vrend_shader_info *sinfo) +{ + int i, index = 0; + + for (i = 0; i < ctx->num_inputs; i++) { + if (ctx->inputs[i].glsl_predefined_no_emit) + continue; + + if (ctx->inputs[i].name != TGSI_SEMANTIC_GENERIC && + ctx->inputs[i].name != TGSI_SEMANTIC_COLOR) + continue; + + if (ctx->inputs[i].interpolate == TGSI_INTERPOLATE_COLOR) + continue; + + sinfo->interpinfo[index].semantic_name = ctx->inputs[i].name; + sinfo->interpinfo[index].semantic_index = ctx->inputs[i].sid; + sinfo->interpinfo[index].interpolate = ctx->inputs[i].interpolate; + index++; + } + return TRUE; +} + +static boolean fill_interpolants(struct dump_ctx *ctx, struct vrend_shader_info *sinfo) +{ + boolean ret; + + if (!ctx->num_interps) + return TRUE; + if (ctx->prog_type == TGSI_PROCESSOR_VERTEX) + return TRUE; + + sinfo->interpinfo = calloc(ctx->num_interps, sizeof(struct vrend_interp_info)); + if (!sinfo->interpinfo) + return FALSE; + + ret = fill_fragment_interpolants(ctx, sinfo); + if (ret == FALSE) + goto out_fail; + + return TRUE; + out_fail: + free(sinfo->interpinfo); + return FALSE; +} + +char *tgsi_convert(const struct tgsi_token *tokens, + struct vrend_shader_key *key, + struct vrend_shader_info *sinfo) +{ + struct dump_ctx ctx; + char *glsl_final; + boolean ret; + + memset(&ctx, 0, sizeof(struct dump_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.key = key; + if (sinfo->so_info.num_outputs) { + ctx.so = &sinfo->so_info; + } + + ctx.glsl_main = malloc(65536); + ctx.glsl_main[0] = '\0'; + tgsi_iterate_shader(tokens, &ctx.iter); + + glsl_final = malloc(65536); + glsl_final[0] = '\0'; + emit_header(&ctx, glsl_final); + emit_ios(&ctx, glsl_final); + + ret = fill_interpolants(&ctx, sinfo); + if (ret == FALSE) { + free(ctx.glsl_main); + free(glsl_final); + return NULL; + } + strcat(glsl_final, ctx.glsl_main); + if (vrend_dump_shaders) + fprintf(stderr,"GLSL: %s\n", glsl_final); + free(ctx.glsl_main); + sinfo->samplers_used_mask = ctx.samplers_used; + sinfo->num_consts = ctx.num_consts; + sinfo->num_inputs = ctx.num_inputs; + sinfo->num_interps = ctx.num_interps; + sinfo->num_outputs = ctx.num_outputs; + sinfo->shadow_samp_mask = ctx.shadow_samp_mask; + return glsl_final; +} + +static void replace_interp(char *program, + const char *var_name, + const char *pstring) +{ + char *ptr; + int mylen = strlen(INTERP_PREFIX) + strlen("out vec4 "); + + ptr = strstr(program, var_name); + + if (!ptr) + return; + + ptr -= mylen; + + memcpy(ptr, pstring, strlen(pstring)); +} + +boolean vrend_patch_vertex_shader_interpolants(char *program, + struct vrend_shader_info *vs_info, + struct vrend_shader_info *fs_info) +{ + int i; + const char *pstring; + char glsl_name[64]; + if (!vs_info || !fs_info) + return TRUE; + + if (!fs_info->interpinfo) + return TRUE; + + for (i = 0; i < fs_info->num_interps; i++) { + pstring = get_interp_string(fs_info->interpinfo[i].interpolate); + if (!pstring) + continue; + + switch (fs_info->interpinfo[i].semantic_name) { + case TGSI_SEMANTIC_GENERIC: + snprintf(glsl_name, 64, "ex_g%d", fs_info->interpinfo[i].semantic_index); + replace_interp(program, glsl_name, pstring); + break; + case TGSI_SEMANTIC_COLOR: + /* color is a bit trickier */ + if (fs_info->interpinfo[i].semantic_index == 1) { + replace_interp(program, "gl_FrontSecondaryColor", pstring); + replace_interp(program, "gl_BackSecondaryColor", pstring); + } else { + replace_interp(program, "gl_FrontColor", pstring); + replace_interp(program, "gl_BackColor", pstring); + } + + break; + } + } + + if (vrend_dump_shaders) + fprintf(stderr,"GLSL: post interp: %s\n", program); + return TRUE; +} diff --git a/src/graw_shader.h b/src/graw_shader.h new file mode 100644 index 0000000..7eda12e --- /dev/null +++ b/src/graw_shader.h @@ -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 diff --git a/src/graw_virtio_lib_renderer.c b/src/graw_virtio_lib_renderer.c new file mode 100644 index 0000000..1bd702f --- /dev/null +++ b/src/graw_virtio_lib_renderer.c @@ -0,0 +1,426 @@ +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#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); + +} diff --git a/src/iov.c b/src/iov.c new file mode 100644 index 0000000..febab06 --- /dev/null +++ b/src/iov.c @@ -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 + * Amit Shah + * Michael Tokarev + * + * 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 +#include + +#include + + +#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 diff --git a/src/virgl_egl.h b/src/virgl_egl.h new file mode 100644 index 0000000..b3c8e13 --- /dev/null +++ b/src/virgl_egl.h @@ -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 diff --git a/src/virgl_egl_context.c b/src/virgl_egl_context.c new file mode 100644 index 0000000..3da48f2 --- /dev/null +++ b/src/virgl_egl_context.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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; + } +} diff --git a/src/virgl_helper.h b/src/virgl_helper.h new file mode 100644 index 0000000..1e84c69 --- /dev/null +++ b/src/virgl_helper.h @@ -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 diff --git a/src/virgl_hw.h b/src/virgl_hw.h new file mode 100644 index 0000000..fb20164 --- /dev/null +++ b/src/virgl_hw.h @@ -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 diff --git a/src/virgl_protocol.h b/src/virgl_protocol.h new file mode 100644 index 0000000..d863b72 --- /dev/null +++ b/src/virgl_protocol.h @@ -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 diff --git a/src/virglrenderer.h b/src/virglrenderer.h new file mode 100644 index 0000000..cd7a8f3 --- /dev/null +++ b/src/virglrenderer.h @@ -0,0 +1,52 @@ +/* library interface from QEMU to virglrenderer */ + +#ifndef VIRGLRENDERER_H +#define VIRGLRENDERER_H + +#include + +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 diff --git a/src/virtgpu_hw.h b/src/virtgpu_hw.h new file mode 100644 index 0000000..9a6f2a4 --- /dev/null +++ b/src/virtgpu_hw.h @@ -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 diff --git a/src/vrend_object.c b/src/vrend_object.c new file mode 100644 index 0000000..53db2db --- /dev/null +++ b/src/vrend_object.c @@ -0,0 +1,182 @@ +#include +#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); +} diff --git a/src/vrend_object.h b/src/vrend_object.h new file mode 100644 index 0000000..4fd1f13 --- /dev/null +++ b/src/vrend_object.h @@ -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 diff --git a/virglrenderer.pc.in b/virglrenderer.pc.in new file mode 100644 index 0000000..d1a00ca --- /dev/null +++ b/virglrenderer.pc.in @@ -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