├── .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 |
--------------------------------------------------------------------------------