├── .gitignore ├── Makefile.am ├── README.md ├── autogen.sh ├── configure.ac ├── contrib └── 70-tegra_vde.rules └── src ├── Makefile.am ├── asm ├── asm.h ├── fragment_asm.h ├── fragment_asm.l ├── fragment_asm.y ├── linker_asm.h ├── linker_asm.l ├── linker_asm.y ├── vertex_asm.h ├── vertex_asm.l └── vertex_asm.y ├── atomic.h ├── bitstream.c ├── bitstream.h ├── decoder.c ├── dmabuf.c ├── dri2.c ├── dri2.h ├── gen_shader_bin.c ├── host1x-api.h ├── host1x-gr2d.c ├── host1x-gr3d.c ├── host1x-pixelbuffer.c ├── host1x.h ├── media.c ├── media.h ├── presentation_queue.c ├── presentation_queue_target.c ├── shaders ├── blend_atop │ ├── fragment.asm │ ├── linker.asm │ └── vertex.asm ├── blend_atop_solid_shade │ ├── fragment.asm │ ├── linker.asm │ └── vertex.asm └── prog.h ├── surface.c ├── surface_bitmap.c ├── surface_cache.c ├── surface_mixer.c ├── surface_output.c ├── surface_rotate.c ├── surface_shared.c ├── surface_video.c ├── tegra_stream.h ├── tegra_stream_v1.c ├── tegra_stream_v2.c ├── tegradrm ├── atomic.h ├── lists.h ├── opentegra_drm.h ├── opentegra_lib.h ├── private.h ├── tegra.c ├── tegra_bo_cache.c ├── uapi_v1 │ ├── channel.c │ ├── fence.c │ ├── job.c │ ├── pushbuf.c │ └── uapi_v1.h └── uapi_v2 │ └── job.c ├── tgr_3d.xml.h ├── uapi ├── dma-buf.h ├── media.h ├── tegra-vde-v1.h ├── tegra-vde.h ├── types-compat.h ├── v4l2-common.h ├── v4l2-controls.h └── videodev2.h ├── util_double_list.h ├── v4l2.c ├── v4l2.h ├── vdpau-tegra.pc.in ├── vdpau_tegra.c └── vdpau_tegra.h /.gitignore: -------------------------------------------------------------------------------- 1 | .* 2 | *.o 3 | *.la 4 | *.lo 5 | *.pc 6 | Makefile 7 | Makefile.in 8 | aclocal.m4 9 | autom4te.cache/ 10 | compile 11 | config.* 12 | configure 13 | depcomp 14 | install-sh 15 | libtool 16 | ltmain.sh 17 | missing 18 | stamp-h1 19 | m4 20 | *.tab.h 21 | *.tab.c 22 | *.lex.c 23 | src/shaders/*.bin.h 24 | src/gen_shader_bin 25 | *~ 26 | *.orig 27 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = src 2 | 3 | ACLOCAL_AMFLAGS = -I m4 4 | udevrulesdir = $(udevdir)/rules.d 5 | dist_udevrules_DATA = contrib/70-tegra_vde.rules 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 | This is a VDPAU backend driver for the NVIDIA Tegra SoC's. 4 | 5 | # Requirements: 6 | 7 | Mandatory: 8 | * autotools 9 | * libvdpau (https://www.freedesktop.org/wiki/Software/VDPAU/) 10 | * pixman (http://www.pixman.org) 11 | * libX11 libXext xextproto libXfixes libXv 12 | * opentegra (https://github.com/grate-driver/xf86-video-opentegra) 13 | 14 | Optional: 15 | * mesa (https://github.com/grate-driver/mesa) 16 | * Linux kernel 4.16+ (https://www.kernel.org/), enable "staging/media" drivers and select "NVIDIA Tegra Video Decoder Engine driver" in the kernel config 17 | 18 | The VDE linux kernel driver is optional, it is required for HW accelerated video decoding. Currently VDE driver 19 | supports CAVLC H.264 videos only. The accelerated video output works without the VDE driver. 20 | 21 | Usage of the most recent mainline upstream Linux kernel is very recommended, not all DRM fixes are backportable and some usability-critical features may be missed in older kernels. 22 | 23 | # Installation: 24 | 25 | ### Ubuntu 26 | 27 | ``` 28 | sudo add-apt-repository ppa:grate-driver/ppa 29 | sudo apt-get update 30 | sudo apt-get install libvdpau-tegra 31 | ``` 32 | 33 | ### Gentoo 34 | 35 | ``` 36 | sudo layman -f -o https://raw.githubusercontent.com/grate-driver/grate-overlay/master/overlay.xml -a grate-overlay 37 | sudo emerge libvdpau-tegra-driver 38 | ``` 39 | 40 | ### Arch Linux 41 | 42 | There is PKGBUILD in https://aur.archlinux.org/packages/libvdpau-tegra-git/. 43 | 44 | ### Fedora 45 | 46 | ``` 47 | sudo dnf copr enable kwizart/grate-driver 48 | sudo dnf update 49 | sudo dnf install xorg-x11-drv-opentegra libvdpau-tegra grate 50 | ``` 51 | 52 | ### From sources 53 | 54 | ``` 55 | git clone https://github.com/grate-driver/libvdpau-tegra.git 56 | cd libvdpau-tegra 57 | sh autogen.sh --prefix=/ 58 | make 59 | sudo make install 60 | ``` 61 | 62 | # Usage example: 63 | 64 | If you are going to use the VDE for accelerated video decoding, first make sure that your user account has access to the VDE device. Giving access to everyone should be fine, driver uses dmabuf and performs all necessary validations, however it will be better if you change the device owner to your user or add it to the groups (video for example) relevant for your account. 65 | 66 | ``` 67 | $ ls -l /dev/tegra_vde 68 | crw------- 1 root root 10, 61 Jun 21 05:37 /dev/tegra_vde 69 | $ sudo chmod 0666 /dev/tegra_vde 70 | $ ls -l /dev/tegra_vde 71 | crw-rw-rw- 1 root root 10, 61 Jun 21 05:37 /dev/tegra_vde 72 | ``` 73 | For a usage example we use mpv (https://mpv.io/). Other players that support VDPAU are also (kinda) working, but mpv is known to work fine and is recommended. 74 | 75 | ``` 76 | $ VDPAU_DRIVER=tegra VDPAU_DRIVER_PATH=/path/to/libvdpau_tegra.so mpv --hwdec=vdpau --vo=vdpau video.mp4 77 | ``` 78 | 79 | The `VDPAU_DRIVER` and `VDPAU_DRIVER_PATH` environment variables aren't required if mesa (https://github.com/grate-driver/mesa) is installed. 80 | 81 | You should see the following lines in the terminal: 82 | ``` 83 | Using hardware decoding (vdpau). 84 | VO: [vdpau] 1280x720 vdpau[yuv420p] 85 | ``` 86 | If you don't see anything related to VDPAU, it means that it doesn't work for some reason. Check that `/usr/lib/vdpau/libvdpau_tegra.so.1` exists, note that `VDPAU_DRIVER_PATH` must point to the directory containing the shared library, not the library file. 87 | 88 | # Resolving issues: 89 | 90 | Debug messages could be enabled using these environment variables: `VDPAU_TRACE=1` `VDPAU_TEGRA_DEBUG=1`. 91 | 92 | # Environment variables: 93 | 94 | * `VDPAU_TEGRA_FORCE_XV=1` force display output to Xv overlay 95 | * `VDPAU_TEGRA_FORCE_DRI=1` force display output using DRI 96 | * `VDPAU_TEGRA_DRI_XV_AUTOSWITCH=1` force-enable Xv<=>DRI output autoswitching (which is disabled if compositor or display rotation detected) 97 | 98 | # Todo: 99 | 100 | * ~~Accelerated output to overlay~~ 101 | * Offload ~~color conversion, blitting~~ and blending to HW 102 | * H.264 CABAC support (reverse-engineering pending) 103 | * Support other codecs, like VC-1 or H.263 104 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | srcdir=`dirname "$0"` 4 | test -z "$srcdir" && srcdir=. 5 | 6 | ORIGDIR=`pwd` 7 | cd "$srcdir" 8 | test -d m4 || mkdir m4 9 | 10 | autoreconf --force --verbose --install || exit 1 11 | cd "$ORIGDIR" || exit $? 12 | 13 | if test -z "$NOCONFIGURE"; then 14 | "$srcdir"/configure "$@" 15 | fi 16 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ([2.60]) 5 | AC_INIT([libvdpau_tegra], [1.0.0], [digetx@gmail.com]) 6 | AC_CONFIG_SRCDIR([src/vdpau_tegra.c]) 7 | AC_CONFIG_HEADERS([config.h]) 8 | AC_CONFIG_AUX_DIR(.) 9 | 10 | AM_INIT_AUTOMAKE([foreign subdir-objects]) 11 | 12 | AM_DISABLE_STATIC 13 | 14 | # Checks for programs. 15 | AC_PROG_CC 16 | AC_PROG_INSTALL 17 | AC_PROG_LIBTOOL 18 | PKG_PROG_PKG_CONFIG 19 | 20 | # Checks for dependencies. 21 | PKG_CHECK_MODULES(X11, x11 xext xextproto xfixes xrandr) 22 | AC_SUBST(X11_CFLAGS) 23 | AC_SUBST(X11_LIBS) 24 | 25 | PKG_CHECK_MODULES(VDPAU, vdpau) 26 | AC_SUBST(VDPAU_CFLAGS) 27 | AC_SUBST(VDPAU_LIBS) 28 | 29 | PKG_CHECK_MODULES(PIXMAN, pixman-1) 30 | AC_SUBST(PIXMAN_CFLAGS) 31 | AC_SUBST(PIXMAN_LIBS) 32 | 33 | PKG_CHECK_MODULES(DRM, [libdrm]) 34 | AC_SUBST(DRM_CFLAGS) 35 | AC_SUBST(DRM_LIBS) 36 | 37 | PKG_CHECK_MODULES(XV, xv) 38 | AC_SUBST(XV_CFLAGS) 39 | AC_SUBST(XV_LIBS) 40 | 41 | dnl ========================================================================== 42 | dnl define PKG_CHECK_VAR for old pkg-config <= 0.28 43 | m4_ifndef([PKG_CHECK_VAR], [ 44 | AC_DEFUN([PKG_CHECK_VAR], 45 | [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl 46 | AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl 47 | 48 | _PKG_CONFIG([$1], [variable="][$3]["], [$2]) 49 | AS_VAR_COPY([$1], [pkg_cv_][$1]) 50 | 51 | AS_VAR_IF([$1], [""], [$5], [$4])dnl 52 | ])dnl PKG_CHECK_VAR 53 | ]) 54 | dnl ========================================================================== 55 | 56 | PKG_CHECK_VAR([udevdir], [udev], [udevdir], [], [udevdir=/lib/udev]) 57 | 58 | # Checks for libraries. 59 | AC_CHECK_LIB([m], [sin]) 60 | 61 | # Checks for header files. 62 | AC_PATH_X 63 | AC_CHECK_HEADERS([fcntl.h limits.h stdint.h stdlib.h string.h sys/ioctl.h unistd.h]) 64 | 65 | # Checks for typedefs, structures, and compiler characteristics. 66 | AC_TYPE_INT32_T 67 | AC_TYPE_INT8_T 68 | AC_TYPE_SIZE_T 69 | AC_TYPE_UINT16_T 70 | AC_TYPE_UINT32_T 71 | AC_TYPE_UINT64_T 72 | AC_TYPE_UINT8_T 73 | 74 | # Checks for library functions. 75 | AC_CHECK_FUNCS([clock_gettime memset munmap]) 76 | 77 | # Initialize compiler compiler 78 | AC_PROG_LEX 79 | if test "$LEX" = :; then 80 | AC_MSG_ERROR([flex not found]) 81 | fi 82 | 83 | AC_CHECK_PROGS(YACC, 'bison -y' byacc yacc, :) 84 | if test "$YACC" = :; then 85 | AC_MSG_ERROR([bison not found]) 86 | fi 87 | 88 | SAVE_CFLAGS=$CFLAGS 89 | SAVE_LIBS=$LIBS 90 | CFLAGS=$DRM_CFLAGS 91 | LIBS=$DRM_LIBS 92 | 93 | AC_CHECK_FUNCS( 94 | [drmSyncobjCreate], 95 | [ 96 | AC_MSG_RESULT([yes]) 97 | AC_DEFINE(HAVE_LIBDRM_SYNCOBJ_SUPPORT, [], [Does libdrm have drmSyncobjCreate]) 98 | ], 99 | [ 100 | AC_MSG_RESULT([no]) 101 | ]) 102 | 103 | CFLAGS=$SAVE_CFLAGS 104 | LIBS=$SAVE_LIBS 105 | 106 | AC_ARG_ENABLE(valgrind, 107 | [AS_HELP_STRING([--enable-valgrind], 108 | [Build libdrm with valgrind support (default: auto)])], 109 | [VALGRIND=$enableval], [VALGRIND=auto]) 110 | if test "x$VALGRIND" != xno; then 111 | PKG_CHECK_MODULES(VALGRIND, [valgrind], [have_valgrind=yes], [have_valgrind=no]) 112 | fi 113 | AC_MSG_CHECKING([whether to enable Valgrind support]) 114 | if test "x$VALGRIND" = xauto; then 115 | VALGRIND="$have_valgrind" 116 | fi 117 | 118 | if test "x$VALGRIND" = "xyes"; then 119 | if ! test "x$have_valgrind" = xyes; then 120 | AC_MSG_ERROR([Valgrind support required but not present]) 121 | fi 122 | AC_DEFINE([HAVE_VALGRIND], 1, [Use valgrind intrinsics to suppress false warnings]) 123 | else 124 | AC_DEFINE([HAVE_VALGRIND], 0) 125 | fi 126 | 127 | AC_MSG_RESULT([$VALGRIND]) 128 | 129 | AC_ARG_ENABLE([debug], 130 | [AS_HELP_STRING([--enable-debug], 131 | [use debug compiler flags and macros @<:@default=disabled@:>@])], 132 | [enable_debug="$enableval"], 133 | [enable_debug=no] 134 | ) 135 | 136 | if test "x$enable_debug" = xyes; then 137 | DEFINES="$DEFINES -DDEBUG" 138 | if test "x$GCC" = xyes; then 139 | if ! echo "$CFLAGS" | grep -q -e '-g'; then 140 | CFLAGS="$CFLAGS -g" 141 | fi 142 | if ! echo "$CFLAGS" | grep -q -e '-O'; then 143 | CFLAGS="$CFLAGS -O0" 144 | fi 145 | fi 146 | if test "x$GXX" = xyes; then 147 | if ! echo "$CXXFLAGS" | grep -q -e '-g'; then 148 | CXXFLAGS="$CXXFLAGS -g" 149 | fi 150 | if ! echo "$CXXFLAGS" | grep -q -e '-O'; then 151 | CXXFLAGS="$CXXFLAGS -O0" 152 | fi 153 | fi 154 | else 155 | DEFINES="$DEFINES -DNDEBUG" 156 | fi 157 | 158 | AC_SUBST([DEFINES]) 159 | 160 | AC_CONFIG_FILES([Makefile 161 | src/Makefile 162 | src/vdpau-tegra.pc]) 163 | AC_OUTPUT 164 | -------------------------------------------------------------------------------- /contrib/70-tegra_vde.rules: -------------------------------------------------------------------------------- 1 | KERNEL=="tegra_vde", NAME="tegra_vde", GROUP="video", MODE="0666" 2 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | AUTOMAKE_OPTIONS=subdir-objects 2 | 3 | AM_CFLAGS = -Wall -pthread -mfp16-format=ieee \ 4 | $(X11_CFLAGS) $(PIXMAN_CFLAGS) $(DRM_CFLAGS) $(XV_CFLAGS) \ 5 | $(VALGRIND_CFLAGS) $(DEFINES) 6 | 7 | AM_CFLAGS += -I$(srcdir)/tegradrm -fvisibility=hidden 8 | 9 | vdpau_tegra_libdir = $(libdir)/vdpau 10 | vdpau_tegra_lib_LTLIBRARIES = libvdpau_tegra.la 11 | 12 | libvdpau_tegra_la_SOURCES = vdpau_tegra.c \ 13 | surface_cache.c \ 14 | surface_rotate.c \ 15 | surface_output.c \ 16 | surface_bitmap.c \ 17 | surface_video.c \ 18 | surface_mixer.c \ 19 | surface_shared.c \ 20 | surface.c \ 21 | presentation_queue.c \ 22 | presentation_queue_target.c \ 23 | decoder.c \ 24 | dmabuf.c \ 25 | bitstream.c \ 26 | host1x-gr2d.c \ 27 | host1x-pixelbuffer.c \ 28 | tegra_stream_v1.c \ 29 | tegra_stream_v2.c \ 30 | dri2.c \ 31 | shaders/prog.h \ 32 | $(shaders_gen) \ 33 | tgr_3d.xml.h \ 34 | shaders.h \ 35 | host1x-gr3d.c \ 36 | host1x-gr3d.h \ 37 | media.c \ 38 | media.h \ 39 | v4l2.c \ 40 | v4l2.h 41 | 42 | libvdpau_tegra_la_SOURCES += tegradrm/atomic.h \ 43 | tegradrm/lists.h \ 44 | tegradrm/opentegra_drm.h \ 45 | tegradrm/opentegra_lib.h \ 46 | tegradrm/private.h \ 47 | tegradrm/tegra.c \ 48 | tegradrm/tegra_bo_cache.c \ 49 | tegradrm/uapi_v1/channel.c \ 50 | tegradrm/uapi_v1/fence.c \ 51 | tegradrm/uapi_v1/job.c \ 52 | tegradrm/uapi_v1/pushbuf.c \ 53 | tegradrm/uapi_v2/job.c 54 | 55 | libvdpau_tegra_la_LDFLAGS = -version-info 1:0:0 -module -Wl,-z,defs 56 | libvdpau_tegra_la_LIBADD = -lm $(X11_LIBS) $(PIXMAN_LIBS) $(DRM_LIBS) $(XV_LIBS) 57 | 58 | pkgconfigdir = ${libdir}/pkgconfig 59 | pkgconfig_DATA = vdpau-tegra.pc 60 | 61 | shaders_dir := $(filter %/, $(wildcard $(srcdir)/shaders/*/)) 62 | shaders_gen := $(addsuffix .bin.h, $(shaders_dir:%/=%)) 63 | 64 | %.bin.h: gen_shader_bin \ 65 | %/vertex.asm \ 66 | %/linker.asm \ 67 | %/fragment.asm 68 | $(builddir)/gen_shader_bin \ 69 | --vs $*/vertex.asm \ 70 | --lnk $*/linker.asm \ 71 | --fs $*/fragment.asm \ 72 | --name $(*F) \ 73 | --out $@ 74 | 75 | asm_grammars := $(wildcard $(srcdir)/asm/*.y) 76 | asm_headers := $(wildcard $(srcdir)/asm/*.h) 77 | asm_lexers := $(wildcard $(srcdir)/asm/*.l) 78 | 79 | asm_gen_c := \ 80 | $(asm_lexers:%.l=%.lex.c) \ 81 | $(asm_grammars:%.y=%.tab.c) 82 | 83 | asm_gen_h := \ 84 | $(asm_grammars:%.y=%.tab.h) 85 | 86 | %.lex.c: $(asm_lexers) 87 | $(LEX) -P $(*F) --nounput -o $@ $*.l 88 | 89 | %.tab.c %.tab.h: $(asm_grammars) 90 | $(YACC) -p $(*F) -b $(*F) -d --debug -o $@ $*.y 91 | 92 | HOSTCC = gcc 93 | 94 | gen_shader_bin: gen_shader_bin.c $(asm_gen_c) $(asm_headers) 95 | $(HOSTCC) -I $(srcdir)/asm -o $(builddir)/$@ $< $(asm_gen_c) 96 | 97 | BUILT_SOURCES = \ 98 | $(asm_gen_c) \ 99 | $(asm_gen_h) \ 100 | $(shaders_gen) 101 | 102 | CLEANFILES = \ 103 | $(asm_gen_c) \ 104 | $(asm_gen_h) \ 105 | $(shaders_gen) \ 106 | $(builddir)/gen_shader_bin 107 | -------------------------------------------------------------------------------- /src/asm/asm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Dmitry Osipenko 3 | * Copyright (c) Erik Faye-Lund 4 | * 5 | * This program is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License as published by the 7 | * Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 | * for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along 16 | * with this program; if not, see . 17 | */ 18 | 19 | #ifndef GRATE_ASM_H 20 | #define GRATE_ASM_H 21 | 22 | #include "fragment_asm.h" 23 | #include "linker_asm.h" 24 | #include "vertex_asm.h" 25 | 26 | struct yy_buffer_state; 27 | 28 | extern struct yy_buffer_state *vertex_asm_scan_string(const char *); 29 | extern int vertex_asmparse(void); 30 | extern int vertex_asmlex_destroy(void); 31 | 32 | struct asm_vec_component { 33 | uint32_t value; 34 | int dirty; 35 | }; 36 | 37 | typedef struct asm_vec4 { 38 | struct asm_vec_component x; 39 | struct asm_vec_component y; 40 | struct asm_vec_component z; 41 | struct asm_vec_component w; 42 | } asm_vec4; 43 | 44 | typedef struct asm_const { 45 | asm_vec4 vector; 46 | int used; 47 | } asm_const; 48 | 49 | typedef struct asm_in_out { 50 | char name[256]; 51 | union { 52 | int used; 53 | int type; 54 | }; 55 | } asm_in_out; 56 | 57 | extern vpe_instr128 asm_vs_instructions[256]; 58 | extern asm_const asm_vs_constants[256]; 59 | extern asm_in_out asm_vs_attributes[16]; 60 | extern asm_in_out asm_vs_exports[16]; 61 | extern asm_in_out asm_vs_uniforms[256]; 62 | extern int asm_vs_instructions_nb; 63 | 64 | extern struct yy_buffer_state *fragment_asm_scan_string(const char *); 65 | extern int fragment_asmparse(void); 66 | extern int fragment_asmlex_destroy(void); 67 | 68 | extern pseq_instr asm_pseq_instructions[64]; 69 | extern mfu_instr asm_mfu_instructions[64]; 70 | extern tex_instr asm_tex_instructions[64]; 71 | extern alu_instr asm_alu_instructions[64]; 72 | extern dw_instr asm_dw_instructions[64]; 73 | 74 | extern instr_sched asm_mfu_sched[64]; 75 | extern instr_sched asm_alu_sched[64]; 76 | 77 | extern uint32_t asm_fs_constants[32]; 78 | 79 | #define FS_UNIFORM_FX10_LOW 1 80 | #define FS_UNIFORM_FX10_HIGH 2 81 | #define FS_UNIFORM_FP20 3 82 | 83 | extern asm_in_out asm_fs_uniforms[32 * 2]; 84 | 85 | extern unsigned asm_fs_instructions_nb; 86 | extern unsigned asm_mfu_instructions_nb; 87 | extern unsigned asm_alu_instructions_nb; 88 | 89 | extern unsigned asm_alu_buffer_size; 90 | extern unsigned asm_pseq_to_dw_exec_nb; 91 | 92 | extern int asm_discards_fragment; 93 | 94 | extern struct yy_buffer_state *linker_asm_scan_string(const char *); 95 | extern int linker_asmparse(void); 96 | extern int linker_asmlex_destroy(void); 97 | 98 | extern link_instr asm_linker_instructions[32]; 99 | 100 | extern unsigned asm_linker_instructions_nb; 101 | extern unsigned asm_linker_used_tram_rows_nb; 102 | 103 | #endif 104 | -------------------------------------------------------------------------------- /src/asm/fragment_asm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Dmitry Osipenko 3 | * Copyright (c) Erik Faye-Lund 4 | * 5 | * This program is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License as published by the 7 | * Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 | * for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along 16 | * with this program; if not, see . 17 | */ 18 | 19 | #ifndef FRAGMENT_ASM_H 20 | #define FRAGMENT_ASM_H 21 | 22 | #include 23 | 24 | #define FRAGMENT_ROW_REG_0 0 25 | #define FRAGMENT_ROW_REG_15 15 26 | #define FRAGMENT_ROW_REG(r) (FRAGMENT_ROW_REG_0 + (r)) 27 | #define FRAGMENT_GENERAL_PURPOSE_REG_0 16 28 | #define FRAGMENT_GENERAL_PURPOSE_REG_7 23 29 | #define FRAGMENT_GENERAL_PURPOSE_REG(r) (FRAGMENT_GENERAL_PURPOSE_REG_0 + (r)) 30 | #define FRAGMENT_ALU_RESULT_REG_0 24 31 | #define FRAGMENT_ALU_RESULT_REG_3 27 32 | #define FRAGMENT_ALU_RESULT_REG(r) (FRAGMENT_ALU_RESULT_REG_0 + (r)) 33 | #define FRAGMENT_EMBEDDED_CONSTANT_0 28 34 | #define FRAGMENT_EMBEDDED_CONSTANT_2 30 35 | #define FRAGMENT_EMBEDDED_CONSTANT(r) (FRAGMENT_EMBEDDED_CONSTANT_0 + (r)) 36 | #define FRAGMENT_LOWP_VEC2_0_1 31 37 | #define FRAGMENT_UNIFORM_REG_0 32 38 | #define FRAGMENT_UNIFORM_REG_31 63 39 | #define FRAGMENT_UNIFORM_REG(r) (FRAGMENT_UNIFORM_REG_0 + (r)) 40 | #define FRAGMENT_CONDITION_REG_0 64 41 | #define FRAGMENT_CONDITION_REG_7 71 42 | #define FRAGMENT_CONDITION_REG(r) (FRAGMENT_CONDITION_REG_0 + (r)) 43 | #define FRAGMENT_POS_X 72 44 | #define FRAGMENT_POS_Y 73 45 | #define FRAGMENT_POLYGON_FACE 75 46 | #define FRAGMENT_KILL_REG 76 47 | 48 | typedef union fragment_instruction_schedule { 49 | struct __attribute__((packed)) { 50 | unsigned instructions_nb:2; 51 | unsigned address:6; 52 | }; 53 | 54 | uint32_t data; 55 | } instr_sched; 56 | 57 | typedef union fragment_alu_instruction_schedule_t114 { 58 | struct __attribute__((packed)) { 59 | unsigned __pad:8; 60 | unsigned instructions_nb:8; 61 | unsigned address:8; 62 | unsigned unk24_31:8; 63 | }; 64 | 65 | uint32_t data; 66 | } alu_instr_sched_t114; 67 | 68 | static inline alu_instr_sched_t114 to_114_alu_sched(uint32_t reg_value) 69 | { 70 | instr_sched t20_sched = { .data = reg_value }; 71 | alu_instr_sched_t114 t114_sched; 72 | 73 | t114_sched.instructions_nb = t20_sched.instructions_nb; 74 | t114_sched.address = t20_sched.address; 75 | t114_sched.unk24_31 = 0xe0; 76 | 77 | return t114_sched; 78 | } 79 | 80 | #define MFU_NOP 0 81 | #define MFU_RCP 1 82 | #define MFU_RSQ 2 83 | #define MFU_LG2 3 84 | #define MFU_EX2 4 85 | #define MFU_SQRT 5 86 | #define MFU_SIN 6 87 | #define MFU_COS 7 88 | #define MFU_FRC 8 89 | #define MFU_PREEX2 9 90 | #define MFU_PRESIN 10 91 | #define MFU_PRECOS 11 92 | 93 | #define MFU_VAR_NOP 0 94 | #define MFU_VAR_FP20 1 95 | #define MFU_VAR_FX10 2 96 | 97 | #define MFU_MUL_DST_BARYCENTRIC_WEIGHT 1 98 | #define MFU_MUL_DST_ROW_REG_0 4 99 | #define MFU_MUL_DST_ROW_REG_1 5 100 | #define MFU_MUL_DST_ROW_REG_2 6 101 | #define MFU_MUL_DST_ROW_REG_3 7 102 | 103 | #define MFU_MUL_SRC_ROW_REG_0 0 104 | #define MFU_MUL_SRC_ROW_REG_1 1 105 | #define MFU_MUL_SRC_ROW_REG_2 2 106 | #define MFU_MUL_SRC_ROW_REG_3 3 107 | #define MFU_MUL_SRC_SFU_RESULT 10 108 | #define MFU_MUL_SRC_BARYCENTRIC_COEF_0 11 109 | #define MFU_MUL_SRC_BARYCENTRIC_COEF_1 12 110 | #define MFU_MUL_SRC_CONST_1 13 111 | 112 | typedef union fragment_mfu_instruction { 113 | struct __attribute__((packed)) { 114 | unsigned var0_saturate:1; 115 | unsigned var0_opcode:2; 116 | unsigned var0_source:4; 117 | 118 | unsigned var1_saturate:1; 119 | unsigned var1_opcode:2; 120 | unsigned var1_source:4; 121 | 122 | unsigned var2_saturate:1; 123 | unsigned var2_opcode:2; 124 | unsigned var2_source:4; 125 | 126 | unsigned var3_saturate:1; 127 | unsigned var3_opcode:2; 128 | unsigned var3_source:4; 129 | 130 | unsigned __pad:4; 131 | 132 | unsigned mul0_src0:4; 133 | unsigned mul0_src1:4; 134 | unsigned mul0_dst:3; 135 | 136 | unsigned mul1_src0:4; 137 | unsigned mul1_src1:4; 138 | unsigned mul1_dst:3; 139 | 140 | unsigned opcode:4; 141 | unsigned reg:6; 142 | }; 143 | 144 | struct __attribute__((packed)) { 145 | uint32_t part0; 146 | uint32_t part1; 147 | }; 148 | } mfu_instr; 149 | 150 | #define ALU_CC_NOP 0 151 | #define ALU_CC_ZERO 1 152 | #define ALU_CC_GREATER_THAN_ZERO 2 153 | #define ALU_CC_ZERO_OR_GREATER 3 154 | 155 | #define ALU_OPCODE_MAD 0 156 | #define ALU_OPCODE_MIN 1 157 | #define ALU_OPCODE_MAX 2 158 | #define ALU_OPCODE_CSEL 3 159 | 160 | #define ALU_NO_SCALE 0 161 | #define ALU_SCALE_X2 1 162 | #define ALU_SCALE_X4 2 163 | #define ALU_SCALE_DIV2 3 164 | 165 | union fragment_alu_instruction { 166 | struct __attribute__((packed)) { 167 | unsigned rD_fixed10:1; 168 | unsigned rD_absolute_value:1; 169 | unsigned rD_enable:1; 170 | unsigned rD_minus_one:1; 171 | unsigned rD_sub_reg_select_high:1; 172 | unsigned rD_reg_select:1; 173 | 174 | unsigned rC_scale_by_two:1; 175 | unsigned rC_negate:1; 176 | unsigned rC_absolute_value:1; 177 | unsigned rC_fixed10:1; 178 | unsigned rC_minus_one:1; 179 | unsigned rC_sub_reg_select_high:1; 180 | unsigned rC_reg_select:7; 181 | 182 | unsigned rB_scale_by_two:1; 183 | unsigned rB_negate:1; 184 | unsigned rB_absolute_value:1; 185 | unsigned rB_fixed10:1; 186 | unsigned rB_minus_one:1; 187 | unsigned rB_sub_reg_select_high:1; 188 | unsigned rB_reg_select:7; 189 | 190 | unsigned rA_scale_by_two:1; 191 | unsigned rA_negate:1; 192 | unsigned rA_absolute_value:1; 193 | unsigned rA_fixed10:1; 194 | unsigned rA_minus_one:1; 195 | unsigned rA_sub_reg_select_high:1; 196 | unsigned rA_reg_select:7; 197 | 198 | unsigned write_low_sub_reg:1; 199 | unsigned write_high_sub_reg:1; 200 | unsigned dst_reg:7; 201 | unsigned condition_code:2; 202 | unsigned saturate_result:1; 203 | unsigned scale_result:2; 204 | 205 | unsigned addition_disable:1; 206 | unsigned accumulate_result_this:1; 207 | unsigned accumulate_result_other:1; 208 | unsigned opcode:2; 209 | }; 210 | 211 | struct __attribute__((packed)) { 212 | uint32_t part0; 213 | uint32_t part1; 214 | }; 215 | }; 216 | 217 | typedef union fragment_alu_instruction_x4 { 218 | struct __attribute__((packed)) { 219 | union fragment_alu_instruction a[4]; 220 | }; 221 | 222 | union { 223 | struct __attribute__((packed)) { 224 | uint64_t __pad1; 225 | uint64_t __pad2; 226 | uint64_t __pad3; 227 | unsigned __pad4:4; 228 | unsigned fx10_low:10; 229 | unsigned fx10_high:10; 230 | }; 231 | 232 | struct __attribute__((packed)) { 233 | uint64_t __pad5; 234 | uint64_t __pad6; 235 | uint64_t __pad7; 236 | unsigned __pad8:4; 237 | unsigned fp20:20; 238 | }; 239 | } imm0; 240 | 241 | union { 242 | struct __attribute__((packed)) { 243 | uint64_t __pad1; 244 | uint64_t __pad2; 245 | uint64_t __pad3; 246 | unsigned __pad4:24; 247 | unsigned fx10_low:10; 248 | unsigned fx10_high:10; 249 | }; 250 | 251 | struct __attribute__((packed)) { 252 | uint64_t __pad5; 253 | uint64_t __pad6; 254 | uint64_t __pad7; 255 | unsigned __pad8:24; 256 | unsigned fp20:20; 257 | }; 258 | } imm1; 259 | 260 | union { 261 | struct __attribute__((packed)) { 262 | uint64_t __pad1; 263 | uint64_t __pad2; 264 | uint64_t __pad3; 265 | uint32_t __pad4; 266 | unsigned __pad5:12; 267 | unsigned fx10_low:10; 268 | unsigned fx10_high:10; 269 | }; 270 | 271 | struct __attribute__((packed)) { 272 | uint64_t __pad6; 273 | uint64_t __pad7; 274 | uint64_t __pad8; 275 | uint32_t __pad9; 276 | unsigned __pad10:12; 277 | unsigned fp20:20; 278 | }; 279 | } imm2; 280 | 281 | struct __attribute__((packed)) { 282 | uint32_t part0; 283 | uint32_t part1; 284 | uint32_t part2; 285 | uint32_t part3; 286 | uint32_t part4; 287 | uint32_t part5; 288 | uint32_t part6; 289 | uint32_t part7; 290 | 291 | uint32_t complement; 292 | }; 293 | } alu_instr; 294 | 295 | typedef union fragment_pseq_instruction { 296 | uint32_t data; 297 | } pseq_instr; 298 | 299 | /* S T R LOD */ 300 | #define TEX_SRC_R0_R1_R2_R3 0 301 | #define TEX_SRC_R2_R3_R0_R1 1 302 | 303 | #define TEX_SAMPLE_DST_R0_R1 0 304 | #define TEX_SAMPLE_DST_R2_R3 1 305 | 306 | typedef union fragment_tex_instruction { 307 | struct __attribute__((packed)) { 308 | unsigned sampler_index:4; 309 | unsigned src_regs_select:1; 310 | unsigned sample_dst_regs_select:1; 311 | unsigned unk_6_9:4; 312 | unsigned enable:1; 313 | unsigned unk_11:1; 314 | unsigned enable_bias:1; 315 | unsigned unk_13_31:19; 316 | }; 317 | 318 | uint32_t data; 319 | } tex_instr; 320 | 321 | typedef union fragment_dw_instruction { 322 | struct __attribute__((packed)) { 323 | unsigned enable:1; 324 | unsigned unk_1:1; 325 | unsigned render_target_index:4; 326 | unsigned unk_6_9:4; 327 | unsigned stencil_write:1; 328 | unsigned unk_11_14:4; 329 | unsigned src_regs_select:1; 330 | unsigned unk_16_31:16; 331 | }; 332 | 333 | uint32_t data; 334 | } dw_instr; 335 | 336 | #endif // FRAGMENT_ASM_H 337 | -------------------------------------------------------------------------------- /src/asm/fragment_asm.l: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Dmitry Osipenko 3 | * Copyright (c) Erik Faye-Lund 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | %option caseless 25 | 26 | %{ 27 | #include 28 | #include "fragment_asm.h" 29 | #include "fragment_asm.tab.h" 30 | 31 | #define YY_NO_INPUT 32 | 33 | extern void yyerror(char *); 34 | 35 | int yywrap(void) 36 | { 37 | return 1; 38 | } 39 | %} 40 | 41 | %% 42 | [ \t]+ /* skip */; 43 | "/*"([^*]|(\*+[^*/]))*\*+\/ /* multi line comment */; 44 | "//".* /* single line comment */; 45 | [\n] yylineno++; 46 | 47 | ".asm" return T_ASM; 48 | ".constants" return T_CONSTANTS; 49 | ".uniforms" return T_UNIFORMS; 50 | [-]{0,1}[0-9]+\.[0-9]+ { 51 | fragment_asmlval.f = atof(yytext); 52 | return T_FLOAT; 53 | } 54 | 0x[0-9a-f]{1,16} { 55 | fragment_asmlval.u = strtoull(yytext + 2, NULL, 16); 56 | return T_HEX; 57 | } 58 | EXEC return T_EXEC; 59 | neg return T_NEG; 60 | abs return T_ABS; 61 | sat return T_SATURATE; 62 | [0-9]+ { 63 | fragment_asmlval.u = atoi(yytext); 64 | return T_NUMBER; 65 | } 66 | \"(.+?)\" { 67 | if (yyleng > sizeof(fragment_asmlval.s) - 1) 68 | return T_SYNTAX_ERROR; 69 | 70 | strcpy(fragment_asmlval.s, yytext + 1); 71 | fragment_asmlval.s[yyleng - 2] = '\0'; 72 | 73 | return T_STRING; 74 | } 75 | "," return ','; 76 | ";" return ';'; 77 | "." return '.'; 78 | "(" return '('; 79 | ")" return ')'; 80 | "[" return '['; 81 | "]" return ']'; 82 | "=" return '='; 83 | "-" return '-'; 84 | "*" return '*'; 85 | 86 | PSEQ: return T_PSEQ; 87 | MFU: return T_MFU; 88 | TEX: return T_TEX; 89 | ALU: return T_ALU; 90 | ALU[0-3]: { 91 | fragment_asmlval.u = atoi(yytext + 3); 92 | return T_ALUX; 93 | } 94 | ALU_COMPLEMENT: return T_ALU_COMPLEMENT; 95 | DW: return T_DW; 96 | 97 | NOP return T_OPCODE_NOP; 98 | 99 | RCP return T_MFU_OPCODE_RCP; 100 | RSQ return T_MFU_OPCODE_RSQ; 101 | LG2 return T_MFU_OPCODE_LG2; 102 | EX2 return T_MFU_OPCODE_EX2; 103 | SQRT return T_MFU_OPCODE_SQRT; 104 | SIN return T_MFU_OPCODE_SIN; 105 | COS return T_MFU_OPCODE_COS; 106 | FRC return T_MFU_OPCODE_FRC; 107 | PREEX2 return T_MFU_OPCODE_PREEX2; 108 | PRESIN return T_MFU_OPCODE_PRESIN; 109 | PRECOS return T_MFU_OPCODE_PRECOS; 110 | 111 | unk return T_MFU_UNK; 112 | 113 | t[0-9]{1,2} { 114 | fragment_asmlval.u = atoi(yytext + 1); 115 | return T_TRAM_ROW; 116 | } 117 | 118 | r[0-9]{1,2} { 119 | fragment_asmlval.u = atoi(yytext + 1); 120 | return T_ROW_REGISTER; 121 | } 122 | g[0-7] { 123 | fragment_asmlval.u = atoi(yytext + 1); 124 | return T_GLOBAL_REGISTER; 125 | } 126 | alu[0-3] { 127 | fragment_asmlval.u = atoi(yytext + 3); 128 | return T_ALU_RESULT_REGISTER; 129 | } 130 | imm[0-2] { 131 | fragment_asmlval.u = atoi(yytext + 3); 132 | return T_IMMEDIATE; 133 | } 134 | #[0-1] { 135 | fragment_asmlval.u = atoi(yytext + 1); 136 | return T_CONST_0_1; 137 | } 138 | u[0-9]{1,2} { 139 | fragment_asmlval.u = atoi(yytext + 1); 140 | return T_ALU_UNIFORM; 141 | } 142 | cr[0-9]{1,2} { 143 | fragment_asmlval.u = atoi(yytext + 2); 144 | return T_ALU_CONDITION_REGISTER; 145 | } 146 | lp return T_ALU_LOWP; 147 | posx return T_POSITION_X; 148 | posy return T_POSITION_Y; 149 | pface return T_POLIGON_FACE; 150 | kill return T_KILL; 151 | 152 | rB return T_ALU_rB; 153 | rC return T_ALU_rC; 154 | 155 | MAD return T_ALU_OPCODE_MAD; 156 | MUL return T_ALU_OPCODE_MUL; 157 | MIN return T_ALU_OPCODE_MIN; 158 | MAX return T_ALU_OPCODE_MAX; 159 | CSEL return T_ALU_OPCODE_CSEL; 160 | 161 | FX10 return T_FX10; 162 | FP20 return T_FP20; 163 | 164 | "l" return T_LOW; 165 | "h" return T_HIGH; 166 | 167 | this return T_ALU_ACCUM_THIS; 168 | other return T_ALU_ACCUM_OTHER; 169 | "eq" return T_ALU_CC_EQ; 170 | "gt" return T_ALU_CC_GT; 171 | "ge" return T_ALU_CC_GE; 172 | "x2" return T_ALU_X2; 173 | "x4" return T_ALU_X4; 174 | "/2" return T_ALU_DIV2; 175 | 176 | "alu_buffer_size" return T_ALU_BUFFER_SIZE; 177 | "pseq_to_dw_exec_nb" return T_PSEQ_DW_EXEC_NB; 178 | 179 | "ipl:" return T_MFU_FETCH_INTERPOLATE; 180 | "sfu:" return T_MFU_SFU; 181 | "mul0:" return T_MFU_MUL0; 182 | "mul1:" return T_MFU_MUL1; 183 | 184 | dst[0-9]{1,2} { 185 | fragment_asmlval.u = atoi(yytext + 3); 186 | return T_MFU_MUL_DST; 187 | } 188 | "bar" { 189 | fragment_asmlval.u = 1; 190 | return T_MFU_MUL_DST_BARYCENTRIC; 191 | } 192 | 193 | src[0-9]{1,2} { 194 | fragment_asmlval.u = atoi(yytext + 3); 195 | return T_MUL_SRC; 196 | } 197 | "sfu" return T_MFU_MUL_SRC_SFU_RESULT; 198 | "bar0" return T_MFU_MUL_SRC_BARYCENTRIC_0; 199 | "bar1" return T_MFU_MUL_SRC_BARYCENTRIC_1; 200 | 201 | tex[0-9]{1,2} { 202 | fragment_asmlval.u = atoi(yytext + 3); 203 | return T_TEX_SAMPLER_ID; 204 | } 205 | 206 | TEX return T_TEX_OPCODE; 207 | TXB return T_TXB_OPCODE; 208 | 209 | "store" return T_DW_STORE; 210 | 211 | rt[0-9]{1,2} { 212 | fragment_asmlval.u = atoi(yytext + 2); 213 | return T_DW_RENDER_TARGET; 214 | } 215 | 216 | "stencil" return T_DW_STENCIL; 217 | 218 | . return T_SYNTAX_ERROR; 219 | %% 220 | -------------------------------------------------------------------------------- /src/asm/linker_asm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Dmitry Osipenko 3 | * Copyright (c) Erik Faye-Lund 4 | * 5 | * This program is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License as published by the 7 | * Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 | * for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along 16 | * with this program; if not, see . 17 | */ 18 | 19 | #ifndef LINKER_ASM_H 20 | #define LINKER_ASM_H 21 | 22 | #include 23 | 24 | #define LINK_SWIZZLE_X 0 25 | #define LINK_SWIZZLE_Y 1 26 | #define LINK_SWIZZLE_Z 2 27 | #define LINK_SWIZZLE_W 3 28 | 29 | #define TRAM_DST_NONE 0 30 | #define TRAM_DST_FX10_LOW 1 31 | #define TRAM_DST_FX10_HIGH 2 32 | #define TRAM_DST_FP20 3 33 | 34 | typedef union shader_linking_instruction { 35 | struct __attribute__((packed)) { 36 | unsigned vec4_select:1; 37 | unsigned __pad1:2; 38 | unsigned vertex_export_index:4; 39 | unsigned __pad2:2; 40 | unsigned tram_row_index:6; 41 | unsigned __pad3:1; 42 | unsigned const_x_across_width:1; 43 | unsigned const_x_across_length:1; 44 | unsigned x_across_point:2; 45 | unsigned const_y_across_width:1; 46 | unsigned const_y_across_length:1; 47 | unsigned y_across_point:2; 48 | unsigned const_z_across_width:1; 49 | unsigned const_z_across_length:1; 50 | unsigned z_across_point:2; 51 | unsigned const_w_across_width:1; 52 | unsigned const_w_across_length:1; 53 | unsigned w_across_point:2; 54 | 55 | unsigned tram_dst_swizzle_x:2; 56 | unsigned tram_dst_type_x:2; 57 | unsigned tram_dst_swizzle_y:2; 58 | unsigned tram_dst_type_y:2; 59 | unsigned tram_dst_swizzle_z:2; 60 | unsigned tram_dst_type_z:2; 61 | unsigned tram_dst_swizzle_w:2; 62 | unsigned tram_dst_type_w:2; 63 | unsigned interpolation_disable_x:1; 64 | unsigned interpolation_disable_y:1; 65 | unsigned interpolation_disable_z:1; 66 | unsigned interpolation_disable_w:1; 67 | }; 68 | 69 | struct __attribute__((packed)) { 70 | uint32_t first; 71 | uint32_t latter; 72 | }; 73 | 74 | uint64_t data; 75 | } link_instr; 76 | 77 | #endif // LINKER_ASM_H 78 | -------------------------------------------------------------------------------- /src/asm/linker_asm.l: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Dmitry Osipenko 3 | * Copyright (c) Erik Faye-Lund 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | %option caseless 25 | 26 | %{ 27 | #include 28 | #include "linker_asm.h" 29 | #include "linker_asm.tab.h" 30 | 31 | #define YY_NO_INPUT 32 | 33 | extern void yyerror(char *); 34 | 35 | int yywrap(void) 36 | { 37 | return 1; 38 | } 39 | %} 40 | 41 | %% 42 | [ \t]+ /* skip */; 43 | "/*"([^*]|(\*+[^*/]))*\*+\/ /* multi line comment */; 44 | "//".* /* single line comment */; 45 | [\n] yylineno++; 46 | "." return '.'; 47 | "(" return '('; 48 | ")" return ')'; 49 | "," return ','; 50 | 51 | export[0-9]{1,2} { 52 | linker_asmlval.u = atoi(yytext + 6); 53 | return T_EXPORT; 54 | } 55 | tram[0-9]{1,2} { 56 | linker_asmlval.u = atoi(yytext + 4); 57 | return T_TRAM_ROW; 58 | } 59 | 60 | link return T_LINK; 61 | 62 | x return T_COMPONENT_X; 63 | y return T_COMPONENT_Y; 64 | z return T_COMPONENT_Z; 65 | w return T_COMPONENT_W; 66 | 67 | "nop" return T_NOP; 68 | 69 | "cw" return T_CONST_ACCROSS_WIDTH; 70 | "cl" return T_CONST_ACCROSS_LENGTH; 71 | "dis" return T_INTERPOLATION_DISABLE; 72 | 73 | "fx10.l" return T_FX10_LOW; 74 | "fx10.h" return T_FX10_HIGH; 75 | 76 | fp20 return T_FP20; 77 | 78 | . return T_SYNTAX_ERROR; 79 | %% 80 | -------------------------------------------------------------------------------- /src/asm/linker_asm.y: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Dmitry Osipenko 3 | * Copyright (c) Erik Faye-Lund 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | %{ 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "asm.h" 31 | 32 | #define PARSE_ERROR(txt) \ 33 | { \ 34 | yyerror(txt); \ 35 | YYABORT; \ 36 | } 37 | 38 | extern int linker_asmlex(void); 39 | extern int linker_asmlineno; 40 | 41 | void __attribute__((weak)) yyerror(char *err) 42 | { 43 | fprintf(stderr, "linker: line %d: %s\n", linker_asmlineno, err); 44 | } 45 | 46 | link_instr asm_linker_instructions[32]; 47 | unsigned asm_linker_instructions_nb; 48 | unsigned asm_linker_used_tram_rows_nb; 49 | 50 | %} 51 | 52 | %token T_EXPORT 53 | %token T_TRAM_ROW 54 | 55 | %token T_COMPONENT_X 56 | %token T_COMPONENT_Y 57 | %token T_COMPONENT_Z 58 | %token T_COMPONENT_W 59 | 60 | %token T_NOP 61 | 62 | %token T_CONST_ACCROSS_WIDTH 63 | %token T_CONST_ACCROSS_LENGTH 64 | %token T_INTERPOLATION_DISABLE 65 | 66 | %token T_FX10_LOW 67 | %token T_FX10_HIGH 68 | %token T_FP20 69 | 70 | %token T_LINK 71 | 72 | %token T_SYNTAX_ERROR 73 | 74 | %type TYPE 75 | %type COMPONENT 76 | %type Z 77 | 78 | %type COLUMN 79 | %type MODIFIERS 80 | %type MODIFIER 81 | 82 | %type instruction 83 | 84 | %union { 85 | unsigned u; 86 | 87 | struct { 88 | unsigned const_accross_width; 89 | unsigned const_accross_length; 90 | unsigned interpolation_disable; 91 | unsigned type; 92 | } component; 93 | 94 | link_instr instr; 95 | } 96 | 97 | %% 98 | 99 | instructions: instructions instruction 100 | { 101 | if (asm_linker_instructions_nb == 32) { 102 | PARSE_ERROR("Too many instructions, 32 maximum"); 103 | } 104 | 105 | asm_linker_instructions[asm_linker_instructions_nb++] = $2; 106 | } 107 | | 108 | { 109 | memset(asm_linker_instructions, 0, sizeof(asm_linker_instructions)); 110 | asm_linker_instructions_nb = 0; 111 | asm_linker_used_tram_rows_nb = 1; 112 | 113 | linker_asmlineno = 1; 114 | } 115 | ; 116 | 117 | instruction: 118 | T_LINK COLUMN ',' COLUMN ',' COLUMN ',' COLUMN ',' 119 | T_TRAM_ROW '.' COMPONENT COMPONENT COMPONENT COMPONENT ',' T_EXPORT Z 120 | { 121 | memset(&yyval.instr, 0, sizeof(yyval.instr)); 122 | 123 | if ($10 > 15) { 124 | PARSE_ERROR("Invalid TRAM row index, 15 maximum"); 125 | } 126 | 127 | if ($12 > 15) { 128 | PARSE_ERROR("Invalid vertex export index, 15 maximum"); 129 | } 130 | 131 | yyval.instr.vec4_select = $18; 132 | yyval.instr.vertex_export_index = $17; 133 | yyval.instr.tram_row_index = $10; 134 | 135 | yyval.instr.const_x_across_width = $2.const_accross_width; 136 | yyval.instr.const_x_across_length = $2.const_accross_length; 137 | yyval.instr.interpolation_disable_x = $2.interpolation_disable; 138 | yyval.instr.tram_dst_type_x = $2.type; 139 | yyval.instr.tram_dst_swizzle_x = $12; 140 | 141 | yyval.instr.const_y_across_width = $4.const_accross_width; 142 | yyval.instr.const_y_across_length = $4.const_accross_length; 143 | yyval.instr.interpolation_disable_y = $4.interpolation_disable; 144 | yyval.instr.tram_dst_type_y = $4.type; 145 | yyval.instr.tram_dst_swizzle_y = $13; 146 | 147 | yyval.instr.const_z_across_width = $6.const_accross_width; 148 | yyval.instr.const_z_across_length = $6.const_accross_length; 149 | yyval.instr.interpolation_disable_z = $6.interpolation_disable; 150 | yyval.instr.tram_dst_type_z = $6.type; 151 | yyval.instr.tram_dst_swizzle_z = $14; 152 | 153 | yyval.instr.const_w_across_width = $8.const_accross_width; 154 | yyval.instr.const_w_across_length = $8.const_accross_length; 155 | yyval.instr.interpolation_disable_w = $8.interpolation_disable; 156 | yyval.instr.tram_dst_type_w = $8.type; 157 | yyval.instr.tram_dst_swizzle_w = $15; 158 | 159 | if ($10 >= asm_linker_used_tram_rows_nb) { 160 | asm_linker_used_tram_rows_nb = $10 + 1; 161 | } 162 | } 163 | ; 164 | 165 | COMPONENT: 166 | T_COMPONENT_X 167 | { 168 | yyval.u = LINK_SWIZZLE_X; 169 | } 170 | | 171 | T_COMPONENT_Y 172 | { 173 | yyval.u = LINK_SWIZZLE_Y; 174 | } 175 | | 176 | T_COMPONENT_Z 177 | { 178 | yyval.u = LINK_SWIZZLE_Z; 179 | } 180 | | 181 | T_COMPONENT_W 182 | { 183 | yyval.u = LINK_SWIZZLE_W; 184 | } 185 | ; 186 | 187 | COLUMN: TYPE MODIFIERS 188 | { 189 | yyval.component = $2; 190 | yyval.component.type = $1; 191 | } 192 | ; 193 | 194 | TYPE: 195 | T_FX10_LOW 196 | { 197 | yyval.u = TRAM_DST_FX10_LOW; 198 | } 199 | | 200 | T_FX10_HIGH 201 | { 202 | yyval.u = TRAM_DST_FX10_HIGH; 203 | } 204 | | 205 | T_FP20 206 | { 207 | yyval.u = TRAM_DST_FP20; 208 | } 209 | | 210 | T_NOP 211 | { 212 | yyval.u = TRAM_DST_NONE; 213 | } 214 | ; 215 | 216 | MODIFIERS: MODIFIERS MODIFIER 217 | { 218 | yyval.component.const_accross_width |= $2.const_accross_width; 219 | yyval.component.const_accross_length |= $2.const_accross_length; 220 | yyval.component.interpolation_disable |= $2.interpolation_disable; 221 | } 222 | | 223 | { 224 | memset(&yyval.component, 0, sizeof(yyval.component)); 225 | } 226 | ; 227 | 228 | MODIFIER: 229 | '(' T_CONST_ACCROSS_WIDTH ')' 230 | { 231 | memset(&yyval.component, 0, sizeof(yyval.component)); 232 | yyval.component.const_accross_width = 1; 233 | } 234 | | 235 | '(' T_CONST_ACCROSS_LENGTH ')' 236 | { 237 | memset(&yyval.component, 0, sizeof(yyval.component)); 238 | yyval.component.const_accross_length = 1; 239 | } 240 | | 241 | '(' T_INTERPOLATION_DISABLE ')' 242 | { 243 | memset(&yyval.component, 0, sizeof(yyval.component)); 244 | yyval.component.interpolation_disable = 1; 245 | } 246 | ; 247 | 248 | Z: '(' T_COMPONENT_Z ')' 249 | { 250 | yyval.u = 1; 251 | } 252 | | 253 | { 254 | yyval.u = 0; 255 | } 256 | 257 | %% 258 | -------------------------------------------------------------------------------- /src/asm/vertex_asm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Dmitry Osipenko 3 | * Copyright (c) Erik Faye-Lund 4 | * 5 | * This program is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License as published by the 7 | * Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 | * for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along 16 | * with this program; if not, see . 17 | */ 18 | 19 | #ifndef VPE_VLIW_H 20 | #define VPE_VLIW_H 21 | 22 | #include 23 | 24 | #define REG_TYPE_UNDEFINED 0 25 | #define REG_TYPE_TEMPORARY 1 26 | #define REG_TYPE_ATTRIBUTE 2 27 | #define REG_TYPE_UNIFORM 3 28 | 29 | #define SWIZZLE_X 0 30 | #define SWIZZLE_Y 1 31 | #define SWIZZLE_Z 2 32 | #define SWIZZLE_W 3 33 | 34 | #define VECTOR_OPCODE_NOP 0 35 | #define VECTOR_OPCODE_MOV 1 36 | #define VECTOR_OPCODE_MUL 2 37 | #define VECTOR_OPCODE_ADD 3 38 | #define VECTOR_OPCODE_MAD 4 39 | #define VECTOR_OPCODE_DP3 5 40 | #define VECTOR_OPCODE_DPH 6 41 | #define VECTOR_OPCODE_DP4 7 42 | #define VECTOR_OPCODE_DST 8 43 | #define VECTOR_OPCODE_MIN 9 44 | #define VECTOR_OPCODE_MAX 10 45 | #define VECTOR_OPCODE_SLT 11 46 | #define VECTOR_OPCODE_SGE 12 47 | #define VECTOR_OPCODE_ARL 13 48 | #define VECTOR_OPCODE_FRC 14 49 | #define VECTOR_OPCODE_FLR 15 50 | #define VECTOR_OPCODE_SEQ 16 51 | #define VECTOR_OPCODE_SFL 17 52 | #define VECTOR_OPCODE_SGT 18 53 | #define VECTOR_OPCODE_SLE 19 54 | #define VECTOR_OPCODE_SNE 20 55 | #define VECTOR_OPCODE_STR 21 56 | #define VECTOR_OPCODE_SSG 22 57 | #define VECTOR_OPCODE_ARR 23 58 | #define VECTOR_OPCODE_ARA 24 59 | #define VECTOR_OPCODE_TXL 25 60 | #define VECTOR_OPCODE_PUSHA 26 61 | #define VECTOR_OPCODE_POPA 27 62 | 63 | #define SCALAR_OPCODE_NOP 0 64 | #define SCALAR_OPCODE_MOV 1 65 | #define SCALAR_OPCODE_RCP 2 66 | #define SCALAR_OPCODE_RCC 3 67 | #define SCALAR_OPCODE_RSQ 4 68 | #define SCALAR_OPCODE_EXP 5 69 | #define SCALAR_OPCODE_LOG 6 70 | #define SCALAR_OPCODE_LIT 7 71 | #define SCALAR_OPCODE_BRA 9 72 | #define SCALAR_OPCODE_CAL 11 73 | #define SCALAR_OPCODE_RET 12 74 | #define SCALAR_OPCODE_LG2 13 75 | #define SCALAR_OPCODE_EX2 14 76 | #define SCALAR_OPCODE_SIN 15 77 | #define SCALAR_OPCODE_COS 16 78 | #define SCALAR_OPCODE_PUSHA 19 79 | #define SCALAR_OPCODE_POPA 20 80 | 81 | typedef union vpe_instruction_u { 82 | struct __attribute__((packed)) { 83 | unsigned end_of_program:1; // 0 84 | unsigned constant_relative_addressing_enable:1; // 1 85 | unsigned export_write_index:5; // 2 .. 6 86 | unsigned scalar_rD_index:6; // 7 .. 12 87 | unsigned vector_op_write_w_enable:1; // 13 88 | unsigned vector_op_write_z_enable:1; // 14 89 | unsigned vector_op_write_y_enable:1; // 15 90 | unsigned vector_op_write_x_enable:1; // 16 91 | unsigned scalar_op_write_w_enable:1; // 17 92 | unsigned scalar_op_write_z_enable:1; // 18 93 | unsigned scalar_op_write_y_enable:1; // 19 94 | unsigned scalar_op_write_x_enable:1; // 20 95 | unsigned rC_type:2; // 21 .. 22 96 | unsigned rC_index:6; // 23 .. 28 97 | unsigned rC_swizzle_w:2; // 29 .. 30 98 | unsigned rC_swizzle_z:2; // 31 .. 32 99 | unsigned rC_swizzle_y:2; // 33 .. 34 100 | unsigned rC_swizzle_x:2; // 35 .. 36 101 | unsigned rC_negate:1; // 37 102 | unsigned rB_type:2; // 38 .. 39 103 | unsigned rB_index:6; // 40 .. 45 104 | unsigned rB_swizzle_w:2; // 46 .. 47 105 | unsigned rB_swizzle_z:2; // 48 .. 49 106 | unsigned rB_swizzle_y:2; // 50 .. 51 107 | unsigned rB_swizzle_x:2; // 52 .. 53 108 | unsigned rB_negate:1; // 54 109 | unsigned rA_type:2; // 55 .. 56 110 | unsigned rA_index:6; // 57 .. 62 111 | unsigned rA_swizzle_w:2; // 63 .. 64 112 | unsigned rA_swizzle_z:2; // 65 .. 66 113 | unsigned rA_swizzle_y:2; // 67 .. 68 114 | unsigned rA_swizzle_x:2; // 69 .. 70 115 | unsigned rA_negate:1; // 71 116 | unsigned attribute_fetch_index:4; // 72 .. 75 117 | unsigned uniform_fetch_index:10; // 76 .. 85 118 | unsigned vector_opcode:5; // 86 .. 90 119 | unsigned scalar_opcode:5; // 91 .. 95 120 | unsigned address_register_select:2; // 96 .. 97 121 | unsigned predicate_swizzle_w:2; // 98 .. 99 122 | unsigned predicate_swizzle_z:2; // 100 .. 101 123 | unsigned predicate_swizzle_y:2; // 102 .. 103 124 | unsigned predicate_swizzle_x:2; // 104 .. 105 125 | unsigned predicate_lt:1; // 106 126 | unsigned predicate_eq:1; // 107 127 | unsigned predicate_gt:1; // 108 128 | unsigned condition_check:1; // 109 129 | unsigned condition_set:1; // 110 130 | unsigned vector_rD_index:6; // 111 .. 116 131 | unsigned rA_absolute_value:1; // 117 132 | unsigned rB_absolute_value:1; // 118 133 | unsigned rC_absolute_value:1; // 119 134 | unsigned bit120:1; // 120 135 | unsigned condition_register_index:1; // 121 136 | unsigned saturate_result:1; // 122 137 | unsigned attribute_relative_addressing_enable:1;// 123 138 | unsigned export_relative_addressing_enable:1; // 124 139 | unsigned condition_flags_write_enable:1; // 125 140 | unsigned export_vector_write_enable:1; // 126 141 | unsigned bit127:1; // 127 142 | }; 143 | 144 | struct __attribute__((packed)) { 145 | unsigned __pad:29; // 0 .. 28 146 | unsigned iaddr:8; // 29 .. 36 147 | }; 148 | 149 | struct __attribute__((packed)) { 150 | uint32_t part0; 151 | uint32_t part1; 152 | uint32_t part2; 153 | uint32_t part3; 154 | }; 155 | } vpe_instr128; 156 | 157 | #endif // VPE_VLIW_H 158 | -------------------------------------------------------------------------------- /src/asm/vertex_asm.l: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Dmitry Osipenko 3 | * Copyright (c) Erik Faye-Lund 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | %option caseless 25 | 26 | %{ 27 | #include 28 | #include "vertex_asm.tab.h" 29 | 30 | #define YY_NO_INPUT 31 | 32 | extern void yyerror(char *); 33 | 34 | int yywrap(void) 35 | { 36 | return 1; 37 | } 38 | %} 39 | 40 | %% 41 | [ \t]+ /* skip */; 42 | "/*"([^*]|(\*+[^*/]))*\*+\/ /* multi line comment */; 43 | "//".* /* single line comment */; 44 | [\n] yylineno++; 45 | 46 | ".asm" return T_ASM; 47 | ".exports" return T_EXPORTS; 48 | ".constants" return T_CONSTANTS; 49 | ".attributes" return T_ATTRIBUTES; 50 | ".uniforms" return T_UNIFORMS; 51 | [-]{0,1}[0-9]+"."[0-9]+ { 52 | vertex_asmlval.f = atof(yytext); 53 | return T_FLOAT; 54 | } 55 | 0x[0-9a-f]{1,8} { 56 | vertex_asmlval.u = strtoul(yytext + 2, NULL, 16); 57 | return T_HEX; 58 | } 59 | EXEC return T_EXEC; 60 | EXEC_END return T_EXEC_END; 61 | A0 return T_ADDRESS_REG; 62 | r[0-9]{1,2} { 63 | vertex_asmlval.u = atoi(yytext + 1); 64 | return T_REGISTER; 65 | } 66 | a return T_ATTRIBUTE; 67 | c return T_CONSTANT; 68 | u { 69 | vertex_asmlval.u = atoi(yytext + 1); 70 | return T_UNDEFINED; 71 | } 72 | - return T_NEG; 73 | abs return T_ABS; 74 | export return T_EXPORT; 75 | vector return T_VECTOR; 76 | scalar return T_SCALAR; 77 | saturate return T_SATURATE; 78 | [0-9]+ { 79 | vertex_asmlval.u = atoi(yytext); 80 | return T_NUMBER; 81 | } 82 | p return T_PREDICATE; 83 | cs return T_SET_CONDITION; 84 | eq return T_CHECK_CONDITION_EQ; 85 | lt return T_CHECK_CONDITION_LT; 86 | gt return T_CHECK_CONDITION_GT; 87 | cc return T_CHECK_CONDITION_CHECK; 88 | cwr return T_CHECK_CONDITION_WR; 89 | cr return T_CONDITION_REGISTER; 90 | x { 91 | vertex_asmlval.c = yytext[0]; 92 | return T_COMPONENT_X; 93 | } 94 | y { 95 | vertex_asmlval.c = yytext[0]; 96 | return T_COMPONENT_Y; 97 | } 98 | z { 99 | vertex_asmlval.c = yytext[0]; 100 | return T_COMPONENT_Z; 101 | } 102 | w { 103 | vertex_asmlval.c = yytext[0]; 104 | return T_COMPONENT_W; 105 | } 106 | "*" { 107 | vertex_asmlval.c = yytext[0]; 108 | return T_COMPONENT_DISABLED; 109 | } 110 | \"(.+?)\" { 111 | if (yyleng > sizeof(vertex_asmlval.s) - 1) 112 | return T_SYNTAX_ERROR; 113 | 114 | strcpy(vertex_asmlval.s, yytext + 1); 115 | vertex_asmlval.s[yyleng - 2] = '\0'; 116 | 117 | return T_STRING; 118 | } 119 | "," return ','; 120 | ";" return ';'; 121 | "." return '.'; 122 | "(" return '('; 123 | ")" return ')'; 124 | "[" return '['; 125 | "]" return ']'; 126 | "=" return '='; 127 | "+" return '+'; 128 | 129 | NOPv return T_VECTOR_OPCODE_NOP; 130 | MOVv return T_VECTOR_OPCODE_MOV; 131 | MULv return T_VECTOR_OPCODE_MUL; 132 | ADDv return T_VECTOR_OPCODE_ADD; 133 | MADv return T_VECTOR_OPCODE_MAD; 134 | DP3v return T_VECTOR_OPCODE_DP3; 135 | DPHv return T_VECTOR_OPCODE_DPH; 136 | DP4v return T_VECTOR_OPCODE_DP4; 137 | DSTv return T_VECTOR_OPCODE_DST; 138 | MINv return T_VECTOR_OPCODE_MIN; 139 | MAXv return T_VECTOR_OPCODE_MAX; 140 | SLTv return T_VECTOR_OPCODE_SLT; 141 | SGEv return T_VECTOR_OPCODE_SGE; 142 | ARLv return T_VECTOR_OPCODE_ARL; 143 | FRCv return T_VECTOR_OPCODE_FRC; 144 | FLRv return T_VECTOR_OPCODE_FLR; 145 | SEQv return T_VECTOR_OPCODE_SEQ; 146 | SFLv return T_VECTOR_OPCODE_SFL; 147 | SGTv return T_VECTOR_OPCODE_SGT; 148 | SLEv return T_VECTOR_OPCODE_SLE; 149 | SNEv return T_VECTOR_OPCODE_SNE; 150 | STRv return T_VECTOR_OPCODE_STR; 151 | SSGv return T_VECTOR_OPCODE_SSG; 152 | ARRv return T_VECTOR_OPCODE_ARR; 153 | ARAv return T_VECTOR_OPCODE_ARA; 154 | TXLv return T_VECTOR_OPCODE_TXL; 155 | PUSHAv return T_VECTOR_OPCODE_PUSHA; 156 | POPAv return T_VECTOR_OPCODE_POPA; 157 | 158 | NOPs return T_SCALAR_OPCODE_NOP; 159 | MOVs return T_SCALAR_OPCODE_MOV; 160 | RCPs return T_SCALAR_OPCODE_RCP; 161 | RCCs return T_SCALAR_OPCODE_RCC; 162 | RSQs return T_SCALAR_OPCODE_RSQ; 163 | EXPs return T_SCALAR_OPCODE_EXP; 164 | LOGs return T_SCALAR_OPCODE_LOG; 165 | LITs return T_SCALAR_OPCODE_LIT; 166 | BRAs return T_SCALAR_OPCODE_BRA; 167 | CALs return T_SCALAR_OPCODE_CAL; 168 | RETs return T_SCALAR_OPCODE_RET; 169 | LG2s return T_SCALAR_OPCODE_LG2; 170 | EX2s return T_SCALAR_OPCODE_EX2; 171 | SINs return T_SCALAR_OPCODE_SIN; 172 | COSs return T_SCALAR_OPCODE_COS; 173 | PUSHAs return T_SCALAR_OPCODE_PUSHA; 174 | POPAs return T_SCALAR_OPCODE_POPA; 175 | 176 | bit120 return T_BIT120; 177 | 178 | . return T_SYNTAX_ERROR; 179 | %% 180 | -------------------------------------------------------------------------------- /src/atomic.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | * 23 | * Authors: 24 | * Chris Wilson 25 | * 26 | */ 27 | 28 | #ifndef _ATOMICS_H 29 | #define _ATOMICS_H 30 | 31 | #define atomic_read(x) ((x)->atomic) 32 | #define atomic_set(x, val) ((x)->atomic = (val)) 33 | #define atomic_inc(x) ((void) __sync_fetch_and_add (&(x)->atomic, 1)) 34 | #define atomic_inc_return(x) (__sync_add_and_fetch (&(x)->atomic, 1)) 35 | #define atomic_dec_and_test(x) (__sync_add_and_fetch (&(x)->atomic, -1) == 0) 36 | #define atomic_add(x, v) ((void) __sync_add_and_fetch(&(x)->atomic, (v))) 37 | #define atomic_dec(x, v) ((void) __sync_sub_and_fetch(&(x)->atomic, (v))) 38 | #define atomic_cmpxchg(x, oldv, newv) __sync_val_compare_and_swap (&(x)->atomic, oldv, newv) 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /src/bitstream.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Dmitry Osipenko 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but WITHOUT 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 | * for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, see . 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "bitstream.h" 25 | 26 | // #define BITSTREAM_DEBUG 27 | 28 | #ifdef BITSTREAM_DEBUG 29 | #define BITSTREAM_DPRINT(f, ...) printf(f, ## __VA_ARGS__) 30 | #else 31 | #define BITSTREAM_DPRINT(...) {} 32 | #endif 33 | 34 | #define BITSTREAM_IPRINT(f, ...) printf(f, ## __VA_ARGS__) 35 | 36 | #define BITSTREAM_ERR(f, ...) \ 37 | { \ 38 | fprintf(stderr, "%s:%d:\n", __FILE__, __LINE__); \ 39 | fprintf(stderr, "bitstream_reader: " f, ## __VA_ARGS__); \ 40 | reader->error = 1; \ 41 | exit(EXIT_FAILURE); \ 42 | } 43 | 44 | #if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ 45 | #error "Unsupported host endianness" 46 | #endif 47 | 48 | #ifndef clz 49 | #define clz __builtin_clz 50 | #endif 51 | 52 | void bitstream_reader_selftest(void) 53 | { 54 | uint8_t test_data[] = { 0x0F, 0xFF, 0x03, 0x10, 0x90, 0x7F }; 55 | bitstream_reader reader; 56 | uint64_t test = htobe64(0xAAAAAAAAAAAAAAAA); 57 | uint32_t val; 58 | int i; 59 | 60 | bitstream_init(&reader, test_data, sizeof(test_data)); 61 | 62 | val = bitstream_read_ue(&reader); 63 | 64 | printf("codenum = %u\n", val); 65 | 66 | assert(val == 30); 67 | 68 | val = bitstream_read_ue(&reader); 69 | 70 | printf("codenum = %u\n", val); 71 | 72 | assert(val == 0); 73 | 74 | bitstream_read_u(&reader, 6); 75 | 76 | val = bitstream_read_ue(&reader); 77 | 78 | printf("codenum = %u\n", val); 79 | 80 | assert(val == 97); 81 | 82 | reader.data_offset = 3; 83 | reader.bit_shift = 4; 84 | 85 | val = bitstream_read_ue(&reader); 86 | 87 | printf("codenum = %u\n", val); 88 | 89 | assert(val == 17); 90 | 91 | val = bitstream_read_ue(&reader); 92 | 93 | printf("codenum = %u\n", val); 94 | 95 | assert(val == 30); 96 | 97 | bitstream_init(&reader, &test, sizeof(test)); 98 | 99 | assert(bitstream_read_u_no_inc(&reader, 16) == 0xAAAA); 100 | 101 | for (i = 0; i < 64; i++) { 102 | unsigned cmp = ((be64toh(test) >> (63 - i))) & 1; 103 | printf("i = %d cmp 0x%X\n", i, cmp); 104 | assert(bitstream_read_u(&reader, 1) == cmp); 105 | } 106 | 107 | bitstream_init(&reader, &test, sizeof(test)); 108 | 109 | test = htobe64(0x0123456789ABCDEF); 110 | 111 | for (i = 0; i < 12; i++) { 112 | unsigned cmp = ((be64toh(test) >> (64 - 5 * (i + 1)))) & 31; 113 | printf("i = %d cmp 0x%X\n", i, cmp); 114 | assert(bitstream_read_u(&reader, 5) == cmp); 115 | } 116 | 117 | bitstream_init(&reader, &test, sizeof(test)); 118 | 119 | for (i = 0; i < 16; i++) { 120 | unsigned cmp = ((be64toh(test) >> (64 - 4 * (i + 1)))) & 15; 121 | printf("i = %d cmp 0x%X\n", i, cmp); 122 | assert(bitstream_read_u(&reader, 4) == cmp); 123 | } 124 | 125 | bitstream_init(&reader, &test, sizeof(test)); 126 | reader.bit_shift = 1; 127 | 128 | for (i = 0; i < 15; i++) { 129 | unsigned cmp = (((be64toh(test) << 1) >> (64 - 4 * (i + 1)))) & 15; 130 | printf("i = %d cmp 0x%X\n", i, cmp); 131 | assert(bitstream_read_u(&reader, 4) == cmp); 132 | } 133 | 134 | printf("%s passed\n", __func__); 135 | } 136 | 137 | void bitstream_init(bitstream_reader *reader, void *data, uint32_t size) 138 | { 139 | reader->data_ptr = data; 140 | reader->bitstream_end = size; 141 | reader->data_offset = 0; 142 | reader->bit_shift = 0; 143 | reader->rbsp_mode = 1; 144 | reader->error = 0; 145 | } 146 | 147 | static int check_range(bitstream_reader *reader, uint32_t offset) 148 | { 149 | if (reader->data_offset + offset >= reader->bitstream_end) { 150 | BITSTREAM_IPRINT("Reached data stream end\n"); 151 | exit(0); 152 | } 153 | 154 | return 0; 155 | } 156 | 157 | inline void bitstream_reader_inc_offset(bitstream_reader *reader, uint32_t delta) 158 | { 159 | reader->data_offset += delta; 160 | } 161 | 162 | uint8_t bitstream_read_rbsp_align(bitstream_reader *reader) 163 | { 164 | if (reader->bit_shift == 0) { 165 | return 0; 166 | } 167 | 168 | return bitstream_read_u(reader, 8 - reader->bit_shift); 169 | } 170 | 171 | uint32_t bitstream_read_next_word(bitstream_reader *reader) 172 | { 173 | uint32_t offset = reader->data_offset; 174 | int align = (reader->bit_shift == 0) ? 0 : 1; 175 | 176 | if (check_range(reader, align + 3) != 0) { 177 | return 0; 178 | } 179 | 180 | return *((uint32_t *)(reader->data_ptr + offset + align)); 181 | } 182 | 183 | static uint8_t bitstream_read_u8_no_inc(bitstream_reader *reader); 184 | 185 | static uint8_t emulation_escape(bitstream_reader *reader, uint32_t offset, 186 | uint8_t data, int inc_offset, int *escaped) 187 | { 188 | uint32_t seq; 189 | 190 | if (data != 0x03 || !reader->rbsp_mode) { 191 | return data; 192 | } 193 | 194 | if (offset < 2 || offset == reader->bitstream_end) { 195 | return data; 196 | } 197 | 198 | seq = *((uint32_t *)(reader->data_ptr + offset - 2)); 199 | seq = be32toh(seq); 200 | 201 | switch (seq) { 202 | case 0x00000300: 203 | case 0x00000301: 204 | case 0x00000302: 205 | case 0x00000303: 206 | BITSTREAM_DPRINT("0x%08X escaped!\n", seq); 207 | if (inc_offset) { 208 | reader->data_offset++; 209 | } 210 | if (escaped != NULL) { 211 | *escaped = 1; 212 | } 213 | return seq & 0xFF; 214 | default: 215 | break; 216 | } 217 | 218 | return data; 219 | } 220 | 221 | static uint8_t bitstream_read_u8_no_inc(bitstream_reader *reader) 222 | { 223 | uint8_t ret; 224 | 225 | if (reader->error) { 226 | return 0; 227 | } 228 | 229 | if (check_range(reader, 0) != 0) { 230 | return 0; 231 | } 232 | 233 | ret = *(reader->data_ptr + reader->data_offset); 234 | 235 | return emulation_escape(reader, reader->data_offset, ret, 1, NULL); 236 | } 237 | 238 | static uint32_t bitstream_read_bits(bitstream_reader *reader, uint8_t bits_nb, 239 | int inc_offset) 240 | { 241 | const uint8_t bit_shift = reader->bit_shift; 242 | const uint8_t *data_ptr = reader->data_ptr; 243 | uint32_t data_offset = reader->data_offset; 244 | const uint64_t mask = (1ll << bits_nb) - 1; 245 | uint8_t bytes_to_read = (bits_nb + bit_shift - 1) >> 3; 246 | const uint8_t rshift = 8 * (bytes_to_read + 1) - (bit_shift + bits_nb); 247 | int escape_inc_offset = 0; 248 | uint64_t ret = 0; 249 | 250 | assert(bits_nb != 0); 251 | assert(bits_nb <= 32); 252 | 253 | if (inc_offset && check_range(reader, bytes_to_read) != 0) { 254 | return 0; 255 | } 256 | 257 | BITSTREAM_DPRINT("===\n"); 258 | BITSTREAM_DPRINT("bit_shift %u bits_nb %u bytes_to_read %u\n", 259 | bit_shift, bits_nb, bytes_to_read); 260 | 261 | do { 262 | uint8_t byte = *(data_ptr + data_offset); 263 | uint8_t lshift = bytes_to_read << 3; 264 | int escaped = 0; 265 | 266 | byte = emulation_escape(reader, data_offset++, byte, 267 | !escape_inc_offset || inc_offset, 268 | &escaped); 269 | 270 | if (escaped) { 271 | data_offset++; 272 | } 273 | 274 | escape_inc_offset = 1; 275 | 276 | ret |= (uint64_t) byte << lshift; 277 | 278 | BITSTREAM_DPRINT("0x%02X lshift %u 0x%lX\n", 279 | byte, lshift, ret); 280 | } while (bytes_to_read--); 281 | 282 | BITSTREAM_DPRINT("ret 0x%lX\n", ret); 283 | BITSTREAM_DPRINT("rshift %u\n", rshift); 284 | BITSTREAM_DPRINT("mask 0x%lX\n", mask); 285 | 286 | ret >>= rshift; 287 | ret &= mask; 288 | 289 | BITSTREAM_DPRINT("ret 0x%lX\n", ret); 290 | BITSTREAM_DPRINT("===\n\n"); 291 | 292 | return ret; 293 | } 294 | 295 | static void bitstream_reader_inc_offset_b(bitstream_reader *reader, 296 | uint8_t bits_nb) 297 | { 298 | uint8_t bit_shift = reader->bit_shift; 299 | 300 | reader->data_offset += (bit_shift + bits_nb) >> 3; 301 | reader->bit_shift = (bit_shift + bits_nb) % 8; 302 | } 303 | 304 | uint32_t bitstream_read_u_no_inc(bitstream_reader *reader, uint8_t bits_nb) 305 | { 306 | uint32_t ret; 307 | 308 | if (reader->bit_shift == 0 && bits_nb == 8) { 309 | ret = bitstream_read_u8_no_inc(reader); 310 | } else { 311 | ret = bitstream_read_bits(reader, bits_nb, 0); 312 | } 313 | 314 | return ret; 315 | } 316 | 317 | uint32_t bitstream_read_u(bitstream_reader *reader, uint8_t bits_nb) 318 | { 319 | uint32_t ret; 320 | 321 | if (reader->bit_shift == 0 && bits_nb == 8) { 322 | ret = bitstream_read_u8_no_inc(reader); 323 | bitstream_reader_inc_offset(reader, 1); 324 | } else { 325 | ret = bitstream_read_bits(reader, bits_nb, 1); 326 | bitstream_reader_inc_offset_b(reader, bits_nb); 327 | } 328 | 329 | return ret; 330 | } 331 | 332 | unsigned bitstream_skip_leading_zeros(bitstream_reader *reader) 333 | { 334 | const uint8_t bit_shift = reader->bit_shift; 335 | uint8_t leading_zeros_align = 0; 336 | uint8_t leading_zeros = 0; 337 | 338 | if (bit_shift != 0 && !reader->error) { 339 | uint8_t byte = bitstream_read_bits(reader, 8 - bit_shift, 0); 340 | 341 | if (byte != 0) { 342 | leading_zeros_align = clz(byte) - 24 - bit_shift; 343 | } else { 344 | leading_zeros_align = 8 - bit_shift; 345 | } 346 | 347 | BITSTREAM_DPRINT("byte 0x%X leading_zeros_align %u\n", 348 | byte, leading_zeros_align); 349 | 350 | if (byte != 0) { 351 | reader->bit_shift += leading_zeros_align; 352 | 353 | bitstream_reader_inc_offset_b(reader, 1); 354 | 355 | return leading_zeros_align; 356 | } 357 | 358 | bitstream_reader_inc_offset_b(reader, leading_zeros_align); 359 | } 360 | 361 | for (;;) { 362 | uint8_t byte = bitstream_read_u8_no_inc(reader); 363 | 364 | leading_zeros += byte ? clz(byte) - 24 : 8; 365 | 366 | BITSTREAM_DPRINT("byte 0x%X leading_zeros %u\n", 367 | byte, leading_zeros); 368 | 369 | if (byte != 0) { 370 | reader->bit_shift += leading_zeros % 8; 371 | 372 | bitstream_reader_inc_offset_b(reader, 1); 373 | 374 | leading_zeros += leading_zeros_align; 375 | 376 | BITSTREAM_DPRINT("leading_zeros %u\n", leading_zeros); 377 | 378 | return leading_zeros; 379 | } 380 | 381 | bitstream_reader_inc_offset(reader, 1); 382 | } 383 | 384 | return 0; 385 | } 386 | 387 | static uint32_t exp_golomb_codenum(unsigned exp, uint32_t val) 388 | { 389 | uint32_t ret = (1l << exp) - 1 + val; 390 | 391 | BITSTREAM_DPRINT("exp %u val %u ret %u\n", exp, val, ret); 392 | 393 | return ret; 394 | } 395 | 396 | uint32_t bitstream_read_ue(bitstream_reader *reader) 397 | { 398 | unsigned leading_zeros; 399 | uint32_t val = 0; 400 | 401 | leading_zeros = bitstream_skip_leading_zeros(reader); 402 | 403 | if (leading_zeros > 31) { 404 | BITSTREAM_ERR("Exp-golomb parse error leading_zeros = %d\n", 405 | leading_zeros); 406 | } 407 | 408 | if (leading_zeros) { 409 | val = bitstream_read_u(reader, leading_zeros); 410 | } 411 | 412 | return exp_golomb_codenum(leading_zeros, val); 413 | } 414 | 415 | int32_t bitstream_read_se(bitstream_reader *reader) 416 | { 417 | uint32_t ue = bitstream_read_ue(reader); 418 | uint32_t val = (ue > 1) ? (ue >> 1) + (ue & 1) : ue; 419 | int positive = ue & 1; 420 | 421 | return positive ? val : -val; 422 | } 423 | -------------------------------------------------------------------------------- /src/bitstream.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Dmitry Osipenko 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but WITHOUT 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 | * for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, see . 16 | */ 17 | 18 | #ifndef BITSTREAM_H 19 | #define BITSTREAM_H 20 | 21 | #include 22 | #include 23 | 24 | typedef struct bitstream_reader { 25 | const uint8_t *data_ptr; 26 | uint32_t bitstream_end; 27 | uint32_t data_offset; 28 | uint32_t NAL_offset; 29 | uint8_t bit_shift; 30 | uint8_t rbsp_mode; 31 | uint8_t error; 32 | } bitstream_reader; 33 | 34 | void bitstream_reader_selftest(void); 35 | void bitstream_init(bitstream_reader *reader, void *data, uint32_t size); 36 | void bitstream_reader_inc_offset(bitstream_reader *reader, uint32_t delta); 37 | uint32_t bitstream_read_u(bitstream_reader *reader, uint8_t bits_nb); 38 | uint32_t bitstream_read_ue(bitstream_reader *reader); 39 | int32_t bitstream_read_se(bitstream_reader *reader); 40 | uint32_t bitstream_read_next_word(bitstream_reader *reader); 41 | uint8_t bitstream_read_rbsp_align(bitstream_reader *reader); 42 | unsigned bitstream_skip_leading_zeros(bitstream_reader *reader); 43 | uint32_t bitstream_read_u_no_inc(bitstream_reader *reader, uint8_t bits_nb); 44 | #define bitstream_read_ae(reader) 0 45 | 46 | #endif // BITSTREAM_H 47 | -------------------------------------------------------------------------------- /src/dmabuf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * NVIDIA TEGRA 2 VDPAU backend driver 3 | * 4 | * Copyright (c) 2016 Dmitry Osipenko 5 | * 6 | * This program is free software; you can redistribute it and/or modify it 7 | * under the terms of the GNU General Public License as published by the 8 | * Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License along 17 | * with this program; if not, see . 18 | */ 19 | 20 | #include "vdpau_tegra.h" 21 | 22 | int sync_dmabuf_write_start(int dmabuf_fd) 23 | { 24 | struct dma_buf_sync sync = { 25 | .flags = DMA_BUF_SYNC_WRITE | DMA_BUF_SYNC_START, 26 | }; 27 | 28 | return ioctl(dmabuf_fd, DMA_BUF_IOCTL_SYNC, &sync); 29 | } 30 | 31 | int sync_dmabuf_write_end(int dmabuf_fd) 32 | { 33 | struct dma_buf_sync sync = { 34 | .flags = DMA_BUF_SYNC_WRITE | DMA_BUF_SYNC_END, 35 | }; 36 | 37 | return ioctl(dmabuf_fd, DMA_BUF_IOCTL_SYNC, &sync); 38 | } 39 | 40 | int sync_dmabuf_read_start(int dmabuf_fd) 41 | { 42 | struct dma_buf_sync sync = { 43 | .flags = DMA_BUF_SYNC_READ | DMA_BUF_SYNC_START, 44 | }; 45 | 46 | return ioctl(dmabuf_fd, DMA_BUF_IOCTL_SYNC, &sync); 47 | } 48 | 49 | int sync_dmabuf_read_end(int dmabuf_fd) 50 | { 51 | struct dma_buf_sync sync = { 52 | .flags = DMA_BUF_SYNC_READ | DMA_BUF_SYNC_END, 53 | }; 54 | 55 | return ioctl(dmabuf_fd, DMA_BUF_IOCTL_SYNC, &sync); 56 | } 57 | -------------------------------------------------------------------------------- /src/dri2.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2007,2008 Red Hat, Inc. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Soft- 6 | * ware"), to deal in the Software without restriction, including without 7 | * limitation the rights to use, copy, modify, merge, publish, distribute, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, provided that the above copyright 10 | * notice(s) and this permission notice appear in all copies of the Soft- 11 | * ware and that both the above copyright notice(s) and this permission 12 | * notice appear in supporting documentation. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- 16 | * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY 17 | * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN 18 | * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE- 19 | * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 20 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 21 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR- 22 | * MANCE OF THIS SOFTWARE. 23 | * 24 | * Except as contained in this notice, the name of a copyright holder shall 25 | * not be used in advertising or otherwise to promote the sale, use or 26 | * other dealings in this Software without prior written authorization of 27 | * the copyright holder. 28 | * 29 | * Authors: 30 | * Kristian Høgsberg (krh@redhat.com) 31 | */ 32 | 33 | #ifndef _DRI2_H_ 34 | #define _DRI2_H_ 35 | 36 | typedef struct 37 | { 38 | unsigned int attachment; 39 | unsigned int names[3]; /* unused entries set to zero.. non-planar formats only use names[0] */ 40 | unsigned int pitch[3]; /* unused entries set to zero.. non-planar formats only use pitch[0] */ 41 | unsigned int cpp; 42 | unsigned int flags; 43 | } DRI2Buffer; 44 | 45 | typedef struct 46 | { 47 | Bool (*WireToEvent)(Display *dpy, XExtDisplayInfo *info, XEvent *event, xEvent *wire); 48 | Status (*EventToWire)(Display *dpy, XExtDisplayInfo *info, XEvent *event, xEvent *wire); 49 | int (*Error)(Display *dpy, xError *err, XExtCodes *codes, int *ret_code); 50 | } DRI2EventOps; 51 | 52 | /* Call this once per display to register event handling code.. if needed */ 53 | extern Bool 54 | DRI2InitDisplay(Display * display, const DRI2EventOps * ops); 55 | 56 | extern Bool 57 | DRI2QueryExtension(Display * display, int *eventBase, int *errorBase); 58 | 59 | extern Bool 60 | DRI2QueryVersion(Display * display, int *major, int *minor); 61 | 62 | extern Bool 63 | DRI2Connect(Display * dpy, XID window, 64 | int driverType, char **driverName, char **deviceName); 65 | 66 | extern Bool 67 | DRI2Authenticate(Display * display, XID window, drm_magic_t magic); 68 | 69 | extern void 70 | DRI2CreateDrawable(Display * display, XID drawable); 71 | 72 | extern void 73 | DRI2DestroyDrawable(Display * display, XID handle); 74 | 75 | extern DRI2Buffer* 76 | DRI2GetBuffers(Display * dpy, XID drawable, 77 | int *width, int *height, 78 | unsigned int *attachments, int count, 79 | int *outCount); 80 | 81 | /** 82 | * \note 83 | * This function is only supported with DRI2 version 1.1 or later. 84 | */ 85 | extern DRI2Buffer* 86 | DRI2GetBuffersWithFormat(Display * dpy, XID drawable, 87 | int *width, int *height, 88 | unsigned int *attachments, 89 | int count, int *outCount); 90 | 91 | extern void 92 | DRI2CopyRegion(Display * dpy, XID drawable, 93 | XserverRegion region, 94 | CARD32 dest, CARD32 src); 95 | 96 | extern void 97 | DRI2SwapBuffers(Display *dpy, XID drawable, CARD64 target_msc, CARD64 divisor, 98 | CARD64 remainder, CARD64 *count); 99 | 100 | extern Bool 101 | DRI2GetMSC(Display *dpy, XID drawable, CARD64 *ust, CARD64 *msc, CARD64 *sbc); 102 | 103 | extern Bool 104 | DRI2WaitMSC(Display *dpy, XID drawable, CARD64 target_msc, CARD64 divisor, 105 | CARD64 remainder, CARD64 *ust, CARD64 *msc, CARD64 *sbc); 106 | 107 | extern Bool 108 | DRI2WaitSBC(Display *dpy, XID drawable, CARD64 target_sbc, CARD64 *ust, 109 | CARD64 *msc, CARD64 *sbc); 110 | 111 | extern void 112 | DRI2SwapInterval(Display *dpy, XID drawable, int interval); 113 | 114 | #endif 115 | -------------------------------------------------------------------------------- /src/gen_shader_bin.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Dmitry Osipenko 3 | * Copyright (c) Erik Faye-Lund 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #include "asm.h" 37 | 38 | static char *vs_path; 39 | static char *fs_path; 40 | static char *lnk_path; 41 | static char *fp_name; 42 | static char *vp_name; 43 | static char *lp_name; 44 | static char *out_name; 45 | 46 | static int parse_command_line(int argc, char *argv[]) 47 | { 48 | int ret; 49 | int c; 50 | 51 | do { 52 | struct option long_options[] = 53 | { 54 | {"vs", required_argument, NULL, 0}, 55 | {"fs", required_argument, NULL, 0}, 56 | {"lnk", required_argument, NULL, 0}, 57 | {"name", required_argument, NULL, 0}, 58 | {"out", required_argument, NULL, 0}, 59 | { /* Sentinel */ } 60 | }; 61 | int option_index = 0; 62 | 63 | c = getopt_long(argc, argv, "", long_options, &option_index); 64 | 65 | switch (c) { 66 | case 0: 67 | switch (option_index) { 68 | case 0: 69 | vs_path = optarg; 70 | break; 71 | case 1: 72 | fs_path = optarg; 73 | break; 74 | case 2: 75 | lnk_path = optarg; 76 | break; 77 | case 3: 78 | fp_name = optarg; 79 | break; 80 | case 4: 81 | out_name = optarg; 82 | break; 83 | default: 84 | return 0; 85 | } 86 | break; 87 | case -1: 88 | break; 89 | default: 90 | fprintf(stderr, "Invalid arguments\n\n"); 91 | return 0; 92 | } 93 | } while (c != -1); 94 | 95 | return 1; 96 | } 97 | 98 | static char *read_file(const char *path) 99 | { 100 | struct stat sb; 101 | char *data; 102 | int fd; 103 | 104 | fd = open(path, O_RDONLY); 105 | if (fd == -1) { 106 | fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno)); 107 | abort(); 108 | } 109 | 110 | if (fstat(fd, &sb) == -1) { 111 | fprintf(stderr, "Failed to get stat %s: %s\n", 112 | path, strerror(errno)); 113 | abort(); 114 | } 115 | 116 | data = calloc(1, sb.st_size + 1); 117 | if (!data) { 118 | fprintf(stderr, "Failed to allocate %ju: %s\n", 119 | (uintmax_t)sb.st_size, path); 120 | abort(); 121 | } 122 | 123 | if (read(fd, data, sb.st_size) == -1) { 124 | fprintf(stderr, "Failed to read %s: %s\n", path, strerror(errno)); 125 | abort(); 126 | } 127 | 128 | close(fd); 129 | 130 | return data; 131 | } 132 | 133 | int main(int argc, char *argv[]) 134 | { 135 | uint32_t in_mask = 0, out_mask = 0; 136 | bool t114_mode = false; 137 | char *asm_txt; 138 | unsigned int i; 139 | FILE *out; 140 | int err; 141 | 142 | /* float decimal point is locale-dependent */ 143 | setlocale(LC_ALL, "C"); 144 | 145 | if (!parse_command_line(argc, argv)) 146 | return 1; 147 | 148 | /* parse vertex asm */ 149 | asm_txt = read_file(vs_path); 150 | if (!asm_txt) 151 | return 1; 152 | 153 | vertex_asm_scan_string(asm_txt); 154 | err = vertex_asmparse(); 155 | if (err) 156 | return err; 157 | 158 | vertex_asmlex_destroy(); 159 | free(asm_txt); 160 | 161 | /* parse linker asm */ 162 | asm_txt = read_file(lnk_path); 163 | if (!asm_txt) 164 | return 1; 165 | 166 | linker_asm_scan_string(asm_txt); 167 | err = linker_asmparse(); 168 | if (err) 169 | return err; 170 | 171 | linker_asmlex_destroy(); 172 | free(asm_txt); 173 | 174 | /* parse fragment asm */ 175 | asm_txt = read_file(fs_path); 176 | if (!asm_txt) 177 | return 1; 178 | 179 | fragment_asm_scan_string(asm_txt); 180 | err = fragment_asmparse(); 181 | if (err) 182 | return err; 183 | 184 | fragment_asmlex_destroy(); 185 | free(asm_txt); 186 | 187 | out = fopen(out_name, "w"); 188 | if (!out) { 189 | fprintf(stderr, "Failed to open %s: %s\n", out_name, strerror(errno)); 190 | return 1; 191 | } 192 | 193 | fprintf(out, "/* Autogenerated file */\n\n"); 194 | fprintf(out, "#include \"shaders/prog.h\"\n\n"); 195 | 196 | gen_fp: 197 | if (t114_mode) 198 | fprintf(out, "static uint32_t fs_%s_t114_words[] = {\n", fp_name); 199 | else 200 | fprintf(out, "static uint32_t fs_%s_words[] = {\n", fp_name); 201 | 202 | fprintf(out, " HOST1X_OPCODE_NONINCR(0x541, %d),\n", 203 | asm_fs_instructions_nb); 204 | for (i = 0; i < asm_fs_instructions_nb; i++) 205 | fprintf(out, " 0x%08X,\n", asm_pseq_instructions[i].data); 206 | 207 | fprintf(out, " HOST1X_OPCODE_IMM(0x500, 0x0),\n"); 208 | 209 | fprintf(out, " HOST1X_OPCODE_NONINCR(0x601, %d),\n", 210 | asm_fs_instructions_nb); 211 | for (i = 0; i < asm_fs_instructions_nb; i++) 212 | fprintf(out, " 0x%08X,\n", asm_mfu_sched[i].data); 213 | 214 | fprintf(out, " HOST1X_OPCODE_NONINCR(0x604, %d),\n", 215 | asm_mfu_instructions_nb * 2); 216 | for (i = 0; i < asm_mfu_instructions_nb; i++) { 217 | fprintf(out, " 0x%08X,\n", asm_mfu_instructions[i].part1); 218 | fprintf(out, " 0x%08X,\n", asm_mfu_instructions[i].part0); 219 | } 220 | 221 | fprintf(out, " HOST1X_OPCODE_NONINCR(0x701, %d),\n", 222 | asm_fs_instructions_nb); 223 | for (i = 0; i < asm_fs_instructions_nb; i++) 224 | fprintf(out, " 0x%08X,\n", asm_tex_instructions[i].data); 225 | 226 | fprintf(out, " HOST1X_OPCODE_NONINCR(0x801, %d),\n", 227 | asm_fs_instructions_nb); 228 | for (i = 0; i < asm_fs_instructions_nb; i++) { 229 | if (t114_mode) 230 | fprintf(out, " 0x%08X,\n", to_114_alu_sched(asm_alu_sched[i].data).data); 231 | else 232 | fprintf(out, " 0x%08X,\n", asm_alu_sched[i].data); 233 | } 234 | 235 | fprintf(out, " HOST1X_OPCODE_NONINCR(0x804, %d),\n", 236 | asm_alu_instructions_nb * 8); 237 | for (i = 0; i < asm_alu_instructions_nb; i++) { 238 | fprintf(out, " 0x%08X,\n", asm_alu_instructions[i].part1); 239 | fprintf(out, " 0x%08X,\n", asm_alu_instructions[i].part0); 240 | fprintf(out, " 0x%08X,\n", asm_alu_instructions[i].part3); 241 | fprintf(out, " 0x%08X,\n", asm_alu_instructions[i].part2); 242 | fprintf(out, " 0x%08X,\n", asm_alu_instructions[i].part5); 243 | fprintf(out, " 0x%08X,\n", asm_alu_instructions[i].part4); 244 | fprintf(out, " 0x%08X,\n", asm_alu_instructions[i].part7); 245 | fprintf(out, " 0x%08X,\n", asm_alu_instructions[i].part6); 246 | } 247 | 248 | fprintf(out, " HOST1X_OPCODE_NONINCR(0x806, %d),\n", 249 | asm_fs_instructions_nb); 250 | for (i = 0; i < asm_fs_instructions_nb; i++) 251 | fprintf(out, " 0x%08X,\n", asm_alu_instructions[i].complement); 252 | 253 | fprintf(out, " HOST1X_OPCODE_NONINCR(0x901, %d),\n", 254 | asm_fs_instructions_nb); 255 | for (i = 0; i < asm_fs_instructions_nb; i++) 256 | fprintf(out, " 0x%08X,\n", asm_dw_instructions[i].data); 257 | 258 | fprintf(out, "};\n\n"); 259 | 260 | if (!t114_mode) { 261 | t114_mode = true; 262 | goto gen_fp; 263 | } 264 | 265 | fprintf(out, "static uint32_t vs_%s_words[] = {\n", fp_name); 266 | 267 | fprintf(out, " HOST1X_OPCODE_NONINCR(0x206, %d),\n", 268 | asm_vs_instructions_nb * 4); 269 | 270 | for (i = 0; i < asm_vs_instructions_nb; i++) { 271 | fprintf(out, " 0x%08X,\n", asm_vs_instructions[i].part3); 272 | fprintf(out, " 0x%08X,\n", asm_vs_instructions[i].part2); 273 | fprintf(out, " 0x%08X,\n", asm_vs_instructions[i].part1); 274 | fprintf(out, " 0x%08X,\n", asm_vs_instructions[i].part0); 275 | } 276 | 277 | fprintf(out, "};\n\n"); 278 | 279 | for (i = 0; i < 16; i++) { 280 | if (asm_vs_attributes[i].used) 281 | in_mask |= 1 << i; 282 | 283 | if (asm_vs_exports[i].used) 284 | out_mask |= 1 << i; 285 | } 286 | 287 | fprintf(out, "static uint32_t lnk_%s_words[] = {\n", fp_name); 288 | 289 | fprintf(out, " HOST1X_OPCODE_INCR(0x300, %d),\n", 290 | asm_linker_instructions_nb * 2); 291 | 292 | for (i = 0; i < asm_linker_instructions_nb; i++) { 293 | fprintf(out, " 0x%08X,\n", asm_linker_instructions[i].first); 294 | fprintf(out, " 0x%08X,\n", asm_linker_instructions[i].latter); 295 | } 296 | 297 | fprintf(out, "};\n\n"); 298 | 299 | fprintf(out, "static struct shader_program prog_%s = {\n", fp_name); 300 | fprintf(out, " .vs_prog_words = vs_%s_words,\n", fp_name); 301 | fprintf(out, " .vs_prog_words_nb = ARRAY_SIZE(vs_%s_words),\n", fp_name); 302 | fprintf(out, " .vs_attrs_in_mask = %u,\n", in_mask); 303 | fprintf(out, " .vs_attrs_out_mask = %u,\n", out_mask); 304 | fprintf(out, "\n"); 305 | fprintf(out, " .fs_prog_words_t114 = fs_%s_t114_words,\n", fp_name); 306 | fprintf(out, " .fs_prog_words = fs_%s_words,\n", fp_name); 307 | fprintf(out, " .fs_prog_words_nb = ARRAY_SIZE(fs_%s_words),\n", fp_name); 308 | fprintf(out, " .fs_alu_buf_size = %u,\n", asm_alu_buffer_size); 309 | fprintf(out, " .fs_pseq_to_dw = %u,\n", asm_pseq_to_dw_exec_nb); 310 | fprintf(out, " .fs_pseq_inst_nb = %u,\n", asm_fs_instructions_nb); 311 | fprintf(out, "\n"); 312 | fprintf(out, " .linker_words = lnk_%s_words,\n", fp_name); 313 | fprintf(out, " .linker_words_nb = ARRAY_SIZE(lnk_%s_words),\n", fp_name); 314 | fprintf(out, " .linker_inst_nb = %u,\n", asm_linker_instructions_nb); 315 | fprintf(out, " .used_tram_rows_nb = %u,\n", asm_linker_used_tram_rows_nb); 316 | fprintf(out, "};\n"); 317 | 318 | return 0; 319 | } 320 | -------------------------------------------------------------------------------- /src/host1x-api.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) GRATE-DRIVER project 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef HOST1X_API_H 24 | #define HOST1X_API_H 25 | 26 | #define host1x_error(fmt, args...) \ 27 | fprintf(stderr, "ERROR: %s: %d: " fmt, __func__, __LINE__, ##args) 28 | 29 | #define PIX_BUF_FMT(id, bpp, planes_nb) \ 30 | ((planes_nb) << 16 | (id) << 8 | (bpp)) 31 | 32 | #define PIX_BUF_FORMAT_BITS(f) \ 33 | ((f) & 0xff) 34 | 35 | #define PIX_BUF_FORMAT_BYTES(f) \ 36 | (PIX_BUF_FORMAT_BITS(f) >> 3) 37 | 38 | #define PIX_BUF_FORMAT_PLANES_NB(f) \ 39 | (((f) >> 16) & 3) 40 | 41 | enum pixel_format { 42 | PIX_BUF_FMT_A8 = PIX_BUF_FMT(0, 8, 1), 43 | PIX_BUF_FMT_L8 = PIX_BUF_FMT(1, 8, 1), 44 | PIX_BUF_FMT_S8 = PIX_BUF_FMT(2, 8, 1), 45 | PIX_BUF_FMT_LA88 = PIX_BUF_FMT(3, 16, 1), 46 | PIX_BUF_FMT_RGB565 = PIX_BUF_FMT(4, 16, 1), 47 | PIX_BUF_FMT_RGBA5551 = PIX_BUF_FMT(5, 16, 1), 48 | PIX_BUF_FMT_RGBA4444 = PIX_BUF_FMT(6, 16, 1), 49 | PIX_BUF_FMT_D16_LINEAR = PIX_BUF_FMT(7, 16, 1), 50 | PIX_BUF_FMT_D16_NONLINEAR = PIX_BUF_FMT(8, 16, 1), 51 | PIX_BUF_FMT_RGBA8888 = PIX_BUF_FMT(9, 32, 1), 52 | PIX_BUF_FMT_RGBA_FP32 = PIX_BUF_FMT(10, 32, 1), 53 | PIX_BUF_FMT_ARGB8888 = PIX_BUF_FMT(11, 32, 1), 54 | PIX_BUF_FMT_ABGR8888 = PIX_BUF_FMT(12, 32, 1), 55 | PIX_BUF_FMT_YV12 = PIX_BUF_FMT(13, 8, 3), 56 | }; 57 | 58 | enum layout_format { 59 | PIX_BUF_LAYOUT_LINEAR, 60 | PIX_BUF_LAYOUT_TILED_16x16, 61 | }; 62 | 63 | struct host1x_csc_params { 64 | uint32_t yos, cvr, cub; 65 | uint32_t cyx, cur, cug; 66 | uint32_t cvb, cvg; 67 | }; 68 | 69 | extern struct host1x_csc_params csc_rgb_default; 70 | 71 | struct host1x_pixelbuffer { 72 | union { 73 | struct drm_tegra_bo *bo; 74 | struct drm_tegra_bo *bos[3]; 75 | }; 76 | enum pixel_format format; 77 | enum layout_format layout; 78 | unsigned width; 79 | unsigned height; 80 | unsigned pitch; 81 | unsigned pitch_uv; 82 | uint32_t guard_offset[3]; 83 | union { 84 | uint32_t bo_offset; 85 | uint32_t bos_offset[3]; 86 | }; 87 | bool guard_enabled; 88 | }; 89 | 90 | #define PIXBUF_GUARD_AREA_SIZE 0x4000 91 | 92 | struct host1x_pixelbuffer *host1x_pixelbuffer_create(struct drm_tegra *drm, 93 | unsigned width, 94 | unsigned height, 95 | unsigned pitch, 96 | unsigned pitch_uv, 97 | enum pixel_format format, 98 | enum layout_format layout); 99 | 100 | struct host1x_pixelbuffer *host1x_pixelbuffer_wrap(struct drm_tegra_bo **bos, 101 | unsigned width, 102 | unsigned height, 103 | unsigned pitch, 104 | unsigned pitch_uv, 105 | enum pixel_format format, 106 | enum layout_format layout); 107 | 108 | void host1x_pixelbuffer_free(struct host1x_pixelbuffer *pixbuf); 109 | 110 | int host1x_pixelbuffer_load_data(struct drm_tegra *drm, 111 | struct tegra_stream *stream, 112 | struct host1x_pixelbuffer *pixbuf, 113 | void *data, 114 | unsigned data_pitch, 115 | unsigned long data_size, 116 | enum pixel_format data_format, 117 | enum layout_format data_layout); 118 | 119 | int host1x_pixelbuffer_setup_guard(struct host1x_pixelbuffer *pixbuf); 120 | 121 | int host1x_pixelbuffer_check_guard(struct host1x_pixelbuffer *pixbuf); 122 | 123 | void host1x_pixelbuffer_disable_bo_guard(void); 124 | 125 | int host1x_gr2d_clear(struct tegra_stream *stream, 126 | struct host1x_pixelbuffer *pixbuf, 127 | uint32_t color); 128 | 129 | int host1x_gr2d_clear_rect(struct tegra_stream *stream, 130 | struct host1x_pixelbuffer *pixbuf, 131 | uint32_t color, 132 | unsigned x, unsigned y, 133 | unsigned width, unsigned height); 134 | 135 | int host1x_gr2d_clear_rect_clipped(struct tegra_stream *stream, 136 | struct host1x_pixelbuffer *pixbuf, 137 | uint32_t color, 138 | unsigned x, unsigned y, 139 | unsigned width, unsigned height, 140 | unsigned clip_x0, unsigned clip_y0, 141 | unsigned clip_x1, unsigned clip_y1, 142 | bool draw_outside); 143 | 144 | enum host1x_2d_rotate { 145 | FLIP_X, 146 | FLIP_Y, 147 | TRANS_LR, 148 | TRANS_RL, 149 | ROT_90, 150 | ROT_180, 151 | ROT_270, 152 | IDENTITY, 153 | }; 154 | 155 | int host1x_gr2d_blit(struct tegra_stream *stream, 156 | struct host1x_pixelbuffer *src, 157 | struct host1x_pixelbuffer *dst, 158 | enum host1x_2d_rotate rotate, 159 | unsigned int sx, unsigned int sy, 160 | unsigned int dx, unsigned int dy, 161 | unsigned int width, int height); 162 | 163 | int host1x_gr2d_surface_blit(struct tegra_stream *stream, 164 | struct host1x_pixelbuffer *src, 165 | struct host1x_pixelbuffer *dst, 166 | struct host1x_csc_params *csc, 167 | unsigned int sx, unsigned int sy, 168 | unsigned int src_width, int src_height, 169 | unsigned int dx, unsigned int dy, 170 | unsigned int dst_width, int dst_height); 171 | 172 | #define FX10(f) (((int32_t)((f) * 256.0f + 0.5f)) & 0x3ff) 173 | #define FX10_L(f) FX10(f) 174 | #define FX10_H(f) (FX10(f) << 10) 175 | #define FX10x2(low, high) (FX10_H(high) | FX10_L(low)) 176 | 177 | #define TGR3D_VAL(reg_name, field_name, value) \ 178 | (((value) << TGR3D_ ## reg_name ## _ ## field_name ## __SHIFT) & \ 179 | TGR3D_ ## reg_name ## _ ## field_name ## __MASK) 180 | 181 | #define TGR3D_BOOL(reg_name, field_name, boolean) \ 182 | ((boolean) ? TGR3D_ ## reg_name ## _ ## field_name : 0) 183 | 184 | #define LOG2_SIZE(v) (31 - __builtin_clz(v)) 185 | #define IS_POW2(v) (((v) & ((v) - 1)) == 0) 186 | 187 | void host1x_gr3d_upload_const_vp(struct tegra_stream *cmds, unsigned index, 188 | float x, float y, float z, float w); 189 | 190 | void host1x_gr3d_upload_const_fp(struct tegra_stream *cmds, unsigned index, 191 | uint32_t constant); 192 | 193 | void host1x_gr3d_setup_scissor(struct tegra_stream *cmds, 194 | unsigned scissor_x, 195 | unsigned scissor_y, 196 | unsigned scissor_width, 197 | unsigned scissor_heigth); 198 | 199 | void host1x_gr3d_setup_viewport_bias_scale(struct tegra_stream *cmds, 200 | float viewport_x_bias, 201 | float viewport_y_bias, 202 | float viewport_z_bias, 203 | float viewport_x_scale, 204 | float viewport_y_scale, 205 | float viewport_z_scale); 206 | 207 | void host1x_gr3d_setup_attribute(struct tegra_stream *cmds, 208 | unsigned index, 209 | struct drm_tegra_bo *bo, 210 | unsigned offset, unsigned type, 211 | unsigned size, unsigned stride); 212 | 213 | void host1x_gr3d_setup_render_target(struct tegra_stream *cmds, 214 | unsigned index, 215 | struct drm_tegra_bo *bo, 216 | unsigned offset, 217 | unsigned pixel_format, 218 | unsigned pitch); 219 | 220 | void host1x_gr3d_enable_render_targets(struct tegra_stream *cmds, uint32_t mask); 221 | 222 | void host1x_gr3d_setup_texture_desc(struct tegra_stream *cmds, 223 | unsigned index, 224 | struct drm_tegra_bo *bo, 225 | unsigned offset, 226 | unsigned width, 227 | unsigned height, 228 | unsigned pixel_format, 229 | bool min_filter_linear, 230 | bool mip_filter_linear, 231 | bool mag_filter_linear, 232 | bool clamp_to_edge, 233 | bool mirrored_repeat); 234 | 235 | void host1x_gr3d_setup_draw_params(struct tegra_stream *cmds, 236 | unsigned primitive_type, 237 | unsigned index_mode, 238 | unsigned first_vtx); 239 | 240 | void host1x_gr3d_draw_primitives(struct tegra_stream *cmds, 241 | unsigned first_index, unsigned count); 242 | 243 | void host1x_gr3d_initialize(struct tegra_stream *cmds, 244 | const struct shader_program *prog); 245 | 246 | #endif 247 | -------------------------------------------------------------------------------- /src/host1x.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, 2013 Erik Faye-Lund 3 | * Copyright (c) 2013 Avionic Design GmbH 4 | * Copyright (c) 2013 Thierry Reding 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a 7 | * copy of this software and associated documentation files (the "Software"), 8 | * to deal in the Software without restriction, including without limitation 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the 11 | * Software is furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 | * DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | #ifndef HOST1X_H 26 | #define HOST1X_H 27 | 28 | #define HOST1X_OPCODE_SETCL(offset, classid, mask) \ 29 | ((0x0 << 28) | (((offset) & 0xfff) << 16) | (((classid) & 0x3ff) << 6) | ((mask) & 0x3f)) 30 | #define HOST1X_OPCODE_INCR(offset, count) \ 31 | ((0x1 << 28) | (((offset) & 0xfff) << 16) | ((count) & 0xffff)) 32 | #define HOST1X_OPCODE_NONINCR(offset, count) \ 33 | ((0x2 << 28) | (((offset) & 0xfff) << 16) | ((count) & 0xffff)) 34 | #define HOST1X_OPCODE_MASK(offset, mask) \ 35 | ((0x3 << 28) | (((offset) & 0xfff) << 16) | ((mask) & 0xffff)) 36 | #define HOST1X_OPCODE_IMM(offset, data) \ 37 | ((0x4 << 28) | (((offset) & 0xfff) << 16) | ((data) & 0xffff)) 38 | #define HOST1X_OPCODE_EXTEND(subop, value) \ 39 | ((0xe << 28) | (((subop) & 0xf) << 24) | ((value) & 0xffffff)) 40 | 41 | #define HOST1X_CLASS_HOST1X 0x01 42 | #define HOST1X_CLASS_GR2D 0x51 43 | #define HOST1X_CLASS_GR2D_SB 0x52 44 | #define HOST1X_CLASS_GR3D 0x60 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /src/media.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Paul Kocialkowski 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the 6 | * "Software"), to deal in the Software without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sub license, and/or sell copies of the Software, and to 9 | * permit persons to whom the Software is furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial portions 14 | * of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 19 | * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 20 | * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "uapi/media.h" 31 | 32 | #include "vdpau_tegra.h" 33 | 34 | int media_request_alloc(int media_fd) 35 | { 36 | int fd; 37 | int rc; 38 | 39 | rc = tegra_ioctl(media_fd, MEDIA_IOC_REQUEST_ALLOC, &fd); 40 | if (rc < 0) { 41 | request_log("Unable to allocate media request: %s\n", 42 | strerror(errno)); 43 | return -1; 44 | } 45 | 46 | return fd; 47 | } 48 | 49 | int media_request_reinit(int request_fd) 50 | { 51 | int rc; 52 | 53 | rc = tegra_ioctl(request_fd, MEDIA_REQUEST_IOC_REINIT, NULL); 54 | if (rc < 0) { 55 | request_log("Unable to reinit media request: %s\n", 56 | strerror(errno)); 57 | return -1; 58 | } 59 | 60 | return 0; 61 | } 62 | 63 | int media_request_queue(int request_fd) 64 | { 65 | int rc; 66 | 67 | rc = tegra_ioctl(request_fd, MEDIA_REQUEST_IOC_QUEUE, NULL); 68 | if (rc < 0) { 69 | request_log("Unable to queue media request: %s\n", 70 | strerror(errno)); 71 | return -1; 72 | } 73 | 74 | return 0; 75 | } 76 | 77 | int media_request_wait_completion(int request_fd) 78 | { 79 | struct timeval tv = { 2, 0 }; 80 | fd_set except_fds; 81 | int rc; 82 | 83 | FD_ZERO(&except_fds); 84 | FD_SET(request_fd, &except_fds); 85 | 86 | do { 87 | rc = select(request_fd + 1, NULL, NULL, &except_fds, &tv); 88 | } while (rc < 0 && (errno == EINTR || errno == EAGAIN)); 89 | 90 | if (rc == 0) { 91 | request_log("Timeout when waiting for media request\n"); 92 | return -1; 93 | } else if (rc < 0) { 94 | request_log("Unable to select media request: %s\n", 95 | strerror(errno)); 96 | return -1; 97 | } 98 | 99 | return 0; 100 | } 101 | -------------------------------------------------------------------------------- /src/media.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Paul Kocialkowski 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the 6 | * "Software"), to deal in the Software without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sub license, and/or sell copies of the Software, and to 9 | * permit persons to whom the Software is furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial portions 14 | * of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 19 | * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 20 | * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | #ifndef _MEDIA_H_ 26 | #define _MEDIA_H_ 27 | 28 | int media_request_alloc(int media_fd); 29 | int media_request_reinit(int request_fd); 30 | int media_request_queue(int request_fd); 31 | int media_request_wait_completion(int request_fd); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /src/shaders/blend_atop/fragment.asm: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Dmitry Osipenko 2018 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | pseq_to_dw_exec_nb = 3 // the number of 'EXEC' block where DW happens 24 | alu_buffer_size = 1 // number of .rgba regs carried through pipeline 25 | 26 | .asm 27 | 28 | EXEC 29 | MFU: sfu: rcp r4 30 | mul0: bar, sfu, bar0 31 | mul1: bar, sfu, bar1 32 | ipl: t1.fp20, t1.fp20, NOP, NOP 33 | 34 | // sample tex1 (mask) 35 | TEX: tex r2, r3, tex0, r0, r1, r2 36 | ; 37 | 38 | EXEC 39 | MFU: sfu: rcp r4 40 | mul0: bar, sfu, bar0 41 | mul1: bar, sfu, bar1 42 | ipl: t0.fx10, t0.fx10, NOP, NOP 43 | 44 | ALU: 45 | ALU0: MAD r0.l, r2.l, r0.l, #0 46 | ALU1: MAD r0.h, r2.h, r0.h, #0 47 | ALU2: MAD r1.l, r3.l, r1.l, #0 48 | ALU3: MAD r1.h, r3.h, -r1.h, #1 49 | ; 50 | 51 | EXEC 52 | // fetch dst pixel to r2,r3 53 | PSEQ: 0x0081000A 54 | 55 | ALU: 56 | ALU0: MAD r0.l, r1.h, r2.l, r0.l 57 | ALU1: MAD r0.h, r1.h, r2.h, r0.h 58 | ALU2: MAD r1.l, r1.h, r3.l, r1.l 59 | 60 | DW: store rt1, r0, r1 61 | ; 62 | -------------------------------------------------------------------------------- /src/shaders/blend_atop/linker.asm: -------------------------------------------------------------------------------- 1 | LINK fx10.l, fx10.h, fx10.l, fx10.h, tram0.xxyy, export1 2 | LINK fp20, fp20, NOP, NOP, tram1.xyzw, export2 3 | -------------------------------------------------------------------------------- /src/shaders/blend_atop/vertex.asm: -------------------------------------------------------------------------------- 1 | .exports 2 | [0] = "position"; 3 | [1] = "colors"; 4 | [2] = "texcoords"; 5 | 6 | .attributes 7 | [0] = "position"; 8 | [1] = "colors"; 9 | [2] = "texcoords"; 10 | 11 | .constants 12 | [0].z = 0.0; 13 | [0].w = 1.0; 14 | 15 | .asm 16 | EXEC(export[0]=vector) 17 | MOVv r63.xy**, a[0].xyzw 18 | ; 19 | 20 | EXEC(export[0]=vector) 21 | MOVv r63.**zw, c[0].xyzw 22 | ; 23 | 24 | EXEC(export[1]=vector) 25 | MOVv r63.xyzw, a[1].xyzw 26 | ; 27 | 28 | EXEC_END(export[2]=vector) 29 | MOVv r63.xy**, a[2].xyzw 30 | ; 31 | -------------------------------------------------------------------------------- /src/shaders/blend_atop_solid_shade/fragment.asm: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Dmitry Osipenko 2018 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | pseq_to_dw_exec_nb = 1 // the number of 'EXEC' block where DW happens 24 | alu_buffer_size = 1 // number of .rgba regs carried through pipeline 25 | 26 | .asm 27 | 28 | EXEC 29 | // fetch dst pixel to r2,r3 30 | PSEQ: 0x0081000A 31 | 32 | MFU: sfu: rcp r4 33 | mul0: bar, sfu, bar0 34 | mul1: bar, sfu, bar1 35 | ipl: t0.fp20, t0.fp20, NOP, NOP 36 | 37 | // sample tex1 (mask) 38 | TEX: tex r0, r1, tex0, r0, r1, r2 39 | 40 | ALU: 41 | ALU0: MAD r0.l, r1.h-1, -r2.l, r0.l 42 | ALU1: MAD r0.h, r1.h-1, -r2.h, r0.h 43 | ALU2: MAD r1.l, r1.h-1, -r3.l, r1.l 44 | 45 | DW: store rt1, r0, r1 46 | ; 47 | -------------------------------------------------------------------------------- /src/shaders/blend_atop_solid_shade/linker.asm: -------------------------------------------------------------------------------- 1 | LINK fp20, fp20, NOP, NOP, tram0.xyzw, export1 2 | -------------------------------------------------------------------------------- /src/shaders/blend_atop_solid_shade/vertex.asm: -------------------------------------------------------------------------------- 1 | .exports 2 | [0] = "position"; 3 | [1] = "texcoords"; 4 | 5 | .attributes 6 | [0] = "position"; 7 | [2] = "texcoords"; 8 | 9 | .constants 10 | [0].z = 0.0; 11 | [0].w = 1.0; 12 | 13 | .asm 14 | EXEC(export[0]=vector) 15 | MOVv r63.xy**, a[0].xyzw 16 | ; 17 | 18 | EXEC(export[0]=vector) 19 | MOVv r63.**zw, c[0].xyzw 20 | ; 21 | 22 | EXEC_END(export[1]=vector) 23 | MOVv r63.xy**, a[2].xyzw 24 | ; 25 | -------------------------------------------------------------------------------- /src/shaders/prog.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Dmitry Osipenko 3 | * Copyright (c) Erik Faye-Lund 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #ifndef __TEGRA_GR3D_SHADER_PROG_H 25 | #define __TEGRA_GR3D_SHADER_PROG_H 26 | 27 | struct shader_program { 28 | uint32_t *vs_prog_words; 29 | unsigned vs_prog_words_nb; 30 | uint16_t vs_attrs_in_mask; 31 | uint16_t vs_attrs_out_mask; 32 | 33 | uint32_t *fs_prog_words; 34 | uint32_t *fs_prog_words_t114; 35 | unsigned fs_prog_words_nb; 36 | unsigned fs_alu_buf_size; 37 | unsigned fs_pseq_to_dw; 38 | unsigned fs_pseq_inst_nb; 39 | 40 | uint32_t *linker_words; 41 | unsigned linker_words_nb; 42 | unsigned linker_inst_nb; 43 | unsigned used_tram_rows_nb; 44 | }; 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /src/surface_bitmap.c: -------------------------------------------------------------------------------- 1 | /* 2 | * NVIDIA TEGRA 2 VDPAU backend driver 3 | * 4 | * Copyright (c) 2016 Dmitry Osipenko 5 | * 6 | * This program is free software; you can redistribute it and/or modify it 7 | * under the terms of the GNU General Public License as published by the 8 | * Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License along 17 | * with this program; if not, see . 18 | */ 19 | 20 | #include "vdpau_tegra.h" 21 | 22 | VdpStatus vdp_bitmap_surface_query_capabilities( 23 | VdpDevice device, 24 | VdpRGBAFormat surface_rgba_format, 25 | VdpBool *is_supported, 26 | uint32_t *max_width, 27 | uint32_t *max_height) 28 | { 29 | tegra_device *dev = get_device(device); 30 | 31 | if (dev == NULL) { 32 | return VDP_STATUS_INVALID_HANDLE; 33 | } 34 | 35 | switch (surface_rgba_format) { 36 | case VDP_RGBA_FORMAT_R8G8B8A8: 37 | case VDP_RGBA_FORMAT_B8G8R8A8: 38 | *is_supported = VDP_TRUE; 39 | break; 40 | default: 41 | *is_supported = VDP_FALSE; 42 | break; 43 | } 44 | 45 | *max_width = INT_MAX; 46 | *max_height = INT_MAX; 47 | 48 | put_device(dev); 49 | 50 | return VDP_STATUS_OK; 51 | } 52 | 53 | VdpStatus vdp_bitmap_surface_create(VdpDevice device, 54 | VdpRGBAFormat rgba_format, 55 | uint32_t width, uint32_t height, 56 | VdpBool frequently_accessed, 57 | VdpBitmapSurface *surface) 58 | { 59 | tegra_device *dev = get_device(device); 60 | 61 | if (dev == NULL) { 62 | return VDP_STATUS_INVALID_HANDLE; 63 | } 64 | 65 | switch (rgba_format) { 66 | case VDP_RGBA_FORMAT_R8G8B8A8: 67 | case VDP_RGBA_FORMAT_B8G8R8A8: 68 | break; 69 | default: 70 | put_device(dev); 71 | return VDP_STATUS_INVALID_RGBA_FORMAT; 72 | } 73 | 74 | *surface = create_surface(dev, width, height, rgba_format, 0, 0); 75 | 76 | if (*surface == VDP_INVALID_HANDLE) { 77 | put_device(dev); 78 | return VDP_STATUS_RESOURCES; 79 | } 80 | 81 | put_device(dev); 82 | 83 | return VDP_STATUS_OK; 84 | } 85 | 86 | VdpStatus vdp_bitmap_surface_destroy(VdpBitmapSurface surface) 87 | { 88 | tegra_surface *surf = get_surface_bitmap(surface); 89 | 90 | if (surf == NULL) { 91 | return VDP_INVALID_HANDLE; 92 | } 93 | 94 | put_surface(surf); 95 | 96 | return destroy_surface(surf); 97 | } 98 | 99 | VdpStatus vdp_bitmap_surface_get_parameters(VdpBitmapSurface surface, 100 | VdpRGBAFormat *rgba_format, 101 | uint32_t *width, uint32_t *height, 102 | VdpBool *frequently_accessed) 103 | { 104 | tegra_surface *surf = get_surface(surface); 105 | 106 | if (surf == NULL) { 107 | return VDP_STATUS_INVALID_HANDLE; 108 | } 109 | 110 | *rgba_format = surf->rgba_format; 111 | *width = surf->width; 112 | *height = surf->height; 113 | *frequently_accessed = VDP_FALSE; 114 | 115 | put_surface(surf); 116 | 117 | return VDP_STATUS_OK; 118 | } 119 | 120 | VdpStatus vdp_bitmap_surface_put_bits_native(VdpBitmapSurface surface, 121 | void const *const *source_data, 122 | uint32_t const *source_pitches, 123 | VdpRect const *destination_rect) 124 | { 125 | tegra_surface *surf; 126 | pixman_image_t *pix; 127 | pixman_format_code_t pfmt; 128 | pixman_bool_t ret; 129 | void *surf_data; 130 | uint32_t width = 0, height = 0; 131 | uint32_t x0 = 0, y0 = 0; 132 | int err; 133 | 134 | if (destination_rect) { 135 | width = destination_rect->x1 - destination_rect->x0; 136 | height = destination_rect->y1 - destination_rect->y0; 137 | x0 = destination_rect->x0; 138 | y0 = destination_rect->y0; 139 | 140 | if (!width || !height) { 141 | return VDP_STATUS_OK; 142 | } 143 | } 144 | 145 | surf = get_surface(surface); 146 | if (surf == NULL) { 147 | return VDP_STATUS_INVALID_HANDLE; 148 | } 149 | 150 | pthread_mutex_lock(&surf->lock); 151 | 152 | if (surf->flags & SURFACE_OUTPUT) { 153 | err = shared_surface_transfer_video(surf); 154 | if (err) { 155 | pthread_mutex_unlock(&surf->lock); 156 | put_surface(surf); 157 | return err; 158 | } 159 | 160 | /* XXX: check whether dirty data is overridden by surface blit */ 161 | surf->data_dirty = true; 162 | } 163 | 164 | err = map_surface_data(surf); 165 | if (err) { 166 | pthread_mutex_unlock(&surf->lock); 167 | put_surface(surf); 168 | return VDP_STATUS_RESOURCES; 169 | } 170 | 171 | pix = surf->pix; 172 | pfmt = pixman_image_get_format(pix); 173 | surf_data = pixman_image_get_data(pix); 174 | 175 | assert(!(surf->flags & SURFACE_VIDEO)); 176 | 177 | if (destination_rect == NULL) { 178 | width = pixman_image_get_width(pix); 179 | height = pixman_image_get_height(pix); 180 | x0 = 0; 181 | y0 = 0; 182 | } 183 | 184 | ret = pixman_blt((void *)source_data[0], surf_data, 185 | source_pitches[0] / 4, pixman_image_get_stride(pix) / 4, 186 | PIXMAN_FORMAT_BPP(pfmt), PIXMAN_FORMAT_BPP(pfmt), 187 | 0, 0, 188 | x0, y0, 189 | width, height); 190 | if (!ret) { 191 | ErrorMsg("pixman_blt failed\n"); 192 | } 193 | 194 | host1x_pixelbuffer_check_guard(surf->pixbuf); 195 | 196 | unmap_surface_data(surf); 197 | 198 | pthread_mutex_unlock(&surf->lock); 199 | 200 | put_surface(surf); 201 | 202 | return VDP_STATUS_OK; 203 | } 204 | -------------------------------------------------------------------------------- /src/surface_cache.c: -------------------------------------------------------------------------------- 1 | /* 2 | * NVIDIA TEGRA 2 VDPAU backend driver 3 | * 4 | * Copyright (c) 2022 Dmitry Osipenko 5 | * 6 | * This program is free software; you can redistribute it and/or modify it 7 | * under the terms of the GNU General Public License as published by the 8 | * Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License along 17 | * with this program; if not, see . 18 | */ 19 | 20 | #include "vdpau_tegra.h" 21 | 22 | #define CACHE_EXPIRE_NSEC (30 * NSEC_PER_SEC) 23 | 24 | static struct list_head tegra_cache_list = { 25 | .prev = &tegra_cache_list, 26 | .next = &tegra_cache_list, 27 | }; 28 | 29 | static pthread_mutex_t cache_lock = PTHREAD_MUTEX_INITIALIZER; 30 | 31 | void tegra_surface_cache_init(tegra_surface_cache *cache) 32 | { 33 | LIST_INITHEAD(&cache->list); 34 | 35 | pthread_mutex_lock(&cache_lock); 36 | LIST_ADD(&cache->cache_list_entry, &tegra_cache_list); 37 | pthread_mutex_unlock(&cache_lock); 38 | } 39 | 40 | static void 41 | tegra_surface_cache_remove_surface_locked(tegra_surface *surf) 42 | { 43 | DebugMsg("surface %u %p cache %p\n", 44 | surf->surface_id, surf, surf->cache_entry.cache); 45 | 46 | LIST_DEL(&surf->cache_entry.entry); 47 | surf->cache_entry.cache = NULL; 48 | unref_surface(surf); 49 | } 50 | 51 | static void tegra_surface_cache_clear_locked(tegra_surface_cache *cache) 52 | { 53 | tegra_surface *surf, *tmp; 54 | 55 | DebugMsg("cache %p\n", cache); 56 | 57 | LIST_FOR_EACH_ENTRY_SAFE(surf, tmp, &cache->list, cache_entry.entry) 58 | tegra_surface_cache_remove_surface_locked(surf); 59 | } 60 | 61 | void tegra_surface_cache_release(tegra_surface_cache *cache) 62 | { 63 | pthread_mutex_lock(&cache_lock); 64 | 65 | tegra_surface_cache_clear_locked(cache); 66 | LIST_DEL(&cache->cache_list_entry); 67 | 68 | pthread_mutex_unlock(&cache_lock); 69 | } 70 | 71 | void tegra_surface_drop_caches(void) 72 | { 73 | tegra_surface_cache *cache; 74 | 75 | DebugMsg("\n"); 76 | 77 | pthread_mutex_lock(&cache_lock); 78 | 79 | LIST_FOR_EACH_ENTRY(cache, &tegra_cache_list, cache_list_entry) 80 | tegra_surface_cache_clear_locked(cache); 81 | 82 | pthread_mutex_unlock(&cache_lock); 83 | } 84 | 85 | static void tegra_surface_cache_cleanup_locked(tegra_surface_cache *cache, 86 | VdpTime time) 87 | { 88 | tegra_surface *surf, *tmp; 89 | 90 | LIST_FOR_EACH_ENTRY_SAFE(surf, tmp, &cache->list, cache_entry.entry) { 91 | if (!surf->destroyed) 92 | continue; 93 | 94 | if (time - surf->cache_entry.last_use >= CACHE_EXPIRE_NSEC) { 95 | DebugMsg("evicted surface %u %p cache %p\n", 96 | surf->surface_id, surf, cache); 97 | 98 | tegra_surface_cache_remove_surface_locked(surf); 99 | } 100 | } 101 | } 102 | 103 | void tegra_surface_cache_surface_update_last_use(tegra_surface *surf) 104 | { 105 | DebugMsg("surface %u %p cache %p\n", 106 | surf->surface_id, surf, surf->cache_entry.cache); 107 | 108 | pthread_mutex_lock(&surf->lock); 109 | surf->cache_entry.last_use = get_time(); 110 | pthread_mutex_unlock(&surf->lock); 111 | } 112 | 113 | void tegra_surface_cache_add_surface(tegra_surface_cache *cache, 114 | tegra_surface *surf) 115 | { 116 | DebugMsg("surface %u %p cache %p\n", 117 | surf->surface_id, surf, surf->cache_entry.cache); 118 | 119 | pthread_mutex_lock(&cache_lock); 120 | 121 | if (!surf->cache_entry.cache) { 122 | LIST_ADDTAIL(&surf->cache_entry.entry, &cache->list); 123 | surf->cache_entry.cache = cache; 124 | ref_surface(surf); 125 | 126 | DebugMsg("surface %u %p added to cache %p\n", 127 | surf->surface_id, surf, cache); 128 | } else { 129 | DebugMsg("surface %u %p not added to cache %p\n", 130 | surf->surface_id, surf, cache); 131 | } 132 | 133 | tegra_surface_cache_surface_update_last_use(surf); 134 | tegra_surface_cache_cleanup_locked(cache, surf->cache_entry.last_use); 135 | 136 | pthread_mutex_unlock(&cache_lock); 137 | } 138 | 139 | void tegra_surface_cache_surface_self_remove(tegra_surface *surf) 140 | { 141 | DebugMsg("surface %u %p cache %p\n", 142 | surf->surface_id, surf, surf->cache_entry.cache); 143 | 144 | pthread_mutex_lock(&cache_lock); 145 | 146 | if (surf->cache_entry.cache) 147 | tegra_surface_cache_remove_surface_locked(surf); 148 | 149 | pthread_mutex_unlock(&cache_lock); 150 | } 151 | 152 | tegra_surface * 153 | tegra_surface_cache_take_surface(tegra_device *dev, 154 | uint32_t width, uint32_t height, 155 | VdpRGBAFormat rgba_format, 156 | int output, int video) 157 | { 158 | tegra_surface_cache *cache; 159 | tegra_surface *surf, *tmp; 160 | 161 | pthread_mutex_lock(&cache_lock); 162 | 163 | DebugMsg("want dev %p width %d height %d rgba_format %d output %d video %d\n", 164 | dev, width, height, rgba_format, output, video); 165 | 166 | if (tegra_vdpau_debug) { 167 | LIST_FOR_EACH_ENTRY(cache, &tegra_cache_list, cache_list_entry) { 168 | LIST_FOR_EACH_ENTRY_SAFE(surf, tmp, &cache->list, cache_entry.entry) { 169 | pthread_mutex_lock(&surf->lock); 170 | 171 | DebugMsg("surface %u %p cache %p dev %p width %d height %d rgba_format %d destroyed %d detached %d shared %d output %d video %d time %llums\n", 172 | surf->surface_id, surf, cache, surf->dev, 173 | surf->width, surf->height, surf->rgba_format, 174 | surf->destroyed, surf->detached, !!surf->shared, 175 | !!(surf->flags & SURFACE_OUTPUT), 176 | !!(surf->flags & SURFACE_VIDEO), 177 | (get_time() - surf->cache_entry.last_use) / 1000000); 178 | 179 | pthread_mutex_unlock(&surf->lock); 180 | } 181 | } 182 | } 183 | 184 | LIST_FOR_EACH_ENTRY(cache, &tegra_cache_list, cache_list_entry) { 185 | LIST_FOR_EACH_ENTRY_SAFE(surf, tmp, &cache->list, cache_entry.entry) { 186 | pthread_mutex_lock(&surf->lock); 187 | 188 | if (surf->destroyed && 189 | surf->dev == dev && 190 | surf->width == width && 191 | surf->height == height && 192 | surf->rgba_format == rgba_format && 193 | !!output == !!(surf->flags & SURFACE_OUTPUT) && 194 | !!video == !!(surf->flags & SURFACE_VIDEO)) 195 | { 196 | ref_surface(surf); 197 | tegra_surface_cache_remove_surface_locked(surf); 198 | 199 | DebugMsg("surface %u %p cache %p\n", 200 | surf->surface_id, surf, cache); 201 | 202 | pthread_mutex_unlock(&surf->lock); 203 | pthread_mutex_unlock(&cache_lock); 204 | 205 | return surf; 206 | } 207 | 208 | pthread_mutex_unlock(&surf->lock); 209 | } 210 | } 211 | 212 | pthread_mutex_unlock(&cache_lock); 213 | 214 | return NULL; 215 | } 216 | -------------------------------------------------------------------------------- /src/surface_rotate.c: -------------------------------------------------------------------------------- 1 | /* 2 | * NVIDIA TEGRA 2 VDPAU backend driver 3 | * 4 | * Copyright (c) 2019 Dmitry Osipenko 5 | * 6 | * This program is free software; you can redistribute it and/or modify it 7 | * under the terms of the GNU General Public License as published by the 8 | * Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License along 17 | * with this program; if not, see . 18 | */ 19 | 20 | #include "vdpau_tegra.h" 21 | 22 | int rotate_surface_gr2d(tegra_surface *src_surf, 23 | tegra_surface *dst_surf, 24 | struct host1x_csc_params *csc, 25 | enum host1x_2d_rotate rotate, 26 | unsigned int sx, unsigned int sy, 27 | unsigned int src_width, int src_height, 28 | unsigned int dx, unsigned int dy, 29 | unsigned int dst_width, int dst_height, 30 | bool check_only) 31 | { 32 | tegra_device *dev; 33 | struct tegra_stream *stream; 34 | struct host1x_pixelbuffer *src; 35 | struct host1x_pixelbuffer *dst; 36 | struct host1x_pixelbuffer *tmp2 = NULL; 37 | struct host1x_pixelbuffer *tmp = NULL; 38 | struct host1x_pixelbuffer *rot = NULL; 39 | unsigned pre_rot_width, pre_rot_height; 40 | unsigned rot_width, rot_height; 41 | unsigned tmp_width, tmp_height; 42 | bool downscale = true; 43 | bool twopass = false; 44 | unsigned x, y; 45 | int ret = 0; 46 | 47 | if (!src_surf || !dst_surf) 48 | return -EINVAL; 49 | 50 | pthread_mutex_lock(&dst_surf->lock); 51 | 52 | if (!(src_surf->flags & SURFACE_VIDEO)) { 53 | DebugMsg("src isn't video surface\n"); 54 | ret = -EINVAL; 55 | goto out_unlock; 56 | } 57 | 58 | if (!(dst_surf->flags & SURFACE_OUTPUT)) { 59 | DebugMsg("dst isn't output surface\n"); 60 | ret = -EINVAL; 61 | goto out_unlock; 62 | } 63 | 64 | if (dst_surf->rgba_format != VDP_RGBA_FORMAT_R8G8B8A8 && 65 | dst_surf->rgba_format != VDP_RGBA_FORMAT_B8G8R8A8) { 66 | DebugMsg("dst has unsupported format %d\n", dst_surf->rgba_format); 67 | ret = -EINVAL; 68 | goto out_unlock; 69 | } 70 | 71 | switch (rotate) { 72 | case ROT_270: 73 | pre_rot_width = dst_height; 74 | pre_rot_height = dst_width; 75 | break; 76 | 77 | case ROT_180: 78 | pre_rot_width = dst_width; 79 | pre_rot_height = dst_height; 80 | break; 81 | 82 | case ROT_90: 83 | pre_rot_width = dst_height; 84 | pre_rot_height = dst_width; 85 | break; 86 | 87 | default: 88 | DebugMsg("invalid mode %d\n", rotate); 89 | ret = -EINVAL; 90 | goto out_unlock; 91 | } 92 | 93 | if (check_only) 94 | goto out_unlock; 95 | 96 | src = src_surf->pixbuf; 97 | dst = dst_surf->pixbuf; 98 | dev = dst_surf->dev; 99 | stream = dst_surf->stream_2d; 100 | 101 | if (pre_rot_width * pre_rot_height > src_width * src_height) 102 | downscale = false; 103 | 104 | if (downscale) { 105 | tmp_width = ALIGN(pre_rot_width, 4); 106 | tmp_height = ALIGN(pre_rot_height, 4); 107 | 108 | rot_width = ALIGN(dst_width, 4); 109 | rot_height = ALIGN(dst_height, 4); 110 | } else { 111 | tmp_width = ALIGN(src_width, 4); 112 | tmp_height = ALIGN(src_height, 4); 113 | 114 | if (rotate == ROT_180) { 115 | rot_width = tmp_width; 116 | rot_height = tmp_height; 117 | } else { 118 | rot_width = tmp_height; 119 | rot_height = tmp_width; 120 | } 121 | } 122 | 123 | tmp = host1x_pixelbuffer_create(dev->drm, 124 | tmp_width, tmp_height, 125 | tmp_width * 4, 0, 126 | dst->format, 127 | PIX_BUF_LAYOUT_LINEAR); 128 | if (!tmp) 129 | return -EINVAL; 130 | 131 | ret = host1x_gr2d_surface_blit(stream, 132 | src, tmp, 133 | csc, sx, sy, 134 | src_width, 135 | src_height, 136 | 0, 0, 137 | tmp_width, 138 | tmp_height); 139 | if (ret) 140 | goto out_unref; 141 | 142 | if (!ALIGNED(dx, 4) || 143 | !ALIGNED(dy, 4) || 144 | tmp_width != pre_rot_width || 145 | tmp_height != pre_rot_height) 146 | { 147 | tmp2 = host1x_pixelbuffer_create(dev->drm, 148 | rot_width, rot_height, 149 | rot_width * 4, 0, 150 | dst->format, 151 | PIX_BUF_LAYOUT_LINEAR); 152 | if (!tmp2) { 153 | ret = -ENOMEM; 154 | goto out_unref; 155 | } 156 | 157 | DebugMsg("two-pass rotation, downscale %u, %u:%u %u:%u %u:%u\n", 158 | downscale, dx, dy, tmp_width, tmp_height, 159 | pre_rot_width, pre_rot_height); 160 | 161 | twopass = true; 162 | 163 | rot = tmp2; 164 | } else { 165 | DebugMsg("direct rotation\n"); 166 | 167 | rot = dst; 168 | } 169 | 170 | if (twopass) { 171 | x = 0; 172 | y = 0; 173 | } else { 174 | x = dx; 175 | y = dy; 176 | } 177 | 178 | ret = host1x_gr2d_blit(stream, 179 | tmp, rot, 180 | rotate, 181 | 0, 0, 182 | x, y, 183 | tmp_width, tmp_height); 184 | if (ret) 185 | goto out_unref; 186 | 187 | if (twopass) 188 | ret = host1x_gr2d_surface_blit(stream, 189 | rot, dst, 190 | &csc_rgb_default, 191 | 0, 0, 192 | rot_width, rot_height, 193 | dx, dy, dst_width, dst_height); 194 | 195 | out_unref: 196 | if (tmp) 197 | host1x_pixelbuffer_free(tmp); 198 | 199 | if (tmp2) 200 | host1x_pixelbuffer_free(tmp2); 201 | 202 | out_unlock: 203 | pthread_mutex_unlock(&dst_surf->lock); 204 | 205 | return ret; 206 | } 207 | -------------------------------------------------------------------------------- /src/surface_video.c: -------------------------------------------------------------------------------- 1 | /* 2 | * NVIDIA TEGRA 2 VDPAU backend driver 3 | * 4 | * Copyright (c) 2016 Dmitry Osipenko 5 | * 6 | * This program is free software; you can redistribute it and/or modify it 7 | * under the terms of the GNU General Public License as published by the 8 | * Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License along 17 | * with this program; if not, see . 18 | */ 19 | 20 | #include "vdpau_tegra.h" 21 | 22 | VdpStatus vdp_video_surface_query_capabilities( 23 | VdpDevice device, 24 | VdpChromaType surface_chroma_type, 25 | VdpBool *is_supported, 26 | uint32_t *max_width, 27 | uint32_t *max_height) 28 | { 29 | tegra_device *dev = get_device(device); 30 | 31 | if (dev == NULL) { 32 | return VDP_STATUS_INVALID_HANDLE; 33 | } 34 | 35 | *is_supported = (surface_chroma_type == VDP_CHROMA_TYPE_420); 36 | *max_width = INT_MAX; 37 | *max_height = INT_MAX; 38 | 39 | put_device(dev); 40 | 41 | return VDP_STATUS_OK; 42 | } 43 | 44 | VdpStatus vdp_video_surface_query_get_put_bits_y_cb_cr_capabilities( 45 | VdpDevice device, 46 | VdpChromaType surface_chroma_type, 47 | VdpYCbCrFormat bits_ycbcr_format, 48 | VdpBool *is_supported) 49 | { 50 | tegra_device *dev = get_device(device); 51 | 52 | if (dev == NULL) { 53 | return VDP_STATUS_INVALID_HANDLE; 54 | } 55 | 56 | *is_supported = (bits_ycbcr_format == VDP_YCBCR_FORMAT_YV12); 57 | 58 | put_device(dev); 59 | 60 | return VDP_STATUS_OK; 61 | } 62 | 63 | VdpStatus vdp_video_surface_create(VdpDevice device, 64 | VdpChromaType chroma_type, 65 | uint32_t width, uint32_t height, 66 | VdpVideoSurface *surface) 67 | { 68 | tegra_device *dev = get_device(device); 69 | 70 | if (dev == NULL) { 71 | return VDP_STATUS_INVALID_HANDLE; 72 | } 73 | 74 | if (chroma_type != VDP_CHROMA_TYPE_420) { 75 | put_device(dev); 76 | return VDP_STATUS_INVALID_CHROMA_TYPE; 77 | } 78 | 79 | *surface = create_surface(dev, width, height, ~0, 0, 1); 80 | 81 | if (*surface == VDP_INVALID_HANDLE) { 82 | put_device(dev); 83 | return VDP_STATUS_RESOURCES; 84 | } 85 | 86 | put_device(dev); 87 | 88 | return VDP_STATUS_OK; 89 | } 90 | 91 | VdpStatus vdp_video_surface_destroy(VdpVideoSurface surface) 92 | { 93 | tegra_surface *surf = get_surface_video(surface); 94 | uint32_t flags; 95 | 96 | if (surf == NULL) { 97 | return VDP_INVALID_HANDLE; 98 | } 99 | 100 | flags = surf->flags; 101 | surf->v4l2.buf_idx = -1; 102 | 103 | put_surface(surf); 104 | 105 | if (!(flags & SURFACE_VIDEO)) { 106 | return VDP_INVALID_HANDLE; 107 | } 108 | 109 | return destroy_surface(surf); 110 | } 111 | 112 | VdpStatus vdp_video_surface_get_parameters(VdpVideoSurface surface, 113 | VdpChromaType *chroma_type, 114 | uint32_t *width, uint32_t *height) 115 | { 116 | tegra_surface *surf = get_surface_video(surface); 117 | 118 | if (surf == NULL) { 119 | return VDP_STATUS_INVALID_HANDLE; 120 | } 121 | 122 | assert(surf->flags & SURFACE_VIDEO); 123 | 124 | if (chroma_type != NULL) { 125 | *chroma_type = VDP_CHROMA_TYPE_420; 126 | } 127 | 128 | if (width != NULL) { 129 | *width = surf->width; 130 | } 131 | 132 | if (width != NULL) { 133 | *height = surf->height; 134 | } 135 | 136 | put_surface(surf); 137 | 138 | return VDP_STATUS_OK; 139 | } 140 | 141 | VdpStatus vdp_video_surface_get_bits_y_cb_cr( 142 | VdpVideoSurface surface, 143 | VdpYCbCrFormat destination_ycbcr_format, 144 | void *const *destination_data, 145 | uint32_t const *destination_pitches) 146 | { 147 | tegra_surface *surf = get_surface_video(surface); 148 | void *dst_y = destination_data[0]; 149 | void *dst_cr = destination_data[1]; 150 | void *dst_cb = destination_data[2]; 151 | int width, height; 152 | int ret; 153 | 154 | if (surf == NULL) { 155 | return VDP_STATUS_INVALID_HANDLE; 156 | } 157 | 158 | assert(surf->flags & SURFACE_VIDEO); 159 | 160 | pthread_mutex_lock(&surf->lock); 161 | 162 | switch (destination_ycbcr_format) { 163 | case VDP_YCBCR_FORMAT_YV12: 164 | break; 165 | default: 166 | pthread_mutex_unlock(&surf->lock); 167 | put_surface(surf); 168 | return VDP_STATUS_NO_IMPLEMENTATION; 169 | } 170 | 171 | ret = map_surface_data(surf); 172 | if (ret) { 173 | pthread_mutex_unlock(&surf->lock); 174 | put_surface(surf); 175 | return ret; 176 | } 177 | 178 | width = surf->width; 179 | height = surf->height; 180 | 181 | /* Copy luma plane. */ 182 | ret = pixman_blt(surf->y_data, dst_y, 183 | surf->pixbuf->pitch / 4, destination_pitches[0] / 4, 184 | 8, 8, 185 | 0, 0, 186 | 0, 0, 187 | width, height); 188 | if (!ret) { 189 | ErrorMsg("pixman_blt failed\n"); 190 | } 191 | 192 | /* Copy chroma blue plane. */ 193 | ret = pixman_blt(surf->cb_data, dst_cb, 194 | surf->pixbuf->pitch_uv / 4, destination_pitches[1] / 4, 195 | 8, 8, 196 | 0, 0, 197 | 0, 0, 198 | width / 2, height / 2); 199 | if (!ret) { 200 | ErrorMsg("pixman_blt failed\n"); 201 | } 202 | 203 | /* Copy chroma red plane. */ 204 | ret = pixman_blt(surf->cr_data, dst_cr, 205 | surf->pixbuf->pitch_uv / 4, destination_pitches[2] / 4, 206 | 8, 8, 207 | 0, 0, 208 | 0, 0, 209 | width / 2, height / 2); 210 | if (!ret) { 211 | ErrorMsg("pixman_blt failed\n"); 212 | } 213 | 214 | unmap_surface_data(surf); 215 | 216 | pthread_mutex_unlock(&surf->lock); 217 | put_surface(surf); 218 | 219 | return VDP_STATUS_OK; 220 | } 221 | 222 | VdpStatus vdp_video_surface_put_bits_y_cb_cr( 223 | VdpVideoSurface surface, 224 | VdpYCbCrFormat source_ycbcr_format, 225 | void const *const *source_data, 226 | uint32_t const *source_pitches) 227 | { 228 | tegra_surface *surf, *orig = get_surface_video(surface); 229 | void *src_y = (void *)source_data[0]; 230 | void *src_cr = (void *)source_data[1]; 231 | void *src_cb = (void *)source_data[2]; 232 | int width, height; 233 | int ret; 234 | 235 | if (orig == NULL) { 236 | return VDP_STATUS_INVALID_HANDLE; 237 | } 238 | 239 | assert(orig->flags & SURFACE_VIDEO); 240 | 241 | switch (source_ycbcr_format) { 242 | case VDP_YCBCR_FORMAT_YV12: 243 | break; 244 | default: 245 | put_surface(orig); 246 | return VDP_STATUS_NO_IMPLEMENTATION; 247 | } 248 | 249 | surf = shared_surface_swap_video(orig); 250 | 251 | if (orig != surf) { 252 | put_surface(orig); 253 | ref_surface(surf); 254 | } 255 | 256 | ret = map_surface_data(surf); 257 | if (ret) { 258 | put_surface(surf); 259 | return ret; 260 | } 261 | 262 | width = surf->width; 263 | height = surf->height; 264 | 265 | /* Copy luma plane. */ 266 | ret = pixman_blt(src_y, surf->y_data, 267 | source_pitches[0] / 4, surf->pixbuf->pitch / 4, 268 | 8, 8, 269 | 0, 0, 270 | 0, 0, 271 | width, height); 272 | if (!ret) { 273 | ErrorMsg("pixman_blt failed\n"); 274 | } 275 | 276 | /* Copy chroma blue plane. */ 277 | ret = pixman_blt(src_cb, surf->cb_data, 278 | source_pitches[1] / 4, surf->pixbuf->pitch_uv / 4, 279 | 8, 8, 280 | 0, 0, 281 | 0, 0, 282 | width / 2, height / 2); 283 | if (!ret) { 284 | ErrorMsg("pixman_blt failed\n"); 285 | } 286 | 287 | /* Copy chroma red plane. */ 288 | ret = pixman_blt(src_cr, surf->cr_data, 289 | source_pitches[2] / 4, surf->pixbuf->pitch_uv / 4, 290 | 8, 8, 291 | 0, 0, 292 | 0, 0, 293 | width / 2, height / 2); 294 | if (!ret) { 295 | ErrorMsg("pixman_blt failed\n"); 296 | } 297 | 298 | host1x_pixelbuffer_check_guard(surf->pixbuf); 299 | 300 | unmap_surface_data(surf); 301 | 302 | put_surface(surf); 303 | 304 | return VDP_STATUS_OK; 305 | } 306 | -------------------------------------------------------------------------------- /src/tegra_stream.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2017 Dmitry Osipenko 3 | * Copyright (C) 2012-2013 NVIDIA Corporation. 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the next 13 | * paragraph) shall be included in all copies or substantial portions of the 14 | * Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 | * IN THE SOFTWARE. 23 | * 24 | * Authors: 25 | * Arto Merilainen 26 | */ 27 | 28 | #ifndef TEGRA_STREAM_H_ 29 | #define TEGRA_STREAM_H_ 30 | 31 | #include 32 | #include 33 | #include 34 | 35 | #include "host1x.h" 36 | #include "opentegra_lib.h" 37 | 38 | #define TGR_STRM_ERROR_MSG(fmt, args...) \ 39 | fprintf(stderr, "%s:%d/%s(): " fmt, __FILE__, __LINE__, __func__, ##args) 40 | 41 | struct tegra_device; 42 | 43 | enum tegra_stream_status { 44 | TEGRADRM_STREAM_FREE, 45 | TEGRADRM_STREAM_CONSTRUCT, 46 | TEGRADRM_STREAM_CONSTRUCTION_FAILED, 47 | TEGRADRM_STREAM_READY, 48 | }; 49 | 50 | struct tegra_reloc { 51 | const void *addr; 52 | struct drm_tegra_bo *bo; 53 | uint32_t offset; 54 | unsigned var_offset; 55 | }; 56 | 57 | struct tegra_fence { 58 | void *opaque; 59 | int refcnt; 60 | bool gr2d; 61 | 62 | bool (*wait_fence)(struct tegra_fence *f); 63 | void (*free_fence)(struct tegra_fence *f); 64 | }; 65 | 66 | struct tegra_stream { 67 | struct drm_tegra_channel *channel; 68 | enum tegra_stream_status status; 69 | struct tegra_fence *last_fence; 70 | bool op_done_synced; 71 | uint32_t **buf_ptr; 72 | uint32_t class_id; 73 | bool tegra114; 74 | 75 | void (*destroy)(struct tegra_stream *stream); 76 | int (*begin)(struct tegra_stream *stream, 77 | struct drm_tegra_channel *channel); 78 | int (*end)(struct tegra_stream *stream); 79 | int (*cleanup)(struct tegra_stream *stream); 80 | int (*flush)(struct tegra_stream *stream); 81 | struct tegra_fence * (*submit)(struct tegra_stream *stream, bool gr2d); 82 | int (*push_reloc)(struct tegra_stream *stream, 83 | struct drm_tegra_bo *bo, 84 | unsigned offset); 85 | int (*push_words)(struct tegra_stream *stream, const void *addr, 86 | unsigned words, int num_relocs, ...); 87 | int (*prep)(struct tegra_stream *stream, uint32_t words); 88 | int (*sync)(struct tegra_stream *stream, 89 | enum drm_tegra_syncpt_cond cond, 90 | bool keep_class); 91 | }; 92 | 93 | /* Stream operations */ 94 | int tegra_stream_create_v1(struct tegra_stream **stream, 95 | struct tegra_device *tegra); 96 | 97 | int grate_stream_create_v2(struct tegra_stream **stream, 98 | struct tegra_device *tegra); 99 | 100 | static inline int tegra_stream_create(struct tegra_stream **stream, 101 | struct tegra_device *tegra, 102 | struct drm_tegra_channel *channel) 103 | { 104 | int ret; 105 | 106 | ret = grate_stream_create_v2(stream, tegra); 107 | if (ret) 108 | ret = tegra_stream_create_v1(stream, tegra); 109 | if (!ret) 110 | (*stream)->channel = channel; 111 | 112 | return ret; 113 | } 114 | 115 | static inline void tegra_stream_destroy(struct tegra_stream *stream) 116 | { 117 | if (!stream) 118 | return; 119 | 120 | return stream->destroy(stream); 121 | } 122 | 123 | static inline int tegra_stream_begin(struct tegra_stream *stream) 124 | { 125 | if (!(stream && stream->status == TEGRADRM_STREAM_FREE)) { 126 | TGR_STRM_ERROR_MSG("Stream status isn't FREE\n"); 127 | return -1; 128 | } 129 | 130 | return stream->begin(stream, stream->channel); 131 | } 132 | 133 | static inline int tegra_stream_end(struct tegra_stream *stream) 134 | { 135 | int ret; 136 | 137 | if (!(stream && stream->status == TEGRADRM_STREAM_CONSTRUCT)) { 138 | TGR_STRM_ERROR_MSG("Stream status isn't CONSTRUCT\n"); 139 | return -1; 140 | } 141 | 142 | ret = stream->end(stream); 143 | stream->buf_ptr = NULL; 144 | 145 | return ret; 146 | } 147 | 148 | static inline int tegra_stream_cleanup(struct tegra_stream *stream) 149 | { 150 | int ret; 151 | 152 | if (!stream) 153 | return -1; 154 | 155 | ret = stream->cleanup(stream); 156 | stream->buf_ptr = NULL; 157 | 158 | return ret; 159 | } 160 | 161 | static inline int tegra_stream_flush(struct tegra_stream *stream) 162 | { 163 | if (!stream) 164 | return -1; 165 | 166 | return stream->flush(stream); 167 | } 168 | 169 | static inline struct tegra_fence * 170 | tegra_stream_submit(struct tegra_stream *stream, bool gr2d) 171 | { 172 | if (!stream) 173 | return NULL; 174 | 175 | return stream->submit(stream, gr2d); 176 | } 177 | 178 | static inline struct tegra_fence * 179 | tegra_stream_ref_fence(struct tegra_fence *f, void *opaque) 180 | { 181 | if (f) { 182 | f->opaque = opaque; 183 | f->refcnt++; 184 | } 185 | 186 | return f; 187 | } 188 | 189 | static inline struct tegra_fence * 190 | tegra_stream_get_last_fence(struct tegra_stream *stream) 191 | { 192 | if (stream->last_fence) 193 | return tegra_stream_ref_fence(stream->last_fence, 194 | stream->last_fence->opaque); 195 | 196 | return NULL; 197 | } 198 | 199 | static inline bool tegra_stream_wait_fence(struct tegra_fence *f) 200 | { 201 | if (f) 202 | return f->wait_fence(f); 203 | 204 | return false; 205 | } 206 | 207 | static inline void tegra_stream_put_fence(struct tegra_fence *f) 208 | { 209 | if (f) { 210 | if (f->refcnt < 0) { 211 | TGR_STRM_ERROR_MSG("BUG: fence refcount underflow\n"); 212 | return; 213 | } 214 | 215 | if (f->refcnt > 10) { 216 | TGR_STRM_ERROR_MSG("BUG: fence refcount overflow\n"); 217 | return; 218 | } 219 | 220 | if (--f->refcnt == -1) 221 | f->free_fence(f); 222 | } 223 | } 224 | 225 | static inline int 226 | tegra_stream_push_reloc(struct tegra_stream *stream, 227 | struct drm_tegra_bo *bo, 228 | unsigned offset) 229 | { 230 | if (!(stream && stream->status == TEGRADRM_STREAM_CONSTRUCT)) { 231 | TGR_STRM_ERROR_MSG("Stream status isn't CONSTRUCT\n"); 232 | return -1; 233 | } 234 | 235 | return stream->push_reloc(stream, bo, offset); 236 | } 237 | 238 | static inline int tegra_stream_push_words(struct tegra_stream *stream, 239 | const void *addr, 240 | unsigned words, 241 | int num_relocs, 242 | ...) 243 | { 244 | va_list args; 245 | int ret; 246 | 247 | if (!(stream && stream->status == TEGRADRM_STREAM_CONSTRUCT)) { 248 | TGR_STRM_ERROR_MSG("Stream status isn't CONSTRUCT\n"); 249 | return -1; 250 | } 251 | 252 | va_start(args, num_relocs); 253 | ret = stream->push_words(stream, addr, words, num_relocs, args); 254 | va_end(args); 255 | 256 | return ret; 257 | } 258 | 259 | static inline int 260 | tegra_stream_prep(struct tegra_stream *stream, uint32_t words) 261 | { 262 | if (!(stream && stream->status == TEGRADRM_STREAM_CONSTRUCT)) { 263 | TGR_STRM_ERROR_MSG("Stream status isn't CONSTRUCT\n"); 264 | return -1; 265 | } 266 | 267 | return stream->prep(stream, words); 268 | } 269 | 270 | static inline int tegra_stream_sync(struct tegra_stream *stream, 271 | enum drm_tegra_syncpt_cond cond, 272 | bool keep_class) 273 | { 274 | if (!(stream && stream->status == TEGRADRM_STREAM_CONSTRUCT)) { 275 | TGR_STRM_ERROR_MSG("Stream status isn't CONSTRUCT\n"); 276 | return -1; 277 | } 278 | 279 | return stream->sync(stream, cond, keep_class); 280 | } 281 | 282 | static inline int 283 | tegra_stream_push(struct tegra_stream *stream, uint32_t word) 284 | { 285 | if (!(stream && stream->status == TEGRADRM_STREAM_CONSTRUCT)) 286 | return -1; 287 | 288 | *(*stream->buf_ptr)++ = word; 289 | stream->op_done_synced = false; 290 | 291 | return 0; 292 | } 293 | 294 | static inline int 295 | tegra_stream_pushf(struct tegra_stream *stream, float f) 296 | { 297 | union { 298 | uint32_t u; 299 | float f; 300 | } value; 301 | 302 | value.f = f; 303 | 304 | return tegra_stream_push(stream, value.u); 305 | } 306 | 307 | static inline int 308 | tegra_stream_push_setclass(struct tegra_stream *stream, unsigned class_id) 309 | { 310 | int result; 311 | 312 | if (stream->class_id == class_id) 313 | return 0; 314 | 315 | result = tegra_stream_push(stream, HOST1X_OPCODE_SETCL(0, class_id, 0)); 316 | 317 | if (result == 0) 318 | stream->class_id = class_id; 319 | 320 | return result; 321 | } 322 | 323 | static inline struct tegra_reloc 324 | tegra_reloc(const void *var_ptr, struct drm_tegra_bo *bo, 325 | uint32_t offset, uint32_t var_offset) 326 | { 327 | struct tegra_reloc reloc = {var_ptr, bo, offset, var_offset}; 328 | return reloc; 329 | } 330 | 331 | #endif 332 | -------------------------------------------------------------------------------- /src/tegradrm/atomic.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | * 23 | * Authors: 24 | * Chris Wilson 25 | * 26 | */ 27 | 28 | #ifndef _ATOMICS_H 29 | #define _ATOMICS_H 30 | 31 | typedef struct { 32 | int atomic; 33 | } atomic_t; 34 | 35 | #define atomic_read(x) ((x)->atomic) 36 | #define atomic_set(x, val) ((x)->atomic = (val)) 37 | #define atomic_inc(x) ((void) __sync_fetch_and_add (&(x)->atomic, 1)) 38 | #define atomic_inc_return(x) (__sync_add_and_fetch (&(x)->atomic, 1)) 39 | #define atomic_dec_and_test(x) (__sync_add_and_fetch (&(x)->atomic, -1) == 0) 40 | #define atomic_add(x, v) ((void) __sync_add_and_fetch(&(x)->atomic, (v))) 41 | #define atomic_dec(x, v) ((void) __sync_sub_and_fetch(&(x)->atomic, (v))) 42 | #define atomic_cmpxchg(x, oldv, newv) __sync_val_compare_and_swap (&(x)->atomic, oldv, newv) 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /src/tegradrm/lists.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * 3 | * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND. USA. 4 | * All Rights Reserved. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a 7 | * copy of this software and associated documentation files (the 8 | * "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sub license, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 17 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 18 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | * 22 | * The above copyright notice and this permission notice (including the 23 | * next paragraph) shall be included in all copies or substantial portions 24 | * of the Software. 25 | */ 26 | 27 | /* 28 | * List macros heavily inspired by the Linux kernel 29 | * list handling. No list looping yet. 30 | */ 31 | 32 | #include 33 | 34 | typedef struct _drmMMListHead 35 | { 36 | struct _drmMMListHead *prev; 37 | struct _drmMMListHead *next; 38 | } drmMMListHead; 39 | 40 | #define DRMINITLISTHEAD(__item) \ 41 | do{ \ 42 | (__item)->prev = (__item); \ 43 | (__item)->next = (__item); \ 44 | } while (0) 45 | 46 | #define DRMLISTADD(__item, __list) \ 47 | do { \ 48 | (__item)->prev = (__list); \ 49 | (__item)->next = (__list)->next; \ 50 | (__list)->next->prev = (__item); \ 51 | (__list)->next = (__item); \ 52 | } while (0) 53 | 54 | #define DRMLISTADDTAIL(__item, __list) \ 55 | do { \ 56 | (__item)->next = (__list); \ 57 | (__item)->prev = (__list)->prev; \ 58 | (__list)->prev->next = (__item); \ 59 | (__list)->prev = (__item); \ 60 | } while(0) 61 | 62 | #define DRMLISTDEL(__item) \ 63 | do { \ 64 | (__item)->prev->next = (__item)->next; \ 65 | (__item)->next->prev = (__item)->prev; \ 66 | } while(0) 67 | 68 | #define DRMLISTDELINIT(__item) \ 69 | do { \ 70 | (__item)->prev->next = (__item)->next; \ 71 | (__item)->next->prev = (__item)->prev; \ 72 | (__item)->next = (__item); \ 73 | (__item)->prev = (__item); \ 74 | } while(0) 75 | 76 | #define DRMLISTENTRY(__type, __item, __field) \ 77 | ((__type *)(((char *) (__item)) - offsetof(__type, __field))) 78 | 79 | #define DRMLISTEMPTY(__item) ((__item)->next == (__item)) 80 | 81 | #define DRMLISTSINGLE(__list) \ 82 | (!DRMLISTEMPTY(__list) && ((__list)->next == (__list)->prev)) 83 | 84 | #define DRMLISTFOREACH(__item, __list) \ 85 | for ((__item) = (__list)->next; \ 86 | (__item) != (__list); (__item) = (__item)->next) 87 | 88 | #define DRMLISTFOREACHSAFE(__item, __temp, __list) \ 89 | for ((__item) = (__list)->next, (__temp) = (__item)->next; \ 90 | (__item) != (__list); \ 91 | (__item) = (__temp), (__temp) = (__item)->next) 92 | 93 | #define DRMLISTFOREACHSAFEREVERSE(__item, __temp, __list) \ 94 | for ((__item) = (__list)->prev, (__temp) = (__item)->prev; \ 95 | (__item) != (__list); \ 96 | (__item) = (__temp), (__temp) = (__item)->prev) 97 | 98 | #define DRMLISTFOREACHENTRY(__item, __list, __head) \ 99 | for ((__item) = DRMLISTENTRY(typeof(*__item), (__list)->next, __head); \ 100 | &(__item)->__head != (__list); \ 101 | (__item) = DRMLISTENTRY(typeof(*__item), \ 102 | (__item)->__head.next, __head)) 103 | 104 | #define DRMLISTFOREACHENTRYSAFE(__item, __temp, __list, __head) \ 105 | for ((__item) = DRMLISTENTRY(typeof(*__item), (__list)->next, __head), \ 106 | (__temp) = DRMLISTENTRY(typeof(*__item), \ 107 | (__item)->__head.next, __head); \ 108 | &(__item)->__head != (__list); \ 109 | (__item) = (__temp), \ 110 | (__temp) = DRMLISTENTRY(typeof(*__item), \ 111 | (__temp)->__head.next, __head)) 112 | 113 | #define DRMLISTJOIN(__list, __join) if (!DRMLISTEMPTY(__list)) { \ 114 | (__list)->next->prev = (__join); \ 115 | (__list)->prev->next = (__join)->next; \ 116 | (__join)->next->prev = (__list)->prev; \ 117 | (__join)->next = (__list)->next; \ 118 | } 119 | -------------------------------------------------------------------------------- /src/tegradrm/opentegra_lib.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012, 2013 Thierry Reding 3 | * Copyright © 2013 Erik Faye-Lund 4 | * Copyright © 2014 NVIDIA Corporation 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a 7 | * copy of this software and associated documentation files (the "Software"), 8 | * to deal in the Software without restriction, including without limitation 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the 11 | * Software is furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | * OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | #ifndef __DRM_OPENTEGRA_H__ 26 | #define __DRM_OPENTEGRA_H__ 1 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | #include "opentegra_drm.h" 33 | 34 | #ifndef __maybe_unused 35 | #define __maybe_unused __attribute__((unused)) 36 | #endif 37 | 38 | enum drm_tegra_class { 39 | DRM_TEGRA_GR2D, 40 | DRM_TEGRA_GR3D, 41 | }; 42 | 43 | enum drm_tegra_soc_id { 44 | DRM_TEGRA_INVALID_SOC, 45 | DRM_TEGRA_UNKOWN_SOC, 46 | DRM_TEGRA20_SOC, 47 | DRM_TEGRA30_SOC, 48 | DRM_TEGRA114_SOC, 49 | }; 50 | 51 | static __maybe_unused const char * const drm_tegra_soc_names[] = { 52 | [DRM_TEGRA_INVALID_SOC] = "invalid", 53 | [DRM_TEGRA_UNKOWN_SOC] = "unknown", 54 | [DRM_TEGRA20_SOC] = "Tegra20", 55 | [DRM_TEGRA30_SOC] = "Tegra30", 56 | [DRM_TEGRA114_SOC] = "Tegra114", 57 | }; 58 | 59 | struct drm_tegra_bo; 60 | struct drm_tegra; 61 | 62 | int drm_tegra_new(struct drm_tegra **drmp, int fd); 63 | void drm_tegra_close(struct drm_tegra *drm); 64 | 65 | int drm_tegra_version(struct drm_tegra *drm); 66 | 67 | enum drm_tegra_soc_id drm_tegra_get_soc_id(struct drm_tegra *drm); 68 | 69 | int drm_tegra_bo_new(struct drm_tegra_bo **bop, struct drm_tegra *drm, 70 | uint32_t flags, uint32_t size); 71 | int drm_tegra_bo_wrap(struct drm_tegra_bo **bop, struct drm_tegra *drm, 72 | uint32_t handle, uint32_t flags, uint32_t size); 73 | struct drm_tegra_bo *drm_tegra_bo_ref(struct drm_tegra_bo *bo); 74 | int drm_tegra_bo_unref(struct drm_tegra_bo *bo); 75 | int drm_tegra_bo_get_handle(struct drm_tegra_bo *bo, uint32_t *handle); 76 | int drm_tegra_bo_map(struct drm_tegra_bo *bo, void **ptr); 77 | int drm_tegra_bo_unmap(struct drm_tegra_bo *bo); 78 | 79 | int drm_tegra_bo_get_flags(struct drm_tegra_bo *bo, uint32_t *flags); 80 | int drm_tegra_bo_set_flags(struct drm_tegra_bo *bo, uint32_t flags); 81 | 82 | struct drm_tegra_bo_tiling { 83 | uint32_t mode; 84 | uint32_t value; 85 | }; 86 | 87 | int drm_tegra_bo_get_tiling(struct drm_tegra_bo *bo, 88 | struct drm_tegra_bo_tiling *tiling); 89 | int drm_tegra_bo_set_tiling(struct drm_tegra_bo *bo, 90 | const struct drm_tegra_bo_tiling *tiling); 91 | 92 | int drm_tegra_bo_get_name(struct drm_tegra_bo *bo, uint32_t *name); 93 | int drm_tegra_bo_from_name(struct drm_tegra_bo **bop, struct drm_tegra *drm, 94 | uint32_t name, uint32_t flags); 95 | 96 | int drm_tegra_bo_to_dmabuf(struct drm_tegra_bo *bo, uint32_t *handle); 97 | int drm_tegra_bo_from_dmabuf(struct drm_tegra_bo **bop, struct drm_tegra *drm, 98 | int fd, uint32_t flags); 99 | 100 | int drm_tegra_bo_get_size(struct drm_tegra_bo *bo, uint32_t *size); 101 | int drm_tegra_bo_forbid_caching(struct drm_tegra_bo *bo); 102 | int drm_tegra_bo_cpu_prep(struct drm_tegra_bo *bo, 103 | uint32_t flags, uint32_t timeout_us); 104 | 105 | struct drm_tegra_channel; 106 | struct drm_tegra_job; 107 | 108 | struct drm_tegra_pushbuf { 109 | uint32_t *ptr; 110 | }; 111 | 112 | struct drm_tegra_fence; 113 | 114 | enum drm_tegra_syncpt_cond { 115 | DRM_TEGRA_SYNCPT_COND_IMMEDIATE, 116 | DRM_TEGRA_SYNCPT_COND_OP_DONE, 117 | DRM_TEGRA_SYNCPT_COND_RD_DONE, 118 | DRM_TEGRA_SYNCPT_COND_WR_SAFE, 119 | DRM_TEGRA_SYNCPT_COND_MAX, 120 | }; 121 | 122 | int drm_tegra_channel_open(struct drm_tegra_channel **channelp, 123 | struct drm_tegra *drm, 124 | enum drm_tegra_class client); 125 | int drm_tegra_channel_close(struct drm_tegra_channel *channel); 126 | 127 | int drm_tegra_job_new(struct drm_tegra_job **jobp, 128 | struct drm_tegra_channel *channel); 129 | int drm_tegra_job_free(struct drm_tegra_job *job); 130 | int drm_tegra_job_submit(struct drm_tegra_job *job, 131 | struct drm_tegra_fence **fencep); 132 | 133 | int drm_tegra_pushbuf_new(struct drm_tegra_pushbuf **pushbufp, 134 | struct drm_tegra_job *job); 135 | int drm_tegra_pushbuf_free(struct drm_tegra_pushbuf *pushbuf); 136 | int drm_tegra_pushbuf_prepare(struct drm_tegra_pushbuf *pushbuf, 137 | unsigned int words); 138 | int drm_tegra_pushbuf_relocate(struct drm_tegra_pushbuf *pushbuf, 139 | struct drm_tegra_bo *target, 140 | unsigned long offset, 141 | unsigned long shift); 142 | int drm_tegra_pushbuf_sync(struct drm_tegra_pushbuf *pushbuf, 143 | enum drm_tegra_syncpt_cond cond); 144 | 145 | int drm_tegra_fence_wait_timeout(struct drm_tegra_fence *fence, 146 | unsigned long timeout); 147 | void drm_tegra_fence_free(struct drm_tegra_fence *fence); 148 | 149 | static inline int drm_tegra_fence_wait(struct drm_tegra_fence *fence) 150 | { 151 | return drm_tegra_fence_wait_timeout(fence, -1); 152 | } 153 | 154 | struct drm_tegra_job_v2 { 155 | struct drm_tegra *drm; 156 | struct drm_tegra_bo_table_entry *bo_table; 157 | unsigned int num_bos; 158 | unsigned int num_bos_max; 159 | unsigned int num_words; 160 | uint32_t *start; 161 | uint32_t *ptr; 162 | }; 163 | 164 | int drm_tegra_job_new_v2(struct drm_tegra_job_v2 **jobp, 165 | struct drm_tegra *drm, 166 | unsigned int num_bos_expected, 167 | unsigned int num_words_expected); 168 | int drm_tegra_job_resize_v2(struct drm_tegra_job_v2 *job, 169 | unsigned int num_words, 170 | unsigned int num_bos, 171 | bool reallocate); 172 | int drm_tegra_job_reset_v2(struct drm_tegra_job_v2 *job); 173 | int drm_tegra_job_free_v2(struct drm_tegra_job_v2 *job); 174 | int drm_tegra_job_push_reloc_v2(struct drm_tegra_job_v2 *job, 175 | struct drm_tegra_bo *target, 176 | unsigned long offset, 177 | uint32_t flags); 178 | int drm_tegra_job_submit_v2(struct drm_tegra_job_v2 *job, 179 | uint32_t syncobj_handle, 180 | uint64_t pipes_mask); 181 | 182 | #endif /* __DRM_TEGRA_H__ */ 183 | -------------------------------------------------------------------------------- /src/tegradrm/private.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012, 2013 Thierry Reding 3 | * Copyright © 2013 Erik Faye-Lund 4 | * Copyright © 2014 NVIDIA Corporation 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a 7 | * copy of this software and associated documentation files (the "Software"), 8 | * to deal in the Software without restriction, including without limitation 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the 11 | * Software is furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | * OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | #ifndef __DRM_TEGRA_PRIVATE_H__ 26 | #define __DRM_TEGRA_PRIVATE_H__ 1 27 | 28 | #ifdef HAVE_CONFIG_H 29 | #include "config.h" 30 | #endif 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #include 40 | 41 | #include "atomic.h" 42 | #include "lists.h" 43 | #include "opentegra_lib.h" 44 | 45 | #define container_of(ptr, type, member) ({ \ 46 | const typeof(((type *)0)->member) *__mptr = (ptr); \ 47 | (type *)((char *)__mptr - offsetof(type, member)); \ 48 | }) 49 | 50 | #define align(offset, align) \ 51 | (((offset) + (align) - 1) & ~((align) - 1)) 52 | 53 | #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) 54 | 55 | #ifndef NDEBUG 56 | #define VDBG_DRM(DRM, FMT, args...) do { \ 57 | if (DRM->debug_bo) \ 58 | fprintf(stderr, "%s: %d: " FMT, \ 59 | __func__, __LINE__, ##args); \ 60 | } while (0) 61 | 62 | #define DBG_BO_STATS(DRM) do { \ 63 | if (DRM->debug_bo) \ 64 | fprintf(stderr, \ 65 | "%s: %d:\tstats: " \ 66 | "total BOs allocated %d (%dKB, " \ 67 | "%d BOs cached %dKB) " \ 68 | "total BOs mapped %d (%d pages, " \ 69 | "%d pages cached of %d BOs)\n", \ 70 | __func__, __LINE__, \ 71 | drm->debug_bos_allocated, \ 72 | drm->debug_bos_total_size / 1000, \ 73 | drm->debug_bos_cached, \ 74 | drm->debug_bos_cached_size / 1000, \ 75 | drm->debug_bos_mapped, \ 76 | drm->debug_bos_total_pages, \ 77 | drm->debug_bos_cached_pages, \ 78 | drm->debug_bos_mappings_cached); \ 79 | } while (0) 80 | 81 | #define VDBG_BO(BO, FMT, args...) do { \ 82 | if (BO->drm->debug_bo) \ 83 | fprintf(stderr, \ 84 | "%s: %d:\tBO %p size %u handle %u name %u " \ 85 | "flags 0x%08X refcnt %d map %p mmap_ref %u " \ 86 | "map_cached %p: " \ 87 | FMT, \ 88 | __func__, __LINE__, BO, BO->size, BO->handle, \ 89 | BO->name, BO->flags, atomic_read(&BO->ref), \ 90 | BO->map, BO->mmap_ref, BO->map_cached, \ 91 | ##args); \ 92 | } while (0) 93 | 94 | #define DBG_BO(BO, FMT) VDBG_BO(BO, FMT "%s", "") 95 | #else 96 | #define VDBG_DRM(DRM, FMT, ...) do {} while (0) 97 | #define DBG_BO_STATS(DRM) do {} while (0) 98 | #define VDBG_BO(BO, FMT, ...) do {} while (0) 99 | #define DBG_BO(BO, FMT) do {} while (0) 100 | #endif 101 | 102 | enum host1x_class { 103 | HOST1X_CLASS_HOST1X = 0x01, 104 | HOST1X_CLASS_GR2D = 0x51, 105 | HOST1X_CLASS_GR2D_SB = 0x52, 106 | HOST1X_CLASS_GR3D = 0x60, 107 | }; 108 | 109 | struct drm_tegra_bo_bucket { 110 | uint32_t size; 111 | drmMMListHead list; 112 | uint32_t num_entries; 113 | uint32_t num_mmap_entries; 114 | bool sparse; 115 | }; 116 | 117 | struct drm_tegra_bo_cache { 118 | struct drm_tegra_bo_bucket cache_bucket[14 * 4 * 2]; 119 | int num_buckets; 120 | time_t time; 121 | }; 122 | 123 | struct drm_tegra_bo_mmap_cache { 124 | drmMMListHead list; 125 | time_t time; 126 | }; 127 | 128 | struct drm_tegra { 129 | uint32_t version; 130 | 131 | /* tables to keep track of bo's, to avoid "evil-twin" buffer objects: 132 | * 133 | * handle_table: maps handle to fd_bo 134 | * name_table: maps flink name to fd_bo 135 | * 136 | * We end up needing two tables, because DRM_IOCTL_GEM_OPEN always 137 | * returns a new handle. So we need to figure out if the bo is already 138 | * open in the process first, before calling gem-open. 139 | */ 140 | void *handle_table, *name_table; 141 | 142 | struct drm_tegra_bo_cache bo_cache; 143 | struct drm_tegra_bo_mmap_cache mmap_cache; 144 | bool close; 145 | int fd; 146 | 147 | #ifndef NDEBUG 148 | bool debug_bo; 149 | bool debug_bo_back_guard; 150 | bool debug_bo_front_guard; 151 | int32_t debug_bos_allocated; 152 | int32_t debug_bos_total_size; 153 | int32_t debug_bos_cached; 154 | int32_t debug_bos_cached_size; 155 | int32_t debug_bos_mapped; 156 | int32_t debug_bos_total_pages; 157 | int32_t debug_bos_cached_pages; 158 | int32_t debug_bos_mappings_cached; 159 | #endif 160 | }; 161 | 162 | struct drm_tegra_bo { 163 | struct drm_tegra *drm; 164 | drmMMListHead push_list; 165 | uint32_t offset; 166 | uint32_t handle; 167 | uint32_t flags; 168 | uint32_t size; 169 | uint32_t name; 170 | atomic_t ref; 171 | uint32_t mmap_ref; 172 | int dmabuf_fd; 173 | void *map; 174 | 175 | #if HAVE_VALGRIND 176 | void *map_vg; 177 | #endif 178 | 179 | bool reuse; 180 | /* 181 | * Cache-accessible fields must be at the end of structure 182 | * due to protection of the rest of the fields by valgrind. 183 | */ 184 | drmMMListHead bo_list; /* bucket-list entry */ 185 | time_t free_time; /* time when added to bucket-list */ 186 | 187 | drmMMListHead mmap_list; /* mmap cache-list entry */ 188 | time_t unmap_time; /* time when added to cache-list */ 189 | void *map_cached; /* holds cached mmap pointer */ 190 | 191 | bool custom_tiling; 192 | 193 | #ifndef NDEBUG 194 | uint32_t debug_size; 195 | 196 | uint64_t *guard_front; 197 | uint64_t *guard_back; 198 | #endif 199 | }; 200 | 201 | int drm_tegra_bo_free(struct drm_tegra_bo *bo); 202 | int __drm_tegra_bo_map(struct drm_tegra_bo *bo, void **ptr); 203 | 204 | void drm_tegra_bo_cache_init(struct drm_tegra_bo_cache *cache, 205 | bool coarse, bool sparse); 206 | void drm_tegra_bo_cache_cleanup(struct drm_tegra *drm, time_t time); 207 | struct drm_tegra_bo * drm_tegra_bo_cache_alloc(struct drm_tegra *drm, 208 | uint32_t *size, uint32_t flags); 209 | int drm_tegra_bo_cache_free(struct drm_tegra_bo *bo); 210 | void drm_tegra_bo_cache_unmap(struct drm_tegra_bo *bo); 211 | void *drm_tegra_bo_cache_map(struct drm_tegra_bo *bo); 212 | 213 | struct drm_tegra_bo_bucket * 214 | drm_tegra_get_bucket(struct drm_tegra *drm, uint32_t size, uint32_t flags); 215 | 216 | void drm_tegra_reset_bo(struct drm_tegra_bo *bo, uint32_t flags, 217 | bool set_flags); 218 | 219 | #if HAVE_VALGRIND 220 | # include 221 | 222 | /* 223 | * For tracking the backing memory (if valgrind enabled, we force a mmap 224 | * for the purposes of tracking) 225 | */ 226 | static void __attribute__((unused)) VG_BO_ALLOC(struct drm_tegra_bo *bo) 227 | { 228 | if (RUNNING_ON_VALGRIND) { 229 | __drm_tegra_bo_map(bo, &bo->map_vg); 230 | VALGRIND_MALLOCLIKE_BLOCK(bo->map_vg, bo->size, 0, 1); 231 | VALGRIND_FREELIKE_BLOCK(bo->map_vg, 0); 232 | DBG_BO(bo, "\n"); 233 | } 234 | } 235 | 236 | static void __attribute__((unused)) VG_BO_FREE(struct drm_tegra_bo *bo) 237 | { 238 | if (RUNNING_ON_VALGRIND) { 239 | munmap(bo->map_vg, bo->size); 240 | DBG_BO(bo, "\n"); 241 | } 242 | } 243 | 244 | /* 245 | * For tracking bo structs that are in the buffer-cache, so that valgrind 246 | * doesn't attribute ownership to the first one to allocate the recycled 247 | * bo. 248 | * 249 | * Note that the bo_list in drm_tegra_bo is used to track the buffers in cache 250 | * so disable error reporting on the range while they are in cache so 251 | * valgrind doesn't squawk about list traversal. 252 | * 253 | */ 254 | static void __attribute__((unused)) VG_BO_RELEASE(struct drm_tegra_bo *bo) 255 | { 256 | if (RUNNING_ON_VALGRIND) { 257 | DBG_BO(bo, "\n"); 258 | 259 | /* 260 | * Disable access in case of an unbalanced BO mmappings to 261 | * simulate the unmap that we perform on BO freeing and 262 | * avoid double freelike marking that would be reported 263 | * by valgrind. 264 | */ 265 | if (bo->map) 266 | VALGRIND_FREELIKE_BLOCK(bo->map_vg, 0); 267 | /* 268 | * Nothing should touch BO now, disable BO memory accesses 269 | * to catch them in valgrind, but leave cache related stuff 270 | * accessible. 271 | */ 272 | VALGRIND_MAKE_MEM_NOACCESS(bo, offsetof(typeof(*bo), bo_list)); 273 | } 274 | } 275 | static void __attribute__((unused)) VG_BO_OBTAIN(struct drm_tegra_bo *bo) 276 | { 277 | if (RUNNING_ON_VALGRIND) { 278 | /* restore BO memory accesses in valgrind */ 279 | VALGRIND_MAKE_MEM_DEFINED(bo, offsetof(typeof(*bo), bo_list)); 280 | 281 | if (bo->map) 282 | VALGRIND_MALLOCLIKE_BLOCK(bo->map_vg, bo->size, 0, 1); 283 | 284 | DBG_BO(bo, "\n"); 285 | } 286 | } 287 | 288 | /* 289 | * Since we don't really unmap BO under valgrind, we need to mark the 290 | * mapped region as freed on BO unmapping in order to catch invalid 291 | * memory accesses. 292 | */ 293 | static void __attribute__((unused)) VG_BO_MMAP(struct drm_tegra_bo *bo) 294 | { 295 | if (RUNNING_ON_VALGRIND) 296 | VALGRIND_MALLOCLIKE_BLOCK(bo->map_vg, bo->size, 0, 1); 297 | } 298 | static void __attribute__((unused)) VG_BO_UNMMAP(struct drm_tegra_bo *bo) 299 | { 300 | if (RUNNING_ON_VALGRIND) 301 | VALGRIND_FREELIKE_BLOCK(bo->map_vg, 0); 302 | } 303 | #else 304 | static inline void VG_BO_ALLOC(struct drm_tegra_bo *bo) {} 305 | static inline void VG_BO_FREE(struct drm_tegra_bo *bo) {} 306 | static inline void VG_BO_RELEASE(struct drm_tegra_bo *bo) {} 307 | static inline void VG_BO_OBTAIN(struct drm_tegra_bo *bo) {} 308 | static inline void VG_BO_MMAP(struct drm_tegra_bo *bo) {} 309 | static inline void VG_BO_UNMMAP(struct drm_tegra_bo *bo) {} 310 | #define RUNNING_ON_VALGRIND 0 311 | #endif 312 | 313 | #endif /* __DRM_TEGRA_PRIVATE_H__ */ 314 | -------------------------------------------------------------------------------- /src/tegradrm/uapi_v1/channel.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012, 2013 Thierry Reding 3 | * Copyright © 2013 Erik Faye-Lund 4 | * Copyright © 2014 NVIDIA Corporation 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a 7 | * copy of this software and associated documentation files (the "Software"), 8 | * to deal in the Software without restriction, including without limitation 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the 11 | * Software is furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | * OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | #ifdef HAVE_CONFIG_H 26 | # include "config.h" 27 | #endif 28 | 29 | #include 30 | #include 31 | 32 | #include 33 | 34 | #include "uapi_v1.h" 35 | 36 | static int drm_tegra_channel_setup(struct drm_tegra_channel *channel) 37 | { 38 | struct drm_tegra *drm = channel->drm; 39 | struct drm_tegra_get_syncpt args; 40 | int err; 41 | 42 | memset(&args, 0, sizeof(args)); 43 | args.context = channel->context; 44 | args.index = 0; 45 | 46 | err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GET_SYNCPT, &args, 47 | sizeof(args)); 48 | if (err < 0) 49 | return err; 50 | 51 | channel->syncpt = args.id; 52 | 53 | return 0; 54 | } 55 | 56 | int drm_tegra_channel_open(struct drm_tegra_channel **channelp, 57 | struct drm_tegra *drm, 58 | enum drm_tegra_class client) 59 | { 60 | struct drm_tegra_open_channel args; 61 | struct drm_tegra_channel *channel; 62 | enum host1x_class class; 63 | int err; 64 | 65 | if (!channelp || !drm) 66 | return -EINVAL; 67 | 68 | switch (client) { 69 | case DRM_TEGRA_GR2D: 70 | class = HOST1X_CLASS_GR2D; 71 | break; 72 | 73 | case DRM_TEGRA_GR3D: 74 | class = HOST1X_CLASS_GR3D; 75 | break; 76 | 77 | default: 78 | return -EINVAL; 79 | } 80 | 81 | channel = calloc(1, sizeof(*channel)); 82 | if (!channel) 83 | return -ENOMEM; 84 | 85 | channel->drm = drm; 86 | 87 | memset(&args, 0, sizeof(args)); 88 | args.client = class; 89 | 90 | err = drmCommandWriteRead(drm->fd, DRM_TEGRA_OPEN_CHANNEL, &args, 91 | sizeof(args)); 92 | if (err < 0) { 93 | free(channel); 94 | return err; 95 | } 96 | 97 | channel->context = args.context; 98 | channel->class = class; 99 | 100 | err = drm_tegra_channel_setup(channel); 101 | if (err < 0) { 102 | free(channel); 103 | return err; 104 | } 105 | 106 | *channelp = channel; 107 | 108 | return 0; 109 | } 110 | 111 | int drm_tegra_channel_close(struct drm_tegra_channel *channel) 112 | { 113 | struct drm_tegra_close_channel args; 114 | struct drm_tegra *drm; 115 | int err; 116 | 117 | if (!channel) 118 | return -EINVAL; 119 | 120 | drm = channel->drm; 121 | 122 | memset(&args, 0, sizeof(args)); 123 | args.context = channel->context; 124 | 125 | err = drmCommandWriteRead(drm->fd, DRM_TEGRA_CLOSE_CHANNEL, &args, 126 | sizeof(args)); 127 | if (err < 0) 128 | return err; 129 | 130 | free(channel); 131 | 132 | return 0; 133 | } 134 | -------------------------------------------------------------------------------- /src/tegradrm/uapi_v1/fence.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012, 2013 Thierry Reding 3 | * Copyright © 2013 Erik Faye-Lund 4 | * Copyright © 2014 NVIDIA Corporation 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a 7 | * copy of this software and associated documentation files (the "Software"), 8 | * to deal in the Software without restriction, including without limitation 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the 11 | * Software is furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | * OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | #ifdef HAVE_CONFIG_H 26 | # include "config.h" 27 | #endif 28 | 29 | #include 30 | #include 31 | 32 | #include 33 | 34 | #include "uapi_v1.h" 35 | 36 | int drm_tegra_fence_wait_timeout(struct drm_tegra_fence *fence, 37 | unsigned long timeout) 38 | { 39 | struct drm_tegra_syncpt_wait args; 40 | 41 | if (!fence) 42 | return -EINVAL; 43 | 44 | memset(&args, 0, sizeof(args)); 45 | args.id = fence->syncpt; 46 | args.thresh = fence->value; 47 | args.timeout = timeout; 48 | 49 | return drmCommandWriteRead(fence->drm->fd, DRM_TEGRA_SYNCPT_WAIT, 50 | &args, sizeof(args)); 51 | } 52 | 53 | void drm_tegra_fence_free(struct drm_tegra_fence *fence) 54 | { 55 | free(fence); 56 | } 57 | -------------------------------------------------------------------------------- /src/tegradrm/uapi_v1/job.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012, 2013 Thierry Reding 3 | * Copyright © 2013 Erik Faye-Lund 4 | * Copyright © 2014 NVIDIA Corporation 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a 7 | * copy of this software and associated documentation files (the "Software"), 8 | * to deal in the Software without restriction, including without limitation 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the 11 | * Software is furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | * OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | #ifdef HAVE_CONFIG_H 26 | # include "config.h" 27 | #endif 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | #include 34 | 35 | #include "uapi_v1.h" 36 | 37 | int drm_tegra_job_add_reloc(struct drm_tegra_job *job, 38 | const struct drm_tegra_reloc *reloc) 39 | { 40 | struct drm_tegra_reloc *relocs; 41 | size_t size; 42 | 43 | size = (job->num_relocs + 1) * sizeof(*reloc); 44 | 45 | relocs = realloc(job->relocs, size); 46 | if (!relocs) 47 | return -ENOMEM; 48 | 49 | job->relocs = relocs; 50 | 51 | job->relocs[job->num_relocs++] = *reloc; 52 | 53 | return 0; 54 | } 55 | 56 | int drm_tegra_job_add_cmdbuf(struct drm_tegra_job *job, 57 | const struct drm_tegra_cmdbuf *cmdbuf) 58 | { 59 | struct drm_tegra_cmdbuf *cmdbufs; 60 | size_t size; 61 | 62 | size = (job->num_cmdbufs + 1) * sizeof(*cmdbuf); 63 | 64 | cmdbufs = realloc(job->cmdbufs, size); 65 | if (!cmdbufs) 66 | return -ENOMEM; 67 | 68 | cmdbufs[job->num_cmdbufs++] = *cmdbuf; 69 | job->cmdbufs = cmdbufs; 70 | 71 | return 0; 72 | } 73 | 74 | int drm_tegra_job_new(struct drm_tegra_job **jobp, 75 | struct drm_tegra_channel *channel) 76 | { 77 | struct drm_tegra_job *job; 78 | 79 | if (!jobp || !channel) 80 | return -EINVAL; 81 | 82 | job = calloc(1, sizeof(*job)); 83 | if (!job) 84 | return -ENOMEM; 85 | 86 | DRMINITLISTHEAD(&job->pushbufs); 87 | job->channel = channel; 88 | job->syncpt = channel->syncpt; 89 | 90 | *jobp = job; 91 | 92 | return 0; 93 | } 94 | 95 | int drm_tegra_job_free(struct drm_tegra_job *job) 96 | { 97 | struct drm_tegra_pushbuf_private *pushbuf; 98 | struct drm_tegra_pushbuf_private *temp; 99 | 100 | if (!job) 101 | return -EINVAL; 102 | 103 | DRMLISTFOREACHENTRYSAFE(pushbuf, temp, &job->pushbufs, list) 104 | drm_tegra_pushbuf_free(&pushbuf->base); 105 | 106 | free(job->cmdbufs); 107 | free(job->relocs); 108 | free(job); 109 | 110 | return 0; 111 | } 112 | 113 | int drm_tegra_job_submit(struct drm_tegra_job *job, 114 | struct drm_tegra_fence **fencep) 115 | { 116 | struct drm_tegra *drm; 117 | struct drm_tegra_fence *fence = NULL; 118 | struct drm_tegra_syncpt *syncpts; 119 | struct drm_tegra_submit args; 120 | int err; 121 | 122 | if (!job) 123 | return -EINVAL; 124 | 125 | /* 126 | * Make sure the current command stream buffer is queued for 127 | * submission. 128 | */ 129 | err = drm_tegra_pushbuf_queue(job->pushbuf); 130 | if (err < 0) 131 | return err; 132 | 133 | job->pushbuf = NULL; 134 | 135 | if (fencep) { 136 | fence = calloc(1, sizeof(*fence)); 137 | if (!fence) 138 | return -ENOMEM; 139 | } 140 | 141 | syncpts = calloc(1, sizeof(*syncpts)); 142 | if (!syncpts) { 143 | free(fence); 144 | return -ENOMEM; 145 | } 146 | 147 | syncpts[0].id = job->syncpt; 148 | syncpts[0].incrs = job->increments; 149 | 150 | memset(&args, 0, sizeof(args)); 151 | args.context = job->channel->context; 152 | args.num_syncpts = 1; 153 | args.num_cmdbufs = job->num_cmdbufs; 154 | args.num_relocs = job->num_relocs; 155 | args.num_waitchks = 0; 156 | args.waitchk_mask = 0; 157 | args.timeout = 1000; 158 | 159 | args.syncpts = (uintptr_t)syncpts; 160 | args.cmdbufs = (uintptr_t)job->cmdbufs; 161 | args.relocs = (uintptr_t)job->relocs; 162 | args.waitchks = 0; 163 | 164 | drm = job->channel->drm; 165 | err = drmCommandWriteRead(drm->fd, DRM_TEGRA_SUBMIT, &args, 166 | sizeof(args)); 167 | if (err < 0) { 168 | free(syncpts); 169 | free(fence); 170 | return err; 171 | } 172 | 173 | if (fence) { 174 | fence->syncpt = job->syncpt; 175 | fence->value = args.fence; 176 | fence->drm = drm; 177 | *fencep = fence; 178 | } 179 | 180 | free(syncpts); 181 | 182 | return 0; 183 | } 184 | -------------------------------------------------------------------------------- /src/tegradrm/uapi_v1/pushbuf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012, 2013 Thierry Reding 3 | * Copyright © 2013 Erik Faye-Lund 4 | * Copyright © 2014 NVIDIA Corporation 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a 7 | * copy of this software and associated documentation files (the "Software"), 8 | * to deal in the Software without restriction, including without limitation 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the 11 | * Software is furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | * OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | #ifdef HAVE_CONFIG_H 26 | # include "config.h" 27 | #endif 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include "uapi_v1.h" 35 | 36 | #define HOST1X_OPCODE_NONINCR(offset, count) \ 37 | ((0x2 << 28) | (((offset) & 0xfff) << 16) | ((count) & 0xffff)) 38 | 39 | static inline unsigned long 40 | drm_tegra_pushbuf_get_offset(struct drm_tegra_pushbuf *pushbuf) 41 | { 42 | struct drm_tegra_pushbuf_private *priv = drm_tegra_pushbuf(pushbuf); 43 | 44 | return (unsigned long)pushbuf->ptr - (unsigned long)priv->start; 45 | } 46 | 47 | int drm_tegra_pushbuf_queue(struct drm_tegra_pushbuf_private *pushbuf) 48 | { 49 | struct drm_tegra_cmdbuf cmdbuf; 50 | int err; 51 | 52 | if (!pushbuf || !pushbuf->bo) 53 | return 0; 54 | 55 | /* unmap buffer object since it won't be accessed anymore */ 56 | drm_tegra_bo_unmap(pushbuf->bo); 57 | 58 | /* add buffer object as command buffers for this job */ 59 | memset(&cmdbuf, 0, sizeof(cmdbuf)); 60 | cmdbuf.words = pushbuf->base.ptr - pushbuf->start; 61 | cmdbuf.handle = pushbuf->bo->handle; 62 | cmdbuf.offset = 0; 63 | 64 | /* maintain mmap refcount balance upon pushbuf free'ing */ 65 | pushbuf->bo = NULL; 66 | 67 | err = drm_tegra_job_add_cmdbuf(pushbuf->job, &cmdbuf); 68 | if (err < 0) 69 | return err; 70 | 71 | return 0; 72 | } 73 | 74 | int drm_tegra_pushbuf_new(struct drm_tegra_pushbuf **pushbufp, 75 | struct drm_tegra_job *job) 76 | { 77 | struct drm_tegra_pushbuf_private *pushbuf; 78 | 79 | if (!pushbufp || !job) 80 | return -EINVAL; 81 | 82 | pushbuf = calloc(1, sizeof(*pushbuf)); 83 | if (!pushbuf) 84 | return -ENOMEM; 85 | 86 | DRMINITLISTHEAD(&pushbuf->list); 87 | DRMINITLISTHEAD(&pushbuf->bos); 88 | pushbuf->job = job; 89 | 90 | *pushbufp = &pushbuf->base; 91 | 92 | DRMLISTADDTAIL(&pushbuf->list, &job->pushbufs); 93 | job->pushbuf = pushbuf; 94 | 95 | return 0; 96 | } 97 | 98 | int drm_tegra_pushbuf_free(struct drm_tegra_pushbuf *pushbuf) 99 | { 100 | struct drm_tegra_pushbuf_private *priv; 101 | struct drm_tegra_bo *bo, *tmp; 102 | 103 | if (!pushbuf) 104 | return -EINVAL; 105 | 106 | priv = drm_tegra_pushbuf(pushbuf); 107 | drm_tegra_bo_unmap(priv->bo); 108 | 109 | DRMLISTFOREACHENTRYSAFE(bo, tmp, &priv->bos, push_list) { 110 | DRMLISTDELINIT(&bo->push_list); 111 | drm_tegra_bo_unref(bo); 112 | } 113 | 114 | DRMLISTDEL(&priv->list); 115 | free(priv); 116 | 117 | return 0; 118 | } 119 | 120 | /** 121 | * drm_tegra_pushbuf_prepare() - prepare push buffer for a series of pushes 122 | * @pushbuf: push buffer 123 | * @words: maximum number of words in series of pushes to follow 124 | */ 125 | int drm_tegra_pushbuf_prepare(struct drm_tegra_pushbuf *pushbuf, 126 | unsigned int words) 127 | { 128 | struct drm_tegra_pushbuf_private *priv; 129 | struct drm_tegra_channel *channel; 130 | struct drm_tegra_bo *bo; 131 | struct drm_tegra *drm; 132 | void *ptr; 133 | int err; 134 | 135 | if (!pushbuf || !words) 136 | return -EINVAL; 137 | 138 | priv = drm_tegra_pushbuf(pushbuf); 139 | channel = priv->job->channel; 140 | drm = channel->drm; 141 | 142 | if (priv->bo && (pushbuf->ptr + words < priv->end)) 143 | return 0; 144 | 145 | /* 146 | * Align to full pages, since buffer object allocations are page 147 | * granular anyway. 148 | */ 149 | words = align(words, 1024); 150 | 151 | err = drm_tegra_bo_new(&bo, drm, 0, words * sizeof(uint32_t)); 152 | if (err < 0) 153 | return err; 154 | 155 | err = drm_tegra_bo_map(bo, &ptr); 156 | if (err < 0) { 157 | drm_tegra_bo_unref(bo); 158 | return err; 159 | } 160 | 161 | /* queue current command stream buffer for submission */ 162 | err = drm_tegra_pushbuf_queue(priv); 163 | if (err < 0) { 164 | drm_tegra_bo_unmap(bo); 165 | drm_tegra_bo_unref(bo); 166 | return err; 167 | } 168 | 169 | #ifndef NDEBUG 170 | if (drm->debug_bo) 171 | assert(DRMLISTEMPTY(&bo->push_list)); 172 | #endif 173 | DRMLISTADD(&bo->push_list, &priv->bos); 174 | 175 | priv->start = priv->base.ptr = ptr; 176 | priv->end = priv->start + bo->size / sizeof(uint32_t); 177 | priv->bo = bo; 178 | 179 | return 0; 180 | } 181 | 182 | int drm_tegra_pushbuf_relocate(struct drm_tegra_pushbuf *pushbuf, 183 | struct drm_tegra_bo *target, 184 | unsigned long offset, 185 | unsigned long shift) 186 | { 187 | struct drm_tegra_pushbuf_private *priv; 188 | struct drm_tegra_reloc reloc; 189 | int err; 190 | 191 | if (!pushbuf || !target) 192 | return -EINVAL; 193 | 194 | priv = drm_tegra_pushbuf(pushbuf); 195 | err = drm_tegra_pushbuf_prepare(pushbuf, 1); 196 | if (err < 0) 197 | return err; 198 | 199 | memset(&reloc, 0, sizeof(reloc)); 200 | reloc.cmdbuf.handle = priv->bo->handle; 201 | reloc.cmdbuf.offset = drm_tegra_pushbuf_get_offset(pushbuf); 202 | reloc.target.handle = target->handle; 203 | reloc.target.offset = offset; 204 | reloc.shift = shift; 205 | 206 | err = drm_tegra_job_add_reloc(priv->job, &reloc); 207 | if (err < 0) 208 | return err; 209 | 210 | *pushbuf->ptr++ = 0xdeadbeef; 211 | 212 | return 0; 213 | } 214 | 215 | int drm_tegra_pushbuf_sync(struct drm_tegra_pushbuf *pushbuf, 216 | enum drm_tegra_syncpt_cond cond) 217 | { 218 | struct drm_tegra_pushbuf_private *priv; 219 | int err; 220 | 221 | if (!pushbuf) 222 | return -EINVAL; 223 | 224 | if (cond >= DRM_TEGRA_SYNCPT_COND_MAX) 225 | return -EINVAL; 226 | 227 | priv = drm_tegra_pushbuf(pushbuf); 228 | err = drm_tegra_pushbuf_prepare(pushbuf, 2); 229 | if (err < 0) 230 | return err; 231 | 232 | *pushbuf->ptr++ = HOST1X_OPCODE_NONINCR(0x0, 0x1); 233 | *pushbuf->ptr++ = cond << 8 | priv->job->syncpt; 234 | priv->job->increments++; 235 | 236 | return 0; 237 | } 238 | -------------------------------------------------------------------------------- /src/tegradrm/uapi_v1/uapi_v1.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012, 2013 Thierry Reding 3 | * Copyright © 2013 Erik Faye-Lund 4 | * Copyright © 2014 NVIDIA Corporation 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a 7 | * copy of this software and associated documentation files (the "Software"), 8 | * to deal in the Software without restriction, including without limitation 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the 11 | * Software is furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | * OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | #ifndef __DRM_TEGRA_PRIVATE_UAPI_V1_H__ 26 | #define __DRM_TEGRA_PRIVATE_UAPI_V1_H__ 1 27 | 28 | #include "private.h" 29 | 30 | struct drm_tegra_channel { 31 | struct drm_tegra *drm; 32 | enum host1x_class class; 33 | uint64_t context; 34 | uint32_t syncpt; 35 | }; 36 | 37 | struct drm_tegra_fence { 38 | struct drm_tegra *drm; 39 | uint32_t syncpt; 40 | uint32_t value; 41 | }; 42 | 43 | struct drm_tegra_pushbuf_private { 44 | struct drm_tegra_pushbuf base; 45 | struct drm_tegra_job *job; 46 | drmMMListHead list; 47 | drmMMListHead bos; 48 | 49 | struct drm_tegra_bo *bo; 50 | uint32_t *start; 51 | uint32_t *end; 52 | }; 53 | 54 | static inline void * 55 | drm_tegra_pushbuf(struct drm_tegra_pushbuf *pb) 56 | { 57 | return container_of(pb, struct drm_tegra_pushbuf_private, base); 58 | } 59 | 60 | int drm_tegra_pushbuf_queue(struct drm_tegra_pushbuf_private *pushbuf); 61 | 62 | struct drm_tegra_job { 63 | struct drm_tegra_channel *channel; 64 | 65 | unsigned int increments; 66 | uint32_t syncpt; 67 | 68 | struct drm_tegra_reloc *relocs; 69 | unsigned int num_relocs; 70 | 71 | struct drm_tegra_cmdbuf *cmdbufs; 72 | unsigned int num_cmdbufs; 73 | 74 | struct drm_tegra_pushbuf_private *pushbuf; 75 | drmMMListHead pushbufs; 76 | }; 77 | 78 | int drm_tegra_job_add_reloc(struct drm_tegra_job *job, 79 | const struct drm_tegra_reloc *reloc); 80 | int drm_tegra_job_add_cmdbuf(struct drm_tegra_job *job, 81 | const struct drm_tegra_cmdbuf *cmdbuf); 82 | 83 | #endif /* __DRM_TEGRA_PRIVATE_UAPI_V1_H__ */ 84 | -------------------------------------------------------------------------------- /src/tegradrm/uapi_v2/job.c: -------------------------------------------------------------------------------- 1 | 2 | #ifdef HAVE_CONFIG_H 3 | # include "config.h" 4 | #endif 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #include "private.h" 13 | 14 | int drm_tegra_job_new_v2(struct drm_tegra_job_v2 **jobp, 15 | struct drm_tegra *drm, 16 | unsigned int num_bos_expected, 17 | unsigned int num_words_expected) 18 | { 19 | struct drm_tegra_job_v2 *job; 20 | void *bo_table; 21 | void *start; 22 | int err; 23 | 24 | if (!jobp || !drm) 25 | return -EINVAL; 26 | 27 | job = calloc(1, sizeof(*job)); 28 | if (!job) 29 | return -ENOMEM; 30 | 31 | if (num_words_expected < 64) 32 | num_words_expected = 64; 33 | 34 | err = posix_memalign(&start, 64, 35 | sizeof(*job->start) * num_words_expected); 36 | if (err) 37 | goto err_free_job; 38 | 39 | if (num_bos_expected < 8) 40 | num_bos_expected = 8; 41 | 42 | err = posix_memalign(&bo_table, 64, 43 | sizeof(*job->bo_table) * num_bos_expected); 44 | if (err) 45 | goto err_free_words; 46 | 47 | job->num_bos_max = num_bos_expected; 48 | job->num_words = num_words_expected; 49 | job->bo_table = bo_table; 50 | job->start = start; 51 | job->ptr = start; 52 | job->drm = drm; 53 | 54 | *jobp = job; 55 | 56 | return 0; 57 | 58 | err_free_words: 59 | free(start); 60 | err_free_job: 61 | free(job); 62 | 63 | return err; 64 | } 65 | 66 | int drm_tegra_job_resize_v2(struct drm_tegra_job_v2 *job, 67 | unsigned int num_words, 68 | unsigned int num_bos, 69 | bool reallocate) 70 | { 71 | unsigned int offset; 72 | void *new_bo_table; 73 | void *new_start; 74 | size_t size; 75 | int err; 76 | 77 | if (!job) 78 | return -EINVAL; 79 | 80 | if (num_words != job->num_words) { 81 | offset = (unsigned int)(job->ptr - job->start); 82 | 83 | err = posix_memalign(&new_start, 64, 84 | sizeof(*job->start) * num_words); 85 | if (err) 86 | return err; 87 | 88 | if (reallocate) { 89 | if (num_words < job->num_words) 90 | size = sizeof(*job->start) * num_words; 91 | else 92 | size = sizeof(*job->start) * job->num_words; 93 | 94 | memcpy(new_start, job->start, size); 95 | } 96 | 97 | free(job->start); 98 | 99 | job->num_words = num_words; 100 | job->start = new_start; 101 | job->ptr = new_start; 102 | job->ptr += offset; 103 | } 104 | 105 | if (num_bos != job->num_bos_max) { 106 | err = posix_memalign(&new_bo_table, 64, 107 | sizeof(*job->bo_table) * num_bos); 108 | if (err) 109 | return err; 110 | 111 | if (reallocate) { 112 | if (num_bos < job->num_bos_max) 113 | size = sizeof(*job->bo_table) * num_bos; 114 | else 115 | size = sizeof(*job->bo_table) * job->num_bos_max; 116 | 117 | memcpy(new_bo_table, job->bo_table, size); 118 | } 119 | 120 | free(job->bo_table); 121 | 122 | job->bo_table = new_bo_table; 123 | job->num_bos_max = num_bos; 124 | } 125 | 126 | return 0; 127 | } 128 | 129 | int drm_tegra_job_reset_v2(struct drm_tegra_job_v2 *job) 130 | { 131 | if (!job) 132 | return -EINVAL; 133 | 134 | job->num_bos = 0; 135 | job->ptr = job->start; 136 | 137 | return 0; 138 | } 139 | 140 | int drm_tegra_job_free_v2(struct drm_tegra_job_v2 *job) 141 | { 142 | if (!job) 143 | return -EINVAL; 144 | 145 | free(job->bo_table); 146 | free(job->start); 147 | free(job); 148 | 149 | return 0; 150 | } 151 | 152 | int drm_tegra_job_push_reloc_v2(struct drm_tegra_job_v2 *job, 153 | struct drm_tegra_bo *target, 154 | unsigned long offset, 155 | uint32_t drm_bo_table_flags) 156 | { 157 | struct drm_tegra_cmdstream_reloc reloc; 158 | unsigned int i; 159 | int err; 160 | 161 | if (!job) 162 | return -EINVAL; 163 | 164 | for (i = 0; i < job->num_bos; i++) { 165 | if (job->bo_table[i].handle == target->handle) 166 | break; 167 | } 168 | 169 | if (i == job->num_bos) { 170 | if (job->num_bos == job->num_bos_max) { 171 | err = drm_tegra_job_resize_v2( 172 | job, job->num_words, job->num_bos_max + 8, true); 173 | if (err) 174 | return err; 175 | } 176 | 177 | job->bo_table[i].handle = target->handle; 178 | job->bo_table[i].flags = drm_bo_table_flags; 179 | job->num_bos++; 180 | } 181 | 182 | reloc.bo_index = i; 183 | reloc.bo_offset = target->offset + offset; 184 | 185 | offset = (unsigned long)(job->ptr - job->start); 186 | 187 | if (offset == job->num_words) { 188 | err = drm_tegra_job_resize_v2( 189 | job, job->num_words + 256, job->num_bos_max, true); 190 | if (err) 191 | return err; 192 | } 193 | 194 | *job->ptr++ = reloc.u_data; 195 | 196 | return 0; 197 | } 198 | 199 | int drm_tegra_job_submit_v2(struct drm_tegra_job_v2 *job, 200 | uint32_t syncobj_handle, 201 | uint64_t pipes_mask) 202 | { 203 | struct drm_tegra_submit_v2 args; 204 | 205 | if (!job) 206 | return -EINVAL; 207 | 208 | args.in_fence = 0; 209 | args.out_fence = syncobj_handle; 210 | args.cmdstream_ptr = (uintptr_t)job->start; 211 | args.bo_table_ptr = (uintptr_t)job->bo_table; 212 | args.num_cmdstream_words = (uint32_t)(job->ptr - job->start); 213 | args.num_bos = job->num_bos; 214 | args.pipes = pipes_mask; 215 | args.uapi_ver = 0; 216 | args.flags = 0; 217 | 218 | return drmCommandWriteRead(job->drm->fd, DRM_TEGRA_SUBMIT_V2, 219 | &args, sizeof(args)); 220 | } 221 | -------------------------------------------------------------------------------- /src/uapi/dma-buf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Framework for buffer objects that can be shared across devices/subsystems. 3 | * 4 | * Copyright(C) 2015 Intel Ltd 5 | * 6 | * This program is free software; you can redistribute it and/or modify it 7 | * under the terms of the GNU General Public License version 2 as published by 8 | * the Free Software Foundation. 9 | * 10 | * This program is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 | * more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program. If not, see . 17 | */ 18 | 19 | #ifndef _DMA_BUF_UAPI_H_ 20 | #define _DMA_BUF_UAPI_H_ 21 | 22 | #include 23 | 24 | /* begin/end dma-buf functions used for userspace mmap. */ 25 | struct dma_buf_sync { 26 | __u64 flags; 27 | }; 28 | 29 | #define DMA_BUF_SYNC_READ (1 << 0) 30 | #define DMA_BUF_SYNC_WRITE (2 << 0) 31 | #define DMA_BUF_SYNC_RW (DMA_BUF_SYNC_READ | DMA_BUF_SYNC_WRITE) 32 | #define DMA_BUF_SYNC_START (0 << 2) 33 | #define DMA_BUF_SYNC_END (1 << 2) 34 | #define DMA_BUF_SYNC_VALID_FLAGS_MASK \ 35 | (DMA_BUF_SYNC_RW | DMA_BUF_SYNC_END) 36 | 37 | #define DMA_BUF_BASE 'b' 38 | #define DMA_BUF_IOCTL_SYNC _IOW(DMA_BUF_BASE, 0, struct dma_buf_sync) 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /src/uapi/tegra-vde-v1.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016-2017 Dmitry Osipenko 3 | * All Rights Reserved. 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the next 13 | * paragraph) shall be included in all copies or substantial portions of the 14 | * Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | * OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | #ifndef _UAPI_TEGRA_VDE_V1_H_ 26 | #define _UAPI_TEGRA_VDE_V1_H_ 27 | 28 | #include 29 | #include 30 | 31 | #if defined(__cplusplus) 32 | extern "C" { 33 | #endif 34 | 35 | #define FLAG_B_FRAME_V1 (1 << 0) 36 | #define FLAG_REFERENCE_V1 (1 << 1) 37 | 38 | struct tegra_vde_h264_frame_v1 { 39 | __s32 y_fd; 40 | __s32 cb_fd; 41 | __s32 cr_fd; 42 | __s32 aux_fd; 43 | __u32 y_offset; 44 | __u32 cb_offset; 45 | __u32 cr_offset; 46 | __u32 aux_offset; 47 | __u32 frame_num; 48 | __u32 flags; 49 | 50 | __u32 reserved; 51 | } __attribute__((packed)); 52 | 53 | struct tegra_vde_h264_decoder_ctx_v1 { 54 | __s32 bitstream_data_fd; 55 | __u32 bitstream_data_offset; 56 | 57 | __u64 dpb_frames_ptr; 58 | __u8 dpb_frames_nb; 59 | __u8 dpb_ref_frames_with_earlier_poc_nb; 60 | 61 | // SPS 62 | __u8 baseline_profile; 63 | __u8 level_idc; 64 | __u8 log2_max_pic_order_cnt_lsb; 65 | __u8 log2_max_frame_num; 66 | __u8 pic_order_cnt_type; 67 | __u8 direct_8x8_inference_flag; 68 | __u8 pic_width_in_mbs; 69 | __u8 pic_height_in_mbs; 70 | 71 | // PPS 72 | __u8 pic_init_qp; 73 | __u8 deblocking_filter_control_present_flag; 74 | __u8 constrained_intra_pred_flag; 75 | __u8 chroma_qp_index_offset; 76 | __u8 pic_order_present_flag; 77 | 78 | // Slice header 79 | __u8 num_ref_idx_l0_active_minus1; 80 | __u8 num_ref_idx_l1_active_minus1; 81 | 82 | __u32 reserved; 83 | } __attribute__((packed)); 84 | 85 | #define VDE_IOCTL_BASE_V1 ('v' + 0x20) 86 | 87 | #define VDE_IO_V1(nr) _IO(VDE_IOCTL_BASE_V1, nr) 88 | #define VDE_IOR_V1(nr, type) _IOR(VDE_IOCTL_BASE_V1, nr, type) 89 | #define VDE_IOW_V1(nr, type) _IOW(VDE_IOCTL_BASE_V1, nr, type) 90 | #define VDE_IOWR_V1(nr, type) _IOWR(VDE_IOCTL_BASE_V1, nr, type) 91 | 92 | #define TEGRA_VDE_DECODE_H264_V1 0x00 93 | 94 | #define TEGRA_VDE_IOCTL_DECODE_H264_V1 \ 95 | VDE_IOW_V1(TEGRA_VDE_DECODE_H264_V1, struct tegra_vde_h264_decoder_ctx_v1) 96 | 97 | #if defined(__cplusplus) 98 | } 99 | #endif 100 | 101 | #endif // _UAPI_TEGRA_VDE_V1_H_ 102 | -------------------------------------------------------------------------------- /src/uapi/tegra-vde.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016-2017 Dmitry Osipenko 3 | * All Rights Reserved. 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the next 13 | * paragraph) shall be included in all copies or substantial portions of the 14 | * Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | * OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | #ifndef _UAPI_TEGRA_VDE_H_ 26 | #define _UAPI_TEGRA_VDE_H_ 27 | 28 | #include 29 | #include 30 | 31 | #if defined(__cplusplus) 32 | extern "C" { 33 | #endif 34 | 35 | #define FLAG_B_FRAME 0x1 36 | #define FLAG_REFERENCE 0x2 37 | 38 | struct tegra_vde_h264_frame { 39 | __s32 y_fd; 40 | __s32 cb_fd; 41 | __s32 cr_fd; 42 | __s32 aux_fd; 43 | __u32 y_offset; 44 | __u32 cb_offset; 45 | __u32 cr_offset; 46 | __u32 aux_offset; 47 | __u32 frame_num; 48 | __u32 flags; 49 | 50 | __u32 reserved[6]; 51 | }; 52 | 53 | struct tegra_vde_h264_decoder_ctx { 54 | __s32 bitstream_data_fd; 55 | __u32 bitstream_data_offset; 56 | 57 | __u64 dpb_frames_ptr; 58 | __u32 dpb_frames_nb; 59 | __u32 dpb_ref_frames_with_earlier_poc_nb; 60 | 61 | // SPS 62 | __u32 baseline_profile; 63 | __u32 level_idc; 64 | __u32 log2_max_pic_order_cnt_lsb; 65 | __u32 log2_max_frame_num; 66 | __u32 pic_order_cnt_type; 67 | __u32 direct_8x8_inference_flag; 68 | __u32 pic_width_in_mbs; 69 | __u32 pic_height_in_mbs; 70 | 71 | // PPS 72 | __u32 pic_init_qp; 73 | __u32 deblocking_filter_control_present_flag; 74 | __u32 constrained_intra_pred_flag; 75 | __u32 chroma_qp_index_offset; 76 | __u32 pic_order_present_flag; 77 | 78 | // Slice header 79 | __u32 num_ref_idx_l0_active_minus1; 80 | __u32 num_ref_idx_l1_active_minus1; 81 | 82 | __u32 reserved[11]; 83 | }; 84 | 85 | #define VDE_IOCTL_BASE ('v' + 0x20) 86 | 87 | #define VDE_IO(nr) _IO(VDE_IOCTL_BASE, nr) 88 | #define VDE_IOR(nr, type) _IOR(VDE_IOCTL_BASE, nr, type) 89 | #define VDE_IOW(nr, type) _IOW(VDE_IOCTL_BASE, nr, type) 90 | #define VDE_IOWR(nr, type) _IOWR(VDE_IOCTL_BASE, nr, type) 91 | 92 | #define TEGRA_VDE_DECODE_H264 0x00 93 | 94 | #define TEGRA_VDE_IOCTL_DECODE_H264 \ 95 | VDE_IOW(TEGRA_VDE_DECODE_H264, struct tegra_vde_h264_decoder_ctx) 96 | 97 | #if defined(__cplusplus) 98 | } 99 | #endif 100 | 101 | #endif // _UAPI_TEGRA_VDE_H_ 102 | -------------------------------------------------------------------------------- /src/uapi/types-compat.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Collabora Ltd. 3 | * Author: Nicolas Dufresne 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Library General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Library General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Library General Public 16 | * License along with this library; if not, write to the 17 | * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, 18 | * Boston, MA 02110-1301, USA. 19 | * 20 | */ 21 | 22 | #include 23 | 24 | #ifndef __TYPES_COMPAT_H__ 25 | #define __TYPES_COMPAT_H__ 26 | 27 | #define __inline__ inline 28 | 29 | #ifdef __linux__ 30 | #include 31 | #include 32 | 33 | #else /* One of the BSDs */ 34 | /* From linux/types.h */ 35 | #ifndef __bitwise__ 36 | # ifdef __CHECKER__ 37 | # define __bitwise__ __attribute__((bitwise)) 38 | # else 39 | # define __bitwise__ 40 | # endif 41 | #endif 42 | 43 | #ifndef __bitwise 44 | # ifdef __CHECK_ENDIAN__ 45 | # define __bitwise __bitwise__ 46 | # else 47 | # define __bitwise 48 | # endif 49 | #endif 50 | 51 | typedef int8_t __s8; 52 | typedef uint8_t __u8; 53 | typedef int16_t __s16; 54 | typedef uint16_t __u16; 55 | typedef int32_t __s32; 56 | typedef uint32_t __u32; 57 | typedef int64_t __s64; 58 | typedef uint64_t __u64; 59 | typedef uint32_t __bitwise __le32; 60 | 61 | #endif 62 | 63 | #endif /* __TYPES_COMPAT_H__ */ 64 | -------------------------------------------------------------------------------- /src/uapi/v4l2-common.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: ((GPL-2.0+ WITH Linux-syscall-note) OR BSD-3-Clause) */ 2 | /* 3 | * include/linux/v4l2-common.h 4 | * 5 | * Common V4L2 and V4L2 subdev definitions. 6 | * 7 | * Users are advised to #include this file either through videodev2.h 8 | * (V4L2) or through v4l2-subdev.h (V4L2 subdev) rather than to refer 9 | * to this file directly. 10 | * 11 | * Copyright (C) 2012 Nokia Corporation 12 | * Contact: Sakari Ailus 13 | * 14 | * This program is free software; you can redistribute it and/or modify 15 | * it under the terms of the GNU General Public License as published by 16 | * the Free Software Foundation; either version 2 of the License, or 17 | * (at your option) any later version. 18 | * 19 | * This program is distributed in the hope that it will be useful, 20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | * GNU General Public License for more details. 23 | * 24 | * Alternatively you can redistribute this file under the terms of the 25 | * BSD license as stated below: 26 | * 27 | * Redistribution and use in source and binary forms, with or without 28 | * modification, are permitted provided that the following conditions 29 | * are met: 30 | * 1. Redistributions of source code must retain the above copyright 31 | * notice, this list of conditions and the following disclaimer. 32 | * 2. Redistributions in binary form must reproduce the above copyright 33 | * notice, this list of conditions and the following disclaimer in 34 | * the documentation and/or other materials provided with the 35 | * distribution. 36 | * 3. The names of its contributors may not be used to endorse or promote 37 | * products derived from this software without specific prior written 38 | * permission. 39 | * 40 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 41 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 42 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 43 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 44 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 46 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 47 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 48 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 49 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 50 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 51 | * 52 | */ 53 | 54 | #ifndef __V4L2_COMMON__ 55 | #define __V4L2_COMMON__ 56 | 57 | #include "types-compat.h" 58 | 59 | /* 60 | * 61 | * Selection interface definitions 62 | * 63 | */ 64 | 65 | /* Current cropping area */ 66 | #define V4L2_SEL_TGT_CROP 0x0000 67 | /* Default cropping area */ 68 | #define V4L2_SEL_TGT_CROP_DEFAULT 0x0001 69 | /* Cropping bounds */ 70 | #define V4L2_SEL_TGT_CROP_BOUNDS 0x0002 71 | /* Native frame size */ 72 | #define V4L2_SEL_TGT_NATIVE_SIZE 0x0003 73 | /* Current composing area */ 74 | #define V4L2_SEL_TGT_COMPOSE 0x0100 75 | /* Default composing area */ 76 | #define V4L2_SEL_TGT_COMPOSE_DEFAULT 0x0101 77 | /* Composing bounds */ 78 | #define V4L2_SEL_TGT_COMPOSE_BOUNDS 0x0102 79 | /* Current composing area plus all padding pixels */ 80 | #define V4L2_SEL_TGT_COMPOSE_PADDED 0x0103 81 | 82 | /* Selection flags */ 83 | #define V4L2_SEL_FLAG_GE (1 << 0) 84 | #define V4L2_SEL_FLAG_LE (1 << 1) 85 | #define V4L2_SEL_FLAG_KEEP_CONFIG (1 << 2) 86 | 87 | struct v4l2_edid { 88 | __u32 pad; 89 | __u32 start_block; 90 | __u32 blocks; 91 | __u32 reserved[5]; 92 | __u8 *edid; 93 | }; 94 | 95 | /* Backward compatibility target definitions --- to be removed. */ 96 | #define V4L2_SEL_TGT_CROP_ACTIVE V4L2_SEL_TGT_CROP 97 | #define V4L2_SEL_TGT_COMPOSE_ACTIVE V4L2_SEL_TGT_COMPOSE 98 | #define V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL V4L2_SEL_TGT_CROP 99 | #define V4L2_SUBDEV_SEL_TGT_COMPOSE_ACTUAL V4L2_SEL_TGT_COMPOSE 100 | #define V4L2_SUBDEV_SEL_TGT_CROP_BOUNDS V4L2_SEL_TGT_CROP_BOUNDS 101 | #define V4L2_SUBDEV_SEL_TGT_COMPOSE_BOUNDS V4L2_SEL_TGT_COMPOSE_BOUNDS 102 | 103 | /* Backward compatibility flag definitions --- to be removed. */ 104 | #define V4L2_SUBDEV_SEL_FLAG_SIZE_GE V4L2_SEL_FLAG_GE 105 | #define V4L2_SUBDEV_SEL_FLAG_SIZE_LE V4L2_SEL_FLAG_LE 106 | #define V4L2_SUBDEV_SEL_FLAG_KEEP_CONFIG V4L2_SEL_FLAG_KEEP_CONFIG 107 | 108 | #endif /* __V4L2_COMMON__ */ 109 | -------------------------------------------------------------------------------- /src/util_double_list.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND. USA. 4 | * All Rights Reserved. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a 7 | * copy of this software and associated documentation files (the 8 | * "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sub license, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 17 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 18 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | * 22 | * The above copyright notice and this permission notice (including the 23 | * next paragraph) shall be included in all copies or substantial portions 24 | * of the Software. 25 | * 26 | */ 27 | 28 | /** 29 | * \file 30 | * List macros heavily inspired by the Linux kernel 31 | * list handling. No list looping yet. 32 | * 33 | * Is not threadsafe, so common operations need to 34 | * be protected using an external mutex. 35 | */ 36 | #ifndef _U_DOUBLE_LIST_H_ 37 | #define _U_DOUBLE_LIST_H_ 38 | 39 | #include 40 | 41 | struct list_head 42 | { 43 | struct list_head *prev; 44 | struct list_head *next; 45 | }; 46 | 47 | static inline void list_inithead(struct list_head *item) 48 | { 49 | item->prev = item; 50 | item->next = item; 51 | } 52 | 53 | static inline void list_add(struct list_head *item, struct list_head *list) 54 | { 55 | item->prev = list; 56 | item->next = list->next; 57 | list->next->prev = item; 58 | list->next = item; 59 | } 60 | 61 | static inline void list_addtail(struct list_head *item, struct list_head *list) 62 | { 63 | item->next = list; 64 | item->prev = list->prev; 65 | list->prev->next = item; 66 | list->prev = item; 67 | } 68 | 69 | static inline void list_replace(struct list_head *from, struct list_head *to) 70 | { 71 | to->prev = from->prev; 72 | to->next = from->next; 73 | from->next->prev = to; 74 | from->prev->next = to; 75 | } 76 | 77 | static inline void list_del(struct list_head *item) 78 | { 79 | item->prev->next = item->next; 80 | item->next->prev = item->prev; 81 | } 82 | 83 | static inline void list_delinit(struct list_head *item) 84 | { 85 | item->prev->next = item->next; 86 | item->next->prev = item->prev; 87 | item->next = item; 88 | item->prev = item; 89 | } 90 | 91 | #define LIST_INITHEAD(__item) list_inithead(__item) 92 | #define LIST_ADD(__item, __list) list_add(__item, __list) 93 | #define LIST_ADDTAIL(__item, __list) list_addtail(__item, __list) 94 | #define LIST_REPLACE(__from, __to) list_replace(__from, __to) 95 | #define LIST_DEL(__item) list_del(__item) 96 | #define LIST_DELINIT(__item) list_delinit(__item) 97 | 98 | #define LIST_ENTRY(__type, __item, __field) \ 99 | ((__type *)(((char *)(__item)) - offsetof(__type, __field))) 100 | 101 | #define LIST_FIRST_ENTRY(__ptr, __type, __field) \ 102 | LIST_ENTRY(__type, (__ptr)->next, __field) 103 | 104 | #define LIST_LAST_ENTRY(__ptr, __type, __field) \ 105 | LIST_ENTRY(__type, (__ptr)->prev, __field) 106 | 107 | #define LIST_IS_EMPTY(__list) \ 108 | ((__list)->next == (__list)) 109 | 110 | #ifndef container_of 111 | #define container_of(ptr, sample, member) \ 112 | (void *)((char *)(ptr) \ 113 | - ((char *)&((typeof(sample))0)->member)) 114 | #endif 115 | 116 | #define LIST_FOR_EACH_ENTRY(pos, head, member) \ 117 | for (pos = container_of((head)->next, pos, member); \ 118 | &pos->member != (head); \ 119 | pos = container_of(pos->member.next, pos, member)) 120 | 121 | #define LIST_FOR_EACH_ENTRY_SAFE(pos, storage, head, member) \ 122 | for (pos = container_of((head)->next, pos, member), \ 123 | storage = container_of(pos->member.next, pos, member); \ 124 | &pos->member != (head); \ 125 | pos = storage, storage = container_of(storage->member.next, storage, member)) 126 | 127 | #define LIST_FOR_EACH_ENTRY_SAFE_REV(pos, storage, head, member) \ 128 | for (pos = container_of((head)->prev, pos, member), \ 129 | storage = container_of(pos->member.prev, pos, member); \ 130 | &pos->member != (head); \ 131 | pos = storage, storage = container_of(storage->member.prev, storage, member)) 132 | 133 | #define LIST_FOR_EACH_ENTRY_FROM(pos, start, head, member) \ 134 | for (pos = container_of((start), pos, member); \ 135 | &pos->member != (head); \ 136 | pos = container_of(pos->member.next, pos, member)) 137 | 138 | #define LIST_FOR_EACH_ENTRY_FROM_REV(pos, start, head, member) \ 139 | for (pos = container_of((start), pos, member); \ 140 | &pos->member != (head); \ 141 | pos = container_of(pos->member.prev, pos, member)) 142 | 143 | #endif /*_U_DOUBLE_LIST_H_*/ 144 | -------------------------------------------------------------------------------- /src/v4l2.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Paul Kocialkowski 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the 6 | * "Software"), to deal in the Software without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sub license, and/or sell copies of the Software, and to 9 | * permit persons to whom the Software is furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial portions 14 | * of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 19 | * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 20 | * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | #ifndef _V4L2_H_ 26 | #define _V4L2_H_ 27 | 28 | #include 29 | 30 | #define V4L_MIN_CODED_SIZE (32 * 1024) 31 | 32 | unsigned int v4l2_type_video_output(bool mplane); 33 | unsigned int v4l2_type_video_capture(bool mplane); 34 | int v4l2_query_capabilities(int video_fd, unsigned int *capabilities); 35 | bool v4l2_find_format(int video_fd, unsigned int type, 36 | unsigned int pixelformat); 37 | int v4l2_try_format(int video_fd, unsigned int type, unsigned int width, 38 | unsigned int height, unsigned int pixelformat, 39 | struct v4l2_format *ret_format); 40 | int v4l2_set_format(int video_fd, unsigned int type, unsigned int pixelformat, 41 | unsigned int width, unsigned int height); 42 | int v4l2_get_format(int video_fd, unsigned int type, unsigned int *width, 43 | unsigned int *height, unsigned int *bytesperline, 44 | unsigned int *sizes, unsigned int *planes_count); 45 | int v4l2_create_buffers(int video_fd, unsigned int type, 46 | unsigned int buffers_count, unsigned int *index_base); 47 | int v4l2_query_buffer(int video_fd, unsigned int type, unsigned int index, 48 | unsigned int *lengths, unsigned int *offsets, 49 | unsigned int buffers_count); 50 | int v4l2_request_buffers(int video_fd, unsigned int type, 51 | unsigned int *buffers_count); 52 | int v4l2_queue_buffer(int video_fd, int request_fd, unsigned int type, 53 | struct timeval *timestamp, unsigned int index, 54 | int *dmafd, unsigned int *size, 55 | unsigned int *used_size, 56 | unsigned int *offset, 57 | unsigned int buffers_count, 58 | unsigned int flags); 59 | int v4l2_dequeue_buffer(int video_fd, unsigned int type, 60 | unsigned int buffers_count, 61 | bool *error); 62 | int v4l2_export_buffer(int video_fd, unsigned int type, unsigned int index, 63 | unsigned int flags, int *export_fds, 64 | unsigned int export_fds_count); 65 | int v4l2_set_control(int video_fd, int request_fd, unsigned int id, void *data, 66 | unsigned int size); 67 | int v4l2_set_stream(int video_fd, unsigned int type, bool enable); 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /src/vdpau-tegra.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | 3 | Name: vdpau-tegra 4 | Description: Open source NVIDIA Tegra2 VDPAU driver 5 | Version: @PACKAGE_VERSION@ 6 | --------------------------------------------------------------------------------