pmaports/main/mesa-grate/0005-grate-driver.patch
2018-11-27 07:47:11 +01:00

6242 lines
194 KiB
Diff

From 527b4ec9895c457fed3387c3342433a4502fea94 Mon Sep 17 00:00:00 2001
From: ryang <decatf@gmail.com>
Date: Thu, 9 Aug 2018 18:46:09 -0400
Subject: [PATCH 5/5] grate-driver
# Conflicts:
# configure.ac
---
configure.ac | 15 +-
meson.build | 5 +
src/gallium/Makefile.am | 5 +
.../auxiliary/pipe-loader/pipe_loader_drm.c | 5 +
src/gallium/auxiliary/target-helpers/drm_helper.h | 22 +
.../auxiliary/target-helpers/drm_helper_public.h | 3 +
src/gallium/drivers/grate/Automake.inc | 11 +
src/gallium/drivers/grate/Makefile.am | 43 ++
src/gallium/drivers/grate/class_ids.h | 37 ++
src/gallium/drivers/grate/grate_common.h | 18 +
src/gallium/drivers/grate/grate_compiler.h | 38 ++
src/gallium/drivers/grate/grate_compiler_fp.c | 241 ++++++++
src/gallium/drivers/grate/grate_compiler_vpe.c | 336 +++++++++++
src/gallium/drivers/grate/grate_context.c | 314 ++++++++++
src/gallium/drivers/grate/grate_context.h | 63 ++
src/gallium/drivers/grate/grate_draw.c | 125 ++++
src/gallium/drivers/grate/grate_draw.h | 7 +
src/gallium/drivers/grate/grate_fp_ir.c | 196 +++++++
src/gallium/drivers/grate/grate_fp_ir.h | 168 ++++++
src/gallium/drivers/grate/grate_fp_vliw.h | 174 ++++++
src/gallium/drivers/grate/grate_program.c | 219 +++++++
src/gallium/drivers/grate/grate_program.h | 29 +
src/gallium/drivers/grate/grate_resource.c | 511 +++++++++++++++++
src/gallium/drivers/grate/grate_resource.h | 30 +
src/gallium/drivers/grate/grate_screen.c | 609 ++++++++++++++++++++
src/gallium/drivers/grate/grate_screen.h | 31 +
src/gallium/drivers/grate/grate_state.c | 634 +++++++++++++++++++++
src/gallium/drivers/grate/grate_state.h | 59 ++
src/gallium/drivers/grate/grate_stream.c | 380 ++++++++++++
src/gallium/drivers/grate/grate_stream.h | 102 ++++
src/gallium/drivers/grate/grate_surface.c | 45 ++
src/gallium/drivers/grate/grate_surface.h | 14 +
src/gallium/drivers/grate/grate_vpe_ir.c | 211 +++++++
src/gallium/drivers/grate/grate_vpe_ir.h | 115 ++++
src/gallium/drivers/grate/host1x01_hardware.h | 136 +++++
src/gallium/drivers/grate/hw_host1x01_uclass.h | 159 ++++++
src/gallium/drivers/grate/meson.build | 68 +++
src/gallium/drivers/grate/tgr_3d.xml.h | 451 +++++++++++++++
src/gallium/meson.build | 6 +
src/gallium/targets/dri/Makefile.am | 2 +
src/gallium/targets/dri/dri.sym | 1 +
src/gallium/targets/dri/meson.build | 6 +-
src/gallium/targets/dri/target.c | 4 +
src/gallium/winsys/tegra/drm/Makefile.am | 33 ++
src/gallium/winsys/tegra/drm/meson.build | 30 +
src/gallium/winsys/tegra/drm/tegra_drm_public.h | 8 +
src/gallium/winsys/tegra/drm/tegra_drm_winsys.c | 17 +
47 files changed, 5731 insertions(+), 5 deletions(-)
create mode 100644 src/gallium/drivers/grate/Automake.inc
create mode 100644 src/gallium/drivers/grate/Makefile.am
create mode 100644 src/gallium/drivers/grate/class_ids.h
create mode 100644 src/gallium/drivers/grate/grate_common.h
create mode 100644 src/gallium/drivers/grate/grate_compiler.h
create mode 100644 src/gallium/drivers/grate/grate_compiler_fp.c
create mode 100644 src/gallium/drivers/grate/grate_compiler_vpe.c
create mode 100644 src/gallium/drivers/grate/grate_context.c
create mode 100644 src/gallium/drivers/grate/grate_context.h
create mode 100644 src/gallium/drivers/grate/grate_draw.c
create mode 100644 src/gallium/drivers/grate/grate_draw.h
create mode 100644 src/gallium/drivers/grate/grate_fp_ir.c
create mode 100644 src/gallium/drivers/grate/grate_fp_ir.h
create mode 100644 src/gallium/drivers/grate/grate_fp_vliw.h
create mode 100644 src/gallium/drivers/grate/grate_program.c
create mode 100644 src/gallium/drivers/grate/grate_program.h
create mode 100644 src/gallium/drivers/grate/grate_resource.c
create mode 100644 src/gallium/drivers/grate/grate_resource.h
create mode 100755 src/gallium/drivers/grate/grate_screen.c
create mode 100644 src/gallium/drivers/grate/grate_screen.h
create mode 100644 src/gallium/drivers/grate/grate_state.c
create mode 100644 src/gallium/drivers/grate/grate_state.h
create mode 100644 src/gallium/drivers/grate/grate_stream.c
create mode 100644 src/gallium/drivers/grate/grate_stream.h
create mode 100644 src/gallium/drivers/grate/grate_surface.c
create mode 100644 src/gallium/drivers/grate/grate_surface.h
create mode 100644 src/gallium/drivers/grate/grate_vpe_ir.c
create mode 100644 src/gallium/drivers/grate/grate_vpe_ir.h
create mode 100644 src/gallium/drivers/grate/host1x01_hardware.h
create mode 100644 src/gallium/drivers/grate/hw_host1x01_uclass.h
create mode 100644 src/gallium/drivers/grate/meson.build
create mode 100644 src/gallium/drivers/grate/tgr_3d.xml.h
create mode 100644 src/gallium/winsys/tegra/drm/Makefile.am
create mode 100644 src/gallium/winsys/tegra/drm/meson.build
create mode 100644 src/gallium/winsys/tegra/drm/tegra_drm_public.h
create mode 100644 src/gallium/winsys/tegra/drm/tegra_drm_winsys.c
diff --git a/configure.ac b/configure.ac
index 3141348..be3b547 100644
--- a/configure.ac
+++ b/configure.ac
@@ -80,6 +80,7 @@ LIBDRM_NVVIEUX_REQUIRED=2.4.66
LIBDRM_NOUVEAU_REQUIRED=2.4.66
LIBDRM_FREEDRENO_REQUIRED=2.4.91
LIBDRM_ETNAVIV_REQUIRED=2.4.89
+LIBDRM_TEGRA_REQUIRED=2.4.81
dnl Versions for external dependencies
DRI2PROTO_REQUIRED=2.8
@@ -1359,7 +1360,7 @@ GALLIUM_DRIVERS_DEFAULT="r300,r600,svga,swrast"
AC_ARG_WITH([gallium-drivers],
[AS_HELP_STRING([--with-gallium-drivers@<:@=DIRS...@:>@],
[comma delimited Gallium drivers list, e.g.
- "i915,nouveau,r300,r600,radeonsi,freedreno,pl111,svga,swrast,swr,vc4,vc5,virgl,etnaviv,imx"
+ "i915,nouveau,r300,r600,radeonsi,freedreno,pl111,svga,swrast,swr,vc4,vc5,virgl,etnaviv,imx,grate"
@<:@default=r300,r600,svga,swrast@:>@])],
[with_gallium_drivers="$withval"],
[with_gallium_drivers="$GALLIUM_DRIVERS_DEFAULT"])
@@ -2735,6 +2736,11 @@ if test -n "$with_gallium_drivers"; then
require_basic_egl "virgl"
fi
;;
+ xgrate)
+ HAVE_GALLIUM_GRATE=yes
+ PKG_CHECK_MODULES([GRATE], [libdrm_tegra >= $LIBDRM_TEGRA_REQUIRED])
+ require_libdrm "tegra"
+ ;;
*)
AC_MSG_ERROR([Unknown Gallium driver: $driver])
;;
@@ -2874,6 +2880,7 @@ AM_CONDITIONAL(HAVE_GALLIUM_SWRAST, test "x$HAVE_GALLIUM_SOFTPIPE" = xyes -o \
AM_CONDITIONAL(HAVE_GALLIUM_VC4, test "x$HAVE_GALLIUM_VC4" = xyes)
AM_CONDITIONAL(HAVE_GALLIUM_VC5, test "x$HAVE_GALLIUM_VC5" = xyes)
AM_CONDITIONAL(HAVE_GALLIUM_VIRGL, test "x$HAVE_GALLIUM_VIRGL" = xyes)
+AM_CONDITIONAL(HAVE_GALLIUM_GRATE, test "x$HAVE_GALLIUM_GRATE" = xyes)
AM_CONDITIONAL(HAVE_GALLIUM_STATIC_TARGETS, test "x$enable_shared_pipe_drivers" = xno)
@@ -3003,6 +3010,7 @@ AC_CONFIG_FILES([Makefile
src/gallium/auxiliary/Makefile
src/gallium/auxiliary/pipe-loader/Makefile
src/gallium/drivers/freedreno/Makefile
+ src/gallium/drivers/grate/Makefile
src/gallium/drivers/i915/Makefile
src/gallium/drivers/llvmpipe/Makefile
src/gallium/drivers/nouveau/Makefile
@@ -3048,14 +3056,15 @@ AC_CONFIG_FILES([Makefile
src/gallium/targets/xvmc/Makefile
src/gallium/tests/trivial/Makefile
src/gallium/tests/unit/Makefile
+ src/gallium/winsys/amdgpu/drm/Makefile
src/gallium/winsys/etnaviv/drm/Makefile
- src/gallium/winsys/imx/drm/Makefile
src/gallium/winsys/freedreno/drm/Makefile
+ src/gallium/winsys/tegra/drm/Makefile
src/gallium/winsys/i915/drm/Makefile
+ src/gallium/winsys/imx/drm/Makefile
src/gallium/winsys/nouveau/drm/Makefile
src/gallium/winsys/pl111/drm/Makefile
src/gallium/winsys/radeon/drm/Makefile
- src/gallium/winsys/amdgpu/drm/Makefile
src/gallium/winsys/svga/drm/Makefile
src/gallium/winsys/sw/dri/Makefile
src/gallium/winsys/sw/kms-dri/Makefile
diff --git a/meson.build b/meson.build
index 2288875..8b796ba 100644
--- a/meson.build
+++ b/meson.build
@@ -137,6 +137,7 @@ with_gallium_r600 = false
with_gallium_nouveau = false
with_gallium_freedreno = false
with_gallium_softpipe = false
+with_gallium_grate = false
with_gallium_vc4 = false
with_gallium_vc5 = false
with_gallium_etnaviv = false
@@ -171,6 +172,7 @@ if _drivers != ''
with_gallium_nouveau = _split.contains('nouveau')
with_gallium_freedreno = _split.contains('freedreno')
with_gallium_softpipe = _split.contains('swrast')
+ with_gallium_grate = _split.contains('grate')
with_gallium_vc4 = _split.contains('vc4')
with_gallium_vc5 = _split.contains('vc5')
with_gallium_etnaviv = _split.contains('etnaviv')
@@ -1028,6 +1030,7 @@ dep_libdrm_nouveau = null_dep
dep_libdrm_etnaviv = null_dep
dep_libdrm_freedreno = null_dep
dep_libdrm_intel = null_dep
+dep_libdrm_tegra = null_dep
_drm_amdgpu_ver = '2.4.91'
_drm_radeon_ver = '2.4.71'
@@ -1035,6 +1038,7 @@ _drm_nouveau_ver = '2.4.66'
_drm_etnaviv_ver = '2.4.89'
_drm_freedreno_ver = '2.4.91'
_drm_intel_ver = '2.4.75'
+_drm_tegra_ver = '2.4.81'
_drm_ver = '2.4.75'
_libdrm_checks = [
@@ -1045,6 +1049,7 @@ _libdrm_checks = [
['nouveau', (with_gallium_nouveau or with_dri_nouveau)],
['etnaviv', with_gallium_etnaviv],
['freedreno', with_gallium_freedreno],
+ ['tegra', with_gallium_tegra],
]
# Loop over the enables versions and get the highest libdrm requirement for all
diff --git a/src/gallium/Makefile.am b/src/gallium/Makefile.am
index cf2fe42..dac78ac 100644
--- a/src/gallium/Makefile.am
+++ b/src/gallium/Makefile.am
@@ -78,6 +78,11 @@ if HAVE_GALLIUM_SWR
SUBDIRS += drivers/swr
endif
+## tegra
+if HAVE_GALLIUM_GRATE
+SUBDIRS += drivers/grate winsys/tegra/drm
+endif
+
## vc4/rpi
if HAVE_GALLIUM_VC4
SUBDIRS += drivers/vc4 winsys/vc4/drm
diff --git a/src/gallium/auxiliary/pipe-loader/pipe_loader_drm.c b/src/gallium/auxiliary/pipe-loader/pipe_loader_drm.c
index c6c6b13..57dec10 100644
--- a/src/gallium/auxiliary/pipe-loader/pipe_loader_drm.c
+++ b/src/gallium/auxiliary/pipe-loader/pipe_loader_drm.c
@@ -111,6 +111,11 @@ static const struct drm_driver_descriptor driver_descriptors[] = {
.configuration = pipe_default_configuration_query,
},
{
+ .driver_name = "tegra",
+ .create_screen = pipe_grate_create_screen,
+ .configuration = pipe_default_configuration_query,
+ },
+ {
.driver_name = "virtio_gpu",
.create_screen = pipe_virgl_create_screen,
.configuration = pipe_default_configuration_query,
diff --git a/src/gallium/auxiliary/target-helpers/drm_helper.h b/src/gallium/auxiliary/target-helpers/drm_helper.h
index 7aea83b..ca20ac7 100644
--- a/src/gallium/auxiliary/target-helpers/drm_helper.h
+++ b/src/gallium/auxiliary/target-helpers/drm_helper.h
@@ -263,6 +263,28 @@ pipe_freedreno_create_screen(int fd, const struct pipe_screen_config *config)
#endif
+#ifdef GALLIUM_GRATE
+#include "tegra/drm/tegra_drm_public.h"
+
+struct pipe_screen *
+pipe_grate_create_screen(int fd, const struct pipe_screen_config *config)
+{
+ struct pipe_screen *screen;
+ screen = tegra_drm_screen_create(fd);
+ return screen ? debug_screen_wrap(screen) : NULL;
+}
+
+#else
+
+struct pipe_screen *
+pipe_grate_create_screen(int fd, const struct pipe_screen_config *config)
+{
+ fprintf(stderr, "grate: driver missing\n");
+ return NULL;
+}
+
+#endif
+
#ifdef GALLIUM_VIRGL
#include "virgl/drm/virgl_drm_public.h"
#include "virgl/virgl_public.h"
diff --git a/src/gallium/auxiliary/target-helpers/drm_helper_public.h b/src/gallium/auxiliary/target-helpers/drm_helper_public.h
index e21ea32..0eb6c17 100644
--- a/src/gallium/auxiliary/target-helpers/drm_helper_public.h
+++ b/src/gallium/auxiliary/target-helpers/drm_helper_public.h
@@ -37,6 +37,9 @@ struct pipe_screen *
pipe_virgl_create_screen(int fd, const struct pipe_screen_config *config);
struct pipe_screen *
+pipe_grate_create_screen(int fd, const struct pipe_screen_config *config);
+
+struct pipe_screen *
pipe_vc4_create_screen(int fd, const struct pipe_screen_config *config);
struct pipe_screen *
diff --git a/src/gallium/drivers/grate/Automake.inc b/src/gallium/drivers/grate/Automake.inc
new file mode 100644
index 0000000..c6070a2
--- /dev/null
+++ b/src/gallium/drivers/grate/Automake.inc
@@ -0,0 +1,11 @@
+if HAVE_GALLIUM_GRATE
+
+TARGET_DRIVERS += tegra
+TARGET_CPPFLAGS += -DGALLIUM_GRATE
+TARGET_LIB_DEPS += \
+ $(top_builddir)/src/gallium/winsys/tegra/drm/libtegradrm.la \
+ $(top_builddir)/src/gallium/drivers/grate/libgrate.la \
+ $(GRATE_LIBS) \
+ $(LIBDRM_LIBS)
+
+endif
diff --git a/src/gallium/drivers/grate/Makefile.am b/src/gallium/drivers/grate/Makefile.am
new file mode 100644
index 0000000..08ac201
--- /dev/null
+++ b/src/gallium/drivers/grate/Makefile.am
@@ -0,0 +1,43 @@
+include $(top_srcdir)/src/gallium/Automake.inc
+
+noinst_LTLIBRARIES = libgrate.la
+
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/gallium/drivers/grate/include \
+ -I$(top_srcdir)/src/gallium/drivers \
+ -I$(top_srcdir)/include
+
+AM_CFLAGS = \
+ $(GALLIUM_CFLAGS) \
+ $(LIBDRM_CFLAGS)
+
+libgrate_la_SOURCES = \
+ class_ids.h \
+ host1x01_hardware.h \
+ hw_host1x01_uclass.h \
+ grate_common.h \
+ grate_compiler_fp.c \
+ grate_compiler_vpe.c \
+ grate_compiler.h \
+ grate_context.c \
+ grate_context.h \
+ grate_draw.c \
+ grate_draw.h \
+ grate_fence.h \
+ grate_fp_ir.c \
+ grate_fp_ir.h \
+ grate_fp_vliw.h \
+ grate_program.c \
+ grate_program.h \
+ grate_resource.c \
+ grate_resource.h \
+ grate_screen.c \
+ grate_screen.h \
+ grate_state.c \
+ grate_state.h \
+ grate_stream.c \
+ grate_stream.h \
+ grate_surface.c \
+ grate_surface.h \
+ grate_vpe_ir.c \
+ grate_vpe_ir.h
diff --git a/src/gallium/drivers/grate/class_ids.h b/src/gallium/drivers/grate/class_ids.h
new file mode 100644
index 0000000..4efda30
--- /dev/null
+++ b/src/gallium/drivers/grate/class_ids.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016 Dmitry Osipenko <digetx@gmail.com>
+ * Copyright (C) 2012-2013 NVIDIA Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Arto Merilainen <amerilainen@nvidia.com>
+ */
+
+#ifndef CLASS_IDS_H_
+#define CLASS_IDS_H_
+
+enum host1x_class {
+ HOST1X_CLASS_GR2D = 0x51,
+ HOST1X_CLASS_GR2D_SB = 0x52,
+ HOST1X_CLASS_GR3D = 0x60,
+};
+
+#endif
diff --git a/src/gallium/drivers/grate/grate_common.h b/src/gallium/drivers/grate/grate_common.h
new file mode 100644
index 0000000..d4b2e07
--- /dev/null
+++ b/src/gallium/drivers/grate/grate_common.h
@@ -0,0 +1,18 @@
+#ifndef GRATE_COMMON_H
+#define GRATE_COMMON_H
+
+#include "grate_screen.h"
+
+#define unimplemented() do { \
+ if (grate_debug & GRATE_DEBUG_UNIMPLEMENTED) \
+ printf("TODO: %s()\n", __func__); \
+} while (0)
+
+#define TGR3D_VAL(reg_name, field_name, value) \
+ (((value) << TGR3D_ ## reg_name ## _ ## field_name ## __SHIFT) & \
+ TGR3D_ ## reg_name ## _ ## field_name ## __MASK)
+
+#define TGR3D_BOOL(reg_name, field_name, boolean) \
+ ((boolean) ? TGR3D_ ## reg_name ## _ ## field_name : 0)
+
+#endif
diff --git a/src/gallium/drivers/grate/grate_compiler.h b/src/gallium/drivers/grate/grate_compiler.h
new file mode 100644
index 0000000..068147d
--- /dev/null
+++ b/src/gallium/drivers/grate/grate_compiler.h
@@ -0,0 +1,38 @@
+#ifndef GRATE_COMPILER_H
+#define GRATE_COMPILER_H
+
+#include "util/list.h"
+
+#include <stdint.h>
+
+struct tgsi_parse_context;
+
+struct grate_vpe_shader {
+ struct list_head instructions;
+ uint16_t output_mask;
+};
+
+struct grate_fp_info {
+ struct {
+ uint32_t src;
+ uint32_t dst;
+ } inputs[16];
+ int num_inputs;
+ int color_input;
+ int max_tram_row;
+};
+
+struct grate_fp_shader {
+ struct list_head fp_instructions;
+ struct list_head alu_instructions;
+ struct list_head mfu_instructions;
+ struct grate_fp_info info;
+};
+
+void
+grate_tgsi_to_vpe(struct grate_vpe_shader *vpe, struct tgsi_parse_context *tgsi);
+
+void
+grate_tgsi_to_fp(struct grate_fp_shader *fp, struct tgsi_parse_context *tgsi);
+
+#endif
diff --git a/src/gallium/drivers/grate/grate_compiler_fp.c b/src/gallium/drivers/grate/grate_compiler_fp.c
new file mode 100644
index 0000000..9b0da15
--- /dev/null
+++ b/src/gallium/drivers/grate/grate_compiler_fp.c
@@ -0,0 +1,241 @@
+#include "grate_compiler.h"
+#include "grate_fp_ir.h"
+
+#include "tgsi/tgsi_parse.h"
+
+#include "util/u_memory.h"
+
+static struct fp_alu_src_operand
+fp_alu_src_row(int index)
+{
+ assert(index >= 0 && index < 16);
+ struct fp_alu_src_operand src = {
+ .index = index
+ };
+ return src;
+}
+
+static struct fp_alu_src_operand
+fp_alu_src_reg(int index)
+{
+ assert(index >= 0 && index < 8);
+ struct fp_alu_src_operand src = {
+ .index = 16 + index
+ };
+ return src;
+}
+
+static struct fp_alu_src_operand
+fp_alu_src_zero()
+{
+ struct fp_alu_src_operand src = {
+ .index = 31,
+ .datatype = FP_DATATYPE_FIXED10,
+ .sub_reg_select_high = 0
+ };
+ return src;
+}
+
+static struct fp_alu_src_operand
+fp_alu_src_one()
+{
+ struct fp_alu_src_operand src = {
+ .index = 31,
+ .datatype = FP_DATATYPE_FIXED10,
+ .sub_reg_select_high = 1
+ };
+ return src;
+}
+
+static struct fp_alu_instr
+fp_alu_sMOV(struct fp_alu_dst_operand dst, struct fp_alu_src_operand src)
+{
+ struct fp_alu_instr ret = {
+ .op = FP_ALU_OP_MAD,
+ .dst = dst,
+ .src = {
+ src,
+ fp_alu_src_one(),
+ fp_alu_src_zero(),
+ fp_alu_src_one()
+ }
+ };
+ return ret;
+}
+
+static struct fp_alu_dst_operand
+fp_alu_dst(const struct tgsi_dst_register *dst, int subreg, bool saturate)
+{
+ struct fp_alu_dst_operand ret = { 0 };
+
+ ret.index = dst->Index;
+ if (dst->File == TGSI_FILE_OUTPUT) {
+ ret.index = 2; // HACK: r2+r3 to match hard-coded store shader for now
+
+ // fixed10
+ // swizzle RGBA -> BGRA
+ int o = subreg < 3 ? (2 - subreg) : 3;
+ ret.index += o / 2;
+ ret.write_low_sub_reg = (o % 2) == 0;
+ ret.write_high_sub_reg = (o % 2) != 0;
+ } else
+ ret.index += subreg;
+
+ ret.saturate = saturate;
+
+ return ret;
+}
+
+static void
+emit_vMOV(struct grate_fp_shader *fp, const struct tgsi_dst_register *dst,
+ bool saturate, const struct tgsi_src_register *src)
+{
+ struct fp_instr *inst = CALLOC_STRUCT(fp_instr);
+ list_inithead(&inst->link);
+
+ struct fp_mfu_instr *mfu = NULL;
+ if (src->File == TGSI_FILE_INPUT) {
+ mfu = CALLOC_STRUCT(fp_mfu_instr);
+ list_inithead(&mfu->link);
+ }
+
+ int swizzle[] = {
+ src->SwizzleX,
+ src->SwizzleY,
+ src->SwizzleZ,
+ src->SwizzleW
+ };
+
+ struct fp_alu_instr_packet *alu = CALLOC_STRUCT(fp_alu_instr_packet);
+ int alu_instrs = 0;
+ list_inithead(&alu->link);
+ for (int i = 0; i < 4; ++i) {
+ if ((dst->WriteMask & (1 << i)) == 0)
+ continue;
+
+ int comp = swizzle[i];
+
+ struct fp_alu_src_operand src0 = { };
+ if (src->File == TGSI_FILE_INPUT) {
+ mfu->var[i].op = FP_VAR_OP_FP20;
+ mfu->var[i].tram_row = src->Index;
+ fp->info.max_tram_row = MAX2(fp->info.max_tram_row, src->Index);
+ src0 = fp_alu_src_row(comp);
+ } else
+ src0 = fp_alu_src_reg(src->Index + comp);
+
+ alu->slots[alu_instrs++] = fp_alu_sMOV(fp_alu_dst(dst, i, saturate), src0);
+ }
+ inst->alu_sched.num_instructions = 1;
+ inst->alu_sched.address = list_length(&fp->fp_instructions);
+
+ if (mfu != NULL) {
+ inst->mfu_sched.num_instructions = 1;
+ inst->mfu_sched.address = list_length(&fp->fp_instructions);
+ list_addtail(&mfu->link, &fp->mfu_instructions);
+ }
+
+ if (dst->File == TGSI_FILE_OUTPUT) {
+ inst->dw.enable = 1;
+ inst->dw.index = 1 + dst->Index;
+ inst->dw.stencil_write = 0;
+ inst->dw.src_regs = FP_DW_REGS_R2_R3; // hard-coded for now
+ }
+
+ list_addtail(&alu->link, &fp->alu_instructions);
+ list_addtail(&inst->link, &fp->fp_instructions);
+}
+
+static void
+emit_tgsi_instr(struct grate_fp_shader *fp, const struct tgsi_full_instruction *inst)
+{
+ bool saturate = inst->Instruction.Saturate != 0;
+
+ switch (inst->Instruction.Opcode) {
+ case TGSI_OPCODE_MOV:
+ emit_vMOV(fp, &inst->Dst[0].Register, saturate,
+ &inst->Src[0].Register);
+ break;
+
+ default:
+ unreachable("unsupported TGSI-opcode!");
+ }
+}
+
+#define LINK_SRC(index) ((index) << 3)
+#define LINK_DST(index, comp, type) (((comp) | (type) << 2) << ((index) * 4))
+#define LINK_DST_NONE 0
+#define LINK_DST_FX10_LOW 1
+#define LINK_DST_FX10_HIGH 2
+#define LINK_DST_FP20 3
+
+static void
+emit_tgsi_input(struct grate_fp_shader *fp, const struct tgsi_full_declaration *decl)
+{
+ assert(decl->Range.First == decl->Range.Last);
+
+ uint32_t src = LINK_SRC(1);
+ uint32_t dst = 0;
+ for (int i = 0; i < 4; ++i)
+ dst |= LINK_DST(i, i, LINK_DST_FP20);
+
+ fp->info.inputs[fp->info.num_inputs].src = src;
+ fp->info.inputs[fp->info.num_inputs].dst = dst;
+
+ if (decl->Declaration.Semantic == TGSI_SEMANTIC_COLOR)
+ fp->info.color_input = decl->Range.First;
+
+ fp->info.num_inputs++;
+}
+
+static void
+emit_tgsi_declaration(struct grate_fp_shader *fp, const struct tgsi_full_declaration *decl)
+{
+ switch (decl->Declaration.File) {
+ case TGSI_FILE_INPUT:
+ emit_tgsi_input(fp, decl);
+ break;
+ }
+}
+
+void
+grate_tgsi_to_fp(struct grate_fp_shader *fp, struct tgsi_parse_context *tgsi)
+{
+ list_inithead(&fp->fp_instructions);
+ list_inithead(&fp->alu_instructions);
+ list_inithead(&fp->mfu_instructions);
+
+ fp->info.num_inputs = 0;
+ fp->info.color_input = -1;
+ fp->info.max_tram_row = 1;
+
+ while (!tgsi_parse_end_of_tokens(tgsi)) {
+ tgsi_parse_token(tgsi);
+ switch (tgsi->FullToken.Token.Type) {
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ emit_tgsi_declaration(fp, &tgsi->FullToken.FullDeclaration);
+ break;
+
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ if (tgsi->FullToken.FullInstruction.Instruction.Opcode != TGSI_OPCODE_END)
+ emit_tgsi_instr(fp, &tgsi->FullToken.FullInstruction);
+ break;
+ }
+ }
+
+ /*
+ * HACK: insert barycentric interpolation setup
+ * This will overwrite instructions in some cases, need proper scheduler
+ * to fix properly
+ */
+ struct fp_mfu_instr *first = list_first_entry(&fp->mfu_instructions, struct fp_mfu_instr, link);
+ first->sfu.op = FP_SFU_OP_RCP;
+ first->sfu.reg = 4;
+ first->mul[0].dst = FP_MFU_MUL_DST_BARYCENTRIC_WEIGHT;
+ first->mul[0].src[0] = FP_MFU_MUL_SRC_SFU_RESULT;
+ first->mul[0].src[1] = FP_MFU_MUL_SRC_BARYCENTRIC_COEF_0;
+
+ first->mul[1].dst = FP_MFU_MUL_DST_BARYCENTRIC_WEIGHT;
+ first->mul[1].src[0] = FP_MFU_MUL_SRC_SFU_RESULT;
+ first->mul[1].src[1] = FP_MFU_MUL_SRC_BARYCENTRIC_COEF_1;
+}
diff --git a/src/gallium/drivers/grate/grate_compiler_vpe.c b/src/gallium/drivers/grate/grate_compiler_vpe.c
new file mode 100644
index 0000000..e7d61ef
--- /dev/null
+++ b/src/gallium/drivers/grate/grate_compiler_vpe.c
@@ -0,0 +1,336 @@
+#include "grate_compiler.h"
+#include "grate_vpe_ir.h"
+
+#include "tgsi/tgsi_parse.h"
+
+#include "util/u_memory.h"
+
+static struct vpe_src_operand
+src_undef()
+{
+ struct vpe_src_operand ret = {
+ .file = VPE_SRC_FILE_UNDEF,
+ .index = 0,
+ .swizzle = { VPE_SWZ_X, VPE_SWZ_Y, VPE_SWZ_Z, VPE_SWZ_W }
+ };
+ return ret;
+}
+
+static struct vpe_src_operand
+attrib(int index, const enum vpe_swz swizzle[4], bool negate, bool absolute)
+{
+ struct vpe_src_operand ret = {
+ .file = VPE_SRC_FILE_ATTRIB,
+ .index = index,
+ .negate = negate,
+ .absolute = absolute
+ };
+ memcpy(ret.swizzle, swizzle, sizeof(ret.swizzle));
+ return ret;
+}
+
+static struct vpe_src_operand
+uniform(int index, const enum vpe_swz swizzle[4], bool negate, bool absolute)
+{
+ struct vpe_src_operand ret = {
+ .file = VPE_SRC_FILE_UNIFORM,
+ .index = index,
+ .negate = negate,
+ .absolute = absolute
+ };
+ memcpy(ret.swizzle, swizzle, sizeof(ret.swizzle));
+ return ret;
+}
+
+static struct vpe_src_operand
+src_temp(int index, const enum vpe_swz swizzle[4], bool negate, bool absolute)
+{
+ struct vpe_src_operand ret = {
+ .file = VPE_SRC_FILE_TEMP,
+ .index = index,
+ .negate = negate,
+ .absolute = absolute
+ };
+ memcpy(ret.swizzle, swizzle, sizeof(ret.swizzle));
+ return ret;
+}
+
+static struct vpe_dst_operand
+dst_undef()
+{
+ struct vpe_dst_operand ret = {
+ .file = VPE_DST_FILE_UNDEF,
+ .index = 0,
+ .write_mask = 0,
+ .saturate = 0
+ };
+ return ret;
+}
+
+static struct vpe_dst_operand
+emit_output(struct grate_vpe_shader *vpe, int index,
+ unsigned int write_mask, bool saturate)
+{
+ vpe->output_mask |= 1 << index;
+ struct vpe_dst_operand ret = {
+ .file = VPE_DST_FILE_OUTPUT,
+ .index = index,
+ .write_mask = write_mask,
+ .saturate = saturate
+ };
+ return ret;
+}
+
+static struct vpe_dst_operand
+dst_temp(int index, unsigned int write_mask, bool saturate)
+{
+ struct vpe_dst_operand ret = {
+ .file = VPE_DST_FILE_TEMP,
+ .index = index,
+ .write_mask = write_mask,
+ .saturate = saturate
+ };
+ return ret;
+}
+
+static struct vpe_vec_instr
+emit_vec_unop(enum vpe_vec_op op, struct vpe_dst_operand dst,
+ struct vpe_src_operand src)
+{
+ struct vpe_vec_instr ret = {
+ .op = op,
+ .dst = dst,
+ .src = { src, src_undef(), src_undef() }
+ };
+ return ret;
+}
+
+static struct vpe_vec_instr
+emit_vec_binop(enum vpe_vec_op op, struct vpe_dst_operand dst,
+ struct vpe_src_operand src0, struct vpe_src_operand src1)
+{
+ struct vpe_vec_instr ret = {
+ .op = op,
+ .dst = dst,
+ .src = { src0, src1, src_undef() }
+ };
+ return ret;
+}
+
+static struct vpe_vec_instr
+emit_vNOP()
+{
+ struct vpe_vec_instr ret = {
+ .op = VPE_VEC_OP_NOP,
+ .dst = dst_undef(),
+ .src = { src_undef(), src_undef(), src_undef() }
+ };
+ return ret;
+}
+
+static struct vpe_vec_instr
+emit_vMOV(struct vpe_dst_operand dst, struct vpe_src_operand src)
+{
+ return emit_vec_unop(VPE_VEC_OP_MOV, dst, src);
+}
+
+static struct vpe_vec_instr
+emit_vADD(struct vpe_dst_operand dst, struct vpe_src_operand src0,
+ struct vpe_src_operand src2)
+{
+ struct vpe_vec_instr ret = {
+ .op = VPE_VEC_OP_ADD,
+ .dst = dst,
+ .src = { src0, src_undef(), src2 } // add is "strange" in that it takes src0 and src2
+ };
+ return ret;
+}
+
+#define GEN_V_BINOP(OP) \
+static struct vpe_vec_instr \
+emit_v ## OP (struct vpe_dst_operand dst, struct vpe_src_operand src0, \
+ struct vpe_src_operand src1) \
+{ \
+ return emit_vec_binop(VPE_VEC_OP_ ## OP, dst, src0, src1); \
+}
+
+GEN_V_BINOP(MUL)
+GEN_V_BINOP(DP3)
+GEN_V_BINOP(DP4)
+GEN_V_BINOP(SLT)
+GEN_V_BINOP(MAX)
+
+static struct vpe_vec_instr
+emit_vMAD(struct vpe_dst_operand dst, struct vpe_src_operand src0,
+ struct vpe_src_operand src1, struct vpe_src_operand src2)
+{
+ struct vpe_vec_instr ret = {
+ .op = VPE_VEC_OP_MAD,
+ .dst = dst,
+ .src = { src0, src1, src2 }
+ };
+ return ret;
+}
+
+static struct vpe_scalar_instr
+emit_sNOP()
+{
+ struct vpe_scalar_instr ret = {
+ .op = VPE_SCALAR_OP_NOP,
+ .dst = dst_undef(),
+ .src = src_undef()
+ };
+ return ret;
+}
+
+#define GEN_S_UNOP(OP) \
+static struct vpe_scalar_instr \
+emit_s ## OP (struct vpe_dst_operand dst, struct vpe_src_operand src) \
+{ \
+ struct vpe_scalar_instr ret = { \
+ .op = VPE_SCALAR_OP_ ## OP, \
+ .dst = dst, \
+ .src = src \
+ }; \
+ return ret; \
+}
+
+GEN_S_UNOP(RSQ)
+
+static struct vpe_instr *
+emit_packed(struct vpe_vec_instr vec, struct vpe_scalar_instr scalar)
+{
+ struct vpe_instr *ret = CALLOC_STRUCT(vpe_instr);
+ list_inithead(&ret->link);
+ ret->vec = vec;
+ ret->scalar = scalar;
+ return ret;
+}
+
+static struct vpe_dst_operand
+tgsi_dst_to_vpe(struct grate_vpe_shader *vpe, const struct tgsi_dst_register *dst, bool saturate)
+{
+ switch (dst->File) {
+ case TGSI_FILE_OUTPUT:
+ return emit_output(vpe, dst->Index, dst->WriteMask, saturate);
+
+ case TGSI_FILE_TEMPORARY:
+ return dst_temp(dst->Index, dst->WriteMask, saturate);
+
+ default:
+ unreachable("unsupported output");
+ }
+}
+
+static struct vpe_src_operand
+tgsi_src_to_vpe(struct grate_vpe_shader *vpe, const struct tgsi_src_register *src)
+{
+ enum vpe_swz swizzle[4] = {
+ src->SwizzleX,
+ src->SwizzleY,
+ src->SwizzleZ,
+ src->SwizzleW
+ };
+ bool negate = src->Negate != 0;
+ bool absolute = src->Absolute != 0;
+
+ switch (src->File) {
+ case TGSI_FILE_INPUT:
+ return attrib(src->Index, swizzle, negate, absolute);
+
+ case TGSI_FILE_CONSTANT:
+ return uniform(src->Index, swizzle, negate, absolute);
+
+ case TGSI_FILE_TEMPORARY:
+ return src_temp(src->Index, swizzle, negate, absolute);
+
+ case TGSI_FILE_IMMEDIATE:
+ /* HACK: allocate uniforms from the top for immediates; need to actually record these */
+ return uniform(1023 - src->Index, swizzle, negate, absolute);
+
+ default:
+ unreachable("unsupported input!");
+ }
+}
+
+static struct vpe_instr *
+tgsi_to_vpe(struct grate_vpe_shader *vpe, const struct tgsi_full_instruction *inst)
+{
+ bool saturate = inst->Instruction.Saturate != 0;
+ switch (inst->Instruction.Opcode) {
+ case TGSI_OPCODE_MOV:
+ return emit_packed(emit_vMOV(tgsi_dst_to_vpe(vpe, &inst->Dst[0].Register, saturate),
+ tgsi_src_to_vpe(vpe, &inst->Src[0].Register)),
+ emit_sNOP());
+
+ case TGSI_OPCODE_ADD:
+ return emit_packed(emit_vADD(tgsi_dst_to_vpe(vpe, &inst->Dst[0].Register, saturate),
+ tgsi_src_to_vpe(vpe, &inst->Src[0].Register),
+ tgsi_src_to_vpe(vpe, &inst->Src[1].Register)),
+ emit_sNOP());
+
+ case TGSI_OPCODE_MUL:
+ return emit_packed(emit_vMUL(tgsi_dst_to_vpe(vpe, &inst->Dst[0].Register, saturate),
+ tgsi_src_to_vpe(vpe, &inst->Src[0].Register),
+ tgsi_src_to_vpe(vpe, &inst->Src[1].Register)),
+ emit_sNOP());
+
+ case TGSI_OPCODE_DP3:
+ return emit_packed(emit_vDP3(tgsi_dst_to_vpe(vpe, &inst->Dst[0].Register, saturate),
+ tgsi_src_to_vpe(vpe, &inst->Src[0].Register),
+ tgsi_src_to_vpe(vpe, &inst->Src[1].Register)),
+ emit_sNOP());
+
+ case TGSI_OPCODE_DP4:
+ return emit_packed(emit_vDP4(tgsi_dst_to_vpe(vpe, &inst->Dst[0].Register, saturate),
+ tgsi_src_to_vpe(vpe, &inst->Src[0].Register),
+ tgsi_src_to_vpe(vpe, &inst->Src[1].Register)),
+ emit_sNOP());
+
+ case TGSI_OPCODE_SLT:
+ return emit_packed(emit_vSLT(tgsi_dst_to_vpe(vpe, &inst->Dst[0].Register, saturate),
+ tgsi_src_to_vpe(vpe, &inst->Src[0].Register),
+ tgsi_src_to_vpe(vpe, &inst->Src[1].Register)),
+ emit_sNOP());
+
+ case TGSI_OPCODE_MAX:
+ return emit_packed(emit_vMAX(tgsi_dst_to_vpe(vpe, &inst->Dst[0].Register, saturate),
+ tgsi_src_to_vpe(vpe, &inst->Src[0].Register),
+ tgsi_src_to_vpe(vpe, &inst->Src[1].Register)),
+ emit_sNOP());
+
+ case TGSI_OPCODE_MAD:
+ return emit_packed(emit_vMAD(tgsi_dst_to_vpe(vpe, &inst->Dst[0].Register, saturate),
+ tgsi_src_to_vpe(vpe, &inst->Src[0].Register),
+ tgsi_src_to_vpe(vpe, &inst->Src[1].Register),
+ tgsi_src_to_vpe(vpe, &inst->Src[2].Register)),
+ emit_sNOP());
+
+ case TGSI_OPCODE_RSQ:
+ return emit_packed(emit_vNOP(),
+ emit_sRSQ(tgsi_dst_to_vpe(vpe, &inst->Dst[0].Register, saturate),
+ tgsi_src_to_vpe(vpe, &inst->Src[0].Register)));
+
+ default:
+ unreachable("unsupported TGSI-opcode!");
+ }
+}
+
+void
+grate_tgsi_to_vpe(struct grate_vpe_shader *vpe, struct tgsi_parse_context *tgsi)
+{
+ list_inithead(&vpe->instructions);
+ vpe->output_mask = 0;
+
+ while (!tgsi_parse_end_of_tokens(tgsi)) {
+ tgsi_parse_token(tgsi);
+ switch (tgsi->FullToken.Token.Type) {
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ if (tgsi->FullToken.FullInstruction.Instruction.Opcode != TGSI_OPCODE_END) {
+ struct vpe_instr *instr = tgsi_to_vpe(vpe, &tgsi->FullToken.FullInstruction);
+ list_addtail(&instr->link, &vpe->instructions);
+ }
+ break;
+ }
+ }
+}
diff --git a/src/gallium/drivers/grate/grate_context.c b/src/gallium/drivers/grate/grate_context.c
new file mode 100644
index 0000000..420724a
--- /dev/null
+++ b/src/gallium/drivers/grate/grate_context.c
@@ -0,0 +1,314 @@
+#include <errno.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "util/u_bitcast.h"
+#include "util/u_memory.h"
+#include "util/u_upload_mgr.h"
+
+#include "indices/u_primconvert.h"
+
+#include "grate_common.h"
+#include "grate_context.h"
+#include "grate_draw.h"
+#include "grate_program.h"
+#include "grate_resource.h"
+#include "grate_screen.h"
+#include "grate_state.h"
+#include "grate_surface.h"
+
+#include "host1x01_hardware.h"
+#include "tgr_3d.xml.h"
+
+static int
+init(struct grate_stream *stream)
+{
+ int err = grate_stream_begin(stream);
+ if (err < 0) {
+ fprintf(stderr, "grate_stream_begin() failed: %d\n", err);
+ return err;
+ }
+
+ grate_stream_push_setclass(stream, HOST1X_CLASS_GR3D);
+
+ /* Tegra30 specific stuff */
+ grate_stream_push(stream, host1x_opcode_incr(0x750, 16));
+ for (int i = 0; i < 16; i++)
+ grate_stream_push(stream, 0x00000000);
+
+ grate_stream_push(stream, host1x_opcode_imm(0x907, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0x908, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0x909, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0x90a, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0x90b, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0xb00, 0x3));
+ grate_stream_push(stream, host1x_opcode_imm(0xb01, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0xb04, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0xb06, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0xb07, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0xb08, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0xb09, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0xb0a, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0xb0b, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0xb0c, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0xb0d, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0xb0e, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0xb0f, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0xb10, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0xb11, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0xb12, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0xb14, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0xe40, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0xe41, 0));
+
+ /* Common stuff */
+ grate_stream_push(stream, host1x_opcode_imm(0x00d, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0x00e, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0x00f, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0x010, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0x011, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0x012, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0x013, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0x014, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0x015, 0));
+
+ grate_stream_push(stream, host1x_opcode_imm(TGR3D_VP_ATTRIB_IN_OUT_SELECT, 0));
+ grate_stream_push(stream, host1x_opcode_imm(TGR3D_DRAW_PARAMS, 0));
+
+ grate_stream_push(stream, host1x_opcode_imm(0x124, 0x7));
+ grate_stream_push(stream, host1x_opcode_imm(0x125, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0x126, 0));
+
+ grate_stream_push(stream, host1x_opcode_incr(0x200, 5));
+ grate_stream_push(stream, 0x00000011);
+ grate_stream_push(stream, 0x0000ffff);
+ grate_stream_push(stream, 0x00ff0000);
+ grate_stream_push(stream, 0x00000000);
+ grate_stream_push(stream, 0x00000000);
+
+ grate_stream_push(stream, host1x_opcode_imm(0x209, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0x20a, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0x20b, 0x3));
+ grate_stream_push(stream, host1x_opcode_imm(TGR3D_LINKER_INSTRUCTION(0), 0));
+ grate_stream_push(stream, host1x_opcode_imm(TGR3D_LINKER_INSTRUCTION(1), 0));
+
+ grate_stream_push(stream, host1x_opcode_incr(TGR3D_CULL_FACE_LINKER_SETUP, 25));
+ grate_stream_push(stream, 0xb8e00000); /* TGR3D_CULL_FACE_LINKER_SETUP */
+ grate_stream_push(stream, 0x00000000); /* TGR3D_POLYGON_OFFSET_UNITS */
+ grate_stream_push(stream, 0x00000000); /* TGR3D_POLYGON_OFFSET_FACTOR */
+ grate_stream_push(stream, 0x00000105); /* TGR3D_POINT_PARAMS */
+ grate_stream_push(stream, u_bitcast_f2u(0.5f)); /* TGR3D_POINT_SIZE */
+ grate_stream_push(stream, u_bitcast_f2u(1.0f)); /* TGR3D_POIN_COORD_RANGE_MAX_S */
+ grate_stream_push(stream, u_bitcast_f2u(1.0f)); /* TGR3D_POIN_COORD_RANGE_MAX_T */
+ grate_stream_push(stream, u_bitcast_f2u(0.0f)); /* TGR3D_POIN_COORD_RANGE_MIN_S */
+ grate_stream_push(stream, u_bitcast_f2u(0.0f)); /* TGR3D_POIN_COORD_RANGE_MIN_T */
+ grate_stream_push(stream, 0x00000000); /* TGR2D_LINE_PARAMS */
+ grate_stream_push(stream, u_bitcast_f2u(0.5f)); /* TGR3D_HALF_LINE_WIDTH */
+ grate_stream_push(stream, u_bitcast_f2u(1.0f)); /* 0x34e - unknonwn */
+ grate_stream_push(stream, 0x00000000); /* 0x34f - unknown */
+ grate_stream_push(stream, 0x00000000); /* TGR3D_SCISSOR_HORIZ */
+ grate_stream_push(stream, 0x00000000); /* TGR3D_SCISSOR_VERT */
+ grate_stream_push(stream, u_bitcast_f2u(0.0f)); /* TGR3D_VIEWPORT_X_BIAS */
+ grate_stream_push(stream, u_bitcast_f2u(0.0f)); /* TGR3D_VIEWPORT_Y_BIAS */
+ grate_stream_push(stream, u_bitcast_f2u(0.5f - powf(2.0, -21))); /* TGR3D_VIEWPORT_Z_BIAS */
+ grate_stream_push(stream, u_bitcast_f2u(0.0f)); /* TGR3D_VIEWPORT_X_SCALE */
+ grate_stream_push(stream, u_bitcast_f2u(0.0f)); /* TGR3D_VIEWPORT_Y_SCALE */
+ grate_stream_push(stream, u_bitcast_f2u(0.5f - powf(2.0, -21))); /* TGR3D_VIEWPORT_Z_SCALE */
+ grate_stream_push(stream, u_bitcast_f2u(1.0f)); /* TGR3D_GUARDBAND_WIDTH */
+ grate_stream_push(stream, u_bitcast_f2u(1.0f)); /* TGR3D_GUARDBAND_HEIGHT */
+ grate_stream_push(stream, u_bitcast_f2u(1.0f)); /* TGR3D_GUARDBAND_DEPTH */
+ grate_stream_push(stream, 0x00000205); /* 0x35b - unknown */
+
+ grate_stream_push(stream, host1x_opcode_imm(0x363, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0x364, 0));
+
+ grate_stream_push(stream, host1x_opcode_imm(TGR3D_STENCIL_FRONT1, 0x07ff));
+ grate_stream_push(stream, host1x_opcode_imm(TGR3D_STENCIL_BACK1, 0x07ff));
+
+ grate_stream_push(stream, host1x_opcode_incr(TGR3D_STENCIL_PARAMS, 18));
+ grate_stream_push(stream, 0x00000040); /* TGR3D_STENCIL_PARAMS */
+ grate_stream_push(stream, 0x00000310); /* TGR3D_DEPTH_TEST_PARAMS*/
+ grate_stream_push(stream, 0x00000000); /* TGR3D_DEPTH_RANGE_NEAR */
+ grate_stream_push(stream, 0x000fffff); /* TGR3D_DEPTH_RANGE_FAR */
+ grate_stream_push(stream, 0x00000001); /* 0x406 - unknown */
+ grate_stream_push(stream, 0x00000000);
+ grate_stream_push(stream, 0x00000000);
+ grate_stream_push(stream, 0x00000000);
+ grate_stream_push(stream, 0x1fff1fff);
+ grate_stream_push(stream, 0x00000000);
+ grate_stream_push(stream, 0x00000006);
+ grate_stream_push(stream, 0x00000000);
+ grate_stream_push(stream, 0x00000008);
+ grate_stream_push(stream, 0x00000048);
+ grate_stream_push(stream, 0x00000000);
+ grate_stream_push(stream, 0x00000000);
+ grate_stream_push(stream, 0x00000000);
+ grate_stream_push(stream, 0x00000000);
+
+ grate_stream_push(stream, host1x_opcode_imm(TGR3D_FP_PSEQ_UPLOAD_INST_BUFFER_FLUSH, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0x501, 0x7));
+ grate_stream_push(stream, host1x_opcode_imm(0x502, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0x503, 0));
+
+ grate_stream_push(stream, host1x_opcode_incr(TGR3D_FP_PSEQ_ENGINE_INST, 32));
+ for (int i = 0; i < 32; i++)
+ grate_stream_push(stream, 0);
+
+ grate_stream_push(stream, host1x_opcode_imm(0x540, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0x542, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0x543, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0x544, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0x545, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0x546, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0x60e, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0x702, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0x740, 0x1));
+ grate_stream_push(stream, host1x_opcode_imm(0x741, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0x742, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0x902, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0x903, 0));
+
+ grate_stream_push(stream, host1x_opcode_incr(0xa00, 13));
+ grate_stream_push(stream, 0x00000e00); /* TGR3D_FDC_CONTROL */
+ grate_stream_push(stream, 0x00000000);
+ grate_stream_push(stream, 0x000001ff);
+ grate_stream_push(stream, 0x000001ff);
+ grate_stream_push(stream, 0x000001ff);
+ grate_stream_push(stream, 0x00000030);
+ grate_stream_push(stream, 0x00000020);
+ grate_stream_push(stream, 0x000001ff);
+ grate_stream_push(stream, 0x00000100);
+ grate_stream_push(stream, 0x0f0f0f0f);
+ grate_stream_push(stream, 0x00000000);
+ grate_stream_push(stream, 0x00000000);
+ grate_stream_push(stream, 0x00000000);
+
+ grate_stream_push(stream, host1x_opcode_imm(0xe20, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0xe21, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0xe22, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0xe25, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0xe26, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0xe27, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0xe28, 0));
+ grate_stream_push(stream, host1x_opcode_imm(0xe29, 0));
+
+ grate_stream_end(stream);
+ grate_stream_flush(stream);
+
+ return 0;
+}
+
+static int
+grate_channel_create(struct grate_context *context,
+ enum drm_tegra_class class,
+ struct grate_channel **channelp)
+{
+ struct grate_screen *screen = grate_screen(context->base.screen);
+ int err;
+ struct drm_tegra_channel *drm_channel;
+ struct grate_channel *channel;
+
+ err = drm_tegra_channel_open(&drm_channel, screen->drm, class);
+ if (err < 0)
+ return err;
+
+ channel = CALLOC_STRUCT(grate_channel);
+ if (!channel)
+ return -ENOMEM;
+
+ channel->context = context;
+
+ err = grate_stream_create(screen->drm, drm_channel, &channel->stream, 32768);
+ if (err < 0) {
+ FREE(channel);
+ drm_tegra_channel_close(drm_channel);
+ return err;
+ }
+
+ *channelp = channel;
+
+ return 0;
+}
+
+static void
+grate_channel_delete(struct grate_channel *channel)
+{
+ grate_stream_destroy(&channel->stream);
+ drm_tegra_channel_close(channel->stream.channel);
+ FREE(channel);
+}
+
+static void
+grate_context_destroy(struct pipe_context *pcontext)
+{
+ struct grate_context *context = grate_context(pcontext);
+
+ if (context->primconvert)
+ util_primconvert_destroy(context->primconvert);
+
+ slab_destroy_child(&context->transfer_pool);
+
+ grate_channel_delete(context->gr3d);
+ grate_channel_delete(context->gr2d);
+ FREE(context);
+}
+
+static void
+grate_context_flush(struct pipe_context *pcontext,
+ struct pipe_fence_handle **pfence,
+ enum pipe_flush_flags flags)
+{
+ unimplemented();
+}
+
+struct pipe_context *
+grate_screen_context_create(struct pipe_screen *pscreen,
+ void *priv, unsigned flags)
+{
+ struct grate_screen *screen = grate_screen(pscreen);
+ int err;
+
+ struct grate_context *context = CALLOC_STRUCT(grate_context);
+ if (!context)
+ return NULL;
+
+ context->base.screen = pscreen;
+ context->base.priv = priv;
+
+ context->primconvert = util_primconvert_create(&context->base,
+ (1 << PIPE_PRIM_QUADS) - 1);
+
+ err = grate_channel_create(context, DRM_TEGRA_GR2D, &context->gr2d);
+ if (err < 0) {
+ fprintf(stderr, "grate_channel_create() failed: %d\n", err);
+ return NULL;
+ }
+
+ err = grate_channel_create(context, DRM_TEGRA_GR3D, &context->gr3d);
+ if (err < 0) {
+ fprintf(stderr, "grate_channel_create() failed: %d\n", err);
+ return NULL;
+ }
+
+ init(&context->gr3d->stream);
+
+ slab_create_child(&context->transfer_pool, &screen->transfer_pool);
+
+ context->base.destroy = grate_context_destroy;
+ context->base.flush = grate_context_flush;
+ context->base.stream_uploader = u_upload_create_default(&context->base);
+ context->base.const_uploader = context->base.stream_uploader;
+
+ grate_context_resource_init(&context->base);
+ grate_context_surface_init(&context->base);
+ grate_context_state_init(&context->base);
+ grate_context_blend_init(&context->base);
+ grate_context_sampler_init(&context->base);
+ grate_context_rasterizer_init(&context->base);
+ grate_context_zsa_init(&context->base);
+ grate_context_program_init(&context->base);
+ grate_context_vbo_init(&context->base);
+ grate_context_draw_init(&context->base);
+
+ return &context->base;
+}
diff --git a/src/gallium/drivers/grate/grate_context.h b/src/gallium/drivers/grate/grate_context.h
new file mode 100644
index 0000000..b1bd69b
--- /dev/null
+++ b/src/gallium/drivers/grate/grate_context.h
@@ -0,0 +1,63 @@
+#ifndef GRATE_CONTEXT_H
+#define GRATE_CONTEXT_H
+
+#include "util/slab.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+
+#include "grate_state.h"
+#include "grate_stream.h"
+
+struct primconvert_context;
+
+struct grate_framebuffer_state {
+ struct pipe_framebuffer_state base;
+ int num_rts;
+ struct drm_tegra_bo *bos[16];
+ uint32_t rt_params[16];
+ uint32_t mask;
+};
+
+struct grate_channel {
+ struct grate_context *context;
+ struct grate_stream stream;
+};
+
+struct grate_context {
+ struct pipe_context base;
+ struct primconvert_context *primconvert;
+
+ struct grate_channel *gr2d;
+ struct grate_channel *gr3d;
+
+ struct grate_framebuffer_state framebuffer;
+
+ struct slab_child_pool transfer_pool;
+
+ struct grate_vertex_state *vs;
+ struct grate_vertexbuf_state vbs;
+ struct pipe_constant_buffer constant_buffer[PIPE_SHADER_TYPES];
+
+ struct grate_zsa_state *zsa;
+ struct grate_rasterizer_state *rast;
+
+ struct grate_vertex_shader_state *vshader;
+ struct grate_fragment_shader_state *fshader;
+
+ uint32_t no_scissor[3];
+ uint32_t viewport[10];
+ uint32_t guardband[4];
+};
+
+static inline struct grate_context *
+grate_context(struct pipe_context *context)
+{
+ return (struct grate_context *)context;
+}
+
+struct pipe_context *
+grate_screen_context_create(struct pipe_screen *pscreen,
+ void *priv, unsigned flags);
+
+#endif
diff --git a/src/gallium/drivers/grate/grate_draw.c b/src/gallium/drivers/grate/grate_draw.c
new file mode 100644
index 0000000..c2c4ab4
--- /dev/null
+++ b/src/gallium/drivers/grate/grate_draw.c
@@ -0,0 +1,125 @@
+#include <stdio.h>
+
+#include "pipe/p_state.h"
+#include "util/u_helpers.h"
+#include "util/u_prim.h"
+#include "indices/u_primconvert.h"
+
+#include "grate_common.h"
+#include "grate_context.h"
+#include "grate_draw.h"
+#include "grate_program.h"
+#include "grate_resource.h"
+#include "grate_state.h"
+
+#include "tgr_3d.xml.h"
+#include "host1x01_hardware.h"
+
+static int
+grate_primitive_type(enum pipe_prim_type mode)
+{
+ switch (mode) {
+ case PIPE_PRIM_POINTS:
+ return TGR3D_PRIMITIVE_TYPE_POINTS;
+
+ case PIPE_PRIM_LINES:
+ return TGR3D_PRIMITIVE_TYPE_LINES;
+
+ case PIPE_PRIM_LINE_LOOP:
+ return TGR3D_PRIMITIVE_TYPE_LINE_LOOP;
+
+ case PIPE_PRIM_LINE_STRIP:
+ return TGR3D_PRIMITIVE_TYPE_LINE_STRIP;
+
+ case PIPE_PRIM_TRIANGLES:
+ return TGR3D_PRIMITIVE_TYPE_TRIANGLES;
+
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ return TGR3D_PRIMITIVE_TYPE_TRIANGLE_STRIP;
+
+ case PIPE_PRIM_TRIANGLE_FAN:
+ return TGR3D_PRIMITIVE_TYPE_TRIANGLE_FAN;
+
+ default:
+ unreachable("unexpected enum pipe_prim_type");
+ }
+}
+
+static void
+grate_draw_vbo(struct pipe_context *pcontext,
+ const struct pipe_draw_info *info)
+{
+ int err;
+ uint32_t value;
+ struct grate_context *context = grate_context(pcontext);
+ struct grate_stream *stream = &context->gr3d->stream;
+ uint16_t out_mask = context->vshader->output_mask;
+
+ if (info->mode >= PIPE_PRIM_QUADS) {
+ // the HW can handle non-trimmed sizes, but pimconvert can't
+ if (!u_trim_pipe_prim(info->mode, (unsigned *)&info->count))
+ return;
+
+ util_primconvert_save_rasterizer_state(context->primconvert, &context->rast->base);
+ util_primconvert_draw_vbo(context->primconvert, info);
+ return;
+ }
+
+ err = grate_stream_begin(stream);
+ if (err < 0) {
+ fprintf(stderr, "grate_stream_begin() failed: %d\n", err);
+ return;
+ }
+
+ grate_stream_push_setclass(stream, HOST1X_CLASS_GR3D);
+
+ grate_emit_state(context);
+
+ grate_stream_push(stream, host1x_opcode_incr(TGR3D_VP_ATTRIB_IN_OUT_SELECT, 1));
+ grate_stream_push(stream, ((uint32_t)context->vs->mask << 16) | out_mask);
+
+ struct pipe_resource *index_buffer = NULL;
+ unsigned offset = 0;
+ if (info->index_size > 0) {
+ unsigned index_offset = 0;
+ if (info->has_user_indices) {
+ if (!util_upload_index_buffer(pcontext, info, &index_buffer, &index_offset)) {
+ fprintf(stderr, "util_upload_index_buffer() failed\n");
+ return;
+ }
+ } else
+ index_buffer = info->index.resource;
+
+ index_offset += info->start * info->index_size;
+ grate_stream_push(stream, host1x_opcode_incr(TGR3D_INDEX_PTR, 1));
+ grate_stream_push_reloc(stream, grate_resource(index_buffer)->bo, index_offset);
+ } else
+ offset = info->start;
+
+ /* draw params */
+ assert(info->index_size >= 0 && info->index_size <= 2);
+ value = TGR3D_VAL(DRAW_PARAMS, INDEX_MODE, info->index_size);
+ value |= context->rast->draw_params;
+ value |= TGR3D_VAL(DRAW_PARAMS, PRIMITIVE_TYPE, grate_primitive_type(info->mode));
+ value |= TGR3D_VAL(DRAW_PARAMS, FIRST, info->start);
+ value |= 0xC0000000; /* flush input caches? */
+
+ grate_stream_push(stream, host1x_opcode_incr(TGR3D_DRAW_PARAMS, 1));
+ grate_stream_push(stream, value);
+
+ assert(info->count > 0 && info->count < (1 << 11));
+ value = TGR3D_VAL(DRAW_PRIMITIVES, INDEX_COUNT, info->count - 1);
+ value |= TGR3D_VAL(DRAW_PRIMITIVES, OFFSET, offset);
+ grate_stream_push(stream, host1x_opcode_incr(TGR3D_DRAW_PRIMITIVES, 1));
+ grate_stream_push(stream, value);
+
+ grate_stream_end(stream);
+
+ grate_stream_flush(stream);
+}
+
+void
+grate_context_draw_init(struct pipe_context *pcontext)
+{
+ pcontext->draw_vbo = grate_draw_vbo;
+}
diff --git a/src/gallium/drivers/grate/grate_draw.h b/src/gallium/drivers/grate/grate_draw.h
new file mode 100644
index 0000000..f83f4cb
--- /dev/null
+++ b/src/gallium/drivers/grate/grate_draw.h
@@ -0,0 +1,7 @@
+#ifndef GRATE_DRAW_H
+#define GRATE_DRAW_H
+
+void
+grate_context_draw_init(struct pipe_context *pcontext);
+
+#endif
diff --git a/src/gallium/drivers/grate/grate_fp_ir.c b/src/gallium/drivers/grate/grate_fp_ir.c
new file mode 100644
index 0000000..4fd7861
--- /dev/null
+++ b/src/gallium/drivers/grate/grate_fp_ir.c
@@ -0,0 +1,196 @@
+#include "grate_fp_ir.h"
+
+void
+grate_fp_pack_alu(uint32_t *dst, struct fp_alu_instr *instr)
+{
+ union {
+ struct __attribute__((packed)) {
+ unsigned rD_fixed10:1;
+ unsigned rD_absolute_value:1;
+ unsigned rD_enable:1;
+ unsigned rD_minus_one:1;
+ unsigned rD_sub_reg_select_high:1;
+ unsigned rD_reg_select:1;
+
+ unsigned rC_scale_by_two:1;
+ unsigned rC_negate:1;
+ unsigned rC_absolute_value:1;
+ unsigned rC_fixed10:1;
+ unsigned rC_minus_one:1;
+ unsigned rC_sub_reg_select_high:1;
+ unsigned rC_reg_select:7;
+
+ unsigned rB_scale_by_two:1;
+ unsigned rB_negate:1;
+ unsigned rB_absolute_value:1;
+ unsigned rB_fixed10:1;
+ unsigned rB_minus_one:1;
+ unsigned rB_sub_reg_select_high:1;
+ unsigned rB_reg_select:7;
+
+ unsigned rA_scale_by_two:1;
+ unsigned rA_negate:1;
+ unsigned rA_absolute_value:1;
+ unsigned rA_fixed10:1;
+ unsigned rA_minus_one:1;
+ unsigned rA_sub_reg_select_high:1;
+ unsigned rA_reg_select:7;
+
+ unsigned write_low_sub_reg:1;
+ unsigned write_high_sub_reg:1;
+ unsigned dst_reg:7;
+ unsigned condition_code:2;
+ unsigned saturate_result:1;
+ unsigned scale_result:2;
+
+ unsigned addition_disable:1;
+ unsigned accumulate_result_this:1;
+ unsigned accumulate_result_other:1;
+ unsigned opcode:2;
+ };
+
+ uint32_t words[2];
+ } tmp = {
+ .opcode = instr->op,
+ .dst_reg = instr->dst.index,
+ .saturate_result = instr->dst.saturate,
+
+ .write_low_sub_reg = instr->dst.write_low_sub_reg,
+ .write_high_sub_reg = instr->dst.write_high_sub_reg,
+
+ .rA_reg_select = instr->src[0].index,
+ .rA_fixed10 = instr->src[0].datatype != FP_DATATYPE_FP20,
+ .rA_sub_reg_select_high = instr->src[0].sub_reg_select_high,
+
+ .rB_reg_select = instr->src[1].index,
+ .rB_fixed10 = instr->src[1].datatype != FP_DATATYPE_FP20,
+ .rB_sub_reg_select_high = instr->src[1].sub_reg_select_high,
+
+ .rC_reg_select = instr->src[2].index,
+ .rC_fixed10 = instr->src[2].datatype != FP_DATATYPE_FP20,
+ .rC_sub_reg_select_high = instr->src[2].sub_reg_select_high,
+
+ .rD_reg_select = instr->src[3].index == instr->src[2].index,
+ .rD_fixed10 = instr->src[3].datatype != FP_DATATYPE_FP20,
+ .rD_sub_reg_select_high = instr->src[3].sub_reg_select_high,
+ };
+
+ /* copy packed instruction into destination */
+ for (int i = 0; i < 2; ++i)
+ dst[i] = tmp.words[1 - i];
+}
+
+uint32_t
+grate_fp_pack_dw(struct fp_dw_instr *instr)
+{
+ union {
+ struct __attribute__((packed)) {
+ unsigned enable:1;
+ unsigned unk_1:1;
+ unsigned render_target_index:4;
+ unsigned unk_6_9:4;
+ unsigned stencil_write:1;
+ unsigned unk_11_14:4;
+ unsigned src_regs_select:1;
+ unsigned unk_16_31:16;
+ };
+
+ uint32_t word;
+ } tmp = {
+ .enable = instr->enable,
+ .unk_16_31 = instr->enable ? 2 : 0, // no idea what this is
+ .render_target_index = instr->index,
+ .stencil_write = instr->stencil_write,
+ .src_regs_select = instr->src_regs,
+ };
+
+ return tmp.word;
+}
+
+void
+grate_fp_pack_mfu(uint32_t *dst, struct fp_mfu_instr *instr)
+{
+ union {
+ struct __attribute__((packed)) {
+ unsigned var0_saturate:1;
+ unsigned var0_opcode:2;
+ unsigned var0_source:4;
+
+ unsigned var1_saturate:1;
+ unsigned var1_opcode:2;
+ unsigned var1_source:4;
+
+ unsigned var2_saturate:1;
+ unsigned var2_opcode:2;
+ unsigned var2_source:4;
+
+ unsigned var3_saturate:1;
+ unsigned var3_opcode:2;
+ unsigned var3_source:4;
+
+ unsigned __pad:4;
+
+ unsigned mul0_src0:4;
+ unsigned mul0_src1:4;
+ unsigned mul0_dst:3;
+
+ unsigned mul1_src0:4;
+ unsigned mul1_src1:4;
+ unsigned mul1_dst:3;
+
+ unsigned opcode:4;
+ unsigned reg:6;
+ };
+
+ uint32_t words[2];
+ } tmp = {
+ .opcode = instr->sfu.op,
+ .reg = instr->sfu.reg,
+
+ .mul0_src0 = instr->mul[0].src[0],
+ .mul0_src1 = instr->mul[0].src[1],
+ .mul0_dst = instr->mul[0].dst,
+
+ .mul1_src0 = instr->mul[1].src[0],
+ .mul1_src1 = instr->mul[1].src[1],
+ .mul1_dst = instr->mul[1].dst,
+
+ .var0_saturate = instr->var[0].saturate,
+ .var0_opcode = instr->var[0].op,
+ .var0_source = instr->var[0].tram_row,
+
+ .var1_saturate = instr->var[1].saturate,
+ .var1_opcode = instr->var[1].op,
+ .var1_source = instr->var[1].tram_row,
+
+ .var2_saturate = instr->var[2].saturate,
+ .var2_opcode = instr->var[2].op,
+ .var2_source = instr->var[2].tram_row,
+
+ .var3_saturate = instr->var[3].saturate,
+ .var3_opcode = instr->var[3].op,
+ .var3_source = instr->var[3].tram_row,
+ };
+
+ /* copy packed instruction into destination */
+ for (int i = 0; i < 2; ++i)
+ dst[i] = tmp.words[1 - i];
+}
+
+uint32_t
+grate_fp_pack_sched(struct fp_sched *sched)
+{
+ assert(sched->num_instructions >= 0 && sched->num_instructions < 4);
+ assert(sched->address >= 0 && sched->address < 64);
+ union {
+ struct __attribute__((packed)) {
+ unsigned num_instructions : 2;
+ unsigned address : 6;
+ };
+ uint32_t word;
+ } tmp = {
+ .num_instructions = sched->num_instructions,
+ .address = sched->address
+ };
+ return tmp.word;
+}
diff --git a/src/gallium/drivers/grate/grate_fp_ir.h b/src/gallium/drivers/grate/grate_fp_ir.h
new file mode 100644
index 0000000..f8d1624
--- /dev/null
+++ b/src/gallium/drivers/grate/grate_fp_ir.h
@@ -0,0 +1,168 @@
+#ifndef FP_IR_H
+#define FP_IR_H
+
+#include "util/list.h"
+
+#include "stdbool.h"
+#include "stdint.h"
+
+enum fp_alu_op {
+ FP_ALU_OP_MAD = 0,
+ FP_ALU_OP_MIN = 1,
+ FP_ALU_OP_MAX = 2,
+ FP_ALU_OP_CSEL = 3
+};
+
+enum fp_scale {
+ FP_SCALE_NONE = 0,
+ FP_SCALE_MUL2 = 1,
+ FP_SCALE_MUL4 = 2,
+ FP_SCALE_DIV2 = 3
+};
+
+enum fp_condition {
+ FP_CONDITION_ALWAYS = 0,
+ FP_CONDITION_EQUAL = 1,
+ FP_CONDITION_GEQUAL = 2,
+ FP_CONDITION_GREATER = 3
+};
+
+struct fp_alu_dst_operand {
+ bool write_low_sub_reg;
+ bool write_high_sub_reg;
+ unsigned index;
+ bool saturate;
+};
+
+enum fp_datatype {
+ FP_DATATYPE_FP20 = 0,
+ FP_DATATYPE_FIXED10 = 1
+};
+
+struct fp_alu_src_operand {
+ bool scale_by_two;
+ bool negate;
+ bool absolute_value;
+ enum fp_datatype datatype;
+ bool minus_one;
+ bool sub_reg_select_high;
+ unsigned index;
+};
+
+struct fp_alu_instr {
+ enum fp_condition condition;
+
+ enum fp_alu_op op;
+ enum fp_scale scale;
+
+ struct fp_alu_dst_operand dst;
+ struct fp_alu_src_operand src[4];
+};
+
+enum fp_dw_src_regs {
+ FP_DW_REGS_R0_R1 = 0,
+ FP_DW_REGS_R2_R3 = 1
+};
+
+struct fp_dw_instr {
+ bool enable;
+ int index;
+ bool stencil_write;
+ enum fp_dw_src_regs src_regs;
+};
+
+enum fp_sfu_op {
+ FP_SFU_OP_NOP = 0,
+ FP_SFU_OP_RCP = 1,
+ FP_SFU_OP_RSQ = 2,
+ FP_SFU_OP_LG2 = 3,
+ FP_SFU_OP_EX2 = 4,
+ FP_SFU_OP_SQRT = 5,
+ FP_SFU_OP_SIN = 6,
+ FP_SFU_OP_COS = 7,
+ FP_SFU_OP_FRC = 8,
+ FP_SFU_OP_PREEX2 = 9,
+ FP_SFU_OP_PRESIN = 10,
+ FP_SFU_OP_PRECOS = 11
+};
+
+enum fp_mfu_mul_dst {
+ FP_MFU_MUL_DST_BARYCENTRIC_WEIGHT = 1,
+ FP_MFU_MUL_DST_ROW_REG_0 = 4,
+ FP_MFU_MUL_DST_ROW_REG_1 = 5,
+ FP_MFU_MUL_DST_ROW_REG_2 = 6,
+ FP_MFU_MUL_DST_ROW_REG_3 = 7
+};
+
+enum fp_mfu_mul_src {
+ FP_MFU_MUL_SRC_ROW_REG_0 = 0,
+ FP_MFU_MUL_SRC_ROW_REG_1 = 1,
+ FP_MFU_MUL_SRC_ROW_REG_2 = 2,
+ FP_MFU_MUL_SRC_ROW_REG_3 = 3,
+ FP_MFU_MUL_SRC_SFU_RESULT = 10,
+ FP_MFU_MUL_SRC_BARYCENTRIC_COEF_0 = 11,
+ FP_MFU_MUL_SRC_BARYCENTRIC_COEF_1 = 12,
+ FP_MFU_MUL_SRC_CONST_1 = 13,
+};
+
+struct fp_mfu_mul {
+ enum fp_mfu_mul_dst dst;
+ enum fp_mfu_mul_src src[2];
+};
+
+enum fp_var_op {
+ FP_VAR_OP_NOP = 0,
+ FP_VAR_OP_FP20 = 1,
+ FP_VAR_OP_FX10 = 2,
+};
+
+struct fp_var_instr {
+ bool saturate;
+ enum fp_var_op op;
+ unsigned tram_row;
+};
+
+struct fp_sfu_instr {
+ enum fp_sfu_op op;
+ unsigned reg;
+};
+
+struct fp_mfu_instr {
+ struct list_head link;
+ struct fp_sfu_instr sfu;
+ struct fp_mfu_mul mul[2];
+ struct fp_var_instr var[4];
+};
+
+struct fp_alu_instr_packet {
+ struct list_head link;
+ struct fp_alu_instr slots[4];
+};
+
+struct fp_sched {
+ int num_instructions;
+ int address;
+};
+
+struct fp_instr {
+ struct list_head link;
+ // TODO: PSEQ
+ struct fp_sched mfu_sched;
+ // TODO: TEX
+ struct fp_sched alu_sched;
+ struct fp_dw_instr dw;
+};
+
+void
+grate_fp_pack_alu(uint32_t *dst, struct fp_alu_instr *instr);
+
+uint32_t
+grate_fp_pack_dw(struct fp_dw_instr *instr);
+
+void
+grate_fp_pack_mfu(uint32_t *dst, struct fp_mfu_instr *instr);
+
+uint32_t
+grate_fp_pack_sched(struct fp_sched *sched);
+
+#endif
diff --git a/src/gallium/drivers/grate/grate_fp_vliw.h b/src/gallium/drivers/grate/grate_fp_vliw.h
new file mode 100644
index 0000000..15f5506
--- /dev/null
+++ b/src/gallium/drivers/grate/grate_fp_vliw.h
@@ -0,0 +1,174 @@
+#ifndef FP_VLIW_H
+#define FP_VLIW_H
+
+#include <stdint.h>
+
+union fragment_mfu_instruction {
+ struct __attribute__((packed)) {
+ unsigned var0_saturate:1;
+ unsigned var0_opcode:2;
+ unsigned var0_source:4;
+
+ unsigned var1_saturate:1;
+ unsigned var1_opcode:2;
+ unsigned var1_source:4;
+
+ unsigned var2_saturate:1;
+ unsigned var2_opcode:2;
+ unsigned var2_source:4;
+
+ unsigned var3_saturate:1;
+ unsigned var3_opcode:2;
+ unsigned var3_source:4;
+
+ unsigned __pad:4;
+
+ unsigned mul0_src0:4;
+ unsigned mul0_src1:4;
+ unsigned mul0_dst:3;
+
+ unsigned mul1_src0:4;
+ unsigned mul1_src1:4;
+ unsigned mul1_dst:3;
+
+ unsigned opcode:4;
+ unsigned reg:6;
+ };
+
+ struct __attribute__((packed)) {
+ uint32_t part0;
+ uint32_t part1;
+ };
+};
+
+union fragment_alu_instruction {
+ struct __attribute__((packed)) {
+ unsigned rD_fixed10:1;
+ unsigned rD_absolute_value:1;
+ unsigned rD_enable:1;
+ unsigned rD_minus_one:1;
+ unsigned rD_sub_reg_select_high:1;
+ unsigned rD_reg_select:1;
+
+ unsigned rC_scale_by_two:1;
+ unsigned rC_negate:1;
+ unsigned rC_absolute_value:1;
+ unsigned rC_fixed10:1;
+ unsigned rC_minus_one:1;
+ unsigned rC_sub_reg_select_high:1;
+ unsigned rC_reg_select:7;
+
+ unsigned rB_scale_by_two:1;
+ unsigned rB_negate:1;
+ unsigned rB_absolute_value:1;
+ unsigned rB_fixed10:1;
+ unsigned rB_minus_one:1;
+ unsigned rB_sub_reg_select_high:1;
+ unsigned rB_reg_select:7;
+
+ unsigned rA_scale_by_two:1;
+ unsigned rA_negate:1;
+ unsigned rA_absolute_value:1;
+ unsigned rA_fixed10:1;
+ unsigned rA_minus_one:1;
+ unsigned rA_sub_reg_select_high:1;
+ unsigned rA_reg_select:7;
+
+ unsigned write_low_sub_reg:1;
+ unsigned write_high_sub_reg:1;
+ unsigned dst_reg:7;
+ unsigned condition_code:2;
+ unsigned saturate_result:1;
+ unsigned scale_result:2;
+
+ unsigned addition_disable:1;
+ unsigned accumulate_result_this:1;
+ unsigned accumulate_result_other:1;
+ unsigned opcode:2;
+ };
+
+ struct __attribute__((packed)) {
+ uint32_t part0;
+ uint32_t part1;
+ };
+};
+
+union fragment_alu_instruction_packet {
+ struct __attribute__((packed)) {
+ union fragment_alu_instruction a[4];
+ };
+
+ union {
+ struct __attribute__((packed)) {
+ uint64_t __pad1;
+ uint64_t __pad2;
+ uint64_t __pad3;
+ unsigned __pad4:4;
+ unsigned fx10_low:10;
+ unsigned fx10_high:10;
+ };
+
+ struct __attribute__((packed)) {
+ uint64_t __pad5;
+ uint64_t __pad6;
+ uint64_t __pad7;
+ unsigned __pad8:4;
+ unsigned fp20:20;
+ };
+ } imm0;
+
+ union {
+ struct __attribute__((packed)) {
+ uint64_t __pad1;
+ uint64_t __pad2;
+ uint64_t __pad3;
+ unsigned __pad4:24;
+ unsigned fx10_low:10;
+ unsigned fx10_high:10;
+ };
+
+ struct __attribute__((packed)) {
+ uint64_t __pad5;
+ uint64_t __pad6;
+ uint64_t __pad7;
+ unsigned __pad8:24;
+ unsigned fp20:20;
+ };
+ } imm1;
+
+ union {
+ struct __attribute__((packed)) {
+ uint64_t __pad1;
+ uint64_t __pad2;
+ uint64_t __pad3;
+ uint32_t __pad4;
+ unsigned __pad5:12;
+ unsigned fx10_low:10;
+ unsigned fx10_high:10;
+ };
+
+ struct __attribute__((packed)) {
+ uint64_t __pad6;
+ uint64_t __pad7;
+ uint64_t __pad8;
+ uint32_t __pad9;
+ unsigned __pad10:12;
+ unsigned fp20:20;
+ };
+ } imm2;
+
+ struct __attribute__((packed)) {
+ uint32_t part0;
+ uint32_t part1;
+ uint32_t part2;
+ uint32_t part3;
+ uint32_t part4;
+ uint32_t part5;
+ uint32_t part6;
+ uint32_t part7;
+
+ uint32_t complement;
+ };
+};
+
+#endif // FP_VLIW_H
diff --git a/src/gallium/drivers/grate/grate_program.c b/src/gallium/drivers/grate/grate_program.c
new file mode 100644
index 0000000..e9c8124
--- /dev/null
+++ b/src/gallium/drivers/grate/grate_program.c
@@ -0,0 +1,219 @@
+#include <stdio.h>
+#include <string.h>
+
+#include "util/u_dynarray.h"
+#include "util/u_memory.h"
+
+#include "tgsi/tgsi_dump.h"
+#include "tgsi/tgsi_parse.h"
+
+#include "host1x01_hardware.h"
+#include "grate_common.h"
+#include "grate_context.h"
+#include "grate_screen.h"
+#include "grate_program.h"
+#include "grate_compiler.h"
+#include "grate_fp_ir.h"
+#include "grate_vpe_ir.h"
+#include "tgr_3d.xml.h"
+
+static void *
+grate_create_vs_state(struct pipe_context *pcontext,
+ const struct pipe_shader_state *template)
+{
+ struct grate_vertex_shader_state *so =
+ CALLOC_STRUCT(grate_vertex_shader_state);
+
+ if (!so)
+ return NULL;
+
+ so->base = *template;
+
+ if (grate_debug & GRATE_DEBUG_TGSI) {
+ fprintf(stderr, "DEBUG: TGSI:\n");
+ tgsi_dump(template->tokens, 0);
+ fprintf(stderr, "\n");
+ }
+
+ struct tgsi_parse_context parser;
+ unsigned ok = tgsi_parse_init(&parser, template->tokens);
+ assert(ok == TGSI_PARSE_OK);
+
+ struct grate_vpe_shader vpe;
+ grate_tgsi_to_vpe(&vpe, &parser);
+
+ int num_instructions = list_length(&vpe.instructions);
+ assert(num_instructions < 256);
+ int num_commands = 2 + num_instructions * 4;
+ uint32_t *commands = MALLOC(num_commands * sizeof(uint32_t));
+ if (!commands) {
+ FREE(so);
+ return NULL;
+ }
+
+ commands[0] = host1x_opcode_imm(TGR3D_VP_UPLOAD_INST_ID, 0);
+ commands[1] = host1x_opcode_nonincr(TGR3D_VP_UPLOAD_INST,
+ num_instructions * 4);
+
+ struct vpe_instr *last = list_last_entry(&vpe.instructions, struct vpe_instr, link);
+ int offset = 2;
+ list_for_each_entry(struct vpe_instr, instr, &vpe.instructions, link) {
+ bool end_of_program = instr == last;
+ grate_vpe_pack(commands + offset, instr, end_of_program);
+ offset += 4;
+ }
+
+ so->blob.commands = commands;
+ so->blob.num_commands = num_commands;
+ so->output_mask = vpe.output_mask;
+
+ return so;
+}
+
+static void
+grate_bind_vs_state(struct pipe_context *pcontext, void *so)
+{
+ grate_context(pcontext)->vshader = so;
+}
+
+static void
+grate_delete_vs_state(struct pipe_context *pcontext, void *so)
+{
+ FREE(so);
+}
+
+static void *
+grate_create_fs_state(struct pipe_context *pcontext,
+ const struct pipe_shader_state *template)
+{
+ struct grate_fragment_shader_state *so =
+ CALLOC_STRUCT(grate_fragment_shader_state);
+
+ if (!so)
+ return NULL;
+
+ so->base = *template;
+
+ if (grate_debug & GRATE_DEBUG_TGSI) {
+ fprintf(stderr, "DEBUG: TGSI:\n");
+ tgsi_dump(template->tokens, 0);
+ fprintf(stderr, "\n");
+ }
+
+ struct tgsi_parse_context parser;
+ unsigned ok = tgsi_parse_init(&parser, template->tokens);
+ assert(ok == TGSI_PARSE_OK);
+
+ struct grate_fp_shader fp;
+ grate_tgsi_to_fp(&fp, &parser);
+
+ struct util_dynarray buf;
+ util_dynarray_init(&buf, NULL);
+
+#define PUSH(x) util_dynarray_append(&buf, uint32_t, (x))
+ PUSH(host1x_opcode_incr(TGR3D_ALU_BUFFER_SIZE, 1));
+ PUSH(0x58000000);
+
+ PUSH(host1x_opcode_imm(TGR3D_FP_PSEQ_QUAD_ID, 0));
+ PUSH(host1x_opcode_imm(TGR3D_FP_UPLOAD_INST_ID_COMMON, 0));
+ PUSH(host1x_opcode_imm(TGR3D_FP_UPLOAD_MFU_INST_ID, 0));
+ PUSH(host1x_opcode_imm(TGR3D_FP_UPLOAD_ALU_INST_ID, 0));
+
+ int num_fp_instrs = list_length(&fp.fp_instructions);
+ assert(num_fp_instrs < 64);
+
+ PUSH(host1x_opcode_incr(TGR3D_FP_PSEQ_ENGINE_INST, 1));
+ PUSH(0x20006000 | num_fp_instrs);
+
+ PUSH(host1x_opcode_incr(TGR3D_FP_PSEQ_DW_CFG, 1));
+ PUSH(0x00000040);
+
+ PUSH(host1x_opcode_imm(TGR3D_FP_PSEQ_UPLOAD_INST_BUFFER_FLUSH, 0));
+
+ PUSH(host1x_opcode_nonincr(TGR3D_FP_PSEQ_UPLOAD_INST, num_fp_instrs));
+ list_for_each_entry(struct fp_instr, instr, &fp.fp_instructions, link)
+ PUSH(0x00000000);
+
+ PUSH(host1x_opcode_nonincr(TGR3D_FP_UPLOAD_MFU_SCHED, num_fp_instrs));
+ list_for_each_entry(struct fp_instr, instr, &fp.fp_instructions, link)
+ PUSH(grate_fp_pack_sched(&instr->mfu_sched));
+
+ int num_mfu_instrs = list_length(&fp.mfu_instructions);
+ assert(num_mfu_instrs < 64); // TODO: not sure if this is really correct
+
+ PUSH(host1x_opcode_nonincr(TGR3D_FP_UPLOAD_MFU_INST, num_mfu_instrs * 2));
+ list_for_each_entry(struct fp_mfu_instr, instr, &fp.mfu_instructions, link) {
+ uint32_t words[2];
+ grate_fp_pack_mfu(words, instr);
+ PUSH(words[0]);
+ PUSH(words[1]);
+ }
+
+ // TODO: emit actual instructions here
+ PUSH(host1x_opcode_nonincr(TGR3D_FP_UPLOAD_TEX_INST, num_fp_instrs));
+ for (int i = 0; i < num_fp_instrs; ++i)
+ PUSH(0x00000000);
+
+ PUSH(host1x_opcode_nonincr(TGR3D_FP_UPLOAD_ALU_SCHED, num_fp_instrs));
+ list_for_each_entry(struct fp_instr, instr, &fp.fp_instructions, link)
+ PUSH(grate_fp_pack_sched(&instr->alu_sched));
+
+ int num_alu_instrs = list_length(&fp.alu_instructions);
+ PUSH(host1x_opcode_nonincr(TGR3D_FP_UPLOAD_ALU_INST,
+ num_alu_instrs * 4 * 2));
+ list_for_each_entry(struct fp_alu_instr_packet, instr, &fp.alu_instructions, link) {
+ for (int i = 0; i < 4; ++i) {
+ uint32_t words[2];
+ grate_fp_pack_alu(words, instr->slots + i);
+ PUSH(words[0]);
+ PUSH(words[1]);
+ }
+ }
+
+ PUSH(host1x_opcode_nonincr(TGR3D_FP_UPLOAD_ALU_INST_COMPLEMENT, num_fp_instrs));
+ list_for_each_entry(struct fp_instr, instr, &fp.fp_instructions, link)
+ PUSH(0x00000000);
+
+ PUSH(host1x_opcode_nonincr(TGR3D_FP_UPLOAD_DW_INST, num_fp_instrs));
+ list_for_each_entry(struct fp_instr, instr, &fp.fp_instructions, link)
+ PUSH(grate_fp_pack_dw(&instr->dw));
+
+ uint32_t tram_setup = 0;
+ tram_setup |= TGR3D_VAL(TRAM_SETUP, USED_TRAM_ROWS_NB, fp.info.max_tram_row);
+ tram_setup |= TGR3D_VAL(TRAM_SETUP, DIV64, 64 / fp.info.max_tram_row);
+
+ PUSH(host1x_opcode_incr(TGR3D_TRAM_SETUP, 1));
+ PUSH(tram_setup);
+
+#undef PUSH
+ util_dynarray_trim(&buf);
+
+ so->blob.num_commands = buf.size / sizeof(uint32_t);
+ so->blob.commands = buf.data;
+ so->info = fp.info;
+ return so;
+}
+
+static void
+grate_bind_fs_state(struct pipe_context *pcontext, void *so)
+{
+ grate_context(pcontext)->fshader = so;
+}
+
+static void
+grate_delete_fs_state(struct pipe_context *pcontext, void *so)
+{
+ FREE(so);
+}
+
+void
+grate_context_program_init(struct pipe_context *pcontext)
+{
+ pcontext->create_vs_state = grate_create_vs_state;
+ pcontext->bind_vs_state = grate_bind_vs_state;
+ pcontext->delete_vs_state = grate_delete_vs_state;
+
+ pcontext->create_fs_state = grate_create_fs_state;
+ pcontext->bind_fs_state = grate_bind_fs_state;
+ pcontext->delete_fs_state = grate_delete_fs_state;
+}
diff --git a/src/gallium/drivers/grate/grate_program.h b/src/gallium/drivers/grate/grate_program.h
new file mode 100644
index 0000000..716443f
--- /dev/null
+++ b/src/gallium/drivers/grate/grate_program.h
@@ -0,0 +1,29 @@
+#ifndef GRATE_PROGRAM_H
+#define GRATE_PROGRAM_H
+
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+
+#include "grate_compiler.h"
+
+struct grate_shader_blob {
+ uint32_t *commands;
+ int num_commands;
+};
+
+struct grate_vertex_shader_state {
+ struct pipe_shader_state base;
+ struct grate_shader_blob blob;
+ uint16_t output_mask;
+};
+
+struct grate_fragment_shader_state {
+ struct pipe_shader_state base;
+ struct grate_shader_blob blob;
+ struct grate_fp_info info;
+};
+
+void
+grate_context_program_init(struct pipe_context *pcontext);
+
+#endif
diff --git a/src/gallium/drivers/grate/grate_resource.c b/src/gallium/drivers/grate/grate_resource.c
new file mode 100644
index 0000000..4f9703b
--- /dev/null
+++ b/src/gallium/drivers/grate/grate_resource.c
@@ -0,0 +1,511 @@
+#include <stdio.h>
+
+#include "util/u_format.h"
+#include "util/u_inlines.h"
+#include "util/u_memory.h"
+#include "util/u_pack_color.h"
+#include "util/u_transfer.h"
+#include "util/u_inlines.h"
+
+#include "grate_common.h"
+#include "grate_context.h"
+#include "grate_resource.h"
+#include "grate_screen.h"
+
+#include "host1x01_hardware.h"
+#include "tgr_3d.xml.h"
+
+#include <libdrm/tegra_drm.h>
+#include <libdrm/tegra.h>
+
+/*
+ * XXX Required to access winsys_handle internals. Should go away in favour
+ * of some abstraction to handle handles in a Tegra-specific winsys
+ * implementation.
+ */
+#include "state_tracker/drm_driver.h"
+
+
+static boolean
+grate_resource_get_handle(struct pipe_screen *pscreen,
+ struct pipe_resource *presource,
+ struct winsys_handle *handle)
+{
+ struct grate_resource *resource = grate_resource(presource);
+ int err;
+
+ if (handle->type == DRM_API_HANDLE_TYPE_SHARED) {
+ err = drm_tegra_bo_get_name(resource->bo, &handle->handle);
+ if (err < 0) {
+ fprintf(stderr, "drm_tegra_bo_get_name() failed: %d\n", err);
+ return FALSE;
+ }
+ } else if (handle->type == DRM_API_HANDLE_TYPE_KMS) {
+ err = drm_tegra_bo_get_handle(resource->bo, &handle->handle);
+ if (err < 0) {
+ fprintf(stderr, "drm_tegra_bo_get_handle() failed: %d\n", err);
+ return FALSE;
+ }
+ } else {
+ fprintf(stdout, "unsupported handle type: %d\n", handle->type);
+ return FALSE;
+ }
+
+ handle->stride = resource->pitch;
+ return TRUE;
+}
+
+static void
+grate_resource_destroy(struct pipe_screen *pscreen,
+ struct pipe_resource *presource)
+{
+ struct grate_resource *resource = grate_resource(presource);
+
+ drm_tegra_bo_unref(resource->bo);
+ FREE(resource);
+}
+
+static void *
+grate_resource_transfer_map(struct pipe_context *pcontext,
+ struct pipe_resource *presource,
+ unsigned level, unsigned usage,
+ const struct pipe_box *box,
+ struct pipe_transfer **transfer)
+{
+ struct grate_context *context = grate_context(pcontext);
+ struct grate_resource *resource = grate_resource(presource);
+ void *ret = NULL;
+ struct pipe_transfer *ptrans;
+
+ if (usage & PIPE_TRANSFER_MAP_DIRECTLY)
+ return NULL;
+
+ ptrans = slab_alloc(&context->transfer_pool);
+ if (!ptrans)
+ return NULL;
+
+ if (drm_tegra_bo_map(resource->bo, &ret))
+ return NULL;
+
+ memset(ptrans, 0, sizeof(*ptrans));
+
+ pipe_resource_reference(&ptrans->resource, presource);
+ ptrans->resource = presource;
+ ptrans->level = level;
+ ptrans->usage = usage;
+ ptrans->box = *box;
+ ptrans->stride = resource->pitch;
+ ptrans->layer_stride = ptrans->stride;
+ *transfer = ptrans;
+
+ return (uint8_t *)ret +
+ box->y * resource->pitch +
+ box->x * util_format_get_blocksize(presource->format);
+}
+
+static void
+grate_resource_transfer_flush_region(struct pipe_context *pcontext,
+ struct pipe_transfer *transfer,
+ const struct pipe_box *box)
+{
+ unimplemented();
+}
+
+static void
+grate_resource_transfer_unmap(struct pipe_context *pcontext,
+ struct pipe_transfer *transfer)
+{
+ struct grate_context *context = grate_context(pcontext);
+
+ drm_tegra_bo_unmap(grate_resource(transfer->resource)->bo);
+
+ pipe_resource_reference(&transfer->resource, NULL);
+ slab_free(&context->transfer_pool, transfer);
+}
+
+static const struct u_resource_vtbl grate_resource_vtbl = {
+ .resource_get_handle = grate_resource_get_handle,
+ .resource_destroy = grate_resource_destroy,
+ .transfer_map = grate_resource_transfer_map,
+ .transfer_flush_region = grate_resource_transfer_flush_region,
+ .transfer_unmap = grate_resource_transfer_unmap,
+};
+
+int
+grate_pixel_format(enum pipe_format format)
+{
+ switch (format) {
+ case PIPE_FORMAT_A8_UNORM:
+ return TGR3D_PIXEL_FORMAT_A8;
+ case PIPE_FORMAT_L8_UNORM:
+ return TGR3D_PIXEL_FORMAT_L8;
+ case PIPE_FORMAT_L8A8_UNORM:
+ return TGR3D_PIXEL_FORMAT_LA88;
+ case PIPE_FORMAT_B5G6R5_UNORM:
+ return TGR3D_PIXEL_FORMAT_RGB565;
+ case PIPE_FORMAT_B5G5R5A1_UNORM:
+ return TGR3D_PIXEL_FORMAT_RGBA5551;
+ case PIPE_FORMAT_B4G4R4A4_UNORM:
+ return TGR3D_PIXEL_FORMAT_RGBA4444;
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ case PIPE_FORMAT_B8G8R8X8_UNORM:
+ return TGR3D_PIXEL_FORMAT_RGBA8888;
+ case PIPE_FORMAT_R32G32B32A32_FLOAT:
+ return TGR3D_PIXEL_FORMAT_RGBA_FP32;
+ case PIPE_FORMAT_S8_UINT:
+ return TGR3D_PIXEL_FORMAT_S8;
+ case PIPE_FORMAT_Z16_UNORM:
+ return TGR3D_PIXEL_FORMAT_D16_LINEAR;
+ default:
+ return -1;
+ }
+}
+
+static struct pipe_resource *
+grate_screen_resource_create(struct pipe_screen *pscreen,
+ const struct pipe_resource *template)
+{
+ struct grate_screen *screen = grate_screen(pscreen);
+ struct grate_resource *resource;
+ uint32_t flags = 0, height, size;
+ int err;
+
+ resource = CALLOC_STRUCT(grate_resource);
+ if (!resource)
+ return NULL;
+
+ resource->base.b = *template;
+
+ pipe_reference_init(&resource->base.b.reference, 1);
+ resource->base.vtbl = &grate_resource_vtbl;
+ resource->base.b.screen = pscreen;
+
+ resource->pitch = template->width0 * util_format_get_blocksize(template->format);
+ height = template->height0;
+
+ resource->tiled = 0;
+ if (template->bind & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW |
+ PIPE_BIND_SCANOUT | PIPE_BIND_DEPTH_STENCIL)) {
+ if (template->bind & PIPE_BIND_DEPTH_STENCIL)
+ resource->pitch = align(resource->pitch, 256);
+ else
+ resource->pitch = align(resource->pitch, 32);
+
+ flags = DRM_TEGRA_GEM_CREATE_BOTTOM_UP;
+ }
+
+ if (template->target != PIPE_BUFFER) {
+ /* pick pixel-format */
+ int format = grate_pixel_format(template->format);
+ assert(format >= 0);
+ resource->format = format;
+ }
+
+ size = resource->pitch * height;
+
+ err = drm_tegra_bo_new(&resource->bo, screen->drm, flags, size);
+ if (err < 0) {
+ fprintf(stderr, "drm_tegra_bo_new() failed: %d\n", err);
+ return NULL;
+ }
+
+ return &resource->base.b;
+}
+
+static struct pipe_resource *
+grate_screen_resource_from_handle(struct pipe_screen *pscreen,
+ const struct pipe_resource *template,
+ struct winsys_handle *handle,
+ unsigned usage)
+{
+ struct grate_screen *screen = grate_screen(pscreen);
+ struct grate_resource *resource;
+ int err, format;
+
+ resource = CALLOC_STRUCT(grate_resource);
+ if (!resource)
+ return NULL;
+
+ resource->base.b = *template;
+
+ pipe_reference_init(&resource->base.b.reference, 1);
+ resource->base.vtbl = &grate_resource_vtbl;
+ resource->base.b.screen = pscreen;
+
+ err = drm_tegra_bo_from_name(&resource->bo, screen->drm,
+ handle->handle, 0);
+ if (err < 0) {
+ fprintf(stderr, "drm_tegra_bo_from_name() failed: %d\n", err);
+ FREE(resource);
+ return NULL;
+ }
+
+ resource->pitch = handle->stride;
+
+ format = grate_pixel_format(template->format);
+ assert(format >= 0);
+ resource->format = format;
+
+ return &resource->base.b;
+}
+
+void
+grate_screen_resource_init(struct pipe_screen *pscreen)
+{
+ pscreen->resource_create = grate_screen_resource_create;
+ pscreen->resource_from_handle = grate_screen_resource_from_handle;
+ pscreen->resource_get_handle = u_resource_get_handle_vtbl;
+ pscreen->resource_destroy = u_resource_destroy_vtbl;
+}
+
+static void
+grate_resource_copy_region(struct pipe_context *pcontext,
+ struct pipe_resource *dst,
+ unsigned int dst_level,
+ unsigned int dstx, unsigned dsty,
+ unsigned int dstz,
+ struct pipe_resource *src,
+ unsigned int src_level,
+ const struct pipe_box *box)
+{
+ unimplemented();
+}
+
+static void
+grate_blit(struct pipe_context *pcontext, const struct pipe_blit_info *info)
+{
+ int err, value;
+ struct grate_context *context = grate_context(pcontext);
+ struct grate_channel *gr2d = context->gr2d;
+ struct grate_resource *dst, *src;
+
+ dst = grate_resource(info->dst.resource);
+ src = grate_resource(info->src.resource);
+
+ err = grate_stream_begin(&gr2d->stream);
+ if (err < 0) {
+ fprintf(stderr, "grate_stream_begin() failed: %d\n", err);
+ return;
+ }
+
+ grate_stream_push_setclass(&gr2d->stream, HOST1X_CLASS_GR2D);
+
+ grate_stream_push(&gr2d->stream, host1x_opcode_mask(0x009, 0x9));
+ grate_stream_push(&gr2d->stream, 0x0000003a); /* 0x009 - trigger */
+ grate_stream_push(&gr2d->stream, 0x00000000); /* 0x00c - cmdsel */
+
+ grate_stream_push(&gr2d->stream, host1x_opcode_mask(0x01e, 0x7));
+ grate_stream_push(&gr2d->stream, 0x00000000); /* 0x01e - controlsecond */
+ /*
+ * [20:20] source color depth (0: mono, 1: same)
+ * [17:16] destination color depth (0: 8 bpp, 1: 16 bpp, 2: 32 bpp)
+ */
+
+ value = 1 << 20;
+ switch (util_format_get_blocksize(dst->base.b.format)) {
+ case 1:
+ value |= 0 << 16;
+ break;
+ case 2:
+ value |= 1 << 16;
+ break;
+ case 4:
+ value |= 2 << 16;
+ break;
+ default:
+ assert(0);
+ }
+
+ grate_stream_push(&gr2d->stream, value); /* 0x01f - controlmain */
+ grate_stream_push(&gr2d->stream, 0x000000cc); /* 0x020 - ropfade */
+
+ grate_stream_push(&gr2d->stream, host1x_opcode_nonincr(0x046, 1));
+
+ /*
+ * [20:20] destination write tile mode (0: linear, 1: tiled)
+ * [ 0: 0] tile mode Y/RGB (0: linear, 1: tiled)
+ */
+ value = (dst->tiled << 20) | src->tiled;
+ grate_stream_push(&gr2d->stream, value); /* 0x046 - tilemode */
+
+ grate_stream_push(&gr2d->stream, host1x_opcode_mask(0x02b, 0xe149));
+ grate_stream_push_reloc(&gr2d->stream, dst->bo, 0); /* 0x02b - dstba */
+
+ grate_stream_push(&gr2d->stream, dst->pitch); /* 0x02e - dstst */
+
+ grate_stream_push_reloc(&gr2d->stream, src->bo, 0); /* 0x031 - srcba */
+
+ grate_stream_push(&gr2d->stream, src->pitch); /* 0x033 - srcst */
+
+ value = info->dst.box.height << 16 | info->dst.box.width;
+ grate_stream_push(&gr2d->stream, value); /* 0x038 - dstsize */
+
+ value = info->src.box.y << 16 | info->src.box.x;
+ grate_stream_push(&gr2d->stream, value); /* 0x039 - srcps */
+
+ value = info->dst.box.y << 16 | info->dst.box.x;
+ grate_stream_push(&gr2d->stream, value); /* 0x03a - dstps */
+
+ grate_stream_end(&gr2d->stream);
+
+ grate_stream_flush(&gr2d->stream);
+}
+
+static uint32_t
+pack_color(enum pipe_format format, const float *rgba)
+{
+ union util_color uc;
+ util_pack_color(rgba, format, &uc);
+ return uc.ui[0];
+}
+
+static int
+fill(struct grate_channel *gr2d,
+ struct grate_resource *dst,
+ uint32_t fill_value, int blocksize,
+ unsigned dstx, unsigned dsty,
+ unsigned width, unsigned height)
+{
+ uint32_t value;
+ int err;
+
+ err = grate_stream_begin(&gr2d->stream);
+ if (err < 0) {
+ fprintf(stderr, "grate_stream_begin() failed: %d\n", err);
+ return -1;
+ }
+
+ grate_stream_push_setclass(&gr2d->stream, HOST1X_CLASS_GR2D);
+
+ grate_stream_push(&gr2d->stream, host1x_opcode_mask(0x09, 0x09));
+ grate_stream_push(&gr2d->stream, 0x0000003a); /* 0x009 - trigger */
+ grate_stream_push(&gr2d->stream, 0x00000000); /* 0x00C - cmdsel */
+
+ grate_stream_push(&gr2d->stream, host1x_opcode_mask(0x1e, 0x07));
+ grate_stream_push(&gr2d->stream, 0x00000000); /* 0x01e - controlsecond */
+
+ value = 1 << 6; /* fill mode */
+ value |= 1 << 2; /* turbofill */
+ switch (blocksize) {
+ case 1:
+ value |= 0 << 16;
+ break;
+ case 2:
+ value |= 1 << 16;
+ break;
+ case 4:
+ value |= 2 << 16;
+ break;
+ default:
+ unreachable("invalid blocksize");
+ }
+ grate_stream_push(&gr2d->stream, value); /* 0x01f - controlmain */
+
+ grate_stream_push(&gr2d->stream, 0x000000cc); /* 0x020 - ropfade */
+
+ grate_stream_push(&gr2d->stream, host1x_opcode_mask(0x2b, 0x09));
+ grate_stream_push_reloc(&gr2d->stream, dst->bo, 0);/* 0x02b - dstba */
+ grate_stream_push(&gr2d->stream, dst->pitch); /* 0x02e - dstst */
+
+ grate_stream_push(&gr2d->stream, host1x_opcode_nonincr(0x35, 1));
+
+ grate_stream_push(&gr2d->stream, fill_value); /* 0x035 - srcfgc */
+
+ grate_stream_push(&gr2d->stream, host1x_opcode_nonincr(0x46, 1));
+ grate_stream_push(&gr2d->stream, dst->tiled << 20); /* 0x046 - tilemode */
+
+ grate_stream_push(&gr2d->stream, host1x_opcode_mask(0x38, 0x05));
+ grate_stream_push(&gr2d->stream, height << 16 | width); /* 0x038 - dstsize */
+ grate_stream_push(&gr2d->stream, dsty << 16 | dstx); /* 0x03a - dstps */
+ grate_stream_end(&gr2d->stream);
+
+ grate_stream_flush(&gr2d->stream);
+
+ return 0;
+}
+
+static void
+grate_clear(struct pipe_context *pcontext, unsigned int buffers,
+ const union pipe_color_union *color, double depth,
+ unsigned int stencil)
+{
+ struct grate_context *context = grate_context(pcontext);
+ struct pipe_framebuffer_state *fb;
+
+ fb = &context->framebuffer.base;
+
+ if (buffers & PIPE_CLEAR_COLOR) {
+ int i;
+ for (i = 0; i < fb->nr_cbufs; ++i) {
+ struct pipe_surface *dst = fb->cbufs[i];
+ if (fill(context->gr2d, grate_resource(dst->texture),
+ pack_color(dst->format, color->f),
+ util_format_get_blocksize(dst->format),
+ 0, 0, dst->width, dst->height) < 0)
+ return;
+ }
+ }
+
+ if (buffers & PIPE_CLEAR_DEPTH || buffers & PIPE_CLEAR_STENCIL) {
+ /* TODO: handle the case where both are not set! */
+ if (fill(context->gr2d, grate_resource(fb->zsbuf->texture),
+ util_pack_z_stencil(fb->zsbuf->format, depth, stencil),
+ util_format_get_blocksize(fb->zsbuf->format),
+ 0, 0, fb->zsbuf->width, fb->zsbuf->height) < 0)
+ return;
+ }
+}
+
+static void
+grate_clear_render_target(struct pipe_context *pipe,
+ struct pipe_surface *dst,
+ const union pipe_color_union *color,
+ unsigned dstx, unsigned dsty,
+ unsigned width, unsigned height,
+ bool render_condition_enabled)
+{
+ assert(!render_condition_enabled);
+ fill(grate_context(pipe)->gr2d, grate_resource(dst->texture),
+ pack_color(dst->format, color->f), util_format_get_blocksize(dst->format),
+ dstx, dsty, width, height);
+}
+
+static void
+grate_clear_depth_stencil(struct pipe_context *pipe,
+ struct pipe_surface *dst,
+ unsigned clear_flags,
+ double depth,
+ unsigned stencil,
+ unsigned dstx, unsigned dsty,
+ unsigned width, unsigned height,
+ bool render_condition_enabled)
+{
+ assert(!render_condition_enabled);
+ fill(grate_context(pipe)->gr2d, grate_resource(dst->texture),
+ util_pack_z_stencil(dst->format, depth, stencil),
+ util_format_get_blocksize(dst->format),
+ dstx, dsty, width, height);
+}
+
+static void
+grate_flush_resource(struct pipe_context *ctx, struct pipe_resource *resource)
+{
+ unimplemented();
+}
+
+void
+grate_context_resource_init(struct pipe_context *pcontext)
+{
+ pcontext->transfer_map = u_transfer_map_vtbl;
+ pcontext->transfer_flush_region = u_transfer_flush_region_vtbl;
+ pcontext->transfer_unmap = u_transfer_unmap_vtbl;
+ pcontext->buffer_subdata = u_default_buffer_subdata;
+ pcontext->texture_subdata = u_default_texture_subdata;
+
+ pcontext->resource_copy_region = grate_resource_copy_region;
+ pcontext->blit = grate_blit;
+ pcontext->clear = grate_clear;
+ pcontext->flush_resource = grate_flush_resource;
+ pcontext->clear_render_target = grate_clear_render_target;
+ pcontext->clear_depth_stencil = grate_clear_depth_stencil;
+}
diff --git a/src/gallium/drivers/grate/grate_resource.h b/src/gallium/drivers/grate/grate_resource.h
new file mode 100644
index 0000000..50a73c3
--- /dev/null
+++ b/src/gallium/drivers/grate/grate_resource.h
@@ -0,0 +1,30 @@
+#ifndef GRATE_RESOURCE_H
+#define GRATE_RESOURCE_H
+
+#include "pipe/p_screen.h"
+#include "util/u_transfer.h"
+
+struct grate_resource {
+ struct u_resource base;
+ struct drm_tegra_bo *bo;
+ unsigned int pitch;
+ unsigned int tiled : 1;
+ unsigned int format : 5;
+};
+
+static inline struct grate_resource *
+grate_resource(struct pipe_resource *resource)
+{
+ return (struct grate_resource *)resource;
+}
+
+int
+grate_pixel_format(enum pipe_format format);
+
+void
+grate_context_resource_init(struct pipe_context *pcontext);
+
+void
+grate_screen_resource_init(struct pipe_screen *pscreen);
+
+#endif
diff --git a/src/gallium/drivers/grate/grate_screen.c b/src/gallium/drivers/grate/grate_screen.c
new file mode 100755
index 0000000..a4fda79
--- /dev/null
+++ b/src/gallium/drivers/grate/grate_screen.c
@@ -0,0 +1,609 @@
+#include <stdio.h>
+
+#include "util/u_memory.h"
+
+#include "grate_common.h"
+#include "grate_context.h"
+#include "grate_resource.h"
+#include "grate_screen.h"
+
+static const struct debug_named_value debug_options[] = {
+ { "unimplemented", GRATE_DEBUG_UNIMPLEMENTED,
+ "Print unimplemented functions" },
+ { "tgsi", GRATE_DEBUG_TGSI,
+ "Dump TGSI during program compile" },
+ { NULL }
+};
+
+DEBUG_GET_ONCE_FLAGS_OPTION(grate_debug, "GRATE_DEBUG", debug_options, 0)
+uint32_t grate_debug;
+
+static void
+grate_screen_destroy(struct pipe_screen *pscreen)
+{
+ struct grate_screen *screen = grate_screen(pscreen);
+
+ slab_destroy_parent(&screen->transfer_pool);
+
+ drm_tegra_close(screen->drm);
+ FREE(screen);
+}
+
+static const char *
+grate_screen_get_name(struct pipe_screen *pscreen)
+{
+ return "Tegra";
+}
+
+static const char *
+grate_screen_get_vendor(struct pipe_screen *pscreen)
+{
+ return "Grate";
+}
+
+static const char *
+grate_screen_get_device_vendor(struct pipe_screen *pscreen)
+{
+ return "NVIDIA";
+}
+
+static int
+grate_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
+{
+ switch (param) {
+ case PIPE_CAP_NPOT_TEXTURES:
+ return 1; /* not really, but mesa requires it for now! */
+
+ case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS:
+ return 0; /* ??? */
+
+ case PIPE_CAP_ANISOTROPIC_FILTER:
+ return 0;
+
+ case PIPE_CAP_POINT_SPRITE:
+ return 1;
+
+ case PIPE_CAP_MAX_RENDER_TARGETS:
+ return 8; /* ??? */
+
+ case PIPE_CAP_OCCLUSION_QUERY:
+ return 0; /* ??? */
+
+ case PIPE_CAP_QUERY_TIME_ELAPSED:
+ return 0; /* ??? - can we use syncpts for this? */
+
+ case PIPE_CAP_TEXTURE_SWIZZLE:
+ return 0;
+
+ case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
+ return 16;
+
+ case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
+ return 0;
+
+ case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
+ return 16; /* ??? */
+
+ case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
+ return 0;
+
+ case PIPE_CAP_BLEND_EQUATION_SEPARATE:
+ return 1;
+
+ case PIPE_CAP_SM3:
+ return 1; /* well, not quite. but perhaps close enough? */
+
+ case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS:
+ return 0;
+
+ case PIPE_CAP_PRIMITIVE_RESTART:
+ return 0; /* probably possible to do by splitting draws, but not sure */
+
+ case PIPE_CAP_INDEP_BLEND_ENABLE:
+ return 0; /* ??? */
+
+ case PIPE_CAP_INDEP_BLEND_FUNC:
+ return 0; /* ??? */
+
+ case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS:
+ return 0;
+
+ case PIPE_CAP_DEPTH_CLIP_DISABLE:
+ return 0; /* ??? */
+
+ case PIPE_CAP_SHADER_STENCIL_EXPORT:
+ return 0; /* ??? */
+
+ case PIPE_CAP_TGSI_INSTANCEID:
+ case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR:
+ return 0;
+
+ case PIPE_CAP_FRAGMENT_COLOR_CLAMPED:
+ return 0; /* probably not */
+
+ case PIPE_CAP_SEAMLESS_CUBE_MAP:
+ case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE:
+ return 0; /* probably not */
+
+ case PIPE_CAP_MIN_TEXEL_OFFSET:
+ case PIPE_CAP_MAX_TEXEL_OFFSET:
+ return 0;
+
+ case PIPE_CAP_CONDITIONAL_RENDER:
+ return 0; /* probably not */
+
+ case PIPE_CAP_TEXTURE_BARRIER:
+ return 0; /* no clue */
+
+ case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS:
+ case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS:
+ case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME:
+ return 0;
+
+ case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS:
+ return 0; /* probably */
+
+ case PIPE_CAP_VERTEX_COLOR_UNCLAMPED:
+ return 1; /* probably irrelevant for GLES2 */
+
+ case PIPE_CAP_VERTEX_COLOR_CLAMPED:
+ return 0; /* probably irrelevant for GLES2 */
+
+ case PIPE_CAP_GLSL_FEATURE_LEVEL:
+ return 120; /* no clue */
+
+ case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION:
+ return 0; /* no idea, need to test */
+
+ case PIPE_CAP_USER_VERTEX_BUFFERS:
+ return 0; /* probably possible, but nasty for kernel */
+
+ case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY:
+ case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY:
+ case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY:
+ return 0;
+
+ case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
+ return 4; /* DWORD aligned, can do pure data GATHER */
+
+ case PIPE_CAP_START_INSTANCE:
+ return 0;
+
+ case PIPE_CAP_QUERY_TIMESTAMP:
+ return 0; /* dunno */
+
+ case PIPE_CAP_BUFFER_SAMPLER_VIEW_RGBA_ONLY:
+ return 0;
+
+ case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT:
+ return 0;
+
+ case PIPE_CAP_CUBE_MAP_ARRAY:
+ return 0;
+
+ case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:
+ case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
+ case PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE:
+ return 0;
+
+ case PIPE_CAP_TGSI_TEXCOORD:
+ return 0;
+
+ case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER:
+ return 1;
+
+ case PIPE_CAP_COMPUTE:
+ case PIPE_CAP_TEXTURE_MULTISAMPLE:
+ case PIPE_CAP_QUERY_PIPELINE_STATISTICS:
+ case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK:
+ return 0;
+
+ case PIPE_CAP_MAX_VIEWPORTS:
+ return 1;
+
+ case PIPE_CAP_MIXED_FRAMEBUFFER_SIZES:
+ return 1;
+
+ case PIPE_CAP_MAX_GEOMETRY_OUTPUT_VERTICES:
+ case PIPE_CAP_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS:
+ case PIPE_CAP_MAX_VERTEX_STREAMS:
+ return 0;
+
+ case PIPE_CAP_MAX_TEXTURE_GATHER_COMPONENTS:
+ case PIPE_CAP_MIN_TEXTURE_GATHER_OFFSET:
+ case PIPE_CAP_MAX_TEXTURE_GATHER_OFFSET:
+ case PIPE_CAP_BUFFER_MAP_PERSISTENT_COHERENT: /* dunno */
+ case PIPE_CAP_TEXTURE_QUERY_LOD:
+ case PIPE_CAP_SAMPLE_SHADING:
+ return 0;
+
+ case PIPE_CAP_DRAW_INDIRECT:
+ case PIPE_CAP_TGSI_FS_FINE_DERIVATIVE:
+ return 0;
+
+ case PIPE_CAP_VENDOR_ID:
+ return 0x10de;
+
+ case PIPE_CAP_DEVICE_ID:
+ return 0xFFFFFFFF;
+
+ case PIPE_CAP_ACCELERATED:
+ return 1;
+
+ case PIPE_CAP_VIDEO_MEMORY:
+ return 0;
+
+ case PIPE_CAP_UMA:
+ return 1;
+
+ case PIPE_CAP_CONDITIONAL_RENDER_INVERTED:
+ return 0; /* no support, shouldn't matter */
+
+ case PIPE_CAP_MAX_VERTEX_ATTRIB_STRIDE:
+ return (1 << 24) - 1;
+
+ case PIPE_CAP_SAMPLER_VIEW_TARGET:
+ case PIPE_CAP_CLIP_HALFZ:
+ case PIPE_CAP_POLYGON_OFFSET_CLAMP:
+ case PIPE_CAP_RESOURCE_FROM_USER_MEMORY:
+ case PIPE_CAP_DEVICE_RESET_STATUS_QUERY:
+ return 0;
+
+ case PIPE_CAP_MAX_SHADER_PATCH_VARYINGS:
+ return 0;
+
+ case PIPE_CAP_TEXTURE_FLOAT_LINEAR:
+ case PIPE_CAP_TEXTURE_HALF_FLOAT_LINEAR:
+ case PIPE_CAP_DEPTH_BOUNDS_TEST:
+ case PIPE_CAP_TGSI_TXQS:
+ return 0;
+
+ case PIPE_CAP_SHAREABLE_SHADERS:
+ return 1;
+
+ case PIPE_CAP_COPY_BETWEEN_COMPRESSED_AND_PLAIN_FORMATS:
+ case PIPE_CAP_CLEAR_TEXTURE: /* might be possible */
+ case PIPE_CAP_DRAW_PARAMETERS:
+ case PIPE_CAP_TGSI_PACK_HALF_FLOAT:
+ case PIPE_CAP_MULTI_DRAW_INDIRECT:
+ case PIPE_CAP_MULTI_DRAW_INDIRECT_PARAMS:
+ return 0;
+
+ case PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL:
+ case PIPE_CAP_TGSI_FS_FACE_IS_INTEGER_SYSVAL:
+ return 0; /* not really sure about these */
+
+ case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT:
+ case PIPE_CAP_INVALIDATE_BUFFER: /* not sure */
+ case PIPE_CAP_STRING_MARKER:
+ case PIPE_CAP_SURFACE_REINTERPRET_BLOCKS: /* can probably be supported */
+ case PIPE_CAP_QUERY_BUFFER_OBJECT:
+ case PIPE_CAP_QUERY_MEMORY_INFO:
+ case PIPE_CAP_FRAMEBUFFER_NO_ATTACHMENT: /* not sure */
+ case PIPE_CAP_ROBUST_BUFFER_ACCESS_BEHAVIOR: /* probably not */
+ case PIPE_CAP_CULL_DISTANCE: /* don't know */
+ case PIPE_CAP_PRIMITIVE_RESTART_FOR_PATCHES:
+ case PIPE_CAP_TGSI_VOTE:
+ case PIPE_CAP_MAX_WINDOW_RECTANGLES:
+ return 0;
+
+ case PIPE_CAP_VIEWPORT_SUBPIXEL_BITS:
+ return 4; /* minimum for GLES 2.0, might be more */
+
+ case PIPE_CAP_MIXED_COLOR_DEPTH_BITS:
+ return 1; /* probably true ? */
+
+ case PIPE_CAP_MIXED_COLORBUFFER_FORMATS:
+ return 1; /* can't see why not... */
+
+ case PIPE_CAP_STREAM_OUTPUT_INTERLEAVE_BUFFERS:
+ case PIPE_CAP_GLSL_OPTIMIZE_CONSERVATIVELY:
+ case PIPE_CAP_TGSI_FS_FBFETCH: /* supported, but let's enable later */
+ case PIPE_CAP_TEXTURE_GATHER_OFFSETS:
+ case PIPE_CAP_DOUBLES:
+ case PIPE_CAP_INT64:
+ case PIPE_CAP_INT64_DIVMOD:
+ case PIPE_CAP_TGSI_CAN_READ_OUTPUTS:
+ case PIPE_CAP_TGSI_TEX_TXF_LZ:
+ case PIPE_CAP_TGSI_CLOCK:
+ case PIPE_CAP_POLYGON_MODE_FILL_RECTANGLE:
+ case PIPE_CAP_SPARSE_BUFFER_PAGE_SIZE:
+ case PIPE_CAP_TGSI_BALLOT:
+ case PIPE_CAP_NATIVE_FENCE_FD:
+ case PIPE_CAP_CAN_BIND_CONST_BUFFER_AS_VERTEX:
+ case PIPE_CAP_ALLOW_MAPPED_BUFFERS_DURING_EXECUTION:
+ case PIPE_CAP_POST_DEPTH_COVERAGE:
+ case PIPE_CAP_BINDLESS_TEXTURE:
+ case PIPE_CAP_QUERY_SO_OVERFLOW:
+ case PIPE_CAP_MEMOBJ:
+ case PIPE_CAP_LOAD_CONSTBUF:
+ case PIPE_CAP_TGSI_ANY_REG_AS_ADDRESS:
+ case PIPE_CAP_TILE_RASTER_ORDER:
+ case PIPE_CAP_MAX_COMBINED_SHADER_OUTPUT_RESOURCES:
+ case PIPE_CAP_SIGNED_VERTEX_BUFFER_OFFSET:
+ return 0;
+
+ default:
+ fprintf(stdout, "%s: unsupported parameter: %d\n", __func__, param);
+ return 0;
+ }
+}
+
+static float
+grate_screen_get_paramf(struct pipe_screen *pscreen,
+ enum pipe_capf param)
+{
+ switch (param) {
+ case PIPE_CAPF_MAX_LINE_WIDTH:
+ case PIPE_CAPF_MAX_LINE_WIDTH_AA:
+ case PIPE_CAPF_MAX_POINT_WIDTH:
+ case PIPE_CAPF_MAX_POINT_WIDTH_AA:
+ return 8192.0f; /* no clue */
+
+ case PIPE_CAPF_MAX_TEXTURE_ANISOTROPY:
+ return 0.0f;
+
+ case PIPE_CAPF_MAX_TEXTURE_LOD_BIAS:
+ return 16.0f;
+
+ default:
+ fprintf(stdout, "%s: unsupported parameter: %d\n", __func__, param);
+ return 0.0f;
+ }
+}
+
+static int
+grate_screen_get_shader_param(struct pipe_screen *pscreen,
+ unsigned int shader,
+ enum pipe_shader_cap param)
+{
+ switch (shader) {
+ case PIPE_SHADER_VERTEX:
+ switch (param) {
+
+ case PIPE_SHADER_CAP_MAX_INSTRUCTIONS:
+ case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS:
+ return 1024;
+
+ /* no vertex-texturing */
+ case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS:
+ case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS:
+ case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
+ case PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS:
+ return 0;
+
+ case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH:
+ case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED:
+ case PIPE_SHADER_CAP_SUBROUTINES:
+ return 0;
+
+ case PIPE_SHADER_CAP_MAX_INPUTS:
+ case PIPE_SHADER_CAP_MAX_OUTPUTS:
+ return 16;
+
+ case PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE:
+ case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
+ return 1024;
+
+ case PIPE_SHADER_CAP_MAX_TEMPS:
+ return 64 * 4; /* 64 vec4s */
+
+ /* cannot index attributes, varyings nor GPRs */
+ case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:
+ case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR:
+ case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR:
+ return 0;
+
+ case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR:
+ return 1; /* can index constant registers */
+
+ case PIPE_SHADER_CAP_INTEGERS:
+ case PIPE_SHADER_CAP_MAX_SHADER_IMAGES:
+ return 0;
+
+ case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED:
+ return 1;
+
+ case PIPE_SHADER_CAP_TGSI_DROUND_SUPPORTED:
+ case PIPE_SHADER_CAP_TGSI_DFRACEXP_DLDEXP_SUPPORTED:
+ case PIPE_SHADER_CAP_TGSI_FMA_SUPPORTED:
+ case PIPE_SHADER_CAP_MAX_SHADER_BUFFERS:
+ return 0;
+
+ case PIPE_SHADER_CAP_TGSI_ANY_INOUT_DECL_RANGE:
+ return 0;
+
+ case PIPE_SHADER_CAP_MAX_UNROLL_ITERATIONS_HINT:
+ return INT_MAX;
+
+ case PIPE_SHADER_CAP_SUPPORTED_IRS:
+ return PIPE_SHADER_IR_TGSI;
+
+ case PIPE_SHADER_CAP_PREFERRED_IR:
+ return PIPE_SHADER_IR_TGSI;
+
+ case PIPE_SHADER_CAP_LOWER_IF_THRESHOLD:
+ return INT_MAX;
+
+ case PIPE_SHADER_CAP_TGSI_SKIP_MERGE_REGISTERS:
+ return 0;
+
+ case PIPE_SHADER_CAP_TGSI_LDEXP_SUPPORTED:
+ return 0;
+
+ case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTERS:
+ case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTER_BUFFERS:
+ return 0;
+
+ default:
+ fprintf(stdout, "%s: unsupported vertex-shader parameter: %d\n", __func__, param);
+ return 0;
+ }
+
+ case PIPE_SHADER_FRAGMENT:
+
+ switch (param) {
+ case PIPE_SHADER_CAP_MAX_INSTRUCTIONS:
+ return 4 * 128;
+
+ case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS:
+ return 4 * 128;
+
+ case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS:
+ return 128;
+
+ case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS:
+ return 128;
+
+ /* no control flow */
+ case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH:
+ case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED:
+ case PIPE_SHADER_CAP_SUBROUTINES:
+ return 0;
+
+ case PIPE_SHADER_CAP_MAX_INPUTS:
+ case PIPE_SHADER_CAP_MAX_OUTPUTS:
+ return 16;
+
+ case PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE:
+ case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
+ return 32;
+
+ case PIPE_SHADER_CAP_MAX_TEMPS:
+ return 16; /* scalars */
+
+ /* no indirection */
+ case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:
+ case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR:
+ case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR:
+ case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR:
+ return 0;
+
+ case PIPE_SHADER_CAP_INTEGERS:
+ case PIPE_SHADER_CAP_MAX_SHADER_IMAGES:
+ return 0;
+
+ case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
+ case PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS:
+ return 16;
+
+ case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED:
+ return 1;
+
+ case PIPE_SHADER_CAP_TGSI_DROUND_SUPPORTED:
+ case PIPE_SHADER_CAP_TGSI_DFRACEXP_DLDEXP_SUPPORTED:
+ return 0;
+
+ case PIPE_SHADER_CAP_TGSI_FMA_SUPPORTED:
+ return 0; /* might really be true, but need more testing to be sure */
+
+ case PIPE_SHADER_CAP_TGSI_ANY_INOUT_DECL_RANGE:
+ return 0;
+
+ case PIPE_SHADER_CAP_MAX_UNROLL_ITERATIONS_HINT:
+ return INT_MAX;
+
+ case PIPE_SHADER_CAP_MAX_SHADER_BUFFERS:
+ return 0;
+
+ case PIPE_SHADER_CAP_SUPPORTED_IRS:
+ return PIPE_SHADER_IR_TGSI;
+
+ case PIPE_SHADER_CAP_PREFERRED_IR:
+ return PIPE_SHADER_IR_TGSI;
+
+ case PIPE_SHADER_CAP_LOWER_IF_THRESHOLD:
+ return INT_MAX;
+
+ case PIPE_SHADER_CAP_TGSI_SKIP_MERGE_REGISTERS:
+ return 0;
+
+ case PIPE_SHADER_CAP_TGSI_LDEXP_SUPPORTED:
+ return 0;
+
+ case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTERS:
+ case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTER_BUFFERS:
+ return 0;
+
+ default:
+ fprintf(stdout, "%s: unsupported fragment-shader parameter: %d\n", __func__, param);
+ return 0;
+ }
+ break;
+
+ case PIPE_SHADER_GEOMETRY:
+ case PIPE_SHADER_TESS_CTRL:
+ case PIPE_SHADER_TESS_EVAL:
+ case PIPE_SHADER_COMPUTE:
+ return 0;
+
+ default:
+ fprintf(stdout, "%s: unknown shader type: %u\n", __func__, shader);
+ return 0;
+ }
+}
+
+static boolean
+grate_screen_is_format_supported(struct pipe_screen *pscreen,
+ enum pipe_format format,
+ enum pipe_texture_target target,
+ unsigned int sample_count,
+ unsigned int usage)
+{
+ if (usage & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_DEPTH_STENCIL)) {
+ if (grate_pixel_format(format) < 0)
+ return false;
+ }
+
+ return true;
+}
+
+static void
+grate_screen_fence_reference(struct pipe_screen *pscreen,
+ struct pipe_fence_handle **ptr,
+ struct pipe_fence_handle *fence)
+{
+ unimplemented();
+}
+
+static boolean
+grate_screen_fence_finish(struct pipe_screen *screen,
+ struct pipe_context *ctx,
+ struct pipe_fence_handle *fence,
+ uint64_t timeout)
+{
+ unimplemented();
+ return FALSE;
+}
+
+struct pipe_screen *
+grate_screen_create(struct drm_tegra *drm)
+{
+ struct grate_screen *screen = CALLOC_STRUCT(grate_screen);
+ if (!screen)
+ return NULL;
+
+ screen->drm = drm;
+
+ grate_debug = debug_get_option_grate_debug();
+
+ screen->base.destroy = grate_screen_destroy;
+ screen->base.get_name = grate_screen_get_name;
+ screen->base.get_vendor = grate_screen_get_vendor;
+ screen->base.get_device_vendor = grate_screen_get_device_vendor;
+ screen->base.get_param = grate_screen_get_param;
+ screen->base.get_paramf = grate_screen_get_paramf;
+ screen->base.get_shader_param = grate_screen_get_shader_param;
+ screen->base.context_create = grate_screen_context_create;
+ screen->base.is_format_supported = grate_screen_is_format_supported;
+
+ /* fence functions */
+ screen->base.fence_reference = grate_screen_fence_reference;
+ screen->base.fence_finish = grate_screen_fence_finish;
+
+ grate_screen_resource_init(&screen->base);
+
+ slab_create_parent(&screen->transfer_pool, sizeof(struct pipe_transfer), 16);
+
+ return &screen->base;
+}
diff --git a/src/gallium/drivers/grate/grate_screen.h b/src/gallium/drivers/grate/grate_screen.h
new file mode 100644
index 0000000..d3b56d1
--- /dev/null
+++ b/src/gallium/drivers/grate/grate_screen.h
@@ -0,0 +1,31 @@
+#ifndef GRATE_SCREEN_H
+#define GRATE_SCREEN_H
+
+#include "pipe/p_screen.h"
+#include "util/slab.h"
+
+#include <libdrm/tegra.h>
+
+extern uint32_t grate_debug;
+
+#define GRATE_DEBUG_UNIMPLEMENTED 0x1
+#define GRATE_DEBUG_TGSI 0x2
+
+struct grate_screen {
+ struct pipe_screen base;
+
+ struct slab_parent_pool transfer_pool;
+
+ struct drm_tegra *drm;
+};
+
+static inline struct grate_screen *
+grate_screen(struct pipe_screen *screen)
+{
+ return (struct grate_screen *)screen;
+}
+
+struct pipe_screen *
+grate_screen_create(struct drm_tegra *drm);
+
+#endif
diff --git a/src/gallium/drivers/grate/grate_state.c b/src/gallium/drivers/grate/grate_state.c
new file mode 100644
index 0000000..0660ab9
--- /dev/null
+++ b/src/gallium/drivers/grate/grate_state.c
@@ -0,0 +1,634 @@
+#include <stdio.h>
+#include <math.h>
+
+#include "util/u_bitcast.h"
+#include "util/u_helpers.h"
+#include "util/u_inlines.h"
+#include "util/u_memory.h"
+#include "util/u_format.h"
+
+#include "grate_common.h"
+#include "grate_context.h"
+#include "grate_program.h"
+#include "grate_resource.h"
+#include "grate_state.h"
+
+#include "tgr_3d.xml.h"
+#include "host1x01_hardware.h"
+
+static void
+grate_set_sample_mask(struct pipe_context *pcontext,
+ unsigned int sample_mask)
+{
+ unimplemented();
+}
+
+static void
+grate_set_constant_buffer(struct pipe_context *pcontext,
+ unsigned int shader, unsigned int index,
+ const struct pipe_constant_buffer *buffer)
+{
+ struct grate_context *context = grate_context(pcontext);
+
+ assert(index == 0);
+ assert(!buffer || buffer->user_buffer);
+
+ util_copy_constant_buffer(&context->constant_buffer[shader], buffer);
+}
+
+static void
+grate_set_framebuffer_state(struct pipe_context *pcontext,
+ const struct pipe_framebuffer_state *framebuffer)
+{
+ struct grate_context *context = grate_context(pcontext);
+ struct pipe_framebuffer_state *cso = &context->framebuffer.base;
+ unsigned int i;
+ uint32_t mask = 0;
+
+ if (framebuffer->zsbuf) {
+ struct grate_resource *res = grate_resource(framebuffer->zsbuf->texture);
+ uint32_t rt_params;
+
+ rt_params = TGR3D_VAL(RT_PARAMS, FORMAT, res->format);
+ rt_params |= TGR3D_VAL(RT_PARAMS, PITCH, res->pitch);
+ rt_params |= TGR3D_BOOL(RT_PARAMS, TILED, res->tiled);
+
+ context->framebuffer.rt_params[0] = rt_params;
+ context->framebuffer.bos[0] = res->bo;
+ mask |= 1;
+ } else {
+ context->framebuffer.rt_params[0] = 0;
+ context->framebuffer.bos[0] = NULL;
+ }
+
+ pipe_surface_reference(&context->framebuffer.base.zsbuf,
+ framebuffer->zsbuf);
+
+ for (i = 0; i < framebuffer->nr_cbufs; i++) {
+ struct pipe_surface *ref = framebuffer->cbufs[i];
+ struct grate_resource *res = grate_resource(ref->texture);
+ uint32_t rt_params;
+
+ rt_params = TGR3D_VAL(RT_PARAMS, FORMAT, res->format);
+ rt_params |= TGR3D_VAL(RT_PARAMS, PITCH, res->pitch);
+ rt_params |= TGR3D_BOOL(RT_PARAMS, TILED, res->tiled);
+
+ context->framebuffer.rt_params[1 + i] = rt_params;
+ context->framebuffer.bos[1 + i] = res->bo;
+ mask |= 1 << (1 + i);
+
+ pipe_surface_reference(&cso->cbufs[i], ref);
+ }
+
+ for (; i < cso->nr_cbufs; i++)
+ pipe_surface_reference(&cso->cbufs[i], NULL);
+
+ context->framebuffer.num_rts = 1 + i;
+ context->framebuffer.mask = mask;
+
+ context->framebuffer.base.width = framebuffer->width;
+ context->framebuffer.base.height = framebuffer->height;
+ context->framebuffer.base.nr_cbufs = framebuffer->nr_cbufs;
+
+ /* prepare the scissor-registers for the non-scissor case */
+ context->no_scissor[0] = host1x_opcode_incr(TGR3D_SCISSOR_HORIZ, 2);
+ context->no_scissor[1] = TGR3D_VAL(SCISSOR_HORIZ, MIN, 0);
+ context->no_scissor[1] |= TGR3D_VAL(SCISSOR_HORIZ, MAX, framebuffer->width);
+ context->no_scissor[2] = TGR3D_VAL(SCISSOR_VERT, MIN, 0);
+ context->no_scissor[2] |= TGR3D_VAL(SCISSOR_VERT, MAX, framebuffer->height);
+}
+
+static void
+grate_set_polygon_stipple(struct pipe_context *pcontext,
+ const struct pipe_poly_stipple *stipple)
+{
+ unimplemented();
+}
+
+static void
+grate_set_scissor_states(struct pipe_context *pcontext,
+ unsigned start_slot,
+ unsigned num_scissors,
+ const struct pipe_scissor_state * scissors)
+{
+ assert(num_scissors == 1);
+ unimplemented();
+}
+
+static void
+grate_set_viewport_states(struct pipe_context *pcontext,
+ unsigned start_slot,
+ unsigned num_viewports,
+ const struct pipe_viewport_state *viewports)
+{
+ struct grate_context *context = grate_context(pcontext);
+ static const float zeps = powf(2.0f, -21);
+
+ assert(num_viewports == 1);
+ assert(start_slot == 0);
+
+ context->viewport[0] = host1x_opcode_incr(TGR3D_VIEWPORT_X_BIAS, 6);
+ context->viewport[1] = u_bitcast_f2u(viewports[0].translate[0] * 16.0f);
+ context->viewport[2] = u_bitcast_f2u(viewports[0].translate[1] * 16.0f);
+ context->viewport[3] = u_bitcast_f2u(viewports[0].translate[2] - zeps);
+ context->viewport[4] = u_bitcast_f2u(viewports[0].scale[0] * 16.0f);
+ context->viewport[5] = u_bitcast_f2u(viewports[0].scale[1] * 16.0f);
+ context->viewport[6] = u_bitcast_f2u(viewports[0].scale[2] - zeps);
+
+ uint32_t depth_near = (viewports[0].translate[2] - viewports[0].scale[2]) * ((1 << 20) - 1);
+ uint32_t depth_far = (viewports[0].translate[2] + viewports[0].scale[2]) * ((1 << 20) - 1);
+ context->viewport[7] = host1x_opcode_incr(TGR3D_DEPTH_RANGE_NEAR, 2);
+ context->viewport[8] = depth_near;
+ context->viewport[9] = depth_far;
+
+ assert(viewports[0].scale[0] >= 0.0f);
+ float max_x = fabs(viewports[0].translate[0]);
+ float max_y = fabs(viewports[0].translate[1]);
+ float scale_x = viewports[0].scale[0];
+ float scale_y = fabs(viewports[0].scale[1]);
+ context->guardband[0] = host1x_opcode_incr(TGR3D_GUARDBAND_WIDTH, 3);
+ context->guardband[1] = u_bitcast_f2u((3967 - max_x) / scale_x);
+ context->guardband[2] = u_bitcast_f2u((3967 - max_y) / scale_y);
+ context->guardband[3] = u_bitcast_f2u(6.99);
+}
+
+static void
+grate_set_vertex_buffers(struct pipe_context *pcontext,
+ unsigned int start, unsigned int count,
+ const struct pipe_vertex_buffer *buffer)
+{
+ struct grate_context *context = grate_context(pcontext);
+ struct grate_vertexbuf_state *vbs = &context->vbs;
+
+ util_set_vertex_buffers_mask(vbs->vb, &vbs->enabled, buffer, start, count);
+ vbs->count = util_last_bit(vbs->enabled);
+}
+
+
+static void
+grate_set_sampler_views(struct pipe_context *pcontext,
+ unsigned shader,
+ unsigned start_slot, unsigned num_views,
+ struct pipe_sampler_view **views)
+{
+ unimplemented();
+}
+
+void
+grate_context_state_init(struct pipe_context *pcontext)
+{
+ pcontext->set_sample_mask = grate_set_sample_mask;
+ pcontext->set_constant_buffer = grate_set_constant_buffer;
+ pcontext->set_framebuffer_state = grate_set_framebuffer_state;
+ pcontext->set_polygon_stipple = grate_set_polygon_stipple;
+ pcontext->set_scissor_states = grate_set_scissor_states;
+ pcontext->set_viewport_states = grate_set_viewport_states;
+ pcontext->set_sampler_views = grate_set_sampler_views;
+ pcontext->set_vertex_buffers = grate_set_vertex_buffers;
+}
+
+static void *
+grate_create_blend_state(struct pipe_context *pcontext,
+ const struct pipe_blend_state *template)
+{
+ struct pipe_blend_state *so = CALLOC_STRUCT(pipe_blend_state);
+ if (!so)
+ return NULL;
+
+ *so = *template;
+
+ return so;
+}
+
+static void
+grate_bind_blend_state(struct pipe_context *pcontext, void *so)
+{
+ unimplemented();
+}
+
+static void
+grate_delete_blend_state(struct pipe_context *pcontext, void *so)
+{
+ FREE(so);
+}
+
+void
+grate_context_blend_init(struct pipe_context *pcontext)
+{
+ pcontext->create_blend_state = grate_create_blend_state;
+ pcontext->bind_blend_state = grate_bind_blend_state;
+ pcontext->delete_blend_state = grate_delete_blend_state;
+}
+
+static void *
+grate_create_sampler_state(struct pipe_context *pcontext,
+ const struct pipe_sampler_state *template)
+{
+ struct pipe_sampler_state *so = CALLOC_STRUCT(pipe_sampler_state);
+ if (!so)
+ return NULL;
+
+ *so = *template;
+
+ return so;
+}
+
+static void
+grate_bind_sampler_states(struct pipe_context *pcontext,
+ unsigned shader, unsigned start_slot,
+ unsigned num_samplers, void **samplers)
+{
+ unimplemented();
+}
+
+static void
+grate_delete_sampler_state(struct pipe_context *pcontext, void *so)
+{
+ FREE(so);
+}
+
+void
+grate_context_sampler_init(struct pipe_context *pcontext)
+{
+ pcontext->create_sampler_state = grate_create_sampler_state;
+ pcontext->bind_sampler_states = grate_bind_sampler_states;
+ pcontext->delete_sampler_state = grate_delete_sampler_state;
+}
+
+static int
+grate_cull_face(int cull_face, bool front_ccw)
+{
+ switch (cull_face) {
+ case PIPE_FACE_NONE:
+ return TGR3D_CULL_FACE_NONE;
+
+ case PIPE_FACE_FRONT:
+ return front_ccw ? TGR3D_CULL_FACE_CCW : TGR3D_CULL_FACE_CW;
+
+ case PIPE_FACE_BACK:
+ return front_ccw ? TGR3D_CULL_FACE_CW : TGR3D_CULL_FACE_CCW;
+
+ case PIPE_FACE_FRONT_AND_BACK:
+ return TGR3D_CULL_FACE_BOTH;
+
+ default:
+ unreachable("unknown cull_face");
+ }
+}
+
+static void *
+grate_create_rasterizer_state(struct pipe_context *pcontext,
+ const struct pipe_rasterizer_state *template)
+{
+ struct grate_rasterizer_state *so = CALLOC_STRUCT(grate_rasterizer_state);
+ if (!so)
+ return NULL;
+
+ so->base = *template;
+
+ so->draw_params = TGR3D_VAL(DRAW_PARAMS, PROVOKING_VERTEX, !template->flatshade_first);
+
+ so->cull_face = TGR3D_BOOL(CULL_FACE_LINKER_SETUP, FRONT_CW, !template->front_ccw);
+ so->cull_face |= TGR3D_VAL(CULL_FACE_LINKER_SETUP, CULL_FACE, grate_cull_face(template->cull_face, !template->front_ccw));
+
+ return so;
+}
+
+static void
+grate_bind_rasterizer_state(struct pipe_context *pcontext, void *so)
+{
+ grate_context(pcontext)->rast = so;
+}
+
+static void
+grate_delete_rasterizer_state(struct pipe_context *pcontext, void *so)
+{
+ FREE(so);
+}
+
+void
+grate_context_rasterizer_init(struct pipe_context *pcontext)
+{
+ pcontext->create_rasterizer_state = grate_create_rasterizer_state;
+ pcontext->bind_rasterizer_state = grate_bind_rasterizer_state;
+ pcontext->delete_rasterizer_state = grate_delete_rasterizer_state;
+}
+
+static int
+grate_compare_func(enum pipe_compare_func func)
+{
+ switch (func) {
+ case PIPE_FUNC_NEVER: return TGR3D_COMPARE_FUNC_NEVER;
+ case PIPE_FUNC_LESS: return TGR3D_COMPARE_FUNC_LESS;
+ case PIPE_FUNC_EQUAL: return TGR3D_COMPARE_FUNC_EQUAL;
+ case PIPE_FUNC_LEQUAL: return TGR3D_COMPARE_FUNC_LEQUAL;
+ case PIPE_FUNC_GREATER: return TGR3D_COMPARE_FUNC_GREATER;
+ case PIPE_FUNC_NOTEQUAL: return TGR3D_COMPARE_FUNC_NOTEQUAL;
+ case PIPE_FUNC_ALWAYS: return TGR3D_COMPARE_FUNC_ALWAYS;
+ default: unreachable("unknown pipe_compare_func");
+ }
+}
+
+static void *
+grate_create_zsa_state(struct pipe_context *pcontext,
+ const struct pipe_depth_stencil_alpha_state *template)
+{
+ struct grate_zsa_state *so = CALLOC_STRUCT(grate_zsa_state);
+ if (!so)
+ return NULL;
+
+ so->base = *template;
+
+ uint32_t depth_test = 0;
+ depth_test |= TGR3D_VAL(DEPTH_TEST_PARAMS, FUNC,
+ grate_compare_func(template->depth.func));
+ depth_test |= TGR3D_BOOL(DEPTH_TEST_PARAMS, DEPTH_TEST,
+ template->depth.enabled);
+ depth_test |= TGR3D_BOOL(DEPTH_TEST_PARAMS, DEPTH_WRITE,
+ template->depth.writemask);
+ depth_test |= 0x200;
+
+ so->commands[0] = host1x_opcode_incr(TGR3D_DEPTH_TEST_PARAMS, 1);
+ so->commands[1] = depth_test;
+
+ return so;
+}
+
+static void
+grate_bind_zsa_state(struct pipe_context *pcontext, void *so)
+{
+ grate_context(pcontext)->zsa = so;
+}
+
+static void
+grate_delete_zsa_state(struct pipe_context *pcontext, void *so)
+{
+ FREE(so);
+}
+
+void
+grate_context_zsa_init(struct pipe_context *pcontext)
+{
+ pcontext->create_depth_stencil_alpha_state = grate_create_zsa_state;
+ pcontext->bind_depth_stencil_alpha_state = grate_bind_zsa_state;
+ pcontext->delete_depth_stencil_alpha_state = grate_delete_zsa_state;
+}
+
+/*
+ * Note: this does not include the stride, which needs to be mixed in later
+ **/
+static uint32_t
+attrib_mode(const struct pipe_vertex_element *e)
+{
+ const struct util_format_description *desc = util_format_description(e->src_format);
+ const int c = util_format_get_first_non_void_channel(e->src_format);
+ uint32_t type, format;
+
+ assert(!desc->is_mixed);
+ assert(c >= 0);
+
+ switch (desc->channel[c].type) {
+ case UTIL_FORMAT_TYPE_UNSIGNED:
+ case UTIL_FORMAT_TYPE_SIGNED:
+ switch (desc->channel[c].size) {
+ case 8:
+ type = TGR3D_ATTRIB_TYPE_UBYTE;
+ break;
+
+ case 16:
+ type = TGR3D_ATTRIB_TYPE_USHORT;
+ break;
+
+ case 32:
+ type = TGR3D_ATTRIB_TYPE_UINT;
+ break;
+
+ default:
+ unreachable("invalid channel-size");
+ }
+
+ if (desc->channel[c].type == UTIL_FORMAT_TYPE_SIGNED)
+ type += 2;
+
+ if (desc->channel[c].normalized)
+ type += 1;
+
+ break;
+
+ case UTIL_FORMAT_TYPE_FIXED:
+ assert(desc->channel[c].size == 32);
+ type = TGR3D_ATTRIB_TYPE_FIXED16;
+ break;
+
+ case UTIL_FORMAT_TYPE_FLOAT:
+ assert(desc->channel[c].size == 32); /* TODO: float16 ? */
+ type = TGR3D_ATTRIB_TYPE_FLOAT32;
+ break;
+
+ default:
+ unreachable("invalid channel-type");
+ }
+
+ format = TGR3D_VAL(ATTRIB_MODE, TYPE, type);
+ format |= TGR3D_VAL(ATTRIB_MODE, SIZE, desc->nr_channels);
+ return format;
+}
+
+static void *
+grate_create_vertex_state(struct pipe_context *pcontext, unsigned int count,
+ const struct pipe_vertex_element *elements)
+{
+ unsigned int i;
+ uint16_t mask = 0;
+ struct grate_vertex_state *vtx = CALLOC_STRUCT(grate_vertex_state);
+ if (!vtx)
+ return NULL;
+
+ for (i = 0; i < count; ++i) {
+ const struct pipe_vertex_element *src = elements + i;
+ struct grate_vertex_element *dst = vtx->elements + i;
+ dst->attrib = attrib_mode(src);
+ dst->buffer_index = src->vertex_buffer_index;
+ dst->offset = src->src_offset;
+ mask |= 1 << i;
+ }
+
+ vtx->num_elements = count;
+ vtx->mask = mask;
+
+ return vtx;
+}
+
+static void
+grate_bind_vertex_state(struct pipe_context *pcontext, void *so)
+{
+ grate_context(pcontext)->vs = so;
+}
+
+static void
+grate_delete_vertex_state(struct pipe_context *pcontext, void *so)
+{
+ FREE(so);
+}
+
+static void
+emit_attribs(struct grate_context *context)
+{
+ unsigned int i;
+ struct grate_stream *stream = &context->gr3d->stream;
+
+ assert(context->vs);
+
+ for (i = 0; i < context->vs->num_elements; ++i) {
+ const struct pipe_vertex_buffer *vb;
+ const struct grate_vertex_element *e = context->vs->elements + i;
+ const struct grate_resource *r;
+
+ assert(e->buffer_index < context->vbs.count);
+ vb = context->vbs.vb + e->buffer_index;
+ assert(!vb->is_user_buffer);
+ r = grate_resource(vb->buffer.resource);
+
+ uint32_t attrib = e->attrib;
+ assert(vb->stride < 1 << 24);
+ attrib |= TGR3D_VAL(ATTRIB_MODE, STRIDE, vb->stride);
+
+ grate_stream_push(stream, host1x_opcode_incr(TGR3D_ATTRIB_PTR(i), 2));
+ grate_stream_push_reloc(stream, r->bo, vb->buffer_offset + e->offset);
+ grate_stream_push(stream, attrib);
+ }
+}
+
+static void
+emit_render_targets(struct grate_context *context)
+{
+ unsigned int i;
+ struct grate_stream *stream = &context->gr3d->stream;
+ const struct grate_framebuffer_state *fb = &context->framebuffer;
+
+ grate_stream_push(stream, host1x_opcode_incr(TGR3D_RT_PARAMS(0), fb->num_rts));
+ for (i = 0; i < fb->num_rts; ++i) {
+ uint32_t rt_params = fb->rt_params[i];
+ /* TODO: setup dither */
+ /* rt_params |= TGR3D_BOOL(RT_PARAMS, DITHER_ENABLE, enable_dither); */
+ grate_stream_push(stream, rt_params);
+ }
+
+ grate_stream_push(stream, host1x_opcode_incr(TGR3D_RT_PTR(0), fb->num_rts));
+ for (i = 0; i < fb->num_rts; ++i)
+ grate_stream_push_reloc(stream, fb->bos[i], 0);
+
+ grate_stream_push(stream, host1x_opcode_incr(TGR3D_RT_ENABLE, 1));
+ grate_stream_push(stream, fb->mask);
+}
+
+static void
+emit_scissor(struct grate_context *context)
+{
+ struct grate_stream *stream = &context->gr3d->stream;
+ grate_stream_push_words(stream, context->no_scissor, 3, 0);
+}
+
+static void
+emit_viewport(struct grate_context *context)
+{
+ struct grate_stream *stream = &context->gr3d->stream;
+ grate_stream_push_words(stream, context->viewport, 10, 0);
+}
+
+static void
+emit_guardband(struct grate_context *context)
+{
+ struct grate_stream *stream = &context->gr3d->stream;
+ grate_stream_push_words(stream, context->guardband, 4, 0);
+}
+
+static void
+emit_zsa_state(struct grate_context *context)
+{
+ struct grate_stream *stream = &context->gr3d->stream;
+ grate_stream_push_words(stream, context->zsa->commands, 2, 0);
+}
+
+static void
+emit_vs_uniforms(struct grate_context *context)
+{
+ struct grate_stream *stream = &context->gr3d->stream;
+ struct pipe_constant_buffer *constbuf = &context->constant_buffer[PIPE_SHADER_VERTEX];
+ int len;
+
+ if (constbuf->user_buffer != NULL) {
+ assert(constbuf->buffer_size % sizeof(uint32_t) == 0);
+
+ len = constbuf->buffer_size / 4;
+ assert(len < 256 * 4);
+
+ grate_stream_push(stream, host1x_opcode_imm(TGR3D_VP_UPLOAD_CONST_ID, 0));
+ grate_stream_push(stream, host1x_opcode_nonincr(TGR3D_VP_UPLOAD_CONST, len));
+ grate_stream_push_words(stream, constbuf->user_buffer, len, 0);
+ }
+}
+
+static void
+emit_shader(struct grate_stream *stream, struct grate_shader_blob *blob)
+{
+ grate_stream_push_words(stream, blob->commands, blob->num_commands, 0);
+}
+
+static void
+emit_program(struct grate_context *context)
+{
+ struct grate_stream *stream = &context->gr3d->stream;
+
+ emit_shader(stream, &context->vshader->blob);
+ emit_shader(stream, &context->fshader->blob);
+
+ uint32_t cull_face_linker_setup = TGR3D_VAL(CULL_FACE_LINKER_SETUP,
+ UNK_18_31, 0x2e38);
+
+ /* depends on cull-face */
+ cull_face_linker_setup |= context->rast->cull_face;
+
+ /* depends on linking */
+ struct grate_fp_info *info = &context->fshader->info;
+ assert(info->num_inputs > 0);
+ cull_face_linker_setup |= TGR3D_VAL(CULL_FACE_LINKER_SETUP,
+ LINKER_INST_COUNT,
+ info->num_inputs - 1);
+
+ uint32_t linker_insts[3 + info->num_inputs * 2];
+ linker_insts[0] = host1x_opcode_incr(TGR3D_CULL_FACE_LINKER_SETUP, 1);
+ linker_insts[1] = cull_face_linker_setup;
+ linker_insts[2] = host1x_opcode_incr(TGR3D_LINKER_INSTRUCTION(0), info->num_inputs * 2);
+
+ for (int i = 0; i < info->num_inputs; ++i) {
+ linker_insts[3 + i * 2] = info->inputs[i].src;
+ linker_insts[3 + i * 2 + 1] = info->inputs[i].dst;
+ }
+
+ if (context->rast->base.flatshade && info->color_input >= 0)
+ linker_insts[3 + info->color_input * 2 + 1] |= 0xf << 16;
+
+ grate_stream_push_words(stream, linker_insts, ARRAY_SIZE(linker_insts), 0);
+}
+
+void
+grate_emit_state(struct grate_context *context)
+{
+ emit_render_targets(context);
+ emit_viewport(context);
+ emit_guardband(context);
+ emit_scissor(context);
+ emit_zsa_state(context);
+ emit_attribs(context);
+ emit_vs_uniforms(context);
+ emit_program(context);
+}
+
+void
+grate_context_vbo_init(struct pipe_context *pcontext)
+{
+ pcontext->create_vertex_elements_state = grate_create_vertex_state;
+ pcontext->bind_vertex_elements_state = grate_bind_vertex_state;
+ pcontext->delete_vertex_elements_state = grate_delete_vertex_state;
+}
diff --git a/src/gallium/drivers/grate/grate_state.h b/src/gallium/drivers/grate/grate_state.h
new file mode 100644
index 0000000..0a96461
--- /dev/null
+++ b/src/gallium/drivers/grate/grate_state.h
@@ -0,0 +1,59 @@
+#ifndef GRATE_STATE_H
+#define GRATE_STATE_H
+
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+
+struct grate_context;
+
+struct grate_rasterizer_state {
+ struct pipe_rasterizer_state base;
+ uint32_t draw_params;
+ uint32_t cull_face;
+};
+
+struct grate_zsa_state {
+ struct pipe_depth_stencil_alpha_state base;
+ uint32_t commands[2];
+};
+
+struct grate_vertexbuf_state {
+ struct pipe_vertex_buffer vb[PIPE_MAX_ATTRIBS];
+ unsigned int count;
+ uint32_t enabled;
+};
+
+struct grate_vertex_element {
+ uint32_t attrib;
+ unsigned int buffer_index;
+ unsigned int offset;
+};
+
+struct grate_vertex_state {
+ struct grate_vertex_element elements[PIPE_MAX_ATTRIBS];
+ unsigned int num_elements;
+ uint16_t mask;
+};
+
+void
+grate_emit_state(struct grate_context *context);
+
+void
+grate_context_state_init(struct pipe_context *pcontext);
+
+void
+grate_context_blend_init(struct pipe_context *pcontext);
+
+void
+grate_context_sampler_init(struct pipe_context *pcontext);
+
+void
+grate_context_rasterizer_init(struct pipe_context *pcontext);
+
+void
+grate_context_zsa_init(struct pipe_context *pcontext);
+
+void
+grate_context_vbo_init(struct pipe_context *pcontext);
+
+#endif
diff --git a/src/gallium/drivers/grate/grate_stream.c b/src/gallium/drivers/grate/grate_stream.c
new file mode 100644
index 0000000..21c21e1
--- /dev/null
+++ b/src/gallium/drivers/grate/grate_stream.c
@@ -0,0 +1,380 @@
+/*
+ * Copyright (c) 2016-2017 Dmitry Osipenko <digetx@gmail.com>
+ * Copyright (C) 2012-2013 NVIDIA Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS\n", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Arto Merilainen <amerilainen@nvidia.com>
+ */
+
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "host1x01_hardware.h"
+#include "hw_host1x01_uclass.h"
+#include "grate_stream.h"
+
+#define ErrorMsg(fmt, args...) \
+ fprintf(stderr, "%s:%d/%s(): " fmt, \
+ __FILE__, __LINE__, __func__, ##args)
+
+/*
+ * grate_stream_create(channel)
+ *
+ * Create a stream for given channel. This function preallocates several
+ * command buffers for later usage to improve performance. Streams are
+ * used for generating command buffers opcode by opcode using
+ * grate_stream_push().
+ */
+
+int
+grate_stream_create(struct drm_tegra *drm,
+ struct drm_tegra_channel *channel,
+ struct grate_stream *stream,
+ uint32_t words_num)
+{
+ stream->status = GRATE_STREAM_FREE;
+ stream->channel = channel;
+ stream->num_words = words_num;
+
+ return 0;
+}
+
+/*
+ * grate_stream_destroy(stream)
+ *
+ * Destroy the given stream object. All resrouces are released.
+ */
+
+void
+grate_stream_destroy(struct grate_stream *stream)
+{
+ if (!stream)
+ return;
+
+ drm_tegra_job_free(stream->job);
+}
+
+/*
+ * grate_stream_flush(stream, fence)
+ *
+ * Send the current contents of stream buffer. The stream must be
+ * synchronized correctly (we cannot send partial streams). If
+ * pointer to fence is given, the fence will contain the syncpoint value
+ * that is reached when operations in the buffer are finished.
+ */
+
+int
+grate_stream_flush(struct grate_stream *stream)
+{
+ struct drm_tegra_fence *fence;
+ int result = 0;
+
+ if (!stream)
+ return -1;
+
+ /* Reflushing is fine */
+ if (stream->status == GRATE_STREAM_FREE)
+ return 0;
+
+ /* Return error if stream is constructed badly */
+ if (stream->status != GRATE_STREAM_READY) {
+ result = -1;
+ goto cleanup;
+ }
+
+ result = drm_tegra_job_submit(stream->job, &fence);
+ if (result != 0) {
+ ErrorMsg("drm_tegra_job_submit() failed %d\n", result);
+ result = -1;
+ goto cleanup;
+ }
+
+ result = drm_tegra_fence_wait_timeout(fence, 1000);
+ if (result != 0) {
+ ErrorMsg("drm_tegra_fence_wait_timeout() failed %d\n", result);
+ result = -1;
+ }
+
+ drm_tegra_fence_free(fence);
+
+cleanup:
+ drm_tegra_job_free(stream->job);
+
+ stream->job = NULL;
+ stream->status = GRATE_STREAM_FREE;
+
+ return result;
+}
+
+/*
+ * grate_stream_begin(stream, num_words, fence, num_fences, num_syncpt_incrs,
+ * num_relocs, class_id)
+ *
+ * Start constructing a stream.
+ * - num_words refer to the maximum number of words the stream can contain.
+ * - fence is a pointer to a table that contains syncpoint preconditions
+ * before the stream execution can start.
+ * - num_fences indicate the number of elements in the fence table.
+ * - num_relocs indicate the number of memory references in the buffer.
+ * - class_id refers to the class_id that is selected in the beginning of a
+ * stream. If no class id is given, the default class id (=usually the
+ * client device's class) is selected.
+ *
+ * This function verifies that the current buffer has enough room for holding
+ * the whole stream (this is computed using num_words and num_relocs). The
+ * function blocks until the stream buffer is ready for use.
+ */
+
+int
+grate_stream_begin(struct grate_stream *stream)
+{
+ int ret;
+
+ /* check stream and its state */
+ if (!(stream && stream->status == GRATE_STREAM_FREE)) {
+ ErrorMsg("Stream status isn't FREE\n");
+ return -1;
+ }
+
+ ret = drm_tegra_job_new(&stream->job, stream->channel);
+ if (ret != 0) {
+ ErrorMsg("drm_tegra_job_new() failed %d\n", ret);
+ return -1;
+ }
+
+ ret = drm_tegra_pushbuf_new(&stream->buffer.pushbuf, stream->job);
+ if (ret != 0) {
+ ErrorMsg("drm_tegra_pushbuf_new() failed %d\n", ret);
+ drm_tegra_job_free(stream->job);
+ return -1;
+ }
+
+ ret = drm_tegra_pushbuf_prepare(stream->buffer.pushbuf, stream->num_words);
+ if (ret != 0) {
+ ErrorMsg("drm_tegra_pushbuf_prepare() failed %d\n", ret);
+ drm_tegra_job_free(stream->job);
+ return -1;
+ }
+
+ stream->class_id = 0;
+ stream->status = GRATE_STREAM_CONSTRUCT;
+
+ return 0;
+}
+
+/*
+ * grate_stream_push_reloc(stream, h, offset)
+ *
+ * Push a memory reference to the stream.
+ */
+
+int
+grate_stream_push_reloc(struct grate_stream *stream,
+ struct drm_tegra_bo *bo,
+ unsigned offset)
+{
+ int ret;
+
+ if (!(stream && stream->status == GRATE_STREAM_CONSTRUCT)) {
+ ErrorMsg("Stream status isn't CONSTRUCT\n");
+ return -1;
+ }
+
+ ret = drm_tegra_pushbuf_relocate(stream->buffer.pushbuf,
+ bo, offset, 0);
+ if (ret != 0) {
+ stream->status = GRATE_STREAM_CONSTRUCTION_FAILED;
+ ErrorMsg("drm_tegra_pushbuf_relocate() failed %d\n", ret);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * grate_stream_push(stream, word)
+ *
+ * Push a single word to given stream.
+ */
+
+int
+grate_stream_push(struct grate_stream *stream, uint32_t word)
+{
+ int ret;
+
+ if (!(stream && stream->status == GRATE_STREAM_CONSTRUCT)) {
+ ErrorMsg("Stream status isn't CONSTRUCT\n");
+ return -1;
+ }
+
+ ret = drm_tegra_pushbuf_prepare(stream->buffer.pushbuf, 1);
+ if (ret != 0) {
+ stream->status = GRATE_STREAM_CONSTRUCTION_FAILED;
+ ErrorMsg("drm_tegra_pushbuf_prepare() failed %d\n", ret);
+ return -1;
+ }
+
+ *stream->buffer.pushbuf->ptr++ = word;
+
+ return 0;
+}
+
+/*
+ * grate_stream_push_setclass(stream, class_id)
+ *
+ * Push "set class" opcode to the stream. Do nothing if the class is already
+ * active
+ */
+
+int
+grate_stream_push_setclass(struct grate_stream *stream, unsigned class_id)
+{
+ int result;
+
+ if (stream->class_id == class_id)
+ return 0;
+
+ result = grate_stream_push(stream, host1x_opcode_setclass(class_id, 0, 0));
+
+ if (result == 0)
+ stream->class_id = class_id;
+
+ return result;
+}
+
+/*
+ * grate_stream_end(stream)
+ *
+ * Mark end of stream. This function pushes last syncpoint increment for
+ * marking end of stream.
+ */
+
+int
+grate_stream_end(struct grate_stream *stream)
+{
+ int ret;
+
+ if (!(stream && stream->status == GRATE_STREAM_CONSTRUCT)) {
+ ErrorMsg("Stream status isn't CONSTRUCT\n");
+ return -1;
+ }
+
+ ret = drm_tegra_pushbuf_sync(stream->buffer.pushbuf,
+ DRM_TEGRA_SYNCPT_COND_OP_DONE);
+ if (ret != 0) {
+ stream->status = GRATE_STREAM_CONSTRUCTION_FAILED;
+ ErrorMsg("drm_tegra_pushbuf_sync() failed %d\n", ret);
+ return -1;
+ }
+
+ stream->status = GRATE_STREAM_READY;
+
+ return 0;
+}
+
+/*
+ * grate_reloc (variable, handle, offset)
+ *
+ * This function creates a reloc allocation. The function should be used in
+ * conjunction with grate_stream_push_words.
+ */
+
+struct grate_reloc
+grate_reloc(const void *var_ptr, struct drm_tegra_bo *bo,
+ uint32_t offset, uint32_t var_offset)
+{
+ struct grate_reloc reloc = {var_ptr, bo, offset, var_offset};
+ return reloc;
+}
+
+/*
+ * grate_stream_push_words(stream, addr, words, ...)
+ *
+ * Push words from given address to stream. The function takes
+ * reloc structs as its argument. You can generate the structs with grate_reloc
+ * function.
+ */
+
+int grate_stream_push_words(struct grate_stream *stream, const void *addr,
+ unsigned words, int num_relocs, ...)
+{
+ struct grate_reloc reloc_arg;
+ va_list ap;
+ uint32_t *pushbuf_ptr;
+ int ret;
+
+ if (!(stream && stream->status == GRATE_STREAM_CONSTRUCT)) {
+ ErrorMsg("Stream status isn't CONSTRUCT\n");
+ return -1;
+ }
+
+ ret = drm_tegra_pushbuf_prepare(stream->buffer.pushbuf, words);
+ if (ret != 0) {
+ stream->status = GRATE_STREAM_CONSTRUCTION_FAILED;
+ ErrorMsg("drm_tegra_pushbuf_prepare() failed %d\n", ret);
+ return -1;
+ }
+
+ /* Class id should be set explicitly, for simplicity. */
+ if (stream->class_id == 0) {
+ stream->status = GRATE_STREAM_CONSTRUCTION_FAILED;
+ ErrorMsg("HOST1X class not specified\n");
+ return -1;
+ }
+
+ /* Copy the contents */
+ pushbuf_ptr = stream->buffer.pushbuf->ptr;
+ memcpy(pushbuf_ptr, addr, words * sizeof(uint32_t));
+
+ /* Copy relocs */
+ va_start(ap, num_relocs);
+ for (; num_relocs; num_relocs--) {
+ reloc_arg = va_arg(ap, struct grate_reloc);
+
+ stream->buffer.pushbuf->ptr = pushbuf_ptr;
+ stream->buffer.pushbuf->ptr += reloc_arg.var_offset / sizeof(uint32_t);
+
+ ret = drm_tegra_pushbuf_relocate(stream->buffer.pushbuf, reloc_arg.bo,
+ reloc_arg.offset, 0);
+ if (ret != 0) {
+ stream->status = GRATE_STREAM_CONSTRUCTION_FAILED;
+ ErrorMsg("drm_tegra_pushbuf_relocate() failed %d\n", ret);
+ break;
+ }
+ }
+ va_end(ap);
+
+ stream->buffer.pushbuf->ptr = pushbuf_ptr + words;
+
+ return ret ? -1 : 0;
+}
diff --git a/src/gallium/drivers/grate/grate_stream.h b/src/gallium/drivers/grate/grate_stream.h
new file mode 100644
index 0000000..e3f57d9
--- /dev/null
+++ b/src/gallium/drivers/grate/grate_stream.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2016 Dmitry Osipenko <digetx@gmail.com>
+ * Copyright (C) 2012-2013 NVIDIA Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Arto Merilainen <amerilainen@nvidia.com>
+ */
+
+#ifndef GRATE_STREAM_H_
+#define GRATE_STREAM_H_
+
+#include <stdint.h>
+#include <libdrm/tegra.h>
+
+#include "class_ids.h"
+
+enum grate_stream_status {
+ GRATE_STREAM_FREE,
+ GRATE_STREAM_CONSTRUCT,
+ GRATE_STREAM_CONSTRUCTION_FAILED,
+ GRATE_STREAM_READY,
+};
+
+struct grate_command_buffer {
+ struct drm_tegra_pushbuf *pushbuf;
+};
+
+struct grate_stream {
+ enum grate_stream_status status;
+
+ struct drm_tegra_job *job;
+ struct drm_tegra_channel *channel;
+
+ struct grate_command_buffer buffer;
+ int num_words;
+ uint32_t class_id;
+};
+
+struct grate_reloc {
+ const void *addr;
+ struct drm_tegra_bo *bo;
+ uint32_t offset;
+ unsigned var_offset;
+};
+
+/* Stream operations */
+int
+grate_stream_create(struct drm_tegra *drm,
+ struct drm_tegra_channel *channel,
+ struct grate_stream *stream,
+ uint32_t words_num);
+void
+grate_stream_destroy(struct grate_stream *stream);
+
+int
+grate_stream_begin(struct grate_stream *stream);
+
+int
+grate_stream_end(struct grate_stream *stream);
+
+int
+grate_stream_flush(struct grate_stream *stream);
+
+int
+grate_stream_push(struct grate_stream *stream, uint32_t word);
+
+int
+grate_stream_push_setclass(struct grate_stream *stream,
+ enum host1x_class class_id);
+
+int
+grate_stream_push_reloc(struct grate_stream *stream,
+ struct drm_tegra_bo *bo, unsigned offset);
+
+struct grate_reloc
+grate_reloc(const void *var_ptr, struct drm_tegra_bo *bo,
+ uint32_t offset, uint32_t var_offset);
+
+int
+grate_stream_push_words(struct grate_stream *stream, const void *addr,
+ unsigned words, int num_relocs, ...);
+
+#endif
diff --git a/src/gallium/drivers/grate/grate_surface.c b/src/gallium/drivers/grate/grate_surface.c
new file mode 100644
index 0000000..e7f90a2
--- /dev/null
+++ b/src/gallium/drivers/grate/grate_surface.c
@@ -0,0 +1,45 @@
+#include <stdio.h>
+
+#include "util/u_inlines.h"
+#include "util/u_memory.h"
+
+#include "grate_surface.h"
+
+static struct pipe_surface *
+grate_create_surface(struct pipe_context *context,
+ struct pipe_resource *resource,
+ const struct pipe_surface *template)
+{
+ unsigned int level = template->u.tex.level;
+ struct grate_surface *surface = CALLOC_STRUCT(grate_surface);
+ if (!surface)
+ return NULL;
+
+ pipe_resource_reference(&surface->base.texture, resource);
+ pipe_reference_init(&surface->base.reference, 1);
+
+ surface->base.context = context;
+ surface->base.format = template->format;
+ surface->base.width = u_minify(resource->width0, level);
+ surface->base.height = u_minify(resource->height0, level);
+ surface->base.u.tex.level = level;
+ surface->base.u.tex.first_layer = template->u.tex.first_layer;
+ surface->base.u.tex.last_layer = template->u.tex.last_layer;
+
+ return &surface->base;
+}
+
+static void
+grate_surface_destroy(struct pipe_context *context,
+ struct pipe_surface *surface)
+{
+ pipe_resource_reference(&surface->texture, NULL);
+ FREE(surface);
+}
+
+void
+grate_context_surface_init(struct pipe_context *context)
+{
+ context->create_surface = grate_create_surface;
+ context->surface_destroy = grate_surface_destroy;
+}
diff --git a/src/gallium/drivers/grate/grate_surface.h b/src/gallium/drivers/grate/grate_surface.h
new file mode 100644
index 0000000..00c967d
--- /dev/null
+++ b/src/gallium/drivers/grate/grate_surface.h
@@ -0,0 +1,14 @@
+#ifndef GRATE_SURFACE_H
+#define GRATE_SURFACE_H
+
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+
+struct grate_surface {
+ struct pipe_surface base;
+};
+
+void
+grate_context_surface_init(struct pipe_context *context);
+
+#endif
diff --git a/src/gallium/drivers/grate/grate_vpe_ir.c b/src/gallium/drivers/grate/grate_vpe_ir.c
new file mode 100644
index 0000000..4afec11
--- /dev/null
+++ b/src/gallium/drivers/grate/grate_vpe_ir.c
@@ -0,0 +1,211 @@
+#include <assert.h>
+#include <stdint.h>
+
+#include "util/macros.h"
+
+#include "grate_vpe_ir.h"
+
+static unsigned
+vpe_write_mask(unsigned input)
+{
+ return (((input >> 0) & 1) << 3) |
+ (((input >> 1) & 1) << 2) |
+ (((input >> 2) & 1) << 1) |
+ (((input >> 3) & 1) << 0);
+}
+
+static unsigned
+vpe_swizzle(enum vpe_swz swizzle[4])
+{
+ return (swizzle[0] << 6) |
+ (swizzle[1] << 4) |
+ (swizzle[2] << 2) |
+ (swizzle[3] << 0);
+}
+
+static unsigned
+vpe_src_reg(struct vpe_src_operand op)
+{
+ union {
+ struct __attribute__((packed)) {
+ unsigned type : 2; // 0 .. 1
+ unsigned index : 6; // 2 .. 7
+ unsigned swizzle : 8; // 8 .. 15
+ unsigned negate : 1; // 16
+ };
+ unsigned value;
+ } u;
+
+ u.type = op.file;
+ u.index = op.index;
+ u.swizzle = vpe_swizzle(op.swizzle);
+ u.negate = op.negate;
+
+ return u.value;
+}
+
+
+void
+grate_vpe_pack(uint32_t *dst, struct vpe_instr *instr, bool end_of_program)
+{
+ /* we can only handle one output register per instruction */
+ assert(instr->vec.dst.file != VPE_DST_FILE_OUTPUT ||
+ instr->scalar.dst.file != VPE_DST_FILE_OUTPUT);
+
+ union {
+ struct __attribute__((packed)) {
+ unsigned end_of_program : 1; // 0
+ unsigned constant_relative_addressing_enable : 1; // 1
+ unsigned export_write_index : 5; // 2 .. 6
+ unsigned scalar_rD_index : 6; // 7 .. 12
+ unsigned vector_op_write_mask : 4; // 13 .. 16
+ unsigned scalar_op_write_mask : 4; // 17 .. 20
+ unsigned rC : 17; // 21 .. 37
+ unsigned rB : 17; // 38 .. 54
+ unsigned rA : 17; // 55 .. 71
+ unsigned attribute_fetch_index : 4; // 72 .. 75
+ unsigned uniform_fetch_index : 10; // 76 .. 85
+ unsigned vector_opcode : 5; // 86 .. 90
+ unsigned scalar_opcode : 5; // 91 .. 95
+ unsigned address_register_select : 2; // 96 .. 97
+ unsigned predicate_swizzle : 8; // 98 .. 105
+ unsigned predicate_lt : 1; // 106
+ unsigned predicate_eq : 1; // 107
+ unsigned predicate_gt : 1; // 108
+ unsigned condition_check : 1; // 109
+ unsigned condition_set : 1; // 110
+ unsigned vector_rD_index : 6; // 111 .. 116
+ unsigned rA_absolute : 1; // 117
+ unsigned rB_absolute : 1; // 118
+ unsigned rC_absolute : 1; // 119
+ unsigned bit120 : 1; // 120
+ unsigned condition_register_index : 1; // 121
+ unsigned saturate_result : 1; // 122
+ unsigned attribute_relative_addressing_enable : 1; // 123
+ unsigned export_relative_addressing_enable : 1; // 124
+ unsigned condition_flags_write_enable : 1; // 125
+ unsigned export_vector_write_enable : 1; // 126
+ unsigned bit127 : 1; // 127
+ };
+
+ uint32_t words[4];
+ } tmp = {
+ .predicate_lt = 1,
+ .predicate_eq = 1,
+ .predicate_gt = 1,
+
+ .predicate_swizzle = (0 << 6) | (1 << 4) | (2 << 2) | 3,
+ };
+
+ /* find the attribute/uniform fetch-values, and zero out the index
+ * for these registers.
+ */
+ int attr_fetch = -1, uniform_fetch = -1;
+ for (int i = 0; i < 3; ++i) {
+ switch (instr->vec.src[i].file) {
+ case VPE_SRC_FILE_ATTRIB:
+ assert(attr_fetch < 0 ||
+ attr_fetch == instr->vec.src[i].index);
+ attr_fetch = instr->vec.src[i].index;
+ instr->vec.src[i].index = 0;
+ break;
+
+ case VPE_SRC_FILE_UNIFORM:
+ assert(uniform_fetch < 0 ||
+ uniform_fetch == instr->vec.src[i].index);
+ uniform_fetch = instr->vec.src[i].index;
+ instr->vec.src[i].index = 0;
+ break;
+
+ default: /* nothing */
+ break;
+ }
+ }
+
+ switch (instr->scalar.src.file) {
+ case VPE_SRC_FILE_ATTRIB:
+ assert(attr_fetch < 0 ||
+ attr_fetch == instr->scalar.src.index);
+ attr_fetch = instr->scalar.src.index;
+ instr->scalar.src.index = 0;
+ break;
+
+ case VPE_SRC_FILE_UNIFORM:
+ assert(uniform_fetch < 0 ||
+ uniform_fetch == instr->scalar.src.index);
+ uniform_fetch = instr->scalar.src.index;
+ instr->scalar.src.index = 0;
+ break;
+
+ default: /* nothing */
+ break;
+
+ }
+
+ tmp.attribute_fetch_index = attr_fetch >= 0 ? attr_fetch : 0;
+ tmp.uniform_fetch_index = uniform_fetch >= 0 ? uniform_fetch : 0;
+
+ tmp.vector_opcode = instr->vec.op;
+ switch (instr->vec.dst.file) {
+ case VPE_DST_FILE_TEMP:
+ tmp.vector_rD_index = instr->vec.dst.index;
+ tmp.export_write_index = 31;
+ break;
+
+ case VPE_DST_FILE_OUTPUT:
+ tmp.vector_rD_index = 63; // disable register-write
+ tmp.export_vector_write_enable = 1;
+ tmp.export_write_index = instr->vec.dst.index;
+ break;
+
+ case VPE_DST_FILE_UNDEF:
+ // assert(0); // TODO: consult NOP
+ break;
+
+ default:
+ unreachable("illegal enum vpe_dst_file value");
+ }
+ tmp.vector_op_write_mask = vpe_write_mask(instr->vec.dst.write_mask);
+
+ tmp.scalar_opcode = instr->scalar.op;
+ switch (instr->scalar.dst.file) {
+ case VPE_DST_FILE_TEMP:
+ tmp.scalar_rD_index = instr->scalar.dst.index;
+ tmp.export_write_index = 31;
+ break;
+
+ case VPE_DST_FILE_OUTPUT:
+ tmp.scalar_rD_index = 63; // disable register-write
+ tmp.export_vector_write_enable = 0;
+ tmp.export_write_index = instr->scalar.dst.index;
+ break;
+
+ case VPE_DST_FILE_UNDEF:
+ // assert(0); // TODO: consult NOP
+ break;
+
+ default:
+ unreachable("illegal enum vpe_dst_file value");
+ }
+ tmp.scalar_op_write_mask = vpe_write_mask(instr->scalar.dst.write_mask);
+
+ tmp.rA = vpe_src_reg(instr->vec.src[0]);
+ tmp.rA_absolute = instr->vec.src[0].absolute;
+
+ tmp.rB = vpe_src_reg(instr->vec.src[1]);
+ tmp.rB_absolute = instr->vec.src[1].absolute;
+
+ if (instr->vec.src[2].file != VPE_SRC_FILE_UNDEF) {
+ tmp.rC = vpe_src_reg(instr->vec.src[2]);
+ tmp.rC_absolute = instr->vec.src[2].absolute;
+ } else if (instr->scalar.src.file != VPE_SRC_FILE_UNDEF) {
+ tmp.rC = vpe_src_reg(instr->scalar.src);
+ tmp.rC_absolute = instr->scalar.src.absolute;
+ }
+
+ tmp.end_of_program = end_of_program;
+
+ /* copy packed instruction into destination */
+ for (int i = 0; i < 4; ++i)
+ dst[i] = tmp.words[3 - i];
+}
diff --git a/src/gallium/drivers/grate/grate_vpe_ir.h b/src/gallium/drivers/grate/grate_vpe_ir.h
new file mode 100644
index 0000000..7a16dc3
--- /dev/null
+++ b/src/gallium/drivers/grate/grate_vpe_ir.h
@@ -0,0 +1,115 @@
+#ifndef GRATE_VPE_IR_H
+#define GRATE_VPE_IR_H
+
+#include "util/list.h"
+
+#include "stdbool.h"
+#include "stdint.h"
+
+enum vpe_src_file {
+ VPE_SRC_FILE_UNDEF = 0,
+ VPE_SRC_FILE_TEMP = 1,
+ VPE_SRC_FILE_ATTRIB = 2,
+ VPE_SRC_FILE_UNIFORM = 3,
+};
+
+enum vpe_dst_file {
+ VPE_DST_FILE_TEMP,
+ VPE_DST_FILE_OUTPUT,
+ VPE_DST_FILE_UNDEF
+};
+
+enum vpe_swz {
+ VPE_SWZ_X = 0,
+ VPE_SWZ_Y = 1,
+ VPE_SWZ_Z = 2,
+ VPE_SWZ_W = 3
+};
+
+enum vpe_vec_op {
+ VPE_VEC_OP_NOP = 0,
+ VPE_VEC_OP_MOV = 1,
+ VPE_VEC_OP_MUL = 2,
+ VPE_VEC_OP_ADD = 3,
+ VPE_VEC_OP_MAD = 4,
+ VPE_VEC_OP_DP3 = 5,
+ VPE_VEC_OP_DPH = 6,
+ VPE_VEC_OP_DP4 = 7,
+ VPE_VEC_OP_DST = 8,
+ VPE_VEC_OP_MIN = 9,
+ VPE_VEC_OP_MAX = 10,
+ VPE_VEC_OP_SLT = 11,
+ VPE_VEC_OP_SGE = 12,
+ VPE_VEC_OP_ARL = 13,
+ VPE_VEC_OP_FRC = 14,
+ VPE_VEC_OP_FLR = 15,
+ VPE_VEC_OP_SEQ = 16,
+ VPE_VEC_OP_SFL = 17,
+ VPE_VEC_OP_SGT = 18,
+ VPE_VEC_OP_SLE = 19,
+ VPE_VEC_OP_SNE = 20,
+ VPE_VEC_OP_STR = 21,
+ VPE_VEC_OP_SSG = 22,
+ VPE_VEC_OP_ARR = 23,
+ VPE_VEC_OP_ARA = 24,
+ VPE_VEC_OP_TXL = 25,
+ VPE_VEC_OP_PUSHA = 26,
+ VPE_VEC_OP_POPA = 27
+};
+
+enum vpe_scalar_op {
+ VPE_SCALAR_OP_NOP = 0,
+ VPE_SCALAR_OP_MOV = 1,
+ VPE_SCALAR_OP_RCP = 2,
+ VPE_SCALAR_OP_RCC = 3,
+ VPE_SCALAR_OP_RSQ = 4,
+ VPE_SCALAR_OP_EXP = 5,
+ VPE_SCALAR_OP_LOG = 6,
+ VPE_SCALAR_OP_LIT = 7,
+ VPE_SCALAR_OP_BRA = 9,
+ VPE_SCALAR_OP_CAL = 11,
+ VPE_SCALAR_OP_RET = 12,
+ VPE_SCALAR_OP_LG2 = 13,
+ VPE_SCALAR_OP_EX2 = 14,
+ VPE_SCALAR_OP_SIN = 15,
+ VPE_SCALAR_OP_COS = 16,
+ VPE_SCALAR_OP_PUSHA = 19,
+ VPE_SCALAR_OP_POPA = 20
+};
+
+struct vpe_dst_operand {
+ enum vpe_dst_file file;
+ int index;
+ unsigned int write_mask;
+ bool saturate;
+};
+
+struct vpe_src_operand {
+ enum vpe_src_file file;
+ int index;
+ enum vpe_swz swizzle[4];
+ bool negate, absolute;
+};
+
+struct vpe_vec_instr {
+ enum vpe_vec_op op;
+ struct vpe_dst_operand dst;
+ struct vpe_src_operand src[3];
+};
+
+struct vpe_scalar_instr {
+ enum vpe_scalar_op op;
+ struct vpe_dst_operand dst;
+ struct vpe_src_operand src;
+};
+
+struct vpe_instr {
+ struct list_head link;
+ struct vpe_vec_instr vec;
+ struct vpe_scalar_instr scalar;
+};
+
+void
+grate_vpe_pack(uint32_t *dst, struct vpe_instr *instr, bool end_of_program);
+
+#endif
diff --git a/src/gallium/drivers/grate/host1x01_hardware.h b/src/gallium/drivers/grate/host1x01_hardware.h
new file mode 100644
index 0000000..a6f6519
--- /dev/null
+++ b/src/gallium/drivers/grate/host1x01_hardware.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2012-2013 NVIDIA Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Arto Merilainen <amerilainen@nvidia.com>
+ */
+
+#ifndef HOST1X01_HARDWARE_H_
+#define HOST1X01_HARDWARE_H_
+
+#include <linux/types.h>
+#include "hw_host1x01_uclass.h"
+
+/* channel registers */
+#define HOST1X_CHANNEL_MAP_SIZE_BYTES 16384
+#define HOST1X_SYNC_MLOCK_NUM 16
+
+/* sync registers */
+#define HOST1X_CHANNEL_SYNC_REG_BASE 0x3000
+#define HOST1X_NB_MLOCKS 16
+
+#define BIT(nr) (1UL << (nr))
+
+static inline uint32_t host1x_class_host_wait_syncpt(unsigned indx,
+ unsigned threshold)
+{
+ return host1x_uclass_wait_syncpt_indx_f(indx) |
+ host1x_uclass_wait_syncpt_thresh_f(threshold);
+}
+
+static inline uint32_t host1x_class_host_load_syncpt_base(unsigned indx,
+ unsigned threshold)
+{
+ return host1x_uclass_load_syncpt_base_base_indx_f(indx) |
+ host1x_uclass_load_syncpt_base_value_f(threshold);
+}
+
+static inline uint32_t host1x_class_host_wait_syncpt_base(unsigned indx,
+ unsigned base_indx,
+ unsigned offset)
+{
+ return host1x_uclass_wait_syncpt_base_indx_f(indx) |
+ host1x_uclass_wait_syncpt_base_base_indx_f(base_indx) |
+ host1x_uclass_wait_syncpt_base_offset_f(offset);
+}
+
+static inline uint32_t host1x_class_host_incr_syncpt_base(unsigned base_indx,
+ unsigned offset)
+{
+ return host1x_uclass_incr_syncpt_base_base_indx_f(base_indx) |
+ host1x_uclass_incr_syncpt_base_offset_f(offset);
+}
+
+static inline uint32_t host1x_class_host_incr_syncpt(unsigned cond,
+ unsigned indx)
+{
+ return host1x_uclass_incr_syncpt_cond_f(cond) |
+ host1x_uclass_incr_syncpt_indx_f(indx);
+}
+
+static inline uint32_t host1x_class_host_indoff_reg_write(unsigned mod_id,
+ unsigned offset,
+ int auto_inc)
+{
+ uint32_t v = host1x_uclass_indoff_indbe_f(0xf) |
+ host1x_uclass_indoff_indmodid_f(mod_id) |
+ host1x_uclass_indoff_indroffset_f(offset);
+ if (auto_inc)
+ v |= host1x_uclass_indoff_autoinc_f(1);
+ return v;
+}
+
+static inline uint32_t host1x_class_host_indoff_reg_read(unsigned mod_id,
+ unsigned offset,
+ int auto_inc)
+{
+ uint32_t v = host1x_uclass_indoff_indmodid_f(mod_id) |
+ host1x_uclass_indoff_indroffset_f(offset) |
+ host1x_uclass_indoff_rwn_read_v();
+ if (auto_inc)
+ v |= host1x_uclass_indoff_autoinc_f(1);
+ return v;
+}
+
+
+/* cdma opcodes */
+static inline uint32_t host1x_opcode_setclass(unsigned class_id,
+ unsigned offset, unsigned mask)
+{
+ return (0 << 28) | (offset << 16) | (class_id << 6) | mask;
+}
+
+static inline uint32_t host1x_opcode_incr(unsigned offset, unsigned count)
+{
+ return (1 << 28) | (offset << 16) | count;
+}
+
+static inline uint32_t host1x_opcode_nonincr(unsigned offset, unsigned count)
+{
+ return (2 << 28) | (offset << 16) | count;
+}
+
+static inline uint32_t host1x_opcode_mask(unsigned offset, unsigned mask)
+{
+ return (3 << 28) | (offset << 16) | mask;
+}
+
+static inline uint32_t host1x_opcode_imm(unsigned offset, unsigned value)
+{
+ return (4 << 28) | (offset << 16) | value;
+}
+
+static inline uint32_t host1x_mask2(unsigned x, unsigned y)
+{
+ return 1 | (1 << (y - x));
+}
+#endif
diff --git a/src/gallium/drivers/grate/hw_host1x01_uclass.h b/src/gallium/drivers/grate/hw_host1x01_uclass.h
new file mode 100644
index 0000000..334af05
--- /dev/null
+++ b/src/gallium/drivers/grate/hw_host1x01_uclass.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2012-2013 NVIDIA Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Arto Merilainen <amerilainen@nvidia.com>
+ */
+
+ /*
+ * Function naming determines intended use:
+ *
+ * <x>_r(void) : Returns the offset for register <x>.
+ *
+ * <x>_w(void) : Returns the word offset for word (4 byte) element <x>.
+ *
+ * <x>_<y>_s(void) : Returns size of field <y> of register <x> in bits.
+ *
+ * <x>_<y>_f(uint32_t v) : Returns a value based on 'v' which has been shifted
+ * and masked to place it at field <y> of register <x>. This value
+ * can be |'d with others to produce a full register value for
+ * register <x>.
+ *
+ * <x>_<y>_m(void) : Returns a mask for field <y> of register <x>. This
+ * value can be ~'d and then &'d to clear the value of field <y> for
+ * register <x>.
+ *
+ * <x>_<y>_<z>_f(void) : Returns the constant value <z> after being shifted
+ * to place it at field <y> of register <x>. This value can be |'d
+ * with others to produce a full register value for <x>.
+ *
+ * <x>_<y>_v(uint32_t r) : Returns the value of field <y> from a full register
+ * <x> value 'r' after being shifted to place its LSB at bit 0.
+ * This value is suitable for direct comparison with other unshifted
+ * values appropriate for use in field <y> of register <x>.
+ *
+ * <x>_<y>_<z>_v(void) : Returns the constant value for <z> defined for
+ * field <y> of register <x>. This value is suitable for direct
+ * comparison with unshifted values appropriate for use in field <y>
+ * of register <x>.
+ */
+
+#ifndef HW_HOST1X_UCLASS_HOST1X_H_
+#define HW_HOST1X_UCLASS_HOST1X_H_
+
+static inline uint32_t host1x_uclass_incr_syncpt_r(void)
+{
+ return 0x0;
+}
+static inline uint32_t host1x_uclass_incr_syncpt_cond_f(uint32_t v)
+{
+ return (v & 0xff) << 8;
+}
+static inline uint32_t host1x_uclass_incr_syncpt_cond_op_done_v(void)
+{
+ return 1;
+}
+static inline uint32_t host1x_uclass_incr_syncpt_indx_f(uint32_t v)
+{
+ return (v & 0xff) << 0;
+}
+static inline uint32_t host1x_uclass_wait_syncpt_r(void)
+{
+ return 0x8;
+}
+static inline uint32_t host1x_uclass_wait_syncpt_indx_f(uint32_t v)
+{
+ return (v & 0xff) << 24;
+}
+static inline uint32_t host1x_uclass_wait_syncpt_thresh_f(uint32_t v)
+{
+ return (v & 0xffffff) << 0;
+}
+static inline uint32_t host1x_uclass_wait_syncpt_base_r(void)
+{
+ return 0x09;
+}
+static inline uint32_t host1x_uclass_wait_syncpt_base_indx_f(uint32_t v)
+{
+ return (v & 0xff) << 24;
+}
+static inline uint32_t host1x_uclass_wait_syncpt_base_base_indx_f(uint32_t v)
+{
+ return (v & 0xff) << 16;
+}
+static inline uint32_t host1x_uclass_wait_syncpt_base_offset_f(uint32_t v)
+{
+ return (v & 0xffff) << 0;
+}
+static inline uint32_t host1x_uclass_wait_syncpt_incr_indx_f(uint32_t v)
+{
+ return (v & 0xff) << 24;
+}
+static inline uint32_t host1x_uclass_wait_syncpt_incr_r(void)
+{
+ return 0x0a;
+}
+static inline uint32_t host1x_uclass_load_syncpt_base_base_indx_f(uint32_t v)
+{
+ return (v & 0xff) << 24;
+}
+static inline uint32_t host1x_uclass_load_syncpt_base_value_f(uint32_t v)
+{
+ return (v & 0xffffff) << 0;
+}
+static inline uint32_t host1x_uclass_incr_syncpt_base_base_indx_f(uint32_t v)
+{
+ return (v & 0xff) << 24;
+}
+static inline uint32_t host1x_uclass_incr_syncpt_base_offset_f(uint32_t v)
+{
+ return (v & 0xffffff) << 0;
+}
+static inline uint32_t host1x_uclass_delay_usec_r(void)
+{
+ return 0x10;
+}
+static inline uint32_t host1x_uclass_indoff_r(void)
+{
+ return 0x2d;
+}
+static inline uint32_t host1x_uclass_indoff_indbe_f(uint32_t v)
+{
+ return (v & 0xf) << 28;
+}
+static inline uint32_t host1x_uclass_indoff_autoinc_f(uint32_t v)
+{
+ return (v & 0x1) << 27;
+}
+static inline uint32_t host1x_uclass_indoff_indmodid_f(uint32_t v)
+{
+ return (v & 0xff) << 18;
+}
+static inline uint32_t host1x_uclass_indoff_indroffset_f(uint32_t v)
+{
+ return (v & 0xffff) << 2;
+}
+static inline uint32_t host1x_uclass_indoff_rwn_read_v(void)
+{
+ return 1;
+}
+#endif
diff --git a/src/gallium/drivers/grate/meson.build b/src/gallium/drivers/grate/meson.build
new file mode 100644
index 0000000..c05475a
--- /dev/null
+++ b/src/gallium/drivers/grate/meson.build
@@ -0,0 +1,68 @@
+# Copyright © 2017 Erik Faye-Lund
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+files_libgrate = files(
+ 'class_ids.h',
+ 'host1x01_hardware.h',
+ 'hw_host1x01_uclass.h',
+ 'grate_common.h',
+ 'grate_compiler_fp.c',
+ 'grate_compiler_vpe.c',
+ 'grate_compiler.h',
+ 'grate_context.c',
+ 'grate_context.h',
+ 'grate_draw.c',
+ 'grate_draw.h',
+ 'grate_fp_ir.c',
+ 'grate_fp_ir.h',
+ 'grate_fp_vliw.h',
+ 'grate_program.c',
+ 'grate_program.h',
+ 'grate_resource.c',
+ 'grate_resource.h',
+ 'grate_screen.c',
+ 'grate_screen.h',
+ 'grate_state.c',
+ 'grate_state.h',
+ 'grate_stream.c',
+ 'grate_stream.h',
+ 'grate_surface.c',
+ 'grate_surface.h',
+ 'grate_vpe_ir.c',
+ 'grate_vpe_ir.h'
+)
+
+libgrate = static_library(
+ 'grate',
+ [files_libgrate],
+ include_directories : [
+ inc_src, inc_include, inc_gallium, inc_gallium_aux,
+ inc_gallium_drivers, inc_drm_uapi,
+ ],
+ c_args : [c_vis_args],
+ cpp_args : [cpp_vis_args],
+ dependencies : [dep_libdrm, dep_libdrm_tegra],
+ build_by_default : false,
+)
+
+driver_grate = declare_dependency(
+ compile_args : '-DGALLIUM_GRATE',
+ link_with : [libgrate, libtegrawinsys],
+)
diff --git a/src/gallium/drivers/grate/tgr_3d.xml.h b/src/gallium/drivers/grate/tgr_3d.xml.h
new file mode 100644
index 0000000..16192db
--- /dev/null
+++ b/src/gallium/drivers/grate/tgr_3d.xml.h
@@ -0,0 +1,451 @@
+#ifndef TGR_3D_XML
+#define TGR_3D_XML
+
+/* Autogenerated file, DO NOT EDIT manually!
+
+This file was generated by the rules-ng-ng headergen tool in this git repository:
+http://github.com/envytools/envytools/
+git clone https://github.com/envytools/envytools.git
+
+The rules-ng-ng source files this header was generated from are:
+- /home/kusma/src/envytools/rnndb/tgr_3d.xml ( 14496 bytes, from 2017-09-06 20:15:12)
+- /home/kusma/src/envytools/rnndb/grate_copyright.xml ( 1556 bytes, from 2017-09-06 18:11:45)
+
+Copyright (C) 2012-2017 by the following authors:
+- Erik Faye-Lund <kusmabite@gmail.com> (kusma)
+- Dmitry Osipenko <digetx@gmail.com> (digetx)
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+
+#define TGR3D_INDEX_MODE_NONE 0x00000000
+#define TGR3D_INDEX_MODE_UINT8 0x00000001
+#define TGR3D_INDEX_MODE_UINT16 0x00000002
+#define TGR3D_PRIMITIVE_TYPE_POINTS 0x00000000
+#define TGR3D_PRIMITIVE_TYPE_LINES 0x00000001
+#define TGR3D_PRIMITIVE_TYPE_LINE_LOOP 0x00000002
+#define TGR3D_PRIMITIVE_TYPE_LINE_STRIP 0x00000003
+#define TGR3D_PRIMITIVE_TYPE_TRIANGLES 0x00000004
+#define TGR3D_PRIMITIVE_TYPE_TRIANGLE_STRIP 0x00000005
+#define TGR3D_PRIMITIVE_TYPE_TRIANGLE_FAN 0x00000006
+#define TGR3D_PROVOKING_VERTEX_FIRST 0x00000000
+#define TGR3D_PROVOKING_VERTEX_LAST 0x00000001
+#define TGR3D_CULL_FACE_NONE 0x00000000
+#define TGR3D_CULL_FACE_CCW 0x00000001
+#define TGR3D_CULL_FACE_CW 0x00000002
+#define TGR3D_CULL_FACE_BOTH 0x00000003
+#define TGR3D_ATTRIB_TYPE_UBYTE 0x00000000
+#define TGR3D_ATTRIB_TYPE_UBYTE_NORM 0x00000001
+#define TGR3D_ATTRIB_TYPE_SBYTE 0x00000002
+#define TGR3D_ATTRIB_TYPE_SBYTE_NORM 0x00000003
+#define TGR3D_ATTRIB_TYPE_USHORT 0x00000004
+#define TGR3D_ATTRIB_TYPE_USHORT_NORM 0x00000005
+#define TGR3D_ATTRIB_TYPE_SSHORT 0x00000006
+#define TGR3D_ATTRIB_TYPE_SSHORT_NORM 0x00000007
+#define TGR3D_ATTRIB_TYPE_UINT 0x00000008
+#define TGR3D_ATTRIB_TYPE_UINT_NORM 0x00000009
+#define TGR3D_ATTRIB_TYPE_SINT 0x0000000a
+#define TGR3D_ATTRIB_TYPE_SINT_NORM 0x0000000b
+#define TGR3D_ATTRIB_TYPE_FIXED16 0x0000000c
+#define TGR3D_ATTRIB_TYPE_FLOAT32 0x0000000d
+#define TGR3D_ATTRIB_TYPE_FLOAT16 0x0000000e
+#define TGR3D_PIXEL_FORMAT_A8 0x00000001
+#define TGR3D_PIXEL_FORMAT_L8 0x00000002
+#define TGR3D_PIXEL_FORMAT_S8 0x00000003
+#define TGR3D_PIXEL_FORMAT_LA88 0x00000004
+#define TGR3D_PIXEL_FORMAT_RGB565 0x00000006
+#define TGR3D_PIXEL_FORMAT_RGBA5551 0x00000009
+#define TGR3D_PIXEL_FORMAT_RGBA4444 0x0000000a
+#define TGR3D_PIXEL_FORMAT_D16_LINEAR 0x0000000b
+#define TGR3D_PIXEL_FORMAT_D16_NONLINEAR 0x0000000c
+#define TGR3D_PIXEL_FORMAT_RGBA8888 0x0000000d
+#define TGR3D_PIXEL_FORMAT_RGBA_FP32 0x00000012
+#define TGR3D_COMPARE_FUNC_NEVER 0x00000000
+#define TGR3D_COMPARE_FUNC_LESS 0x00000001
+#define TGR3D_COMPARE_FUNC_EQUAL 0x00000002
+#define TGR3D_COMPARE_FUNC_LEQUAL 0x00000003
+#define TGR3D_COMPARE_FUNC_GREATER 0x00000004
+#define TGR3D_COMPARE_FUNC_NOTEQUAL 0x00000005
+#define TGR3D_COMPARE_FUNC_GEQUAL 0x00000006
+#define TGR3D_COMPARE_FUNC_ALWAYS 0x00000007
+#define TGR3D_SYNCPT_CONDITIONAL_IMMEDIATE 0x00000000
+#define TGR3D_SYNCPT_CONDITIONAL_OP_DONE 0x00000001
+#define TGR3D_SYNCPT_CONDITIONAL_RD_DONE 0x00000002
+#define TGR3D_SYNCPT_CONDITIONAL_WR_SAFE 0x00000003
+#define TGR3D_STENCIL_OP_ZERO 0x00000000
+#define TGR3D_STENCIL_OP_KEEP 0x00000001
+#define TGR3D_STENCIL_OP_REPLACE 0x00000002
+#define TGR3D_STENCIL_OP_INCR 0x00000003
+#define TGR3D_STENCIL_OP_DECR 0x00000004
+#define TGR3D_STENCIL_OP_INVERT 0x00000005
+#define TGR3D_STENCIL_OP_INCR_WRAP 0x00000006
+#define TGR3D_STENCIL_OP_DECR_WRAP 0x00000007
+#define TGR3D_INCR_SYNCPT 0x00000000
+#define TGR3D_INCR_SYNCPT_SYNCPT_INDEX__MASK 0x000000ff
+#define TGR3D_INCR_SYNCPT_SYNCPT_INDEX__SHIFT 0
+#define TGR3D_INCR_SYNCPT_CONDITION__MASK 0x00000700
+#define TGR3D_INCR_SYNCPT_CONDITION__SHIFT 8
+
+#define TGR3D_WAIT_SYNCPT 0x00000008
+
+#define TGR3D_WAIT_SYNCPT_BASE 0x00000009
+#define TGR3D_WAIT_SYNCPT_BASE_OFFSET__MASK 0x0000ffff
+#define TGR3D_WAIT_SYNCPT_BASE_OFFSET__SHIFT 0
+#define TGR3D_WAIT_SYNCPT_BASE_BASE_IDX__MASK 0x00ff0000
+#define TGR3D_WAIT_SYNCPT_BASE_BASE_IDX__SHIFT 16
+#define TGR3D_WAIT_SYNCPT_BASE_IDX__MASK 0xff000000
+#define TGR3D_WAIT_SYNCPT_BASE_IDX__SHIFT 24
+
+#define TGR3D_LOAD_SYNCPT_BASE 0x0000000b
+
+#define TGR3D_INCR_SYNCPT_BASE 0x0000000c
+#define TGR3D_INCR_SYNCPT_BASE_OFFSET__MASK 0x00ffffff
+#define TGR3D_INCR_SYNCPT_BASE_OFFSET__SHIFT 0
+#define TGR3D_INCR_SYNCPT_BASE_BASE_IDX__MASK 0xff000000
+#define TGR3D_INCR_SYNCPT_BASE_BASE_IDX__SHIFT 24
+
+#define TGR3D_INDOFF2 0x0000002c
+
+#define TGR3D_INDOFF 0x0000002d
+
+#define TGR3D_ATTRIB_PTR(i0) (0x00000100 + 0x2*(i0))
+#define TGR3D_ATTRIB_PTR__ESIZE 0x00000002
+#define TGR3D_ATTRIB_PTR__LEN 0x00000010
+
+#define TGR3D_ATTRIB_MODE(i0) (0x00000101 + 0x2*(i0))
+#define TGR3D_ATTRIB_MODE__ESIZE 0x00000002
+#define TGR3D_ATTRIB_MODE__LEN 0x00000010
+#define TGR3D_ATTRIB_MODE_TYPE__MASK 0x0000000f
+#define TGR3D_ATTRIB_MODE_TYPE__SHIFT 0
+#define TGR3D_ATTRIB_MODE_SIZE__MASK 0x000000f0
+#define TGR3D_ATTRIB_MODE_SIZE__SHIFT 4
+#define TGR3D_ATTRIB_MODE_STRIDE__MASK 0xffffff00
+#define TGR3D_ATTRIB_MODE_STRIDE__SHIFT 8
+
+#define TGR3D_VP_ATTRIB_IN_OUT_SELECT 0x00000120
+#define TGR3D_VP_ATTRIB_IN_OUT_SELECT_OUT0 0x00000001
+#define TGR3D_VP_ATTRIB_IN_OUT_SELECT_OUT1 0x00000002
+#define TGR3D_VP_ATTRIB_IN_OUT_SELECT_OUT2 0x00000004
+#define TGR3D_VP_ATTRIB_IN_OUT_SELECT_OUT3 0x00000008
+#define TGR3D_VP_ATTRIB_IN_OUT_SELECT_OUT4 0x00000010
+#define TGR3D_VP_ATTRIB_IN_OUT_SELECT_OUT5 0x00000020
+#define TGR3D_VP_ATTRIB_IN_OUT_SELECT_OUT6 0x00000040
+#define TGR3D_VP_ATTRIB_IN_OUT_SELECT_OUT7 0x00000080
+#define TGR3D_VP_ATTRIB_IN_OUT_SELECT_OUT8 0x00000100
+#define TGR3D_VP_ATTRIB_IN_OUT_SELECT_OUT9 0x00000200
+#define TGR3D_VP_ATTRIB_IN_OUT_SELECT_OUT10 0x00000400
+#define TGR3D_VP_ATTRIB_IN_OUT_SELECT_OUT11 0x00000800
+#define TGR3D_VP_ATTRIB_IN_OUT_SELECT_OUT12 0x00001000
+#define TGR3D_VP_ATTRIB_IN_OUT_SELECT_OUT13 0x00002000
+#define TGR3D_VP_ATTRIB_IN_OUT_SELECT_OUT14 0x00004000
+#define TGR3D_VP_ATTRIB_IN_OUT_SELECT_OUT15 0x00008000
+#define TGR3D_VP_ATTRIB_IN_OUT_SELECT_IN0 0x00010000
+#define TGR3D_VP_ATTRIB_IN_OUT_SELECT_IN1 0x00020000
+#define TGR3D_VP_ATTRIB_IN_OUT_SELECT_IN2 0x00040000
+#define TGR3D_VP_ATTRIB_IN_OUT_SELECT_IN3 0x00080000
+#define TGR3D_VP_ATTRIB_IN_OUT_SELECT_IN4 0x00100000
+#define TGR3D_VP_ATTRIB_IN_OUT_SELECT_IN5 0x00200000
+#define TGR3D_VP_ATTRIB_IN_OUT_SELECT_IN6 0x00400000
+#define TGR3D_VP_ATTRIB_IN_OUT_SELECT_IN7 0x00800000
+#define TGR3D_VP_ATTRIB_IN_OUT_SELECT_IN8 0x01000000
+#define TGR3D_VP_ATTRIB_IN_OUT_SELECT_IN9 0x02000000
+#define TGR3D_VP_ATTRIB_IN_OUT_SELECT_IN10 0x04000000
+#define TGR3D_VP_ATTRIB_IN_OUT_SELECT_IN11 0x08000000
+#define TGR3D_VP_ATTRIB_IN_OUT_SELECT_IN12 0x04000000
+#define TGR3D_VP_ATTRIB_IN_OUT_SELECT_IN13 0x20000000
+#define TGR3D_VP_ATTRIB_IN_OUT_SELECT_IN14 0x40000000
+#define TGR3D_VP_ATTRIB_IN_OUT_SELECT_IN15 0x80000000
+
+#define TGR3D_INDEX_PTR 0x00000121
+
+#define TGR3D_DRAW_PARAMS 0x00000122
+#define TGR3D_DRAW_PARAMS_INDEX_MODE__MASK 0x30000000
+#define TGR3D_DRAW_PARAMS_INDEX_MODE__SHIFT 28
+#define TGR3D_DRAW_PARAMS_PROVOKING_VERTEX__MASK 0x08000000
+#define TGR3D_DRAW_PARAMS_PROVOKING_VERTEX__SHIFT 27
+#define TGR3D_DRAW_PARAMS_PRIMITIVE_TYPE__MASK 0x07000000
+#define TGR3D_DRAW_PARAMS_PRIMITIVE_TYPE__SHIFT 24
+#define TGR3D_DRAW_PARAMS_FIRST__MASK 0x00ffffff
+#define TGR3D_DRAW_PARAMS_FIRST__SHIFT 0
+
+#define TGR3D_DRAW_PRIMITIVES 0x00000123
+#define TGR3D_DRAW_PRIMITIVES_INDEX_COUNT__MASK 0xfff00000
+#define TGR3D_DRAW_PRIMITIVES_INDEX_COUNT__SHIFT 20
+#define TGR3D_DRAW_PRIMITIVES_OFFSET__MASK 0x000fffff
+#define TGR3D_DRAW_PRIMITIVES_OFFSET__SHIFT 0
+
+#define TGR3D_VP_UPLOAD_INST_ID 0x00000205
+
+#define TGR3D_VP_UPLOAD_INST 0x00000206
+
+#define TGR3D_VP_UPLOAD_CONST_ID 0x00000207
+
+#define TGR3D_VP_UPLOAD_CONST 0x00000208
+
+#define TGR3D_LINKER_INSTRUCTION(i0) (0x00000300 + 0x2*(i0))
+#define TGR3D_LINKER_INSTRUCTION__ESIZE 0x00000002
+#define TGR3D_LINKER_INSTRUCTION__LEN 0x00000020
+
+#define TGR3D_CULL_FACE_LINKER_SETUP 0x00000343
+#define TGR3D_CULL_FACE_LINKER_SETUP_LINKER_INST_COUNT__MASK 0x000003e0
+#define TGR3D_CULL_FACE_LINKER_SETUP_LINKER_INST_COUNT__SHIFT 5
+#define TGR3D_CULL_FACE_LINKER_SETUP_FRONT_CW 0x00008000
+#define TGR3D_CULL_FACE_LINKER_SETUP_CULL_FACE__MASK 0x00030000
+#define TGR3D_CULL_FACE_LINKER_SETUP_CULL_FACE__SHIFT 16
+#define TGR3D_CULL_FACE_LINKER_SETUP_UNK_18_31__MASK 0xfffc0000
+#define TGR3D_CULL_FACE_LINKER_SETUP_UNK_18_31__SHIFT 18
+
+#define TGR3D_POLYGON_OFFSET_UNITS 0x00000344
+
+#define TGR3D_POLYFON_OFFSET_FACTOR 0x00000345
+
+#define TGR3D_POINT_PARAMS 0x00000346
+
+#define TGR3D_POINT_SIZE 0x00000347
+
+#define TGR3D_POINT_COORD_RANGE_MAX_S 0x00000348
+
+#define TGR3D_POINT_COORD_RANGE_MAX_T 0x00000349
+
+#define TGR3D_POINT_COORD_RANGE_MIN_S 0x0000034a
+
+#define TGR3D_POINT_COORD_RANGE_MIN_T 0x0000034b
+
+#define TGR3D_LINE_PARAMS 0x0000034c
+
+#define TGR3D_HALF_LINE_WIDTH 0x0000034d
+
+#define TGR3D_SCISSOR_HORIZ 0x00000350
+#define TGR3D_SCISSOR_HORIZ_MIN__MASK 0xffff0000
+#define TGR3D_SCISSOR_HORIZ_MIN__SHIFT 16
+#define TGR3D_SCISSOR_HORIZ_MAX__MASK 0x0000ffff
+#define TGR3D_SCISSOR_HORIZ_MAX__SHIFT 0
+
+#define TGR3D_SCISSOR_VERT 0x00000351
+#define TGR3D_SCISSOR_VERT_MIN__MASK 0xffff0000
+#define TGR3D_SCISSOR_VERT_MIN__SHIFT 16
+#define TGR3D_SCISSOR_VERT_MAX__MASK 0x0000ffff
+#define TGR3D_SCISSOR_VERT_MAX__SHIFT 0
+
+#define TGR3D_VIEWPORT_X_BIAS 0x00000352
+
+#define TGR3D_VIEWPORT_Y_BIAS 0x00000353
+
+#define TGR3D_VIEWPORT_Z_BIAS 0x00000354
+
+#define TGR3D_VIEWPORT_X_SCALE 0x00000355
+
+#define TGR3D_VIEWPORT_Y_SCALE 0x00000356
+
+#define TGR3D_VIEWPORT_Z_SCALE 0x00000357
+
+#define TGR3D_GUARDBAND_WIDTH 0x00000358
+
+#define TGR3D_GUARDBAND_HEIGHT 0x00000359
+
+#define TGR3D_GUARDBAND_DEPTH 0x0000035a
+
+#define TGR3D_STENCIL_FRONT1 0x00000400
+#define TGR3D_STENCIL_FRONT1_MASK__MASK 0x000000ff
+#define TGR3D_STENCIL_FRONT1_MASK__SHIFT 0
+#define TGR3D_STENCIL_FRONT1_FUNC__MASK 0x00000700
+#define TGR3D_STENCIL_FRONT1_FUNC__SHIFT 8
+
+#define TGR3D_STENCIL_BACK1 0x00000401
+#define TGR3D_STENCIL_BACK1_MASK__MASK 0x000000ff
+#define TGR3D_STENCIL_BACK1_MASK__SHIFT 0
+#define TGR3D_STENCIL_BACK1_FUNC__MASK 0x00000700
+#define TGR3D_STENCIL_BACK1_FUNC__SHIFT 8
+
+#define TGR3D_STENCIL_PARAMS 0x00000402
+#define TGR3D_STENCIL_PARAMS_STENCIL_WRITE_EARLY 0x00000040
+#define TGR3D_STENCIL_PARAMS_STENCIL_TEST 0x00000020
+
+#define TGR3D_DEPTH_TEST_PARAMS 0x00000403
+#define TGR3D_DEPTH_TEST_PARAMS_DEPTH_WRITE 0x00000100
+#define TGR3D_DEPTH_TEST_PARAMS_FUNC__MASK 0x000000f0
+#define TGR3D_DEPTH_TEST_PARAMS_FUNC__SHIFT 4
+#define TGR3D_DEPTH_TEST_PARAMS_DEPTH_TEST 0x00000008
+
+#define TGR3D_DEPTH_RANGE_NEAR 0x00000404
+
+#define TGR3D_DEPTH_RANGE_FAR 0x00000405
+
+#define TGR3D_FP_PSEQ_UPLOAD_INST_BUFFER_FLUSH 0x00000500
+
+#define TGR3D_FP_PSEQ_ENGINE_INST 0x00000520
+
+#define TGR3D_FP_PSEQ_UPLOAD_INST_ID 0x00000540
+
+#define TGR3D_FP_PSEQ_UPLOAD_INST 0x00000541
+
+#define TGR3D_FP_PSEQ_QUAD_ID 0x00000545
+
+#define TGR3D_FP_PSEQ_DW_CFG 0x00000546
+#define TGR3D_FP_PSEQ_DW_CFG_PSEQ_TO_DW_EXEC_NB__MASK 0xffffffc0
+#define TGR3D_FP_PSEQ_DW_CFG_PSEQ_TO_DW_EXEC_NB__SHIFT 6
+
+#define TGR3D_FP_UPLOAD_MFU_SCHED_ID 0x00000600
+
+#define TGR3D_FP_UPLOAD_MFU_SCHED 0x00000601
+#define TGR3D_FP_UPLOAD_MFU_SCHED_OFFSET__MASK 0x000000fc
+#define TGR3D_FP_UPLOAD_MFU_SCHED_OFFSET__SHIFT 2
+#define TGR3D_FP_UPLOAD_MFU_SCHED_COUNT__MASK 0x00000003
+#define TGR3D_FP_UPLOAD_MFU_SCHED_COUNT__SHIFT 0
+
+#define TGR3D_FP_UPLOAD_MFU_INST_ID 0x00000603
+
+#define TGR3D_FP_UPLOAD_MFU_INST 0x00000604
+
+#define TGR3D_FP_UPLOAD_TEX_INST_ID 0x00000700
+
+#define TGR3D_FP_UPLOAD_TEX_INST 0x00000701
+
+#define TGR3D_TEXTURE_POINTER(i0) (0x00000710 + 0x1*(i0))
+#define TGR3D_TEXTURE_POINTER__ESIZE 0x00000001
+#define TGR3D_TEXTURE_POINTER__LEN 0x00000010
+
+#define TGR3D_TEXTURE_DESC1(i0) (0x00000720 + 0x2*(i0))
+#define TGR3D_TEXTURE_DESC1__ESIZE 0x00000002
+#define TGR3D_TEXTURE_DESC1__LEN 0x00000010
+#define TGR3D_TEXTURE_DESC1_MAGFILTER_LINEAR 0x20000000
+#define TGR3D_TEXTURE_DESC1_MINFILTER_LINEAR_WITHIN 0x10000000
+#define TGR3D_TEXTURE_DESC1_MINFILTER_LINEAR_BETWEEN 0x08000000
+#define TGR3D_TEXTURE_DESC1_FORMAT__MASK 0x00001f00
+#define TGR3D_TEXTURE_DESC1_FORMAT__SHIFT 8
+#define TGR3D_TEXTURE_DESC1_WRAP_S_MIRRORED_REPEAT 0x00000008
+#define TGR3D_TEXTURE_DESC1_WRAP_T_MIRRORED_REPEAT 0x00000004
+#define TGR3D_TEXTURE_DESC1_WRAP_S_CLAMP_TO_EDGE 0x00000002
+#define TGR3D_TEXTURE_DESC1_WRAP_T_CLAMP_TO_EDGE 0x00000001
+
+#define TGR3D_TEXTURE_DESC2(i0) (0x00000721 + 0x2*(i0))
+#define TGR3D_TEXTURE_DESC2__ESIZE 0x00000002
+#define TGR3D_TEXTURE_DESC2__LEN 0x00000010
+#define TGR3D_TEXTURE_DESC2_WIDTH__MASK 0xfff00000
+#define TGR3D_TEXTURE_DESC2_WIDTH__SHIFT 20
+#define TGR3D_TEXTURE_DESC2_HEIGHT__MASK 0x000fff00
+#define TGR3D_TEXTURE_DESC2_HEIGHT__SHIFT 8
+#define TGR3D_TEXTURE_DESC2_WIDTH_LOG2__MASK 0xf0000000
+#define TGR3D_TEXTURE_DESC2_WIDTH_LOG2__SHIFT 28
+#define TGR3D_TEXTURE_DESC2_HEIGHT_LOG2__MASK 0x0f000000
+#define TGR3D_TEXTURE_DESC2_HEIGHT_LOG2__SHIFT 24
+#define TGR3D_TEXTURE_DESC2_MAX_LOD__MASK 0x0000f000
+#define TGR3D_TEXTURE_DESC2_MAX_LOD__SHIFT 12
+#define TGR3D_TEXTURE_DESC2_MIPMAP_DISABLE 0x00000080
+#define TGR3D_TEXTURE_DESC2_NOT_POW2_DIMENSIONS 0x00000040
+
+#define TGR3D_FP_UPLOAD_ALU_SCHED_ID 0x00000800
+
+#define TGR3D_FP_UPLOAD_ALU_SCHED 0x00000801
+#define TGR3D_FP_UPLOAD_ALU_SCHED_OFFSET__MASK 0x000000fc
+#define TGR3D_FP_UPLOAD_ALU_SCHED_OFFSET__SHIFT 2
+#define TGR3D_FP_UPLOAD_ALU_SCHED_COUNT__MASK 0x00000003
+#define TGR3D_FP_UPLOAD_ALU_SCHED_COUNT__SHIFT 0
+
+#define TGR3D_FP_UPLOAD_ALU_INST_ID 0x00000803
+
+#define TGR3D_FP_UPLOAD_ALU_INST 0x00000804
+
+#define TGR3D_FP_UPLOAD_ALU_INST_COMPLEMENT 0x00000806
+
+#define TGR3D_FP_CONST(i0) (0x00000820 + 0x1*(i0))
+#define TGR3D_FP_CONST__ESIZE 0x00000001
+#define TGR3D_FP_CONST__LEN 0x00000020
+
+#define TGR3D_FP_UPLOAD_DW_INST_ID 0x00000900
+
+#define TGR3D_FP_UPLOAD_DW_INST 0x00000901
+
+#define TGR3D_RT_ENABLE 0x00000903
+#define TGR3D_RT_ENABLE_0 0x00000001
+#define TGR3D_RT_ENABLE_1 0x00000002
+#define TGR3D_RT_ENABLE_2 0x00000004
+#define TGR3D_RT_ENABLE_3 0x00000008
+#define TGR3D_RT_ENABLE_4 0x00000010
+#define TGR3D_RT_ENABLE_5 0x00000020
+#define TGR3D_RT_ENABLE_6 0x00000040
+#define TGR3D_RT_ENABLE_7 0x00000080
+#define TGR3D_RT_ENABLE_8 0x00000100
+#define TGR3D_RT_ENABLE_9 0x00000200
+#define TGR3D_RT_ENABLE_10 0x00000400
+#define TGR3D_RT_ENABLE_11 0x00000800
+#define TGR3D_RT_ENABLE_12 0x00001000
+#define TGR3D_RT_ENABLE_13 0x00002000
+#define TGR3D_RT_ENABLE_14 0x00004000
+#define TGR3D_RT_ENABLE_15 0x00008000
+#define TGR3D_RT_ENABLE_DEPTH_BUFFER 0x00010000
+
+#define TGR3D_FDC_CONTROL 0x00000a00
+#define TGR3D_FDC_CONTROL_INVALIDATE 0x00000001
+
+#define TGR3D_RT_PTR(i0) (0x00000e00 + 0x1*(i0))
+#define TGR3D_RT_PTR__ESIZE 0x00000001
+#define TGR3D_RT_PTR__LEN 0x00000010
+
+#define TGR3D_RT_PARAMS(i0) (0x00000e10 + 0x1*(i0))
+#define TGR3D_RT_PARAMS__ESIZE 0x00000001
+#define TGR3D_RT_PARAMS__LEN 0x00000010
+#define TGR3D_RT_PARAMS_DITHER_ENABLE 0x00000001
+#define TGR3D_RT_PARAMS_FORMAT__MASK 0x0000007c
+#define TGR3D_RT_PARAMS_FORMAT__SHIFT 2
+#define TGR3D_RT_PARAMS_PITCH__MASK 0x01ffff00
+#define TGR3D_RT_PARAMS_PITCH__SHIFT 8
+#define TGR3D_RT_PARAMS_TILED 0x04000000
+
+#define TGR3D_ALU_BUFFER_SIZE 0x00000e20
+#define TGR3D_ALU_BUFFER_SIZE_SIZE__MASK 0x00000003
+#define TGR3D_ALU_BUFFER_SIZE_SIZE__SHIFT 0
+#define TGR3D_ALU_BUFFER_SIZE_SIZEx4__MASK 0xff000000
+#define TGR3D_ALU_BUFFER_SIZE_SIZEx4__SHIFT 24
+
+#define TGR3D_TRAM_SETUP 0x00000e21
+#define TGR3D_TRAM_SETUP_DIV64__MASK 0x0000007f
+#define TGR3D_TRAM_SETUP_DIV64__SHIFT 0
+#define TGR3D_TRAM_SETUP_USED_TRAM_ROWS_NB__MASK 0x00007f00
+#define TGR3D_TRAM_SETUP_USED_TRAM_ROWS_NB__SHIFT 8
+
+#define TGR3D_FP_UPLOAD_INST_ID_COMMON 0x00000e22
+
+#define TGR3D_DITHER 0x00000e26
+
+#define TGR3D_STENCIL_FRONT2 0x00000e28
+#define TGR3D_STENCIL_FRONT2_REF__MASK 0x03fe0000
+#define TGR3D_STENCIL_FRONT2_REF__SHIFT 17
+#define TGR3D_STENCIL_FRONT2_OP_FAIL__MASK 0x00000007
+#define TGR3D_STENCIL_FRONT2_OP_FAIL__SHIFT 0
+#define TGR3D_STENCIL_FRONT2_OP_ZFAIL__MASK 0x00000038
+#define TGR3D_STENCIL_FRONT2_OP_ZFAIL__SHIFT 3
+#define TGR3D_STENCIL_FRONT2_OP_ZPASS__MASK 0x000001c0
+#define TGR3D_STENCIL_FRONT2_OP_ZPASS__SHIFT 6
+
+#define TGR3D_STENCIL_BACK2 0x00000e29
+#define TGR3D_STENCIL_BACK2_REF__MASK 0x03fe0000
+#define TGR3D_STENCIL_BACK2_REF__SHIFT 17
+#define TGR3D_STENCIL_BACK2_OP_FAIL__MASK 0x00000007
+#define TGR3D_STENCIL_BACK2_OP_FAIL__SHIFT 0
+#define TGR3D_STENCIL_BACK2_OP_ZFAIL__MASK 0x00000038
+#define TGR3D_STENCIL_BACK2_OP_ZFAIL__SHIFT 3
+#define TGR3D_STENCIL_BACK2_OP_ZPASS__MASK 0x000001c0
+#define TGR3D_STENCIL_BACK2_OP_ZPASS__SHIFT 6
+
+
+#endif /* TGR_3D_XML */
diff --git a/src/gallium/meson.build b/src/gallium/meson.build
index 88e664e..93e1c5e 100644
--- a/src/gallium/meson.build
+++ b/src/gallium/meson.build
@@ -86,6 +86,12 @@ if with_gallium_freedreno
else
driver_freedreno = declare_dependency()
endif
+if with_gallium_grate
+ subdir('winsys/tegra/drm')
+ subdir('drivers/grate')
+else
+ driver_grate = declare_dependency()
+endif
if with_gallium_vc4
subdir('winsys/vc4/drm')
subdir('drivers/vc4')
diff --git a/src/gallium/targets/dri/Makefile.am b/src/gallium/targets/dri/Makefile.am
index 9597235..aa07c419 100644
--- a/src/gallium/targets/dri/Makefile.am
+++ b/src/gallium/targets/dri/Makefile.am
@@ -74,6 +74,8 @@ include $(top_srcdir)/src/gallium/drivers/svga/Automake.inc
include $(top_srcdir)/src/gallium/drivers/freedreno/Automake.inc
+include $(top_srcdir)/src/gallium/drivers/grate/Automake.inc
+
include $(top_srcdir)/src/gallium/drivers/vc4/Automake.inc
include $(top_srcdir)/src/gallium/drivers/vc5/Automake.inc
include $(top_srcdir)/src/gallium/drivers/pl111/Automake.inc
diff --git a/src/gallium/targets/dri/dri.sym b/src/gallium/targets/dri/dri.sym
index 1fdf18b..3e0abf9 100644
--- a/src/gallium/targets/dri/dri.sym
+++ b/src/gallium/targets/dri/dri.sym
@@ -6,6 +6,7 @@
radeon_drm_winsys_create;
amdgpu_winsys_create;
fd_drm_screen_create;
+ grate_drm_screen_create;
local:
*;
};
diff --git a/src/gallium/targets/dri/meson.build b/src/gallium/targets/dri/meson.build
index 0081bb6..6186a47 100644
--- a/src/gallium/targets/dri/meson.build
+++ b/src/gallium/targets/dri/meson.build
@@ -56,8 +56,9 @@ libgallium_dri = shared_library(
dependencies : [
dep_selinux, dep_expat, dep_libdrm, dep_llvm, dep_thread,
driver_swrast, driver_r300, driver_r600, driver_radeonsi, driver_nouveau,
- driver_pl111, driver_vc4, driver_vc5, driver_freedreno, driver_etnaviv,
- driver_imx, driver_i915, driver_svga, driver_virgl, driver_swr,
+ driver_pl111, driver_vc4, driver_vc5, driver_grate, driver_freedreno,
+ driver_etnaviv, driver_imx, driver_i915, driver_svga, driver_virgl,
+ driver_swr,
],
)
@@ -67,6 +68,7 @@ foreach d : [[with_gallium_pl111, 'pl111_dri.so'],
[with_gallium_freedreno, ['msm_dri.so', 'kgsl_dri.so']],
[with_gallium_softpipe or with_gallium_swr, 'swrast_dri.so'],
[with_gallium_softpipe and with_gallium_drisw_kms, 'kms_swrast_dri.so'],
+ [with_gallium_grate, 'tegra_dri.so'],
[with_gallium_vc4, 'vc4_dri.so'],
[with_gallium_vc5, 'vc5_dri.so'],
[with_gallium_etnaviv, 'etnaviv_dri.so'],
diff --git a/src/gallium/targets/dri/target.c b/src/gallium/targets/dri/target.c
index 5ee1761..4982431 100644
--- a/src/gallium/targets/dri/target.c
+++ b/src/gallium/targets/dri/target.c
@@ -86,3 +86,7 @@ DEFINE_LOADER_DRM_ENTRYPOINT(vc5)
DEFINE_LOADER_DRM_ENTRYPOINT(imx_drm)
DEFINE_LOADER_DRM_ENTRYPOINT(etnaviv)
#endif
+
+#if defined(GALLIUM_GRATE)
+DEFINE_LOADER_DRM_ENTRYPOINT(tegra)
+#endif
diff --git a/src/gallium/winsys/tegra/drm/Makefile.am b/src/gallium/winsys/tegra/drm/Makefile.am
new file mode 100644
index 0000000..ff34092
--- /dev/null
+++ b/src/gallium/winsys/tegra/drm/Makefile.am
@@ -0,0 +1,33 @@
+# Copyright © 2012 Intel Corporation
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+include $(top_srcdir)/src/gallium/Automake.inc
+
+AM_CFLAGS = \
+ -I$(top_srcdir)/src/gallium/drivers \
+ $(GALLIUM_CFLAGS) \
+ $(GRATE_CFLAGS)
+
+noinst_LTLIBRARIES = libtegradrm.la
+
+libtegradrm_la_SOURCES = \
+ tegra_drm_winsys.c
diff --git a/src/gallium/winsys/tegra/drm/meson.build b/src/gallium/winsys/tegra/drm/meson.build
new file mode 100644
index 0000000..8f9f7d3
--- /dev/null
+++ b/src/gallium/winsys/tegra/drm/meson.build
@@ -0,0 +1,30 @@
+# Copyright © 2017 Erik Faye-Lund
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+libtegrawinsys = static_library(
+ 'tegrawinsys',
+ files('tegra_drm_winsys.c'),
+ include_directories : [
+ inc_src, inc_include,
+ inc_gallium, inc_gallium_aux, inc_gallium_drivers,
+ ],
+ dependencies : [dep_libdrm, dep_libdrm_tegra],
+ c_args : [c_vis_args],
+)
diff --git a/src/gallium/winsys/tegra/drm/tegra_drm_public.h b/src/gallium/winsys/tegra/drm/tegra_drm_public.h
new file mode 100644
index 0000000..eceb7c8
--- /dev/null
+++ b/src/gallium/winsys/tegra/drm/tegra_drm_public.h
@@ -0,0 +1,8 @@
+#ifndef TEGRA_DRM_PUBLIC_H
+#define TEGRA_DRM_PUBLIC_H
+
+struct pipe_screen;
+
+struct pipe_screen *tegra_drm_screen_create(int fd);
+
+#endif
diff --git a/src/gallium/winsys/tegra/drm/tegra_drm_winsys.c b/src/gallium/winsys/tegra/drm/tegra_drm_winsys.c
new file mode 100644
index 0000000..0f41960
--- /dev/null
+++ b/src/gallium/winsys/tegra/drm/tegra_drm_winsys.c
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <libdrm/tegra.h>
+
+#include "grate/grate_screen.h"
+#include "tegra_drm_public.h"
+
+struct pipe_screen *tegra_drm_screen_create(int fd)
+{
+ struct drm_tegra *drm;
+ int err = drm_tegra_new(&drm, fd);
+ if (err < 0)
+ return NULL;
+
+ return grate_screen_create(drm);
+}
--
2.7.4