From 527b4ec9895c457fed3387c3342433a4502fea94 Mon Sep 17 00:00:00 2001 From: ryang 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 + * 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 + */ + +#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 + +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 +#include +#include + +#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 + +#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 + +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 +#include + +#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 + +#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 +#include + +/* + * 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 + +#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 + +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 +#include + +#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 + * 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 + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#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 + * 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 + */ + +#ifndef GRATE_STREAM_H_ +#define GRATE_STREAM_H_ + +#include +#include + +#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 + +#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 +#include + +#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 + */ + +#ifndef HOST1X01_HARDWARE_H_ +#define HOST1X01_HARDWARE_H_ + +#include +#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 + */ + + /* + * Function naming determines intended use: + * + * _r(void) : Returns the offset for register . + * + * _w(void) : Returns the word offset for word (4 byte) element . + * + * __s(void) : Returns size of field of register in bits. + * + * __f(uint32_t v) : Returns a value based on 'v' which has been shifted + * and masked to place it at field of register . This value + * can be |'d with others to produce a full register value for + * register . + * + * __m(void) : Returns a mask for field of register . This + * value can be ~'d and then &'d to clear the value of field for + * register . + * + * ___f(void) : Returns the constant value after being shifted + * to place it at field of register . This value can be |'d + * with others to produce a full register value for . + * + * __v(uint32_t r) : Returns the value of field from a full register + * 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 of register . + * + * ___v(void) : Returns the constant value for defined for + * field of register . This value is suitable for direct + * comparison with unshifted values appropriate for use in field + * of register . + */ + +#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 (kusma) +- Dmitry Osipenko (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 +#include + +#include + +#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